<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[RevenueCat Blog]]></title><description><![CDATA[RevenueCat Blog]]></description><link>https://www.revenuecat.com</link><generator>GatsbyJS</generator><lastBuildDate>Thu, 14 May 2026 10:32:51 GMT</lastBuildDate><item><title><![CDATA[How to know if your free tier is generous enough]]></title><description><![CDATA[Is your freemium tier just a trial in disguise?]]></description><link>https://www.revenuecat.com/blog/growth/recommendation-test-opal/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/recommendation-test-opal/</guid><pubDate>Thu, 14 May 2026 10:00:00 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/Blog_61_Is-your-free-tier-generous-enough_.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Going freemium is supposed to unlock organic growth. You give away the core product, users fall in love, and they tell their friends. But for many apps, it doesn’t play out that way. The free tier feels like a stripped-down trial, users churn before forming a habit, and the word-of-mouth engine never starts.&lt;/p&gt;



&lt;p&gt;The standard freemium diagnostics don’t help much here. Conversion rate, paid penetration, and LTV — they all measure what your paying users are doing. None of them tell you whether your &lt;em&gt;non&lt;/em&gt;-paying users are an asset or dead weight.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/kenneth-schlenker-sub-club-podcast-2026/&quot;&gt;On a recent episode&lt;/a&gt; of the Sub Club podcast, Opal CEO Kenneth Schlenker shared the question he uses instead: &lt;strong&gt;would a non-paying user recommend the app to a friend?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;If the answer is no, you need to give away more.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-this-question-matters-more-than-conversion-rate&quot;&gt;Why this question matters more than conversion rate&lt;/h2&gt;



&lt;p&gt;“If you want the freemium dynamic to really pay out, you need to make sure that the free users are recommending the app,” Kenneth says. “Otherwise, that doesn’t work.”&lt;/p&gt;



&lt;p&gt;Freemium works only if free users stick around long enough to build a habit and recommend the app. If your &lt;a href=&quot;https://www.revenuecat.com/blog/growth/freemium-tier-design/&quot;&gt;free tier&lt;/a&gt; is too restrictive — it’s missing core features to achieve users’ &lt;a href=&quot;https://www.revenuecat.com/blog/growth/what-drives-users-to-pay-jobs-to-be-done/&quot;&gt;job-to-be-done&lt;/a&gt;, or it just feels like a countdown to a &lt;a href=&quot;https://www.revenuecat.com/feature/paywalls&quot;&gt;paywall&lt;/a&gt; rather than a useful product — then neither happens. You get a small percentage converting to paid and zero organic pull.&lt;/p&gt;



&lt;p&gt;That’s the trap. A free tier designed to demo the product instead of &lt;em&gt;be&lt;/em&gt; a product.&lt;/p&gt;



&lt;script src=&quot;https://fast.wistia.com/player.js&quot; async=&quot;&quot;&gt;&lt;/script&gt;&lt;script src=&quot;https://fast.wistia.com/embed/jo708ctaxe.js&quot; async=&quot;&quot; type=&quot;module&quot;&gt;&lt;/script&gt;&lt;style&gt;wistia-player[media-id=&apos;jo708ctaxe&apos;]:not(:defined) { background: center / contain no-repeat url(&apos;https://fast.wistia.com/embed/medias/jo708ctaxe/swatch&apos;); display: block; filter: blur(5px); }&lt;/style&gt; &lt;wistia-player media-id=&quot;jo708ctaxe&quot; aspect=&quot;1.7777777777777777&quot; style=&quot;width: 600px;height: 338px;&quot;&gt;&lt;/wistia-player&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-to-actually-answer-the-question&quot;&gt;How to actually answer the question&lt;/h2&gt;



&lt;p&gt;The recommendation question is a heuristic, not a metric. But you can triangulate toward an answer by watching two things in parallel:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;LTV of installs&lt;/li&gt;



&lt;li&gt;Overall retention across both free and paid users&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;When Opal tested how much to give away in their core ‘blocks’ feature — the scheduled restrictions that block distracting apps during specific times — the team tried everything from one block (very restrictive) to several, measuring these two &lt;a href=&quot;https://www.revenuecat.com/blog/growth/activation-metrics/&quot;&gt;metrics&lt;/a&gt; at every step.&lt;/p&gt;



&lt;p&gt;The goal was to &lt;strong&gt;find the point where both metrics were moving up&lt;/strong&gt;. Rather than focusing on just paid conversion, or free-to-paid funnel efficiency, this would show &lt;strong&gt;the combined health of the user base&lt;/strong&gt;.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;603&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-4-1024x603.png&quot; alt=&quot;&quot; class=&quot;wp-image-53788&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-4-1024x603.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-4-300x177.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-4-768x452.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-4-1536x904.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-4-50x29.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-4-68x40.png 68w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-4-696x410.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-4-560x329.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-4-503x296.png 503w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-4-802x472.png 802w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-4-80x47.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-4-48x28.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-4.png 1635w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;“Turns out that three [blocks] is enough for free users to get a great experience,” Kenneth explains. “They can actually really use the app, try out a few different things, and then also really power users that are convinced will pay because they want more.”&lt;/p&gt;



&lt;p&gt;Three blocks gave non-payers enough &lt;strong&gt;utility to build a habit&lt;/strong&gt; — and &lt;strong&gt;recommend the app&lt;/strong&gt;. It also left enough headroom that committed users still had a &lt;strong&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/how-to-turn-freemium-users-into-loyal-subscribers/&quot;&gt;reason to upgrade&lt;/a&gt;&lt;/strong&gt;. If LTV and retention don’t both improve as you adjust your free tier, you’re optimizing one segment at the other’s expense.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-yes-actually-unlocks&quot;&gt;What ‘yes’ actually unlocks&lt;/h2&gt;



&lt;p&gt;When Opal moved from a &lt;a href=&quot;https://www.revenuecat.com/blog/growth/hard-paywall-vs-freemium/&quot;&gt;hard paywall to a genuinely generous free tier&lt;/a&gt;, their pay penetration — the share of monthly active users on a paid plan — dropped from 20% to 9%. That sounds like a disaster, but it wasn’t.&lt;/p&gt;



&lt;p&gt;The free tier unlocked a segment Opal couldn’t reach behind a paywall: high school and college students, who now make up two-thirds of Opal’s DAUs. These users dragged pay penetration down — but they were doing something more valuable: telling their classmates, then telling their schools. Students recommending the app to administrators created Opal for Schools, now a contracted B2B revenue line. That distribution channel didn’t exist when there was only a hard paywall.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Overall, the shift pushed Opal past one million daily active users. “It’s a short-term, scary drop, but what happens in the long-term is that it pays back tenfold,” Kenneth says.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-takeaway&quot;&gt;The takeaway&lt;/h2&gt;



&lt;p&gt;If your non-payers wouldn’t recommend the product, you don’t have freemium — you have a trial in disguise.&lt;/p&gt;



&lt;p&gt;The fix isn’t always to give away more. Sometimes it’s to give away differently — more of one feature, less of another, restructured so the &lt;a href=&quot;https://www.revenuecat.com/blog/growth/deezer-sherina-khalidi-sub-club-podcast/&quot;&gt;free experience&lt;/a&gt; is genuinely useful rather than a teaser. But the recommendation question is the compass. Pair it with parallel tracking of LTV and overall retention, and you have a way to find the line for your own product.&lt;/p&gt;



&lt;p&gt;Think about:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Does it &lt;a href=&quot;https://www.revenuecat.com/blog/growth/hard-paywall-vs-soft-paywall/&quot;&gt;unlock enough utility&lt;/a&gt; to build a habit or progress towards their goal?&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Does it unlock enough to make them recommend the app?&lt;/li&gt;



&lt;li&gt;Does it keep enough back to give users a reason to upgrade?&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Most teams &lt;a href=&quot;https://www.revenuecat.com/blog/growth/freemium-at-scale-how-life360-built-trust-and-hit-1-8b/&quot;&gt;optimize their free tier&lt;/a&gt; to maximize conversion. The teams that win optimize it to maximize recommendation, and let conversion follow.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[A machine learning test doubled Life360’s top-tier subscriptions — without losing a single mid-tier user]]></title><description><![CDATA[Giordano Contestabile ran a test that showed degrading Life360's free tier would drive massive revenue — and then the executive team yelled at him for even suggesting it.]]></description><link>https://www.revenuecat.com/blog/growth/giordano-contestabile-life360-sub-club-podcast-2026/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/giordano-contestabile-life360-sub-club-podcast-2026/</guid><pubDate>Wed, 13 May 2026 13:34:45 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/RC-Blog-Cover-Life360-1.png" length="0" type="image/*"/><content:encoded>&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-freemium-bill-of-rights&quot;&gt;The freemium bill of rights&lt;/h2&gt;



&lt;p&gt;Six months into his role as VP of Product at Life360, Giordano Contestabile ran an experiment. The numbers came back showing a massive revenue upside. He ran to the executive team, expecting a celebration. Instead, he got yelled at.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;Protecting Freemium at 100M Users AND Driving $500M Revenue – Giordano Contestabile, Life360&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/hPwt12zZMCY?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;iframe loading=&quot;lazy&quot; width=&quot;100%&quot; height=&quot;180&quot; frameborder=&quot;no&quot; scrolling=&quot;no&quot; seamless=&quot;&quot; src=&quot;https://share.transistor.fm/e/af9aaabe?color=FFFFFF&amp;amp;background=30343C&quot;&gt;&lt;/iframe&gt;



&lt;p&gt;He had violated what former CEO Chris Hulls called the “freemium bill of rights” — a core set of principles dictating that certain features, particularly those related to family safety, must never be taken away from free users to force a conversion.&lt;/p&gt;



&lt;p&gt;“The reason number one why people tell us they don’t subscribe is because the free tier is good enough,” Contestabile says. “Our philosophy is that literally we want to do something about it, but that something is not making the free tier worse — is trying to provide more value and really diversify the subscription offering.”&lt;/p&gt;



&lt;p&gt;For an app with nearly 100 million monthly active users, that free tier is the ultimate moat. Life360 relies heavily on network effects; the app isn’t useful in “solo mode,” and the primary discovery channel is parents telling other parents. Locking core utility behind a paywall might juice short-term revenue, but it would fundamentally break the viral loop that built the company.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-an-inconclusive-experiment-is-the-only-true-failure&quot;&gt;Why an inconclusive experiment is the only true failure&lt;/h2&gt;



&lt;p&gt;To find new ways to drive revenue without degrading the free experience, Life360 had to scale its experimentation. But Contestabile doesn’t view experimentation as a series of isolated tests; he treats it as a portfolio.&lt;/p&gt;



&lt;p&gt;The effectiveness of that portfolio comes down to three levers: velocity (how many experiments ship), win rate (what percentage succeed), and average win size. But surprisingly, Contestabile doesn’t mind a low win rate.&lt;/p&gt;



&lt;p&gt;“The only experiments that we are sad about is an experiment that is inconclusive,” he explains. “Then we feel we wasted our time — we didn’t set up the experiment correctly or the hypothesis wasn’t right.”&lt;/p&gt;



&lt;p&gt;A loss, on the other hand, is just data. It proves or disproves a hypothesis. Often, a losing experiment reveals that a feature didn’t work broadly, but resonated deeply with a specific cohort — like users in the suburbs who have been on the platform for a month and own a dog.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Those granular learnings feed directly into the next cycle of tests.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-ml-doubled-platinum-subscriptions&quot;&gt;How ML doubled Platinum subscriptions&lt;/h2&gt;



&lt;p&gt;That granular approach to segmentation recently led to one of Life360’s biggest wins.&lt;/p&gt;



&lt;p&gt;The app offers three subscription tiers: Silver, Gold, and Platinum. Historically, the vast majority of users chose Gold. In paywall flows, it’s difficult to clearly articulate the value of all three tiers without overwhelming the user, so the team typically defaulted to presenting the Gold option.&lt;/p&gt;



&lt;p&gt;To challenge this, the team deployed a machine learning model utilizing about 900 distinct data points to identify users with a high propensity to buy the Platinum tier. When the model detected a high-propensity user, it dynamically presented the Platinum offer instead of Gold.&lt;/p&gt;



&lt;p&gt;The results were staggering. “It doubled the percentage of new users subscribing to Platinum,” Contestabile says. “But it did that without losing a single gold subscriber, which was super surprising.”&lt;/p&gt;



&lt;p&gt;The model successfully identified users who wouldn’t have converted on the Gold tier anyway, but were perfectly matched for the specific benefits of Platinum.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-parents-aren-t-viral&quot;&gt;Parents aren’t viral&lt;/h2&gt;



&lt;p&gt;Not every data-driven bet pans out. Knowing that 40% of Life360’s users discovered the app through word-of-mouth — usually parents talking at school pickup — the team tried to digitize that behavior.&lt;/p&gt;



&lt;p&gt;They built in-app referral mechanics. They offered free Silver subscriptions to users who invited friends. They tested multiple variations of sharing buttons.&lt;/p&gt;



&lt;p&gt;“Nothing. Really failure across the board,” Contestabile admits. “And the reason is people my age, families, older people — they are not viral. Parents are not viral.”&lt;/p&gt;



&lt;p&gt;The demographic that actually exhibits viral sharing behavior on mobile devices are teenagers. But while teens are on Life360, the parents are the ones making the purchasing and installation decisions. The team learned the hard way that you can’t force a digital referral loop onto an audience whose natural sharing behavior is entirely offline.&lt;/p&gt;



&lt;p&gt;In &lt;a href=&quot;https://www.youtube.com/watch?v=hPwt12zZMCY&quot;&gt;the full episode&lt;/a&gt;, Giordano and David also discuss how Life360 incorporates physical hardware like Tile into its subscription ecosystem, why the company is pushing to make growth a mandate for every department including HR and Finance, and the strategic value of the new “pet profile” feature.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Guest links:&lt;/strong&gt;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Giordano Contestabile on &lt;a href=&quot;https://www.linkedin.com/in/gcontestabile/&quot;&gt;LinkedIn&lt;/a&gt;&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.life360.com/&quot;&gt;Life360&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.life360.com/careers&quot;&gt;Life360 Careers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title><![CDATA[Testing subscriptions on Compose Multiplatform: one test suite for iOS and Android]]></title><description><![CDATA[In this article, you'll work through a complete subscription testing setup for a Compose Multiplatform app.]]></description><link>https://www.revenuecat.com/blog/engineering/testing-subscription-cmp/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/testing-subscription-cmp/</guid><pubDate>Tue, 12 May 2026 00:22:09 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/Blog_72_Testing-Compose-Multiplatform-Subscriptions.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;You wrote your subscription logic once in&amp;nbsp;&lt;code&gt;commonMain&lt;/code&gt;, your Compose Multiplatform paywall renders the same on iPhone and Pixel, and your&amp;nbsp;&lt;code&gt;CustomerInfo&lt;/code&gt;&amp;nbsp;flow works on both platforms without a single&amp;nbsp;&lt;code&gt;expect/actual&lt;/code&gt;. Then you sit down to test it and find that the same product still has two sandboxes, two test account systems, two CI jobs, and two completely different ways for the platform to say “the purchase succeeded.” The unified codebase from&amp;nbsp;&lt;a href=&quot;https://www.revenuecat.com/blog/engineering/cmp-subscriptions/&quot;&gt;Compose Multiplatform Subscriptions&lt;/a&gt;&amp;nbsp;stops at the test boundary, and most teams either skip purchase testing entirely or maintain two parallel test suites that drift apart.&lt;/p&gt;



&lt;p&gt;In this article, you’ll work through a complete subscription testing setup for a Compose Multiplatform app, exploring why Google Play and StoreKit sandboxes resist unification, how RevenueCat’s Test Store collapses both into one sandbox, how to wire the Test Store into a KMP build with a single&amp;nbsp;&lt;code&gt;BuildConfig&lt;/code&gt;&amp;nbsp;field, why the right testability boundary is a&amp;nbsp;&lt;code&gt;PaywallsRepository&lt;/code&gt;&amp;nbsp;interface in&amp;nbsp;&lt;code&gt;commonMain&lt;/code&gt;, how to write coroutine and&amp;nbsp;&lt;code&gt;StateFlow&lt;/code&gt;&amp;nbsp;tests in&amp;nbsp;&lt;code&gt;commonTest&lt;/code&gt;&amp;nbsp;so a single suite runs against both targets, why fakes beat mocks for KMP subscription code, and how to layer instrumented tests on top so the same code path is exercised end to end.&lt;/p&gt;



&lt;p&gt;Every snippet uses the same source layout as&amp;nbsp;&lt;a href=&quot;https://github.com/RevenueCat/cat-paywalls-kmp&quot;&gt;cat-paywalls-kmp&lt;/a&gt;, the official CMP demo, so you can drop these patterns into a real project without renaming anything.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-fundamental-problem-one-product-two-sandboxes&quot;&gt;&lt;strong&gt;The fundamental problem: One product, two sandboxes&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Subscription testing on a native Android app is already an undertaking. The&amp;nbsp;&lt;a href=&quot;https://www.revenuecat.com/blog/engineering/the-ultimate-guide-to-android-subscription-testing/&quot;&gt;ultimate guide to Android subscription testing&lt;/a&gt;&amp;nbsp;lists license testers, internal tracks, closed tracks, the&amp;nbsp;&lt;code&gt;android.test.purchased&lt;/code&gt;&amp;nbsp;static response, and a handful of&amp;nbsp;&lt;code&gt;BillingClient&lt;/code&gt;&amp;nbsp;quirks before you can reliably run a single purchase end to end. The equivalent path on iOS adds StoreKit configuration files, sandbox tester accounts, accelerated renewal cycles, and TestFlight rate limits that change throughout the year.&lt;/p&gt;



&lt;p&gt;When the same product ships on both stores, you do not get to pick one of these paths. You run both, and you reconcile the differences yourself. A purchase that goes through in the Google Play closed track does not appear in App Store Connect. A StoreKit&amp;nbsp;&lt;code&gt;Transaction&lt;/code&gt;&amp;nbsp;that arrives over the iOS testing pipeline does not flow through your Android&amp;nbsp;&lt;code&gt;PurchasesUpdatedListener&lt;/code&gt;. Even when the entire app is one Kotlin codebase, you write two&amp;nbsp;&lt;code&gt;@Test&lt;/code&gt;&amp;nbsp;annotations, two CI matrices, and two test data setups.&lt;/p&gt;



&lt;p&gt;There is also the unit test gap. Google Play does not expose any way to simulate a purchase inside a JVM unit test. StoreKit configuration files run in the iOS simulator, not in&amp;nbsp;&lt;code&gt;kotlinx-coroutines-test&lt;/code&gt;. So even before you worry about cross platform reconciliation, you cannot get a working purchase flow inside&amp;nbsp;&lt;code&gt;commonTest&lt;/code&gt;&amp;nbsp;at all. The standard advice is to push everything below the SDK boundary into integration tests, which means most teams end up testing only the parts of their code that do not actually touch&amp;nbsp;&lt;code&gt;Purchases&lt;/code&gt;.&lt;/p&gt;



&lt;p&gt;Look at the&amp;nbsp;&lt;code&gt;CatArticlesDetailViewModel&lt;/code&gt;&amp;nbsp;from the cat-paywalls-kmp demo and you can see the shape of the problem:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1pHz5E wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;class CatArticlesDetailViewModel(\n  articleId: Long,\n  articlesRepository: ArticlesRepository,\n  paywallsRepository: PaywallsRepository,\n) : ViewModel() {\n\n  val customerInfo: StateFlow&lt;CustomerInfo?&gt; =\n    paywallsRepository.fetchCustomerInfo()\n      .map { it.getOrNull() }\n      .stateIn(\n        scope = viewModelScope,\n        started = SharingStarted.WhileSubscribed(5000),\n        initialValue = null,\n      )\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This class has real business logic. It decides whether to fade an article body, whether to surface a “Join Now” CTA, what to do when the network call fails, and when to recompose. None of that logic depends on whether the underlying receipt came from Google Play or StoreKit. But if&amp;nbsp;&lt;code&gt;PaywallsRepository.fetchCustomerInfo()&lt;/code&gt;&amp;nbsp;only emits values when a real billing SDK is connected to a real store, you cannot reach any of this logic from a unit test. The KMP win disappears at exactly the boundary where you most need it back.&lt;/p&gt;



&lt;p&gt;The rest of this article is about getting it back.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;the-test-store-a-sandbox-built-into-revenuecat-itself&quot;&gt;&lt;strong&gt;The Test Store: A sandbox built into RevenueCat itself&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The shortest path out of the two sandbox problem is to stop using the two sandboxes for development purchases. RevenueCat’s&amp;nbsp;&lt;a href=&quot;https://www.revenuecat.com/docs/test-and-launch/sandbox/test-store&quot;&gt;Test Store&lt;/a&gt;&amp;nbsp;is a sandbox built into the platform itself, not into Google Play or the App Store. You configure it once in the dashboard, set a different API key in your app, and the SDK routes every purchase through RevenueCat’s own purchase modal instead of asking the native store to open its dialog.&lt;/p&gt;



&lt;p&gt;The modal it shows is small and deliberate. When the user taps “Subscribe” inside the&amp;nbsp;&lt;code&gt;Paywall&lt;/code&gt;&amp;nbsp;composable, the SDK overlays a three button sheet:&amp;nbsp;&lt;strong&gt;Test valid purchase&lt;/strong&gt;,&amp;nbsp;&lt;strong&gt;Test failed purchase&lt;/strong&gt;, and&amp;nbsp;&lt;strong&gt;Cancel&lt;/strong&gt;. Tapping the first one is what a successful purchase looks like from your app’s perspective. The SDK marks the receipt valid on the backend,&amp;nbsp;&lt;code&gt;awaitPurchase&lt;/code&gt;&amp;nbsp;resumes with a&amp;nbsp;&lt;code&gt;StoreTransaction&lt;/code&gt;, the&amp;nbsp;&lt;code&gt;CustomerInfo&lt;/code&gt;&amp;nbsp;flow emits a new value with&amp;nbsp;&lt;code&gt;entitlements[&quot;premium&quot;].isActive == true&lt;/code&gt;, and your gated UI unlocks the same way it would in production. The other two buttons exercise the failure and cancellation paths without you having to fake an exception by hand.&lt;/p&gt;



&lt;p&gt;There is no Play Console setup, no App Store Connect tester account, and no license tester opt in URL. The Test Store works in the simulator, the emulator, debug builds on a real device, and CI runners. Auto renewal still happens, just on accelerated cycles: a monthly subscription renews every five minutes, an annual subscription renews every hour, both stop after five renewals so a test session never runs longer than around five hours. Every Test Store purchase shows up in the same RevenueCat dashboard as production data, which means the same&amp;nbsp;&lt;code&gt;CustomerInfo&lt;/code&gt;&amp;nbsp;shape, the same webhook payloads, and the same entitlement transitions you ship against.&lt;/p&gt;



&lt;p&gt;Two practical rules. First, you need&amp;nbsp;&lt;code&gt;purchases-kmp&lt;/code&gt;&amp;nbsp;2.2.2 or newer for the Test Store path; the cat-paywalls-kmp demo pins&amp;nbsp;&lt;code&gt;2.10.2+17.55.1&lt;/code&gt;. Second, a Test Store key is a debug only artifact. It looks like&amp;nbsp;&lt;code&gt;test_...&lt;/code&gt;&amp;nbsp;instead of&amp;nbsp;&lt;code&gt;goog_...&lt;/code&gt;&amp;nbsp;or&amp;nbsp;&lt;code&gt;appl_...&lt;/code&gt;&amp;nbsp;and is rejected by the server if the SDK is configured against a production project. Treat it the same way you would treat a debug signing key: useful for development, never in a release.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;setting-up-the-test-store-in-a-kmp-project&quot;&gt;&lt;strong&gt;Setting up the Test Store in a KMP project&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The whole setup is one extra&amp;nbsp;&lt;code&gt;BuildConfig&lt;/code&gt;&amp;nbsp;field on the Android side and one decision in your&amp;nbsp;&lt;code&gt;Application.onCreate&lt;/code&gt;&amp;nbsp;about which key to use. iOS does not need a separate change because the same Kotlin code reads the same configuration when the shared module initializes on the Swift side.&lt;/p&gt;



&lt;p&gt;Start with the Gradle build. In&amp;nbsp;&lt;code&gt;composeApp/build.gradle.kts&lt;/code&gt;, read the Test Store key from&amp;nbsp;&lt;code&gt;local.properties&lt;/code&gt;&amp;nbsp;and expose it through&amp;nbsp;&lt;code&gt;buildConfigField&lt;/code&gt;. Pulling the key from a local property file (which is already gitignored by Android Studio) keeps it out of source control by default:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1X05R0 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;import java.util.Properties\n\nval localProperties = Properties().apply {\n  val file = rootProject.file(\&amp;quot;local.properties\&amp;quot;)\n  if (file.exists()) file.inputStream().use { load(it) }\n}\n\nandroid {\n  namespace = \&amp;quot;com.revenuecat.catpaywalls\&amp;quot;\n  defaultConfig {\n    applicationId = \&amp;quot;com.revenuecat.catpaywalls\&amp;quot;\n    buildConfigField(\n      \&amp;quot;String\&amp;quot;,\n      \&amp;quot;REVENUECAT_TEST_API_KEY\&amp;quot;,\n      \&amp;quot;\\\&amp;quot;${localProperties.getProperty(\&amp;quot;revenuecat.test.api.key\&amp;quot;, \&amp;quot;\&amp;quot;)}\\\&amp;quot;\&amp;quot;,\n    )\n  }\n  buildFeatures {\n    compose = true\n    buildConfig = true\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Notice the default value of an empty string. If&amp;nbsp;&lt;code&gt;local.properties&lt;/code&gt;&amp;nbsp;does not contain&amp;nbsp;&lt;code&gt;revenuecat.test.api.key&lt;/code&gt;, the field is still defined and compiles cleanly. That matters for two reasons: release builds pulled from a clean CI checkout do not see the key at all, and any developer who has not opted into the Test Store keeps the regular production path without any source changes.&lt;/p&gt;



&lt;p&gt;The&amp;nbsp;&lt;code&gt;local.properties&lt;/code&gt;&amp;nbsp;entry on a developer machine is one line:&lt;/p&gt;



&lt;pre class=&quot;wp-block-code&quot;&gt;&lt;code&gt;revenuecat.test.api.key=test_YOUR_KEY_HERE
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;The key selection happens in&amp;nbsp;&lt;code&gt;CatArticlesApplication&lt;/code&gt;, which is the Android entry point for the shared Compose surface. The pattern is “prefer Test Store key when present, fall back to the production key otherwise”:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Ze1UCH wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;class CatArticlesApplication : Application() {\n\n  override fun onCreate() {\n    super.onCreate()\n\n    Purchases.logLevel = LogLevel.DEBUG\n    val apiKey = BuildConfig.REVENUECAT_TEST_API_KEY\n      .takeIf { it.isNotBlank() } ?: REVENUECAT_API_KEY\n\n    Purchases.configure(\n      PurchasesConfiguration(apiKey = apiKey) {\n        appUserId = null\n      },\n    )\n  }\n\n  companion object {\n    private const val REVENUECAT_API_KEY = \&amp;quot;your_revenuecat_api_key\&amp;quot;\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Two design decisions here are worth pulling out. The first is that the same&amp;nbsp;&lt;code&gt;Purchases.configure&lt;/code&gt;&amp;nbsp;call routes either to the Test Store or to production. The KMP SDK does not have a separate “test mode” flag; it picks the backend based on the key prefix and behaves identically otherwise. Your&amp;nbsp;&lt;code&gt;commonMain&lt;/code&gt;&amp;nbsp;code never has to ask which backend it is talking to. The second is that this is a debug only ergonomics, not a build flavor. Every developer can flip on Test Store for their personal build by adding one line to their own&amp;nbsp;&lt;code&gt;local.properties&lt;/code&gt;, without any branches in the source tree.&lt;/p&gt;



&lt;p&gt;The iOS side does not need an analogue. When the Kotlin runtime starts on iOS, it shares the same&amp;nbsp;&lt;code&gt;Purchases.sharedInstance&lt;/code&gt;&amp;nbsp;configured by the platform&amp;nbsp;&lt;code&gt;App&lt;/code&gt;&amp;nbsp;struct. If you want the iOS app to also use the Test Store during development, configure the same&amp;nbsp;&lt;code&gt;test_...&lt;/code&gt;&amp;nbsp;key in the SwiftUI entry point:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZML446 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@main\nstruct iosAppApp: App {\n    init() {\n        Purchases.logLevel = .debug\n        Purchases.configure(withAPIKey: testStoreApiKey ?? \&amp;quot;your_ios_api_key\&amp;quot;)\n    }\n    var body: some Scene {\n        WindowGroup { ContentView() }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Read&amp;nbsp;&lt;code&gt;testStoreApiKey&lt;/code&gt;&amp;nbsp;from an&amp;nbsp;&lt;code&gt;.xcconfig&lt;/code&gt;, a&amp;nbsp;&lt;code&gt;Info.plist&lt;/code&gt;&amp;nbsp;entry, or a build setting. The shape is the same as on Android: take the key from a local source of truth, fall back to a production constant.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;the-testability-boundary-wrapping-purchases-behind-a-repository&quot;&gt;&lt;strong&gt;The testability boundary: wrapping Purchases behind a repository&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Even with the Test Store wired up, you do not want every unit test to depend on a running&amp;nbsp;&lt;code&gt;Purchases.sharedInstance&lt;/code&gt;. The SDK assumes a platform context that is not present in&amp;nbsp;&lt;code&gt;commonTest&lt;/code&gt;: an Android&amp;nbsp;&lt;code&gt;Context&lt;/code&gt;, a&amp;nbsp;&lt;code&gt;BillingClient&lt;/code&gt;, an iOS StoreKit transaction listener. The cat-paywalls-kmp demo solves this by funneling every call into the SDK through a single repository interface in&amp;nbsp;&lt;code&gt;core/data&lt;/code&gt;:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1R5RPr wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;interface PaywallsRepository {\n  fun fetchOffering(): Flow&lt;Result&lt;Offering&gt;&gt;\n  fun fetchCustomerInfo(): Flow&lt;Result&lt;CustomerInfo&gt;&gt;\n  fun awaitPurchase(packageId: String): Flow&lt;Result&lt;StoreTransaction&gt;&gt;\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;There are three things to notice about this interface. First, every method returns a&amp;nbsp;&lt;code&gt;Flow&amp;lt;Result&amp;lt;T&amp;gt;&amp;gt;&lt;/code&gt;&amp;nbsp;instead of a suspend function. That choice gives&amp;nbsp;&lt;code&gt;StateFlow&lt;/code&gt;&amp;nbsp;consumers something to&amp;nbsp;&lt;code&gt;.map&lt;/code&gt;&amp;nbsp;and&amp;nbsp;&lt;code&gt;.collect&lt;/code&gt;&amp;nbsp;without paying for an extra&amp;nbsp;&lt;code&gt;viewModelScope.launch&lt;/code&gt;, and it lets the implementation choose between cold flow semantics and&amp;nbsp;&lt;code&gt;stateIn&lt;/code&gt;&amp;nbsp;caching without changing callers. Second, the types in the return positions are all from&amp;nbsp;&lt;code&gt;com.revenuecat.purchases.kmp.models.*&lt;/code&gt;. They are pure Kotlin data classes that exist in&amp;nbsp;&lt;code&gt;commonMain&lt;/code&gt;, which means a test can construct or hold them without expect/actual gymnastics. Third, there is no platform specific code in the signature, which is what lets the same interface back both&amp;nbsp;&lt;code&gt;androidMain&lt;/code&gt;&amp;nbsp;and&amp;nbsp;&lt;code&gt;iosMain&lt;/code&gt;&amp;nbsp;consumers.&lt;/p&gt;



&lt;p&gt;The production implementation wraps&amp;nbsp;&lt;code&gt;Purchases.sharedInstance&lt;/code&gt;&amp;nbsp;with&amp;nbsp;&lt;code&gt;suspendCancellableCoroutine&lt;/code&gt;&amp;nbsp;and a small&amp;nbsp;&lt;code&gt;Flow&lt;/code&gt;&amp;nbsp;builder. The shape is straightforward:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Zs0JGm wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;class PaywallsRepositoryImpl : PaywallsRepository {\n\n  override fun fetchCustomerInfo(): Flow&lt;Result&lt;CustomerInfo&gt;&gt; = flow {\n    try {\n      val customerInfo = Purchases.sharedInstance.awaitCustomerInfo()\n      emit(Result.success(customerInfo))\n    } catch (e: Exception) {\n      emit(Result.failure(e))\n    }\n  }.flowOn(Dispatchers.IO)\n\n  override fun fetchOffering(): Flow&lt;Result&lt;Offering&gt;&gt; = flow {\n    try {\n      val offerings = Purchases.sharedInstance.awaitOfferings()\n      val current = offerings.current ?: error(\&amp;quot;No current offering\&amp;quot;)\n      emit(Result.success(current))\n    } catch (e: Exception) {\n      emit(Result.failure(e))\n    }\n  }.flowOn(Dispatchers.IO)\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This is the only place in the entire codebase that imports&amp;nbsp;&lt;code&gt;Purchases.sharedInstance&lt;/code&gt;. Every&amp;nbsp;&lt;code&gt;ViewModel&lt;/code&gt;, every Compose function, every test is on the other side of the interface. That is the boundary you need to make&amp;nbsp;&lt;code&gt;commonTest&lt;/code&gt;&amp;nbsp;viable, because anything above this line can be exercised against a fake.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;unit-testing-in-commontest-the-patterns-that-work-on-both-platforms&quot;&gt;&lt;strong&gt;Unit testing in commonTest: the patterns that work on both platforms&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;A Kotlin Multiplatform unit test cannot use MockK, Mockito, or any reflection based mocking framework. Those libraries are JVM only. They will compile in&amp;nbsp;&lt;code&gt;commonTest&lt;/code&gt;&amp;nbsp;if MockK is on the version catalog, but the&amp;nbsp;&lt;code&gt;iosTest&lt;/code&gt;&amp;nbsp;target will fail to link when Kotlin/Native tries to resolve the bytecode generation runtime. The cat-paywalls-kmp demo even declares MockK in&amp;nbsp;&lt;code&gt;gradle/libs.versions.toml&lt;/code&gt;&amp;nbsp;and then never uses it, because the moment you adopt the convention plugin that runs&amp;nbsp;&lt;code&gt;commonTest&lt;/code&gt;&amp;nbsp;against both targets you cannot import it from shared code.&lt;/p&gt;



&lt;p&gt;What does work in&amp;nbsp;&lt;code&gt;commonTest&lt;/code&gt;&amp;nbsp;is&amp;nbsp;&lt;code&gt;kotlin-test&lt;/code&gt;,&amp;nbsp;&lt;code&gt;kotlinx-coroutines-test&lt;/code&gt;, and Turbine. The cat-paywalls-kmp&amp;nbsp;&lt;code&gt;KmpLibraryConventionPlugin&lt;/code&gt;&amp;nbsp;wires them into every feature module at the source set level:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZlIQTL wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;sourceSets.apply {\n  commonMain.dependencies {\n    implementation(libs.findLibrary(\&amp;quot;kotlinx-coroutines-core\&amp;quot;).get())\n  }\n  commonTest.dependencies {\n    implementation(libs.findLibrary(\&amp;quot;kotlin-test\&amp;quot;).get())\n    implementation(libs.findLibrary(\&amp;quot;kotlinx-coroutines-test\&amp;quot;).get())\n    implementation(libs.findLibrary(\&amp;quot;turbine\&amp;quot;).get())\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The reason this is in a convention plugin and not in each feature module’s&amp;nbsp;&lt;code&gt;build.gradle.kts&lt;/code&gt;&amp;nbsp;is that you want this to be free. Every module that hosts a&amp;nbsp;&lt;code&gt;ViewModel&lt;/code&gt;&amp;nbsp;or a state holder needs the same test dependencies, and forcing each module to opt in by hand is exactly the kind of friction that ends with someone writing logic they cannot reach from a test. The plugin makes “write a unit test” the default, not a setup task.&lt;/p&gt;



&lt;p&gt;A feature module then only declares what is unique to its tests. For&amp;nbsp;&lt;code&gt;feature/subscriptions&lt;/code&gt;, the only extra dependency is&amp;nbsp;&lt;code&gt;core/data&lt;/code&gt;, because the test uses the real&amp;nbsp;&lt;code&gt;PaywallsRepository&lt;/code&gt;&amp;nbsp;interface:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1J7Ao2 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;plugins { id(\&amp;quot;catpaywalls.kmp.feature\&amp;quot;) }\nandroid { namespace = \&amp;quot;com.revenuecat.catpaywalls.feature.subscriptions\&amp;quot; }\nkotlin {\n  sourceSets {\n    commonTest.dependencies {\n      implementation(projects.core.data)\n    }\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;That is the entire test wiring. From here, you can write a&amp;nbsp;&lt;code&gt;class SubscriptionManagementViewModelTest&lt;/code&gt;&amp;nbsp;in&amp;nbsp;&lt;code&gt;feature/subscriptions/src/commonTest/kotlin/...&lt;/code&gt;&amp;nbsp;and it will be picked up by&amp;nbsp;&lt;code&gt;androidUnitTest&lt;/code&gt;&amp;nbsp;and&amp;nbsp;&lt;code&gt;iosTest&lt;/code&gt;&amp;nbsp;automatically. One file, both targets.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;why-fakes-beat-mocks-for-kmp-subscription-code&quot;&gt;&lt;strong&gt;Why fakes beat mocks for KMP subscription code&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;With MockK off the table, your options are hand written fakes or expect/actual mock factories. The cat-paywalls-kmp demo picks fakes for every test, and the choice is more deliberate than it looks. Subscription code has two properties that make fakes the better fit even in a JVM only project. First, the surface area of&amp;nbsp;&lt;code&gt;PaywallsRepository&lt;/code&gt;&amp;nbsp;is small. Three methods, all returning&amp;nbsp;&lt;code&gt;Flow&amp;lt;Result&amp;lt;T&amp;gt;&amp;gt;&lt;/code&gt;. There is nothing to mock that a small data class with a few setters cannot already express. Second, the same fake is reused across many tests with different setup, which makes a stateful builder more readable than a stack of&amp;nbsp;&lt;code&gt;every { ... } returns ...&lt;/code&gt;&amp;nbsp;lines.&lt;/p&gt;



&lt;p&gt;Here is what the canonical fake from&amp;nbsp;&lt;code&gt;FakePaywallsRepository.kt&lt;/code&gt;&amp;nbsp;looks like:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-UFd6p wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;class FakePaywallsRepository : PaywallsRepository {\n  private var offeringResult: Result&lt;Offering&gt;? = null\n  private var customerInfoResult: Result&lt;CustomerInfo&gt;? = null\n  private var purchaseResults: MutableMap&lt;String, Result&lt;StoreTransaction&gt;&gt; = mutableMapOf()\n\n  fun setCustomerInfoResult(result: Result&lt;CustomerInfo&gt;?) {\n    customerInfoResult = result\n  }\n\n  fun setPurchaseResult(packageId: String, result: Result&lt;StoreTransaction&gt;) {\n    purchaseResults[packageId] = result\n  }\n\n  fun simulateOfferingError(message: String = \&amp;quot;Failed to fetch offering\&amp;quot;) {\n    offeringResult = Result.failure(Exception(message))\n  }\n\n  fun simulateCustomerInfoError(message: String = \&amp;quot;Failed to fetch customer info\&amp;quot;) {\n    customerInfoResult = Result.failure(Exception(message))\n  }&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The constructor takes no arguments. The fake starts in a deliberately empty state where every flow emits a “not configured” failure. A test then sets the slots it cares about and leaves the others alone. That asymmetry is the value of fakes over mocks: you do not have to enumerate every method up front, you only describe the scenario you are testing.&lt;/p&gt;



&lt;p&gt;The flow methods themselves are one line each, with the empty case routed through a recognisable exception so a misconfigured test fails loudly rather than hanging on an empty flow:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1pKm8h wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;  override fun fetchCustomerInfo(): Flow&lt;Result&lt;CustomerInfo&gt;&gt; = flow {\n    emit(customerInfoResult ?: Result.failure(IllegalStateException(\&amp;quot;No customer info configured\&amp;quot;)))\n  }\n\n  override fun awaitPurchase(packageId: String): Flow&lt;Result&lt;StoreTransaction&gt;&gt; = flow {\n    emit(purchaseResults[packageId] ?: Result.failure(IllegalStateException(\&amp;quot;Package not found: $packageId\&amp;quot;)))\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The&amp;nbsp;&lt;code&gt;IllegalStateException&lt;/code&gt;&amp;nbsp;here is not for production semantics. It is a test ergonomic. When a future contributor adds a test that calls a method without setting it up, the test fails with a message that names the missing slot, which is much faster to debug than an empty&amp;nbsp;&lt;code&gt;Flow&lt;/code&gt;&amp;nbsp;that just never emits.&lt;/p&gt;



&lt;p&gt;One limitation to call out. The fake holds and returns&amp;nbsp;&lt;code&gt;Offering&lt;/code&gt;&amp;nbsp;and&amp;nbsp;&lt;code&gt;CustomerInfo&lt;/code&gt;&amp;nbsp;values, but it does not construct them. Those types come from&amp;nbsp;&lt;code&gt;purchases-kmp&lt;/code&gt;&amp;nbsp;and do not currently expose public constructors. That means you can test the failure paths through the fake directly, but a successful “purchase completed and entitlement is now active” assertion has to be exercised against a real&amp;nbsp;&lt;code&gt;Purchases.sharedInstance&lt;/code&gt;. That is exactly the seam the Test Store fills, and the next two sections show how.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;writing-tests-against-the-fake&quot;&gt;&lt;strong&gt;Writing tests against the fake&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;A ViewModel test in&amp;nbsp;&lt;code&gt;commonTest&lt;/code&gt;&amp;nbsp;looks almost identical to its androidx counterpart. The only differences are the&amp;nbsp;&lt;code&gt;kotlinx.coroutines.test.StandardTestDispatcher&lt;/code&gt;&amp;nbsp;instead of&amp;nbsp;&lt;code&gt;TestCoroutineDispatcher&lt;/code&gt;, and Turbine instead of&amp;nbsp;&lt;code&gt;LiveData&lt;/code&gt;&amp;nbsp;observers. Here is the setup pattern that the cat-paywalls-kmp&amp;nbsp;&lt;code&gt;SubscriptionManagementViewModelTest&lt;/code&gt;&amp;nbsp;uses:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z2nSPTV wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@OptIn(ExperimentalCoroutinesApi::class)\nclass SubscriptionManagementViewModelTest {\n\n  private val testDispatcher = StandardTestDispatcher()\n  private lateinit var fakeRepository: FakePaywallsRepository\n\n  @BeforeTest\n  fun setup() {\n    Dispatchers.setMain(testDispatcher)\n    fakeRepository = FakePaywallsRepository()\n  }\n\n  @AfterTest\n  fun tearDown() {\n    Dispatchers.resetMain()\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;&lt;code&gt;Dispatchers.setMain&lt;/code&gt;&amp;nbsp;replaces the main dispatcher that&amp;nbsp;&lt;code&gt;viewModelScope&lt;/code&gt;&amp;nbsp;uses with the test dispatcher. Without that swap, any&amp;nbsp;&lt;code&gt;StateFlow.stateIn(viewModelScope, ...)&lt;/code&gt;&amp;nbsp;would post to the real main thread and the test would hang, because there is no Android main looper in&amp;nbsp;&lt;code&gt;commonTest&lt;/code&gt;.&amp;nbsp;&lt;code&gt;Dispatchers.resetMain&lt;/code&gt;&amp;nbsp;after each test is the symmetric tear down. Together they give you deterministic scheduling: nothing runs until you ask it to.&lt;/p&gt;



&lt;p&gt;The actual test reaches into the fake, instantiates the ViewModel, and asserts on its state through Turbine. The pattern for an error path:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZiPp5S wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Test\nfun whenCustomerInfoFetchFails_stateIsError() = runTest {\n  fakeRepository.simulateCustomerInfoError(\&amp;quot;Failed to fetch customer info\&amp;quot;)\n  val viewModel = SubscriptionManagementViewModel(fakeRepository)\n\n  viewModel.uiState.test {\n    assertIs&lt;SubscriptionManagementUiState.Loading&gt;(awaitItem())\n    testDispatcher.scheduler.advanceUntilIdle()\n    val errorState = awaitItem()\n    assertIs&lt;SubscriptionManagementUiState.Error&gt;(errorState)\n    assertEquals(\&amp;quot;Failed to fetch customer info\&amp;quot;, errorState.message)\n    cancelAndIgnoreRemainingEvents()\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Three details earn their keep here. The first&amp;nbsp;&lt;code&gt;awaitItem()&lt;/code&gt;&amp;nbsp;returns the initial&amp;nbsp;&lt;code&gt;Loading&lt;/code&gt;&amp;nbsp;value because&amp;nbsp;&lt;code&gt;StateFlow&lt;/code&gt;&amp;nbsp;always replays its current state on collection.&amp;nbsp;&lt;code&gt;testDispatcher.scheduler.advanceUntilIdle()&lt;/code&gt;&amp;nbsp;then drains every queued coroutine in the test scope, which is what causes the repository’s flow to emit, the ViewModel’s&amp;nbsp;&lt;code&gt;combine&lt;/code&gt;&amp;nbsp;chain to run, and the next state to land in the&amp;nbsp;&lt;code&gt;StateFlow&lt;/code&gt;. The second&amp;nbsp;&lt;code&gt;awaitItem()&lt;/code&gt;&amp;nbsp;picks that state up, and the assertion confirms the error message survives the pipeline.&lt;/p&gt;



&lt;p&gt;If you write four or five tests like this, you cover the entire surface of the ViewModel’s state machine. The initial loading state, the offering error path, the customer info error path, the combined error path, and the cancellation path are each one fake setter plus an&amp;nbsp;&lt;code&gt;awaitItem()&lt;/code&gt;. None of these tests need a billing client, none of them need a network, and the same suite runs against the JVM target and the iOS target without modification.&lt;/p&gt;



&lt;p&gt;What this suite cannot cover is the actual purchase. Because the fake cannot construct an&amp;nbsp;&lt;code&gt;Offering&lt;/code&gt;&amp;nbsp;with real packages, you cannot run a test that says “the user taps subscribe, the SDK validates the receipt, and the entitlement flips to active.” For that path you need the Test Store, and the right place for it is an instrumented test on top of the unit suite, not inside it.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;integration-testing-with-the-test-store-on-android&quot;&gt;&lt;strong&gt;Integration testing with the Test Store on Android&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The&amp;nbsp;&lt;a href=&quot;https://www.revenuecat.com/blog/engineering/testing-test-store/&quot;&gt;Testing Test Store&lt;/a&gt;&amp;nbsp;post on the RevenueCat engineering blog walks through this end to end, and the same approach applies to a CMP project because the Android target compiles down to a normal&amp;nbsp;&lt;code&gt;androidTest&lt;/code&gt;&amp;nbsp;source set. Put the integration test in&amp;nbsp;&lt;code&gt;composeApp/src/androidTest/kotlin/...&lt;/code&gt;. Configure&amp;nbsp;&lt;code&gt;Purchases&lt;/code&gt;&amp;nbsp;once with the Test Store key, launch a small activity that drives a real purchase, and use Espresso to tap one of the three buttons that the Test Store modal presents.&lt;/p&gt;



&lt;p&gt;The setup uses&amp;nbsp;&lt;code&gt;InstrumentationRegistry.getInstrumentation().targetContext&lt;/code&gt;&amp;nbsp;because the test runs in a real Android process, not in a JVM unit test. The configuration call is the same one your&amp;nbsp;&lt;code&gt;Application&lt;/code&gt;&amp;nbsp;makes, but pinned to the Test Store key:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z28tIXY wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Before\nfun setup() {\n  val context = InstrumentationRegistry.getInstrumentation().targetContext\n  Purchases.logLevel = LogLevel.DEBUG\n  Purchases.configure(\n    PurchasesConfiguration.Builder(context, BuildConfig.REVENUECAT_TEST_API_KEY)\n      .purchasesAreCompletedBy(PurchasesAreCompletedBy.REVENUECAT)\n      .build()\n  )\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The actual purchase test then resolves the test offering, launches the activity, and waits for the Test Store modal to appear before tapping the “Test valid Purchase” button:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1aDkiJ wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Test\nfun successfulPurchaseUpdatesEntitlements() = runBlocking {\n  val offerings = Purchases.sharedInstance.awaitOfferings()\n  val pkg = offerings.all[\&amp;quot;test-offering\&amp;quot;]!!.availablePackages.first()\n\n  activityScenario = ActivityScenario.launch(TestPurchaseActivity::class.java)\n  activityScenario.onActivity { activity -&gt;\n    activity.launchPurchase(pkg) { result, _ -&gt; purchaseResult = result }\n  }\n\n  delay(2_000)\n  onView(withText(\&amp;quot;Test valid Purchase\&amp;quot;)).perform(click())\n\n  withTimeout(30.seconds) {\n    while (purchaseResult == null) delay(500)\n  }\n\n  assertTrue(purchaseResult!!.customerInfo.entitlements.active.isNotEmpty())\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Two things to call out. The&amp;nbsp;&lt;code&gt;delay(2_000)&lt;/code&gt;&amp;nbsp;before the Espresso tap exists because the Test Store modal is rendered through the host activity, and Espresso needs the view hierarchy to settle before it can find the button. The 30 second timeout on the assertion accounts for the round trip to the RevenueCat backend that validates the receipt and updates&amp;nbsp;&lt;code&gt;CustomerInfo&lt;/code&gt;. Both numbers can be tuned for your CI environment, but they are intentionally generous because the test is doing real network work.&lt;/p&gt;



&lt;p&gt;The companion tests are the other two buttons. Tapping “Test failed Purchase” lets you assert that the entitlement stays inactive and the error propagates through your domain layer. Tapping “Cancel” lets you assert that the&amp;nbsp;&lt;code&gt;PurchaseCancelled&lt;/code&gt;&amp;nbsp;exception is mapped to a no op rather than surfaced as a user facing error. Three tests, three modal buttons, one Test Store key, no Play Console.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;the-ios-side-storekit-configuration-files-and-what-the-test-store-unifies&quot;&gt;&lt;strong&gt;The iOS side: StoreKit configuration files and what the Test Store unifies&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;On iOS, the equivalent of an instrumented test is a StoreKit configuration file driving an XCUITest. Apple introduced&amp;nbsp;&lt;a href=&quot;https://www.revenuecat.com/docs/test-and-launch/sandbox/apple-app-store&quot;&gt;StoreKit configuration files&lt;/a&gt;&amp;nbsp;in Xcode 12, and they remain the canonical way to test purchases inside the iOS simulator without setting up a sandbox account. You describe the products in a&amp;nbsp;&lt;code&gt;.storekit&lt;/code&gt;&amp;nbsp;file, attach it to a scheme, and run the app under that scheme. Purchases then resolve through the configuration file instead of the App Store backend, and you can use XCUITest to drive the resulting native StoreKit modal.&lt;/p&gt;



&lt;p&gt;This works, and for an iOS only app it is often the right answer. In a Compose Multiplatform project, the trade off looks different. The StoreKit configuration file only covers the iOS side. It does not interact with your Android tests, it does not flow data through your&amp;nbsp;&lt;code&gt;PaywallsRepository&lt;/code&gt;, and a successful purchase against it does not show up in the RevenueCat dashboard the way a real purchase does. You end up with two parallel integration suites that test the same Kotlin code through two completely different driver layers.&lt;/p&gt;



&lt;p&gt;The Test Store collapses this. When the same&amp;nbsp;&lt;code&gt;commonMain&lt;/code&gt;&amp;nbsp;code is configured against a Test Store key on both platforms, an iOS purchase goes through the same RevenueCat modal as an Android purchase, the same backend validates the receipt, and the same&amp;nbsp;&lt;code&gt;CustomerInfo&lt;/code&gt;&amp;nbsp;flow emits the same shape on both sides. Your iOS integration test can then drive the same three button modal with XCUITest:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z12JCbm wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;func testSuccessfulPurchase() throws {\n    let app = XCUIApplication()\n    app.launch()\n    app.buttons[\&amp;quot;Subscribe\&amp;quot;].tap()\n    app.buttons[\&amp;quot;Test valid Purchase\&amp;quot;].tap()\n\n    let unlockedHeader = app.staticTexts[\&amp;quot;Premium Article\&amp;quot;]\n    XCTAssertTrue(unlockedHeader.waitForExistence(timeout: 30))\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The pattern mirrors the Android Espresso test almost line for line. Find the subscribe button, find the “Test valid Purchase” button, wait for the gated content to unlock. The same three Test Store buttons cover the same three scenarios. The same&amp;nbsp;&lt;code&gt;CustomerInfo&lt;/code&gt;&amp;nbsp;update unlocks the same composable. You still write two driver layers because the OS testing frameworks are different, but the data plane is shared, the network calls are the same, and the dashboard sees both runs as the same Test Store activity.&lt;/p&gt;



&lt;p&gt;For most teams, this is enough. If you also want to exercise the native StoreKit error paths (parental controls blocking a purchase, sandbox account expired, region restrictions), keep a small&amp;nbsp;&lt;code&gt;.storekit&lt;/code&gt;&amp;nbsp;based suite for those edge cases. The bulk of your purchase path coverage moves to the Test Store and shrinks the size of the iOS only suite to a handful of platform specific tests.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;a-three-layer-testing-strategy&quot;&gt;&lt;strong&gt;A three layer testing strategy&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Putting it all together, a Compose Multiplatform subscription app has three useful test layers, and each one answers a different question.&lt;/p&gt;



&lt;p&gt;The first layer is&amp;nbsp;&lt;code&gt;commonTest&lt;/code&gt;&amp;nbsp;unit tests against&amp;nbsp;&lt;code&gt;FakePaywallsRepository&lt;/code&gt;. This is where you cover your ViewModel state machine: initial loading, error paths, cancellation handling, derived UI states, and any business logic that lives above the SDK boundary. These tests are fast, deterministic, run on both targets from a single source set, and never touch the network. They are the layer you run on every PR, in pre push hooks, and on every CI build.&lt;/p&gt;



&lt;p&gt;The second layer is instrumented tests against the Test Store. On Android this is&amp;nbsp;&lt;code&gt;androidTest&lt;/code&gt;&amp;nbsp;with Espresso. On iOS this is XCUITest. Both drive the same RevenueCat purchase modal, both produce real&amp;nbsp;&lt;code&gt;CustomerInfo&lt;/code&gt;&amp;nbsp;updates, and both verify the end to end flow from subscribe button to unlocked content. These tests are slower and a little flakier because they include real network calls, but they are the only layer where you can prove that the purchase path works for a real receipt. Run them on merges to main, on release branches, and as part of your release qualification.&lt;/p&gt;



&lt;p&gt;The third layer is optional and platform specific. A StoreKit configuration file based suite for iOS edge cases that the Test Store does not model. A Google Play closed track for the rare bugs that only reproduce against the real billing client. Both are valuable, but neither is the workhorse. They exist to plug specific gaps, not to cover the core purchase flow.&lt;/p&gt;



&lt;p&gt;The numbers shift the right way too. The unit tests are tens of milliseconds each and run on every commit. The instrumented Test Store tests are seconds each and run on merge. The native edge case suites are minutes each and run on release. Most of your purchase coverage ends up in the layer that runs most often, which is the opposite of what happens when you only have a&amp;nbsp;&lt;code&gt;closedTrack&lt;/code&gt;&amp;nbsp;and a StoreKit configuration file.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;ci-considerations-one-matrix-three-jobs&quot;&gt;&lt;strong&gt;CI considerations: one matrix, three jobs&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The CI shape that falls out of this is straightforward. One job runs&amp;nbsp;&lt;code&gt;commonTest&lt;/code&gt;&amp;nbsp;for both targets:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZCeTp2 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;- name: Run unit tests (JVM + iOS)\n  run: .\/gradlew allTests&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;&lt;code&gt;allTests&lt;/code&gt;&amp;nbsp;is the umbrella task that Kotlin Multiplatform creates when you have both Android and iOS targets configured. It dispatches to&amp;nbsp;&lt;code&gt;jvmTest&lt;/code&gt;,&amp;nbsp;&lt;code&gt;iosX64Test&lt;/code&gt;,&amp;nbsp;&lt;code&gt;iosSimulatorArm64Test&lt;/code&gt;, and any other target you have enabled. A failure in any one fails the job. Run this on every push, every pull request, and every nightly build.&lt;/p&gt;



&lt;p&gt;The second job runs the Test Store instrumented tests on Android. The blog’s CI snippet works as written:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1GybAh wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;- uses: reactivecircus\/android-emulator-runner@v2\n  with:\n    api-level: 30\n    target: google_apis\n    arch: x86_64\n    script: .\/gradlew :composeApp:connectedAndroidTest&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Two practical notes. The Test Store key needs to be available to this job, but not to forks or to release builds. The cleanest way is a repository secret that the job writes to&amp;nbsp;&lt;code&gt;local.properties&lt;/code&gt;&amp;nbsp;at the start of the run, so the same&amp;nbsp;&lt;code&gt;buildConfigField&lt;/code&gt;&amp;nbsp;pattern picks it up. The job should also run on merges to main and on release branches, not on every PR, because it includes real network calls and consumes Test Store renewals.&lt;/p&gt;



&lt;p&gt;The third job runs the iOS XCUITests. A standard&amp;nbsp;&lt;code&gt;xcodebuild test&lt;/code&gt;&amp;nbsp;invocation against the same scheme that ships the app, with the Test Store key injected through the same mechanism your local builds use. Both Android and iOS integration jobs read from the same RevenueCat project, which means a single dashboard view shows test activity from both platforms.&lt;/p&gt;



&lt;p&gt;The result is a CI surface that mirrors the test layers. Fast feedback from the unit suite on every commit. Slower but realistic feedback from the Test Store suite on merge. The expensive native suites only when you cut a release. None of these jobs require coordinating two sandboxes, and the same&amp;nbsp;&lt;code&gt;PaywallsRepository&lt;/code&gt;&amp;nbsp;and&amp;nbsp;&lt;code&gt;ViewModel&lt;/code&gt;&amp;nbsp;code is exercised end to end at every layer.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;conclusion&quot;&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;In this article, you’ve worked through a complete subscription testing setup for a Compose Multiplatform app. You configured the RevenueCat Test Store from&amp;nbsp;&lt;code&gt;local.properties&lt;/code&gt;&amp;nbsp;and a single&amp;nbsp;&lt;code&gt;buildConfigField&lt;/code&gt;, drew the testability boundary at a&amp;nbsp;&lt;code&gt;PaywallsRepository&lt;/code&gt;&amp;nbsp;interface so the SDK never leaks into your ViewModels or your tests, wrote&amp;nbsp;&lt;code&gt;commonTest&lt;/code&gt;&amp;nbsp;unit tests against a&amp;nbsp;&lt;code&gt;FakePaywallsRepository&lt;/code&gt;&amp;nbsp;using&amp;nbsp;&lt;code&gt;kotlin-test&lt;/code&gt;,&amp;nbsp;&lt;code&gt;kotlinx-coroutines-test&lt;/code&gt;, and Turbine, then layered instrumented tests on top with Espresso on Android and XCUITest on iOS that drive the same three button Test Store modal. The same shared code path is exercised from&amp;nbsp;&lt;code&gt;commonTest&lt;/code&gt;&amp;nbsp;all the way through to the receipt validation backend, on both platforms, without two parallel test suites.&lt;/p&gt;



&lt;p&gt;The thing worth internalizing is what changed at each layer. Subscription testing usually fragments because the sandboxes do. By moving the development sandbox up into RevenueCat itself, the Test Store turns the two platform problem back into one. By putting a small repository interface between&amp;nbsp;&lt;code&gt;Purchases.sharedInstance&lt;/code&gt;&amp;nbsp;and the rest of your app,&amp;nbsp;&lt;code&gt;commonTest&lt;/code&gt;&amp;nbsp;becomes a viable home for the bulk of your business logic tests. By using fakes instead of mocks at the unit layer, the same suite runs against both Kotlin targets without expect/actual or a JVM only mocking framework. Each of these choices is small. Together they collapse what used to be two test suites into one.&lt;/p&gt;



&lt;p&gt;Whether you are porting an Android subscription app to iOS, starting a new CMP product from scratch, or trying to get purchase testing into CI for the first time, this layered setup gives you the smallest surface area you can ship a cross platform subscription app on with real confidence. The full source for every snippet in this article lives in&amp;nbsp;&lt;a href=&quot;https://github.com/RevenueCat/cat-paywalls-kmp&quot;&gt;cat-paywalls-kmp&lt;/a&gt;, and a free RevenueCat project with a Test Store key is the only thing you need to run all three layers locally.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Revenge of the brand manager: why ‘pretty’ ads fail at direct response]]></title><description><![CDATA[Why you should be optimizing for live experience over aesthetics]]></description><link>https://www.revenuecat.com/blog/growth/direct-response-creative/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/direct-response-creative/</guid><pubDate>Mon, 11 May 2026 14:42:25 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/Blog_60_Why-‘ugly-ads-do-better-for-direct-response.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;There’s a persistent temptation in app growth to make things look beautiful. When a team finally gets budget for creative production, the instinct is to hire a slick agency, shoot in 4K, and write a punchy, conceptual slogan. It feels like real marketing — like you’re finally building a brand.&lt;/p&gt;



&lt;p&gt;But when those ads hit the Facebook and Instagram feeds, they often bomb.&lt;/p&gt;



&lt;p&gt;I framed this pattern &lt;a href=&quot;https://www.youtube.com/watch?v=Wj9d0ej3rmk&quot;&gt;during a recent Sub Club Live&lt;/a&gt; as “revenge of the brand manager”. This happens when you optimize for aesthetics rather than addressing the messy, stressful reality your users actually inhabit.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-selling-a-vibe-instead-of-a-solution&quot;&gt;Selling a vibe instead of a solution&lt;/h2&gt;



&lt;p&gt;Take a recent ad campaign from Granola, a popular AI note-taking app. Granola’s ads were undeniably gorgeous — exactly what a brand manager wants to see on a billboard.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;523&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-2-1024x523.png&quot; alt=&quot;&quot; class=&quot;wp-image-53766&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-2-1024x523.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-2-300x153.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-2-768x392.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-2-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-2-78x40.png 78w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-2-696x355.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-2-560x286.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-2-840x429.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-2-80x41.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-2-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-2.png 1199w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The problem? The ads didn’t speak to the user.&lt;/p&gt;



&lt;p&gt;When I look at creative like this, I see an ad made by somebody who hasn’t taken the time or trouble to really understand the world their users inhabit. While it checks a lot of boxes for traditional advertising best practices, in direct response advertising, it doesn’t really speak to what the users are going through.&lt;/p&gt;



&lt;p&gt;When a user is scrolling through Instagram or TikTok, a conceptual slogan doesn’t stop them. They don’t care about your brand identity — they care about their own immediate problems. If your ad looks like it was made simply to be beautiful, it registers as an ad. An interruption rather than a solution. As we’ve seen with the shift toward &lt;a href=&quot;https://www.revenuecat.com/blog/growth/ugc-ads-apps/&quot;&gt;value-first UGC ads&lt;/a&gt;, users have developed a profound blindness to anything that feels overly produced or disconnected from their reality.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-designing-for-the-lived-experience&quot;&gt;Designing for the lived experience&lt;/h2&gt;



&lt;p&gt;If beautiful slogans don’t work, what does? The fix is to root your creative entirely in the user’s lived experience. You have to depict a specific scenario that the user recognizes immediately.&lt;/p&gt;



&lt;p&gt;For a note-taking app like Granola, I would suggest focusing on a visceral moment of panic.&lt;/p&gt;



&lt;p&gt;Take a specific instance from your user’s life, like a CEO asking what the client said. You freeze. But then you look at this app, and remember your notes. That kind of lived experience ad works much, much better versus a slogan where I don’t even know what the product does for anyone.&lt;/p&gt;



&lt;script src=&quot;https://fast.wistia.com/player.js&quot; async=&quot;&quot;&gt;&lt;/script&gt;&lt;script src=&quot;https://fast.wistia.com/embed/dehf64pfbs.js&quot; async=&quot;&quot; type=&quot;module&quot;&gt;&lt;/script&gt;&lt;style&gt;wistia-player[media-id=&apos;dehf64pfbs&apos;]:not(:defined) { background: center / contain no-repeat url(&apos;https://fast.wistia.com/embed/medias/dehf64pfbs/swatch&apos;); display: block; filter: blur(5px); }&lt;/style&gt; &lt;wistia-player media-id=&quot;dehf64pfbs&quot; aspect=&quot;1.7777777777777777&quot; style=&quot;width: 600px;height: 338px;&quot;&gt;&lt;/wistia-player&gt;



&lt;p&gt;This approach works because it leverages the &lt;a href=&quot;https://www.revenuecat.com/blog/growth/solve-app-problems-emotionally/&quot;&gt;emotion that comes with a solved problem&lt;/a&gt;. The user isn’t buying an AI note-taker; they’re buying an escape hatch for when their boss puts them on the spot. By visualizing the panic of the problem and the relief of the solution, the ad earns the click.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-ugly-often-wins&quot;&gt;Why ‘ugly’ often wins&lt;/h2&gt;



&lt;p&gt;This reality is often frustrating for founders and designers. As David pointed out during our live session, it is easy to err on the side of polish because we all love the ideal of pristine brand advertising. But in direct response, the ‘ugly’ design — the one that clearly and bluntly states the problem — is frequently what wins the &lt;a href=&quot;https://www.revenuecat.com/blog/growth/subscription-app-creative-testing/&quot;&gt;creative testing&lt;/a&gt; phase.&lt;/p&gt;



&lt;p&gt;When you’re scaling &lt;a href=&quot;https://www.revenuecat.com/blog/growth/web-to-app-paid-user-acquisition/&quot;&gt;paid user acquisition&lt;/a&gt;, you cannot afford to let aesthetic preferences dictate strategy. If you &lt;a href=&quot;https://www.revenuecat.com/blog/growth/overanalyze-creative-analysis-paid-ads/&quot;&gt;overanalyze your creative&lt;/a&gt; through the lens of brand purity, you miss the scrappy, relatable angles that actually drive downloads and &lt;a href=&quot;https://www.revenuecat.com/blog/growth/7-day-trial-subscription-app/&quot;&gt;trial starts&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;So the next time you brief a designer or a creator, ban the conceptual slogans. Ask them to show you the moment your user sweats, and the moment your app makes them breathe a sigh of relief.&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;p&gt;&lt;em&gt;About the Author: Shamanth Rao is the founder and CEO of &lt;a href=&quot;https://www.rocketshiphq.com/&quot;&gt;RocketShip HQ&lt;/a&gt;, a boutique growth marketing firm with over $100 million in managed spend. He hosts the &lt;a href=&quot;https://mobileuseracquisitionshow.com/&quot;&gt;Mobile User Acquisition Show&lt;/a&gt;, where he’s launched Intelligent Artifice, a deep dive on how AI is transforming performance marketing.&lt;/em&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Meet the subscription app pre-mortem: how to plan for failure before you ship]]></title><description><![CDATA[Why pessimistic planning leads to optimistic launches]]></description><link>https://www.revenuecat.com/blog/growth/subscription-app-pre-mortem/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/subscription-app-pre-mortem/</guid><pubDate>Fri, 08 May 2026 10:45:34 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/Blog-51_Why-the-best-teams-plan-for-failure-before-they-ship.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;When I started out in the app industry, I worked at a growth agency that partnered with a development agency. As a result, a lot of our projects involved launching entirely new websites or app redesigns.&lt;/p&gt;



&lt;p&gt;It was amazing — a fresh slate to use all our customer insights and improve performance! …But also slightly terrifying. Not because of the work itself, but because of the waiting.&lt;/p&gt;



&lt;p&gt;That horrible in-between phase after you’ve shipped something, where you’re refreshing dashboards, overanalyzing early feedback, and catastrophizing every dip in the numbers.&lt;/p&gt;



&lt;p&gt;What helped me wasn’t positive thinking. It was the opposite: leaning into pessimism.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Deliberately imagining everything that could go wrong &lt;em&gt;before&lt;/em&gt; launch. Thinking through every possible scenario. Having the trickiest, most uncomfortable conversations with clients and teams to explore all the what-ifs.&lt;/p&gt;



&lt;p&gt;It’s called a &lt;strong&gt;pre-mortem&lt;/strong&gt;. (A bit morbid, but it works.)&lt;/p&gt;



&lt;p&gt;Since then, I’ve used it for everything from website redesigns to &lt;a href=&quot;https://www.revenuecat.com/blog/growth/guide-to-mobile-paywalls-subscription-apps/&quot;&gt;subscription app launches&lt;/a&gt;; especially in products where feedback loops are fast and the stakes compound quickly.&lt;/p&gt;



&lt;p&gt;And it’s become one of my favorite planning tools.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-is-a-pre-mortem&quot;&gt;What is a pre-mortem?&lt;/h2&gt;



&lt;p&gt;A regular post-mortem happens after something fails, the classic sprint retrospective. You gather the team, ask not only ‘what went right’ but also ‘what went wrong’ or ‘what could have gone better’, and try to learn from it.&lt;/p&gt;



&lt;p&gt;It often comes with a few cringe-inducing &lt;em&gt;“we could have predicted that”&lt;/em&gt; moments, where Captain Hindsight suddenly looks like a genius.&lt;/p&gt;



&lt;p&gt;The problem is, &lt;strong&gt;it’s reactive rather than proactive&lt;/strong&gt;. You’re analyzing what went wrong after the fact, but it doesn’t change the outcome.&lt;/p&gt;



&lt;p&gt;A pre-mortem flips that. The concept is simple: before you launch, imagine it’s three months later, and the launch has completely flopped. Really put yourselves in that moment: the disappointment, the stress, and the why-is-this-happening panic. Bring it to life.&lt;/p&gt;



&lt;p&gt;Then ask the full team: &lt;strong&gt;&lt;em&gt;why did it fail?&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;I called it pessimistic, but honestly, it’s not. It only becomes pessimistic if you assume failure is inevitable and stop there. The real goal is to &lt;strong&gt;surface risks while you can still do something about them&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;If anything, it’s more realistic — and even optimistic — because it assumes you &lt;em&gt;can&lt;/em&gt; fix and prevent those risks.&lt;/p&gt;



&lt;p&gt;And the interesting part? The things that come up in a pre-mortem are rarely surprising. They’re usually the things everyone already half-knows but hasn’t said out loud.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-who-came-up-with-such-a-morbid-concept&quot;&gt;Who came up with such a morbid concept?&lt;/h2&gt;



&lt;p&gt;The credit goes to Gary Klein and his often-cited &lt;a href=&quot;https://hbr.org/2007/09/performing-a-project-premortem&quot;&gt;Harvard Business Review article from 2007&lt;/a&gt;. But Gary (and yes, given how much I love this concept, we’re absolutely on a first-name basis) had been using the method for a good 30 years before that. He first developed it in the early 90s, so no one needs to do confusing maths back from 2007.&lt;/p&gt;



&lt;p&gt;A psychologist by trade, he was fascinated by how people make decisions under pressure and uncertainty. He studied this in one of the most high-stakes environments imaginable: the US Air Force. Later, he developed the idea of pre-mortems further within his own research company, drawing not only on that work but also on medical post-mortems.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;What Gary understood — and what more of us need to recognize — is the flawed reality of group decision-making. We’re wired for harmony. We want to get along. No one wants to be the negative Nancy, pointing out risks or poking holes in a plan.&lt;/p&gt;



&lt;p&gt;I recently emailed a client outlining all the risks in their current target-setting model and ended with, “sorry, this is a bit negative…”.&lt;em&gt; &lt;/em&gt;I felt bad raising those risks, but I also knew, from experience, what happens when you don’t. When you let people believe targets are promises rather than stretch goals. Still, it sucks to be the one to say it. That’s exactly the tension Gary Klein was trying to solve. A pre-mortem removes the pressure to keep up a ‘rah-rah, everything is great!’ mindset.&lt;/p&gt;



&lt;p&gt;Instead, it creates a space &lt;strong&gt;where calling out risks isn’t awkward; it’s expected&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;Since then, the concept has taken off. You’ll find pre-mortems everywhere now: in startups, corporate boardrooms, and even back in the military (a full-circle moment, really).&lt;/p&gt;



&lt;p&gt;Daniel Kahneman — who many people know from his book &lt;em&gt;Thinking, Fast and Slow&lt;/em&gt; — even called it his single most valuable decision-making technique. Not bad for something that started as an internal fix at a small research company.&lt;/p&gt;



&lt;p&gt;Gary later expanded on the idea with what he calls the ‘double-barreled pre-mortem’. After imagining failure, you run a second round where you daydream about wild success — and what could go wrong &lt;em&gt;there&lt;/em&gt;, too.&lt;/p&gt;



&lt;p&gt;It sounds more optimistic, but the goal is the same: surface risks. Even success can break things. If only Ticketmaster had done that before the Taylor Swift Eras Tour ticket sales…&lt;/p&gt;



&lt;p&gt;So that’s how, and why, pre-mortems started. But beyond making it easier to speak up, why else is this tactic so useful?&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-do-pre-mortems-actually-help&quot;&gt;Why do pre-mortems actually help?&lt;/h2&gt;



&lt;p&gt;There are five reasons why pre-mortems are so powerful:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-they-make-you-a-better-fortune-teller&quot;&gt;1. They make you a better fortune teller&lt;/h3&gt;



&lt;p&gt;Pre-mortems use a technique known as &lt;em&gt;prospective hindsight&lt;/em&gt; (a fancy way of saying imagining the future), which Deborah Mitchell at Wharton found can &lt;a href=&quot;https://onlinelibrary.wiley.com/doi/abs/10.1002/bdm.3960020103#:~:text=Abstract,nature%20of%20explanations%20for%20events.&quot;&gt;increase your ability to correctly identify reasons for future outcomes by 30%&lt;/a&gt;. All that by pretending it has happened. You basically become a better fortune teller, pretty cool, right?&lt;/p&gt;



&lt;p&gt;So it helps you surface real potential risks more effectively than just thinking about them without a specific prompt.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-it-creates-psychological-safety-to-talk-about-risks&quot;&gt;2. It creates psychological safety to talk about risks&lt;/h3&gt;



&lt;p&gt;We’ve talked a bit about this already. By making the goal ‘identify risks’, you make it safe to say them out loud. People are often all thinking “the founder keeps changing priorities” or “pretty sure this plan was ChatGPT and hasn’t been checked”, but they might be too scared to say it out loud.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;As you see others be more open, you’ll also end up being more open.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;I think this is especially valuable when you have a room full of young, smart people. I remember at my first job, I assumed whatever senior leadership said was the right call. It felt intimidating to challenge someone with 20 years more experience than me.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Now, as a leader, I know you can tell people to speak up — but the reality is, not everyone will. A pre-mortem helps level that playing field. It gives people permission, and a clear prompt, to question assumptions, raise concerns, and say the thing they might otherwise keep to themselves.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-it-makes-the-fear-concrete&quot;&gt;3. It makes the fear concrete&lt;/h3&gt;



&lt;p&gt;Vague anxiety is paralyzing; we’ve all catastrophized over endless, nameless what-ifs. Specific risks, though, are manageable.&lt;/p&gt;



&lt;p&gt;Once you’ve written “what if no one buys it?” on paper and mapped out a plan for it, it stops being a powerful fear. It becomes just another scenario to handle.&lt;/p&gt;



&lt;p&gt;Even better, involving the whole team in a pre-mortem helps counteract the planning fallacy — that tendency to be overly optimistic, assume everything will work out, and underestimate time, costs, and risks. By making the risks concrete, you can create a clear action plan.&lt;/p&gt;



&lt;p&gt;Think of it as a bit of growth group therapy.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-4-it-removes-panic-from-decision-making&quot;&gt;4. It removes panic from decision-making&lt;/h3&gt;



&lt;p&gt;Have you ever stood in line for coffee, and suddenly it’s your turn way faster than you expected? The barista asks, “What would you like?” and you stammer out, “Um… errr, a vanilla matcha latte, wait, an iced vanilla matcha latte!” Only to take a sip and think, “What was I thinking?”&lt;/p&gt;



&lt;p&gt;Okay, that might have just been my own therapy moment the other day, but the point stands: under pressure, we’re terrible at making decisions on the spot.&lt;/p&gt;



&lt;p&gt;The same goes for post-launch problems — you’re stressed, stakeholders are asking questions; you’re tempted to make snap, reactive decisions. You blurt out the first thing that comes to mind, and hope for the best.&lt;/p&gt;



&lt;p&gt;A pre-mortem changes that. If you’ve already decided, ‘If X happens, we do Y’, then you don’t have to think under pressure. You execute the plan. You’ve already discussed the right course of action as a team, ahead of time. I do this for every experiment I run because it makes ‘failed’ experiments easier to handle: we know what failure looks like, we can learn from it, and we already have a sense of what to test next.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-5-it-gives-you-permission-to-take-action-imperfectly&quot;&gt;5. It gives you permission to take action imperfectly&lt;/h3&gt;



&lt;p&gt;I once worked with a Head of Product who was basically a pre-mortem specialist, though he probably didn’t realize it, since we’d never talked about pre-mortems. He had an uncanny ability to spot every possible risk, think it through, and tackle it. Sometimes, it felt frustrating, as it could slow projects down. Until I realized that if I named the risk and laid out a plan, he was more than happy to roll with imperfection.&lt;/p&gt;



&lt;p&gt;The extreme opposite of optimism in project planning isn’t pessimism, it’s &lt;em&gt;perfectionism&lt;/em&gt;. Try to control everything, and you’ll never go live.&lt;/p&gt;



&lt;p&gt;A pre-mortem shows you that even if things go wrong, you have a path forward. That makes it easier to ship. The goal isn’t to prevent every risk, it’s to be conscious of which risks you’re willing to accept and which you aren’t.&lt;/p&gt;



&lt;p&gt;By now, hopefully, you’re convinced and starting to wonder how to run your own pre-mortem.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-to-run-a-pre-mortem&quot;&gt;How to run a pre-mortem&lt;/h2&gt;



&lt;p&gt;While the concept itself is simple, a few small tweaks in setup and approach can make your pre-mortem far more powerful.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-1-gather-the-relevant-individuals&quot;&gt;Step 1: Gather the relevant individuals&lt;/h3&gt;



&lt;p&gt;While you can do a pre-mortem alone, I can’t recommend doing it with your team enough. Different people spot different risks based on their expertise, and hearing others’ perspectives can reveal risks you might never have considered.&lt;/p&gt;



&lt;p&gt;Even better: bring in someone outside the project; someone who won’t have rose-tinted glasses. Ideally, a classic naysayer who can look critically at what’s being assessed (kind of like that Head of Product I once worked with).&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-2-set-the-scene&quot;&gt;Step 2: Set the scene&lt;/h3&gt;



&lt;p&gt;Next, set the scene.&lt;/p&gt;



&lt;p&gt;Say something like: “It’s [date 2–3 months from now]. This launch has failed. Not a minor disappointment, but a proper flop. What happened?”&lt;/p&gt;



&lt;p&gt;Pick a timeframe that feels realistic for the project. Then lean into the drama — think back to high school theater class and really bring it to life. The goal is to make it feel real, to transport yourself to that future moment, and look back with hindsight.&lt;/p&gt;



&lt;p&gt;You can even get creative: have AI mock up a founder email, a critical internal memo, or an article in a relevant newspaper or magazine. The more tangible and vivid the scenario, the easier it is to uncover the real risks.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-3-list-every-reason-it-might-have-failed&quot;&gt;Step 3: List every reason it might have failed&lt;/h3&gt;



&lt;p&gt;Have everyone list reasons &lt;em&gt;separately&lt;/em&gt;. Write down everything, even if they seem unlikely. For example:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;We couldn’t reach enough of our target audience&lt;/li&gt;



&lt;li&gt;The &lt;a href=&quot;https://www.revenuecat.com/blog/growth/app-trial-conversion-rate-insights/&quot;&gt;trial-to-paid conversion rate&lt;/a&gt; is too low&lt;/li&gt;



&lt;li&gt;We saw very &lt;a href=&quot;https://www.revenuecat.com/blog/growth/subscription-app-churn-reasons-how-to-fix/&quot;&gt;high initial churn&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;We struggled to get downloads&lt;/li&gt;



&lt;li&gt;The price felt wrong (too high, too low, confusing)&lt;/li&gt;



&lt;li&gt;A competitor launched something similar at the same time&lt;/li&gt;



&lt;li&gt;We got bad press or reviews early on&lt;/li&gt;



&lt;li&gt;The team burned out before we could iterate&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The more specific, the better. We aren’t aiming for perfection here; &lt;em&gt;quantity over quality&lt;/em&gt; is the key at this stage. The goal is to surface as many potential risks as possible.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-4-go-through-the-risks-and-group-them-by-theme&quot;&gt;Step 4: Go through the risks and group them by theme&lt;/h3&gt;



&lt;p&gt;There will inevitably be some overlap in the concerns people raise. That’s okay, this is a no-judgment moment. At this stage, you’re not prioritizing; you’re organizing.&lt;/p&gt;



&lt;p&gt;Give everyone a chance to voice their concerns. Whatever you do, &lt;em&gt;don’t&lt;/em&gt; try to diminish them or explain why something won’t happen, especially if you’re the leader or founder.&lt;/p&gt;



&lt;p&gt;Instead, focus on grouping the concerns by theme. This helps you see more clearly:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Which concerns are the most common&lt;/li&gt;



&lt;li&gt;Which areas seem to carry the most potential risks&lt;/li&gt;
&lt;/ul&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;715&quot; height=&quot;555&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image.png&quot; alt=&quot;&quot; class=&quot;wp-image-53730&quot; style=&quot;width:500px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image.png 715w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-300x233.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-50x39.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-52x40.png 52w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-598x464.png 598w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-696x540.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-560x435.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-381x296.png 381w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-608x472.png 608w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-80x62.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-48x37.png 48w&quot; sizes=&quot;auto, (max-width: 715px) 100vw, 715px&quot;&gt;&lt;/figure&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-optional-additional-step-when-pre-mortems-require-a-culture-change&quot;&gt;Optional additional step: When pre-mortems require a culture change&lt;/h4&gt;



&lt;p&gt;In some companies, getting into the pre-mortem mindset can be tricky. When things are busy or deadlines are tight, it’s easy to skip it. Or sometimes, people just feel uncomfortable bringing up the uncomfortable.&lt;/p&gt;



&lt;p&gt;Here, the framework &lt;a href=&quot;https://coda.io/@shreyas/pre-mortems&quot;&gt;Shreyas Doshi suggests&lt;/a&gt; can be really useful. He recommends categorizing risks into three types:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Tiger: &lt;/strong&gt;a real threat — something that will hurt the company if left unaddressed.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Paper tiger: &lt;/strong&gt;a perceived risk/threat that, on closer inspection, is unlikely to cause real problems. These are the things the team might be stressing over, but are actually minor and manageable.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Elephant: &lt;/strong&gt;unsurprisingly, this is ‘the elephant in the room’ — a risk that is present but isn’t being talked about.&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Using this playful, visual language helps build the psychological safety that’s so important for effective pre-mortems. It makes discussions lighter and more approachable, and it gives you a way to raise risks in other settings too. For example: “This might be a paper tiger, but have we considered…?”&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-5-for-each-risk-theme-ask-two-questions&quot;&gt;Step 5: For each risk theme, ask two questions&lt;/h3&gt;



&lt;p&gt;Now that you’ve done some idea spring cleaning, it’s time to assess risk levels and impact:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Certainty assessment: &lt;/strong&gt;how likely is it to happen?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Impact assessment: &lt;/strong&gt;how bad is it if it happens?&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;This helps you map everything onto a simple 2×2 grid, so you don’t get stuck debating unlikely scenarios or low-impact risks. Instead, you can focus your energy on the ones that actually matter.&lt;/p&gt;



&lt;p&gt;Depending on the size of the group and the scope of the project, this might even be a separate session. The goal here isn’t to solve everything yet; it’s to start identifying which risks deserve your attention first.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-6-determine-whether-you-need-to-plan-or-prevent-those-risks&quot;&gt;Step 6: Determine whether you need to plan or prevent those risks&lt;/h3&gt;



&lt;p&gt;Next, focus on those biggest risks and decide whether they’re preventable, plannable, or both:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Prevent: &lt;/strong&gt;can we reduce the likelihood of this happening?&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Plan: &lt;/strong&gt;if it happens anyway, what will we do?&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;If you try to prevent every single risk, nothing will ever go live, so this is where you need to be critical. Ask yourself: Is this something we can realistically mitigate, or is it a risk we need to consciously accept?&lt;/p&gt;



&lt;p&gt;The goal isn’t to eliminate all risk. It’s to understand it and feel prepared for what might happen.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-7-work-out-potential-solutions&quot;&gt;Step 7: Work out potential solutions&lt;/h3&gt;



&lt;p&gt;Now, depending on the complexity of the risk, this might require an extra session — or a few — to properly think through. Don’t get caught trying to solve everything on the spot. Some risks need deeper brainstorming or input from others.&lt;/p&gt;



&lt;p&gt;What &lt;em&gt;does&lt;/em&gt; help is summarizing your plans into simple if/then statements. They’re clear, practical, and bring a sense of calm to the unknown.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;For example:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;If activation is below 10%, we’ll simplify the first-time experience and retest&lt;/li&gt;



&lt;li&gt;If we attract the wrong customers, we’ll adjust our targeting and messaging before scaling spend&lt;/li&gt;



&lt;li&gt;If nobody hits the paywall, we’ll move it earlier and test different copy&lt;/li&gt;



&lt;li&gt;If day 1 churn is above X%, we’ll investigate whether the paywall is creating impulse conversions&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Each of these should be tied to a specific metric you’re already tracking — trial conversion rate, &lt;a href=&quot;https://www.revenuecat.com/blog/growth/activation-metrics/&quot;&gt;activation rate&lt;/a&gt;, churn, and MRR. Set your &lt;a href=&quot;https://www.revenuecat.com/blog/growth/subscription-metrics-mobile-apps/&quot;&gt;trigger thresholds &lt;em&gt;before&lt;/em&gt; launch&lt;/a&gt;, so you’re not debating what ‘bad’ looks like after the fact.&lt;/p&gt;



&lt;p&gt;If you’re running paywall or pricing experiments, &lt;a href=&quot;https://www.revenuecat.com/feature/experiments/&quot;&gt;RevenueCat’s Experiments feature&lt;/a&gt; lets you set up A/B tests and define success metrics before you launch — so you’re not making decisions under pressure.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-8-review-and-revisit&quot;&gt;Step 8: Review and revisit&lt;/h3&gt;



&lt;p&gt;One last thing: don’t let your pre-mortem gather dust in a shared doc like so many other strategy decks. Depending on your timelines, set a few clear check-in points, for example, Day 7, Day 30, and Day 90 post-launch.&lt;/p&gt;



&lt;p&gt;At each one, revisit your if/then statements and ask: are any of these scenarios actually playing out?&amp;nbsp;&lt;/p&gt;



&lt;p&gt;This is where the pre-mortem really earns its keep. The planning is valuable, but the follow-through is what helps you avoid those “we should have seen that coming” moments later on.&lt;/p&gt;



&lt;p&gt;For longer projects, it can even be worth running a second pre-mortem closer to launch; a fresh look, with more context, often surfaces new risks you couldn’t see earlier.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;892&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-1-892x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-53732&quot; style=&quot;width:400px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-1-892x1024.png 892w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-1-261x300.png 261w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-1-768x882.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-1-1338x1536.png 1338w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-1-44x50.png 44w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-1-35x40.png 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-1-404x464.png 404w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-1-696x799.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-1-488x560.png 488w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-1-258x296.png 258w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-1-411x472.png 411w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-1-70x80.png 70w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-1-42x48.png 42w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/image-1.png 1448w&quot; sizes=&quot;auto, (max-width: 892px) 100vw, 892px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-example-subscription-app-pre-mortem&quot;&gt;Example: subscription app pre-mortem&lt;/h2&gt;



&lt;p&gt;Before launching a new subscription tier for a client last year, we ran a quick pre-mortem.&lt;/p&gt;



&lt;p&gt;One of the risks we identified: ‘Existing customers might feel cheated if new customers get a better deal’.&lt;/p&gt;



&lt;p&gt;We couldn’t fully prevent that. The new tier genuinely offered better value, and it needed to. It unlocked a segment of customers we were previously pricing out. But by naming the risk, we could prepare for it:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;We spent more time positioning the existing tier, not just promoting the new one&lt;/li&gt;



&lt;li&gt;We added a relevant feature to the higher tier to reduce cannibalization&lt;/li&gt;



&lt;li&gt;We communicated proactively with existing customers, explaining the new tier and who it was for&lt;/li&gt;



&lt;li&gt;We prepared responses for the support team&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The result? Far fewer complaints than expected, and only a small increase in support tickets (mostly from customers who missed the updates).&lt;/p&gt;



&lt;p&gt;More importantly, the new tier drove growth rather than cannibalizing the existing one, with overall MRR increasing significantly.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-when-to-use-pre-mortems&quot;&gt;When to use pre-mortems&lt;/h2&gt;



&lt;p&gt;Pre-mortems work in a wide range of scenarios:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Launching a new product or SKU&lt;/li&gt;



&lt;li&gt;Changes to subscription models&lt;/li&gt;



&lt;li&gt;Pricing adjustments&lt;/li&gt;



&lt;li&gt;Entering a new market or channel&lt;/li&gt;



&lt;li&gt;Rebrands or major website overhauls&lt;/li&gt;



&lt;li&gt;Paid campaign pushes&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;I even run them with new advisory clients to make sure I can support them effectively and drive real impact.&lt;/p&gt;



&lt;p&gt;Basically, try a pre-mortem anytime failure would hurt, and you want to have thought it through in advance.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-a-pre-mortem-won-t-make-launches-less-scary&quot;&gt;A pre-mortem won’t make launches less scary&lt;/h2&gt;



&lt;p&gt;You’ll probably still refresh dashboards too often and overanalyze early data — I certainly do.&lt;/p&gt;



&lt;p&gt;But the &lt;em&gt;quality&lt;/em&gt; of your anxiety changes. Instead of a vague dread that something &lt;em&gt;might&lt;/em&gt; go wrong, you have a clear list of what &lt;em&gt;could&lt;/em&gt; go wrong, and a plan for each scenario.&lt;/p&gt;



&lt;p&gt;The best launches I’ve been part of weren’t the ones where nothing went wrong. They were the ones where we’d already talked through what we’d do if things did go wrong.&lt;/p&gt;



&lt;p&gt;So before your next &lt;a href=&quot;https://www.revenuecat.com/blog/growth/paywall-tests-grow-app-revenue/&quot;&gt;paywall test&lt;/a&gt;, pricing change, or new tier launch, take 30 minutes with your team. Imagine the worst, write it down, make a plan.&lt;/p&gt;



&lt;p&gt;Then ship it anyway.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[A complete guide to migrating from Google Play Billing v7 to v8 (and preparing for v9)]]></title><description><![CDATA[This article covers the Google Play Billing Library v7 to v8 migration timeline, removed APIs and replacements, updated connection/query/purchase flows, new v8–v8.3 behaviors, and how to prepare for v9.]]></description><link>https://www.revenuecat.com/blog/engineering/play-billing-8-migration/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/play-billing-8-migration/</guid><pubDate>Fri, 08 May 2026 00:41:42 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/Blog_59_Google-Play-Billing-v7-to-v8.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Every Android subscription team lives on the same two year clock. The Play Billing Library you shipped with last year is on a deprecation timer, and the Play Console will refuse new uploads the moment the timer runs out. v7 is the next version to hit that wall. After August 31, 2026, you can no longer publish a new app or update built against v7, and v8 has been generally available since June 30, 2025 with significant additions still arriving in v8.1 through v8.3. This guide walks you through the migration end to end, then sets you up for v9.&lt;/p&gt;



&lt;p&gt;In this article, you’ll explore the v7 to v8 deprecation timeline and what each date actually means, the full list of removed APIs and their replacements, a step by step migration of the connection, query, and purchase flows, the new behaviors v8 adds that are worth adopting today, what v8.1 through v8.3 layer on top, and how to prepare for v9 before Google publishes a single line of its API surface.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-deprecation-timeline-that-sets-your-deadline&quot;&gt;&lt;strong&gt;The deprecation timeline that sets your deadline&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Google has run a two year deprecation cycle for the Play Billing Library across several major versions. Every major version gets two years of support after release, then the Play Console stops accepting new builds compiled against it. The deprecation FAQ publishes the exact dates:&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Library version&lt;/th&gt;&lt;th&gt;Last date for new apps and updates&lt;/th&gt;&lt;th&gt;Extension request deadline&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;5.x&lt;/td&gt;&lt;td&gt;2024-08-31&lt;/td&gt;&lt;td&gt;2024-11-01&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;6.x&lt;/td&gt;&lt;td&gt;2025-08-31&lt;/td&gt;&lt;td&gt;2025-11-01&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;7.x&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;2026-08-31&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;2026-11-01&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;8.x&lt;/td&gt;&lt;td&gt;2027-08-31&lt;/td&gt;&lt;td&gt;2027-11-01&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;The phrasing in the FAQ is precise and worth reading carefully: “This deprecation prevents only new apps and updates from using older versions of the Play Billing Library. Existing apps that use a deprecated version of the library will continue to function as expected.”&lt;/p&gt;



&lt;p&gt;That distinction matters. The deadline is a publishing gate, not a runtime kill switch. Already published v7 binaries keep transacting after August 31, 2026. What stops is your ability to ship a new release. If your app receives any updates at all, including security patches and bug fixes, you need to be on v8 before that gate closes. The extension request deadline of November 1, 2026 is for teams that need to file a formal request through the Play Console to keep shipping v7 builds for a brief additional window. It is not a free extension you receive automatically.&lt;/p&gt;



&lt;p&gt;The Play Console signals this through a warning and an inbox message on the Policy status page once your app is on a deprecated version. If your&amp;nbsp;&lt;code&gt;AndroidManifest.xml&lt;/code&gt;&amp;nbsp;does not contain the entry named&amp;nbsp;&lt;code&gt;com.google.android.play.billingclient.version&lt;/code&gt;, the Play Console cannot detect your library version, and the warning never reaches you. That entry is added automatically by the library, but manifest merging in multi module projects sometimes drops it. Verify it exists in your final merged manifest before you trust the absence of warnings.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-changed-in-v8-the-removals-at-a-glance&quot;&gt;&lt;strong&gt;What changed in v8: the removals at a glance&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;v8 removed several APIs that had been deprecated for one or two prior versions. If your code still uses any of these, the v8 upgrade will fail to compile until you replace them.&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Removed API&lt;/th&gt;&lt;th&gt;Replacement&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;querySkuDetailsAsync()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;queryProductDetailsAsync(QueryProductDetailsParams, ProductDetailsResponseListener)&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;queryPurchaseHistoryAsync()&lt;/code&gt;&amp;nbsp;(all overloads)&lt;/td&gt;&lt;td&gt;No direct client API. Track history server side.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;enablePendingPurchases()&lt;/code&gt;&amp;nbsp;(no arg)&lt;/td&gt;&lt;td&gt;&lt;code&gt;enablePendingPurchases(PendingPurchasesParams)&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;queryPurchasesAsync(String skuType, PurchasesResponseListener)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;queryPurchasesAsync(QueryPurchasesParams, PurchasesResponseListener)&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;BillingClient.Builder.enableAlternativeBilling()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;enableUserChoiceBilling(UserChoiceBillingListener)&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;AlternativeBillingListener&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;UserChoiceBillingListener&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;AlternativeChoiceDetails&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;UserChoiceDetails&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;The signature of&amp;nbsp;&lt;code&gt;ProductDetailsResponseListener.onProductDetailsResponse()&lt;/code&gt;&amp;nbsp;also changed. The callback now returns a&amp;nbsp;&lt;code&gt;QueryProductDetailsResult&lt;/code&gt;&amp;nbsp;that splits the response into a fetched list and an unfetched list with per product status codes, replacing the older single list signature. Any class that implements this listener has to be updated, even if the rest of its logic is unchanged.&lt;/p&gt;



&lt;p&gt;Two terminology changes accompany the API removals. “In app items” are now called “one time products” throughout the documentation and the API surface. The class names themselves did not change, the documentation simply uses the new term, but the rename carries a behavioral implication: one time products in v8 can have multiple purchase options and offers, the same way subscriptions did in v7.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-1-bump-the-dependency-and-your-minsdk&quot;&gt;&lt;strong&gt;Step 1: Bump the dependency and your minSdk&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The first change is the Gradle coordinate. v8.0.0 was the first release in the v8 line, but most teams should target the latest patch in the v8 series instead of pinning to 8.0.0:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ls1Nw wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;dependencies {\n    val billingVersion = \&amp;quot;8.3.0\&amp;quot;\n    implementation(\&amp;quot;com.android.billingclient:billing:$billingVersion\&amp;quot;)\n    implementation(\&amp;quot;com.android.billingclient:billing-ktx:$billingVersion\&amp;quot;)\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The library raised its&amp;nbsp;&lt;code&gt;minSdkVersion&lt;/code&gt;&amp;nbsp;to 23 starting at v8.1.0. If your app still supports API 21 or 22, you have two choices: pin to 8.0.0, which keeps the original v7 minSdk of 21, or raise your own minSdk to 23 and adopt the latest v8 patch. The latter is the right call for almost every team, since API 23 was released in 2015 and the device tail below it has been negligible for years. v8.1 is also built against Kotlin 2.2.0, which can affect projects on older Kotlin versions if you consume the&amp;nbsp;&lt;code&gt;billing-ktx&lt;/code&gt;&amp;nbsp;artifact, though this is a small jump for any project already on a recent Kotlin Compose stack.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;step-2-migrate-enablependingpurchases&quot;&gt;&lt;strong&gt;Step 2: Migrate enablePendingPurchases&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The no argument&amp;nbsp;&lt;code&gt;enablePendingPurchases()&lt;/code&gt;&amp;nbsp;was deprecated in v7 and removed in v8. It used to be a single method that turned on pending purchase support for in app items implicitly. v8 replaces it with a builder that forces you to declare which product categories you want pending support for.&lt;/p&gt;



&lt;p&gt;In v7, you had:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZMe0YG wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;val billingClient = BillingClient.newBuilder(context)\n    .setListener(purchasesUpdatedListener)\n    .enablePendingPurchases()\n    .build()&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;In v8, the equivalent call is:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z2hlc8n wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;val pendingPurchasesParams = PendingPurchasesParams.newBuilder()\n    .enableOneTimeProducts()\n    .build()\n\nval billingClient = BillingClient.newBuilder(context)\n    .setListener(purchasesUpdatedListener)\n    .enablePendingPurchases(pendingPurchasesParams)\n    .build()&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Notice that&amp;nbsp;&lt;code&gt;.enableOneTimeProducts()&lt;/code&gt;&amp;nbsp;is not implicit. The deprecated zero argument version was, by Google’s own description, equivalent to a builder with&amp;nbsp;&lt;code&gt;.enableOneTimeProducts()&lt;/code&gt;&amp;nbsp;set, so if you do not include this call you will silently lose pending purchase support for one time products. That regression is invisible in unit tests and in most countries with credit card based purchase flows. It surfaces as broken purchases in markets where users pay with cash at convenience stores or with bank transfers, primarily Japan, Germany, Brazil, Mexico, and Indonesia. Add&amp;nbsp;&lt;code&gt;.enableOneTimeProducts()&lt;/code&gt;&amp;nbsp;even if you think you do not need it.&lt;/p&gt;



&lt;p&gt;If you sell prepaid subscription top ups, also add&amp;nbsp;&lt;code&gt;.enablePrepaidPlans()&lt;/code&gt;&amp;nbsp;to the builder. This was added in v7 specifically for prepaid plan pending transactions and carries over into v8 unchanged.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;step-3-update-queryproductdetailsasync-to-the-new-callback-shape&quot;&gt;&lt;strong&gt;Step 3: Update queryProductDetailsAsync to the new callback shape&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;&lt;code&gt;queryProductDetailsAsync&lt;/code&gt;&amp;nbsp;itself is not removed, but its callback was. The pre v8 listener received a&amp;nbsp;&lt;code&gt;BillingResult&lt;/code&gt;&amp;nbsp;and a&amp;nbsp;&lt;code&gt;List&amp;lt;ProductDetails&amp;gt;&lt;/code&gt;. The v8 listener receives a&amp;nbsp;&lt;code&gt;BillingResult&lt;/code&gt;&amp;nbsp;and a&amp;nbsp;&lt;code&gt;QueryProductDetailsResult&lt;/code&gt;&amp;nbsp;that splits products into two lists. Any product that failed to fetch shows up in the unfetched list with its own status code, instead of being silently dropped.&lt;/p&gt;



&lt;p&gt;The pre v8 callback looked like this:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1AShJp wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;billingClient.queryProductDetailsAsync(params) { billingResult, productDetailsList -&gt;\n    if (billingResult.responseCode == BillingResponseCode.OK) {\n        productDetailsList.forEach { details -&gt;\n            renderProduct(details)\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The v8 version exposes both the successful fetches and the failures:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1eMd88 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;billingClient.queryProductDetailsAsync(params) { billingResult, queryProductDetailsResult -&gt;\n    if (billingResult.responseCode == BillingResponseCode.OK) {\n        queryProductDetailsResult.productDetailsList.forEach { details -&gt;\n            renderProduct(details)\n        }\n        queryProductDetailsResult.unfetchedProductList.forEach { unfetched -&gt;\n            logUnfetched(unfetched.productId, unfetched.statusCode)\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The reason this matters is that pre v8, if you queried five products and one of them was misconfigured in the Play Console, the whole call could return successfully with that product silently missing from the list. Your paywall would render four products and you would have no idea the fifth was even attempted. The new shape makes the partial failure explicit. Each unfetched entry carries a status code that tells you whether the product is unavailable in the user’s country, has not yet been published, or hit a transient error.&lt;/p&gt;



&lt;p&gt;This is also the moment to rebuild any abstraction layer that wraps&amp;nbsp;&lt;code&gt;queryProductDetailsAsync&lt;/code&gt;&amp;nbsp;in a coroutine or flow. The return type of your suspending wrapper has to change from&amp;nbsp;&lt;code&gt;List&amp;lt;ProductDetails&amp;gt;&lt;/code&gt;&amp;nbsp;to a sealed class or pair that carries the unfetched information forward. If you have a typealias for the listener type itself, the typealias has to be updated, since the lambda signature is different.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;step-4-replace-the-deprecated-querypurchasesasync-overload&quot;&gt;&lt;strong&gt;Step 4: Replace the deprecated queryPurchasesAsync overload&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;v8 removed the overload of&amp;nbsp;&lt;code&gt;queryPurchasesAsync&lt;/code&gt;&amp;nbsp;that took a raw SKU type string. The replacement uses a&amp;nbsp;&lt;code&gt;QueryPurchasesParams&lt;/code&gt;&amp;nbsp;builder that wraps the same product type with the new typed enum.&lt;/p&gt;



&lt;p&gt;Before:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1gkkLt wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;billingClient.queryPurchasesAsync(BillingClient.SkuType.SUBS) { result, purchases -&gt;\n    handlePurchases(result, purchases)\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;After:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-KE6e2 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;val params = QueryPurchasesParams.newBuilder()\n    .setProductType(BillingClient.ProductType.SUBS)\n    .build()\n\nbillingClient.queryPurchasesAsync(params) { result, purchases -&gt;\n    handlePurchases(result, purchases)\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The behavior is identical when invoked correctly. The&amp;nbsp;&lt;code&gt;SkuType&lt;/code&gt;&amp;nbsp;constants are gone, replaced by&amp;nbsp;&lt;code&gt;ProductType.SUBS&lt;/code&gt;&amp;nbsp;and&amp;nbsp;&lt;code&gt;ProductType.INAPP&lt;/code&gt;. If you have a single shared method that accepts a string for the SKU type, refactor it to accept a&amp;nbsp;&lt;code&gt;String&lt;/code&gt;&amp;nbsp;that matches the new enum values, or convert it to use&amp;nbsp;&lt;code&gt;BillingClient.ProductType&lt;/code&gt;&amp;nbsp;directly.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;step-5-querypurchasehistoryasync-has-no-client-side-replacement&quot;&gt;&lt;strong&gt;Step 5: queryPurchaseHistoryAsync has no client side replacement&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;&lt;code&gt;queryPurchaseHistoryAsync&lt;/code&gt;&amp;nbsp;was deprecated in v7 and fully removed in v8. There is no equivalent client API. This is the only v8 removal that does not have a direct one to one replacement, and it tends to surprise teams the most.&lt;/p&gt;



&lt;p&gt;Google’s reasoning is straightforward, even if undocumented in the migration page itself: purchase history is not authoritative source of truth on the client. Any history a client builds up can be incomplete, since the device may have been offline during a refund or revocation. The Play Developer API on your server has the authoritative record, and any analytics, audit, or reconciliation flow that depends on knowing past purchases should query it server side instead.&lt;/p&gt;



&lt;p&gt;If you previously used&amp;nbsp;&lt;code&gt;queryPurchaseHistoryAsync&lt;/code&gt;&amp;nbsp;for one of these reasons, you now have two paths. The first is to call the Play Developer API endpoint&amp;nbsp;&lt;code&gt;purchases.subscriptionsv2.get&lt;/code&gt;&amp;nbsp;from your backend whenever you need to inspect a subscription’s full history, including its&amp;nbsp;&lt;code&gt;linkedPurchaseToken&lt;/code&gt;&amp;nbsp;chain. The second is to lean on Real Time Developer Notifications and persist the events as they arrive, building your own purchase history table. Most teams already do the latter for analytics and revenue reporting, in which case the v8 removal is a no op.&lt;/p&gt;



&lt;p&gt;If you used&amp;nbsp;&lt;code&gt;queryPurchaseHistoryAsync&lt;/code&gt;&amp;nbsp;for entitlement restoration on a fresh install or after a reinstall, switch to&amp;nbsp;&lt;code&gt;queryPurchasesAsync&lt;/code&gt;&amp;nbsp;with the new params builder.&amp;nbsp;&lt;code&gt;queryPurchasesAsync&lt;/code&gt;&amp;nbsp;returns active purchases tied to the current Google account, which is what restoration actually needs. Active purchases is a smaller set than full history, but it is the correct set for entitlement granting. Note that v8 also stops returning consumed one time products and expired subscriptions from&amp;nbsp;&lt;code&gt;queryPurchasesAsync&lt;/code&gt;, so configure your one time products as non consumable in the Play Console if you need them to survive a reinstall.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;step-6-move-from-alternative-billing-to-user-choice-billing&quot;&gt;&lt;strong&gt;Step 6: Move from alternative billing to user choice billing&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;v7 already deprecated the&amp;nbsp;&lt;code&gt;enableAlternativeBilling&lt;/code&gt;&amp;nbsp;builder method, and v8 removed it entirely. The replacement is&amp;nbsp;&lt;code&gt;enableUserChoiceBilling&lt;/code&gt;, which takes a&amp;nbsp;&lt;code&gt;UserChoiceBillingListener&lt;/code&gt;&amp;nbsp;instead of an&amp;nbsp;&lt;code&gt;AlternativeBillingListener&lt;/code&gt;&amp;nbsp;and exposes a&amp;nbsp;&lt;code&gt;UserChoiceDetails&lt;/code&gt;&amp;nbsp;payload instead of&amp;nbsp;&lt;code&gt;AlternativeChoiceDetails&lt;/code&gt;.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1zI6hQ wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;val billingClient = BillingClient.newBuilder(context)\n    .setListener(purchasesUpdatedListener)\n    .enableUserChoiceBilling { userChoiceDetails -&gt;\n        recordExternalSelection(userChoiceDetails)\n    }\n    .enablePendingPurchases(pendingPurchasesParams)\n    .build()&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The functional contract is the same: when the user picks your billing system over Google Play’s at checkout, the listener fires with the purchase details so your backend can complete the transaction outside of Google Play’s payment flow. Only the type names changed. If you carry a per region build flavor where user choice billing is enabled in some regions and disabled in others, the build flavor logic does not need to change, only the type references.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;one-time-products-and-the-multi-offer-surface&quot;&gt;&lt;strong&gt;One time products and the multi offer surface&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;v8 renamed in app items to one time products and gave them the same multi offer capability subscriptions had since v5. A single one time product can now carry multiple purchase options, each with its own price, regional availability, and offers attached. This is the change that motivates the bulk of v8’s surface, and it is also the reason the unfetched product list now exists. With multiple offers per product, the partial failure modes multiplied, and a flat list could no longer represent what happened.&lt;/p&gt;



&lt;p&gt;The class names did not change.&amp;nbsp;&lt;code&gt;ProductDetails&lt;/code&gt;&amp;nbsp;is still&amp;nbsp;&lt;code&gt;ProductDetails&lt;/code&gt;. What changed is the&amp;nbsp;&lt;code&gt;oneTimePurchaseOfferDetails&lt;/code&gt;&amp;nbsp;accessor, which can now expose multiple offers and pre-order details starting at v8.1.0. If your paywall renders a single price for an in app item, you are still on the v7 mental model. v8 lets you expose a discounted offer or a regional offer on the same product without creating a duplicate SKU. This is opt in: existing one time products continue to surface a single offer until you configure additional options in the Play Console.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;new-behaviors-worth-adopting-in-v8&quot;&gt;&lt;strong&gt;New behaviors worth adopting in v8&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Two of v8’s additions are not strictly required but are worth turning on at migration time, since they reduce code you would otherwise carry yourself.&lt;/p&gt;



&lt;p&gt;The first is&amp;nbsp;&lt;code&gt;enableAutoServiceReconnection()&lt;/code&gt;. The Play Billing service can disconnect for a number of reasons: the user installs an update to Google Play, the device wakes from a long sleep, the system reclaims the bound service. Pre v8, you had to implement&amp;nbsp;&lt;code&gt;onBillingServiceDisconnected()&lt;/code&gt;&amp;nbsp;and call&amp;nbsp;&lt;code&gt;startConnection()&lt;/code&gt;&amp;nbsp;again with appropriate backoff. v8 ships an opt in builder method that handles this for you:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-kXKPW wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;val billingClient = BillingClient.newBuilder(context)\n    .setListener(purchasesUpdatedListener)\n    .enablePendingPurchases(pendingPurchasesParams)\n    .enableAutoServiceReconnection()\n    .build()&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;When auto reconnection is enabled, your&amp;nbsp;&lt;code&gt;onBillingServiceDisconnected()&lt;/code&gt;&amp;nbsp;override can be a no op, and the library handles retry with backoff internally. Auto reconnection is opt in rather than the default. If you want to manage connection lifecycle yourself, leave it disabled and continue handling&amp;nbsp;&lt;code&gt;onBillingServiceDisconnected()&lt;/code&gt;&amp;nbsp;directly.&lt;/p&gt;



&lt;p&gt;The second addition is&amp;nbsp;&lt;code&gt;BillingResult.subResponseCode&lt;/code&gt;. Pre v8, the&amp;nbsp;&lt;code&gt;BillingResult&lt;/code&gt;&amp;nbsp;returned for purchase failures grouped many cases under&amp;nbsp;&lt;code&gt;BILLING_UNAVAILABLE&lt;/code&gt;&amp;nbsp;or&amp;nbsp;&lt;code&gt;ERROR&lt;/code&gt;. v8 adds a sub response code on&amp;nbsp;&lt;code&gt;BillingResult&lt;/code&gt;&amp;nbsp;that distinguishes specific failure cases:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;code&gt;PAYMENT_DECLINED_DUE_TO_INSUFFICIENT_FUNDS&lt;/code&gt;: the user’s payment method does not have sufficient funds.&lt;/li&gt;



&lt;li&gt;&lt;code&gt;USER_INELIGIBLE&lt;/code&gt;: the user is not eligible for the offer they tried to redeem, typically because they have already used a one time intro offer.&lt;/li&gt;



&lt;li&gt;&lt;code&gt;NO_APPLICABLE_SUB_RESPONSE_CODE&lt;/code&gt;: the failure does not map to a more specific sub code.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The ineligibility code is the one you almost certainly want to handle, because it lets you steer the user back to a fallback offer instead of leaving them at a failed purchase screen. The sub code arrives in the&amp;nbsp;&lt;code&gt;BillingResult&lt;/code&gt;&amp;nbsp;delivered to your&amp;nbsp;&lt;code&gt;PurchasesUpdatedListener.onPurchasesUpdated&lt;/code&gt;&amp;nbsp;callback:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z168mCW wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;override fun onPurchasesUpdated(result: BillingResult, purchases: List&lt;Purchase&gt;?) {\n    if (result.responseCode == BillingResponseCode.ITEM_UNAVAILABLE) {\n        when (result.subResponseCode) {\n            SubResponseCode.USER_INELIGIBLE -&gt; showFallbackOffer()\n            SubResponseCode.PAYMENT_DECLINED_DUE_TO_INSUFFICIENT_FUNDS -&gt; showFundsError()\n            else -&gt; showGenericError()\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;what-v81-v82-and-v83-add-on-top&quot;&gt;&lt;strong&gt;What v8.1, v8.2, and v8.3 add on top&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;v8 has been moving fast since GA. Three minor releases between November and December 2025 added significant capabilities that are easy to miss if you only read the v8.0 migration guide.&lt;/p&gt;



&lt;p&gt;v8.1.0, released November 6, 2025, introduced suspended subscription handling. A subscription enters the suspended state when Google detects abuse or a payment dispute and pauses delivery of entitlements without canceling the subscription. Pre v8.1, suspended subscriptions were invisible to client side queries. v8.1 adds an&amp;nbsp;&lt;code&gt;isSuspended&lt;/code&gt;&amp;nbsp;flag on&amp;nbsp;&lt;code&gt;Purchase&lt;/code&gt;&amp;nbsp;and a parameter to&amp;nbsp;&lt;code&gt;queryPurchasesAsync&lt;/code&gt;&amp;nbsp;to include suspended purchases in the result. The pattern is to filter purchases by&amp;nbsp;&lt;code&gt;isSuspended&lt;/code&gt;&amp;nbsp;before granting entitlement, and route suspended ones into a separate UI branch that explains the hold to the user:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Zfzk4W wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;val params = QueryPurchasesParams.newBuilder()\n    .setProductType(BillingClient.ProductType.SUBS)\n    .build()\n\nbillingClient.queryPurchasesAsync(params) { result, purchases -&gt;\n    purchases.forEach { purchase -&gt;\n        if (purchase.isSuspended) {\n            showSuspendedState()\n        } else if (purchase.purchaseState == Purchase.PurchaseState.PURCHASED) {\n            grantEntitlement(purchase)\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;v8.1 also reworks subscription replacement. The old&amp;nbsp;&lt;code&gt;SubscriptionUpdateParams.setSubscriptionReplacementMode()&lt;/code&gt;&amp;nbsp;is now deprecated in favor of&amp;nbsp;&lt;code&gt;SubscriptionProductReplacementParams&lt;/code&gt;&amp;nbsp;set on the per product builder. The new shape supports a&amp;nbsp;&lt;code&gt;KEEP_EXISTING&lt;/code&gt;&amp;nbsp;replacement mode that lets you upsell a second subscription on the same account without canceling the existing one, which is useful for bundled offerings.&lt;/p&gt;



&lt;p&gt;v8.2.0 and v8.2.1, released in December 2025, generalize what used to be the External Offers Program into a broader Billing Program surface. The old methods (&lt;code&gt;enableExternalOffer&lt;/code&gt;,&amp;nbsp;&lt;code&gt;isExternalOfferAvailableAsync&lt;/code&gt;,&amp;nbsp;&lt;code&gt;createExternalOfferReportingDetailsAsync&lt;/code&gt;,&amp;nbsp;&lt;code&gt;showExternalOfferInformationDialog&lt;/code&gt;) are deprecated and replaced by&amp;nbsp;&lt;code&gt;enableBillingProgram(int)&lt;/code&gt;,&amp;nbsp;&lt;code&gt;isBillingProgramAvailableAsync&lt;/code&gt;,&amp;nbsp;&lt;code&gt;createBillingProgramReportingDetailsAsync&lt;/code&gt;, and&amp;nbsp;&lt;code&gt;launchExternalLink&lt;/code&gt;. v8.3.0, shipped December 23, 2025, adds the developer provided billing flow on top, with&amp;nbsp;&lt;code&gt;BillingProgram.EXTERNAL_PAYMENTS&lt;/code&gt;,&amp;nbsp;&lt;code&gt;EnableBillingProgramParams&lt;/code&gt;, and&amp;nbsp;&lt;code&gt;DeveloperBillingOptionParams&lt;/code&gt;. This consolidation is Google’s response to the regulatory pressure that emerged from the Epic Games ruling and similar requirements in other jurisdictions, where Google is required to support developer provided billing and out of app payment links.&lt;/p&gt;



&lt;p&gt;If your app uses the External Offers Program today, the deprecation is a clear signal to start migrating. The methods still work in v8.2 and v8.3, but they will likely be removed in v9. Migrating to the Billing Program surface now is a one time cost that buys you out of a forced migration later.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;preparing-for-v9-before-its-api-surface-exists&quot;&gt;&lt;strong&gt;Preparing for v9 before its API surface exists&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;At the moment, the release notes top out at v8.3.0. The deprecation FAQ does not list a v9 row. There is no public alpha, beta, or release candidate. So how do you prepare?&lt;/p&gt;



&lt;p&gt;By understanding the cadence and the direction of change. Google has shipped a new major version of the Play Billing Library roughly once a year, with v7 released in May 2024 and v8 reaching GA on June 30, 2025. On that pattern, v9 is expected to land in mid 2027, lining up with the v8 sunset deadline of August 31, 2027.&lt;/p&gt;



&lt;p&gt;The direction of change is also predictable from the rapid v8.1 through v8.3 releases. Google is consolidating the external billing surface (External Offers Program, user choice billing, developer provided billing) into a unified Billing Programs API. v9 is likely to remove the deprecated External Offers methods, formalize the Billing Programs surface, and possibly extend it further to handle additional regulatory regimes.&lt;/p&gt;



&lt;p&gt;Three things you can do today to be ready:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Opt in early&lt;/strong&gt;: adopt every opt in API v8 ships, including&amp;nbsp;&lt;code&gt;enableAutoServiceReconnection()&lt;/code&gt;&amp;nbsp;and the new&amp;nbsp;&lt;code&gt;SubscriptionProductReplacementParams&lt;/code&gt;. The opt in surface in one major version is the default surface in the next.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Migrate off External Offers&lt;/strong&gt;: the Billing Programs surface in v8.2 and v8.3 is the forward path, and it gives you a non breaking migration window before v9 forces it.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Move history server side&lt;/strong&gt;: v8 removed&amp;nbsp;&lt;code&gt;queryPurchaseHistoryAsync&lt;/code&gt;&amp;nbsp;for a reason, and v9 will not reintroduce it. Build your purchase audit trail server side from RTDN events and the Play Developer API.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;If you do these three things in your v8 migration, the v9 migration in mid 2027 becomes incremental rather than disruptive.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;how-revenuecat-absorbs-the-v7-to-v8-transition&quot;&gt;&lt;strong&gt;How RevenueCat absorbs the v7 to v8 transition&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The recurring nature of Play Billing Library migrations is the kind of work that taxes a small team disproportionately. Every two years, someone has to read the migration guide, refactor the connection layer, retest pending purchases in cash payment markets, audit the&amp;nbsp;&lt;code&gt;queryPurchaseHistoryAsync&lt;/code&gt;&amp;nbsp;removal, and verify that no listener signature change broke a downstream module. The work is rarely interesting, and it always lands on the team that least wants to do it.&lt;/p&gt;



&lt;p&gt;RevenueCat absorbs this migration on your behalf. The RevenueCat Android SDK 9.x ships with Play Billing Library 8 already integrated, and the SDK API surface most apps interact with did not change between RC SDK 8.x and 9.x. The only meaningful changes for app code are a Kotlin minimum of 1.8.0 and the removal of&amp;nbsp;&lt;code&gt;data class&lt;/code&gt;&amp;nbsp;modifiers from a handful of public types, which means&amp;nbsp;&lt;code&gt;copy()&lt;/code&gt;&amp;nbsp;and component destructuring no longer work on those types.&amp;nbsp;&lt;code&gt;equals()&lt;/code&gt;&amp;nbsp;and&amp;nbsp;&lt;code&gt;hashCode()&lt;/code&gt;&amp;nbsp;are preserved. The migration path is documented in the&amp;nbsp;&lt;a href=&quot;https://www.revenuecat.com/docs/sdk-guides/android-native-8x-to-9x-migration&quot;&gt;RevenueCat 8.x to 9.x Android migration guide&lt;/a&gt;, and the rationale and feature set are walked through in the&amp;nbsp;&lt;a href=&quot;https://www.revenuecat.com/blog/engineering/google-play-billing-v8/&quot;&gt;Play Billing Library 8 support in Purchases SDK v9.0.0&lt;/a&gt;&amp;nbsp;engineering post.&lt;/p&gt;



&lt;p&gt;The practical implication is that the v7 to v8 migration steps in this article reduce to: bump your RevenueCat SDK from 8.x to 9.x, bump your Kotlin to 1.8 or later, replace any&amp;nbsp;&lt;code&gt;copy()&lt;/code&gt;&amp;nbsp;or destructuring on the affected RC types with explicit constructors, and verify your one time products are configured as non consumables in the RevenueCat dashboard (since v8 cannot query consumed one time products). That is the entire migration. The v8 specific work, including the new&amp;nbsp;&lt;code&gt;PendingPurchasesParams&lt;/code&gt;&amp;nbsp;builder, the&amp;nbsp;&lt;code&gt;queryProductDetailsAsync&lt;/code&gt;&amp;nbsp;callback shape, the&amp;nbsp;&lt;code&gt;queryPurchasesAsync&lt;/code&gt;&amp;nbsp;overload swap, the user choice billing rename, and the unfetched product handling, is already done inside the SDK.&lt;/p&gt;



&lt;p&gt;The same property holds for v9. When v9 ships, RevenueCat will release a new SDK that integrates it, and your app code moves forward with the same pattern: bump the SDK, possibly bump your Kotlin or minSdk, and run your test suite. The recurring Play Billing Library migration stops being something your team has to schedule.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;conclusion&quot;&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;In this article, you’ve explored the full v7 to v8 migration: the deprecation timeline that sets your August 31, 2026 deadline, the removed APIs and their replacements, the six concrete migration steps from Gradle bump through user choice billing, the new behaviors v8 ships with&amp;nbsp;&lt;code&gt;enableAutoServiceReconnection&lt;/code&gt;&amp;nbsp;and&amp;nbsp;&lt;code&gt;BillingResult.subResponseCode&lt;/code&gt;, the three minor releases that added suspended subscriptions and the unified Billing Programs surface, and a pattern based read on what v9 will likely require.&lt;/p&gt;



&lt;p&gt;Understanding the structural reasons behind each removal helps you make better decisions during the migration itself.&amp;nbsp;&lt;code&gt;queryPurchaseHistoryAsync&lt;/code&gt;&amp;nbsp;is gone because purchase history was never authoritative on the client. The new&amp;nbsp;&lt;code&gt;enablePendingPurchases&lt;/code&gt;&amp;nbsp;builder is explicit because the implicit version silently regressed cash payment flows in some markets. The unfetched product list exists because partial failures had to become visible once one time products gained multiple offers. Each change reflects a problem the prior surface failed to handle, and the v9 changes will follow the same logic.&lt;/p&gt;



&lt;p&gt;Whether you’re migrating to v8 this quarter, planning the v9 transition for 2027, or evaluating whether to outsource billing infrastructure to a platform like RevenueCat, this foundation lets you ship Android subscriptions without losing weeks every two years to a forced upgrade. For the official source material, refer to Google’s&amp;nbsp;&lt;a href=&quot;https://developer.android.com/google/play/billing/migrate-gpblv8&quot;&gt;migrating to Play Billing Library 8&lt;/a&gt;&amp;nbsp;page, the&amp;nbsp;&lt;a href=&quot;https://developer.android.com/google/play/billing/deprecation-faq&quot;&gt;deprecation FAQ&lt;/a&gt;, and the&amp;nbsp;&lt;a href=&quot;https://developer.android.com/google/play/billing/release-notes&quot;&gt;release notes&lt;/a&gt;.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Meet Rico: Your tireless app growth advisor]]></title><description><![CDATA[Ask Rico what changed, what it means, and what to do next, right from RevenueCat or Slack.]]></description><link>https://www.revenuecat.com/blog/company/rico-app-growth-advisor/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/company/rico-app-growth-advisor/</guid><pubDate>Wed, 06 May 2026 16:35:37 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/Blog-57_Meet-Rico_-Your-tireless-app-growth-advisor.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;You’ve got the charts. You’ve got the cohorts. You’ve got the experiment results. But somewhere between the data and your next decision, there’s a question you’re not sure how to answer.&lt;/p&gt;



&lt;p&gt;Meet Rico, RevenueCat’s app growth advisor built directly into your RevenueCat dashboard and available in Slack. Ask why conversions dropped, which experiment to run, or how your churn rate compares to similar apps. Rico turns your RevenueCat data into your next move.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-an-advisor-not-a-search-bar&quot;&gt;An advisor, not a search bar&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;731&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/Group-2147228078-1024x731.png&quot; alt=&quot;&quot; class=&quot;wp-image-53693&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/Group-2147228078-1024x731.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/Group-2147228078-300x214.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/Group-2147228078-768x548.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/Group-2147228078-1536x1096.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/Group-2147228078-50x36.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/Group-2147228078-56x40.png 56w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/Group-2147228078-650x464.png 650w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/Group-2147228078-696x497.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/Group-2147228078-560x400.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/Group-2147228078-415x296.png 415w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/Group-2147228078-661x472.png 661w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/Group-2147228078-80x57.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/Group-2147228078-48x34.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/Group-2147228078.png 1859w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Rico is an embedded domain expert with access to your RevenueCat data, the App Store and Google Play Billing Library documentation, and the industry-wide State of Subscription Apps (SOSA) benchmarks.&lt;/p&gt;



&lt;p&gt;Not only can you ask Rico straightforward questions like “show me MRR by country” or “compare this month’s performance vs last month,” you can ask Rico real, business-outcome questions:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;em&gt;“Where am I leaving money on the table in the trial-to-paid flow?”&lt;/em&gt;&lt;/li&gt;



&lt;li&gt;&lt;em&gt;“Based on the A/B test, should we do a 0 vs 7-day trial next?”&lt;/em&gt;&lt;/li&gt;



&lt;li&gt;&lt;em&gt;“What is the average conversion to paying for a fitness app?”&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-what-rico-can-do-for-you&quot;&gt;What Rico can do for you&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1015&quot; height=&quot;860&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/custom-link-animation-2-2.png&quot; alt=&quot;&quot; class=&quot;wp-image-53695&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/custom-link-animation-2-2.png 1015w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/custom-link-animation-2-2-300x254.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/custom-link-animation-2-2-768x651.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/custom-link-animation-2-2-50x42.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/custom-link-animation-2-2-47x40.png 47w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/custom-link-animation-2-2-548x464.png 548w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/custom-link-animation-2-2-696x590.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/custom-link-animation-2-2-560x474.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/custom-link-animation-2-2-349x296.png 349w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/custom-link-animation-2-2-557x472.png 557w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/custom-link-animation-2-2-80x68.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/custom-link-animation-2-2-48x41.png 48w&quot; sizes=&quot;auto, (max-width: 1015px) 100vw, 1015px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Rico’s capabilities span across data analysis, technical debugging, and growth strategy. Here is what your new advisor can do:&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Diagnose revenue and retention&lt;/strong&gt;&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“Why did MRR drop in Germany last week?”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Rico can pull your overview metrics, fetch chart data with complex filters, and compare periods to spot anomalies. If revenue drops, Rico can surface exactly which cohort, country, or product is driving the change.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Review product and entitlement setups&lt;/strong&gt;&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“Is my annual product configured correctly in the App Store?”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;App Store and Google Play configurations are notoriously easy to get wrong. Rico can review your products, entitlements, offerings, and packages to verify that everything is attached correctly and properly configured in the stores.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Analyze experiments and strategy&lt;/strong&gt;&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“Based on the A/B test, should we do a 0 vs 7-day trial next?”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Rico lists your A/B test results and helps you interpret the winners and losers. It can provide paywall and pricing strategy recommendations, trial optimization advice, and retention analysis.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Benchmark against the industry&lt;/strong&gt;&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“How does my app’s trial conversion compare to similar apps in my category?”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Rico has a dedicated benchmarks tool that compares your project’s actual metrics against industry peers. Ask how your trial conversion, churn rate, or MRR growth stacks up against apps in your category. Rico surfaces where you’re ahead, where you’re behind, and what to test next, using data from the SOSA reports.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Deep-dive into customers&lt;/strong&gt;&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“Look up user abc123: they say they paid but don’t have access.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;When a user writes in with a billing issue, give Rico their app user ID. Rico pulls their full profile: active entitlements, subscription status, purchase history, and any custom attributes your app has set.&lt;/p&gt;



&lt;p&gt;Then Rico tells you what it sees. Is the subscription in billing retry? Did they cancel but still have access? Have they been refunded before? Are they enrolled in an experiment that might explain unexpected behavior? For most support tickets, that’s enough to diagnose the issue and respond with confidence.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Research documentation and SDKs&lt;/strong&gt;&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“How do I implement a custom paywall in React Native?”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Rico has full access to the RevenueCat docs and all open-source SDK repositories across iOS, Android, Flutter, React Native, Unity, KMP, and JS. Ask about an implementation detail and Rico finds the exact code snippet or proven approach. Ask about a recent SDK release and Rico pulls the changelog. If something seems broken, Rico can check the live status of RevenueCat’s API.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Learn from the best in the industry&lt;/strong&gt;&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“What do high-retention apps do differently in their first 30 days?”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Rico can search the RevenueCat blog and pull insights from the SubClub podcast. Hundreds of conversations with the founders and operators who have built the most successful subscription apps. Ask Rico what high-retention apps do differently, how apps in your category structure their trial strategy, or what operators have figured out about reducing involuntary churn.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Project and team management&lt;/strong&gt;&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“Who changed the annual product entitlement yesterday?”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Rico can list your apps, API keys, and collaborators, and pull your project’s audit log. Every entry records who made a change, what they changed, and when. That covers everything from product and entitlement config to experiment activity, webhook updates, and collaborator role changes.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Feature adoption audit&lt;/strong&gt;&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“Which RevenueCat features am I not using that I should be?”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Ask Rico to run a feature adoption audit on your project. It checks every RevenueCat feature against your actual usage data and returns three things: what you’re actively using, what’s gone dormant, and what you’ve never tried.&lt;/p&gt;



&lt;p&gt;Rico might flag that your Refund Handling integration stopped flowing data three months ago, meaning Apple has been approving refunds without your input. Or it might notice you’re running Customer Center but haven’t enabled the Retention Messaging API, which gives you a second chance to retain users when they try to cancel in the App Store.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;App and competitor research&lt;/strong&gt;&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“What’s Duolingo’s monetization strategy?”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Give Rico any app’s bundle ID or package name and it will pull the App Store and Google Play metadata side by side. Ratings, pricing, category, IAP structure, localization breadth, release cadence, the full picture.&lt;/p&gt;



&lt;p&gt;Ask Rico to look up a competitor and it will flag what their monetization strategy tells you: whether they’re running a trial-led conversion model, how their content scope affects willingness to pay, what their rating trajectory suggests about product-market fit.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-rico-in-slack&quot;&gt;&lt;strong&gt;Rico in Slack&lt;/strong&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;929&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/Frame-2147226609-1-1024x929.png&quot; alt=&quot;&quot; class=&quot;wp-image-53697&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/Frame-2147226609-1-1024x929.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/Frame-2147226609-1-300x272.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/Frame-2147226609-1-768x696.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/Frame-2147226609-1-50x45.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/Frame-2147226609-1-44x40.png 44w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/Frame-2147226609-1-512x464.png 512w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/Frame-2147226609-1-696x631.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/Frame-2147226609-1-560x508.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/Frame-2147226609-1-326x296.png 326w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/Frame-2147226609-1-521x472.png 521w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/Frame-2147226609-1-80x73.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/Frame-2147226609-1-48x44.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/Frame-2147226609-1.png 1416w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Most revenue questions start in Slack. Someone posts a screenshot and asks, “Anyone know why this dropped?” Then everyone waits for the one person who knows how to pull the number.&lt;/p&gt;



&lt;p&gt;With the Slack integration, you can now tag &lt;code&gt;@Rico&lt;/code&gt; in any channel with a question. The answer lands in the thread: the data, the context, and what to do next. Visible to everyone in the conversation.&lt;/p&gt;



&lt;p&gt;To &lt;a href=&quot;https://www.revenuecat.com/docs/dashboard-and-metrics/dashboard-and-metrics/rico#installing-rico-in-slack&quot;&gt;connect Rico&lt;/a&gt; to your Slack workspace, go to Account Settings in the RevenueCat dashboard, open the Rico tab, and click Connect to authorize the integration.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-try-rico-today&quot;&gt;&lt;strong&gt;Try Rico today&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Rico is available in public beta.&lt;/p&gt;



&lt;p&gt;Head to your RevenueCat dashboard and ask for a health check. Tell Rico to run a feature adoption audit, or ask: &lt;em&gt;“What’s the biggest bottleneck to my revenue growth right now?”&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;Open the dashboard or add Rico to Slack. Ask your first question.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Build a paywall by describing what you want]]></title><description><![CDATA[Build and refine production-ready paywalls in seconds with RevenueCat’s Paywalls AI Editor.]]></description><link>https://www.revenuecat.com/blog/company/paywalls-ai-editor/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/company/paywalls-ai-editor/</guid><pubDate>Wed, 06 May 2026 13:49:08 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/Blog-58_Build-a-paywall-by-describing-what-you-want.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;At the &lt;a href=&quot;https://www.youtube.com/watch?v=bcnUYWLo-I4&quot;&gt;RevenueCat World Paywall Speed Building Championships 2025&lt;/a&gt;, the winner built a complete, production-ready paywall in 3 minutes and 16 seconds. It was an incredible feat of human engineering and drag-and-drop mastery.&lt;/p&gt;



&lt;p&gt;You can now make that record completely obsolete.&lt;/p&gt;



&lt;p&gt;You know you need to test your paywalls. The difference between a mediocre paywall and a great one is often the difference between a struggling app and a thriving subscription business.&lt;/p&gt;



&lt;p&gt;But for anyone who isn’t a speed-building champion, the reality is different. Creating a paywall that looks good, handles every edge case, and is ready to publish requires design skills and engineering time you don’t have. Iterating on it takes even longer.&lt;/p&gt;



&lt;p&gt;The result is a “good enough” paywall that never gets tested.&lt;/p&gt;



&lt;p&gt;RevenueCat’s Paywalls AI Editor changes this. It’s a conversational paywall agent that lets you generate a production-ready paywall from a text prompt in seconds.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-from-drag-and-drop-to-done-in-seconds&quot;&gt;From drag-and-drop to done-in-seconds&lt;/h2&gt;



&lt;figure class=&quot;wp-block-video&quot;&gt;&lt;video height=&quot;1080&quot; style=&quot;aspect-ratio: 1920 / 1080;&quot; width=&quot;1920&quot; controls=&quot;&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/AI-Paywalls.mp4&quot;&gt;&lt;/video&gt;&lt;/figure&gt;



&lt;p&gt;You can edit any aspect of your paywall using natural language. Type “make the annual plan more prominent” or “use a darker color palette.” Every change streams live in the preview.&lt;/p&gt;



&lt;p&gt;RevenueCat Paywalls AI Editor handles the entire paywall creation process from end to end. Whether you’re starting from a blank canvas or adapting an existing template, the AI Editor gives you complete control over every layer of your paywall.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-copywriting-and-conversion&quot;&gt;Copywriting and conversion&lt;/h3&gt;



&lt;p&gt;Great paywalls live and die on their copy. You can ask the builder to rewrite your headlines, subheads, and CTA text to match your brand voice. Personalize the copy using custom variables like {{ custom.first_name }} or rewrite pricing language with variables like {{ product.price }} and {{ product.relative_discount }}. Clean up awkward copy, fix mismatched monthly and yearly labels, and rebalance plan emphasis, for example, changing the default selected plan, updating badge wording, or anchoring users toward the annual option.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-visual-design-and-layout&quot;&gt;&lt;strong&gt;Visual design and layout&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;You control the entire visual mood through natural language. Ask the builder to restyle your colors, adjust spacing, update typography, or fix contrast issues. Add or refine your layout for light and dark modes separately, for example, a white background with dark text in light mode and a deep navy with a glowing CTA in dark mode. Generate and swap imagery for your hero sections and backgrounds to better match your brand on the fly.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-components-and-structure&quot;&gt;&lt;strong&gt;Components and structure&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Building a paywall means assembling the right pieces. The AI Editor drops in whatever you need on command. You can add headers, feature lists, testimonials, comparison tables, timelines, carousels, and package groups. Remove, duplicate, reorder, or move any existing section, for example, pulling a testimonial block above the pricing cards to build trust before the ask. Ensure compliance by adding sticky footers and updating your Terms and Privacy URLs.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-localization&quot;&gt;&lt;strong&gt;Localization&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Scaling your app means translating your paywall. The AI Editor adds localizations directly to your layout and updates translated copy across every component. Fine-tune individual localized strings, for example, shortening a German CTA that overflows its button and test how different languages affect your layout before you push the changes live.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-pre-launch-auditing&quot;&gt;&lt;strong&gt;Pre-launch auditing&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Before you ship, the builder acts as a second set of eyes. Ask it to audit your paywall for common conversion killers. It flags issues like a low-contrast CTA button, a pricing card that clips on iPhone SE, a missing restore purchases link, or an annual plan that looks identical to the monthly one. Get a list of fixes you can apply instantly with a single follow-up prompt.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-try-the-ai-editor-today&quot;&gt;Try the AI Editor today&lt;/h2&gt;



&lt;p&gt;The RevenueCat Paywalls AI Editor is available in public beta.&lt;/p&gt;



&lt;p&gt;Log into your dashboard, click “Create paywall,” and select “Generate with AI”. Describe what you want to build. Try to beat 3 minutes and 16 seconds. We think you will.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[The Hail Mary pitch that launched a #1 App Store hit]]></title><description><![CDATA[Bria Sullivan pitched a focus timer to Hank Green at the end of a meeting that was already over — and it hit #1 on the App Store.]]></description><link>https://www.revenuecat.com/blog/growth/bria-sullivan-focus-friend-launched-podcast-2026/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/bria-sullivan-focus-friend-launched-podcast-2026/</guid><pubDate>Wed, 06 May 2026 13:16:16 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/LD-Blog-Cover-Bria-Sullivan-1.png" length="0" type="image/*"/><content:encoded>&lt;div class=&quot;lazyblock-d7d847878df0-1GEcbK wp-block-lazyblock-d7d847878df0&quot;&gt;&lt;blogpostyoutube embed-url=&quot;https://www.youtube.com/watch?v=RfCIikVJBkw&quot;&gt;
&lt;/blogpostyoutube&gt;&lt;/div&gt;


&lt;iframe loading=&quot;lazy&quot; width=&quot;100%&quot; height=&quot;180&quot; frameborder=&quot;no&quot; scrolling=&quot;no&quot; seamless=&quot;&quot; src=&quot;https://share.transistor.fm/e/75dc2995?color=FFFFFF&amp;amp;background=30343C&quot;&gt;&lt;/iframe&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-hail-mary-pitch&quot;&gt;The Hail Mary pitch&lt;/h2&gt;



&lt;p&gt;Bria Sullivan had already found success with her game Boba Story, but she wanted to experiment with monetizing a creator’s audience through an app. After a chance dinner meeting with YouTuber Hank Green, she secured a pitch meeting. The goal was to build something for one of his educational channels, Crash Course.&lt;/p&gt;



&lt;p&gt;The meeting didn’t go well. The team wasn’t interested, and the answer was a polite “no.” But as the call was wrapping up, Bria threw out one last idea: “What about a Focus Timer, a Crash Course focus timer?”&lt;/p&gt;



&lt;p&gt;That single question changed the trajectory of the project. While the Crash Course team still passed, Hank Green himself loved the concept. An hour later, he texted her to say he couldn’t stop thinking about it. They decided to partner up and build it specifically for his core audience—the “Nerdfighters.” It was a reminder that sometimes the best opportunities come from simply putting yourself in the room and refusing to let the meeting end on a rejection.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-live-streaming-user-research-on-tiktok&quot;&gt;Live-streaming user research on TikTok&lt;/h2&gt;



&lt;p&gt;Rather than building in a vacuum, Bria used her existing TikTok audience to validate the app’s design in real time. During long live streams, she would draw different art styles, show color palettes, and ask her viewers directly what they preferred.&lt;/p&gt;



&lt;p&gt;She presented six different variations of the app’s central character—a “bean”—and let the audience guide the direction. “When it comes to female audiences too and anything gamified, the look and feel matters so much for organic reach,” she explains. “It’s like what’s going to make someone convert, and the way something looks is a huge reason why people convert.”&lt;/p&gt;



&lt;p&gt;This public validation ensured that by the time the app was ready, it already matched the exact aesthetic preferences of its target users. The original, lo-fi “Bee and Puppycat” style she initially favored was scrapped entirely based on this immediate, unfiltered feedback.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-backlash-of-monetizing-a-fanbase&quot;&gt;The backlash of monetizing a fanbase&lt;/h2&gt;



&lt;p&gt;Partnering with a massive creator solves the distribution problem, but it introduces a unique set of challenges. When Focus Friend quietly launched via a YouTube community post, the initial reaction wasn’t purely celebratory.&lt;/p&gt;



&lt;p&gt;Despite getting 20,000 downloads in the first week, Bria was flooded with angry emails and negative reviews. Users were upset that the app used a subscription model instead of a lifetime unlock, and they were highly sensitive to standard app practices like ad tracking. Because the app was tied to Hank Green—a beloved public figure known for his philanthropy—users felt a personal betrayal that they wouldn’t feel toward a faceless corporation.&lt;/p&gt;



&lt;p&gt;“I learned that,” Bria says. “Every app on your phone uses those things, but for some reason he’s not allowed to.” To protect Hank’s reputation and maintain trust, they made the difficult decision to strip out advertising tracking IDs entirely. It was a move that essentially killed their ability to do paid user acquisition, but it preserved the core relationship with the audience.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-creators-make-terrible-product-managers&quot;&gt;Why creators make terrible product managers&lt;/h2&gt;



&lt;p&gt;Bria’s experience with Focus Friend taught her a crucial lesson about creator partnerships: influencers rarely know what makes a good standalone app.&lt;/p&gt;



&lt;p&gt;“I don’t think that influencers really know what a good idea is for them to do for their audience,” she observes. “They always, for some reason, they always want a social media or they want a feed of information. And I’m just like, no, I just don’t think that those are good ideas for apps personally.”&lt;/p&gt;



&lt;p&gt;Her advice to developers looking to partner with creators is to act as the product manager. Creators understand their audience’s content preferences, but developers understand utility. The most successful collaborations happen when the developer steers the product toward a clear, functional use case—like a focus timer—rather than trying to build another content feed.&lt;/p&gt;



&lt;p&gt;In &lt;a href=&quot;https://www.youtube.com/watch?v=RfCIikVJBkw&quot;&gt;the full episode&lt;/a&gt;, Bria also talks about her journey from learning Android development in 2010 to winning an App Store Award, the reality of being a solo developer while raising a newborn, and why she believes product instinct is far more valuable than pure engineering skill.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-guest-links&quot;&gt;Guest links:&lt;/h2&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.linkedin.com/in/briasullivan/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Bria Sullivan on LinkedIn&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://apps.apple.com/us/app/focus-friend-study-timer/id6450682289&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Focus Friend on the App Store&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://apps.apple.com/us/app/boba-story/id1535742211&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Boba Story on the App Store&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title><![CDATA[AI-generated ads: balancing attention and trust in user-generated content]]></title><description><![CDATA[What actually works in synthetic ads, and how to juggle the boundary between algorithmic success and brand trust]]></description><link>https://www.revenuecat.com/blog/growth/ad-generated-ads-ugc/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/ad-generated-ads-ugc/</guid><pubDate>Wed, 06 May 2026 13:02:26 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/05/Blog-55_AI-generated-UGC_-what-you-need-to-know.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;User-generated videos are no longer exclusively &lt;em&gt;user&lt;/em&gt; generated.&lt;/p&gt;



&lt;p&gt;With the rise of AI, advertisers can now generate creator-style ads in a matter of hours using synthetic avatars, automated voiceovers, and video tools. What used to require weeks of coordination and creator involvement can now be executed in an afternoon.&lt;/p&gt;



&lt;p&gt;This shift is not just technological, it reflects a deeper change in how advertising operates — the pace of modern platforms has outgrown traditional content production.&lt;/p&gt;



&lt;p&gt;But this raises a fundamental question. If content no longer needs to be created by real people to perform, what actually drives trust, and where does artificial intelligence start to break it?&lt;/p&gt;



&lt;p&gt;Based on what we’ve tested at Mojo, the answer is more nuanced than the current hype suggests. But there’s a few key learnings:&amp;nbsp;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Replication beats interpretation&lt;/li&gt;



&lt;li&gt;The cost of failure has collapsed&lt;/li&gt;



&lt;li&gt;AI knows what looks real, but humans know what feels real&lt;/li&gt;



&lt;li&gt;You are no longer building an ad; you are building a system&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-real-driver-ad-fatigue&quot;&gt;&lt;strong&gt;The real driver: ad fatigue&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The rise of AI-generated ads is not driven by novelty alone. While it is undeniably fueled by the fact that technology has finally crossed a critical threshold of fidelity, the primary catalyst for its adoption is a structural constraint: ad fatigue&lt;/p&gt;



&lt;p&gt;On platforms like TikTok and Meta, videos are consumed at a relentless pace. A highly-effective ad can lose its impact within days. For subscription-based products, this rapid decay directly increases the cost of acquiring a new customer.&lt;/p&gt;



&lt;p&gt;Today, those stakes couldn’t be higher — with RevenueCat data showing &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps/&quot;&gt;the top 25% of subscription apps grew 80% year-over-year in 2026&lt;/a&gt;, while the bottom 25% shrank by 33%. In a winner-take-more market, efficient acquisition isn’t just about optimization, it’s about your app surviving at all.&lt;/p&gt;



&lt;p&gt;The natural response is to produce more videos. But this is where the traditional system breaks:standard production is slow and requires a lot of resources. Even highly efficient teams operate on multi-week cycles. Meanwhile, the algorithms shift in real time.&lt;/p&gt;



&lt;p&gt;This creates a fundamental mismatch: &lt;strong&gt;the algorithm evolves faster than your production process&lt;/strong&gt;. AI removes that constraint. Instead of asking what the next ad should be, teams can now ask how many variations they can test today. The primary advantage of AI is not that it produces better ads. It’s that it allows you to discover better ads faster.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-case-study-scaling-the-mojo-auto-edit-winner&quot;&gt;Case study: Scaling the Mojo ‘Auto Edit’ winner&lt;/h2&gt;



&lt;p&gt;At Mojo, one of our highest-performing ads was a simple 30-second split-screen video featuring a speaker explaining the product on top and a screen recording of the app on the bottom. This video converted trial users to paid at 23%.&lt;/p&gt;



&lt;p&gt;The secret was the person. Our creator was our Product Manager. When he explained the product, he was walking through something he deeply understood. His conviction came from ownership. That kind of authenticity is extremely difficult to synthesize from scratch.&lt;/p&gt;



&lt;script src=&quot;https://fast.wistia.com/player.js&quot; async=&quot;&quot;&gt;&lt;/script&gt;&lt;script src=&quot;https://fast.wistia.com/embed/2cungs4wsi.js&quot; async=&quot;&quot; type=&quot;module&quot;&gt;&lt;/script&gt;&lt;style&gt;wistia-player[media-id=&apos;2cungs4wsi&apos;]:not(:defined) { background: center / contain no-repeat url(&apos;https://fast.wistia.com/embed/medias/2cungs4wsi/swatch&apos;); display: block; filter: blur(5px); }&lt;/style&gt; &lt;wistia-player media-id=&quot;2cungs4wsi&quot; aspect=&quot;0.5625&quot; style=&quot;width: 600px;height: 338px;&quot;&gt;&lt;/wistia-player&gt;



&lt;p&gt;&lt;em&gt;Baseline: Our top-performing human UGC. Notice the genuine conviction of our PM talking about the feature he built.&lt;/em&gt;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-phase-1-why-replication-outperformed-native-creators&quot;&gt;&lt;strong&gt;Phase 1: why replication outperformed native creators&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;To scale this ad internationally, we initially recruited local creators in several countries to recreate the video. The result was disappointing — despite strong production quality, performance dropped across markets.&lt;/p&gt;



&lt;p&gt;The issue came down to execution: each creator interpreted the script slightly differently. Pauses were shortened, pacing changed, and gestures were misaligned. Individually, these differences seemed minor, but collectively, they killed performance.&lt;/p&gt;



&lt;p&gt;There was also a constraint regarding legal rights. We often did not have the rights to extend a creator’s content into other languages. This highlighted a critical point: &lt;strong&gt;the best-performing creator is the one you actually own.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;So we changed strategy. Instead of adapting the ad, we replicated it: we used video translation tools like HeyGen to dub the original video, while strictly preserving the timing, the pauses, the gestures, and the exact energy. In Brazil, the dubbed version achieved a 40% lower acquisition cost compared to native creators.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;The lesson here is that execution mechanics matter just as much as the message. AI does not reinterpret; it preserves.&lt;/p&gt;



&lt;script src=&quot;https://fast.wistia.com/player.js&quot; async=&quot;&quot;&gt;&lt;/script&gt;&lt;script src=&quot;https://fast.wistia.com/embed/8o7j5p7qcz.js&quot; async=&quot;&quot; type=&quot;module&quot;&gt;&lt;/script&gt;&lt;style&gt;wistia-player[media-id=&apos;8o7j5p7qcz&apos;]:not(:defined) { background: center / contain no-repeat url(&apos;https://fast.wistia.com/embed/medias/8o7j5p7qcz/swatch&apos;); display: block; filter: blur(5px); }&lt;/style&gt; &lt;wistia-player media-id=&quot;8o7j5p7qcz&quot; aspect=&quot;0.5625&quot; style=&quot;width: 600px;height: 338px;&quot;&gt;&lt;/wistia-player&gt;



&lt;p&gt;&lt;em&gt;AI Dubbing: 95% perfect lip-sync preserving our PM’s original high energy.&lt;/em&gt;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-phase-2-ai-avatars-the-80-failure-rate&quot;&gt;&lt;strong&gt;Phase 2: AI avatars (the 80% failure rate)&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Encouraged by these results, we moved to fully AI-generated avatars. We expected the speed of production to compensate for a slight dip in quality. Instead, the outcome was binary: most of the profiles we tested failed almost immediately.&lt;/p&gt;



&lt;p&gt;The generic avatars we initially generated did not work, and the reasons went beyond mere technical fidelity.&lt;/p&gt;



&lt;p&gt;First, we encountered a fundamental &lt;strong&gt;perspective and staging issue&lt;/strong&gt;. As you can see in the variations above, the avatars were placed in hyper-polished environments — studio microphones, cinematic lighting, and stylized backgrounds. Some were even positioned at slight three-quarter angles rather than looking directly into the lens. This immediately broke the native, informal visual code of UGC. The user’s brain categorized the content as a commercial within the first second.&lt;/p&gt;



&lt;p&gt;Second, there was a major &lt;strong&gt;casting issue&lt;/strong&gt;. The avatars simply did not match our Product Manager’s original profile or conversational energy. We were trying to scale a specific type of raw, founder-led credibility, but we were using avatars that looked like generic stock models or polished influencers. The disconnect between the message and the messenger was jarring.&lt;/p&gt;



&lt;p&gt;These flaws, combined with the expected rigid expressions, caused rapid drop-offs. One avatar had a mere 0.2-second lip-sync delay on a key word, which resulted in a 68% drop in click-through rate compared to the human baseline. Users couldn’t articulate why they did not trust it, but the data was brutal.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;But one avatar worked.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Instead of using a generic, polished profile, we used HeyGen to create a custom digital twin based strictly on our original Product Manager. We stripped away the studio mics and cinematic lighting. We matched his raw facecam perspective, his specific look, and his exact baseline energy.&lt;/p&gt;



&lt;p&gt;Because the source material already had natural presence and inherent credibility, the output felt believable. That version reached &lt;strong&gt;87% of the original human conversion rate.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;The economics changed dramatically:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Traditional creator: &lt;strong&gt;$500&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;Generating the custom AI avatar: &lt;strong&gt;$20&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;strong&gt;RESULT: 31% lower cost per acquisition.&lt;/strong&gt;&lt;/p&gt;



&lt;script src=&quot;https://fast.wistia.com/player.js&quot; async=&quot;&quot;&gt;&lt;/script&gt;&lt;script src=&quot;https://fast.wistia.com/embed/60djmtbbvs.js&quot; async=&quot;&quot; type=&quot;module&quot;&gt;&lt;/script&gt;&lt;style&gt;wistia-player[media-id=&apos;60djmtbbvs&apos;]:not(:defined) { background: center / contain no-repeat url(&apos;https://fast.wistia.com/embed/medias/60djmtbbvs/swatch&apos;); display: block; filter: blur(5px); }&lt;/style&gt; &lt;wistia-player media-id=&quot;60djmtbbvs&quot; aspect=&quot;0.5625&quot; style=&quot;width: 600px;height: 338px;&quot;&gt;&lt;/wistia-player&gt;



&lt;p&gt;&lt;em&gt;The $20 Winner: Natural head tilts and accurate micro-expressions driving a 31% lower CPA.&lt;/em&gt;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-phase-3-the-double-ai-stack&quot;&gt;&lt;strong&gt;Phase 3: the double AI stack&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Once we identified a &lt;a href=&quot;https://www.revenuecat.com/blog/growth/informed-empathy-user-interviews-ad-creatives/&quot;&gt;winning creative&lt;/a&gt;, we introduced a two-step process: generating the base video using the custom avatar, then instantly translating it into multiple new languages using &lt;a href=&quot;https://www.revenuecat.com/blog/growth/jack-tanmay-elevenlabs-sub-club-podcast-2026/&quot;&gt;ElevenLabs&lt;/a&gt; for localized, natural-sounding voice cloning.&lt;/p&gt;



&lt;script src=&quot;https://fast.wistia.com/player.js&quot; async=&quot;&quot;&gt;&lt;/script&gt;&lt;script src=&quot;https://fast.wistia.com/embed/dlqbge03we.js&quot; async=&quot;&quot; type=&quot;module&quot;&gt;&lt;/script&gt;&lt;style&gt;wistia-player[media-id=&apos;dlqbge03we&apos;]:not(:defined) { background: center / contain no-repeat url(&apos;https://fast.wistia.com/embed/medias/dlqbge03we/swatch&apos;); display: block; filter: blur(5px); }&lt;/style&gt; &lt;wistia-player media-id=&quot;dlqbge03we&quot; aspect=&quot;0.5625&quot; style=&quot;width: 600px;height: 338px;&quot;&gt;&lt;/wistia-player&gt;



&lt;p&gt;&lt;strong&gt;The results (Brazil localized metrics):&lt;/strong&gt;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;CPA:&lt;/strong&gt; $8 (31% lower than the human control)&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;CTR:&lt;/strong&gt; 4.5%&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Conversion Rate:&lt;/strong&gt; 3.1%&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;ROAS:&lt;/strong&gt; 2.1x&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;strong&gt;The cultural limit:&lt;/strong&gt; This ‘double layer’ stack (a synthetic avatar that is then dubbed into another language) worked flawlessly in Brazil and Spanish-speaking markets, where users are highly receptive to direct-response UGC formats. However, when we pushed this exact same dubbed avatar to Europe (France, Germany), it failed. The European audience was far more sensitive to the uncanny valley, and the double layer of AI broke their trust.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;This highlighted to us that sensitivity to artificial media is not just technical. It is geographic and culturally dependent. You can’t assume universal adoption.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-key-takeaways-how-ai-generated-ugc-impacts-ad-performance-and-trust&quot;&gt;&lt;strong&gt;Key takeaways: how AI-generated UGC impacts ad performance and trust&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Ads are our business, so we had the luxury of being able to test AI-generated ads and finesse the output. Many apps won’t be able to take this same risk and time, so here’s my top learnings from our creative experiments with AI &lt;a href=&quot;https://www.revenuecat.com/blog/growth/ugc-ads-apps/&quot;&gt;user-generated content&lt;/a&gt;.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-natural-execution-beats-polished-authenticity&quot;&gt;&lt;strong&gt;Why natural execution beats polished authenticity&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;There is a common assumption that videos made by users perform well because they’re authentic. In practice, authenticity is only part of the story. These videos work because — even when users are following a script — they &lt;em&gt;feel&lt;/em&gt; natural.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;The best-performing ads rely on familiar patterns like direct-to-camera delivery, informal conversational tones, and simple visuals. AI is highly effective at replicating these patterns. By mimicking the structure of successful content, AI-generated ads can improve early metrics like views and watch time.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-balancing-algorithmic-attention-vs-user-trust&quot;&gt;&lt;strong&gt;Balancing algorithmic attention vs. user trust&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;One of the most important insights from our experiments is that these ads operate across two distinct layers:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;The algorithm rewards &lt;strong&gt;attention&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;The user decides based on &lt;strong&gt;trust&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;AI helps you win the first, but it doesn’t guarantee the second.&lt;/p&gt;



&lt;p&gt;In our tests, fully synthetic avatars struggled in formats that rely on credibility, especially testimonials or personal stories. People are sensitive to anything that feels artificial in emotional contexts. We subconsciously scan for micro-expressions, subtle changes in eye contact, and the natural hesitation that signals genuine human experience. When an algorithm tries to simulate a heartfelt story, it misses these imperceptible cues. The result is a subconscious rejection by the viewer.&lt;/p&gt;



&lt;p&gt;Conversely, AI thrives in structured, utility-driven formats. For product demonstrations, tutorials, and feature breakdowns, clarity and pacing matter far more than emotional authenticity. The rule is simple: &lt;strong&gt;use AI to explain, and use humans to convince&lt;/strong&gt;. This principle was at the heart of our strategy when we decided to scale our own top-performing content at Mojo.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-economics-of-failing-fast&quot;&gt;&lt;strong&gt;The economics of failing fast&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The real advantage of AI was not just cost. It was speed.&lt;/p&gt;



&lt;p&gt;With traditional methods, &lt;a href=&quot;https://www.revenuecat.com/blog/growth/subscription-app-creative-testing/&quot;&gt;creative testing&lt;/a&gt; five human creators takes $2,500 and three weeks of production to find one potential winner. Testing five AI variations takes $100 and just two hours.&lt;/p&gt;



&lt;p&gt;The downside of &lt;a href=&quot;https://www.revenuecat.com/blog/growth/overanalyze-creative-analysis-paid-ads/&quot;&gt;testing creatives&lt;/a&gt; has collapsed. You’re no longer optimizing for perfect execution upfront, you’re optimizing for iteration speed. You are no longer buying videos, you’re buying iterations — and iteration compounds.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-from-production-to-decision-making&quot;&gt;&lt;strong&gt;From production to decision-making&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Before, production was the bottleneck. Now, production is instant. But a new bottleneck emerges: decision-making.&lt;/p&gt;



&lt;p&gt;When you only have five videos a month, you can rely on intuition. When you can generate 50 variations a day, intuition fails. Teams no longer need to figure out how to produce content. They need to figure out what to test and what to cut.&lt;/p&gt;



&lt;p&gt;AI did not remove the need for creativity. It made taste and data analysis the new competitive advantages. Bad decisions now scale just as fast as good ones.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-hidden-risks&quot;&gt;&lt;strong&gt;The hidden risks&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Like any new approach to &lt;a href=&quot;https://www.revenuecat.com/blog/growth/creative-fatigue-mobile-apps-roas/&quot;&gt;ad creatives&lt;/a&gt;, there are payoffs you have to consider:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-cookie-cutter-ads&quot;&gt;Cookie-cutter ads&lt;/h3&gt;



&lt;p&gt;We’re already seeing a specific aesthetic emerge among AI-generated ads: perfect lighting, lack of breathing pauses, and synthetic enthusiasm. If every brand starts using similar avatars, these videos will become the new fatigued format. &lt;a href=&quot;https://www.revenuecat.com/blog/growth/detect-ad-fatigue-mobile-apps/&quot;&gt;Ad fatigue&lt;/a&gt; won’t disappear; it just shifts from the individual video to the format itself.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-navigating-the-legal-maze&quot;&gt;Navigating the legal maze&lt;/h3&gt;



&lt;p&gt;There’s also a significant legal challenge. Building your acquisition engine on a digital copy of a real person is a liability maze. Who owns the likeness if that employee leaves the company?&amp;nbsp;&lt;/p&gt;



&lt;p&gt;With external creators, the problem is worse. If you don’t secure rights to use their digital likeness, you’re essentially renting your growth. &lt;strong&gt;Owned content scales, rented content does not.&lt;/strong&gt; Brands need to rethink their talent contracts entirely. You need specific likeness agreements that outline exactly how, where, and for how long a synthetic avatar can be used, including clauses that allow the company to run the digital copy for six to twelve months after an employee departs.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-audience-backlash-and-reputational-risk&quot;&gt;Audience backlash and reputational risk&lt;/h3&gt;



&lt;p&gt;The risk of audience backlash is a reality that cannot be ignored. Audiences are becoming increasingly sophisticated at identifying synthetic media, and for subscription-based apps, the stakes are uniquely high. Because the business model relies on an ongoing relationship, being perceived as using deceptive or low-quality AI &lt;a href=&quot;https://www.revenuecat.com/blog/growth/creative-volume-meta-ad/&quot;&gt;creative at volume&lt;/a&gt; can be devastating.&lt;/p&gt;



&lt;p&gt;It creates what is essentially a ‘trust tax’, if a user feels tricked by an advertisement, they might install the app, but will inevitably churn. It doesn’t just hurt immediate acquisition; it erodes the fundamental trust that drives long-term retention. Every app audience is different, so it’s vital to consider your specific consumer group’s sentiment. The challenge for brands moving forward is finding the balance between being transparent, efficient, and maintaining a sincere human connection.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-best-practices-for-scaling-ai-generated-ads&quot;&gt;&lt;strong&gt;Best practices for scaling AI-generated ads&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Before you generate new AI content, you need to answer a few fundamental questions:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Do you own the source material and likeness rights?&lt;/li&gt;



&lt;li&gt;Is the format utility-driven rather than an emotional story?&lt;/li&gt;



&lt;li&gt;Can you kill the campaign in 24 hours if the data shows it is failing?&lt;/li&gt;



&lt;li&gt;Have you tested your specific market’s tolerance for synthetic media?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Most importantly, you have to &lt;strong&gt;break the perfection&lt;/strong&gt;. Perfect delivery feels like a commercial. Here’s what we’ve found works:&amp;nbsp;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Lower the resolution slightly so it does not look like a studio shoot&lt;/li&gt;



&lt;li&gt;Let the audio retain a bit of background room tone.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Artificial intelligence naturally gravitates toward a flawless output, so you have to actively force it to be messy.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-checklist-when-to-use-ai-or-real-users-for-ads-nbsp&quot;&gt;Checklist: when to use AI or real users for ads&amp;nbsp;&lt;/h3&gt;



&lt;p&gt;If you’re deciding between a human creator and a synthetic avatar, use this quick reference guide based on our testing:&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Opt for AI-generated ads when:&lt;/strong&gt;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;The goal is utility:&lt;/strong&gt; product walkthroughs, feature demos, or screen-recording tutorials&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;You need scale: &lt;/strong&gt;testing 10+ hook variations or localizing an ad into five different languages&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Speed is critical: &lt;/strong&gt;you need to respond to a creative trend within 24 hours&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Cost is the bottleneck: &lt;/strong&gt;you have a winning script but a limited budget for multiple creators&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;strong&gt;Opt for real humans when:&lt;/strong&gt;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;The goal is trust: &lt;/strong&gt;personal testimonials, ‘storytime’ formats, or founder-led brand intros&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Emotional nuance is key: &lt;/strong&gt;content that requires subtle micro-expressions or genuine empathy&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;High-value markets: &lt;/strong&gt;targeting regions (like Europe) with high sensitivity to ‘uncanny valley’ media&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Originality: &lt;/strong&gt;creating the source material that will eventually be replicated by AI&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-new-ugc&quot;&gt;&lt;strong&gt;The new UGC&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;We’re entering an era of infinite content where the true bottleneck is no longer creation, but judgment. While the technological barrier to generating an ad has effectively dropped to zero, &lt;strong&gt;the psychological barrier to earning consumer trust has never been higher&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;Algorithms are exceptionally good at replicating familiar patterns to buy attention, compress feedback loops, and scale distribution. What they cannot do, however, is synthesize genuine conviction. The top growth teams of the future won’t merely be those who test the fastest. Instead, they will be the ones who understand exactly when to automate a system for efficiency, and when to rely on a real human heartbeat for persuasion.Ultimately, AI didn’t make advertising smarter — it simply revealed the clear boundary between what machines can execute and what they cannot. &lt;strong&gt;Speed and automation will always buy you attention, but it takes a human to earn trust&lt;/strong&gt;.&lt;/p&gt;


&lt;div class=&quot;lazyblock-dd0db17b8671-24xJHo wp-block-lazyblock-dd0db17b8671&quot;&gt;&lt;blogpostpodcastcta title=&quot;Eleven Labs on the Sub Club podcast&quot; description=&quot;Hear the story behind Eleven Labs, the AI tool Anthony and the Mojo team used for their winning creative&quot; links=&quot;[{&amp;quot;link-title&amp;quot;:&amp;quot;YouTube&amp;quot;,&amp;quot;link-url&amp;quot;:&amp;quot;https:\/\/www.youtube.com\/watch?v=3r8pr9w_lDQ&amp;quot;,&amp;quot;link-image&amp;quot;:&amp;quot;youtube&amp;quot;},{&amp;quot;link-title&amp;quot;:&amp;quot;Spotify&amp;quot;,&amp;quot;link-url&amp;quot;:&amp;quot;https:\/\/open.spotify.com\/episode\/3gC8n6pbe52ppPB0BWLyTa?si=feaba85b2af14556&amp;quot;,&amp;quot;link-image&amp;quot;:&amp;quot;spotify&amp;quot;},{&amp;quot;link-title&amp;quot;:&amp;quot;Apple Podcasts&amp;quot;,&amp;quot;link-url&amp;quot;:&amp;quot;https:\/\/podcasts.apple.com\/gb\/podcast\/how-elevenlabs-turns-feature-launches-into-a-growth\/id1538057974?i=1000753972691&amp;quot;,&amp;quot;link-image&amp;quot;:&amp;quot;apple-podcasts&amp;quot;}]&quot;&gt;
&lt;/blogpostpodcastcta&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[The post-purchase screen: how to stop Day 0 cancellations]]></title><description><![CDATA[How to stop losing subscribers before they even start the trial]]></description><link>https://www.revenuecat.com/blog/growth/post-purchase-screen/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/post-purchase-screen/</guid><pubDate>Tue, 05 May 2026 10:21:34 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Post-purchase-screen.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;There are a lot of things that keep me up at night: my ADHD medication, whether I locked the back door, my dog trying to get on the bed… and these trial cancellation numbers. Yep, stats like these are enough to steal my Zs (and now they’re about to do the same to you, sorry in advance).&lt;/p&gt;



&lt;p&gt;A staggering 55.4% of 3-day trials are cancelled on Day 0. Ouch.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;That’s over half gone before they’ve even had a chance to use what they signed up for. Talk about not giving an app a fair shot. So what’s happening, and how can apps combat it?&lt;/p&gt;



&lt;p&gt;Whilst the number does drop a bit with longer trials, even with a 30-day trial nearly a third of &lt;strong&gt;users cancel on the very first day&lt;/strong&gt;. Combine Day 0 and Day 1, and you’re looking at &lt;strong&gt;84% of 3-day trial cancellations happening in that first 24 hours.&lt;/strong&gt; For 7-day trials, it’s still 64%.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;618&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/of-trial-cancellations-by-day-and-trial-duration-1024x618.png&quot; alt=&quot;&quot; class=&quot;wp-image-53660&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/of-trial-cancellations-by-day-and-trial-duration-1024x618.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/of-trial-cancellations-by-day-and-trial-duration-300x181.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/of-trial-cancellations-by-day-and-trial-duration-768x463.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/of-trial-cancellations-by-day-and-trial-duration-1536x926.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/of-trial-cancellations-by-day-and-trial-duration-2048x1235.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/of-trial-cancellations-by-day-and-trial-duration-50x30.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/of-trial-cancellations-by-day-and-trial-duration-66x40.png 66w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/of-trial-cancellations-by-day-and-trial-duration-696x420.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/of-trial-cancellations-by-day-and-trial-duration-560x338.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/of-trial-cancellations-by-day-and-trial-duration-491x296.png 491w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/of-trial-cancellations-by-day-and-trial-duration-783x472.png 783w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/of-trial-cancellations-by-day-and-trial-duration-80x48.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/of-trial-cancellations-by-day-and-trial-duration-48x29.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;% of trial cancellations, by day and trial duration — State of Subscription Apps 2026&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;Do you see why those numbers keep me up at night?&amp;nbsp;&lt;/p&gt;



&lt;p&gt;And it’s not just trials, even annual subscriptions see &lt;strong&gt;almost 35% of cancellations within the first month.&lt;/strong&gt; &lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;616&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Cancellation-timeline-for-annual-subscriptions-1024x616.png&quot; alt=&quot;&quot; class=&quot;wp-image-53662&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Cancellation-timeline-for-annual-subscriptions-1024x616.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Cancellation-timeline-for-annual-subscriptions-300x180.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Cancellation-timeline-for-annual-subscriptions-768x462.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Cancellation-timeline-for-annual-subscriptions-1536x924.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Cancellation-timeline-for-annual-subscriptions-2048x1232.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Cancellation-timeline-for-annual-subscriptions-50x30.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Cancellation-timeline-for-annual-subscriptions-67x40.png 67w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Cancellation-timeline-for-annual-subscriptions-696x419.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Cancellation-timeline-for-annual-subscriptions-560x337.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Cancellation-timeline-for-annual-subscriptions-492x296.png 492w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Cancellation-timeline-for-annual-subscriptions-785x472.png 785w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Cancellation-timeline-for-annual-subscriptions-80x48.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Cancellation-timeline-for-annual-subscriptions-48x29.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Cancellation timeline for annual subscriptions — State of Subscription Apps 2026&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-55-of-free-trials-cancel-on-day-zero&quot;&gt;&lt;strong&gt;Why 55% of free trials cancel on day zero&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;This data from the &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps/&quot;&gt;State of Subscription Apps Report 2026&lt;/a&gt; really surprised me. &lt;a href=&quot;https://www.revenuecat.com/blog/growth/subscription-app-churn-reasons-how-to-fix/&quot;&gt;Users are churning fast&lt;/a&gt;, losing faith in the app from the outset, feeling disappointed. It’s like your date slipping out after the first drink. You’re left wondering… how did it go so wrong so fast?&lt;/p&gt;



&lt;p&gt;The first place we tend to look is &lt;strong&gt;onboarding&lt;/strong&gt;. While I’ve seen plenty of wins from &lt;a href=&quot;https://www.revenuecat.com/blog/growth/fix-onboarding-funnels/&quot;&gt;improving onboarding and paywalls&lt;/a&gt;, it’s not enough. These early cancellations show a clear pattern: people &lt;em&gt;want&lt;/em&gt; to try your product. They hand over their payment details, click subscribe… and then something goes wrong immediately after.&lt;/p&gt;



&lt;p&gt;Most advice on reducing early cancellations focuses on the in-app experience, pre-trial onboarding or &lt;a href=&quot;https://subclub.com/episode/how-to-boost-retention-with-subscription-lifecycle-messaging-alice-muir-phiture&quot;&gt;improving your lifecycle marketing&lt;/a&gt;. All this is important, but there’s one step almost nobody talks about: &lt;strong&gt;the post-subscription screen.&lt;/strong&gt; The very thing your users see the moment after they convert.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-introducing-app-aftercare-aka-the-post-purchase-screen&quot;&gt;&lt;strong&gt;Introducing app aftercare: aka, the post-purchase screen&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;I first realized this when I interviewed &lt;a href=&quot;https://www.revenuecat.com/blog/growth/how-top-apps-approach-paywalls/&quot;&gt;Rosie Hoggmascall, Head of Product &amp;amp; UX at Fyxer.ai, on her approach to paywalls&lt;/a&gt;. She emphasized thinking about &lt;strong&gt;what happens &lt;/strong&gt;&lt;strong&gt;&lt;em&gt;after&lt;/em&gt;&lt;/strong&gt;&lt;strong&gt; purchase&lt;/strong&gt;, and it stuck with me. I call it aftercare, because that’s exactly what most apps are missing: care.&lt;/p&gt;



&lt;p&gt;Think about it like this: you walk into a shop, buy something, and the minute your transaction goes through, the salesperson turns away. No “Great choice!”, no bag, no receipt, no guidance on how it works. Just… nothing. You’d feel weirdly used. Embarrassed. Probably just awkwardly standing there wondering, “Now what?”.&lt;/p&gt;



&lt;p&gt;That’s exactly what most apps do.&lt;/p&gt;



&lt;p&gt;I walked through a ton of post-purchase screens to see how different apps handle this moment. (Confession: I didn’t spend hundreds of pounds on subscriptions. I have to be very strict on my app subscriptions, given how many I test. So I used &lt;a href=&quot;https://mobbin.com/&quot;&gt;Mobbin&lt;/a&gt; for examples, though I did peek at some in the wild too.) What I found was a spectrum: some apps completely miss the moment, and some absolutely nail it.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-6-levels-of-post-purchase-screen-optimization&quot;&gt;&lt;strong&gt;6 Levels of post-purchase screen optimization&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Here’s how to level up your post-purchase screen, step by step. I see six levels of post-purchase screens:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;The basic version: straight into the app&lt;/li&gt;



&lt;li&gt;A clear confirmation screen&lt;/li&gt;



&lt;li&gt;Celebrate the moment&lt;/li&gt;



&lt;li&gt;Remind them what they are getting&lt;/li&gt;



&lt;li&gt;Highlight what you’ll help them achieve&lt;/li&gt;



&lt;li&gt;Give them one clear next step&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Each is slightly better than the last, and more in tune with what the user needs.&lt;/p&gt;



&lt;p&gt;Now, I will say that as much as I love a neat little framework, some apps I reviewed broke the mould, choosing to use the post-purchase moment to push users to sign up for an account or pursue an upsell. That also works in certain scenarios, so I’ll cover when to go with those approaches as well.&lt;/p&gt;



&lt;p&gt;I’ve also made a Mobbin board with 13 examples of different app onboarding-to-post-purchase screen journeys. &lt;a href=&quot;https://mobbin.com/collections/8cfbacbc-d7bf-4d77-85eb-2aeda12b9c44/mobile/flows?utm_source=share_link&amp;amp;utm_medium=share&amp;amp;utm_campaign=collection_sharing&quot;&gt;Check it out here.&lt;/a&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;605&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-52-1024x605.png&quot; alt=&quot;&quot; class=&quot;wp-image-53652&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-52-1024x605.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-52-300x177.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-52-768x453.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-52-1536x907.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-52-50x30.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-52-68x40.png 68w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-52-696x411.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-52-560x331.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-52-501x296.png 501w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-52-800x472.png 800w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-52-80x47.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-52-48x28.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-52.png 2048w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-level-1-the-default-straight-into-app-version&quot;&gt;&lt;strong&gt;Level 1: the default straight-into-app version&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The most common approach is to rely on Apple’s default “You’re all set” confirmation, then dump users straight into the app. That’s it. No intermediate screen, no acknowledgement of what just happened, no guidance on what to do next.&lt;/p&gt;



&lt;p&gt;Take &lt;a href=&quot;https://zerolongevity.com/&quot;&gt;Zero&lt;/a&gt;, a weightloss and metabolic health app. You subscribe, get the standard Apple pop-up, and then you’re deposited straight into the app. What next?&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;427&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-40-1024x427.png&quot; alt=&quot;&quot; class=&quot;wp-image-53628&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-40-1024x427.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-40-300x125.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-40-768x320.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-40-50x21.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-40-96x40.png 96w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-40-696x290.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-40-560x234.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-40-840x350.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-40-80x33.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-40-48x20.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-40.png 1122w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;a href=&quot;https://www.masterclass.com/&quot;&gt;MasterClass&lt;/a&gt;, the online learning platform, does the same. You could argue it makes sense — MasterClass has a massive library, and users potentially already know what they want to watch or were attracted by a specific expert to subscribe. But even here, a little extra care would go a long way. If someone clicks through that confirmation screen too quickly (and they will), they might not even register what they just signed up for — or how much they’re paying.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;904&quot; height=&quot;467&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-42.png&quot; alt=&quot;&quot; class=&quot;wp-image-53632&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-42.png 904w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-42-300x155.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-42-768x397.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-42-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-42-77x40.png 77w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-42-696x360.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-42-560x289.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-42-840x434.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-42-80x41.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-42-48x25.png 48w&quot; sizes=&quot;auto, (max-width: 904px) 100vw, 904px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;It’s the same as the store example I shared earlier: no acknowledgement, no guidance, just an abrupt ending.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-level-2-a-clear-confirmation-screen&quot;&gt;&lt;strong&gt;Level 2: a clear confirmation screen&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Level two is a simple but meaningful upgrade — after the standard Apple confirmation, add your own screen that &lt;strong&gt;acknowledges what just happened&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://talkpillowtalk.com/&quot;&gt;Pillow Talk&lt;/a&gt;, an AI journaling app, does this really well. It welcomes you to Pillow Talk Plus, confirms that everything in the plan is now yours — the insights, the support, the space to process — and then guides you straight into the app.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;905&quot; height=&quot;477&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-41.png&quot; alt=&quot;&quot; class=&quot;wp-image-53630&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-41.png 905w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-41-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-41-768x405.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-41-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-41-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-41-696x367.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-41-560x296.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-41-840x443.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-41-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-41-48x25.png 48w&quot; sizes=&quot;auto, (max-width: 905px) 100vw, 905px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;It doesn’t list every feature exhaustively, but it gives a reassuring tick that you made the right choice. It also helps clarify that your subscription went through, in case you clicked past the Apple pop-up too quickly (as I tend to do).&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.lifesum.com/&quot;&gt;Lifesum&lt;/a&gt;, a calorie-counter and meal-planning app, takes a similar approach: “Your journey has begun”. Simple, warm, and focused on the outcome rather than the features. That small moment matters more than you might think, especially for someone on a trial who could still talk themselves out of it.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;432&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-51-1024x432.png&quot; alt=&quot;&quot; class=&quot;wp-image-53650&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-51-1024x432.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-51-300x127.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-51-768x324.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-51-50x21.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-51-95x40.png 95w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-51-696x294.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-51-560x236.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-51-840x355.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-51-80x34.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-51-48x20.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-51.png 1255w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;That little moment of “You made the right choice, here’s what’s ahead” can do a lot of heavy lifting. It’s the same as a salesperson in a store saying, “All set — enjoy!”&lt;/p&gt;



&lt;p&gt;You can take it even further by reminding users of their original reason for signing up (their &lt;a href=&quot;https://www.revenuecat.com/blog/growth/what-drives-users-to-pay-jobs-to-be-done/&quot;&gt;Job to be Done&lt;/a&gt;) to &lt;strong&gt;reassure them and reinforce why they’re here&lt;/strong&gt;. It’s such a simple screen, and not a huge effort to implement, which is why I think this should be the minimum standard for any app.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-level-3-celebrate-the-moment&quot;&gt;&lt;strong&gt;Level 3: celebrate the moment&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Now we can do even better. Be the store employee who doesn’t just say, “You’re all set,” but adds a little enthusiasm: “I have that shirt too” or “Those shorts have been so popular, I love them”. The tiny extra phrase that &lt;strong&gt;makes you feel good about your purchase&lt;/strong&gt; (and less guilty about spending money when you swore off clothes shopping for the month… ahem, not talking about me here).&lt;/p&gt;



&lt;p&gt;In-app, you can take the same approach: make the post-purchase screen feel like a genuine celebration. Not cringe or over-the-top, but a moment that acknowledges they made a good decision, and this is something worth celebrating.&lt;/p&gt;



&lt;p&gt;This is what &lt;a href=&quot;https://www.duolingo.com/&quot;&gt;Duolingo&lt;/a&gt; does. When I first explored this topic with Rosie, she mentioned their celebratory animation, which quickly makes you feel good about the decision you just made.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;787&quot; height=&quot;552&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-47.png&quot; alt=&quot;&quot; class=&quot;wp-image-53642&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-47.png 787w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-47-300x210.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-47-768x539.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-47-50x35.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-47-57x40.png 57w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-47-662x464.png 662w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-47-696x488.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-47-560x393.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-47-422x296.png 422w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-47-673x472.png 673w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-47-80x56.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-47-48x34.png 48w&quot; sizes=&quot;auto, (max-width: 787px) 100vw, 787px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;I mean, we rarely see that owl so happy — it’s nice to see.&lt;/p&gt;



&lt;p&gt;Animations are a great way to spark that energy. Take &lt;a href=&quot;https://pages.kitchenstories.com/en/app&quot;&gt;Kitchen Stories&lt;/a&gt;, a recipe app: their fun confetti screen welcomes you with, “You can now start using Kitchen Stories Plus!” It could be a bit clearer about exactly what’s included in Plus, but the moment of celebration is there, and it works. (And there is confetti, who doesn’t love a bit of confetti.)&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;431&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-44-1024x431.png&quot; alt=&quot;&quot; class=&quot;wp-image-53636&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-44-1024x431.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-44-300x126.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-44-768x324.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-44-50x21.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-44-95x40.png 95w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-44-696x293.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-44-560x236.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-44-840x354.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-44-80x34.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-44-48x20.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-44.png 1125w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-level-4-remind-them-what-they-re-actually-getting&quot;&gt;&lt;strong&gt;Level 4: remind them what they’re actually getting&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Here’s something app teams do too quickly: assuming users remember what’s included in the plan they just upgraded to. Spoiler: they don’t. Especially on a trial, where part of the decision might have been, “Well, I can always cancel”.&lt;/p&gt;



&lt;p&gt;It’s like making a big order at a restaurant; it’s nice when the waiter repeats it back to you, reassuring you they’ve captured your order. The same applies here. Especially if the upgrade came through a feature-specific paywall, users might not even know all the premium features they now have access to.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Use the post-purchase screen to remind the user of their purchase&lt;/strong&gt;. It provides clarity, removes nerves, and also reminds them of all the great features now available.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.alltrails.com/&quot;&gt;AllTrails&lt;/a&gt;, the hike, bike, and run app, does this really well for their Peak subscription. First, there’s a simple animation welcoming you. Then, after suggesting push notifications, they clearly list everything included in the plan.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;For users who were previously on Plus, they even reassure you that you’re still getting all the Plus features too.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;434&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-38-1024x434.png&quot; alt=&quot;&quot; class=&quot;wp-image-53624&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-38-1024x434.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-38-300x127.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-38-768x326.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-38-50x21.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-38-94x40.png 94w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-38-696x295.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-38-560x237.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-38-840x356.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-38-80x34.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-38-48x20.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-38.png 1264w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1009&quot; height=&quot;537&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-46.png&quot; alt=&quot;&quot; class=&quot;wp-image-53639&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-46.png 1009w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-46-300x160.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-46-768x409.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-46-50x27.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-46-75x40.png 75w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-46-696x370.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-46-560x298.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-46-556x296.png 556w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-46-840x447.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-46-80x43.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-46-48x26.png 48w&quot; sizes=&quot;auto, (max-width: 1009px) 100vw, 1009px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;That prompt to enable push notifications, with a clear explanation like “We’ll remind you before your trial ends”, is also a clever way to tackle Day 0 cancellations. It’s a double win: you get permission to send notifications, and the user feels less anxious about forgetting to cancel if they want to — &lt;strong&gt;preventing the pre-emptive trial cancellation&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;This point about notifications is worth dwelling on. You can promise users reminders upfront, but if they haven’t enabled notifications yet, that promise doesn’t land. The post-purchase screen is the perfect moment to set this up, in context, when the reason is obvious, and the value is immediate.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-level-5-highlight-what-you-ll-help-them-achieve-nbsp&quot;&gt;&lt;strong&gt;Level 5: highlight what you’ll help them achieve&amp;nbsp;&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;&lt;a href=&quot;https://www.beside.com/&quot;&gt;Beside&lt;/a&gt;, an AI receptionist app does this particularly well. It congratulates you on starting your trial, then immediately &lt;strong&gt;reminds you of the outcome you’re here for&lt;/strong&gt;: your clients will get instant answers, and you’ll get time back. &lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1006&quot; height=&quot;531&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-56.png&quot; alt=&quot;&quot; class=&quot;wp-image-53664&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-56.png 1006w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-56-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-56-768x405.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-56-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-56-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-56-696x367.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-56-560x296.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-56-840x443.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-56-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-56-48x25.png 48w&quot; sizes=&quot;auto, (max-width: 1006px) 100vw, 1006px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;It also backs that up with three concrete stats:&amp;nbsp;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;100% of business calls answered&lt;/li&gt;



&lt;li&gt;80% of inquiries handled automatically&lt;/li&gt;



&lt;li&gt;30% more bookings&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;You haven’t even opened the app properly yet, and you’re already thinking about results, instead of fighting buyer’s remorse and wondering whether to cancel.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.makeheadway.com/&quot;&gt;Headway&lt;/a&gt;, the bitesized book summaries and personal growth app, is one of my favorites here. It combines the celebratory approach from earlier with a satisfying star animation: “Congrats! Now you are a member of Headway Premium, together with 1.7 million learners.”&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1007&quot; height=&quot;532&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-39.png&quot; alt=&quot;&quot; class=&quot;wp-image-53626&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-39.png 1007w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-39-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-39-768x406.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-39-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-39-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-39-696x368.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-39-560x296.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-39-840x444.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-39-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-39-48x25.png 48w&quot; sizes=&quot;auto, (max-width: 1007px) 100vw, 1007px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;That &lt;strong&gt;community framing&lt;/strong&gt; is smart. It immediately signals that this isn’t some scrappy app you should second-guess. 1.7 million people made the same choice you just did.&lt;/p&gt;



&lt;p&gt;We often assume that because someone signed up for a trial or subscribed, they already trust us. But really, they’ve only trusted us enough to make that first purchase (that’s &lt;em&gt;free&lt;/em&gt;!). The post-purchase screen is your chance to &lt;strong&gt;keep building that trust&lt;/strong&gt;, step by step.&lt;/p&gt;



&lt;p&gt;Then it reframes the moment around the &lt;a href=&quot;https://www.revenuecat.com/blog/growth/what-drives-users-to-pay-jobs-to-be-done/&quot;&gt;Job to Be Done&lt;/a&gt;: “It’s Day 1 of your self-growth journey”. That’s more than a confirmation, it’s a feeling of excited expectation. This is a new me. I’ll finally stop doomscrolling Instagram and start learning!&lt;/p&gt;



&lt;p&gt;Headway reinforces this by &lt;strong&gt;focusing on outcomes&lt;/strong&gt; — grow your productivity, get daily motivation, improve your soft skills — rather than just listing features. It’s about making the user feel the value they just unlocked.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-level-6-give-them-a-clear-next-step&quot;&gt;&lt;strong&gt;Level 6: give them a clear next step&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;For some apps, the biggest barrier after subscribing isn’t doubt, it’s paralysis. Where do I start? What should I do first? If your app has a lot of content or options, that first decision can feel overwhelming enough to make someone close it entirely.&lt;/p&gt;



&lt;p&gt;Now you &lt;em&gt;don’t&lt;/em&gt; want to hit users with ten questions right after purchase — I don’t know about you, but when that happens, I just blank or pick the first thing that comes to mind.&lt;/p&gt;



&lt;p&gt;The solution isn’t &lt;em&gt;more information&lt;/em&gt;, it’s &lt;strong&gt;fewer choices&lt;/strong&gt;. &lt;a href=&quot;https://www.greg.app/&quot;&gt;Greg&lt;/a&gt;, a plant care app, handles this brilliantly. The post-purchase screen gives you one job: start adding your plants. Take a photo or upload one. No menus to navigate, no features to explore, no extra decisions. Just &lt;strong&gt;one clear first step that gets you using the product immediately&lt;/strong&gt;.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;431&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-48-1024x431.png&quot; alt=&quot;&quot; class=&quot;wp-image-53644&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-48-1024x431.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-48-300x126.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-48-768x323.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-48-50x21.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-48-95x40.png 95w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-48-696x293.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-48-560x236.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-48-840x354.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-48-80x34.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-48-48x20.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-48.png 1121w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;I had a similar experience with &lt;a href=&quot;https://www.picnic.photos/&quot;&gt;Picnic&lt;/a&gt;, a photo-organizing app. The moment I subscribed, it took me straight to a folder of my 2017 photos and had me swipe left or right to decide what to keep — Tinder-style.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;As someone who hasn’t used a dating app in ten years, I got to enjoy the fun of swiping again. Once I finished that folder, the app celebrated how much space I’d freed up and let me delete the photos. Then I could move to the next folder at my own pace, making the process clear, fun, and completely manageable.&lt;/p&gt;



&lt;figure class=&quot;wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex&quot;&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;473&quot; height=&quot;1024&quot; data-id=&quot;53646&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-49-473x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-53646&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-49-473x1024.png 473w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-49-138x300.png 138w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-49-768x1664.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-49-709x1536.png 709w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-49-23x50.png 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-49-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-49-214x464.png 214w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-49-696x1508.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-49-258x560.png 258w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-49-137x296.png 137w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-49-218x472.png 218w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-49-37x80.png 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-49-22x48.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-49.png 945w&quot; sizes=&quot;auto, (max-width: 473px) 100vw, 473px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;473&quot; height=&quot;1024&quot; data-id=&quot;53654&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-53-473x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-53654&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-53-473x1024.png 473w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-53-138x300.png 138w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-53-768x1664.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-53-709x1536.png 709w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-53-23x50.png 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-53-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-53-214x464.png 214w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-53-696x1508.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-53-258x560.png 258w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-53-137x296.png 137w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-53-218x472.png 218w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-53-37x80.png 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-53-22x48.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-53.png 945w&quot; sizes=&quot;auto, (max-width: 473px) 100vw, 473px&quot;&gt;&lt;/figure&gt;
&lt;/figure&gt;



&lt;p&gt;What that did (and I don’t think it was accidental) was make me feel immediate progress. I wasn’t thinking about whether the weekly subscription was worth it; I was busy clearing out my 2017 camera roll. By the time I came up for air, I was already invested, and honestly, it was kind of fun sifting through years of photos.&lt;/p&gt;



&lt;p&gt;Another approach is to provide a &lt;strong&gt;brief instruction on what to do next&lt;/strong&gt;. After the celebratory owl, this is exactly what Duolingo does: a simple, clear set of steps showing how the app works and what to do first:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;539&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-50-1024x539.png&quot; alt=&quot;&quot; class=&quot;wp-image-53648&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-50-1024x539.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-50-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-50-768x404.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-50-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-50-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-50-696x367.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-50-560x296.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-50-840x442.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-50-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-50-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-50.png 1069w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;While many apps include this guidance in their onboarding — and yes, &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps/&quot;&gt;most users will see it on Day 0&lt;/a&gt; — for anyone signing up later, it’s a helpful reminder of what they’ll get and how it works.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-alternative-post-purchase-onboarding-strategies&quot;&gt;&lt;strong&gt;Alternative post-purchase onboarding strategies&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Now we’ve covered the six levels of app aftercare, let’s push it just a little further. Depending on your app, you can also use this moment to encourage users to create an account or present a subtle upsell, making the post-purchase screen do double duty.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-push-for-the-account-setup&quot;&gt;&lt;strong&gt;1. Push for the account setup&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;If account creation is important to your app — for saving progress, personalizing the experience, or staying in touch — and you haven’t already collected it, the post-purchase screen is a good moment to ask for account creation. Not perfect, sure — ideally, you’d have it earlier, but better late than never.&lt;/p&gt;



&lt;p&gt;The key is &lt;strong&gt;giving users a real reason to hand over their details right now&lt;/strong&gt;. Not “create an account to continue” (that feels like a gate), but motivation to pass over that info. Back to our shop example: if setting up an account comes with a perk, like 10% off, we’re much more likely to go for it.&lt;/p&gt;



&lt;p&gt;Alan Mind, a previous CBT-guided journaling app, does this well: “Save your progress and secure your journal”. That’s a reason that actually matters to the user, showing that their data and privacy are safe.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;894&quot; height=&quot;477&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-43.png&quot; alt=&quot;&quot; class=&quot;wp-image-53633&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-43.png 894w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-43-300x160.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-43-768x410.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-43-50x27.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-43-75x40.png 75w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-43-696x371.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-43-560x299.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-43-555x296.png 555w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-43-840x448.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-43-80x43.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-43-48x26.png 48w&quot; sizes=&quot;auto, (max-width: 894px) 100vw, 894px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;What would make this even better is offering frictionless sign-up options, like Apple or Google. It removes effort at exactly the moment users are least motivated to fill out forms.&amp;nbsp;&amp;nbsp;&lt;/p&gt;



&lt;p&gt;As it stands, it’s not entirely clear what the password requirements are either, which can make this step feel unnecessarily clunky, and that’s the last thing you want right after someone has just subscribed.&lt;/p&gt;



&lt;p&gt;Calm, the meditation app approaches this a bit better:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1017&quot; height=&quot;534&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-57.png&quot; alt=&quot;&quot; class=&quot;wp-image-53666&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-57.png 1017w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-57-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-57-768x403.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-57-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-57-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-57-696x365.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-57-560x294.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-57-840x441.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-57-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-57-48x25.png 48w&quot; sizes=&quot;auto, (max-width: 1017px) 100vw, 1017px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Post-purchase, you get a &lt;a href=&quot;https://www.revenuecat.com/blog/growth/how-did-you-hear-about-us-surveys/&quot;&gt;&lt;em&gt;how did you hear about us &lt;/em&gt;survey&lt;/a&gt;, and are then encouraged to sign up for an account to track progress.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-go-for-the-upsell&quot;&gt;&lt;strong&gt;2. Go for the upsell&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;One final option — and one to use carefully — is leveraging the post-purchase high to push for a longer commitment or additional purchase. This tends to show up more in larger, well-known apps that are focused on increasing &lt;a href=&quot;https://www.revenuecat.com/blog/growth/what-is-lifetime-value-ltv-apps/&quot;&gt;realized LTV&lt;/a&gt; per paying customer.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://flo.health/&quot;&gt;Flo&lt;/a&gt;, a cycle-tracking and women’s health app, does this with confidence. After congratulating you on starting Flo Premium, it presents a ‘gift’, which turns out to be a &lt;a href=&quot;https://www.revenuecat.com/blog/growth/lifetime-subscriptions/&quot;&gt;44% lifetime discount&lt;/a&gt; on an &lt;a href=&quot;https://www.revenuecat.com/blog/growth/annual-subscriptions-apps-pros-cons/&quot;&gt;annual subscription&lt;/a&gt;.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;358&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-45-1024x358.png&quot; alt=&quot;&quot; class=&quot;wp-image-53638&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-45-1024x358.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-45-300x105.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-45-768x269.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-45-50x18.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-45-114x40.png 114w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-45-696x244.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-45-560x196.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-45-840x294.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-45-80x28.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-45-48x17.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-45.png 1514w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The framing is smart: it’s positioned as a gift, not a sales pitch. And by locking in annual subscribers at the moment of highest trust, they’re tackling both trial drop-off and long-term churn in one move.&lt;/p&gt;



&lt;p&gt;Headway takes a slightly different approach. After the celebratory screen, they offer a one-time deal on a Self-Reflection Ebook at a discounted price. &lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1006&quot; height=&quot;527&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-58.png&quot; alt=&quot;&quot; class=&quot;wp-image-53668&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-58.png 1006w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-58-300x157.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-58-768x402.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-58-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-58-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-58-696x365.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-58-560x293.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-58-840x440.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-58-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-58-48x25.png 48w&quot; sizes=&quot;auto, (max-width: 1006px) 100vw, 1006px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;This is a more classic upsell moment, the kind you’d usually see in e-commerce. You’re already in a ‘yes’ mindset, trust is high, and a complementary product can feel genuinely helpful rather than pushy.&lt;/p&gt;



&lt;p&gt;That said, sequencing matters. Focus on getting the basics right first, making sure users feel good about what they’ve just committed to, and only then, ask for more.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-to-build-your-first-post-purchase-screen&quot;&gt;&lt;strong&gt;How to build your first post-purchase screen&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Getting started is easy. If you’re currently at Level 1, don’t try to jump straight to Level 5, as tempting as it is. Start with Level 2. It’s a single screen you can ship in a sprint: acknowledge what just happened, remind users why they signed up, and make them feel good about it. That alone puts you ahead of most apps.&lt;/p&gt;



&lt;p&gt;Once that’s live, start layering in improvements. Add a celebratory moment or a clear first step, depending on what your app needs. If your product has a lot of content and users tend to feel overwhelmed, prioritize a clear next step or simple instructions (like Duolingo). If your product is simple but the commitment feels big (like Headway), lean into celebration and reassurance.&lt;/p&gt;



&lt;p&gt;The main &lt;a href=&quot;https://www.revenuecat.com/blog/growth/activation-metrics/&quot;&gt;metrics to watch&lt;/a&gt; are your &lt;strong&gt;Day 0 and Day 1 cancellation rates&lt;/strong&gt;. Track before and after launching the new screen to measure impact. If you offer a &lt;a href=&quot;https://www.revenuecat.com/blog/growth/7-day-trial-subscription-app/&quot;&gt;free trial&lt;/a&gt;, also monitor your trial-to-paid conversion rate, especially if you’ve added things like push notification opt-ins or feature reminders (like AllTrails has).&lt;/p&gt;



&lt;p&gt;If you go down the upsell route, focus on realized LTV and retention, not just the conversion rate on that single offer. A pushy upsell that damages trust will cost you far more in churn than it generates in upgrades.&lt;/p&gt;



&lt;p&gt;Because ultimately, the goal isn’t to optimize the post-purchase screen in isolation, it’s to &lt;strong&gt;get the moment after someone subscribes &lt;/strong&gt;&lt;strong&gt;&lt;em&gt;right&lt;/em&gt;&lt;/strong&gt;, because that sets the tone for the entire relationship.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-don-t-skip-this-onboarding-moment&quot;&gt;&lt;strong&gt;Don’t skip this onboarding moment&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;There are many ways to approach the post-purchase screen, and not every approach will fit every app. But the one thing I’d strongly push back on is doing nothing, dropping users straight into the app, and hoping they figure it out.&lt;/p&gt;



&lt;p&gt;At a minimum, give users clarity on what they’ve just subscribed to. Add a moment of celebration, a clear next step, or a reminder of the outcome they’re working towards. These aren’t big product investments, but they can make a real difference to those Day 0 cancellation numbers.&lt;/p&gt;



&lt;p&gt;You’ve already done the hard work of earning someone’s trust to the point that they’re willing to subscribe. Don’t stop guiding them the moment they do.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Compose Multiplatform subscriptions: single codebase for iOS and Android]]></title><description><![CDATA[This article walks through building a Kotlin Multiplatform app with the RevenueCat KMP SDK, covering setup, purchases, entitlement gating, and server-driven paywalls using the official cat-paywalls-kmp demo structure.]]></description><link>https://www.revenuecat.com/blog/engineering/cmp-subscriptions/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/cmp-subscriptions/</guid><pubDate>Thu, 30 Apr 2026 01:40:16 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Blog-56_Compose-Multiplatform-Subscriptions.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;You ship a subscription app on Android and your team starts the iOS port. Suddenly you are maintaining two paywall implementations for Android and iOS, two billing integrations, and two sets of receipt verification code with different APIs and different bugs. RevenueCat’s&amp;nbsp;&lt;a href=&quot;https://github.com/RevenueCat/purchases-kmp&quot;&gt;purchases-kmp SDK&lt;/a&gt;&amp;nbsp;collapses that duplication. You write your subscription logic once in&amp;nbsp;&lt;code&gt;commonMain&lt;/code&gt;, the SDK wraps Google Play Billing on Android and StoreKit on iOS, and a Compose Multiplatform paywall component renders the same UI on both platforms.&lt;/p&gt;



&lt;p&gt;In this article, you’ll set up a Kotlin Multiplatform project with the RevenueCat KMP SDK, configure dashboard products and entitlements, initialize Purchases on Android and iOS, gate premium content from common code, run an in app purchase from&amp;nbsp;&lt;code&gt;commonMain&lt;/code&gt;, and drop in a server driven paywall built with the dashboard’s Paywall Editor. You’ll work directly with the same source layout used by&amp;nbsp;&lt;a href=&quot;https://github.com/RevenueCat/cat-paywalls-kmp&quot;&gt;cat-paywalls-kmp&lt;/a&gt;, the official KMP demo app.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-you-ll-build&quot;&gt;&lt;strong&gt;What you’ll build&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;You’ll end up with a Compose Multiplatform app that lists premium articles, fades the body until the user is entitled, opens a server driven paywall, runs the purchase through the platform native dialog, and refreshes the entitlement state. The same screen runs on both iPhone and a Pixel without a single line of duplicated UI code.&lt;/p&gt;



&lt;p&gt;The repository structure is a normal multi module KMP project: a&amp;nbsp;&lt;code&gt;composeApp&lt;/code&gt;&amp;nbsp;module with&amp;nbsp;&lt;code&gt;commonMain&lt;/code&gt;,&amp;nbsp;&lt;code&gt;androidMain&lt;/code&gt;, and&amp;nbsp;&lt;code&gt;iosMain&lt;/code&gt;&amp;nbsp;source sets, a few&amp;nbsp;&lt;code&gt;feature&lt;/code&gt;&amp;nbsp;modules (home, article, paywalls, subscriptions), and&amp;nbsp;&lt;code&gt;core&lt;/code&gt;&amp;nbsp;modules for data, network, and design system. Every line of subscription logic in this tutorial lives in&amp;nbsp;&lt;code&gt;commonMain&lt;/code&gt;.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-single-codebase-changes-the-math&quot;&gt;&lt;strong&gt;Why single codebase changes the math&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Building cross-platform subscriptions without a shared SDK means writing every subscription concept twice. You query Google Play with&amp;nbsp;&lt;code&gt;BillingClient&lt;/code&gt;&amp;nbsp;and a purchase token, and you query StoreKit with&amp;nbsp;&lt;code&gt;Product.products(for:)&lt;/code&gt;&amp;nbsp;and a signed JWS. You verify receipts with two completely separate server APIs, store them in two different shapes, and reconcile them with a backend mapping layer. None of this work is the part of your product that users care about.&lt;/p&gt;



&lt;p&gt;The RevenueCat KMP SDK gives you four shared concepts that hide all of that:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Offerings&lt;/strong&gt;&amp;nbsp;are the set of products you currently sell, configured in the dashboard rather than in your app.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Packages&lt;/strong&gt;&amp;nbsp;are the buyable units inside an offering (monthly, annual, lifetime).&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Entitlements&lt;/strong&gt;&amp;nbsp;are the access levels your app cares about (&lt;code&gt;premium&lt;/code&gt;,&amp;nbsp;&lt;code&gt;pro&lt;/code&gt;,&amp;nbsp;&lt;code&gt;family&lt;/code&gt;), independent of which store the user paid through.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;CustomerInfo&lt;/strong&gt;&amp;nbsp;is a single object that aggregates every active entitlement for the current user, regardless of platform.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Once you have these four objects, your app stops asking “did this user buy through Google Play or App Store?” and starts asking “is&amp;nbsp;&lt;code&gt;customerInfo.entitlements[&quot;premium&quot;]&lt;/code&gt;&amp;nbsp;active?” That single property check works the same on iOS and Android.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;prerequisites-and-dashboard-setup&quot;&gt;&lt;strong&gt;Prerequisites and dashboard setup&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Before any code, you’ll set up four things in the&amp;nbsp;&lt;a href=&quot;https://app.revenuecat.com/&quot;&gt;RevenueCat dashboard&lt;/a&gt;:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;A&amp;nbsp;&lt;strong&gt;project&lt;/strong&gt;&amp;nbsp;with one Android app and one iOS app, each linked to its store credentials.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Products&lt;/strong&gt;&amp;nbsp;imported from Google Play Console and App Store Connect.&lt;/li&gt;



&lt;li&gt;An&amp;nbsp;&lt;strong&gt;entitlement&lt;/strong&gt;&amp;nbsp;named&amp;nbsp;&lt;code&gt;premium&lt;/code&gt;&amp;nbsp;(or whatever identifier you prefer).&lt;/li&gt;



&lt;li&gt;An&amp;nbsp;&lt;strong&gt;offering&lt;/strong&gt;&amp;nbsp;with one or more packages attached, marked as the current offering.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Two codelabs walk through the dashboard side end to end. If you have not configured products yet, go through them first:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://revenuecat.github.io/codelabs/google-play.html&quot;&gt;RevenueCat Google Play Integration&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://revenuecat.github.io/codelabs/app-store.html&quot;&gt;RevenueCat App Store Integration&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The two important screens to land on are the entitlement and the offering. The entitlement is the unit your app code checks:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;282&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/dashboard-entitlement-1024x282.png&quot; alt=&quot;&quot; class=&quot;wp-image-53537&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/dashboard-entitlement-1024x282.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/dashboard-entitlement-300x83.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/dashboard-entitlement-768x211.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/dashboard-entitlement-1536x423.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/dashboard-entitlement-2048x564.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/dashboard-entitlement-50x14.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/dashboard-entitlement-125x34.png 125w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/dashboard-entitlement-696x192.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/dashboard-entitlement-560x154.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/dashboard-entitlement-840x231.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/dashboard-entitlement-80x22.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/dashboard-entitlement-48x13.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The offering is what your app fetches at runtime. It bundles the packages you want this version of the app to display, and you can change its contents without shipping a new build:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;323&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/dashboard-offering-1024x323.png&quot; alt=&quot;&quot; class=&quot;wp-image-53539&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/dashboard-offering-1024x323.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/dashboard-offering-300x95.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/dashboard-offering-768x242.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/dashboard-offering-50x16.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/dashboard-offering-125x40.png 125w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/dashboard-offering-696x219.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/dashboard-offering-560x177.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/dashboard-offering-840x265.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/dashboard-offering-80x25.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/dashboard-offering-48x15.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/dashboard-offering.png 1462w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;After both apps are set up, copy the public SDK API keys from&amp;nbsp;&lt;strong&gt;Project Settings &amp;gt; API Keys&lt;/strong&gt;. There is one key per platform, and you will use both of them in Step 2.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;step-1-add-the-revenuecat-kmp-sdk&quot;&gt;&lt;strong&gt;Step 1: Add the RevenueCat KMP SDK&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The KMP SDK ships as two artifacts:&amp;nbsp;&lt;code&gt;purchases-kmp-core&lt;/code&gt;&amp;nbsp;for the subscription logic and&amp;nbsp;&lt;code&gt;purchases-kmp-ui&lt;/code&gt;&amp;nbsp;for the Compose Multiplatform paywall component. Both are published to Maven Central with a single version coordinate of the form&amp;nbsp;&lt;code&gt;&amp;lt;sdk&amp;gt;+&amp;lt;hybrid-common&amp;gt;&lt;/code&gt;. The number after the plus sign matters when you link the iOS pod, so do not strip it.&lt;/p&gt;



&lt;p&gt;Start by adding the version and library entries to&amp;nbsp;&lt;code&gt;gradle/libs.versions.toml&lt;/code&gt;:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZMPOUE wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;[versions]\npurchases-kmp = \&amp;quot;2.10.2+17.55.1\&amp;quot;\n\n[libraries]\npurchases-kmp-core = { module = \&amp;quot;com.revenuecat.purchases:purchases-kmp-core\&amp;quot;, version.ref = \&amp;quot;purchases-kmp\&amp;quot; }\npurchases-kmp-ui   = { module = \&amp;quot;com.revenuecat.purchases:purchases-kmp-ui\&amp;quot;,   version.ref = \&amp;quot;purchases-kmp\&amp;quot; }&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Then declare the dependencies inside the&amp;nbsp;&lt;code&gt;commonMain&lt;/code&gt;&amp;nbsp;source set of your app module’s&amp;nbsp;&lt;code&gt;build.gradle.kts&lt;/code&gt;. In the cat-paywalls-kmp demo this lives in&amp;nbsp;&lt;code&gt;composeApp/build.gradle.kts&lt;/code&gt;:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1VPS5L wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;kotlin {\n  sourceSets {\n    commonMain.dependencies {\n      \/\/ RevenueCat\n      implementation(libs.purchases.kmp.core)\n      \/\/ Compose Multiplatform paywall component\n      implementation(libs.purchases.kmp.ui)\n    }\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Notice that both Android and iOS pull the same&amp;nbsp;&lt;code&gt;commonMain&lt;/code&gt;&amp;nbsp;dependency. There is no&amp;nbsp;&lt;code&gt;androidMain.dependencies { implementation(&quot;com.revenuecat...&quot;) }&lt;/code&gt;&amp;nbsp;block. The KMP artifact carries platform specific bindings inside it.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;linking-the-ios-native-framework&quot;&gt;&lt;strong&gt;Linking the iOS native framework&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The KMP SDK depends on&amp;nbsp;&lt;code&gt;PurchasesHybridCommon&lt;/code&gt;, a native iOS framework that wraps StoreKit. The cleanest way to bring it in is through the Kotlin CocoaPods plugin. Apply the plugin to your&amp;nbsp;&lt;code&gt;composeApp&lt;/code&gt;&amp;nbsp;module:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-t5TIi wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;plugins {\n  alias(libs.plugins.kotlin.multiplatform)\n  alias(libs.plugins.compose.multiplatform)\n  alias(libs.plugins.compose.compiler)\n  kotlin(\&amp;quot;native.cocoapods\&amp;quot;)\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Then declare both pods inside the&amp;nbsp;&lt;code&gt;kotlin { cocoapods { ... } }&lt;/code&gt;&amp;nbsp;block. Pin the pod version to the same major as your&amp;nbsp;&lt;code&gt;purchases-kmp&lt;/code&gt;&amp;nbsp;artifact so the Kotlin and Swift sides agree on protocol shapes:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-223DO6 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;kotlin {\n  cocoapods {\n    summary = \&amp;quot;Cat Paywalls KMP App\&amp;quot;\n    homepage = \&amp;quot;&lt;https:\/\/github.com\/revenuecat\/cat-paywalls-kmp&gt;\&amp;quot;\n    version = \&amp;quot;1.0\&amp;quot;\n    ios.deploymentTarget = \&amp;quot;15.0\&amp;quot;\n    podfile = project.file(\&amp;quot;..\/iosApp\/Podfile\&amp;quot;)\n\n    framework {\n      baseName = \&amp;quot;ComposeApp\&amp;quot;\n      isStatic = true\n    }\n\n    pod(\&amp;quot;RevenueCat\&amp;quot;) {\n      version = \&amp;quot;~&gt; 5.21\&amp;quot;\n      extraOpts += listOf(\&amp;quot;-compiler-option\&amp;quot;, \&amp;quot;-fmodules\&amp;quot;)\n    }\n    pod(\&amp;quot;RevenueCatUI\&amp;quot;) {\n      version = \&amp;quot;~&gt; 5.21\&amp;quot;\n      extraOpts += listOf(\&amp;quot;-compiler-option\&amp;quot;, \&amp;quot;-fmodules\&amp;quot;)\n    }\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Run&amp;nbsp;&lt;code&gt;./gradlew podInstall&lt;/code&gt;&amp;nbsp;once. Gradle generates a&amp;nbsp;&lt;code&gt;.podspec&lt;/code&gt;&amp;nbsp;for your shared module and writes a&amp;nbsp;&lt;code&gt;Podfile.lock&lt;/code&gt;&amp;nbsp;next to your iOS app. From now on, opening the iOS workspace in Xcode pulls everything down through CocoaPods.&lt;/p&gt;



&lt;p&gt;The KMP SDK uses Kotlin/Native interop bindings that are still flagged as experimental, so opt in inside any iOS source set that touches them:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-eALma wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;kotlin {\n  sourceSets {\n    all {\n      languageSettings {\n        if (name.startsWith(\&amp;quot;ios\&amp;quot;)) {\n          optIn(\&amp;quot;kotlinx.cinterop.ExperimentalForeignApi\&amp;quot;)\n        }\n      }\n    }\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;That is the entire setup. No platform-specific source files yet. Everything else lives in&amp;nbsp;&lt;code&gt;commonMain&lt;/code&gt;.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;step-2-initialize-purchases-on-each-platform&quot;&gt;&lt;strong&gt;Step 2: Initialize Purchases on each platform&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;&lt;code&gt;Purchases&lt;/code&gt;&amp;nbsp;is a singleton. You configure it once early in the app lifecycle, then every other call goes through&amp;nbsp;&lt;code&gt;Purchases.sharedInstance&lt;/code&gt;. Initialization is the only place where Android and iOS code differ, and only because each platform has its own application entry point.&lt;/p&gt;



&lt;p&gt;On Android, initialize from your&amp;nbsp;&lt;code&gt;Application.onCreate&lt;/code&gt;. The cat-paywalls-kmp demo does this in&amp;nbsp;&lt;code&gt;CatArticlesApplication&lt;/code&gt;:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1YId35 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;class CatArticlesApplication : Application() {\n\n  override fun onCreate() {\n    super.onCreate()\n\n    Purchases.logLevel = LogLevel.DEBUG\n    Purchases.configure(\n      PurchasesConfiguration(apiKey = REVENUECAT_ANDROID_API_KEY) {\n        appUserId = null \/\/ Anonymous user\n      },\n    )\n  }\n\n  companion object {\n    private const val REVENUECAT_ANDROID_API_KEY = \&amp;quot;your_android_api_key\&amp;quot;\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The&amp;nbsp;&lt;code&gt;PurchasesConfiguration(apiKey) { ... }&lt;/code&gt;&amp;nbsp;builder is a small DSL. Inside the trailing lambda you can set&amp;nbsp;&lt;code&gt;appUserId&lt;/code&gt;,&amp;nbsp;&lt;code&gt;purchasesAreCompletedBy&lt;/code&gt;,&amp;nbsp;&lt;code&gt;verificationMode&lt;/code&gt;, and other options. Passing&amp;nbsp;&lt;code&gt;appUserId = null&lt;/code&gt;&amp;nbsp;tells the SDK to generate an anonymous identifier in the form&amp;nbsp;&lt;code&gt;$RCAnonymousID:&amp;lt;uuid&amp;gt;&lt;/code&gt;. When the user later signs in to your backend, you call&amp;nbsp;&lt;code&gt;Purchases.sharedInstance.logIn(userId)&lt;/code&gt;&amp;nbsp;and RevenueCat transfers any purchases to that account.&lt;/p&gt;



&lt;p&gt;Do not forget to register the&amp;nbsp;&lt;code&gt;Application&lt;/code&gt;&amp;nbsp;class and the&amp;nbsp;&lt;code&gt;INTERNET&lt;/code&gt;&amp;nbsp;permission in&amp;nbsp;&lt;code&gt;AndroidManifest.xml&lt;/code&gt;:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z60MIq wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;&lt;application\n    android:name=\&amp;quot;.CatArticlesApplication\&amp;quot;\n    android:label=\&amp;quot;@string\/app_name\&amp;quot;&gt;\n    &lt;activity android:name=\&amp;quot;.MainActivity\&amp;quot; android:exported=\&amp;quot;true\&amp;quot;&gt;\n        &lt;intent-filter&gt;\n            &lt;action android:name=\&amp;quot;android.intent.action.MAIN\&amp;quot; \/&gt;\n            &lt;category android:name=\&amp;quot;android.intent.category.LAUNCHER\&amp;quot; \/&gt;\n        &lt;\/intent-filter&gt;\n    &lt;\/activity&gt;\n&lt;\/application&gt;\n\n&lt;uses-permission android:name=\&amp;quot;android.permission.INTERNET\&amp;quot; \/&gt;&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;On iOS, initialize from your SwiftUI&amp;nbsp;&lt;code&gt;App&lt;/code&gt;&amp;nbsp;struct. You import the native&amp;nbsp;&lt;code&gt;RevenueCat&lt;/code&gt;&amp;nbsp;pod here, not the KMP wrapper, because configuration runs in Swift before the Kotlin runtime starts:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1OLQya wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;swift&quot; content=&quot;&amp;quot;import SwiftUI\nimport RevenueCat\n\n@main\nstruct iosAppApp: App {\n\n    init() {\n        Purchases.logLevel = .debug\n        Purchases.configure(withAPIKey: \&amp;quot;your_ios_api_key\&amp;quot;)\n    }\n\n    var body: some Scene {\n        WindowGroup {\n            ContentView()\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;&lt;code&gt;ContentView&lt;/code&gt;&amp;nbsp;then hosts the shared Compose surface inside a&amp;nbsp;&lt;code&gt;UIViewControllerRepresentable&lt;/code&gt;:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1f0snP wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;swift&quot; content=&quot;&amp;quot;struct ComposeView: UIViewControllerRepresentable {\n    func makeUIViewController(context: Context) -&gt; UIViewController {\n        MainViewControllerKt.MainViewController()\n    }\n\n    func updateUIViewController(_ uiViewController: UIViewController, context: Context) {}\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The Kotlin side of that bridge is a one liner in&amp;nbsp;&lt;code&gt;iosMain&lt;/code&gt;:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1YbxrF wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;swift&quot; content=&quot;&amp;quot;fun MainViewController(): UIViewController {\n  val appGraph = createGraph&lt;AppGraph&gt;()\n  return ComposeUIViewController {\n    App(appGraph = appGraph)\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;&lt;code&gt;App&lt;/code&gt;&amp;nbsp;is the same&amp;nbsp;&lt;code&gt;@Composable&lt;/code&gt;&amp;nbsp;you call from&amp;nbsp;&lt;code&gt;MainActivity&lt;/code&gt;&amp;nbsp;on Android. From this point on, every screen you build runs on both platforms.&lt;/p&gt;



&lt;p&gt;The reason initialization is split is that&amp;nbsp;&lt;code&gt;Purchases.configure&lt;/code&gt;&amp;nbsp;reaches into the platform billing client immediately. On Android it asks&amp;nbsp;&lt;code&gt;BillingClient&lt;/code&gt;&amp;nbsp;to open a connection. On iOS it registers a StoreKit transaction listener. Both need to happen before any Compose composition starts, which is why you do not configure inside&amp;nbsp;&lt;code&gt;commonMain&lt;/code&gt;.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;step-3-check-entitlements-from-common-code&quot;&gt;&lt;strong&gt;Step 3: Check entitlements from common code&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Once&amp;nbsp;&lt;code&gt;Purchases&lt;/code&gt;&amp;nbsp;is configured, you can ask “is the current user entitled to premium?” from anywhere in&amp;nbsp;&lt;code&gt;commonMain&lt;/code&gt;. The KMP SDK exposes coroutine friendly suspend variants of every callback API. The one you want here is&amp;nbsp;&lt;code&gt;awaitCustomerInfo()&lt;/code&gt;:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z29SMCn wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;suspend fun isPremium(): Boolean {\n  val customerInfo = Purchases.sharedInstance.awaitCustomerInfo()\n  return customerInfo.entitlements[\&amp;quot;premium\&amp;quot;]?.isActive == true\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;&lt;code&gt;CustomerInfo.entitlements&lt;/code&gt;&amp;nbsp;is a map keyed by the entitlement identifier you set up in the dashboard. The value is an&amp;nbsp;&lt;code&gt;EntitlementInfo&lt;/code&gt;&amp;nbsp;with an&amp;nbsp;&lt;code&gt;isActive&lt;/code&gt;&amp;nbsp;flag, an&amp;nbsp;&lt;code&gt;expirationDate&lt;/code&gt;, a&amp;nbsp;&lt;code&gt;willRenew&lt;/code&gt;&amp;nbsp;boolean, and a&amp;nbsp;&lt;code&gt;store&lt;/code&gt;&amp;nbsp;enum that tells you which platform the underlying purchase came from. For access decisions, only&amp;nbsp;&lt;code&gt;isActive&lt;/code&gt;&amp;nbsp;matters. The entitlement is active whether the user subscribed through the App Store, Google Play, Stripe, or a promotional grant from your support team.&lt;/p&gt;



&lt;p&gt;Most apps wrap this in a repository so the rest of the app can collect a&amp;nbsp;&lt;code&gt;Flow&lt;/code&gt;&amp;nbsp;and forget about callbacks. The cat-paywalls-kmp demo defines&amp;nbsp;&lt;code&gt;PaywallsRepository&lt;/code&gt;&amp;nbsp;in&amp;nbsp;&lt;code&gt;core/data&lt;/code&gt;:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZwDhuu wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;interface PaywallsRepository {\n  fun fetchOffering(): Flow&lt;Result&lt;Offering&gt;&gt;\n  fun fetchCustomerInfo(): Flow&lt;Result&lt;CustomerInfo&gt;&gt;\n  fun awaitPurchase(packageId: String): Flow&lt;Result&lt;StoreTransaction&gt;&gt;\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The&amp;nbsp;&lt;code&gt;fetchCustomerInfo&lt;/code&gt;&amp;nbsp;implementation is a thin Flow wrapper around the SDK call, with&amp;nbsp;&lt;code&gt;Dispatchers.IO&lt;/code&gt;&amp;nbsp;to keep network work off the main thread:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1HNuTF wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;override fun fetchCustomerInfo(): Flow&lt;Result&lt;CustomerInfo&gt;&gt; = flow {\n  try {\n    val customerInfo = Purchases.sharedInstance.awaitCustomerInfo()\n    emit(Result.success(customerInfo))\n  } catch (e: Exception) {\n    emit(Result.failure(e))\n  }\n}.flowOn(Dispatchers.IO)&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;A ViewModel collects this flow and exposes a&amp;nbsp;&lt;code&gt;StateFlow&amp;lt;CustomerInfo?&amp;gt;&lt;/code&gt;:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-12b2PB wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;class CatArticlesDetailViewModel(\n  articleId: Long,\n  articlesRepository: ArticlesRepository,\n  paywallsRepository: PaywallsRepository,\n) : ViewModel() {\n\n  val customerInfo: StateFlow&lt;CustomerInfo?&gt; =\n    paywallsRepository.fetchCustomerInfo()\n      .map { it.getOrNull() }\n      .stateIn(\n        scope = viewModelScope,\n        started = SharingStarted.WhileSubscribed(5000),\n        initialValue = null,\n      )\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The Compose Multiplatform UI then reads it like any other state and decides whether to render the article body or fade it behind a paywall prompt:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-9N6HQ wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;private const val ENTITLEMENT_PREMIUM = \&amp;quot;premium\&amp;quot;\n\n@Composable\nprivate fun CatArticlesDetailContent(\n  article: Article,\n  viewModel: CatArticlesDetailViewModel,\n  navigateToPaywalls: () -&gt; Unit,\n) {\n  val customerInfo by viewModel.customerInfo.collectAsState()\n  val isEntitled = customerInfo?.entitlements?.get(ENTITLEMENT_PREMIUM)?.isActive == true\n\n  DetailsContent(\n    article = article,\n    onJoinClicked = navigateToPaywalls,\n    isEntitled = isEntitled,\n  )\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;&lt;code&gt;DetailsContent&lt;/code&gt;&amp;nbsp;applies a&amp;nbsp;&lt;code&gt;fadingEdge&lt;/code&gt;&amp;nbsp;modifier when&amp;nbsp;&lt;code&gt;isEntitled&lt;/code&gt;&amp;nbsp;is false. Subscribed users see the article through to the end. Free users see the first few paragraphs fade into a “Join Now” CTA. The same composable runs on both iOS and Android.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;step-4-run-a-purchase-from-commonmain&quot;&gt;&lt;strong&gt;Step 4: Run a purchase from&amp;nbsp;&lt;code&gt;commonMain&lt;/code&gt;&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Triggering a purchase is two suspend calls: fetch the current offering, then call&amp;nbsp;&lt;code&gt;awaitPurchase&lt;/code&gt;&amp;nbsp;with one of its packages. The SDK takes care of opening Google Play’s billing dialog or StoreKit’s purchase sheet, validating the receipt with the store, and posting it to RevenueCat for tracking.&lt;/p&gt;



&lt;p&gt;The&amp;nbsp;&lt;code&gt;awaitPurchase&lt;/code&gt;&amp;nbsp;helper from&amp;nbsp;&lt;code&gt;purchases-kmp-core&lt;/code&gt;&amp;nbsp;accepts a&amp;nbsp;&lt;code&gt;Package&lt;/code&gt;:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-dMbUU wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;suspend fun purchaseMonthly() {\n  val offerings = Purchases.sharedInstance.awaitOfferings()\n  val current = offerings.current ?: error(\&amp;quot;No current offering configured\&amp;quot;)\n\n  val monthly = current.monthly\n    ?: current.availablePackages.first()\n\n  val transaction = Purchases.sharedInstance.awaitPurchase(monthly)\n\n  \/\/ The SDK has already verified the receipt and updated CustomerInfo.\n  \/\/ Your existing customerInfo flow will emit the new state on its own.\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;&lt;code&gt;Offering&lt;/code&gt;&amp;nbsp;exposes convenience accessors for common cadences (&lt;code&gt;monthly&lt;/code&gt;,&amp;nbsp;&lt;code&gt;annual&lt;/code&gt;,&amp;nbsp;&lt;code&gt;lifetime&lt;/code&gt;) and a generic&amp;nbsp;&lt;code&gt;availablePackages: List&amp;lt;Package&amp;gt;&lt;/code&gt;&amp;nbsp;if you want to build a custom plan picker. The cat-paywalls-kmp demo wraps this in&amp;nbsp;&lt;code&gt;PaywallsRepository.awaitPurchase(packageId)&lt;/code&gt;:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-2cIvVe wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;override fun awaitPurchase(packageId: String): Flow&lt;Result&lt;StoreTransaction&gt;&gt; = flow {\n  try {\n    val offerings = Purchases.sharedInstance.awaitOfferings()\n    val pkg = offerings.current?.availablePackages?.find { it.identifier == packageId }\n      ?: error(\&amp;quot;Package not found: $packageId\&amp;quot;)\n\n    val transaction = Purchases.sharedInstance.awaitPurchase(pkg)\n    emit(Result.success(transaction))\n  } catch (e: Exception) {\n    emit(Result.failure(e))\n  }\n}.flowOn(Dispatchers.IO)&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Two things to know about the return value. First, the&amp;nbsp;&lt;code&gt;StoreTransaction&lt;/code&gt;&amp;nbsp;is informational only. The receipt has already been validated server side by the time&amp;nbsp;&lt;code&gt;awaitPurchase&lt;/code&gt;&amp;nbsp;resumes, and the user’s&amp;nbsp;&lt;code&gt;CustomerInfo&lt;/code&gt;&amp;nbsp;has been updated on RevenueCat’s backend. Second, the next call to&amp;nbsp;&lt;code&gt;awaitCustomerInfo()&lt;/code&gt;&amp;nbsp;will reflect the new entitlement, which means any UI bound to your&amp;nbsp;&lt;code&gt;customerInfo&lt;/code&gt;&amp;nbsp;flow recomposes automatically. You do not need to manually invalidate state.&lt;/p&gt;



&lt;p&gt;If the user cancels the dialog, the SDK throws a&amp;nbsp;&lt;code&gt;PurchasesException&lt;/code&gt;&amp;nbsp;whose&amp;nbsp;&lt;code&gt;code&lt;/code&gt;&amp;nbsp;is&amp;nbsp;&lt;code&gt;PurchaseCancelled&lt;/code&gt;. Catch it and treat it as a no op rather than an error.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;step-5-drop-in-a-server-driven-paywall&quot;&gt;&lt;strong&gt;Step 5: Drop in a server driven paywall&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;You could build the package picker yourself, but RevenueCat’s Paywall Editor lets you design the entire screen in the dashboard and update it without shipping a new build. The&amp;nbsp;&lt;code&gt;purchases-kmp-ui&lt;/code&gt;&amp;nbsp;artifact includes a&amp;nbsp;&lt;code&gt;Paywall&lt;/code&gt;&amp;nbsp;composable that renders the configured paywall on both Android and iOS.&lt;/p&gt;



&lt;p&gt;You design the paywall in the dashboard’s visual editor:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;735&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/paywall-editor-1024x735.gif&quot; alt=&quot;&quot; class=&quot;wp-image-53541&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/paywall-editor-1024x735.gif 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/paywall-editor-300x215.gif 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/paywall-editor-768x552.gif 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/paywall-editor-1536x1103.gif 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/paywall-editor-50x36.gif 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/paywall-editor-56x40.gif 56w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/paywall-editor-646x464.gif 646w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/paywall-editor-696x500.gif 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/paywall-editor-560x402.gif 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/paywall-editor-412x296.gif 412w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/paywall-editor-657x472.gif 657w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/paywall-editor-80x57.gif 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/paywall-editor-48x34.gif 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;In your KMP code, the entire paywall screen is one&amp;nbsp;&lt;code&gt;Paywall&lt;/code&gt;&amp;nbsp;call. The cat-paywalls-kmp demo lives in&amp;nbsp;&lt;code&gt;feature/paywalls/CatCustomPaywalls.kt&lt;/code&gt;:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-BVPTm wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Composable\nfun CatCustomPaywalls() {\n  val composeNavigator = currentComposeNavigator\n\n  Box(\n    modifier = Modifier\n      .fillMaxSize()\n      .background(Color.White),\n  ) {\n    Paywall(\n      options = PaywallOptions(\n        dismissRequest = { composeNavigator.navigateUp() },\n      ),\n    )\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;&lt;code&gt;PaywallOptions&lt;/code&gt;&amp;nbsp;is where you pass callbacks for dismissal, purchase completion, and restore. With no offering passed, the component renders the&amp;nbsp;&lt;strong&gt;current offering&lt;/strong&gt;&amp;nbsp;assigned to the user in the dashboard. If you are running an A/B test, RevenueCat picks the variant for this user automatically and attributes any conversion to the right experiment arm.&lt;/p&gt;



&lt;p&gt;This is the part that pays for itself. The entire visual design of the paywall, including which packages to show, how to highlight the recommended plan, what copy to use for the trial CTA, and which offering to display, is configurable from the dashboard. You can tweak headline copy or swap a one screen layout for a feature comparison layout in the morning, watch conversion metrics in the afternoon, and revert by clicking a button if the new variant underperforms. None of this requires a Play Store or App Store review cycle.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;putting-it-all-together-the-architecture&quot;&gt;&lt;strong&gt;Putting it all together: the architecture&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Here is how all the pieces line up in a finished KMP project. In code, the cat-paywalls-kmp demo organizes responsibilities by module:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;composeApp&lt;/code&gt;&lt;/strong&gt;&amp;nbsp;is the only module with platform specific code. Its&amp;nbsp;&lt;code&gt;androidMain&lt;/code&gt;&amp;nbsp;configures&amp;nbsp;&lt;code&gt;Purchases&lt;/code&gt;&amp;nbsp;from the&amp;nbsp;&lt;code&gt;Application&lt;/code&gt;, its&amp;nbsp;&lt;code&gt;iosMain&lt;/code&gt;&amp;nbsp;exposes a&amp;nbsp;&lt;code&gt;MainViewController()&lt;/code&gt;&amp;nbsp;to SwiftUI, and its&amp;nbsp;&lt;code&gt;commonMain&lt;/code&gt;&amp;nbsp;holds&amp;nbsp;&lt;code&gt;App.kt&lt;/code&gt;&amp;nbsp;plus a Navigation Compose&amp;nbsp;&lt;code&gt;NavHost&lt;/code&gt;.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;&lt;code&gt;feature/*&lt;/code&gt;&lt;/strong&gt;&amp;nbsp;modules are screens (home, article, paywalls, account, subscriptions). They depend on&amp;nbsp;&lt;code&gt;core/*&lt;/code&gt;&amp;nbsp;and contain Compose Multiplatform UI plus ViewModels.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;&lt;code&gt;core/data&lt;/code&gt;&lt;/strong&gt;&amp;nbsp;owns&amp;nbsp;&lt;code&gt;PaywallsRepository&lt;/code&gt;, the only place that calls into&amp;nbsp;&lt;code&gt;Purchases.sharedInstance&lt;/code&gt;. Everything else reads&amp;nbsp;&lt;code&gt;Flow&amp;lt;Offering&amp;gt;&lt;/code&gt;&amp;nbsp;and&amp;nbsp;&lt;code&gt;Flow&amp;lt;CustomerInfo&amp;gt;&lt;/code&gt;&amp;nbsp;from this repository.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;&lt;code&gt;core/model&lt;/code&gt;&lt;/strong&gt;,&amp;nbsp;&lt;strong&gt;&lt;code&gt;core/network&lt;/code&gt;&lt;/strong&gt;,&amp;nbsp;&lt;strong&gt;&lt;code&gt;core/designsystem&lt;/code&gt;&lt;/strong&gt;,&amp;nbsp;&lt;strong&gt;&lt;code&gt;core/navigation&lt;/code&gt;&lt;/strong&gt;&amp;nbsp;hold the data classes, Ktor client, theme, and navigation graph respectively.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The final UX you ship looks like this. Subscribed users see the full article and a subscription management screen sourced from the same&amp;nbsp;&lt;code&gt;CustomerInfo&lt;/code&gt;&amp;nbsp;object:&lt;/p&gt;



&lt;figure class=&quot;wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-2 is-layout-flex wp-block-gallery-is-layout-flex&quot;&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;449&quot; height=&quot;942&quot; data-id=&quot;53553&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-1-1.png&quot; alt=&quot;&quot; class=&quot;wp-image-53553&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-1-1.png 449w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-1-1-143x300.png 143w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-1-1-24x50.png 24w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-1-1-19x40.png 19w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-1-1-221x464.png 221w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-1-1-267x560.png 267w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-1-1-141x296.png 141w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-1-1-225x472.png 225w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-1-1-38x80.png 38w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-1-1-23x48.png 23w&quot; sizes=&quot;auto, (max-width: 449px) 100vw, 449px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;471&quot; height=&quot;1024&quot; data-id=&quot;53551&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-2-1-471x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-53551&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-2-1-471x1024.png 471w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-2-1-138x300.png 138w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-2-1-768x1670.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-2-1-706x1536.png 706w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-2-1-942x2048.png 942w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-2-1-23x50.png 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-2-1-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-2-1-213x464.png 213w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-2-1-696x1513.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-2-1-258x560.png 258w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-2-1-136x296.png 136w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-2-1-217x472.png 217w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-2-1-37x80.png 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-2-1-22x48.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-2-1-scaled.png 1177w&quot; sizes=&quot;auto, (max-width: 471px) 100vw, 471px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;471&quot; height=&quot;1024&quot; data-id=&quot;53549&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-3-1-471x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-53549&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-3-1-471x1024.png 471w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-3-1-138x300.png 138w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-3-1-768x1670.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-3-1-706x1536.png 706w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-3-1-942x2048.png 942w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-3-1-23x50.png 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-3-1-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-3-1-213x464.png 213w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-3-1-696x1513.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-3-1-258x560.png 258w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-3-1-136x296.png 136w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-3-1-217x472.png 217w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-3-1-37x80.png 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-3-1-22x48.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/preview-3-1-scaled.png 1177w&quot; sizes=&quot;auto, (max-width: 471px) 100vw, 471px&quot;&gt;&lt;/figure&gt;
&lt;/figure&gt;



&lt;p&gt;The same&amp;nbsp;&lt;code&gt;SubscriptionManagementScreen&lt;/code&gt;&amp;nbsp;reads&amp;nbsp;&lt;code&gt;customerInfo.activeSubscriptions&lt;/code&gt;,&amp;nbsp;&lt;code&gt;customerInfo.entitlements[&quot;premium&quot;]?.isActive&lt;/code&gt;, and&amp;nbsp;&lt;code&gt;customerInfo.originalAppUserId&lt;/code&gt;&amp;nbsp;to render its content, and runs without modification on both platforms. There is no&amp;nbsp;&lt;code&gt;if (Build.VERSION...)&lt;/code&gt;&amp;nbsp;and no&amp;nbsp;&lt;code&gt;#if os(iOS)&lt;/code&gt;. The code lives once, in&amp;nbsp;&lt;code&gt;commonMain&lt;/code&gt;, and the SDK does the platform translation underneath.&lt;/p&gt;



&lt;p&gt;If you want to inspect the full source as a reference, every file shown in this article is in&amp;nbsp;&lt;a href=&quot;https://github.com/RevenueCat/cat-paywalls-kmp&quot;&gt;cat-paywalls-kmp&lt;/a&gt;. The minimum surface to get a working integration is the four steps above plus the dashboard setup. Everything else is product specific UI.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;conclusion&quot;&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;In this article, you’ve configured the RevenueCat KMP SDK in a Compose Multiplatform project, initialized&amp;nbsp;&lt;code&gt;Purchases&lt;/code&gt;&amp;nbsp;on Android and iOS, gated a premium screen with&amp;nbsp;&lt;code&gt;CustomerInfo.entitlements&lt;/code&gt;, run a real purchase through&amp;nbsp;&lt;code&gt;awaitPurchase&lt;/code&gt;, and rendered a server driven paywall with the&amp;nbsp;&lt;code&gt;Paywall&lt;/code&gt;&amp;nbsp;composable from&amp;nbsp;&lt;code&gt;purchases-kmp-ui&lt;/code&gt;. Every piece of subscription logic except platform initialization lives in&amp;nbsp;&lt;code&gt;commonMain&lt;/code&gt;, which means your iOS and Android apps stay in lockstep without any code duplication.&lt;/p&gt;



&lt;p&gt;The thing worth internalizing is what the SDK takes off your plate. You no longer think in terms of purchase tokens versus signed transactions, two notification pipelines, or two receipt verification servers. You think in terms of offerings, packages, entitlements, and&amp;nbsp;&lt;code&gt;CustomerInfo&lt;/code&gt;, and the SDK collapses both stores into those four concepts. That same abstraction is what makes the visual Paywall Editor possible, since it is far easier to ship one server driven UI when there is only one shared state model underneath.&lt;/p&gt;



&lt;p&gt;Whether you are porting an existing Android subscription app to iOS, starting a new product on KMP from scratch, or experimenting with paywall variants without burning a release cycle, this setup gives you the smallest surface area you can ship a cross platform subscription app on. The remaining engineering time goes back into the parts of your app that actually differentiate your product.&lt;/p&gt;



&lt;p&gt;As always, happy coding!&lt;/p&gt;



&lt;p&gt;—&amp;nbsp;&lt;a href=&quot;https://github.com/skydoves/&quot;&gt;Jaewoong&lt;/a&gt;&amp;nbsp;(skydoves)&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[How a switch from hard paywall to freemium led to a 75% LTV lift and a 50% conversion drop]]></title><description><![CDATA[Moving from a hard paywall to freemium is like switching from checkers to chess]]></description><link>https://www.revenuecat.com/blog/growth/hard-paywall-vs-freemium/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/hard-paywall-vs-freemium/</guid><pubDate>Wed, 29 Apr 2026 16:06:13 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Blog-covers-1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;For the vast majority of subscription apps, the most reliable path to profitability is simple: lock your core value behind a &lt;a href=&quot;https://www.revenuecat.com/blog/growth/hard-paywall-vs-soft-paywall/&quot;&gt;hard paywall&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;The data backs this up. According to &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps/&quot;&gt;our State of Subscription Apps report&lt;/a&gt;, hard paywalls convert downloads to paid at a median of 10.7% — five times better than the 2.1% median for freemium apps. The floor for hard paywalls (4.2%) is actually double the median for freemium.&lt;/p&gt;



&lt;p&gt;“If you’re a bootstrapped startup or you’re operating with limited outside capital, it’s a much more reliable and low-risk way of growing your business,” explains growth advisor Phil Carter in &lt;a href=&quot;https://www.revenuecat.com/blog/growth/phil-carter-elemental-growth-sub-club-podcast-2026/&quot;&gt;a recent episode of the Sub Club podcast&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;But what if you want to build a billion-dollar company?&lt;/p&gt;



&lt;p&gt;“There are a lot of examples of apps like Spotify, Duolingo, Strava that have done that through freemium,” Phil says. “You’re just going to attract a much larger user base at the top of the funnel if you have a free version of your product.”&lt;/p&gt;



&lt;script src=&quot;https://fast.wistia.com/player.js&quot; async=&quot;&quot;&gt;&lt;/script&gt;&lt;script src=&quot;https://fast.wistia.com/embed/oy30z431st.js&quot; async=&quot;&quot; type=&quot;module&quot;&gt;&lt;/script&gt;&lt;style&gt;wistia-player[media-id=&apos;oy30z431st&apos;]:not(:defined) { background: center / contain no-repeat url(&apos;https://fast.wistia.com/embed/medias/oy30z431st/swatch&apos;); display: block; filter: blur(5px); }&lt;/style&gt; &lt;wistia-player media-id=&quot;oy30z431st&quot; aspect=&quot;1.7777777777777777&quot; style=&quot;width: 600px;height: 338px;&quot;&gt;&lt;/wistia-player&gt;



&lt;p&gt;The transition from a hard paywall to freemium is the highest-ceiling growth lever a mature app can pull. It’s also the most dangerous. To illustrate the stakes, Phil shared the story of his biggest win — and his biggest failure — from the past year. Both involved the exact same strategy.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-win-a-75-increase-in-ltv&quot;&gt;The win: a 75% increase in LTV&lt;/h2&gt;



&lt;p&gt;Phil’s biggest win came from helping an established subscription app move away from a traditional hard paywall. But rather than simply opening up the app and hoping users would eventually subscribe, his team implemented a “&lt;a href=&quot;https://www.revenuecat.com/blog/growth/paywall-redesigns-case-studies/&quot;&gt;multistep paywall&lt;/a&gt;.”&lt;/p&gt;



&lt;p&gt;The strategy reframed the value proposition. Instead of saying, &lt;em&gt;You have to pay for this product now&lt;/em&gt;, the new onboarding flow communicated a different message: &lt;em&gt;This product is free and will always be free, but we want you to try the best version of it for &lt;/em&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/7-day-trial-subscription-app/&quot;&gt;&lt;em&gt;seven days&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. After that, we’d love to have you continue paying to get maximum value.&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;The results were staggering.&lt;/p&gt;



&lt;p&gt;“We saw a 75% increase in LTV per user through the implementation of this multistep paywall along with some other &lt;a href=&quot;https://www.revenuecat.com/blog/growth/offering-customization-examples-targeting/&quot;&gt;pricing and packaging optimizations&lt;/a&gt;,” Phil says.&lt;/p&gt;



&lt;p&gt;By removing the hard gate, the app widened its top-of-funnel significantly. More users experienced the core product, organic acquisition accelerated, and the multistep paywall successfully captured the revenue upside.&lt;/p&gt;



&lt;p&gt;“It pretty fundamentally altered the full potential size of this business,” Phil notes.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;619&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/hard-paywall-vs.-multistep-paywall-freemium-trial-1024x619.png&quot; alt=&quot;&quot; class=&quot;wp-image-53530&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/hard-paywall-vs.-multistep-paywall-freemium-trial-1024x619.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/hard-paywall-vs.-multistep-paywall-freemium-trial-300x181.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/hard-paywall-vs.-multistep-paywall-freemium-trial-768x465.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/hard-paywall-vs.-multistep-paywall-freemium-trial-50x30.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/hard-paywall-vs.-multistep-paywall-freemium-trial-66x40.png 66w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/hard-paywall-vs.-multistep-paywall-freemium-trial-696x421.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/hard-paywall-vs.-multistep-paywall-freemium-trial-560x339.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/hard-paywall-vs.-multistep-paywall-freemium-trial-489x296.png 489w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/hard-paywall-vs.-multistep-paywall-freemium-trial-780x472.png 780w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/hard-paywall-vs.-multistep-paywall-freemium-trial-80x48.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/hard-paywall-vs.-multistep-paywall-freemium-trial-48x29.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/hard-paywall-vs.-multistep-paywall-freemium-trial.png 1516w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-fail-a-50-drop-in-conversion&quot;&gt;The fail: a 50% drop in conversion&lt;/h2&gt;



&lt;p&gt;The success of the multistep paywall might suggest that every scaling app should immediately drop its hard paywall. But Phil’s biggest failure of the year serves as a stark warning against treating freemium as a silver bullet.&lt;/p&gt;



&lt;p&gt;With a different client, Phil’s team attempted a similar shift to freemium. The results were disastrous.&lt;/p&gt;



&lt;p&gt;“The initial results didn’t work at all,” he admits. “We saw more than a 50% reduction in subscriber conversion. We very quickly pulled off of it after a couple of weeks.”&lt;/p&gt;



&lt;p&gt;Why did the exact same strategic move produce such radically different outcomes?&lt;/p&gt;



&lt;p&gt;It comes down to &lt;a href=&quot;https://www.revenuecat.com/blog/growth/product-market-fit-subscription-apps/&quot;&gt;product-market fit&lt;/a&gt; and the inherent complexity of &lt;a href=&quot;https://www.revenuecat.com/blog/growth/how-to-turn-freemium-users-into-loyal-subscribers/&quot;&gt;managing a freemium model&lt;/a&gt;. When an app relies on a hard paywall, it forces a binary decision before the user has fully experienced the product. The conversion is driven by the promise of value, the quality of the marketing, and the friction of the paywall itself.&lt;/p&gt;



&lt;p&gt;When you remove that friction, you’re entirely reliant on the product’s ability to demonstrate ongoing, undeniable value. If the free experience is too generous, users have no incentive to upgrade. If it’s too restrictive, they churn before forming a habit.&lt;/p&gt;



&lt;p&gt;According to &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps/&quot;&gt;State of Subscription Apps 2026&lt;/a&gt;, 55% of all 3-day trial cancellations happen on Day 0 — meaning the battle for the subscriber is won or lost in the first session.&lt;/p&gt;



&lt;p&gt;As Phil puts it, moving from a hard paywall to freemium is “like moving from playing checkers to playing chess because it requires a lot more sophistication.”&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-when-should-you-make-the-switch&quot;&gt;When should you make the switch?&lt;/h2&gt;



&lt;p&gt;If you’re considering dropping your hard paywall, the data and Phil’s experience suggest a clear framework for the decision:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-stay-with-a-hard-paywall-if&quot;&gt;&lt;strong&gt;1. Stay with a hard paywall if:&lt;/strong&gt;&lt;/h3&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;You’re bootstrapped or highly capital-constrained&lt;/li&gt;



&lt;li&gt;You need immediate cash flow to fund paid acquisition&lt;/li&gt;



&lt;li&gt;Your product solves an acute, immediate problem rather than building a long-term habit&lt;/li&gt;



&lt;li&gt;You don’t have the product analytics infrastructure to rigorously test feature gating&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-consider-testing-freemium-if&quot;&gt;&lt;strong&gt;2. Consider testing freemium if:&lt;/strong&gt;&lt;/h3&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;You’ve achieved strong product-market fit and high retention among your core users&lt;/li&gt;



&lt;li&gt;You’ve got the runway to absorb a temporary dip in conversion rates while you optimize the model&lt;/li&gt;



&lt;li&gt;Your product benefits from network effects or user-generated content (like &lt;a href=&quot;https://www.revenuecat.com/blog/growth/cem-kansu-duolingo-sub-club-podcast-2026/&quot;&gt;Duolingo’s massive free experience&lt;/a&gt;)&lt;/li&gt;



&lt;li&gt;You’ve hit a growth ceiling with paid acquisition and need to unlock organic, word-of-mouth growth at scale&lt;/li&gt;
&lt;/ul&gt;



&lt;script src=&quot;https://fast.wistia.com/player.js&quot; async=&quot;&quot;&gt;&lt;/script&gt;&lt;script src=&quot;https://fast.wistia.com/embed/ksqoeu5aw4.js&quot; async=&quot;&quot; type=&quot;module&quot;&gt;&lt;/script&gt;&lt;style&gt;wistia-player[media-id=&apos;ksqoeu5aw4&apos;]:not(:defined) { background: center / contain no-repeat url(&apos;https://fast.wistia.com/embed/medias/ksqoeu5aw4/swatch&apos;); display: block; filter: blur(5px); }&lt;/style&gt; &lt;wistia-player media-id=&quot;ksqoeu5aw4&quot; aspect=&quot;1.7777777777777777&quot; style=&quot;width: 600px;height: 338px;&quot;&gt;&lt;/wistia-player&gt;



&lt;p&gt;Freemium isn’t a pricing strategy; it’s a product strategy. If you treat it simply as a different way to display your paywall, you risk halving your conversion rate. But if you treat it as a fundamental shift in how you deliver value, it might just be the move that turns your app into a billion-dollar business.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[The counterintuitive freemium strategy that scaled Opal to 1M daily active users]]></title><description><![CDATA[Kenneth Schlenker dropped Opal’s paid conversion rate from 20% to 9% — and it resulted in an explosion of daily active users and compounding revenue.]]></description><link>https://www.revenuecat.com/blog/growth/kenneth-schlenker-sub-club-podcast-2026/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/kenneth-schlenker-sub-club-podcast-2026/</guid><pubDate>Wed, 29 Apr 2026 12:58:49 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/RC-Blog-Cover-Kenneth-Schlenker-1.png" length="0" type="image/*"/><content:encoded>&lt;div class=&quot;lazyblock-d7d847878df0-Z1wvawQ wp-block-lazyblock-d7d847878df0&quot;&gt;&lt;blogpostyoutube embed-url=&quot;https://www.youtube.com/watch?v=tJnJflSXaE4&quot;&gt;
&lt;/blogpostyoutube&gt;&lt;/div&gt;


&lt;iframe loading=&quot;lazy&quot; width=&quot;100%&quot; height=&quot;180&quot; frameborder=&quot;no&quot; scrolling=&quot;no&quot; seamless=&quot;&quot; src=&quot;https://share.transistor.fm/e/a7812acd?color=FFFFFF&amp;amp;background=30343C&quot;&gt;&lt;/iframe&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-dropping-conversion-to-9-was-the-right-move&quot;&gt;Why dropping conversion to 9% was the right move&lt;/h2&gt;



&lt;p&gt;When Opal, the popular screen time and focus app, hit $5 million in annual recurring revenue (ARR), they were scaling efficiently with a hard paywall. The business model was working, but user growth was plateauing.&lt;/p&gt;



&lt;p&gt;To build a product capable of reaching a billion users, CEO Kenneth Schlenker made a terrifying decision: transition to a true freemium model. The immediate result was a massive drop in their download-to-paid conversion rate, plummeting from 20% down to 9%.&lt;/p&gt;



&lt;p&gt;But that drop was exactly what the company needed. By giving away the core product for free, Opal unlocked entirely new segments—specifically high school and college students, who now make up two-thirds of their daily active users (DAUs). These free users became the app’s marketing engine. The initial hit to conversion was eclipsed by an explosion in organic growth, pushing Opal past 1 million DAUs and $10 million in ARR.&lt;/p&gt;



&lt;p&gt;“We’ve seen a decrease in our conversion to paid, but we’ve also seen as a consequence of that an explosion of our DAUs and revenue with it,” Schlenker explains. “It’s a short-term, scary drop, but what happens in the long-term is that it pays back tenfold.”&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-would-a-free-user-recommend-it-test&quot;&gt;The “would a free user recommend it?” test&lt;/h2&gt;



&lt;p&gt;The success of a freemium model hinges on a single question: would a non-paying user recommend the app to a friend? If the answer is no, the paywall is too restrictive.&lt;/p&gt;



&lt;p&gt;Schlenker argues that many apps fail at freemium because their free tier feels like a crippled trial rather than a complete experience. If users hit aggressive limits before they can extract real value, they won’t stick around, and they certainly won’t tell their friends.&lt;/p&gt;



&lt;p&gt;To find the right balance, Opal experimented heavily with their “blocks” feature. They tested giving free users just one block, then two, then more. They eventually landed on three free blocks per day. This proved to be the sweet spot—enough functionality for free users to get a great experience and build a habit, while still leaving power users hungry enough to upgrade.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-you-can-t-vibe-code-a-brand&quot;&gt;You can’t “vibe code” a brand&lt;/h2&gt;



&lt;p&gt;With the rise of AI coding tools, the narrative of the “billion-dollar one-person company” has gained traction. The idea is that a single developer can spin up a functional app in a weekend and scale it to massive revenue. Schlenker calls this a lie.&lt;/p&gt;



&lt;p&gt;While AI is incredibly efficient at generating functional tools, it cannot generate emotional resonance. A screen time app is technically simple to build—Schlenker notes that people frequently launch Opal clones—but building a category-defining company requires more than just code.&lt;/p&gt;



&lt;p&gt;“Teams create product soul. You can’t vibe code a brand,” Schlenker says. “I think that a recipe for failure in my mind is just to create something that has a function, which AI does really, really well… but you need more than that to be able to be successful.”&lt;/p&gt;



&lt;p&gt;That “soul” is evident in Opal’s design choices, like the highly engineered, tactile interaction of cracking open a digital gemstone when a user hits a focus milestone. It’s an expensive, difficult feature to build that doesn’t directly move a metric on a spreadsheet, but it’s the exact kind of magical moment that builds brand affinity and long-term retention.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-expanding-beyond-the-app-store-into-schools&quot;&gt;Expanding beyond the App Store into schools&lt;/h2&gt;



&lt;p&gt;Opal’s organic growth among students led to an unexpected B2B opportunity. A high school in Los Angeles reached out to the company because their students—who were already using Opal independently—suggested the app as a solution to the state’s impending phone ban.&lt;/p&gt;



&lt;p&gt;This organically birthed “Opal for Schools,” a specialized deployment that blocks distracting apps while students are on campus, but allows access to educational tools and emergency contacts. Crucially, it’s not just a “bell-to-bell” restriction. Students keep the app after school, using it to manage their own study time and sleep schedules.&lt;/p&gt;



&lt;p&gt;By partnering with schools, Opal is essentially building the next generation of professional users while solving an immediate crisis for educators.&lt;/p&gt;



&lt;p&gt;In &lt;a href=&quot;https://www.youtube.com/watch?v=tJnJflSXaE4&quot;&gt;the full episode&lt;/a&gt;, Kenneth also discusses why retention is the only real moat for consumer apps, how they turned a viral user video into their most successful ad, and why every AI feature should be evaluated by whether it makes the user win.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-guest-links&quot;&gt;Guest links:&lt;/h2&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.linkedin.com/in/kennethschlenker/&quot;&gt;Kenneth Schlenker on LinkedIn&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://twitter.com/kennethschlenk&quot;&gt;Kenneth Schlenker on X&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.opal.so/&quot;&gt;Opal&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Apple’s new monthly subscriptions with a 12-month commitment: useful, but probably not magic]]></title><description><![CDATA[A practical look at Apple’s new monthly annual subscriptions, what Google Play already supports, and where 12-month commitments might actually help.]]></description><link>https://www.revenuecat.com/blog/engineering/monthly-subscription-12-month-commitment/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/monthly-subscription-12-month-commitment/</guid><pubDate>Tue, 28 Apr 2026 15:45:38 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Monthly-subscriptions-with-12month-commitment.jpg" length="0" type="image/*"/><content:encoded>&lt;p&gt;Apple has introduced &lt;a href=&quot;https://developer.apple.com/news/?id=agq42lxe&quot;&gt;monthly subscriptions with a 12-month commitment&lt;/a&gt;: an annual subscription that customers pay for month by month. Developers can configure and test them now, and Apple says they’ll be available to customers in May everywhere except the United States and Singapore.&lt;/p&gt;



&lt;p&gt;This is a meaningful new pricing tool, especially for markets where paying a full year upfront is a real barrier. But it is probably not a new default subscription model for most apps. In fact, Google Play has worked similarly for a while, but is not wildly popular. The best use case is localized experimentation: making annual-style commitment more accessible without giving up the long-term retention benefits of a yearly plan.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-apple-announced&quot;&gt;What Apple announced&lt;/h2&gt;



&lt;p&gt;Apple’s new option lets developers offer an auto-renewable subscription that behaves like an annual commitment, but bills the customer monthly.&lt;/p&gt;



&lt;p&gt;Instead of asking someone to pay, say, $59.99 today for a year of access, you can ask them to commit to 12 monthly payments. The customer can cancel at any time, but they will still be charged monthly for the remainder of their 12 month period. At the end of their commitment they will lose access to paid features and will no longer be charged.&lt;/p&gt;



&lt;p&gt;Apple is also handling some of the customer-facing transparency. Customers can see completed and remaining payments in their Apple Account, and Apple says it will send email and push notifications before renewal.&lt;/p&gt;



&lt;p&gt;The important availability note: Apple says this will be available worldwide except in the United States and Singapore.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-this-is-not-just-a-monthly-plan&quot;&gt;This is not just “a monthly plan”&lt;/h2&gt;



&lt;p&gt;The implementation detail that matters is that Apple is modeling this as an annual subscription product with multiple billing plans.&lt;/p&gt;



&lt;p&gt;In App Store Connect, developers create an annual auto-renewable subscription and choose between billing plan types, including “1 Year Upfront” and “Monthly With 12-Month Commitment.” Those billing plans can exist under the same product ID.&lt;/p&gt;



&lt;p&gt;That means a single subscription product can now have multiple ways to pay:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;One annual price paid upfront&lt;/li&gt;



&lt;li&gt;One monthly price paid over a 12-month commitment&lt;/li&gt;



&lt;li&gt;Different intro, promo, win-back, or offer-code behavior per billing plan&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The customer does not simply pick from an Apple-generated menu at random. Your app or paywall still needs to present the right option and initiate the purchase with the intended billing plan. Developers also need to clearly show both the monthly payment and the total commitment amount before purchase.&lt;/p&gt;



&lt;p&gt;This is all very similar to Google Play’s &lt;a href=&quot;https://support.google.com/googleplay/android-developer/answer/12154973?hl=en&quot;&gt;installment base plan for subscriptions&lt;/a&gt;: one subscription concept, multiple purchasable configurations.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-this-probably-won-t-change-everything&quot;&gt;Why this probably won’t change everything&lt;/h2&gt;



&lt;p&gt;The obvious first reaction is: this is huge. Annual subscriptions, but paid monthly, should reduce friction and increase conversion.&lt;/p&gt;



&lt;p&gt;Maybe. In some cases.&lt;/p&gt;



&lt;p&gt;But Google Play has supported installment-style subscriptions for a while, and they have not become the default way most apps monetize. There is a reason for that: for many apps, the standard annual plan is still better.&lt;/p&gt;



&lt;p&gt;A paid-upfront annual subscription gives the developer cash today. It improves short-term payback, reduces monthly billing failure risk, and creates cleaner revenue recognition for the business. If your audience can comfortably pay upfront, the traditional annual plan is still a very strong product.&lt;/p&gt;



&lt;p&gt;Monthly annual commitments are different. They may lower the purchase barrier, but they do not give you all of the cash upfront. They also add complexity to pricing, paywall copy, analytics, support, and cancellation expectations.&lt;/p&gt;



&lt;p&gt;So the goal should not be “replace annual subscriptions.” The goal should be “test whether this unlocks customers who wanted the annual value proposition but could not or would not pay the whole amount upfront.”&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-where-it-gets-interesting&quot;&gt;Where it gets interesting&lt;/h2&gt;



&lt;p&gt;The strongest opportunity is localization.&lt;/p&gt;



&lt;p&gt;In many markets, the problem with annual subscriptions is not that users dislike commitment. It is that the upfront price is too high relative to local purchasing power. A $50 or $60 annual subscription can be a meaningful expense. Breaking that into monthly payments while preserving a yearly commitment changes the decision.&lt;/p&gt;



&lt;p&gt;That makes this especially worth testing in markets where:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Annual conversion is low, but monthly retention is healthy&lt;/li&gt;



&lt;li&gt;Users respond to annual discounts but hesitate at checkout&lt;/li&gt;



&lt;li&gt;Local purchasing power makes upfront annual pricing feel too steep&lt;/li&gt;



&lt;li&gt;You already localize pricing and paywall strategy by country&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;This is not currently useful for the US, especially because Apple is excluding the US (and Singapore) from launch. But that actually reinforces the point: this is less about a universal monetization shift and more about giving developers another regional pricing lever.&lt;/p&gt;



&lt;p&gt;As of writing, Google Play only supports their &lt;a href=&quot;https://support.google.com/googleplay/android-developer/answer/12154973?hl=en&quot;&gt;installments based plans for subscriptions&lt;/a&gt; in Brazil, France, Italy, and Spain. This may be a good signal that these regions are more likely to be interested in these types of offers.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-not-to-use-it-for&quot;&gt;What not to use it for&lt;/h2&gt;



&lt;p&gt;This should not be used to cover up weak retention.&lt;/p&gt;



&lt;p&gt;If users do not keep finding value in your app, putting them into a 12-month payment commitment is unlikely to create a better business. It may create more support tickets, more refund requests, more negative reviews, and more payment failures.&lt;/p&gt;



&lt;p&gt;The right apps to test this are apps with proven long-term value. If users already stick around, but upfront annual pricing is the barrier, monthly commitments could help. If users churn because they stop using the product after two weeks, this won’t help.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-developers-should-watch&quot;&gt;What developers should watch&lt;/h2&gt;



&lt;p&gt;The obvious metric is conversion: does a monthly annual commitment convert better than a paid-upfront annual plan?&lt;/p&gt;



&lt;p&gt;But that alone is not enough. Developers should also watch:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Annual-plan cannibalization&lt;/li&gt;



&lt;li&gt;Payment failure and recovery rates&lt;/li&gt;



&lt;li&gt;Refund and support volume&lt;/li&gt;



&lt;li&gt;Renewal into the next 12-month commitment&lt;/li&gt;



&lt;li&gt;Subscriber sentiment in reviews and support conversations&lt;/li&gt;



&lt;li&gt;Net revenue by country compared with standard monthly and annual options&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;This is a pricing experiment, not just a checkout experiment. The upside is incremental revenue from users who would not have bought annual upfront. The downside is replacing high-quality upfront annual purchases with slower, riskier monthly payments.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-revenuecat-is-thinking-about-support&quot;&gt;How RevenueCat is thinking about support&lt;/h2&gt;



&lt;p&gt;Over here at RevenueCat we are, of course, all over this.&lt;/p&gt;



&lt;p&gt;Early testing suggests these transactions can move through our systems, but full support requires some product changes our engineering team is already hard at work on.&lt;/p&gt;



&lt;p&gt;Developers will need a clean way to understand which billing plans are available, present the right pricing terms, choose the intended billing plan at purchase time, and measure performance after launch. Paywalls will also need to account for regional availability, since the monthly commitment option is not available everywhere.&lt;/p&gt;



&lt;p&gt;We’re actively looking at the right way to model and expose this so developers can take advantage of it without taking on all of the complexity themselves. More details will come as Apple’s rollout gets closer and we finalize support across the RevenueCat platform.&lt;/p&gt;



&lt;p&gt;For now, the practical takeaway is simple: this is a useful new tool, especially for localized annual pricing. It is not a magic monetization switch. The apps that benefit most will be the ones that test it deliberately, explain it clearly, and already have the retention to make a 12-month commitment feel fair.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Stop building features: why early-stage apps need a learning roadmap first]]></title><description><![CDATA[A framework to test assumptions before committing to features]]></description><link>https://www.revenuecat.com/blog/growth/learning-roadmap-for-apps/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/learning-roadmap-for-apps/</guid><pubDate>Tue, 28 Apr 2026 10:11:45 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Blog-46_Meet-the-learning-roadmap-for-early-stage-apps.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Most early-stage founders have a roadmap full of features they want to build. It feels productive; you’re shipping, you’re making progress.&lt;/p&gt;



&lt;p&gt;And while I love &lt;a href=&quot;https://www.revenuecat.com/blog/growth/fast-shipping/&quot;&gt;fast shipping over perfection&lt;/a&gt;, when that speed is focused purely on features, it can be dangerous — especially when you start planning months ahead. You’re assuming you know what users need before validating it, and you’re also committing to features and improvements in a space that is still highly volatile.&lt;/p&gt;



&lt;p&gt;Then the roadmap becomes a to-do list of guesses; &lt;a href=&quot;https://www.producttalk.org/measurable-outcomes-all-things-product-podcast-with-teresa-torres-petra-wille/?srsltid=AfmBOoreRqgf5LpiRjXj1pivffGItpmRkHpHv9vmnriUI7eQHtDtA54N&quot;&gt;outputs rather than outcomes&lt;/a&gt;. You ship features with great excitement, but you don’t necessarily learn whether they actually matter. Or, at the very least, learning happens much more slowly than it should.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;I’ve seen new subscription apps spend months building features that nobody actually uses, because they never paused to ask: what do we need to learn right now?&lt;/p&gt;



&lt;p&gt;For early-stage subscription apps, roadmaps shouldn’t be about what to build, as you really can’t reliably predict more than a quarter ahead anyway.&lt;/p&gt;



&lt;p&gt;Instead, they should be about what to learn.&lt;/p&gt;



&lt;p&gt;That’s exactly what we’ll focus on: building a learning roadmap.&lt;/p&gt;



&lt;p&gt;A learning roadmap is a structured plan built around questions and hypotheses rather than features — designed to &lt;a href=&quot;https://www.revenuecat.com/blog/growth/customer-validation-subscription-app/&quot;&gt;validate assumptions before committing to a build&lt;/a&gt;.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-focus-on-validating-over-shipping-features&quot;&gt;Focus on validating over shipping features&lt;/h2&gt;



&lt;p&gt;There’s a difference between a shipping mindset and a validating mindset.&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Shipping feature mindset:&lt;/strong&gt; What features can we release this quarter?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Validating mindset: &lt;/strong&gt;What’s the most important question we need to answer right now?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Pre-&lt;a href=&quot;https://www.revenuecat.com/blog/growth/product-market-fit-subscription-apps/&quot;&gt;Product-Market Fit&lt;/a&gt;, you’re not trying to build a complete app that does everything. Instead, you’re trying to figure out whether you’re building the right thing.&lt;/p&gt;



&lt;p&gt;The goal is to learn what actually matters to your early users, and what drives them to pay.&lt;/p&gt;



&lt;p&gt;The beauty of switching to a validating mindset is that it often doesn’t require building a full feature to generate insight. You focus on the smallest possible test that lets you learn.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-how-robinhood-validated-pre-launch&quot;&gt;How Robinhood validated pre-launch&lt;/h3&gt;



&lt;p&gt;Before building their trading app, &lt;a href=&quot;https://robinhood.com/gb/en/&quot;&gt;Robinhood&lt;/a&gt; launched a waitlist landing page. The value prop was simple: ‘Commission-free trading.’ The main goal was a basic email sign-up, plus a referral loop that encouraged people to move up the list by sharing.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;900&quot; height=&quot;506&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-36.png&quot; alt=&quot;&quot; class=&quot;wp-image-53455&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-36.png 900w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-36-300x169.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-36-768x432.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-36-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-36-71x40.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-36-696x391.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-36-560x315.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-36-526x296.png 526w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-36-840x472.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-36-80x45.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-36-48x27.png 48w&quot; sizes=&quot;auto, (max-width: 900px) 100vw, 900px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Source: &lt;a href=&quot;http://kickofflabs.com&quot;&gt;kickofflabs.com&lt;/a&gt;&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;The result was over 1 million sign-ups before the app even existed.&lt;/p&gt;



&lt;p&gt;But sign-ups alone weren’t the signal they focused on. They tracked several behaviors to understand the quality of that early audience:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Referral behavior:&lt;/strong&gt; Were people sharing unprompted? (Yes, the viral coefficient was strong)&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Email engagement:&lt;/strong&gt; Did waitlist users open updates and ask about launch timing?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Willingness to act: &lt;/strong&gt;When early access was offered to top referrers, did people actually work to earn it?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;When you do eventually build a feature, it should usually be because something has been validated, and even then, you’re building it to answer a question, not just to add another piece to the product.&lt;/p&gt;



&lt;p&gt;What does a learning roadmap look like?&lt;/p&gt;



&lt;p&gt;A learning roadmap is structured around questions rather than features.&lt;/p&gt;



&lt;p&gt;For each question, you should be clear on what you think the answer might be, how you’ll test it, and what would indicate whether you’re right or wrong.&lt;/p&gt;



&lt;p&gt;The structure looks like this: Strategic Goal → Question → Hypothesis → Test → Success Criteria → Next Step.&lt;/p&gt;



&lt;p&gt;It’s important that every question you try to answer is directly tied back to a broader strategic goal.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;990&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-37-1024x990.png&quot; alt=&quot;&quot; class=&quot;wp-image-53458&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-37-1024x990.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-37-300x290.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-37-768x743.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-37-50x48.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-37-41x40.png 41w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-37-480x464.png 480w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-37-696x673.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-37-560x542.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-37-306x296.png 306w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-37-488x472.png 488w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-37-80x77.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-37-48x46.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-37.png 1338w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;This forces you to be specific about what you’re trying to learn rather than just shipping and hoping.&lt;/p&gt;



&lt;p&gt;For example, imagine you aren’t sure whether users understand the app’s value before they &lt;a href=&quot;https://www.revenuecat.com/blog/growth/paywalls-study-guide/&quot;&gt;reach the paywall&lt;/a&gt;.&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Strategic Goal: &lt;/strong&gt;Improve the download-to-trial-started conversion rate.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Question: &lt;/strong&gt;Do users understand the value before they hit the paywall?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Hypothesis:&lt;/strong&gt; Users will better understand the app’s value if we show more visualizations of what the app looks like, directly linked to the benefits we’re measuring.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Test: &lt;/strong&gt;Add a screenshot of the app to the benefits section instead of illustrations.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Success Criteria: &lt;/strong&gt;A significant increase in the &lt;a href=&quot;https://www.revenuecat.com/blog/growth/paywall-redesigns-case-studies/&quot;&gt;conversion rate at the first paywall&lt;/a&gt;.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Next step: &lt;/strong&gt;If confirmed, explore other ways to communicate value more strongly. If disproven, test alternatives; for example, adding a short video before onboarding that shows the outcomes users can achieve.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Each question you’re trying to answer is essentially an opportunity to create value for your users.&lt;/p&gt;



&lt;p&gt;The key insight, drawn from the work of &lt;a href=&quot;https://www.producttalk.org/measurable-outcomes-all-things-product-podcast-with-teresa-torres-petra-wille/?srsltid=AfmBOoreRqgf5LpiRjXj1pivffGItpmRkHpHv9vmnriUI7eQHtDtA54N&quot;&gt;Teresa Torres on continuous discovery&lt;/a&gt;, is to think about opportunities the way your customers would describe them, rather than in internal product language.&lt;/p&gt;



&lt;p&gt;For example, you can reframe the question from the user’s perspective: “I don’t understand what this app does before I have to pay.”&lt;/p&gt;



&lt;p&gt;Customer-centric framing like this helps you consider multiple possible solutions, and that’s why it’s important not to jump to the first test idea.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;If a test, such as “adding a screenshot instead of illustrations,” fails, it doesn’t necessarily mean the underlying question is answered. You may need to explore several different ways to test the same hypothesis before reaching clarity.&lt;/p&gt;



&lt;p&gt;The way I approach this is by noting down a few things first:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;The quantitative data behind the question or hypothesis&lt;/strong&gt;, for example, we see a very low trial-start rate while &lt;a href=&quot;https://www.revenuecat.com/blog/growth/fix-onboarding-funnels/&quot;&gt;onboarding completion&lt;/a&gt; is already high.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;The qualitative data that helps us understand the behavior further&lt;/strong&gt;, for example, during user testing, we observed that people who clicked away from the paywall were still trying to figure out what the app actually does.&lt;/li&gt;



&lt;li&gt;According to &lt;a href=&quot;https://www.revenuecat.com/blog/growth/subscription-app-trends-benchmarks-2026/&quot;&gt;SOSA 2026&lt;/a&gt;, 55% of all 3-day trial cancellations happen on Day 0 — making the question of whether users understand your value before the paywall one of the most critical assumptions to test early.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;From there, I work out multiple possible test ideas. For instance, in this example, you could also try:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Adding a short video to the onboarding that shows the app in action&lt;/li&gt;



&lt;li&gt;Testing a feature carousel at the start&lt;/li&gt;



&lt;li&gt;Showing a simplified “what you can do in the app” overview during onboarding&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;You can then return to the original question and evaluate which approach is most likely to help you gain clarity, given the insights you’ve gathered.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-three-buckets-now-next-later&quot;&gt;The three buckets: Now, Next, Later&lt;/h2&gt;



&lt;p&gt;If you’re wondering what you should be building 2–3 months from now, don’t worry, you really don’t need to know.&lt;/p&gt;



&lt;p&gt;I’ve always said that a quarter in a startup can feel like a year in a corporation. Honestly, a month in an early-stage startup can feel like a quarter in a later-stage one. Things move fast, and thank goodness for expensive skincare and blonde hair to help hide the grey hairs I’m convinced startups are responsible for.&lt;/p&gt;



&lt;p&gt;While your vision and strategy should be long-term, your roadmap can stay short-term. Trying to plan much beyond that usually just leads to endless rework.&lt;/p&gt;



&lt;p&gt;I like structuring a learning roadmap into three time horizons: Now, Next, and Later; a framework popularised by &lt;a href=&quot;https://www.prodpad.com/blog/invented-now-next-later-roadmap/&quot;&gt;Janna Bastow&lt;/a&gt;, which gives you permission not to do everything at once.&lt;/p&gt;



&lt;p&gt;Your buckets can look like this:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Now (&lt;/strong&gt;&lt;strong&gt;1–2&lt;/strong&gt;&lt;strong&gt; weeks):&lt;/strong&gt; The most critical question you need to answer right now. Just one question. Maximum focus.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Next (&lt;/strong&gt;&lt;strong&gt;2–4&lt;/strong&gt;&lt;strong&gt; weeks):&lt;/strong&gt; The questions that are likely to come next, depending on what you learn from what you’re testing now. These are tentative rather than fully committed — for example: &lt;em&gt;“If this happens, then we will do X”&lt;/em&gt;, based on the signals you’re seeing.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Later (backlog):&lt;/strong&gt; Ideas and questions you want to explore eventually, but aren’t scheduling yet. These can and will change as you learn.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;This approach keeps you focused while still allowing you to capture ideas without getting distracted.&lt;/p&gt;



&lt;p&gt;If you’re anything like me, you probably generate a million ideas during the early phase. While long-term planning is hard, ideation usually isn’t, so having a backlog helps you park ideas and return to them later.&lt;/p&gt;



&lt;p&gt;And honestly, a lot of ideas won’t survive that process (I have so many post-it notes with article ideas that, days later, make me wonder what I was thinking). So make a habit of tidying the backlog regularly.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;907&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-34-1024x907.png&quot; alt=&quot;&quot; class=&quot;wp-image-53453&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-34-1024x907.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-34-300x266.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-34-768x680.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-34-50x44.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-34-45x40.png 45w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-34-524x464.png 524w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-34-696x616.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-34-560x496.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-34-334x296.png 334w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-34-533x472.png 533w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-34-80x71.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-34-48x42.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-34.png 1326w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-to-prioritize-what-to-learn&quot;&gt;How to prioritize what to learn&lt;/h2&gt;



&lt;p&gt;You can’t test everything at once; all those ideas and questions you want to explore will need to be prioritized ruthlessly.&lt;/p&gt;



&lt;p&gt;This is where assumptions come in. Start by testing the assumptions that would undermine your strategy if they turned out to be wrong.&lt;/p&gt;



&lt;p&gt;I usually think about three types of assumptions:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Problem assumptions. &lt;/strong&gt;Do users actually have this problem and care enough to change behavior?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Value assumptions. &lt;/strong&gt;Does our solution genuinely help in a way that users recognize?&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/guide-to-app-pricing-research-methods/&quot;&gt;&lt;strong&gt;Willingness to pay assumptions&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;.&lt;/strong&gt; Will enough users pay enough at this price point for the product to be sustainable?&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;It’s very simplified, but as a new subscription app, you are essentially trying to answer these questions pre–&lt;a href=&quot;https://www.revenuecat.com/blog/growth/product-market-fit-subscription-apps/&quot;&gt;product-market fit&lt;/a&gt;:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Do users have this problem strongly enough to change behavior?&lt;/li&gt;



&lt;li&gt;Do they understand the value before reaching the paywall?&lt;/li&gt;



&lt;li&gt;Are they &lt;a href=&quot;https://www.revenuecat.com/blog/growth/7-day-trial-subscription-app/&quot;&gt;willing to pay at this price point&lt;/a&gt;?&lt;/li&gt;



&lt;li&gt;What makes them come back after day one?&lt;/li&gt;



&lt;li&gt;What’s the &lt;a href=&quot;https://www.revenuecat.com/blog/growth/activation-metrics/&quot;&gt;core action that predicts retention&lt;/a&gt;?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;My suggestion is to test in that order. If the problem isn’t real, there’s no point in testing around value assumptions. If the solution doesn’t work, there’s no point in testing pricing.&lt;/p&gt;



&lt;p&gt;From there, group related questions together; you’ll often find that many of them are connected. For example, returning to the paywall scenario, the question of “understanding value before the paywall” might break down into sub-questions such as:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Do they see what the app looks like?&lt;/li&gt;



&lt;li&gt;Do they understand the outcomes they can achieve?&lt;/li&gt;



&lt;li&gt;Do they know how long it will take to see results?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Grouping questions this way helps you identify the parent question to prioritize, and also reveals which sub-questions are likely to be answered together.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;999&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-35-1024x999.png&quot; alt=&quot;&quot; class=&quot;wp-image-53452&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-35-1024x999.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-35-300x293.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-35-768x750.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-35-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-35-41x40.png 41w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-35-475x464.png 475w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-35-696x679.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-35-560x547.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-35-303x296.png 303w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-35-484x472.png 484w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-35-80x78.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-35-48x48.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-35.png 1330w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;For example, if you’re building a sleep app and you’re unsure whether your audience struggles more with falling asleep or with staying asleep, that’s a problem assumption you can validate through user research.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-smaller-tests-faster-learning&quot;&gt;Smaller tests, faster learning&lt;/h2&gt;



&lt;p&gt;Hopefully, you’re convinced by now that you don’t need to build a full feature to learn — and that, as a result, a traditional feature roadmap is somewhat limiting. The goal, instead, is to test assumptions with the least possible effort.&lt;/p&gt;



&lt;p&gt;You’ve already seen how the waitlist approach worked for Robinhood, but there are many other options, too:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Prototypes. &lt;/strong&gt;It’s never been easier to mock up prototypes using AI tools like &lt;a href=&quot;https://lovable.dev/&quot;&gt;Lovable&lt;/a&gt;.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Painted door tests. &lt;/strong&gt;Here, you basically fake it till you make it, literally. You could show a fake feature button that isn’t yet functional.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Manual versions of features. &lt;/strong&gt;If you eventually want to automate something, start by testing the human version first. For instance, you might want to build automated skin analysis and recommendations, but initially test having someone manually provide the advice.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Start with the first part only. &lt;/strong&gt;For example, if you’re building a community feedback loop, you might begin by testing whether a simple “like” interaction is used, even if the downstream functionality isn’t built yet. In one case, the like action didn’t even trigger any visible response at the start, but it helped validate that users were willing to engage with that behavior.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;If you want to go even lighter, you can start with research, such as browsing forums to validate the problem space or conducting user interviews before creating any mockups. For early-stage startups, user research is almost always a good investment of time.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-happens-when-you-learn&quot;&gt;What happens when you learn&lt;/h2&gt;



&lt;p&gt;Every test will lead to one of three outcomes:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Confidence goes up&lt;/li&gt;



&lt;li&gt;Confidence goes down&lt;/li&gt;



&lt;li&gt;The result is inconclusive&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;I’ll be honest, that last one kind of sucks, but I promise it can still teach you something. This gives you clarity on what to do next:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;If confidence goes up&lt;/strong&gt;, decide whether you need further validation, whether there’s more to learn, or whether you can move on to the next question.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;If confidence declines, &lt;/strong&gt;decide whether you need further validation, whether there’s more to learn, or whether you can move on to the next question.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;If the result is inconclusive&lt;/strong&gt;, it could mean several things: perhaps the change didn’t have the expected impact, there wasn’t enough data, or the test itself wasn’t the right way to answer the question. You can then decide the best next step based on the cause.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;The goal isn’t to be right. In early-stage work, you will be wrong quite often, and that’s completely normal.&lt;/p&gt;



&lt;p&gt;​​The real objective is to learn quickly enough that being wrong doesn’t become costly.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-to-know-you-re-making-progress&quot;&gt;How to know you’re making progress&lt;/h2&gt;



&lt;p&gt;A learning roadmap can sometimes feel slower because you’re not shipping visible features. This is where trust can start to waver, for founders and teams alike.&lt;/p&gt;



&lt;p&gt;Progress simply looks different, and part of adopting a validating mindset is redefining what progress means.&lt;/p&gt;



&lt;p&gt;Progress can be seen in several ways:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;You can articulate what you now know that you didn’t know before&lt;/li&gt;



&lt;li&gt;You’ve eliminated solutions that don’t work (negative results are progress)&lt;/li&gt;



&lt;li&gt;Your questions are getting more specific and focused&lt;/li&gt;



&lt;li&gt;You’re converging on a smaller set of high-confidence opportunities&lt;/li&gt;



&lt;li&gt;Your success criteria are becoming more measurable over time&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Discussing regularly in sprint meetings what you’ve learned and understood, as well as small wins, helps you better see the progress that might not show up yet in your dashboards.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-common-traps-with-planning-your-roadmap&quot;&gt;Common traps with planning your roadmap&lt;/h2&gt;



&lt;p&gt;Across the startups I’ve worked with, the same roadmap mistakes keep repeating. They’re rarely about effort or intent; they’re about how decisions are made.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-building-before-validating&quot;&gt;1. Building before validating&lt;/h3&gt;



&lt;p&gt;This often shows up in disguise.&lt;/p&gt;



&lt;p&gt;Teams will sometimes say they aren’t following a feature roadmap, yet a specific feature or update suddenly starts feeling inevitable. Everyone becomes convinced it’s important. When you ask what that belief is based on, the answer is usually something like, &lt;em&gt;“we just know”&lt;/em&gt; or &lt;em&gt;“we have to do this.”&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;That’s still building before validating.&lt;/p&gt;



&lt;p&gt;Confidence is not the same as evidence. Even strong intuition needs to be grounded in research, data, or real user signals. The more excited you are about an idea, the more disciplined you need to be about pressure-testing it.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-too-many-priorities&quot;&gt;2. Too many priorities&lt;/h3&gt;



&lt;p&gt;If everything is a priority, nothing is.&lt;/p&gt;



&lt;p&gt;A strategy is not ten parallel projects; it’s a clear commitment to one or two things that matter right now. Your roadmap should reflect that focus.&lt;/p&gt;



&lt;p&gt;Be ruthless with your “now” bucket. If you’re trying to answer several big questions at once, you’ll likely make shallow progress on all of them and meaningful progress on none.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-vague-success-criteria&quot;&gt;3. Vague success criteria&lt;/h3&gt;



&lt;p&gt;“We’ll see if users like it” is not a success criterion.&lt;/p&gt;



&lt;p&gt;“It’s slightly better” isn’t either.&lt;/p&gt;



&lt;p&gt;Early on, statistical significance isn’t always possible, and that’s fine. What matters is being explicit about what success looks like before you start.&lt;/p&gt;



&lt;p&gt;Ask yourself:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;What signal would make you confident enough to continue?&lt;/li&gt;



&lt;li&gt;What outcome would clearly tell you to stop?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Also, think through secondary metrics in advance. For example:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;If the main metric doesn’t improve but another one does, what would you do?&lt;/li&gt;



&lt;li&gt;If the main metric improves but something else worsens, is that acceptable?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Planning these scenarios early prevents a lot of post-hoc rationalization.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-4-ignoring-negative-results&quot;&gt;4. Ignoring negative results&lt;/h3&gt;



&lt;p&gt;It’s tempting to explain away data that doesn’t confirm what you want to believe. As one speaker once said, &lt;em&gt;“If you torture the data enough, it will always confess.”&lt;/em&gt; That idea has stuck with me because it’s painfully true.&lt;/p&gt;



&lt;p&gt;There will almost always be a way to frame results as “not that bad” or to cherry-pick supporting slices of data. Clear success criteria help protect against this, but mindset matters too.&lt;/p&gt;



&lt;p&gt;Negative results aren’t something to be ashamed of. Most things won’t work; that’s completely normal. Treat failed experiments as learning rather than something to justify away. That’s what actually moves teams forward.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-5-never-moving-on&quot;&gt;5. Never moving on&lt;/h3&gt;



&lt;p&gt;The final trap is getting stuck in testing mode.&lt;/p&gt;



&lt;p&gt;Testing can feel safe because there’s always one more variant to try or one more week of data to collect. But at some point, you need enough signal to make a decision and move forward.&lt;/p&gt;



&lt;p&gt;Roadmaps are not about infinite validation — they’re about building confidence and then committing.&lt;/p&gt;



&lt;p&gt;Be honest with yourself about whether more testing will actually change your decision, or whether it’s just a way to avoid making one.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Some signs you’re ready to move on:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;You’ve tested across 2–3 cohorts, and the pattern is consistent&lt;/li&gt;



&lt;li&gt;The signal is strong enough to justify allocating resources (not just “slightly positive”)&lt;/li&gt;



&lt;li&gt;Further testing is unlikely to change your decision&lt;/li&gt;



&lt;li&gt;You’re delaying commitment rather than genuinely learning&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Use this list of common mistakes to keep yourself in check; you can even use it as part of a sprint retrospective. Going through the following questions as a team:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Were there any cases where we built before validating?&lt;/li&gt;



&lt;li&gt;What are our top priorities? Do we need to narrow them down?&lt;/li&gt;



&lt;li&gt;Are the success criteria of all the experiments clear enough?&lt;/li&gt;



&lt;li&gt;What were the ‘negative’ results this sprint? What did we learn from them?&lt;/li&gt;



&lt;li&gt;Is it time to move on from any focus areas?&lt;/li&gt;
&lt;/ol&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-stay-the-course-refine-or-pivot&quot;&gt;Stay the course, refine or pivot?&lt;/h2&gt;



&lt;p&gt;In &lt;a href=&quot;https://theleanstartup.com/principles&quot;&gt;&lt;em&gt;Eric Ries’s&lt;/em&gt; Lean Startup framework&lt;/a&gt;, there’s a recommendation to hold regular (often monthly) meetings to decide whether to pivot or persevere, essentially, whether to change direction or stay the course.&lt;/p&gt;



&lt;p&gt;I agree with the methodology, but the binary framing can feel a bit too black-and-white. The decision is usually not as simple as either killing an idea or continuing unchanged. Sometimes something is working partially, and the pressure to choose between pivoting and persevering can push teams toward perseverance because pivoting feels scarier. That’s where sunk cost fallacy starts creeping in; you’ve invested so much that it’s hard to step away.&lt;/p&gt;



&lt;p&gt;Instead, I prefer thinking about it in three options:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Stay the course (persevere). &lt;/strong&gt;When the core hypothesis is confirmed, focus on execution and iteration.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Refine. &lt;/strong&gt;The direction is generally right, but some details are wrong. This isn’t about small optimization; it’s about making a meaningful adjustment, such as changing the target audience, refining positioning, or altering features.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Pivot (or kill). &lt;/strong&gt;The core hypothesis is disproven, meaning you need to fundamentally rethink the problem, the user, or the solution.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Most launches don’t need a pivot; they need refinement. A true pivot should only happen when evidence clearly contradicts your core assumption about the problem or user, such as when target users don’t perceive value or when there are no meaningful signals of monetisation.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;547&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-33-1024x547.png&quot; alt=&quot;&quot; class=&quot;wp-image-53450&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-33-1024x547.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-33-300x160.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-33-768x410.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-33-50x27.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-33-75x40.png 75w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-33-696x372.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-33-560x299.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-33-554x296.png 554w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-33-840x449.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-33-80x43.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-33-48x26.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-33.png 1318w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;A well-known example of a major pivot is that of Instagram. Originally launched as Burbn, the product started as a check-in app with many features.&lt;/p&gt;



&lt;p&gt;After launch, the data showed that:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Most features were being ignored&lt;/li&gt;



&lt;li&gt;Photo sharing had unusually strong engagement&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The founders stripped away everything except photos because they realised their core hypothesis was wrong: users weren’t primarily looking for a check-in app or the broader feature set. Instead, they doubled down on the signal with the strongest user engagement and pivoted around that.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-when-can-you-move-on-from-a-learning-roadmap&quot;&gt;When can you move on from a learning roadmap?&lt;/h2&gt;



&lt;p&gt;A learning-style roadmap isn’t meant to last forever.&lt;/p&gt;



&lt;p&gt;At some point, it can start to lose its usefulness. Instead of providing clarity and direction, it may begin to feel like a long list of unresolved questions. As teams scale and the number of initiatives grows, a pure learning roadmap can sometimes create more noise than focus.&lt;/p&gt;



&lt;p&gt;This is usually a sign that you’re getting closer to product–market fit.&lt;/p&gt;



&lt;p&gt;As confidence increases, the balance naturally shifts. Post–product–market fit, you tend to have a clearer understanding of who your users are, what they want, and which problems truly matter. At that stage, a more traditional, feature-oriented roadmap (still focused though on outcomes) often becomes more practical.&lt;/p&gt;



&lt;p&gt;That doesn’t mean learning stops.&lt;/p&gt;



&lt;p&gt;Markets evolve. User behavior changes. Competitors improve. The difference is that the focus moves from mostly learning with some building to mostly building with some learning.&lt;/p&gt;



&lt;p&gt;You’re no longer questioning everything, but you still leave room to validate key assumptions and challenge strategic direction when necessary.&lt;/p&gt;



&lt;p&gt;In that sense, a learning roadmap is what helps you reach the point where a feature roadmap actually starts working.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-building-roadmaps-around-questions-not-outputs&quot;&gt;Building roadmaps around questions, not outputs&lt;/h2&gt;



&lt;p&gt;So remember, in early-stage subscription apps, strong roadmaps are built around questions — not features, not incremental improvement points, and definitely not growth for growth’s sake.&lt;/p&gt;



&lt;p&gt;A simple structure works well:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;What are we doing &lt;strong&gt;now&lt;/strong&gt;?&lt;/li&gt;



&lt;li&gt;What are we doing &lt;strong&gt;next&lt;/strong&gt;?&lt;/li&gt;



&lt;li&gt;What comes &lt;strong&gt;later&lt;/strong&gt;?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Your backlog belongs firmly in the &lt;strong&gt;later&lt;/strong&gt; bucket.&lt;/p&gt;



&lt;p&gt;The real work is being ruthless about identifying the assumptions that could undermine your idea if they turn out to be wrong, and prioritizing those first.&lt;/p&gt;



&lt;p&gt;Start by testing small and moving quickly. Only then should you expand and build with greater confidence.&lt;/p&gt;



&lt;p&gt;This approach can sometimes feel slower because you’re shipping less. In practice, it’s usually faster. Teams that default to constant building often spend months delivering features that nobody actually wants. Starting with learning helps avoid the waste of building things just for the sake of building.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;752&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-32-1024x752.png&quot; alt=&quot;&quot; class=&quot;wp-image-53448&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-32-1024x752.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-32-300x220.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-32-768x564.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-32-50x37.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-32-54x40.png 54w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-32-632x464.png 632w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-32-696x511.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-32-560x411.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-32-403x296.png 403w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-32-643x472.png 643w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-32-80x59.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-32-48x35.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-32.png 1318w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;If you want to go deeper into defining your strategy and identifying the right questions to answer, you can explore my full course on &lt;a href=&quot;https://www.startapp.school/courses/how-to-make-an-app-people-will-pay-for&quot;&gt;&lt;strong&gt;building an app that people will pay for&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Recapping App Monetization Seoul]]></title><description><![CDATA[Jaewoong Eum reflects on DARO and RevenueCat's app monetization event]]></description><link>https://www.revenuecat.com/blog/company/recapping-app-monetization-seoul/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/company/recapping-app-monetization-seoul/</guid><pubDate>Fri, 24 Apr 2026 10:46:55 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_0172-1-scaled.jpg" length="0" type="image/*"/><content:encoded>&lt;p&gt;On April 10, monetization leaders from Korea’s top apps came together at Boutique Monaco in Seoul for a night of honest conversation about how apps actually make money. The event, App Monetization Seoul, was co-hosted by DARO, RevenueCat, and EHVM Apps Capital.&lt;/p&gt;



&lt;p&gt;There was a great turnout with C-levels, growth leads, and product folks from companies like Google, AppsFlyer, Toss (Viva Republica), Healing Paper, Moloco, Criteo, SNOW, and CJ. The mix of ad-side and subscription-side practitioners in the same room was what made the evening work.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-two-levers-that-drive-ad-revenue&quot;&gt;Two levers that drive ad revenue&lt;/h2&gt;



&lt;p&gt;Eungil Cho, BD Manager at DARO, opened the evening. His framing was simple and hard to argue with. Ad revenue comes down to two levers: eCPM and impressions. Getting one of them right is not enough. The teams that win are the ones that balance both and build a culture of continuous experimentation around them.&lt;/p&gt;



&lt;p&gt;The point landed because the insights came out of DARO’s own experience running ad monetization for Alarmy, the number one alarm app globally built by Delightroom. Real numbers, real trade-offs, no slideware.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;683&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_9594-1024x683.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-53378&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_9594-1024x683.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_9594-300x200.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_9594-768x512.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_9594-1536x1024.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_9594-2048x1365.jpg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_9594-50x33.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_9594-60x40.jpg 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_9594-696x464.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_9594-560x373.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_9594-444x296.jpg 444w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_9594-708x472.jpg 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_9594-80x53.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_9594-48x32.jpg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-actually-moves-subscription-revenue&quot;&gt;What actually moves subscription revenue&lt;/h2&gt;



&lt;p&gt;Rik Haandrikman, VP of Growth at RevenueCat, spoke next: his session pulled from the &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps/&quot;&gt;State of Subscription Apps&lt;/a&gt; 2026 data across 115,000 apps on the RevenueCat platform. The talk cut through a lot of the rumours floating around about paywalls, pricing, and trials, and replaced it with what the numbers actually say.&lt;/p&gt;



&lt;p&gt;If you have been guessing at what drives subscription revenue, the answer is that most of the industry is guessing too. The signal, when you zoom out across that many apps, is sharper than you would think.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;715&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.43.03-PM-1024x715.png&quot; alt=&quot;&quot; class=&quot;wp-image-53380&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.43.03-PM-1024x715.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.43.03-PM-300x210.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.43.03-PM-768x537.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.43.03-PM-1536x1073.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.43.03-PM-50x35.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.43.03-PM-57x40.png 57w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.43.03-PM-664x464.png 664w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.43.03-PM-696x486.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.43.03-PM-560x391.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.43.03-PM-424x296.png 424w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.43.03-PM-676x472.png 676w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.43.03-PM-80x56.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.43.03-PM-48x34.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.43.03-PM.png 1546w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-global-opportunities-founders-keep-missing&quot;&gt;The global opportunities founders keep missing&lt;/h2&gt;



&lt;p&gt;The night closed with a panel on global monetization. &lt;a href=&quot;https://www.revenuecat.com/blog/growth/guide-to-selling-apps/&quot;&gt;Evelin Herrera&lt;/a&gt;, CEO of EHVM and the person behind more than 150 mobile app and game M&amp;amp;A deals, joined Rik and Seunghwan Stephan Seo, Chief of Staff and Product Owner at Delightroom.&lt;/p&gt;



&lt;p&gt;The conversation kept coming back to the same point. Korean app founders have world-class products, but many of them leave real revenue on the table because they underinvest in markets outside their core. Evelin’s view from the deal side, paired with Stephan’s operator view from Alarmy’s global playbook, made the case concrete.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;683&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_4167-1024x683.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-53382&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_4167-1024x683.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_4167-300x200.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_4167-768x512.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_4167-1536x1024.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_4167-2048x1365.jpg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_4167-50x33.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_4167-60x40.jpg 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_4167-696x464.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_4167-560x373.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_4167-444x296.jpg 444w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_4167-708x472.jpg 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_4167-80x53.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_4167-48x32.jpg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-finger-food-and-frank-q-amp-as&quot;&gt;Finger food and frank Q&amp;amp;As&lt;/h2&gt;



&lt;p&gt;The last 90 minutes were networking over finger food. This is the part of these events that is hard to engineer and easy to get wrong, but conversation flowed and the food was great. Conversations that started in the Q&amp;amp;A kept going through the networking, which is usually the sign of a room full of the right people.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;725&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.41.56-PM-1024x725.png&quot; alt=&quot;&quot; class=&quot;wp-image-53386&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.41.56-PM-1024x725.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.41.56-PM-300x212.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.41.56-PM-768x544.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.41.56-PM-1536x1088.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.41.56-PM-50x35.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.41.56-PM-56x40.png 56w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.41.56-PM-655x464.png 655w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.41.56-PM-696x493.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.41.56-PM-560x397.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.41.56-PM-418x296.png 418w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.41.56-PM-666x472.png 666w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.41.56-PM-80x57.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.41.56-PM-48x34.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.41.56-PM.png 1553w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-3 is-layout-flex wp-block-gallery-is-layout-flex&quot;&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;682&quot; data-id=&quot;53388&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.41.29-PM-1024x682.png&quot; alt=&quot;&quot; class=&quot;wp-image-53388&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.41.29-PM-1024x682.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.41.29-PM-300x200.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.41.29-PM-768x511.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.41.29-PM-1536x1023.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.41.29-PM-50x33.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.41.29-PM-60x40.png 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.41.29-PM-696x463.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.41.29-PM-560x373.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.41.29-PM-445x296.png 445w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.41.29-PM-709x472.png 709w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.41.29-PM-80x53.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.41.29-PM-48x32.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.41.29-PM.png 1565w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;713&quot; data-id=&quot;53384&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.42.35-PM-1024x713.png&quot; alt=&quot;&quot; class=&quot;wp-image-53384&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.42.35-PM-1024x713.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.42.35-PM-300x209.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.42.35-PM-768x534.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.42.35-PM-50x35.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.42.35-PM-57x40.png 57w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.42.35-PM-667x464.png 667w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.42.35-PM-696x484.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.42.35-PM-560x390.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.42.35-PM-425x296.png 425w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.42.35-PM-678x472.png 678w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.42.35-PM-80x56.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.42.35-PM-48x33.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-1.42.35-PM.png 1503w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;683&quot; data-id=&quot;53390&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_9799-1024x683.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-53390&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_9799-1024x683.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_9799-300x200.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_9799-768x512.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_9799-1536x1024.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_9799-2048x1365.jpg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_9799-50x33.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_9799-60x40.jpg 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_9799-696x464.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_9799-560x373.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_9799-444x296.jpg 444w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_9799-708x472.jpg 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_9799-80x53.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_9799-48x32.jpg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;683&quot; data-id=&quot;53396&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_0169-1-1024x683.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-53396&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_0169-1-1024x683.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_0169-1-300x200.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_0169-1-768x512.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_0169-1-1536x1024.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_0169-1-2048x1365.jpg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_0169-1-50x33.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_0169-1-60x40.jpg 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_0169-1-696x464.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_0169-1-560x373.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_0169-1-444x296.jpg 444w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_0169-1-708x472.jpg 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_0169-1-80x53.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/20260410_Evelin_BoutiqueMonaco_HR_0169-1-48x32.jpg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;
&lt;/figure&gt;



&lt;p&gt;Thanks to everyone who came out.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Yes, you can build a subscription app with AI (but it might hurt a bit)]]></title><description><![CDATA[The vibe coding hype is real — but the execution is messy ]]></description><link>https://www.revenuecat.com/blog/engineering/vibe-coding-reality-vs-hype/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/vibe-coding-reality-vs-hype/</guid><pubDate>Thu, 23 Apr 2026 12:03:43 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Blog-45_An-honest-review-of-vibe-coding-my-first-app.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;We’re in the middle of an AI-fueled hype cycle where it feels like everyone is building apps in a weekend and making $100K a month. It is as exciting as it is misleading.&lt;/p&gt;



&lt;p&gt;“Your app, &lt;em&gt;OnTimer – Never Be Late&lt;/em&gt;, is ready for distribution.”&lt;/p&gt;



&lt;p&gt;When I finally saw that message from Apple’s review team, I knew two things were true:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Yes, you can build your own mobile app with AI&lt;/li&gt;



&lt;li&gt;You’re probably not going to do it in a weekend (it took me four months)&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;I like to joke that any idiot can build an app now — just ask me how I know. But we really are living in an amazing moment. Great ideas have never been limited to a specific set of people; anyone of any background, education, or technical ability can have a million-dollar idea. The limit has always been whether those same people have the technological know-how to turn that idea into reality. Now, as we’ve all seen, AI has erased that limitation.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-reality-behind-vibe-coding-your-first-app&quot;&gt;The reality behind vibe coding your first app&lt;/h2&gt;



&lt;p&gt;I don’t know how to code.&lt;/p&gt;



&lt;p&gt;When I started building the app in November 2025, I was just trying to see what was possible with vibe coding. But each time I got something to work, or fought through a bug, I got more determined to see it through.&lt;/p&gt;



&lt;p&gt;Seeing the app in the App Store and getting my first customers has been incredibly rewarding. It was also harder than I expected.&lt;/p&gt;



&lt;p&gt;So yes, you can vibe code a real subscription app. &lt;strong&gt;Is it as easy as everyone says? &lt;/strong&gt;That’s a more nuanced answer. But I’m going to share what I learned so you can do it too, and maybe even avoid some of my mistakes.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-lesson-1-don-t-wait-for-the-perfect-idea-build-something&quot;&gt;Lesson 1: don’t wait for the perfect idea, build something&lt;/h2&gt;



&lt;p&gt;If you’ve ever gotten a frustrated text from a colleague saying, “We’re all on the Zoom, are you joining?” then you’ll understand &lt;a href=&quot;https://www.ontimer.app/&quot;&gt;OnTimer&lt;/a&gt;’s origin story.&lt;/p&gt;



&lt;p&gt;Every morning, I used to check my calendar and set alarms two minutes before my meetings. I hate being late, and regular calendar notifications are too easy to ignore. I needed something more persistent, otherwise I’d just keep writing that email or staring at a chart.&lt;/p&gt;



&lt;p&gt;So when I wanted to see what was possible with vibe coding, I didn’t go looking for the perfect idea, &lt;strong&gt;I just automated my own behavior&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;I didn’t know if it could make money, I didn’t know how many other people shared the problem. I just knew I didn’t want to wait.&lt;/p&gt;



&lt;p&gt;In a world where you can build anything, paralyzing yourself in search of that perfect, differentiated idea, is a great way to get stuck doing nothing.&amp;nbsp;&amp;nbsp;&lt;/p&gt;



&lt;p&gt;So when I saw a LinkedIn post for Supervibes, ‘The vibe coder for native apps’, I got to work.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-lesson-2-pictures-are-not-products-and-ai-often-doesn-t-know-the-difference&quot;&gt;Lesson 2: pictures are not products, and AI often doesn’t know the difference&lt;/h2&gt;



&lt;p&gt;I was blown away when my initial prompts transformed my vision for OnTimer onto the screen in minutes. It’s almost intoxicating to see your app come to life like that.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;But I quickly learned that there is a big difference between what you’re seeing and what is actually working. This has been a recurring theme throughout the process.&amp;nbsp;&amp;nbsp;&lt;/p&gt;



&lt;p&gt;I knew oAuth would need real setup, that was expected. What I didn’t expect was that the &lt;strong&gt;AI would fake things that actually mattered to the user experience&lt;/strong&gt;.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;When Supervibes initially coded the app with fake calendar data, that seemed acceptable as a starting point. But it also ‘faked’ things that would come back to bite me. On the homescreen it had created a sync icon with text that said, “Auto-syncs every 15 minutes”. As it turned out, this wasn’t a feature or setting — it was pure window-dressing, but I didn’t know to question it.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;It took me about a week to get oAuth and the initial calendar connections working. When my Xcode-connected test phone fired its first OnTimer alarm for a meeting, it was the first time I started to believe this could work.&lt;/p&gt;



&lt;p&gt;But remember earlier how I told you I was an idiot? This is where that comes back into focus.&amp;nbsp;&amp;nbsp;&lt;/p&gt;



&lt;p&gt;With the core functionality ‘working’, I spent my nights and weekends slogging through the App Store’s somewhat-convoluted process and finally sent a first build to TestFlight.&lt;/p&gt;



&lt;p&gt;That was eye-opening, and not in a good way. The full screen alarms that worked so well on my test phone, when the app was in the foreground, didn’t work at all when the app was in the background. And since the automatic sync was fake, OnTimer’s &lt;em&gt;never be late&lt;/em&gt; promise was pretty empty.&amp;nbsp;&amp;nbsp;&lt;/p&gt;



&lt;p&gt;I eventually switched from Supervibes to Claude Code, but this is a ‘gotcha’ across AI tools. The ‘pictures’ they paint feel real, but pictures aren’t products. The inconsistency between what was hard-coded in, and what wasn’t, made it near-impossible to differentiate between whether something was built and functional, or just a convincing visual.&lt;/p&gt;



&lt;p&gt;If I could go back,&amp;nbsp; I would have spent a few hours with a whiteboard before writing my first prompt and asked:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;What does success look like at each stage?&amp;nbsp;&lt;/li&gt;



&lt;li&gt;What qualifies as working?&amp;nbsp;&lt;/li&gt;



&lt;li&gt;What are my expectations as a user?&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-lesson-3-your-simple-app-might-actually-be-more-complex-than-you-think&quot;&gt;Lesson 3: your simple app might actually be more complex than you think&lt;/h2&gt;



&lt;p&gt;Sharing that first version on TestFlight early turned out to be a great decision. The feedback was swift and painful.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Connecting oAuth turned out to be the easy part. Building a persistent notification system that works in the background is not. Making the &lt;em&gt;never be late&lt;/em&gt; guarantee work when a phone is silenced is not. Syncing multiple calendars reliably is not. Every time I solved one challenge, a new one seemed to appear.&amp;nbsp;&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;473&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-29-473x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-53341&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-29-473x1024.png 473w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-29-138x300.png 138w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-29-768x1664.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-29-709x1536.png 709w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-29-23x50.png 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-29-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-29-214x464.png 214w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-29-696x1508.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-29-258x560.png 258w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-29-137x296.png 137w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-29-218x472.png 218w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-29-37x80.png 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-29-22x48.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-29.png 945w&quot; sizes=&quot;auto, (max-width: 473px) 100vw, 473px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;This is somewhat the nature of AI: what you see from the outside appears functional and sleek. Even when a problem arises, it seems to be resolved fairly simply. But behind each challenge and subsequent resolution, the respective jerry-rigged solutions become knots that come back around to haunt you. Because we only see the front of the AI tool, &lt;strong&gt;it often appears problems are solved, when actually they’ve just been plastered over&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;I learned quickly that there is a lot of complexity in building a ‘simple’ app. As a vibe coder, this is where you are kind of on your own.&lt;/p&gt;



&lt;p&gt;On a team, you have people and experience to think this stuff through. Often you avoid pitfalls because your engineers have already run into them before. With vibe coding it’s just you and an LLM. &lt;strong&gt;If you don’t ask the right questions, it’s hard to know what’s coming next.&lt;/strong&gt;&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Here’s what I should have done differently:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Asked an LLM to compare my plan to app store rules and iOS limitations&lt;/li&gt;



&lt;li&gt;Created a ‘Perfect.md’ file that described the ideal end-to-end user experience and forced Claude to align every change to it&lt;/li&gt;



&lt;li&gt;Talked through my idea with others (humans!)&amp;nbsp; to uncover challenges early&lt;/li&gt;
&lt;/ol&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-lesson-4-the-vibe-coding-landmines-are-scary-but-they-aren-t-deadly&quot;&gt;Lesson 4: the vibe coding landmines are scary, but they aren’t deadly&lt;/h2&gt;



&lt;p&gt;Three or four times as I was building OnTimer, I hit walls that seemed insurmountable.&amp;nbsp; I ran into issues that brought everything to a halt, and pushed me to the edge of my sanity.&amp;nbsp;&amp;nbsp;&lt;/p&gt;



&lt;p&gt;A few weeks in I got caught in a cycle. Identify bug → prompt Claude to fix → Claude says “Perfect, I fixed it” → nothing changes → repeat&amp;nbsp;&lt;/p&gt;



&lt;p&gt;My prompts eventually devolved into me telling Claude to “Go F%ck itself” which didn’t help.&lt;/p&gt;



&lt;p&gt;In a moment of desperation, I asked Claude to show me how to manually make a change to one word on my homescreen. I was losing my mind, and Claude couldn’t even make the simplest of changes, let alone fix the bug.&lt;/p&gt;



&lt;p&gt;Then I saw my manual change instantly revert itself. I didn’t know why, but I finally saw what was happening. It turned out an update I made was causing new code to save to a backup drive, while the live file stayed static.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;It was a week of hell, for what turned out to be a five-minute fix.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;The problem with vibe coding is that &lt;strong&gt;you don’t have the same instincts or approach engineers have&lt;/strong&gt;. We can’t look at the code the way they can. When things break, it’s easy to get lost.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;But here is what I learned: don’t keep doing the same things over and over that aren’t working, and don’t let Claude (or *insert AI tool*) do it either. Even when you try to prompt root cause analysis, it can have a tendency to just keep trying to fix the same area of your code. You have to get it out of its own way.&lt;/p&gt;



&lt;p&gt;A good tactic I have found is to use another LLM to challenge Claude. If a fix doesn’t work I bring in ChatGPT:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;I share the Claude Code thread and relevant files, and ask ChatGPT for a fresh analysis and prompt&lt;/li&gt;



&lt;li&gt;I send the prompt to Claude in Plan mode, and go back and forth between the two LLMs&lt;/li&gt;



&lt;li&gt;When it’s fixed, I update my Claude.MD file with a detailed explanation to prevent similar issues in the future&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Bugs are probably the worst part of vibe coding. They’re not just time-killers; they rob you of your confidence. It’s not fun, but the more you battle through these, the faster and better you get at it.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-lesson-5-monetize-early-you-won-t-regret-it&quot;&gt;Lesson 5: monetize early, you won’t regret it&lt;/h2&gt;



&lt;p&gt;From the beginning I knew I was going to launch OnTimer as a subscription app. Monetizing your app forces you to focus on value delivery and &lt;a href=&quot;https://www.revenuecat.com/blog/growth/product-market-fit-subscription-apps/&quot;&gt;product-market fit&lt;/a&gt;. Those are great forcing functions, even when you are still learning.&lt;/p&gt;



&lt;p&gt;You will have to make real decisions: freemium vs. paid, &lt;a href=&quot;https://www.revenuecat.com/blog/growth/7-day-trial-subscription-app/&quot;&gt;free trial lengths&lt;/a&gt;, what lives behind the paywall and what doesn’t. I chose freemium with an &lt;a href=&quot;https://www.revenuecat.com/blog/growth/annual-subscriptions-apps-pros-cons/&quot;&gt;annual subscription&lt;/a&gt;. The free tier lets users experience the core alarm functionality. The paid tier unlocks multiple calendars and Time-to-Leave departure alerts.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;472&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-8.53.29-AM-472x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-53373&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-8.53.29-AM-472x1024.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-8.53.29-AM-138x300.png 138w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-8.53.29-AM-768x1665.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-8.53.29-AM-709x1536.png 709w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-8.53.29-AM-945x2048.png 945w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-8.53.29-AM-23x50.png 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-8.53.29-AM-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-8.53.29-AM-214x464.png 214w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-8.53.29-AM-696x1509.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-8.53.29-AM-258x560.png 258w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-8.53.29-AM-137x296.png 137w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-8.53.29-AM-218x472.png 218w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-8.53.29-AM-37x80.png 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-8.53.29-AM-22x48.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-23-at-8.53.29-AM.png 1179w&quot; sizes=&quot;auto, (max-width: 472px) 100vw, 472px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Figuring out what to place behind the paywall forced me to ask myself what was valuable enough to pay for, and what needed to be free to get someone hooked. That thinking made OnTimer a better app.&lt;/p&gt;



&lt;p&gt;Monetization adds layers:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;App Store complexity:&lt;/strong&gt; subscription apps get more scrutiny from reviewers, and rejections are more painful when you’re trying to ship&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Entitlement logic:&lt;/strong&gt; your app needs to know what a user has paid for, and show it appropriately&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Paywall considerations&lt;/strong&gt;: a bad paywall doesn’t just hurt conversion, it can get your app rejected entirely&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Fortunately, RevenueCat makes this a lot faster and easier. They provide an integration prompt for vibe coders, which was like magic.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;530&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/RevenueCat-AI-prompt-1024x530.png&quot; alt=&quot;&quot; class=&quot;wp-image-53345&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/RevenueCat-AI-prompt-1024x530.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/RevenueCat-AI-prompt-300x155.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/RevenueCat-AI-prompt-768x398.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/RevenueCat-AI-prompt-1536x795.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/RevenueCat-AI-prompt-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/RevenueCat-AI-prompt-77x40.png 77w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/RevenueCat-AI-prompt-696x360.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/RevenueCat-AI-prompt-560x290.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/RevenueCat-AI-prompt-840x435.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/RevenueCat-AI-prompt-80x41.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/RevenueCat-AI-prompt-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/RevenueCat-AI-prompt.png 2048w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;I fed it into Claude and within minutes I was walking through RevenueCat’s setup guide. In less than a day I had a &lt;a href=&quot;https://www.revenuecat.com/blog/growth/paywalls-study-guide/&quot;&gt;working paywall&lt;/a&gt;.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;It wasn’t perfect. I did get rejected from the App Store twice because of a paywall issue — a nuance in the RevenueCat UI builder looked correct visually but wasn’t behaving right in practice, reverting to a default state rather than the one I’d selected. I hit customer support, quickly got it sorted, and finally got OnTimer approved.&lt;/p&gt;



&lt;p&gt;What was cool though, is that I went back into the paywall builder a few days ago, and the issue I ran into had been fixed. It’s great when your feedback helps the next developer avoid the same pitfall.&lt;/p&gt;



&lt;p&gt;RevenueCat did the heavy lifting so that I could focus on developing the app’s core value. They handle the logistics of your subscription infrastructure so you can stay focused on building something people want to pay for.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;So, I really encourage you to monetize early because:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;It forces honest conversations about value: &lt;/strong&gt;if someone won’t pay for it, that’s information — find out early&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Subscribers give better feedback than free users:&lt;/strong&gt; they have skin in the game and they want it to work&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Revenue changes your psychology: &lt;/strong&gt;even a few dollars a month makes you more serious about shipping and improving&lt;/li&gt;
&lt;/ol&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-go-build-your-first-app-it-s-worth-it&quot;&gt;Go build your first app, it’s worth it&lt;/h2&gt;



&lt;p&gt;You should absolutely go build your first app. It’s not as easy as the hype makes it sound. Things break, and you hit walls. You have moments of real frustration and doubt.&lt;/p&gt;



&lt;p&gt;But you also have moments of amazing accomplishment. Yesterday I had a doctor’s appointment, and OnTimer’s Time-to-Leave feature fired off an alarm based on traffic and distance.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;I built that!&lt;/strong&gt;&amp;nbsp;&lt;/p&gt;



&lt;p&gt;…Okay, Claude helped.&amp;nbsp;&amp;nbsp;&lt;/p&gt;



&lt;p&gt;The point is that vibe coding is real. You may not make $100K/month right off the bat like many on LinkedIn and X would have you believe — it will probably take longer than you expect. It took me about four months to launch. But if you push through the hard parts, you can build something you are proud of.&lt;/p&gt;



&lt;p&gt;Now I’m shipping, learning, and even starting to see the first signs of revenue. The next challenge is growing it, and that’s going to be hard too.&lt;/p&gt;



&lt;p&gt;But I’m in it now, and you can bet this won’t be the only app I build.&lt;/p&gt;



&lt;p&gt;AI got me started. &lt;strong&gt;Persistence is what got me here.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;&lt;em&gt;Check out &lt;/em&gt;&lt;a href=&quot;https://apps.apple.com/us/app/ontimer-never-be-late/id6755317601&quot;&gt;&lt;em&gt;OnTimer – Never be late on the App Store&lt;/em&gt;&lt;/a&gt;&lt;em&gt;!&lt;/em&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[How to add trial notifications to your subscriptions]]></title><description><![CDATA[Remind your customers that their trial is about to expire and build trust]]></description><link>https://www.revenuecat.com/blog/engineering/how-to-add-trial-notifications-to-your-subscriptions/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/how-to-add-trial-notifications-to-your-subscriptions/</guid><pubDate>Wed, 22 Apr 2026 14:50:05 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Blog_27_How-to-add-trial-notifications-to-your-subscriptions.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Free trials are one of the best ways to convert users into paying subscribers — but they can backfire. When a user forgets they started a trial, the unexpected charge feels like a betrayal. They refund, leave a bad review, and never come back. Even worse, that one bad experience can make them reluctant to try any subscription app again. &lt;/p&gt;



&lt;p&gt;A simple &lt;strong&gt;reminder notification a day or two before the trial converts changes the dynamic entirely&lt;/strong&gt;. The user feels respected, not tricked. They either cancel (which they would have anyway) or they convert knowing exactly what they’re paying for. Either way, you build trust — and trust is what drives long-term retention.&lt;/p&gt;



&lt;p&gt;I’ve written about building trial reminders before using &lt;a href=&quot;https://claude.ai/local_sessions/link&quot;&gt;RevenueCat and Zapier&lt;/a&gt; to power email-based notifications. In this tutorial, we’ll build a similar system using local and remote push notifications in React Native — though the same concepts apply to Kotlin and Swift.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-to-plan-trial-reminders&quot;&gt;How to plan trial reminders&lt;/h2&gt;



&lt;p&gt;Trial reminders don’t have to be complicated, but sending out more than one reminder builds trust, and removes uncertainty. I would recommend a lightweight three-notification pattern:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-activation-nudge-same-day&quot;&gt;1. Activation nudge (same day)&lt;/h3&gt;



&lt;p&gt;Send a notification on the first day, highlighting a feature they have not yet tried, in order to signal that the notifications work, and to get them to experience their first “aha moment” during the trial.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-mid-trial-reminder-two-days-before-end&quot;&gt;2. Mid-trial reminder (two days before end)&lt;/h3&gt;



&lt;p&gt;Two days before the trial is about to expire, remind them that the trial is ongoing and that it will expire in the next few days. You will most likely see users cancelling their trial at this point — that is to be expected. That gives you a chance to capture them with a win-back offer, for example.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-trial-ending-alert-morning-of-last-day&quot;&gt;3. Trial-ending alert (morning of last day)&lt;/h3&gt;



&lt;p&gt;On the morning of the last day, send a transparent, helpful reminder:&lt;/p&gt;



&lt;p&gt;&lt;em&gt;“Your trial ends today. Keep access by staying on your plan — or cancel anytime.”&lt;/em&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-to-implement-trial-notifications-in-react-native&quot;&gt;How to implement trial notifications in React Native&lt;/h2&gt;



&lt;p&gt;There are two approaches: local notifications (no server needed) and remote notifications (requires a small backend). We’ll walk through both, starting with local.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-local-notifications-approach&quot;&gt;Local notifications approach&lt;/h3&gt;



&lt;p&gt;With local notifications, all the reminder logic lives on the device — no server needed. When a user starts a trial, you grab the trial expiration date from RevenueCat’s customerInfo.entitlements (specifically the expirationDate on the active entitlement), then schedule notifications relative to that date.&lt;/p&gt;



&lt;p&gt;Local notifications are the simplest approach — very little code and no backend to maintain. The trade-off is that the notification schedule can only update when the user opens your app. If someone cancels their trial through the App Store settings page, for example, the app won’t know to unschedule the reminders until it’s opened again. The same applies if they switch to a plan without a trial.&lt;/p&gt;



&lt;p&gt;Additionally, local notifications will fail if the user’s device is powered off, and orchestrating other notification channels such as email is harder with local notifications. Some Android phones also have limitations on delivering local notifications at the exact scheduled time.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-remote-notifications&quot;&gt;Remote notifications&lt;/h3&gt;



&lt;p&gt;The alternative to local notifications is a server-driven approach. You run a lightweight backend that listens for RevenueCat webhook events and schedules or cancels trial reminders accordingly.&lt;/p&gt;



&lt;p&gt;This approach takes more work to set up, but it’s significantly more reliable. You can update notification content without shipping an app update, use multiple channels (push notifications and email, for instance), and cancel reminders immediately when a user unsubscribes — no app open required. The backend itself doesn’t need to be complex: a single endpoint that digests webhooks and schedules notifications is all you need.&lt;/p&gt;



&lt;p&gt;On the client side you only need to take care to store users’ push notification token, which is something RevenueCat can actually help you manage. You can &lt;a href=&quot;https://www.revenuecat.com/docs/customers/customer-attributes#setting-push-tokens&quot;&gt;save push tokens in Attributes&lt;/a&gt;, from which they are available using either REST API or Webhooks.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-choosing-a-notification-package-to-use&quot;&gt;Choosing a notification package to use&lt;/h2&gt;



&lt;p&gt;React Native does not come with notifications included, so you need to install and configure an external dependency to run them. Here are a few options that support both remote and local notifications:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/expo/expo/tree/main/packages/expo-notifications&quot;&gt;&lt;strong&gt;Expo Notifications&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;Expo notifications is excellent for notifications, especially if you have an Expo project. This tutorial will use Expo Notifications for the examples.&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://github.com/wix/react-native-notifications&quot;&gt;&lt;strong&gt;react-native-notifications&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;Wix has been maintaining their own notification package for React Native for over 10 years already. It’s stable and has all the features you need for notifications.&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://github.com/invertase/notifee&quot;&gt;&lt;strong&gt;@notifee/react-native&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;Notifee is a feature rich notification library for both iOS and Android. It’s especially powerful when you want rich notifications, with images, custom sounds and interactability.&lt;/li&gt;
&lt;/ol&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-subscription-reminders-with-local-notifications&quot;&gt;Subscription reminders with local notifications&lt;/h2&gt;



&lt;p&gt;The next parts assume that you’ve installed and configured your notification package for your project.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-1-create-a-trial-schedule-object&quot;&gt;Step 1: create a trial schedule object&lt;/h3&gt;



&lt;p&gt;We will want to remind users three different times, so let’s build a trial object that will be used for scheduling when and containing the messages we want to send. The following trialSchedule follows the 3-part trial reminder structure we discussed earlier.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-19LJYk wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;export interface TrialReminder {\n  id: string;\n  \/** Ms after trial start. Used when useEndOffset is false. *\/\n  delayFromStart: number;\n  \/** Ms before trial end. Used when useEndOffset is true. *\/\n  beforeEnd: number;\n  title: string;\n  body: string;\n  \/** If true, schedule relative to trial end (beforeEnd). If false, schedule relative to trial start (delayFromStart). *\/\n  useEndOffset: boolean;\n}\n\nexport const trialSchedule: TrialReminder[] = [\n  {\n    id: \&amp;quot;trial_activation\&amp;quot;,\n    delayFromStart: 6 * 60 * 60 * 1000, \/\/ 6 hours after start\n    beforeEnd: 0,\n    title: \&amp;quot;Your trial is active \ud83c\udf89\&amp;quot;,\n    body: \&amp;quot;Have you tried [Feature X] yet? Tap to explore what&apos;s included.\&amp;quot;,\n    useEndOffset: false,\n  },\n  {\n    id: \&amp;quot;trial_mid_reminder\&amp;quot;,\n    delayFromStart: 0,\n    beforeEnd: 2 * 24 * 60 * 60 * 1000, \/\/ 2 days before end\n    title: \&amp;quot;Your trial ends in 2 days\&amp;quot;,\n    body: \&amp;quot;Just a heads-up: your free trial expires soon. Make the most of it!\&amp;quot;,\n    useEndOffset: true,\n  },\n  {\n    id: \&amp;quot;trial_ending\&amp;quot;,\n    delayFromStart: 0,\n    beforeEnd: 8 * 60 * 60 * 1000, \/\/ morning of last day\n    title: \&amp;quot;Your trial ends today\&amp;quot;,\n    body: \&amp;quot;Keep access by staying on your plan \u2014 or cancel anytime.\&amp;quot;,\n    useEndOffset: true,\n  },\n];&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-2-schedule-notifications-during-subscription-process&quot;&gt;Step 2: schedule notifications during subscription process&lt;/h3&gt;



&lt;p&gt;Scheduling the trial reminders will happen when users subscribe. We can use getCustomerInfo to check if user is running a trial:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-29NCE1 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;import * as Notifications from \&amp;quot;expo-notifications\&amp;quot;;\nimport Purchases from \&amp;quot;react-native-purchases\&amp;quot;;\nimport { trialSchedule } from \&amp;quot;.\/trialSchedule\&amp;quot;;\n\nasync function scheduleTrialReminders(trialEndDate: Date): Promise&lt;void&gt; {\n  const endMs = trialEndDate.getTime();\n\n  for (const reminder of trialSchedule) {\n    const triggerMs = reminder.useEndOffset\n      ? endMs - reminder.beforeEnd\n      : Date.now() + reminder.delayFromStart;\n\n    \/\/ Don&apos;t schedule reminders in the past\n    if (triggerMs &lt;= Date.now()) continue;\n\n    await Notifications.scheduleNotificationAsync({\n      identifier: reminder.id,\n      content: {\n        title: reminder.title,\n        body: reminder.body,\n      },\n      trigger: { date: new Date(triggerMs) },\n    });\n  }\n}\n\nconst customerInfo = await Purchases.getCustomerInfo();\nconst sub = customerInfo.subscriptionsByProductIdentifier[\&amp;quot;your_product_id\&amp;quot;];\n\nif (sub &amp;amp;&amp;amp; sub.periodType === \&amp;quot;TRIAL\&amp;quot;) {\n  const trialEnd = sub.expiresDate;   \/\/ when the trial expires\n  const willConvert = sub.willRenew;  \/\/ will it auto-convert to paid?\n  const isSandbox = sub.isSandbox;    \/\/ skip reminders for sandbox\n\n  if (trialEnd &amp;amp;&amp;amp; willConvert &amp;amp;&amp;amp; !isSandbox) {\n    await scheduleTrialReminders(new Date(trialEnd));\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-3-unschedule-notifications-on-unsubscribe&quot;&gt;Step 3: unschedule notifications on unsubscribe&lt;/h3&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1qLCxO wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;import * as Notifications from \&amp;quot;expo-notifications\&amp;quot;;\nimport Purchases from \&amp;quot;react-native-purchases\&amp;quot;;\nimport { trialSchedule } from \&amp;quot;.\/trialSchedule\&amp;quot;;\n\nasync function cancelTrialReminders() {\n  for (const reminder of trialSchedule) {\n    await Notifications.cancelScheduledNotificationAsync(reminder.id);\n  }\n}\n\nasync function handleSubscriptionChange() {\n  const customerInfo = await Purchases.getCustomerInfo();\n  const entitlement = customerInfo.entitlements.active[\&amp;quot;your_entitlement_id\&amp;quot;];\n\n  \/\/ Only cancel reminders if the user previously had an active entitlement\n  \/\/ but is no longer in a trial (converted to paid, cancelled, or expired)\n  if (!entitlement) {\n    \/\/ No active entitlement at all \u2014 could be a fresh user, don&apos;t cancel\n    return;\n  }\n\n  if (entitlement.periodType !== \&amp;quot;TRIAL\&amp;quot;) {\n    \/\/ Entitlement is active but no longer a trial \u2014 cancel pending reminders\n    await cancelTrialReminders();\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-subscription-reminders-with-remote-notifications&quot;&gt;Subscription reminders with remote notifications&lt;/h2&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-1-store-users-push-tokens&quot;&gt;Step 1: store users’ push tokens&lt;/h3&gt;



&lt;p&gt;The first step to adding remote trial notifications is to track the users’ push tokens. This is made easy with RevenueCat Attributes, where you can store additional structured information about customers. These attributes can later be read using the REST API.&lt;/p&gt;



&lt;p&gt;If you take a look at the &lt;a href=&quot;https://www.revenuecat.com/docs/customers/customer-attributes#reserved-attributes&quot;&gt;documentation for Attributes&lt;/a&gt;, you see that both $apnsTokens and $fcmTokens are reserved attributes. This means that we can store push tokens in RevenueCat as well. Doing that through code is just a few lines:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-2kXQEl wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;import * as Notifications from \&amp;quot;expo-notifications\&amp;quot;;\nimport Purchases from \&amp;quot;react-native-purchases\&amp;quot;;\n\nasync function registerPushToken() {\n  const { status } = await Notifications.requestPermissionsAsync();\n  if (status !== \&amp;quot;granted\&amp;quot;) return;\n\n  const devicePushToken = await Notifications.getDevicePushTokenAsync();\n  await Purchases.setPushToken(devicePushToken.data);\n\n  \/\/ Optionally store Expo push token for Expo&apos;s push service.\n  \/\/ Note: getExpoPushTokenAsync() requires a projectId in bare workflow.\n  \/\/ Find yours at https:\/\/expo.dev under your project settings.\n  const expoPushToken = await Notifications.getExpoPushTokenAsync({\n    projectId: \&amp;quot;your-expo-project-id\&amp;quot;,\n  });\n  await Purchases.setAttributes({\n    $expoPushToken: expoPushToken.data,\n  });\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;That is all that is needed from the client side, as long as you have configured your notifications correctly. The rest of the tutorial will focus on what needs to happen on the server side.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-2-build-a-notification-backend&quot;&gt;Step 2: build a notification backend&lt;/h3&gt;



&lt;p&gt;All of the logic for trial reminders will happen on the backend side. For this we need to build an endpoint that accepts webhooks from RevenueCat and then schedules notifications based on those. To understand which types of Webhook events we need to support, we can take a look at the &lt;a href=&quot;https://www.revenuecat.com/docs/integrations/webhooks/sample-events&quot;&gt;webhook sample events&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;In this example we are going to use a Cloudflare worker, but it’s not a requirement. You could also build this using Zapier and OneSignal.&lt;/p&gt;



&lt;p&gt;Here’s some example code:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1kTJxK wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;\/\/ Cloudflare Worker\nexport default {\n  async fetch(request: Request, env: Env): Promise&lt;Response&gt; {\n    const authHeader = request.headers.get(\&amp;quot;Authorization\&amp;quot;);\n    if (authHeader !== `Bearer ${env.RC_WEBHOOK_SECRET}`) {\n      return new Response(\&amp;quot;Unauthorized\&amp;quot;, { status: 401 });\n    }\n\n    const payload = await request.json();\n    const {\n      type,\n      app_user_id,\n      period_type,\n      purchased_at_ms,\n      expiration_at_ms,\n      cancel_reason,\n      subscriber_attributes,\n    } = payload.event;\n\n    if (type === \&amp;quot;INITIAL_PURCHASE\&amp;quot; &amp;amp;&amp;amp; period_type === \&amp;quot;TRIAL\&amp;quot;) {\n      \/\/ New trial started \u2014 schedule all three reminders\n      await scheduleTrialReminders(env, {\n        userId: app_user_id,\n        purchasedAt: purchased_at_ms,\n        expiresAt: expiration_at_ms,\n        pushToken: subscriber_attributes?.$expoPushToken?.value,\n      });\n    } else if (type === \&amp;quot;CANCELLATION\&amp;quot; &amp;amp;&amp;amp; cancel_reason === \&amp;quot;UNSUBSCRIBE\&amp;quot;) {\n      \/\/ User explicitly cancelled during trial \u2014 cancel pending reminders\n      await cancelTrialReminders(env, app_user_id);\n    } else if (type === \&amp;quot;EXPIRATION\&amp;quot;) {\n      \/\/ Trial or subscription expired without renewal \u2014 cancel pending reminders\n      await cancelTrialReminders(env, app_user_id);\n    } else if (type === \&amp;quot;TRIAL_CONVERTED\&amp;quot;) {\n      \/\/ Trial successfully converted to paid \u2014 no need to send trial-ending reminders\n      await cancelTrialReminders(env, app_user_id);\n    }\n\n    return new Response(\&amp;quot;OK\&amp;quot;, { status: 200 });\n  },\n\n  \/\/ Cron: runs hourly to send due notifications\n  async scheduled(event: ScheduledEvent, env: Env) {\n    await sendDueNotifications(env);\n  },\n};\n\n\/\/ scheduleTrialReminders, cancelTrialReminders, and sendDueNotifications\n\/\/ are backend helpers you implement to store\/retrieve scheduled notifications\n\/\/ and dispatch them via your push provider (e.g. Expo Push API, FCM, APNs).&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Let’s go through the main functions of the code.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Unwrapping the webhook payload is the first step.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;The POST request from RevenueCat webhook is sent to our worker which then unwraps the contents. In this case the interesting parts are:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;period_type, tells us if the subscription is TRIAL type&lt;/li&gt;



&lt;li&gt;purchased_at_ms, tells us when user made the purchase&lt;/li&gt;



&lt;li&gt;expiration_at_ms, tells us when the trial will convert&lt;/li&gt;



&lt;li&gt;subscriber_attributes, from here we can get the push notification token to use&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;&lt;strong&gt;Scheduling notifications&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;In our code we check first if the purchase is trial type, then we schedule a notification 6 hours from that if the purchase was made before 12pm, otherwise we schedule it for the next day. Then we schedule a mid-trial reminder 2 days before the trial ends. Last scheduled reminder is set for the morning of the expiring subscription. If the subscription expires in the morning, we schedule it for the evening of the previous day.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Unscheduling notifications&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;The last logic we have for the apps is that we unschedule the notification if the user cancels the trial. In this case we monitor for the cancel_reason being UNSUBSCRIBE and then remove the scheduled notifications.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Running logic to send notifications periodically&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;The last part of the code is that we run a different worker every hour to send notifications to users based on their scheduled times. This is done through a cron job.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-3-enable-webhooks-in-the-revenuecat-dashboard&quot;&gt;Step 3: enable webhooks in the RevenueCat dashboard&lt;/h3&gt;



&lt;p&gt;Navigate to the RevenueCat dashboard, and select the &lt;strong&gt;Integrations&lt;/strong&gt; tab from the sidebar. Under &lt;strong&gt;Core Tools&lt;/strong&gt;, select &lt;strong&gt;Webhooks&lt;/strong&gt;. Click &lt;strong&gt;Add Webhook&lt;/strong&gt; and set the Delivery URL to your worker endpoint (e.g. &lt;code&gt;https://your-worker.your-subdomain.workers.dev&lt;/code&gt;). Set the Authorization header to match the &lt;code&gt;RC_WEBHOOK_SECRET&lt;/code&gt; you configured in your worker. Make sure to enable at minimum the &lt;code&gt;INITIAL_PURCHASE&lt;/code&gt;, &lt;code&gt;CANCELLATION&lt;/code&gt;, &lt;code&gt;EXPIRATION&lt;/code&gt;, and &lt;code&gt;TRIAL_CONVERTED&lt;/code&gt; event types.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-wrap-up&quot;&gt;Wrap-up&lt;/h2&gt;



&lt;p&gt;Trial notifications are one of the fastest, lowest-effort ways to improve trial quality and conversion. With clear data (purchasedDate, expiresDate) and a small amount of React Native code, you can build a trust-first notification flow that feels more like Blinkist — transparent, helpful, and user-centred.&lt;/p&gt;



&lt;p&gt;Start with the three-message sequence, keep the messaging honest, and iterate based on user behavior. You’ll see the lift.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[How an email list became a 15-year safety net for a solo app developer]]></title><description><![CDATA[Joe Allen built Teleprompter Pro without a CS degree, a marketing budget, or a plan — and it still became his full-time business.]]></description><link>https://www.revenuecat.com/blog/growth/joe-allen-teleprompter-pro-launched-podcast-2026/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/joe-allen-teleprompter-pro-launched-podcast-2026/</guid><pubDate>Wed, 22 Apr 2026 12:58:17 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/LD-Blog-Cover-Joe-Allen-1.png" length="0" type="image/*"/><content:encoded>&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;How a Videographer Turned a Workaround into a Full-Time App Business — Joe Allen, Teleprompter Pro&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/4icSRmG-CIE?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;iframe loading=&quot;lazy&quot; width=&quot;100%&quot; height=&quot;180&quot; frameborder=&quot;no&quot; scrolling=&quot;no&quot; seamless=&quot;&quot; src=&quot;https://share.transistor.fm/e/13d58f29?color=FFFFFF&amp;amp;background=30343C&quot;&gt;&lt;/iframe&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-personal-workaround-that-became-a-business&quot;&gt;&lt;strong&gt;The personal workaround that became a business&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Teleprompter Pro didn’t start with market research; it started with a frustrating freelance video gig. In 2010, Joe was a 19-year-old freelance videographer working on a low-budget pilot. They needed a teleprompter, but he was “too cool to write on a piece of paper and hold it.”&lt;/p&gt;



&lt;p&gt;He tried using Apple Pages on a first-generation iPad to scroll text, but the experience was clunky. He couldn’t even easily get a black background. Having recently downloaded Xcode, he decided to build a simple scrolling text app himself.&lt;/p&gt;



&lt;p&gt;“It just sort of moved some text up,” he recalls. But when he put it on the App Store alongside a few other random projects, it was the only one that gained traction. It solved a genuine problem for people doing video production. For the next seven years, that simple utility app generated steady, organic revenue while Joe worked a full-time job in web and graphic design. It wasn’t until 2018 that the app’s revenue allowed him to quit his job and go full-time indie.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-app-store-river-and-the-illusion-of-control&quot;&gt;&lt;strong&gt;The App Store river and the illusion of control&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Many developers attribute every spike in downloads to a brilliant new feature they just shipped. Joe takes a more humbling view of his app’s growth trajectory.&lt;/p&gt;



&lt;p&gt;“I think we assume that literally everything is happening to us and that we’re responsible for any of the success,” he notes. The reality is that the App Store is a massive river. Sometimes your app is just sitting right in the current, benefiting from a small algorithmic tweak or a new search trend.&lt;/p&gt;



&lt;p&gt;Joe embraced this reality early on. “We’ve never, ever had a day of zero revenue ever,” he says, even during the years when he was barely updating the app. Accepting that he didn’t control every single variable freed him from constantly chasing the algorithm. Instead, he could focus on building a reliable product and let organic momentum do the heavy lifting.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-unexpected-roi-of-personal-customer-support&quot;&gt;&lt;strong&gt;The unexpected ROI of personal customer support&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;When Joe finally transitioned to full-time indie development, he found himself spending an enormous amount of time answering customer support emails. Many were simple questions—like explaining that a user’s orientation lock was on—but he felt a deep responsibility to ensure every user got a helpful answer.&lt;/p&gt;



&lt;p&gt;While it consumed his working days, that direct line to users became his most valuable product research tool. “A lot of questions we get are just super simple… but I sort of feared that that would turn into one-star reviews or someone abandoning the product,” he explains.&lt;/p&gt;



&lt;p&gt;Those conversations led to crucial feature additions, like adding a video recording option, and eventually highlighted the need for better onboarding. More importantly, taking the time to personally respond built immense goodwill. Users who were initially frustrated often became loyal advocates, simply because they received a genuine reply from the app’s creator rather than an automated corporate response.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-why-an-email-list-is-the-ultimate-safety-net&quot;&gt;&lt;strong&gt;Why an email list is the ultimate safety net&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;If there is one piece of advice Joe insists on, it’s the importance of owning your audience. From the very early days, he asked users for an email address. He didn’t have a grand marketing plan; he just liked the idea of being able to announce cool things to people.&lt;/p&gt;



&lt;p&gt;That simple decision became the foundation of his business stability. “I’m quite convinced that that is the single most important thing I ever did for my career,” he says.&lt;/p&gt;



&lt;p&gt;When he transitioned Teleprompter Pro from a paid upfront model to a subscription model in 2020, he didn’t have to rely on App Store release notes to communicate the change. He could email his users directly, explain that existing customers were grandfathered in, and offer a discount to those on the fence. When he launched his new app, Captions (Recap), earlier this week, he emailed a segmented list of users who actively record video, offering them the Pro upgrade for free if they pre-ordered.&lt;/p&gt;



&lt;p&gt;The App Store algorithm can change overnight, but an email list ensures you never have to start from zero.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=4icSRmG-CIE&quot;&gt;In the full episode&lt;/a&gt;, Joe also discusses the stress of navigating an unexpected “spam” rejection from App Store Review for his new app, the benefits of attending industry events, and why slow, steady growth is often the healthiest path for indie developers.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-guest-links&quot;&gt;Guest links:&lt;/h2&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://teleprompterpro.com/&quot;&gt;Teleprompter Pro&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://captionsapp.com/&quot;&gt;Captions&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.linkedin.com/in/joe-allen-5746671b/&quot;&gt;Joe Allen LinkedIn&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title><![CDATA[Build web funnels with Stripe Billing and Managed Payments in RevenueCat Web]]></title><description><![CDATA[Build web purchase flows on Stripe with billing, checkout, and merchant-of-record support now across RevenueCat Web.]]></description><link>https://www.revenuecat.com/blog/company/stripe-managed-payments-revenuecat-web/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/company/stripe-managed-payments-revenuecat-web/</guid><pubDate>Wed, 22 Apr 2026 12:03:04 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Blog-43_Build-web-funnels-with-Stripe-Billing-and-Managed-Payments-in-RevenueCat-Web.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;If you build on Stripe and want a merchant-of-record path for web, you can now do more in RevenueCat Web: by using &lt;a href=&quot;https://www.revenuecat.com/integrations/stripe/&quot;&gt;Stripe Billing&lt;/a&gt; and &lt;a href=&quot;https://www.revenuecat.com/docs/web/integrations/stripe/stripe-managed-payments&quot;&gt;Stripe Managed Payments&lt;/a&gt; across Web Purchase Links, Web Paywalls, Funnels, and the Web SDK.&lt;/p&gt;



&lt;p&gt;This gives you a powerful toolkit to build web purchase flows, with Stripe at the center of billing and checkout. For eligible flows, you can also use Stripe Managed Payments, which adds a Stripe-native merchant-of-record option to the same web monetization path.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-stripe-in-revenuecat-web&quot;&gt;Stripe in RevenueCat Web&lt;/h2&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;Stripe Billing Managed Payments with RevenueCat Web&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/BqgnJpfnsa0?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;As web monetization becomes a bigger part of your app business, your stack needs to hold together. You want purchase flows on the web, billing that still makes sense, and tools that don’t force you to rebuild everything around a new system.&lt;/p&gt;



&lt;p&gt;With RevenueCat Web, you can now combine &lt;a href=&quot;https://www.revenuecat.com/integrations/stripe/&quot;&gt;Stripe Billing&lt;/a&gt; and &lt;a href=&quot;https://www.revenuecat.com/docs/web/integrations/stripe/stripe-managed-payments&quot;&gt;Stripe Managed Payments&lt;/a&gt; with the touchpoints you already use to launch and scale purchase flows like your paywall and checkout. Billing, checkout, and web monetization can now work together in one Stripe-based path inside RevenueCat Web.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-across-paywalls-links-funnels-and-the-web-sdk&quot;&gt;Across paywalls, links, funnels, and the Web SDK&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;685&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Ecosystem-1-1024x685.png&quot; alt=&quot;&quot; class=&quot;wp-image-53325&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Ecosystem-1-1024x685.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Ecosystem-1-300x201.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Ecosystem-1-768x514.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Ecosystem-1-1536x1028.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Ecosystem-1-2048x1370.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Ecosystem-1-50x33.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Ecosystem-1-60x40.png 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Ecosystem-1-694x464.png 694w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Ecosystem-1-696x466.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Ecosystem-1-560x375.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Ecosystem-1-442x296.png 442w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Ecosystem-1-706x472.png 706w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Ecosystem-1-80x54.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Ecosystem-1-48x32.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;This support shows up in the places where you build and sell. You can use Stripe-backed billing and checkout across the main RevenueCat Web features that shape your web monetization journey.&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Features&lt;/th&gt;&lt;th&gt;What you can do&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Funnels&lt;/td&gt;&lt;td&gt;Build end-to-end acquisition and conversion flows on top of Stripe&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Web SDK&lt;/td&gt;&lt;td&gt;Build Stripe-powered purchase flows directly into your web experience&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Web Purchase Links&lt;/td&gt;&lt;td&gt;Launch shareable purchase flows backed by Stripe Billing and Managed Payments&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Web Paywalls&lt;/td&gt;&lt;td&gt;Present web paywalls tied to Stripe-backed products and checkout&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;That range matters. You are not adding one checkout button to one page, you’re bringing Stripe into RevenueCat Web across the touchpoints that support acquisition, conversion, and lifecycle flows.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-stripe-managed-payments-in-revenuecat-web&quot;&gt;Stripe Managed Payments in RevenueCat Web&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;576&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Stripe-Manged-Payments-2-1024x576.png&quot; alt=&quot;&quot; class=&quot;wp-image-53356&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Stripe-Manged-Payments-2-1024x576.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Stripe-Manged-Payments-2-300x169.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Stripe-Manged-Payments-2-768x432.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Stripe-Manged-Payments-2-1536x864.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Stripe-Manged-Payments-2-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Stripe-Manged-Payments-2-71x40.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Stripe-Manged-Payments-2-696x392.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Stripe-Manged-Payments-2-560x315.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Stripe-Manged-Payments-2-526x296.png 526w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Stripe-Manged-Payments-2-840x472.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Stripe-Manged-Payments-2-80x45.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Stripe-Manged-Payments-2-48x27.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Stripe-Manged-Payments-2.png 1920w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;If merchant-of-record matters to you, this release matters even more. It affects how you handle tax, operational overhead, and the structure of your checkout flow.&lt;/p&gt;



&lt;p&gt;Alongside Stripe-backed billing in RevenueCat Web, you now have a path to use &lt;a href=&quot;https://www.revenuecat.com/docs/web/integrations/stripe/stripe-managed-payments&quot;&gt;Stripe Managed Payments&lt;/a&gt; for eligible flows through Stripe Checkout — which is especially relevant if you want a merchant-of-record model without moving away from Stripe.&lt;/p&gt;



&lt;p&gt;The benefits are straightforward:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;More choice in how you build on web&lt;/li&gt;



&lt;li&gt;More continuity with your existing Stripe setup&lt;/li&gt;



&lt;li&gt;A clear Stripe-based path to merchant-of-record in RevenueCat Web features you use to drive conversion&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-the-stack-works&quot;&gt;How the stack works&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;691&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/simplified-1024x691.png&quot; alt=&quot;&quot; class=&quot;wp-image-53329&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/simplified-1024x691.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/simplified-300x203.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/simplified-768x519.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/simplified-1536x1037.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/simplified-2048x1383.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/simplified-50x34.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/simplified-59x40.png 59w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/simplified-687x464.png 687w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/simplified-696x470.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/simplified-560x378.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/simplified-438x296.png 438w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/simplified-699x472.png 699w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/simplified-80x54.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/simplified-48x32.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Each part of the Stripe stack plays a different role:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Stripe Billing handles your subscription and billing setup&lt;/li&gt;



&lt;li&gt;Stripe Managed Payments gives you a merchant-of-record model for eligible flows&lt;/li&gt;



&lt;li&gt;RevenueCat Web brings those pieces into the paywalls, links, funnels, and SDK flows you use to sell on the web&lt;/li&gt;
&lt;/ol&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Layer&lt;/th&gt;&lt;th&gt;What it means for you&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Stripe Billing&lt;/td&gt;&lt;td&gt;Your subscriptions and billing system live in Stripe&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Stripe Managed Payments&lt;/td&gt;&lt;td&gt;You get Stripe’s merchant-of-record model for eligible flows&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;RevenueCat Web&lt;/td&gt;&lt;td&gt;You use these capabilities across paywalls, links, funnels, and SDK-driven experiences&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;You can keep Stripe at the center while using RevenueCat Web to launch and optimize the purchase experience around it.&lt;/p&gt;



&lt;p&gt;More app teams now treat web as a serious monetization opportunity. This changes what you need from your stack. You need purchase flows that fit your product, billing that fits your business, and infrastructure that supports how you test, package, and iterate on the web.&lt;/p&gt;



&lt;p&gt;By combing Stripe Billing and Stripe Managed Payments with RevenueCat, you now have a stronger option to do just that.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-start-building&quot;&gt;Start building&lt;/h2&gt;



&lt;p&gt;If you already use Stripe and want to bring merchant-of-record into your web monetization setup, now is a good time to take a closer look. You can build Stripe-powered purchase flows in RevenueCat Web with support for both &lt;a href=&quot;https://www.revenuecat.com/integrations/stripe/&quot;&gt;Stripe Billing&lt;/a&gt; and &lt;a href=&quot;https://www.revenuecat.com/docs/web/integrations/stripe/stripe-managed-payments&quot;&gt;Stripe Managed Payments&lt;/a&gt;.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;800&quot; height=&quot;800&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/webforapps.avif&quot; alt=&quot;&quot; class=&quot;wp-image-53331&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/webforapps.avif 800w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/webforapps-300x300.avif 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/webforapps-150x150.avif 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/webforapps-768x768.avif 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/webforapps-50x50.avif 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/webforapps-40x40.avif 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/webforapps-464x464.avif 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/webforapps-696x696.avif 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/webforapps-560x560.avif 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/webforapps-296x296.avif 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/webforapps-472x472.avif 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/webforapps-80x80.avif 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/webforapps-48x48.avif 48w&quot; sizes=&quot;auto, (max-width: 800px) 100vw, 800px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Start with the docs, review the setup and eligibility details, and map the first flow you want to launch. You can also join us at our Stripe Sessions pre-event on April 28th to see how app teams are approaching web funnels, web-to-app, and app-to-web growth: &lt;a href=&quot;https://luma.com/webforapps&quot;&gt;Reserve your spot&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;If you are building on web with Stripe, you now have a stronger path to do it in RevenueCat.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Announcing Paywall rules: show or hide paywall components]]></title><description><![CDATA[Change visibility of components based on rules]]></description><link>https://www.revenuecat.com/blog/engineering/announcing-paywall-rules-show-or-hide-paywall-components/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/announcing-paywall-rules-show-or-hide-paywall-components/</guid><pubDate>Wed, 22 Apr 2026 10:02:06 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/customize-with-Paywall-Rules.png" length="0" type="image/*"/><content:encoded>&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;Paywall rules: show or hide paywall components&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/nh-6FXU1-oY?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;RevenueCat Paywalls is the easiest way to build custom paywalls for your app. Combined with RevenueCat Targeting, it allows you to serve a different paywall to different customers without having to make new releases. And now, with the release of the new &lt;strong&gt;Paywall Rules feature&lt;/strong&gt; you can take personalized paywalls even further, without having to make new paywalls.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/tools/paywalls/creating-paywalls/rules&quot;&gt;Paywall Rules&lt;/a&gt; allow you to customize the visibility of paywall components based on both preset and Custom Variable based rules, enabling you to &lt;strong&gt;customize a single paywall to support multiple scenarios&lt;/strong&gt;.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-hides-components-when-a-package-is-selected-and-more&quot;&gt;Hides components when a package is selected, and more&lt;/h2&gt;



&lt;p&gt;What do Paywall Rules look like in practice? &lt;/p&gt;



&lt;p&gt;One example is using Paywall Rules to show a trial timeline only when a trial is available, or to display a different package based on a custom variable.&lt;/p&gt;



&lt;p&gt;Paywall Rules supports the following rules at the moment:&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Rule&lt;/th&gt;&lt;th&gt;When the rules will take effect&lt;/th&gt;&lt;th&gt;What Rules are available&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;offer.intro&lt;/td&gt;&lt;td&gt;If the user selects a package that includes an introductory offer&lt;/td&gt;&lt;td&gt;Visibility and text overrides&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;offer.promo&lt;/td&gt;&lt;td&gt;If the user selects a package that includes a promotional offer&lt;/td&gt;&lt;td&gt;Visibility and text overrides&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;package.identifier&lt;/td&gt;&lt;td&gt;If the user selects a package that matches the defined identifier&lt;/td&gt;&lt;td&gt;Visibility only&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Custom variable&lt;/td&gt;&lt;td&gt;If the paywall is rendered with or without the defined custom variable.&lt;/td&gt;&lt;td&gt;Visibility only&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;offer.multiphase&lt;/td&gt;&lt;td&gt;If the user selects a package that includes a promotional offer&lt;/td&gt;&lt;td&gt;Text overrides only&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-to-create-your-first-paywall-rule&quot;&gt;How to create your first Paywall Rule&lt;/h2&gt;



&lt;p&gt;To create a Rule for your paywall, navigate to paywall editor and select the &lt;strong&gt;Paywall logic&lt;/strong&gt; tab from the left sidebar. You will see the following button to create a new rule:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-style-default&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;592&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-22-1024x592.png&quot; alt=&quot;Screenshot of RevenueCat Paywall logic tab, showing Create Rule button&quot; class=&quot;wp-image-53156&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-22-1024x592.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-22-300x173.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-22-768x444.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-22-1536x887.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-22-2048x1183.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-22-50x29.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-22-69x40.png 69w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-22-696x402.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-22-560x324.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-22-512x296.png 512w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-22-817x472.png 817w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-22-80x46.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-22-48x28.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Creating a rule has two parts:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Selecting the Rule that will control component visibility&lt;/li&gt;



&lt;li&gt;Selecting either existing or new components that the rule will be applied to&lt;/li&gt;
&lt;/ol&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;592&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-23-1024x592.png&quot; alt=&quot;Screenshot of Paywall editor and Paywall Rule tab, showing new offer.intro rule that demermines if a selected package is shown if there&apos;s an introductory offer available for the user.&quot; class=&quot;wp-image-53159&quot; title=&quot;as shown by the purple highlight around the preview&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-23-1024x592.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-23-300x173.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-23-768x444.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-23-1536x888.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-23-2048x1183.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-23-50x29.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-23-69x40.png 69w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-23-696x402.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-23-560x324.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-23-512x296.png 512w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-23-817x472.png 817w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-23-80x46.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-23-48x28.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;A purple highlight around the preview indicates that you’re viewing how paywall look like with Rule applied.&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;When viewing your rule, any component that you add will be set to only be visible for that Rule. You can edit this later if you require the component to be visible in more cases.&lt;/p&gt;



&lt;p&gt;Rules are evaluated at runtime, after publishing your paywall, which allows multiple rules to exist on a component. Rules are applied to a component in the order defined in the table above. Custom variable rules are evaluated in alphabetical order.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-current-limitations-of-paywall-rules&quot;&gt;Current limitations of Paywall Rules&lt;/h2&gt;



&lt;p&gt;Paywall Rules are supported on most components that you can add to your paywall, with the following limitations:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Express checkout buttons&lt;/li&gt;



&lt;li&gt;Individual pages of a carousel&lt;/li&gt;



&lt;li&gt;Individual tabs&lt;/li&gt;



&lt;li&gt;Footer&lt;/li&gt;



&lt;li&gt;Sheet&lt;/li&gt;



&lt;li&gt;Purchase Button&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-wrapping-up&quot;&gt;Wrapping up&lt;/h2&gt;



&lt;p&gt;Paywall Rules make it easier than ever to build smart, context-aware paywalls without the overhead of maintaining multiple paywall variants. Whether you want to highlight a trial offer, swap out packages based on a custom variable, or tailor messaging for promotional offers, a single paywall can now handle it all. &lt;/p&gt;



&lt;p&gt;As we continue to expand the supported components and rule types, we’re excited to see the creative ways developers and growth teams use this feature to drive conversions. &lt;/p&gt;



&lt;p&gt;Give Paywall Rules a try and let us know what you think 👉 &lt;a href=&quot;https://www.revenuecat.com/docs/tools/paywalls/creating-paywalls/rules&quot;&gt;Paywall Rules documentation&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Exit Offers in RevenueCat Paywalls: A Practical Guide for Android]]></title><description><![CDATA[This article explains how exit offers work on Android, how to configure and implement them correctly with RevenueCat, and common pitfalls that can prevent them from appearing.]]></description><link>https://www.revenuecat.com/blog/engineering/exit-offer-android/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/exit-offer-android/</guid><pubDate>Wed, 22 Apr 2026 00:39:29 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Blog-41_Exit-Offers-in-Android.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;When a user dismisses your paywall without purchasing, the conversion opportunity is lost. Exit offers change this by presenting a second offer at the moment of dismissal, typically a lower price, a longer trial, or a different plan. This is the same strategy e-commerce sites use for cart abandonment: catch the user on the way out with an alternative they might accept. RevenueCat’s paywall system supports exit offers as a dashboard configured feature that requires no code changes, but only if you present your paywall the correct way.&lt;/p&gt;



&lt;p&gt;In this article, you’ll explore how exit offers work on Android, why the presentation method matters, how to configure them in the RevenueCat dashboard, the correct code for both&amp;nbsp;&lt;code&gt;PaywallDialog&lt;/code&gt;&amp;nbsp;and&amp;nbsp;&lt;code&gt;PaywallActivityLauncher&lt;/code&gt;, and the common mistake that silently prevents exit offers from appearing.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-exit-offers-are-and-when-they-trigger&quot;&gt;&lt;strong&gt;What exit offers are and when they trigger&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;An exit offer is a secondary paywall that appears automatically when a user dismisses your primary paywall without making a purchase. The flow looks like this:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;User sees the main paywall (e.g., an annual plan at $49.99/year)&lt;/li&gt;



&lt;li&gt;User taps the close button or swipes to dismiss&lt;/li&gt;



&lt;li&gt;Instead of closing, a second paywall appears with the exit offer (e.g., a monthly plan at $4.99/month)&lt;/li&gt;



&lt;li&gt;User either subscribes to the exit offer or dismisses again, which closes everything&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;The exit offer is a separate offering configured in the RevenueCat dashboard. It has its own paywall design, its own packages, and its own pricing. The SDK handles the transition between the main paywall and the exit offer automatically.&lt;/p&gt;



&lt;p&gt;Exit offers do not trigger when the user has already completed a purchase. If the user subscribes on the main paywall, the paywall closes normally without showing the exit offer.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-presentation-mode-requirement&quot;&gt;&lt;strong&gt;The presentation mode requirement&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;This is the most important point in this article:&amp;nbsp;&lt;strong&gt;exit offers only work with&amp;nbsp;&lt;code&gt;PaywallDialog&lt;/code&gt;&amp;nbsp;and&amp;nbsp;&lt;code&gt;PaywallActivity&lt;/code&gt;&amp;nbsp;on Android.&lt;/strong&gt;&amp;nbsp;They do not work with the&amp;nbsp;&lt;code&gt;Paywall&lt;/code&gt;&amp;nbsp;composable embedded directly in your layout.&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Presentation method&lt;/th&gt;&lt;th&gt;Exit offers supported&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;PaywallDialog&lt;/code&gt;&amp;nbsp;(Composable)&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;PaywallActivityLauncher&lt;/code&gt;&amp;nbsp;(Activity)&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;Paywall&lt;/code&gt;&amp;nbsp;composable (embedded)&lt;/td&gt;&lt;td&gt;No&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;The reason is structural.&amp;nbsp;&lt;code&gt;PaywallDialog&lt;/code&gt;&amp;nbsp;and&amp;nbsp;&lt;code&gt;PaywallActivity&lt;/code&gt;&amp;nbsp;control their own dismiss flow. When the user taps close, the SDK intercepts the dismiss action, checks if an exit offer is configured, and presents the exit offering before actually closing. The&amp;nbsp;&lt;code&gt;Paywall&lt;/code&gt;&amp;nbsp;composable, on the other hand, is embedded directly into your Compose layout. It has no concept of “dismiss” because it is just a composable in your navigation graph. There is nothing to intercept.&lt;/p&gt;



&lt;p&gt;If you are currently using the&amp;nbsp;&lt;code&gt;Paywall&lt;/code&gt;&amp;nbsp;composable and want exit offers, you need to switch to&amp;nbsp;&lt;code&gt;PaywallDialog&lt;/code&gt;&amp;nbsp;or&amp;nbsp;&lt;code&gt;PaywallActivityLauncher&lt;/code&gt;. The migration is straightforward and covered in the sections below.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-setting-up-exit-offers-in-the-dashboard&quot;&gt;&lt;strong&gt;Setting up exit offers in the dashboard&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Exit offers are configured entirely in the RevenueCat dashboard. No code changes are required once your paywall is presented with a supported method.&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Create the exit offer offering.&lt;/strong&gt;&amp;nbsp;In your RevenueCat project, create a new offering (e.g., “exit_offer_monthly”) with the packages you want to show as the exit offer. This could be a discounted monthly plan, a longer free trial, or a different product entirely.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Create a paywall for the exit offer offering.&lt;/strong&gt;&amp;nbsp;Attach a paywall to the exit offer offering using the Paywalls editor. Design it as you would any other paywall. This is the screen the user will see after dismissing the main paywall.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Link the exit offer to your main paywall.&lt;/strong&gt;&amp;nbsp;In the Paywalls editor for your main paywall, open the exit offer settings and select the exit offer offering you created. This tells the SDK which offering to present when the user dismisses.&lt;/li&gt;
&lt;/ol&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;429&quot; height=&quot;173&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/1.png&quot; alt=&quot;&quot; class=&quot;wp-image-53315&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/1.png 429w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/1-300x121.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/1-50x20.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/1-99x40.png 99w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/1-80x32.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/1-48x19.png 48w&quot; sizes=&quot;auto, (max-width: 429px) 100vw, 429px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Once linked, the exit offer is live. The SDK handles preloading the exit offering data, intercepting the dismiss action, and presenting the exit offer paywall.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;presenting-with-paywalldialog&quot;&gt;&lt;strong&gt;Presenting with&amp;nbsp;&lt;code&gt;PaywallDialog&lt;/code&gt;&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;&lt;code&gt;PaywallDialog&lt;/code&gt;&amp;nbsp;is the recommended way to present paywalls in Compose. It displays the paywall as a full screen dialog on compact devices and a standard dialog on tablets. Exit offers work automatically.&lt;/p&gt;



&lt;p&gt;The simplest setup uses&amp;nbsp;&lt;code&gt;setRequiredEntitlementIdentifier&lt;/code&gt;&amp;nbsp;to show the paywall only if the user does not have a specific entitlement:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1JLGmf wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Composable\nfun LockedScreen() {\n    YourContent()\n\n    PaywallDialog(\n        PaywallDialogOptions.Builder()\n            .setRequiredEntitlementIdentifier(\&amp;quot;premium\&amp;quot;)\n            .setListener(\n                object : PaywallListener {\n                    override fun onPurchaseCompleted(\n                        customerInfo: CustomerInfo,\n                        storeTransaction: StoreTransaction,\n                    ) {\n                        \/\/ Handle successful purchase\n                    }\n                }\n            )\n            .build()\n    )\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;If you need custom display logic, use&amp;nbsp;&lt;code&gt;setShouldDisplayBlock&lt;/code&gt;:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Zn2XGv wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Composable\nfun MainScreen() {\n    YourContent()\n\n    PaywallDialog(\n        PaywallDialogOptions.Builder()\n            .setShouldDisplayBlock { customerInfo -&gt;\n                customerInfo.entitlements.active.isEmpty()\n            }\n            .setDismissRequest {\n                \/\/ Called when the paywall (and exit offer, if any) is fully dismissed\n            }\n            .setListener(\n                object : PaywallListener {\n                    override fun onPurchaseCompleted(\n                        customerInfo: CustomerInfo,\n                        storeTransaction: StoreTransaction,\n                    ) {\n                        \/\/ Handle successful purchase\n                    }\n                }\n            )\n            .build()\n    )\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;No additional code is needed for exit offers. The&amp;nbsp;&lt;code&gt;PaywallDialog&lt;/code&gt;&amp;nbsp;handles the flow internally: it preloads the exit offering on display, intercepts the dismiss action, and transitions to the exit offer paywall if configured. The&amp;nbsp;&lt;code&gt;setDismissRequest&lt;/code&gt;&amp;nbsp;callback fires only when the user has fully dismissed both the main paywall and the exit offer (or if no exit offer is configured).&lt;/p&gt;



&lt;p&gt;When using&amp;nbsp;&lt;code&gt;setShouldDisplayBlock&lt;/code&gt;&amp;nbsp;together with an exit offer, the SDK also evaluates the block before showing the exit offer. If the condition returns&amp;nbsp;&lt;code&gt;false&lt;/code&gt;&amp;nbsp;(for example, the user purchased on the main paywall and now has an active entitlement), the exit offer is skipped and the dialog closes directly.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;presenting-with-paywallactivitylauncher&quot;&gt;&lt;strong&gt;Presenting with&amp;nbsp;&lt;code&gt;PaywallActivityLauncher&lt;/code&gt;&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;For apps that do not use Compose or prefer an Activity based approach,&amp;nbsp;&lt;code&gt;PaywallActivityLauncher&lt;/code&gt;&amp;nbsp;launches the paywall as a separate Activity. Exit offers work automatically here as well, the SDK launches the exit offer as a second Activity on top of the first.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Si43x wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;class MainActivity : ComponentActivity(), PaywallResultHandler {\n\n    private lateinit var paywallLauncher: PaywallActivityLauncher\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        paywallLauncher = PaywallActivityLauncher(this, this)\n    }\n\n    fun showPaywall() {\n        paywallLauncher.launchIfNeeded(\n            requiredEntitlementIdentifier = \&amp;quot;premium\&amp;quot;,\n        )\n    }\n\n    override fun onActivityResult(result: PaywallResult) {\n        when (result) {\n            is PaywallResult.Purchased -&gt; {\n                \/\/ User purchased (from main paywall or exit offer)\n            }\n            is PaywallResult.Cancelled -&gt; {\n                \/\/ User dismissed everything without purchasing\n            }\n            is PaywallResult.Error -&gt; {\n                \/\/ Handle error\n            }\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;When the user dismisses the main paywall Activity, the SDK automatically launches the exit offer Activity on top. If the user purchases from the exit offer, the result is&amp;nbsp;&lt;code&gt;PaywallResult.Purchased&lt;/code&gt;. If they dismiss the exit offer too, the result is&amp;nbsp;&lt;code&gt;PaywallResult.Cancelled&lt;/code&gt;. The&amp;nbsp;&lt;code&gt;onActivityResult&lt;/code&gt;&amp;nbsp;callback handles both scenarios uniformly.&lt;/p&gt;



&lt;p&gt;To launch without an entitlement check, use&amp;nbsp;&lt;code&gt;launch()&lt;/code&gt;&amp;nbsp;instead of&amp;nbsp;&lt;code&gt;launchIfNeeded()&lt;/code&gt;:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-TCKEI wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;fun showPaywallUnconditionally() {\n    paywallLauncher.launch()\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;the-embedded-paywall-composable-why-exit-offers-do-not-work&quot;&gt;&lt;strong&gt;The embedded&amp;nbsp;&lt;code&gt;Paywall&lt;/code&gt;&amp;nbsp;composable: Why exit offers do not work&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;If you are embedding the&amp;nbsp;&lt;code&gt;Paywall&lt;/code&gt;&amp;nbsp;composable directly in a navigation graph, exit offers will not trigger:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1hF9Yr wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/\/ Exit offers will NOT work with this approach\ncomposable(route = \&amp;quot;paywall\&amp;quot;) {\n    Paywall(\n        options = PaywallOptions.Builder(\n            onDismiss = { navController.popBackStack() }\n        )\n            .setListener(\n                object : PaywallListener {\n                    override fun onPurchaseCompleted(\n                        customerInfo: CustomerInfo,\n                        storeTransaction: StoreTransaction,\n                    ) {\n                        \/\/ Handle purchase\n                    }\n                }\n            )\n            .build()\n    )\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The&amp;nbsp;&lt;code&gt;Paywall&lt;/code&gt;&amp;nbsp;composable renders the paywall content directly in your layout. When the user taps the dismiss button,&amp;nbsp;&lt;code&gt;onDismiss&lt;/code&gt;&amp;nbsp;navigates back via&amp;nbsp;&lt;code&gt;navController.popBackStack()&lt;/code&gt;. The paywall has no opportunity to intercept this dismissal and show an exit offer because the navigation action happens immediately.&lt;/p&gt;



&lt;p&gt;If you want exit offers while keeping a navigation based flow, replace the embedded&amp;nbsp;&lt;code&gt;Paywall&lt;/code&gt;&amp;nbsp;with a&amp;nbsp;&lt;code&gt;PaywallDialog&lt;/code&gt;&amp;nbsp;placed inside the screen composable:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z2nM1Mp wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/\/ Exit offers WILL work with this approach\ncomposable(route = \&amp;quot;paywall\&amp;quot;) {\n    PaywallDialog(\n        PaywallDialogOptions.Builder()\n            .setDismissRequest { navController.popBackStack() }\n            .setListener(\n                object : PaywallListener {\n                    override fun onPurchaseCompleted(\n                        customerInfo: CustomerInfo,\n                        storeTransaction: StoreTransaction,\n                    ) {\n                        navController.popBackStack()\n                    }\n                }\n            )\n            .build()\n    )\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The behavior is identical from the user’s perspective, a full screen paywall appears and can be dismissed, but the&amp;nbsp;&lt;code&gt;PaywallDialog&lt;/code&gt;&amp;nbsp;manages the dismiss flow internally, enabling exit offers.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;how-exit-offers-work-under-the-hood&quot;&gt;&lt;strong&gt;How exit offers work under the hood&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;When a paywall loads, the SDK calls&amp;nbsp;&lt;code&gt;preloadExitOffering()&lt;/code&gt;&amp;nbsp;in the background. This method checks whether the current paywall’s configuration includes an exit offer reference (an offering ID stored in&amp;nbsp;&lt;code&gt;PaywallComponentsData.exitOffers.dismiss.offeringId&lt;/code&gt;). If it does, the SDK fetches that offering from RevenueCat’s backend and holds it in memory.&lt;/p&gt;



&lt;p&gt;When the user taps close, the SDK checks two conditions:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Has the user completed a purchase? If yes, close normally. No exit offer.&lt;/li&gt;



&lt;li&gt;Is there a preloaded exit offering? If yes, present it instead of closing.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;For&amp;nbsp;&lt;code&gt;PaywallDialog&lt;/code&gt;, the transition works through a state swap. The current dialog offering is set to&amp;nbsp;&lt;code&gt;null&lt;/code&gt;&amp;nbsp;(closing the current paywall), and the exit offering is set as a pending offering. A&amp;nbsp;&lt;code&gt;LaunchedEffect&lt;/code&gt;&amp;nbsp;detects this transition and opens the exit offer as a new dialog.&lt;/p&gt;



&lt;p&gt;For&amp;nbsp;&lt;code&gt;PaywallActivity&lt;/code&gt;, the transition launches a new Activity. The exit offer Activity uses the same&amp;nbsp;&lt;code&gt;PaywallActivity&lt;/code&gt;&amp;nbsp;class but with the exit offering’s ID passed as an argument. The result from the exit offer Activity is forwarded back to the original caller.&lt;/p&gt;



&lt;p&gt;The SDK also tracks exit offer events for analytics. When an exit offer is shown, a&amp;nbsp;&lt;code&gt;paywall_exit_offer&lt;/code&gt;&amp;nbsp;event is recorded with the exit offer type (&lt;code&gt;dismiss&lt;/code&gt;) and the exit offering identifier. This data appears in RevenueCat Charts, letting you measure how exit offers affect your conversion funnel.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;platform-differences&quot;&gt;&lt;strong&gt;Platform differences&lt;/strong&gt;&lt;/h2&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;ios&quot;&gt;&lt;strong&gt;iOS&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Exit offers on iOS work with&amp;nbsp;&lt;code&gt;presentPaywall()&lt;/code&gt;&amp;nbsp;and&amp;nbsp;&lt;code&gt;presentPaywallIfNeeded()&lt;/code&gt;. They do not work with&amp;nbsp;&lt;code&gt;PaywallView&lt;/code&gt;&amp;nbsp;embedded in SwiftUI. This is the same structural limitation as Android: the presentation method must control the dismiss flow.&lt;/p&gt;



&lt;p&gt;One important consideration: Apple’s App Store Review Guideline 5.6 (Developer Code of Conduct) has been cited in some rejections for apps that show additional offers when the user tries to dismiss a paywall. Apple’s definition of “manipulative practices” is subjective, and enforcement is inconsistent across reviewers. Some apps use exit offers on iOS without issues, while others have been rejected. If you want to start with a safer approach, use RevenueCat’s Targeting feature to enable exit offers only for Android users.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;react-native&quot;&gt;&lt;strong&gt;React Native&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Exit offers work with the&amp;nbsp;&lt;code&gt;presentPaywall&lt;/code&gt;&amp;nbsp;and&amp;nbsp;&lt;code&gt;presentPaywallIfNeeded&lt;/code&gt;&amp;nbsp;functions. They do not work with the&amp;nbsp;&lt;code&gt;&amp;lt;RevenueCatUI.Paywall&amp;gt;&lt;/code&gt;&amp;nbsp;component embedded in your layout. The pattern is consistent across all platforms: only presentation methods that control the dismiss flow support exit offers.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;kotlin-multiplatform&quot;&gt;&lt;strong&gt;Kotlin Multiplatform&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Exit offers are not yet supported in the RevenueCat KMP SDK.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;conclusion&quot;&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;In this article, you’ve explored how exit offers work in RevenueCat’s paywall system on Android, from dashboard configuration to the correct presentation methods. The key takeaway is that exit offers require&amp;nbsp;&lt;code&gt;PaywallDialog&lt;/code&gt;&amp;nbsp;or&amp;nbsp;&lt;code&gt;PaywallActivityLauncher&lt;/code&gt;. The&amp;nbsp;&lt;code&gt;Paywall&lt;/code&gt;&amp;nbsp;composable does not support them because it has no dismiss flow to intercept.&lt;/p&gt;



&lt;p&gt;Understanding this distinction helps you choose the right presentation method from the start. If you plan to use exit offers, build your paywall integration around&amp;nbsp;&lt;code&gt;PaywallDialog&lt;/code&gt;&amp;nbsp;(for Compose) or&amp;nbsp;&lt;code&gt;PaywallActivityLauncher&lt;/code&gt;&amp;nbsp;(for Activity based flows). If you are already using the embedded&amp;nbsp;&lt;code&gt;Paywall&lt;/code&gt;&amp;nbsp;composable, switching to&amp;nbsp;&lt;code&gt;PaywallDialog&lt;/code&gt;&amp;nbsp;is a small change that unlocks exit offers without altering the user experience.&lt;/p&gt;



&lt;p&gt;Whether you are implementing exit offers for the first time, migrating from an embedded paywall to a dialog based one, or evaluating how exit offers could affect your conversion funnel, the patterns in this article give you a clear path to get them working correctly on Android.&lt;/p&gt;



&lt;p&gt;As always, happy coding!&lt;/p&gt;



&lt;p&gt;—&amp;nbsp;&lt;a href=&quot;https://github.com/skydoves/&quot;&gt;Jaewoong (skydoves)&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Write the Tweet before you build the product]]></title><description><![CDATA[If you can't explain the feature in 280 characters, it probably isn't worth building]]></description><link>https://www.revenuecat.com/blog/growth/write-the-tweet-first/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/write-the-tweet-first/</guid><pubDate>Tue, 21 Apr 2026 14:06:04 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Blog_42_Write-the-Tweet-before-you-build-the-product.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;In the early 2000s, Amazon popularised a product development framework that has since become Silicon Valley folklore: the &lt;a href=&quot;https://www.aboutamazon.com/news/workplace/an-insider-look-at-amazons-culture-and-processes&quot;&gt;Working Backwards method&lt;/a&gt;. Before writing a single line of code, Amazon product managers were required to write the press release announcing the product’s launch. The logic was simple but ruthless: if the press release wasn’t compelling, the product wasn’t worth building.&lt;/p&gt;



&lt;p&gt;Today, consumer attention spans have shrunk from the length of a newspaper article to the length of a TikTok video. As growth advisor Phil Carter noted in &lt;a href=&quot;https://www.revenuecat.com/blog/growth/phil-carter-elemental-growth-sub-club-podcast-2026/&quot;&gt;a recent episode of the Sub Club podcast&lt;/a&gt;, the Amazon memo has evolved for the AI era:&lt;/p&gt;



&lt;p&gt;“Now instead of a news article, it’s a Tweet or a TikTok video,” Carter explains. “It is really helpful to start with the end in mind because the reality is &lt;strong&gt;no matter how good your product is, if people aren’t willing to give it a shot, it’s not going to matter.&lt;/strong&gt;“&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-wp-embed is-provider-wistia-inc wp-block-embed-wistia-inc&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; class=&quot;wp-embedded-content&quot; sandbox=&quot;allow-scripts&quot; security=&quot;restricted&quot; title=&quot;blog-write-the-tweet-before-phil-carter-clip1 Video&quot; src=&quot;https://fast.wistia.net/embed/iframe/chg2jvjgyf?dnt=1#?secret=fzVAQWyXzC&quot; data-secret=&quot;fzVAQWyXzC&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; width=&quot;500&quot; height=&quot;281&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;For modern subscription apps, especially those leveraging AI, the new forcing function for product development is this: &lt;strong&gt;write the Tweet before you build the feature.&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;576&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Tweet-before-you-build-it-1-1024x576.png&quot; alt=&quot;&quot; class=&quot;wp-image-53304&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Tweet-before-you-build-it-1-1024x576.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Tweet-before-you-build-it-1-300x169.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Tweet-before-you-build-it-1-768x432.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Tweet-before-you-build-it-1-1536x864.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Tweet-before-you-build-it-1-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Tweet-before-you-build-it-1-71x40.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Tweet-before-you-build-it-1-696x392.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Tweet-before-you-build-it-1-560x315.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Tweet-before-you-build-it-1-526x296.png 526w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Tweet-before-you-build-it-1-840x472.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Tweet-before-you-build-it-1-80x45.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Tweet-before-you-build-it-1-48x27.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Tweet-before-you-build-it-1.png 1920w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-elevenlabs-approach-to-feature-launches&quot;&gt;&lt;strong&gt;The ElevenLabs approach to feature launches&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;This isn’t just a theoretical exercise. It’s how some of the fastest-growing consumer AI companies actually operate.&lt;/p&gt;



&lt;p&gt;Take ElevenLabs. In &lt;a href=&quot;https://www.revenuecat.com/blog/growth/jack-tanmay-elevenlabs-sub-club-podcast-2026/&quot;&gt;a separate Sub Club episode featuring their mobile growth leads&lt;/a&gt;, the team revealed that their product specs often begin as a literal Twitter thread. Before building launch assets, landing pages, or writing code, they ask one question: can the value of this feature be explained clearly in a Tweet?&lt;/p&gt;



&lt;p&gt;If the answer is no, it’s a red flag. Writing the narrative first forces clarity. It prevents engineering teams from falling in love with a technically-impressive feature that users won’t actually care about. By starting with the Tweet, ElevenLabs ensures every feature they ship has a built-in hook for organic distribution.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-tiktok-filter-demonstrability-is-distribution&quot;&gt;&lt;strong&gt;The TikTok filter: demonstrability is distribution&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;This concept extends beyond X (formerly Twitter) to video-first platforms like TikTok and Instagram Reels. In fact, visual demonstrability is arguably the most important attribute a new feature can have.&lt;/p&gt;



&lt;p&gt;“It’s almost a good filter when building products,” says Sub Club host David Barnard. “Would this make a good TikTok video?”&lt;/p&gt;



&lt;p&gt;Consider the rise of Cal AI. In a crowded health and fitness category dominated by established giants like MyFitnessPal, Cal AI broke through by building a product experience that was inherently viral. Their hook was entirely visual: take a photo of your meal, and the app instantly calculates the macros.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;576&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Tweet-before-you-build-it-2-1024x576.png&quot; alt=&quot;&quot; class=&quot;wp-image-53306&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Tweet-before-you-build-it-2-1024x576.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Tweet-before-you-build-it-2-300x169.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Tweet-before-you-build-it-2-768x432.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Tweet-before-you-build-it-2-1536x864.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Tweet-before-you-build-it-2-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Tweet-before-you-build-it-2-71x40.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Tweet-before-you-build-it-2-696x392.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Tweet-before-you-build-it-2-560x315.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Tweet-before-you-build-it-2-526x296.png 526w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Tweet-before-you-build-it-2-840x472.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Tweet-before-you-build-it-2-80x45.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Tweet-before-you-build-it-2-48x27.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Tweet-before-you-build-it-2.png 1920w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Is machine vision calorie tracking perfectly accurate every time? No. But as a product experience, it’s magical. More importantly, &lt;strong&gt;it’s demonstrable in three seconds&lt;/strong&gt;. That demonstrability fueled a massive wave of user-generated content (UGC) and paid ad performance, propelling the app’s rapid growth.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-wp-embed is-provider-wistia-inc wp-block-embed-wistia-inc&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; class=&quot;wp-embedded-content&quot; sandbox=&quot;allow-scripts&quot; security=&quot;restricted&quot; title=&quot;blog-write-the-tweet-before-phil-carter-clip2 Video&quot; src=&quot;https://fast.wistia.net/embed/iframe/7kmyrvh74c?dnt=1#?secret=IQswlKvDDk&quot; data-secret=&quot;IQswlKvDDk&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; width=&quot;500&quot; height=&quot;281&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;As Joseph Choi highlighted in &lt;a href=&quot;https://www.revenuecat.com/blog/growth/joseph-choi-sub-club-podcast-2024/&quot;&gt;another Sub Club conversation about TikTok virality&lt;/a&gt;, &lt;strong&gt;platforms with algorithmic feeds reward products that can instantly communicate their value proposition visually&lt;/strong&gt;. If your core feature requires a three-minute tutorial to understand, it will struggle to find organic traction.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-building-for-the-automagical-moment&quot;&gt;&lt;strong&gt;Building for the ‘automagical’ moment&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The ‘write the Tweet’ philosophy is ultimately about engineering an ‘automagical’ first-time user experience. In an app ecosystem where the average consumer is bombarded with thousands of ad impressions daily, and &lt;a href=&quot;https://www.revenuecat.com/blog/growth/subscription-app-trends-benchmarks-2026/&quot;&gt;where hard paywalls often convert 5x better than freemium models&lt;/a&gt;, you have a very narrow window to prove your worth.&lt;/p&gt;



&lt;p&gt;When you write the Tweet first, you are forced to distill your product’s value into its most potent form. You are designing for the &lt;em&gt;aha!&lt;/em&gt; &lt;em&gt;moment&lt;/em&gt;; for the exact moment a user realizes your app solves their problem in a way they’ve never seen before.&lt;/p&gt;



&lt;p&gt;A perfect example of this is the screen time app one sec. Founder Frederik Riedel built the initial prototype in a weekend to solve his own social media habit. A single, well-crafted Tweet demonstrating how the app forced a deep breath before opening Instagram &lt;a href=&quot;https://www.revenuecat.com/blog/growth/frederik-riedel-expected-12-his-app-cut-screen-time-by-57/&quot;&gt;drove months of sustained organic growth&lt;/a&gt;. The product &lt;em&gt;was&lt;/em&gt; the marketing.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-to-apply-the-tweet-first-framework&quot;&gt;&lt;strong&gt;How to apply the tweet first framework&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;If you want to implement this in your own product development cycle, start by adding a mandatory section to your product spec templates. Before detailing the technical requirements or user flows, require the product manager to draft:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;The hook:&lt;/strong&gt; a 280-character Tweet announcing the feature. What is the single most exciting thing about it?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;The visual:&lt;/strong&gt; a description of the three-second video clip that would accompany the Tweet or serve as a TikTok ad. What exactly is happening on screen?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;The user testimonial:&lt;/strong&gt; what is the specific, enthusiastic quote you want a user to leave in an App Store review after trying it?&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;If your team struggles to write these three elements, you likely have a positioning problem — or worse, a product problem.&lt;/p&gt;



&lt;p&gt;As Phil Carter puts it, “You need to start with the end in mind, which is how are you going to get your first hundred or first thousand users? And part of that is writing the Tweet upfront or figuring out what the TikTok video needs to look like upfront.”&lt;/p&gt;



&lt;p&gt;In the AI era, shipping fast is table stakes. Shipping features that actually resonate requires clarity. So next time you’re debating a feature on your roadmap, don’t ask if you &lt;em&gt;can&lt;/em&gt; build it. Ask if you can tweet it.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[6 steps to design a freemium tier that drives upgrades ]]></title><description><![CDATA[Why the top 10% of freemium apps outperform hard paywalls]]></description><link>https://www.revenuecat.com/blog/growth/freemium-tier-design/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/freemium-tier-design/</guid><pubDate>Tue, 21 Apr 2026 11:49:45 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/6-steps-freemium-strategy.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;It’s tempting to jump straight to tactics when it comes to freemium. There’s so much more you can do than just a hard paywall: engagement moments, upgrade triggers based on usage, contextual nudges… I’m getting excited just writing about it!&amp;nbsp;&lt;/p&gt;



&lt;p&gt;But what deserves more attention is working out &lt;em&gt;what&lt;/em&gt; to offer free vs. paid. There’s a lot of generic advice out there:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;“Give them a taste of premium”&lt;/li&gt;



&lt;li&gt;“Provide value”&lt;/li&gt;



&lt;li&gt;“Balance value and pushing upgrade”&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;None of which answers the tricky question: &lt;strong&gt;what do you offer in your free versus premium tiers?&lt;/strong&gt; How did freemium giants like Duolingo, Slack, and Strava figure out what belongs in each?&lt;/p&gt;



&lt;p&gt;That’s what I want to cover here. I promise to stay strategic rather than tactical, but practical enough that you and your team can actually use this to decide what belongs in each tier. Follow this step-by-step process, and you’ll end up with a &lt;strong&gt;clear, defensible freemium strategy&lt;/strong&gt;.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-does-the-data-say-about-free-vs-paid&quot;&gt;What does the data say about free vs. paid?&lt;/h2&gt;



&lt;p&gt;Before we begin, a quick note: &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps/&quot;&gt;the numbers&lt;/a&gt; can make freemium look like the underdog: &lt;a href=&quot;https://www.revenuecat.com/blog/growth/hard-paywall-vs-soft-paywall/&quot;&gt;hard paywall&lt;/a&gt; products have median conversion rates of about 10.7%, compared to 2.1% for freemium models, and can generate roughly 8× more revenue per install after 14 days. While it’s true that &lt;a href=&quot;https://www.revenuecat.com/blog/growth/subscription-app-trends-benchmarks-2026/&quot;&gt;hard paywalls can be huge performers&lt;/a&gt;, it’s not the &lt;strong&gt;rule&lt;/strong&gt;. And that’s only the median story.&lt;/p&gt;



&lt;p&gt;The strongest freemium products — think of companies like Duolingo, Slack, and Strava — show how wide the performance spread can be. Top freemium apps can achieve &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps/&quot;&gt;retention rates between 42.4% and 58.1%&lt;/a&gt;, far outperforming average outcomes.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;616&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-26-1024x616.png&quot; alt=&quot;&quot; class=&quot;wp-image-53281&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-26-1024x616.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-26-300x181.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-26-768x462.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-26-1536x924.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-26-50x30.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-26-66x40.png 66w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-26-696x419.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-26-560x337.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-26-492x296.png 492w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-26-784x472.png 784w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-26-80x48.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-26-48x29.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-26.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Retained subscribers after 1 year, by access methods — State of Subscription Apps 2026&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;In other words, &lt;strong&gt;freemium rewards exceptional execution&lt;/strong&gt;: the difference between a mediocre strategy and a great one is enormous, and getting the tier design right is what determines whether you land in that top bracket.&lt;/p&gt;



&lt;p&gt;So, let’s jump into six steps to creating a freemium strategy that actually drives upgrades.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-0-is-freemium-even-right-for-you&quot;&gt;Step 0: is freemium even right for you?&lt;/h2&gt;



&lt;p&gt;I’d be doing you a disservice if I skipped this step, but if you’ve already thought this through, no offence taken at all — jump straight to Step 1.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Still with me? Let’s cover the considerations when deciding if freemium is right for your app.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-understanding-audience-size-in-free-vs-paid&quot;&gt;Understanding audience size in free vs. paid&lt;/h3&gt;



&lt;p&gt;The first consideration is &lt;strong&gt;audience size.&lt;/strong&gt; If you’re building a product you want to scale broadly, freemium is usually the default choice. The word-of-mouth potential and advantage of a large &lt;a href=&quot;https://www.revenuecat.com/blog/growth/fix-onboarding-funnels/&quot;&gt;top-of-funnel&lt;/a&gt; reach often outweigh the downside of a lower &lt;a href=&quot;https://www.revenuecat.com/blog/growth/app-trial-conversion-rate-insights/&quot;&gt;conversion rate&lt;/a&gt;. On the other hand, if your product serves a very niche audience, you may want to save yourself some time and go straight to a hard paywall model (possibly paired with a trial).&lt;/p&gt;



&lt;p&gt;If you compare &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps/&quot;&gt;day 35 downloads to paid for freemium vs. hard paywall&lt;/a&gt;, the averages differ greatly:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;612&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Day-35-download-to-paid-by-access-method-1024x612.png&quot; alt=&quot;&quot; class=&quot;wp-image-53291&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Day-35-download-to-paid-by-access-method-1024x612.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Day-35-download-to-paid-by-access-method-300x179.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Day-35-download-to-paid-by-access-method-768x459.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Day-35-download-to-paid-by-access-method-1536x917.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Day-35-download-to-paid-by-access-method-50x30.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Day-35-download-to-paid-by-access-method-67x40.png 67w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Day-35-download-to-paid-by-access-method-696x416.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Day-35-download-to-paid-by-access-method-560x334.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Day-35-download-to-paid-by-access-method-496x296.png 496w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Day-35-download-to-paid-by-access-method-790x472.png 790w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Day-35-download-to-paid-by-access-method-80x48.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Day-35-download-to-paid-by-access-method-48x29.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Day-35-download-to-paid-by-access-method.png 1768w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Day 35 download-to-paid, freemium vs. hard paywall — State of Subscription Apps 2026&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;That means that, in a freemium model, you typically want at least ~1,000+ free users to build a meaningful paid cohort. Based on these ranges, if you have around 5,000 users, freemium might yield roughly 110–225 paying customers, whereas a hard paywall could convert closer to 325–1,085.&lt;/p&gt;



&lt;p&gt;If you’re unsure whether your audience is large enough to support a freemium strategy, it’s worth estimating your &lt;a href=&quot;https://subclub.com/episode/how-to-succeed-with-freemium-and-hybrid-monetization-paul-ganev-surfline&quot;&gt;Serviceable Addressable Market (SAM)&lt;/a&gt; to see whether you can realistically reach the scale needed for freemium to work.&lt;/p&gt;



&lt;p&gt;Unless you have a very good reason why people would convert at a higher-than-average rate — &lt;a href=&quot;https://www.getmonetizely.com/articles/slacks-freemium-strategy-how-they-convert-free-users-to-paying-customers-2024-breakdown&quot;&gt;Slack converts at over 30%&lt;/a&gt; because of its business case and strong freemium strategy — the math needs to work for lower conversion rates.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-revenue-delay-within-freemium-apps&quot;&gt;Revenue delay within freemium apps&lt;/h3&gt;



&lt;p&gt;Freemium apps tend to lean toward more habit-forming, viral products. That virality comes at a cost: there is a delay in revenue. Hard paywall users mostly convert on Day 0, while a larger share of freemium users convert weeks after download, meaning you need the runway to wait:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;579&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-25-1024x579.png&quot; alt=&quot;&quot; class=&quot;wp-image-53279&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-25-1024x579.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-25-300x170.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-25-768x434.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-25-1536x869.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-25-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-25-71x40.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-25-696x394.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-25-560x317.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-25-523x296.png 523w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-25-834x472.png 834w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-25-80x45.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-25-48x27.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-25.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Average revenue per install (RPI) after 14 days, split by access method and pricepoint — State of Subscription Apps 2026&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-willingness-to-pay-and-pricing-confidence&quot;&gt;Willingness to pay and pricing confidence&lt;/h3&gt;



&lt;p&gt;It’s harder for newer apps to understand willingness to pay with a freemium model because you need a bigger audience to learn from. Is it not converting because people won’t pay — or is it converting less because of freemium? For new apps, it could be worth &lt;a href=&quot;https://www.leanfoundry.com/lean-1-2-3/mar-15-2025&quot;&gt;temporarily starting with a hard paywall to learn&lt;/a&gt;, then switching to freemium once you understand your price sensitivity better. Alternatively, if you expect word-of-mouth to be your primary growth driver or you’re in a crowded market, you can take the &lt;a href=&quot;https://subclub.com/episode/how-headspace-optimized-revenue-by-gating-content-shreya-oswal-and-keya-patel-headspace&quot;&gt;Headspace approach&lt;/a&gt;: start with a very generous free tier and then, over time, move more behind the paywall.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-don-t-let-freemium-make-you-timid-on-pricing&quot;&gt;Don’t let freemium make you timid on pricing&lt;/h3&gt;



&lt;p&gt;There’s no published data directly showing that freemium apps charge less than hard paywall apps, but in my experience, the tendency is there — and it’s a trap. &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps/&quot;&gt;RevenueCat’s data&lt;/a&gt; shows that higher price points actually drive better Day 35 conversion rates (2.8% median vs. 1.4% for low-priced apps) and higher revenue per install.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;610&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-24-1024x610.png&quot; alt=&quot;&quot; class=&quot;wp-image-53275&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-24-1024x610.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-24-300x179.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-24-768x458.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-24-1536x916.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-24-50x30.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-24-67x40.png 67w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-24-696x415.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-24-560x334.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-24-497x296.png 497w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-24-792x472.png 792w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-24-80x48.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-24-48x29.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-24.png 1768w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Day 35 download-to-paid, by pricepoint — State of Subscription Apps 2026&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;The logic is counterintuitive but sound: if someone has experienced genuine value in your free tier and still chooses to upgrade, they’re a high-intent buyer. Price accordingly. &lt;strong&gt;Your generous free tier should give you confidence to charge more, not less&lt;/strong&gt;.&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-Z6bMJh wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Action time&quot; text=&quot;&lt;p&gt;&lt;strong&gt;Fill in the following template:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;We&apos;ll start with [Freemium / Hard paywall] because [reasoning].&lt;/em&gt;&lt;/p&gt;&quot; icon=&quot;circle-check&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-1-what-is-your-goal-with-freemium&quot;&gt;Step 1: what is your goal with freemium?&lt;/h2&gt;



&lt;p&gt;You’ve decided freemium is right for you. Now the question is what you want that free tier to &lt;em&gt;do&lt;/em&gt; for your business.&lt;/p&gt;



&lt;p&gt;Your goal shapes everything that follows: how generous your free tier is, where you draw the paywall line, and how aggressively you push for upgrades. People often think freemium’s main benefit is purely for word-of-mouth or volume, but freemium can serve many goals.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-stand-out-in-a-competitive-market&quot;&gt;1. Stand out in a competitive market&lt;/h3&gt;



&lt;p&gt;Healthi, a weight-loss app, &lt;a href=&quot;https://subclub.com/episode/how-freemium-can-outperform-free-trials-shaun-steingold-momentum-labs&quot;&gt;intentionally went freemium&lt;/a&gt; because its major competitors — Weight Watchers and Noom — didn’t offer a free version. This helped them gain traction and stand out in a crowded market.&lt;/p&gt;



&lt;p&gt;When standing out from the competition is your goal, you’ll typically want a generous free version to begin with. You’re using free as a wedge against incumbents. Over time, as you establish your position, you can tighten the free tier and charge more — similar to what Headspace did and what we see with several larger AI apps.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-drive-organic-growth-through-word-of-mouth&quot;&gt;2. Drive organic growth through word-of-mouth&lt;/h3&gt;



&lt;p&gt;People are much more likely to recommend a free app than a paid one, and many freemium apps benefit from running fewer ads as a result. &lt;a href=&quot;https://subclub.com/episode/why-your-free-users-are-your-real-growth-engine-cem-kansu-duolingo-cpo&quot;&gt;Duolingo’s former VP of Product, Cem Kansu, put it bluntly on the Sub Club podcast&lt;/a&gt;: at Duolingo, free users were never treated as freeloaders. They were the primary distribution channel. Around 80% of new users arrive organically, powered by viral loops, shareable progress, and the app’s built-in motivation systems.&lt;/p&gt;



&lt;p&gt;When this is your goal, you need to think carefully about how to ensure free users get enough value to recommend you, and whether you can build viral loops into your freemium model. If free users don’t love the product, there’s nothing to spread.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-help-build-a-habit&quot;&gt;3. Help build a habit&lt;/h3&gt;



&lt;p&gt;Some apps naturally take longer to build value or to understand. In these cases, freemium can give you time to convert users who a trial (rarely longer than 30 days) simply can’t.&lt;/p&gt;



&lt;p&gt;When this is your goal, think about the actions needed to get the user far enough along to pay. For example, &lt;a href=&quot;https://fitbod.me/&quot;&gt;Fitbod&lt;/a&gt;, a fitness app, offers three workouts completely free before you need to pay. After three workouts, you’re starting to get into the habit of using the app and seeing the value. The free tier isn’t about generosity, it’s about giving users enough runway to form the habit.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-4-you-need-volume-for-your-app-to-work&quot;&gt;4. You need volume for your app to work&lt;/h3&gt;



&lt;p&gt;Some apps need scale for their core product to function, whether that’s data, community, or network effects.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;For example, I worked with an IBS app that was just starting out. Their main feature of value was a powerful scanning tool that helps you understand what you can and can’t eat based on what triggers your gut health issues. They were intentionally very generous with the scanning tool — more generous than they needed to be — because every new market they entered, they needed a lot of data on what foods to include, and this was cheaper and easier to source through user data than external data sources. For one new market they were testing, they went so far as to omit a paywall entirely because their data outweighed short-term revenue.&lt;/p&gt;



&lt;p&gt;If their goal had been just word-of-mouth, they could have offered less, which is exactly what they did in their main market, where they already had enough data. They still grew substantially organically, resulting in YoY revenue up 70%–80% and paid conversions rising from 6.6% to 13.7% (well above average for freemium).&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.strava.com/&quot;&gt;Strava&lt;/a&gt; is another example: free users recording activities generate the route data, segment data, and social activity that make premium features like heatmaps, leaderboards, and route suggestions valuable. The more people tracking for free, the better the paid product becomes making it worthwhile having a generous free tier.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-5-have-a-positive-impact-on-the-world&quot;&gt;5. Have a positive impact on the world&lt;/h3&gt;



&lt;p&gt;The final reason is a tricky one. I’ve worked with an app that genuinely grew out of a desire to help people (one of the best parts about specialising in wellness apps). They had a very generous free tier: you could use the main features without ever paying. But people weren’t activating as much as premium users — we’re talking 1%-2% active for freemium vs. 60% for premium.&lt;/p&gt;



&lt;p&gt;With free user activation being extremely low, they weren’t actually achieving their impact goal. You need to find ways to stay true to this mission while actually delivering value. For example, when Headspace removed its freemium content, it still offered free meditations on YouTube to stay true to its goal of having a positive impact, just through a different channel.&lt;/p&gt;



&lt;p&gt;So start by defining your main goals to ensure you design your model the right way. Depending on your goal, you may intentionally choose to be more or less generous.&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-17h7kn wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Action time&quot; text=&quot;&lt;p&gt;&lt;strong&gt;Fill in the following template:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Our main goal(s) with freemium are [goal(s)] because [reasoning]. This will have the following [impact] on how we shape our model.&lt;/em&gt;&lt;/p&gt;&quot; icon=&quot;circle-check&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-2-define-what-user-success-looks-like&quot;&gt;Step 2: define what user success looks like&lt;/h2&gt;



&lt;p&gt;Your users have a job they’re trying to achieve with your app, and when they achieve it, they retain. If you have the data, look at what it shows for paying users; if you don’t, define the actions that will predict success.&lt;/p&gt;



&lt;p&gt;I like how &lt;a href=&quot;https://www.revenuecat.com/blog/growth/revenue-strategies-low-intent-users/&quot;&gt;Alice Muir Kocourková&lt;/a&gt; explains it:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“Free users should be able to achieve meaningful progress toward their goal&amp;nbsp; —&amp;nbsp; but not reach the full solution.”&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;So you need to know not only your goal, but theirs too. That then allows you to work backwards to what actions get them to that point.&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-29XbU2 wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Action time&quot; text=&quot;&lt;p&gt;&lt;strong&gt;Fill in the following template:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;For [specific audience] who [job to be done / problem they&apos;re trying to solve], our app [how it addresses the pain / painkiller focus] by [your unique way of delivering value].&lt;/em&gt;&lt;/p&gt;&quot; icon=&quot;circle-check&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-3-choose-your-freemium-architecture&quot;&gt;Step 3: choose your freemium architecture&lt;/h2&gt;



&lt;p&gt;Based on the above, you can now think through how to shape your freemium setup. Not all freemium models are built the same way. Some apps offer very different features for free vs. premium users, while others offer a taster of premium features. Before you map individual features to free and paid, you need to &lt;strong&gt;decide &lt;em&gt;how&lt;/em&gt; the free tier relates to the paid tier&lt;/strong&gt;. There are three broad approaches, each suited to a different type of product.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-the-taster-model-same-product-with-limits&quot;&gt;1. The taster model: same product, with limits&lt;/h3&gt;



&lt;p&gt;Here, users get the full product experience up to a certain limit. The free version doesn’t feel stripped down, it feels complete enough to use and get real value. The upgrade trigger comes from usage growth, not from missing features.&lt;/p&gt;



&lt;p&gt;Loom, the video-sharing platform, is a great example. I used it for free for a good year, maxing out at 5-minute recordings and saving up to 25 videos. I didn’t use it often, so I’d occasionally delete older videos to make room. Over time, I started seeing the value, and I reached a point where five minutes felt frustrating, and sending four separate videos to a client did not exactly scream professional. I switched to paid and have been a loyal customer for years.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;475&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1024x475.jpeg&quot; alt=&quot;&quot; class=&quot;wp-image-53277&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1024x475.jpeg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-300x139.jpeg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-768x357.jpeg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-50x23.jpeg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-86x40.jpeg 86w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-696x323.jpeg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-560x260.jpeg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-840x390.jpeg 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-80x37.jpeg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-48x22.jpeg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image.jpeg 1456w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Other examples include Zoom (free users get the same tools but hit a 40-minute limit) and Notion (same editor and workspace, but with block limits and limited guest invitations).&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-when-this-works-well&quot;&gt;When this works well:&lt;/h4&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Usage impacts value: saving more videos, longer recordings, more storage are genuinely more valuable as you use the product more.&lt;/li&gt;



&lt;li&gt;Your core value is what drives word-of-mouth, so you want or need free users to experience the real thing.&lt;/li&gt;



&lt;li&gt;There’s a natural inflection point where casual usage becomes serious usage. Think of it as the ‘defining the relationship’ moment — you don’t want an app situationship.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;For this to work, you need to identify, or create, that natural inflection point where casual clearly becomes serious. Set limits too high and users never hit them; set them too low and the free tier feels like a trial with extra steps.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-the-split-model-different-features-for-different-jobs&quot;&gt;2. The split model: different features for different jobs&lt;/h3&gt;



&lt;p&gt;Here, free and paid users get distinctly different capabilities. Premium isn’t ‘more of the same’ — it’s a different set of tools serving a different (usually more advanced or professional) use case.&lt;/p&gt;



&lt;p&gt;For example, CapCut, the video editing app, offers basic video editing features for free, but as I edited my video and wanted fancier subtitles and better editing tools, it was indicated that these were premium features. I could edit without them, but for a business use case where I wanted a more polished result, paid made sense.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://subclub.com/episode/how-to-succeed-with-freemium-and-hybrid-monetization-paul-ganev-surfline&quot;&gt;Surfline, a surfing app&lt;/a&gt;, works the same way. Casual once-a-year surfers only need a basic forecast, and the free app handles that well. Serious surf fanatics want extended forecasts, wave timeline features, and detailed swell data. &lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;417&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-2-1024x417.jpeg&quot; alt=&quot;&quot; class=&quot;wp-image-53295&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-2-1024x417.jpeg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-2-300x122.jpeg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-2-768x313.jpeg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-2-50x20.jpeg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-2-98x40.jpeg 98w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-2-696x283.jpeg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-2-560x228.jpeg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-2-840x342.jpeg 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-2-80x33.jpeg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-2-48x20.jpeg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-2.jpeg 1456w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;As a casual surfer myself, I just want to know whether I can surf (and hope I can stand up). I have no clue what the wavelengths and frequencies mean. But as those casual users start to fall in love with surfing (or move closer to a beach), they may become paid users at a later stage.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-when-this-works-well-0&quot;&gt;When this works well:&lt;/h4&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;You serve distinct user segments with different needs (casual vs. power user, personal vs. professional, individual vs. team)&lt;/li&gt;



&lt;li&gt;Paid features have meaningfully higher value, or higher cost to serve, that justifies a separate tier&lt;/li&gt;



&lt;li&gt;Free features are strong enough to stand alone — they’re not just a teaser for what’s behind the paywall&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;strong&gt;The risk:&lt;/strong&gt; If the split feels artificial, e.g. if users constantly bump into locked features during their normal workflow, it creates frustration. So the locked features should feel like a different destination, rather than a roadblock on the same path.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-the-hybrid-model-taster-limits-split-features&quot;&gt;3. The hybrid model: taster limits + split features&lt;/h3&gt;



&lt;p&gt;Many of the best freemium apps combine both approaches: some features are available to everyone with usage limits, while others are exclusively premium. This gives you two distinct upgrade triggers: “I need more of what I already use” and “I want access to something new”.&lt;/p&gt;



&lt;p&gt;Slack offers you a taster, or well, practically a full free meal. You get the full workspace experience, but message history is limited to 90 days, and you’re capped on integrations. Yet features like Slack Connect (cross-organisation channels) are fully premium, because they’re classic business features that signal a team should be able to pay. Casual teams never need them; business teams can’t live without them.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;767&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-1024x767.jpeg&quot; alt=&quot;&quot; class=&quot;wp-image-53283&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-1024x767.jpeg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-300x225.jpeg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-768x575.jpeg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-50x37.jpeg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-53x40.jpeg 53w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-619x464.jpeg 619w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-696x522.jpeg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-560x420.jpeg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-395x296.jpeg 395w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-630x472.jpeg 630w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-80x60.jpeg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-48x36.jpeg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1.jpeg 1456w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;ChatGPT works similarly too: free users get access to capable models with usage limits (taster), while advanced models, deeper reasoning tools, and higher-volume image generation are premium-only (split).&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;538&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-27-1024x538.png&quot; alt=&quot;&quot; class=&quot;wp-image-53285&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-27-1024x538.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-27-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-27-768x403.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-27-1536x806.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-27-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-27-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-27-696x365.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-27-560x294.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-27-840x441.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-27-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-27-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-27.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;And Duolingo also does the same: free users get all lessons (the core product) with ads and limited ‘hearts’ (taster), while unlimited practice, progress quizzes, and offline access are premium-only (split).&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-when-this-works-well-1&quot;&gt;When this works well:&lt;/h4&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;You have both a broad casual audience and a smaller power-user segment.&lt;/li&gt;



&lt;li&gt;Some features scale with usage (good for limits) while others are binary; you either need them or you don’t.&lt;/li&gt;



&lt;li&gt;You want multiple upgrade triggers at different points in the user journey.&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-which-approach-is-right-for-you&quot;&gt;Which approach is right for you?&lt;/h3&gt;



&lt;p&gt;If you aren’t sure, these questions can help:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Does your product’s value increase with usage volume? &lt;/strong&gt;(More messages, more storage, more recordings.) Lean toward the taster model. Set limits where casual use flips into serious use.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Does your product serve clearly different user types?&lt;/strong&gt; (Hobby vs. professional, individual vs. team, consumer vs. business.) Lean toward the split model. Gate features by segment, rather than usage.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Is your user base very broad, with a wide spectrum of needs?&lt;/strong&gt; Lean toward the hybrid model. Use taster limits for the core experience and split features for power tools.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Don’t feel like you need to set and forget; this may be something you test and evolve as you learn. Your architecture can change over time, it’s much easier to tighten a generous free tier than to loosen a restrictive one.&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-574sl wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Action time&quot; text=&quot;&lt;p&gt;&lt;strong&gt;Fill in the following template (I promise you it&apos;s worth thinking these through — consider it app journaling! Great for the soul, and for app growth.)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;We will go with [model type] to begin with because [reasoning].&lt;/em&gt;&lt;/p&gt;&quot; icon=&quot;circle-check&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-4-map-your-free-vs-paid-offering&quot;&gt;Step 4: map your free vs. paid offering&lt;/h2&gt;



&lt;p&gt;Now, this is likely to be something you will optimize and experiment with vs. set-and-forget, but you need to start somewhere. Based on the above, if you’ve worked that out already, this step should feel quite natural.&lt;/p&gt;



&lt;p&gt;Now, this is likely to be something you’ll optimize and experiment with rather than set and forget, but you need to start somewhere. If you’ve worked through Steps 1–3, this step should feel quite natural.&lt;/p&gt;



&lt;p&gt;For each feature, map out whether it’s free, paid, or limited — and critically, write down the strategic rationale for &lt;em&gt;why&lt;/em&gt;. This forces you to articulate the reasoning, which makes it much easier to revisit later and to align your team. For example, here’s how some of Strava’s features map out:&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Feature&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Free&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Paid (Summit)&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Strategic rationale&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;GPS activity recording&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;✓ Full access&lt;/td&gt;&lt;td&gt;✓&lt;/td&gt;&lt;td&gt;The product is about tracking. Gating it kills the network. Every recorded activity = content for the social feed.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Activity upload from devices&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;✓ Garmin, Apple, Wahoo etc.&lt;/td&gt;&lt;td&gt;✓&lt;/td&gt;&lt;td&gt;Device integrations expand the top-of-funnel. Every synced watch is a distribution channel.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Segment leaderboards&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Limited (personal only)&lt;/td&gt;&lt;td&gt;✓ Full leaderboards&lt;/td&gt;&lt;td&gt;This is the upgrade hook. Competitive athletes need to see where they rank so this is a natural “aha moment” trigger.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Power analysis (cycling)&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;✗&lt;/td&gt;&lt;td&gt;✓&lt;/td&gt;&lt;td&gt;Niche but extremely high willingness-to-pay. Cyclists already spend thousands on gear.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Clubs &amp;amp; group challenges&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;✓&lt;/td&gt;&lt;td&gt;✓&lt;/td&gt;&lt;td&gt;Clubs are viral loops: each club invite is organic acquisition. Free access maximises reach.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;A few additional considerations as you map this out:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-keep-ai-costs-in-mind&quot;&gt;1. Keep AI costs in mind&lt;/h3&gt;



&lt;p&gt;If your app uses AI features, some things you’d like to offer for free may simply be too expensive to give away. This is &lt;a href=&quot;https://www.revenuecat.com/blog/growth/ai-hybrid-monetization/&quot;&gt;reshaping freemium for AI-first apps:&lt;/a&gt; rather than gating features, many are adopting usage-based models where free users get a set number of credits or queries.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;ChatGPT, for example, doesn’t lock features so much as it limits how much of the best model you can use before you need to upgrade. When mapping your features, note the cost to serve alongside the strategic rationale — it may override your preference.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-consider-platform-specific-differences&quot;&gt;2. Consider platform-specific differences&lt;/h3&gt;



&lt;p&gt;Your strategy may need to differ for iOS and Android, based on the differences in how those user groups monetise. &lt;a href=&quot;https://www.youtube.com/watch?v=n6f0UVbATng&amp;amp;t=1s&quot;&gt;Lose It!&lt;/a&gt; has a platform-specific paywall strategy: the same feature (barcode scanner) is free-with-ads on Android, but paid on iOS. Some apps also lean more heavily on ads for Android because there’s a lower likelihood of paying. This breaks the “sacred rule” of platform parity, but Lose It! led with data and adjusted based on what actually worked per platform.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-having-your-bill-of-rights-in-place&quot;&gt;3. Having your Bill of Rights in place&lt;/h3&gt;



&lt;p&gt;This might be the most important part of this step. As you map features to free and paid, you also need to define what you’re &lt;em&gt;not&lt;/em&gt; willing to move.&lt;/p&gt;



&lt;p&gt;Here’s the problem: it’s very easy to slowly shift more and more of your offering to premium, one experiment at a time, until the free tier offers little value. Each individual experiment might show a lift in conversion rate. But over time, the cumulative effect of reducing free value — on word-of-mouth, on user experience, on brand love — is almost impossible to measure until it’s too late.&lt;/p&gt;



&lt;p&gt;Chris Hulls, Founder and CEO of Life360 (the family safety platform used by over 80 million active users), &lt;a href=&quot;https://subclub.com/episode/freemium-done-right-lessons-from-a-multi-billion-dollar-app-chris-hulls-life360&quot;&gt;talked about exactly this on the Sub Club podcast&lt;/a&gt;. Life360 recently wrote a ‘Bill of Rights’ for their free users, an internal document that acts as a constitution for what cannot be touched. Whilst their Bill of Rights isn’t publicly available, to give you an idea of what it includes, Chris did share:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“This is probably the most important: the core map, location history, and place alerts, they must be free. Doesn’t mean we can’t move the paywall a bit, but real value there, no deceptive tactics… The real anchor is all around the lifeblood to who we are.”&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Jacob Eiting, RevenueCat’s CEO, nailed why this matters in that &lt;a href=&quot;https://subclub.com/episode/freemium-done-right-lessons-from-a-multi-billion-dollar-app-chris-hulls-life360&quot;&gt;Sub Club podcast:&lt;/a&gt; nobody runs a holdout group long enough to see the cumulative effect of chipping away at the free tier. You can &lt;a href=&quot;https://www.revenuecat.com/blog/engineering/mobile-app-a-b-price-testing-guide/&quot;&gt;A/B test&lt;/a&gt; removing any single feature, and retention looks fine. Do it 20 times, and you’ve quietly eroded the thing that made people love you.&lt;/p&gt;



&lt;p&gt;I love the concept of the Bill of Rights and recommend taking notes on your own. This is likely a longer-term project, and if you are larger already, an internal discussion, but worth thinking through the following questions:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;What must always be free, no matter what?&lt;/strong&gt; These are the features that &lt;em&gt;are&lt;/em&gt; the product. If you gated them, you’d kill the thing that keeps people coming back. (Life360: core map + location sharing + place alerts. Duolingo: daily lessons. Strava: GPS tracking and the social feed.)&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;What is the core value that free users receive, and is it real value, not a teaser?&lt;/strong&gt; Chris’s test is simple: real value forever for free, period, rather than some crippled demo or a countdown to a paywall. A genuinely useful product someone could use indefinitely without paying.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;What can we experiment with, and what’s off-limits for testing?&lt;/strong&gt; Some things you A/B test aggressively (paywall copy, timing, pricing) and some things you never touch because they are core to the free experience.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;What would make a free user feel cheated if we moved it behind the paywall?&lt;/strong&gt; This surfaces the emotional contract, not just the functional one. Users might not churn immediately, but they’ll stop recommending you.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;What dark patterns or ‘growth hacks’ are we explicitly ruling out?&lt;/strong&gt; Life360 included this in their Bill of Rights: no deceptive tactics, no ads that interrupt the Job to be Done, no springing changes on users without notice. Writing down what you &lt;em&gt;won’t&lt;/em&gt; do is as important as what you will.&lt;/li&gt;
&lt;/ol&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-5-work-out-if-a-trial-is-needed&quot;&gt;Step 5: work out if a trial is needed&lt;/h2&gt;



&lt;p&gt;Sometimes newer freemium apps default to offering a free trial, thinking they need to. It’s well-intentioned, but definitely not a requirement. Rather, trials should be strategic: offering them when users need to experience premium features to understand their value, or only to highly engaged users or &lt;a href=&quot;https://www.revenuecat.com/blog/growth/when-is-the-best-time-to-send-a-win-back-offer/&quot;&gt;win-back users&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;A few considerations:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-do-users-need-to-experience-premium-to-understand-it&quot;&gt;1. Do users need to experience premium to understand it?&lt;/h3&gt;



&lt;p&gt;If your premium features are the kind of thing people need to try (like advanced analytics or personalized coaching), a trial makes sense. If the free-to-paid gap is self-evident from the free tier, e.g. “I can see the leaderboard exists but I can’t use it”, a trial may be unnecessary.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-consider-reverse-trials&quot;&gt;2. Consider reverse trials&lt;/h3&gt;



&lt;p&gt;Rather than a traditional free trial that ends and asks users to pay or leave, a reverse trial gives new users premium access for a limited time, then drops them to the free tier. This is increasingly popular in freemium apps because users experience the gap between paid and free from the perspective of losing something (loss aversion), which is a stronger motivator than never having had it.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;It’s distinct from a traditional trial because the user lands on freemium rather than churning entirely.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-don-t-go-too-long&quot;&gt;3. Don’t go too long&lt;/h3&gt;



&lt;p&gt;In general, avoid overly long trials to prevent further delay of monetization. Daily-use apps can get away with a 3-day trial, while weekly-use apps may need 7 days. Match trial length to your app’s usage cadence so users have enough time to experience value but not so much that the urgency to decide disappears.&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-ZMKr8S wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Action time&quot; text=&quot;&lt;p&gt;&lt;strong&gt;Fill in the following template:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;We [will/won’t] offer a free trial because [reasoning].&lt;/em&gt;&lt;/p&gt;&quot; icon=&quot;circle-check&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-6-start-working-on-how-you-communicate-and-push-for-upgrade&quot;&gt;Step 6: start working on how you communicate and push for upgrade&lt;/h2&gt;



&lt;p&gt;Only once you’ve designed a strong setup can you jump to the part I got all excited about at the beginning: the tactics. It’s not to underestimate them; they just work 10x better once you’ve designed the foundations well. Alice Muir Kocourková shares some great pointers on how to do this in her article &lt;a href=&quot;https://www.revenuecat.com/blog/growth/how-to-turn-freemium-users-into-loyal-subscribers/&quot;&gt;&lt;em&gt;How to turn freemium users into loyal subscribers&lt;/em&gt;&lt;/a&gt;. I’d recommend prioritizing the following areas first:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-communicating-freemium-value-nbsp&quot;&gt;1. Communicating freemium value&amp;nbsp;&lt;/h3&gt;



&lt;p&gt;Not getting caught up on listing everything, but zooming in on the few drivers that matter to that user to upgrade. First, work on your overall upgrade message, then get fancier by improving based on user intent and usage (Alice has some great tips for this).&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-onboarding-for-expectations&quot;&gt;2. Onboarding for expectations&lt;/h3&gt;



&lt;p&gt;If your goal is word-of-mouth, you need to be much more intentional in onboarding so that the free experience is strong; if you are focusing on long-term conversion, you may push a bit harder for paid upfront.&lt;/p&gt;



&lt;p&gt;How much you communicate about premium during onboarding is a strategic choice. But no matter your goal, don’t be too discreet. Nothing is worse than thinking an app is fully free, only to get a nasty shock after you’ve invested effort in setting it up and using it. That erodes trust fast.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-working-hard-on-paywall-timing-and-visibility-nbsp&quot;&gt;3. Working hard on paywall timing and visibility&amp;nbsp;&lt;/h3&gt;



&lt;p&gt;A common mistake in freemium is low paywall visibility. I was watching a show on the Channel 4 app (Okay, it was &lt;em&gt;Married at First Sight: Australia&lt;/em&gt;, don’t judge me too much) and I got about 11 episodes in, being driven absolutely mad by the ads. I ended up Googling and discovered that I could upgrade to ad-free for £3.99. Maybe they earned more from me through the ads, but I was at the point of abandoning the show in frustration at the 10–15 minutes of ads per episode. Not knowing about premium nearly caused me to churn entirely.&lt;/p&gt;



&lt;p&gt;Consider what the right moments in the journey are to surface your upgrade offer. Spotify is the gold standard here: their ad interruptions aren’t random annoyances, but carefully calibrated strategic friction — a reminder of what premium feels like, placed at the exact moment you’re most annoyed by the free experience. It’s no coincidence they achieve a 46% freemium-to-paid conversion rate.&lt;/p&gt;



&lt;p&gt;The best freemium apps don’t just build a great free tier and hope people upgrade. They design specific moments throughout the user journey where the value of premium becomes undeniable, and then make it effortless to act on that feeling.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-freemium-isn-t-glamorous&quot;&gt;Freemium isn’t glamorous&lt;/h2&gt;



&lt;p&gt;Freemium is one of the hardest &lt;a href=&quot;https://www.revenuecat.com/blog/growth/ai-hybrid-monetization/&quot;&gt;monetization models&lt;/a&gt; to get right, but when it works, it compounds: free users drive word-of-mouth, which drives more free users, which strengthens your product (through data, network effects, or community), which makes premium more valuable, which funds more investment in the free tier. It’s a flywheel, but only if the foundations are strong.&lt;/p&gt;



&lt;p&gt;The work in this guide:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Deciding your goal&lt;/li&gt;



&lt;li&gt;Defining user success&lt;/li&gt;



&lt;li&gt;Choosing your architecture&lt;/li&gt;



&lt;li&gt;Mapping features with rationale&lt;/li&gt;



&lt;li&gt;Determining if you need a free trial&lt;/li&gt;



&lt;li&gt;Writing your Bill of Rights&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;All of this isn’t glamorous. But it’s the difference between the median freemium app (2.2% conversion) and the top 10% (where freemium apps outperform even hard paywalls), so do the strategic work first, and then I give you full permission to go wild on the tactics.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[We made our whole company vibe code apps — here’s what we learned ]]></title><description><![CDATA[We ran an internal vibe coding hackathon to understand where to improve our product]]></description><link>https://www.revenuecat.com/blog/company/revenuecat-vibe-coding-apps/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/company/revenuecat-vibe-coding-apps/</guid><pubDate>Mon, 20 Apr 2026 11:59:03 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/cover-for-Vibeathon-scaled.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;At RevenueCat we’ve seen a strong trend in first-time developers shipping apps and making their first dollars using vibe coding tools. The trend is clearly visible in number of developers making their first API call:&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-rich is-provider-twitter wp-block-embed-twitter&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;blockquote class=&quot;twitter-tweet&quot; data-width=&quot;500&quot; data-dnt=&quot;true&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;i still don&apos;t think i&apos;ve fully comprehended the implications of this &lt;a href=&quot;https://t.co/U0KPe6F0TR&quot;&gt;pic.twitter.com/U0KPe6F0TR&lt;/a&gt;&lt;/p&gt;— Jacob Eiting (@jeiting) &lt;a href=&quot;https://twitter.com/jeiting/status/1990976422836646203?ref_src=twsrc%5Etfw&quot;&gt;November 19, 2025&lt;/a&gt;&lt;/blockquote&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;To understand this new wave of developers, we decided to become them. &lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-making-everyone-a-customer&quot;&gt;Making everyone a customer&lt;/h2&gt;



&lt;p&gt;At the end of last year we kicked off an internal hackathon, titled &lt;strong&gt;Vibeathon&lt;/strong&gt;, here at RevenueCat. The idea was simple: get everyone in the company to build apps using the same tools our customers are using. This included tools such as Vibecode, Rork, Claude, Cursor, and other agentic development tools — tools that allow non-engineers to build software.&lt;/p&gt;



&lt;p&gt;Shipping quickly and often is one of the core values at RevenueCat, so we gave everyone until the end of January to build an app, add the RevenueCat SDK, and ship it to app stores. Out of the full RevenueCat company, 44 signed up for the hackathon, close to 30 apps got built, and 12 made it to app stores in time. The best part was that most people were from non-engineering functions.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-learning-through-building&quot;&gt;Learning through building&lt;/h2&gt;



&lt;p&gt;Unsurprisingly, people ended up solving their own problems: building apps to track golf progress, recognize good firewood, scan receipts for taxes, and get book suggestions. Our hackathon showed the democratizing effect of vibe coding in microscale: cheaper build process makes it easier to target underserved niches.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;523&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-18-at-11.52.06-1024x523.png&quot; alt=&quot;Screenshot from App Store showing the app Bygone&quot; class=&quot;wp-image-53238&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-18-at-11.52.06-1024x523.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-18-at-11.52.06-300x153.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-18-at-11.52.06-768x392.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-18-at-11.52.06-1536x784.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-18-at-11.52.06-2048x1045.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-18-at-11.52.06-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-18-at-11.52.06-78x40.png 78w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-18-at-11.52.06-696x355.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-18-at-11.52.06-560x286.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-18-at-11.52.06-840x429.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-18-at-11.52.06-80x41.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Screenshot-2026-04-18-at-11.52.06-48x24.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;One of the apps that was built during Vibeathon is &lt;a href=&quot;https://apps.apple.com/us/app/bygone-yesterdays-weather/id6756671942&quot;&gt;Bygone&lt;/a&gt;. Bygone helps you understand today’s weather by showing how it’s changed since yesterday &lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;Before publishing this article I took a look at how much money the built apps have made, and at the moment these apps sit at a bit over $700 in revenue since the beginning of the year. Not enough for anyone to retire, but enough to signal that we built things people found valuable. Comparatively, the two batches of Shipathon (2024 and 2025) have collectively made over $5.5 million, so our apps have some catching up to do still.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-fast-to-build-hard-to-understand&quot;&gt;Fast to build, hard to understand&lt;/h3&gt;



&lt;p&gt;The focus of this hackathon was learning, and we ended up learning about our product, customers, and the vibe coding movement more than we could have expected.&lt;/p&gt;



&lt;p&gt;During the Vibeathon people were building fast and iterating quicker, but a lot of people emphasized how little they actually gained understanding in what was being built. Apps ended up being blackboxes that rely on AI to make improvements. When Apple would reject the app because of a bug, the participants could not diagnose the problem themselves, but had to go back to the AI and hope that it could fix it. Vibecoders are not authors of the product, but operators.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Some participants wanted a more structured approach and created SPEC.md and AGENTS.md to describe how agents should approach the tasks and what patterns to avoid. After that Codex was capable of one-shotting the app during dinner time, signalling that skill in vibecoding is not prompting, but specification writing. Good spec of course requires good understanding of the development concepts that the agent needs to follow. Essentially you’re aiming at getting a good output from a junior developer.&lt;/p&gt;



&lt;p&gt;Most apps were built with React Native (with few Swift exceptions), and all but one targeted iOS. This was also the only platform most of the vibe coding tools support, despite React Native being a cross-platform framework.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-app-store-was-the-hard-part&quot;&gt;The App Store was the hard part&lt;/h3&gt;



&lt;p&gt;Vibeathon brought in a lot of people who had not previously built apps, or had maybe built an app a decade ago and not touched App Store Connect or Play Store Console after that. For most people it turned out that building the app is the actual easy part, and getting it approved through Apple’s and Google’s reviews is the hard part.&lt;/p&gt;



&lt;p&gt;This could be called the last mile problem of vibe coding, when code and implementation become cheaper and more approachable by masses, the real moat is in turning those things into apps and services that users can actually download.&lt;/p&gt;



&lt;p&gt;People also struggled with setting up accounts, in some cases it taking Apple a few weeks to ensure that all required documentation was in order to deploy an app. The contrast is huge, when building an app can take just 5 minutes, but becoming able to distribute can take weeks. This is one of the topics we plan to focus on in the new &lt;a href=&quot;https://www.startapp.school/&quot;&gt;StartApp School program&lt;/a&gt;, by providing detailed guidance on how to set up your Apple and Google Developer accounts.&lt;/p&gt;



&lt;p&gt;Monetizing remains a big hurdle as well. Adding RevenueCat SDK is easy, but Apple and Google have both made it very difficult to be compliant with all their in-app purchases rulings on the first try. Almost no app got through the review process the first submission, and most people reported the constant back and forth between fixing reported issues, to end up just getting new ones.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-make-your-people-code&quot;&gt;Make your people code&lt;/h2&gt;



&lt;p&gt;Even before we kicked off Vibeathon, RevenueCat was working on better support for different vibecoding tools. Last year we released our MCP, which allows you to setup and manage products in RevenueCat and App Store Connect through agents. We’ve since improved the MCP with more features, and improved the support for it in different vibe coding tools. RevenueCat dashboard also now supports more agent friendly setup flow, giving you the prompts to setup the SDK without having to do it yourself.&lt;/p&gt;



&lt;p&gt;Vibeathon was the first time we forced people to work solo on these projects. The promise of vibecoding being that anyone from sales to marketing, and operations to engineering could build and monetize apps, without spending considerable time on learning how to code, or having previous technical experience. Understanding this is important as it is being embodied in our new customers as well, who are building apps with a similar setup: no technical background.&amp;nbsp;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Your app got cloned. Now what? A developer’s guide to protecting your work from copycats]]></title><description><![CDATA[From trademark filings to App Store complaints, here’s what you need to know (and avoid) when defending your app against clones]]></description><link>https://www.revenuecat.com/blog/growth/protect-app-from-copycats/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/protect-app-from-copycats/</guid><pubDate>Thu, 16 Apr 2026 16:33:24 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Dev-guide-to-copycat-apps.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Building a successful app is hard enough — even in the age of vibe coding. So watching someone else copy your hard work, slap a new logo on it, and siphon away your revenue is infuriating.&lt;/p&gt;



&lt;p&gt;The app ecosystem has always had a copycat problem, but recent advancements in AI and vibe coding have poured fuel on the fire — making vibe coded app clones one of the fastest-growing threats to original developers. Today, a functional clone of a validated app idea can be generated in days, complete with scraped marketing copy and a nearly identical user interface. When OpenAI launched its official Sora mobile app in late 2025, the App Store was immediately flooded with over a dozen “Sora” and “Sora 2” branded fakes, accumulating hundreds of thousands of downloads and generating significant revenue before Apple intervened.&lt;/p&gt;



&lt;p&gt;For developers, the question is no longer if your successful app will be copied, but when. And more importantly: how do you protect your app from copycats — legally and practically?&lt;/p&gt;



&lt;p&gt;In theory, intellectual property (IP) law provides a robust shield. In reality, the gap between legal theory and the practical experience of navigating App Store disputes is wide. Here is a breakdown of the IP instruments available to app creators, from copyright, patents, and trademarks, to how the platforms handle infringement claims, and the real-world strategies to actually protect your app.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-intellectual-property-toolkit&quot;&gt;The intellectual property toolkit&lt;/h2&gt;



&lt;p&gt;When developers discover a clone, their first instinct is often to claim, “They stole my idea!” Unfortunately, IP law does not protect ideas or concepts. It only protects the specific &lt;em&gt;expression&lt;/em&gt; or &lt;em&gt;implementation&lt;/em&gt; of those ideas. Understanding the different types of mobile app intellectual property protection is the first step in building your defensive moat.&lt;/p&gt;



&lt;p&gt;First, here’s your toolkit at a glance:&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;IP instrument&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;What it protects&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;Cost and timeline&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;Practical utility for indie devs&lt;/strong&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Copyright&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Source code, UI graphics, text&lt;/td&gt;&lt;td&gt;Low cost, automatic&lt;/td&gt;&lt;td&gt;Moderate (easy to circumvent by rewriting code)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Trademark&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;App name, logo, icon&lt;/td&gt;&lt;td&gt;~$350/class, 6-12 months&lt;/td&gt;&lt;td&gt;High (best tool for stopping deceptive clones)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Utility Patent&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Algorithms, functional methods&lt;/td&gt;&lt;td&gt;$10k-$38k+, 2-4 years&lt;/td&gt;&lt;td&gt;Low (too slow and expensive for most)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Trade Secret&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Proprietary backend logic&lt;/td&gt;&lt;td&gt;Cost of security measures&lt;/td&gt;&lt;td&gt;Moderate (only works if kept confidential)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;&lt;em&gt;Note: the table above is specific to the US. While many of the terms and tools work the same way across the world, we’ve gone into more depth on global IP tools further down.&lt;/em&gt;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-copyright-protecting-the-expression&quot;&gt;Copyright: protecting the expression&lt;/h3&gt;



&lt;p&gt;Copyright law automatically protects the original expression of your ideas as soon as they are fixed in a tangible medium. For a mobile app, this includes the source code, user interface graphics, original text, and promotional materials.&lt;/p&gt;



&lt;p&gt;However, copyright is limited by the tension between an idea and the expression of that idea. You cannot copyright the concept of a habit tracker or a meditation timer. If a competitor sees your app, understands how it works, and writes entirely new code to achieve the same functionality with different visual assets, they have not committed copyright infringement.&lt;/p&gt;



&lt;p&gt;While copyright is automatic in most places — the Berne Convention ensures that a work is automatically protected as soon as it’s created — registering your work with the relevant authorities (such as the US Copyright Office) is highly recommended. Registration provides a public record of your ownership, makes enforcement significantly easier, and is often a prerequisite for filing a lawsuit or claiming statutory damages. In the US in particular, registration is a prerequisite for filing a federal infringement lawsuit and for claiming statutory damages, making it a practical necessity rather than a mere formality.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-trademark-protecting-the-brand&quot;&gt;Trademark: protecting the brand&lt;/h3&gt;



&lt;p&gt;For most independent developers and small studios, trademarks are the most practical and effective legal tool. A trademark protects the elements that identify the source of your app — primarily its name, logo, and potentially a distinctive slogan.&lt;/p&gt;



&lt;p&gt;When copycats strike, they often try to confuse users by adopting a name or icon that is deceptively similar to the original. A registered trademark gives you direct, actionable leverage to stop this — and is the clearest basis for an App Store trademark infringement complaint. Both Apple and Google have mechanisms to remove apps that infringe on registered trademarks, and having that registration certificate in hand dramatically speeds up the process.&lt;/p&gt;



&lt;p&gt;There have even been instances where copycat apps claim a trademark before the original has, meaning these apps them generally win out in App Store battles. So it’s crucial to sort your trademark out &lt;em&gt;before &lt;/em&gt;launching and giving anyone time to catch up.&lt;/p&gt;



&lt;p&gt;While you establish “common law” rights simply by using a name in commerce, a formal federal registration provides nationwide protection and a presumption of validity. App trademark registration typically costs around $350 per class in the US — a worthwhile investment for any app showing traction.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-patent-protecting-the-functionality&quot;&gt;Patent: protecting the functionality&lt;/h3&gt;



&lt;p&gt;Utility patents offer the strongest form of protection, safeguarding the novel and non-obvious functional aspects of an invention — the underlying methods, algorithms, and processes that make your app work. Unlike copyright, a patent prevents competitors from using your technical innovations even if they write their own code from scratch.&lt;/p&gt;



&lt;p&gt;However, software patents come with significant hurdles. The process is notoriously slow, often taking two to four years, and prohibitively expensive for many indie developers, with costs frequently ranging from $10,000 to $38,000 or more. Not only that, but following the 2014 Supreme Court decision in &lt;em&gt;Alice Corp. v. CLS Bank&lt;/em&gt;, obtaining patents for abstract software concepts has become increasingly difficult in the United States.&lt;/p&gt;



&lt;p&gt;For well-funded startups with truly novel backend technology, patents are a critical asset. For the average indie developer building a utility app, they are rarely a practical first line of defense.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;The App that Cuts Screen Time by 57% (Backed by Science) — Frederik Riedel, one sec&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/kE-DTun0CbM?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;The exception: Frederik Riedel successfully patented onesec’s intervention mechanism, that is used to reduce users’ screen time, because he was worried about big tech companies copying his invention.&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-global-dimension-national-vs-international-protection&quot;&gt;The global dimension: national vs. international protection&lt;/h3&gt;



&lt;p&gt;A common misconception among developers is that securing IP rights in their home country provides global protection. In reality, IP rights are territorial. A US trademark does not automatically protect your app in Europe, and vice versa.&lt;/p&gt;



&lt;p&gt;For developers targeting a global audience, navigating international IP can be daunting. However, several frameworks simplify the process:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.wipo.int/en/web/madrid-system&quot;&gt;The Madrid System (Trademarks)&lt;/a&gt;: Administered by the World Intellectual Property Organization (WIPO), the Madrid System allows you to apply for trademark protection in up to 132 countries by filing a single international application and paying one set of fees. This is significantly cheaper and easier than hiring local attorneys in dozens of jurisdictions.&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.euipo.europa.eu/en/trade-marks&quot;&gt;The EU Trade Mark (EUTM)&lt;/a&gt;: If Europe is a key market, filing a single EUTM application with the EUIPO provides immediate protection across all 27 EU member states for a base fee of €850. This is vastly more efficient than filing national trademarks in each European country.&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.wipo.int/en/web/pct-system&quot;&gt;The Patent Cooperation Treaty (PCT)&lt;/a&gt;: For the rare indie developer pursuing software patents, the PCT provides a unified procedure for filing patent applications to protect inventions in over 150 contracting states, delaying the expensive process of entering national phases.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;When deciding where to file, follow your user base and your revenue. If 80% of your subscribers are in the US and the UK, prioritize trademark registrations in those two jurisdictions before worrying about the rest of the world.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-the-app-stores-handle-disputes&quot;&gt;How the app stores handle disputes&lt;/h2&gt;



&lt;p&gt;When you spot a clone, your immediate goal is to get it removed from the store. Both Apple and Google provide dispute resolution processes, but navigating them requires understanding their underlying philosophies.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-apple-app-store-process&quot;&gt;The Apple App Store process&lt;/h3&gt;



&lt;p&gt;Apple’s App Review Guidelines explicitly forbid copycats. Guideline 4.1(a) states: “Come up with your own ideas… Don’t simply copy the latest popular app on the App Store, or make some minor changes to another app’s name or UI and pass it off as your own”.&lt;/p&gt;



&lt;p&gt;When you submit a claim to report a copycat app through the Apple App Store Dispute Form, Apple typically forwards your complaint to the accused developer and encourages both parties to resolve the issue directly. Apple’s stated position is that it does not mediate IP disputes or investigate the underlying merits of complex legal claims.&lt;/p&gt;



&lt;p&gt;If the accused developer fails to respond or provide a satisfactory defense, Apple may eventually remove the app. In clear-cut cases of trademark infringement—especially when the complainant provides a valid registration number—Apple often acts swiftly. However, in murkier cases involving UI similarities or copyright claims, the process can drag on, leaving the original developer frustrated.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-google-play-store-process&quot;&gt;The Google Play Store process&lt;/h3&gt;



&lt;p&gt;Google’s approach is structurally similar. Developers can submit a policy violation notice regarding intellectual property. Google forwards the complaint, encourages direct resolution, and may remove the app if the issue remains unresolved.&lt;/p&gt;



&lt;p&gt;Both platforms have faced criticism for operating what some legal experts call a “black box” dispute system. Outcomes are decided privately, often with little explanation. This system can also be weaponized; there are documented cases of larger companies or bad actors filing baseless IP complaints that result in legitimate apps being temporarily removed without due process, simply because the platform wants to avoid liability. Beyond the legal routes, your subscription metrics can also serve as an early warning system — often long before a formal complaint is needed.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-using-subscription-data-as-an-early-warning-system&quot;&gt;Using subscription data as an early warning system&lt;/h2&gt;



&lt;p&gt;Before you ever receive an angry customer support email intended for a copycat, your subscription metrics will likely show the first signs of trouble. Clones that successfully siphon your traffic don’t just steal random users—they steal your highest-intent users who are actively searching for your brand.&lt;/p&gt;



&lt;p&gt;According to &lt;a href=&quot;https://www.revenuecat.com/blog/growth/subscription-app-trends-benchmarks-2026/&quot;&gt;RevenueCat’s &lt;em&gt;State of Subscription Apps 2026&lt;/em&gt; report&lt;/a&gt;, which analyzed over 115,000 apps and $16 billion in revenue, the battle for a subscriber is won or lost almost immediately. You can use these benchmarks to detect if a copycat is impacting your funnel:&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;1. Monitor your Day 0 cancellation rate&lt;/strong&gt; The report found that 55% of all 3-day trial cancellations happen on Day 0. If a copycat is intercepting your branded search traffic, users who intended to download your app will quickly realize they’ve been duped and cancel immediately. A sudden spike in Day 0 trial cancellations, especially from organic search traffic, is a strong indicator of brand confusion.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;2. Watch your Download-to-Paid (D35) conversion&lt;/strong&gt; Hard paywalls convert at a median rate of 10.7% by day 35, five times better than freemium models (2.1%). If you run a hard paywall and your D35 conversion rate suddenly drops while top-of-funnel installs remain steady or grow, it may mean lower-intent or confused users are entering your funnel while your high-intent users are being diverted to a clone.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;3. Track involuntary churn anomalies&lt;/strong&gt; If your app is cloned and the copycat aggressively monetizes users who thought they were buying your product, those users will often issue chargebacks or cancel their cards when they realize the error. &lt;a href=&quot;https://www.revenuecat.com/blog/growth/google-play-billing-error-churn-how-to-fix/&quot;&gt;The global benchmark for involuntary billing failures on Google Play is 31% of all cancellations&lt;/a&gt; (14% on the App Store). A sudden deviation from your baseline involuntary churn rate can signal that users are disputing charges related to brand confusion.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-theory-vs-reality-the-developer-experience&quot;&gt;Theory vs. reality: the developer experience&lt;/h2&gt;



&lt;p&gt;The legal theory suggests a clear path: register your IP, file a complaint, and watch the copycat disappear. The reality experienced by developers is often much messier.&lt;/p&gt;



&lt;p&gt;Consider the case of the Bend app, a popular stretching utility. When a near-identical clone appeared on the App Store, the original developers didn’t just rely on a simple form submission. They meticulously documented the similarities, creating side-by-side video comparisons of the onboarding flows and UI mimicry. They leaned heavily on Apple’s Guideline 4.1, engaged legal counsel to send formal cease-and-desist letters, and maintained constant pressure on both the platform and the infringing studio. It was this combined, multi-front approach that ultimately led to the clone’s removal.&lt;/p&gt;



&lt;p&gt;Conversely, relying solely on the platforms can backfire. In one notable case involving the video app Reely, a major tech company filed a trademark complaint claiming logo similarity. Google, following its standard procedure, removed Reely without investigating the merits of the claim. The developer was forced to initiate federal litigation and secure a temporary restraining order just to force the parties to the negotiating table and get the app reinstated.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-a-practical-playbook-for-protecting-your-app-from-copycats&quot;&gt;A practical playbook for protecting your app from copycats&lt;/h2&gt;



&lt;p&gt;Given the limitations of the legal system and the opacity of the app stores, how should developers protect their work? The most successful strategies combine proactive legal steps with strong business fundamentals.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;1. Trademark early and often:&lt;/strong&gt; Do not wait until you are successful to protect your brand. File a trademark application for your app’s name and logo as early as possible. When a clone appears, a registered trademark is the sharpest weapon you can wield to remove a clone from the App Store.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;2. Document your development:&lt;/strong&gt; Maintain meticulous records of your design process, code commits, and asset creation. Date-stamp your work. If you ever need to prove that you are the original creator and hold the copyright to the UI or code, this paper trail will be invaluable.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;3. Build a comprehensive case:&lt;/strong&gt; If you find a copycat, do not just send an angry email to Apple Support. Build a dossier. Create side-by-side visual comparisons. Highlight identical text strings, stolen marketing assets, and UI mimicry. Make it as easy as possible for the platform reviewer to see the blatant theft.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;4. Utilize cease-and-desist letters:&lt;/strong&gt; Often, a formal letter from an attorney on legal letterhead is enough to scare off a low-effort copycat. Many clone developers are looking for easy money and will fold at the first sign of genuine legal resistance.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;5. The ultimate moat: brand and community:&lt;/strong&gt; Legal tools are necessary, but they are reactive. The most sustainable defense against copycats is building a brand that users love and trust. A clone can copy your pixels, but they cannot copy your community, your customer support, or your reputation.&lt;/p&gt;



&lt;p&gt;As one developer noted in a recent Hacker News discussion about the surge in AI-generated clones: “Your best moat against low effort copycats? Stamina”. Copycats are opportunistic; they rarely have the dedication to maintain the app, fix bugs, respond to user feedback, and continuously iterate. By moving faster and building deeper relationships with your users, you ensure that even if someone steals your interface, they can never steal your business.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[RevenueCat Charts v3: fresher data, better decisions]]></title><description><![CDATA[We’ve rebuilt RevenueCat’s data infrastructure from the ground up.]]></description><link>https://www.revenuecat.com/blog/engineering/revenuecat-charts-v3-fresher-data-better-decisions/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/revenuecat-charts-v3-fresher-data-better-decisions/</guid><pubDate>Thu, 16 Apr 2026 02:12:49 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Charts-v3.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;&lt;/p&gt;



&lt;p&gt;We’ve rebuilt RevenueCat’s data infrastructure from the ground up.&lt;/p&gt;



&lt;p&gt;That rewrite powers a big upgrade we’re excited to share today: &lt;strong&gt;Charts v3&lt;/strong&gt; — a new Charts experience that gives you fresh data in seconds, plus a bunch of new ways to slice, segment, and understand your subscription business.&lt;/p&gt;



&lt;p&gt;At a high level, this new infrastructure unlocks two big things:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Real-time updates across almost every chart:&lt;/strong&gt; instead of waiting hours or days for metrics from App Store Connect or Google Play Console, our new real-time events now flow into your charts as soon as they happen, so you can actually watch launches, experiments, and promos play out in real time.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;A much faster path to new charts:&lt;/strong&gt; because we rebuilt our analytics on a unified subscription model, it’s now &lt;em&gt;way&lt;/em&gt; easier for us to ship new charts and dimensions — which is why, just in the last year of testing and refining this system, we’ve already added a ton of new charts and charting features.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;You can see Charts v3 in your project today by enabling the “v3” toggle on the top right of any chart. When disabled, you will see the legacy chart data and new features enabled by Charts v3 will not be available.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;900&quot; height=&quot;514&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-21.png&quot; alt=&quot;&quot; class=&quot;wp-image-53143&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-21.png 900w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-21-300x171.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-21-768x439.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-21-50x29.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-21-70x40.png 70w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-21-696x397.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-21-560x320.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-21-518x296.png 518w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-21-826x472.png 826w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-21-80x46.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-21-48x27.png 48w&quot; sizes=&quot;auto, (max-width: 900px) 100vw, 900px&quot;&gt;&lt;/figure&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-real-time-actually-means&quot;&gt;What ‘real-time’ actually means&lt;/h2&gt;



&lt;p&gt;Previously, charts updated in batches every 2–12 hours depending on the dataset. Now, almost all charts refresh in &lt;strong&gt;real time&lt;/strong&gt; as events come in, giving you:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Immediate feedback on launches, paywall tests, and promos&lt;/li&gt;



&lt;li&gt;Better intra-day monitoring for spikes, dips, or anomalies&lt;/li&gt;



&lt;li&gt;More consistent behavior across charts, since they’re all driven by the same live pipeline&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Charts v3 currently supports &lt;strong&gt;App Store, Play Store, Stripe, and RevenueCat Web Billing&lt;/strong&gt; apps, with support for our other supported stores coming soon.&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-data-shifts-you-may-notice&quot;&gt;Data shifts you may notice&lt;/h2&gt;



&lt;p&gt;When you enable Charts v3, you may notice some numbers shift compared to the “legacy charts”. That’s expected — and while we understand this may be temporarily disruptive, it’s ultimately a &lt;em&gt;good&lt;/em&gt; thing. Here’s what’s going on at a high level, based on the new Charts v3 architecture:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-a-unified-subscription-model-across-stores&quot;&gt;A unified subscription model across stores&lt;/h3&gt;



&lt;p&gt;Behind the scenes, all charts are now powered by a single, normalized subscriptions model. Instead of treating each store slightly differently, we map store-specific behaviors into a shared model that’s consistent everywhere.&lt;/p&gt;



&lt;p&gt;This new model lets us:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Distinguish product changes (e.g. switching from plan A to B) from simple renewals&lt;/li&gt;



&lt;li&gt;Treat resubscriptions (coming back after a lapse) differently from continuous renewals&lt;/li&gt;



&lt;li&gt;In our &lt;strong&gt;Active Subscriptions Movement&lt;/strong&gt; chart, resubscriptions after a lapsed subscription are now called out as a separate positive line item. In the past, resubscriptions on the Apple App Store were instead shown as negative churn.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Other charts, like &lt;strong&gt;Subscription Retention&lt;/strong&gt; and &lt;strong&gt;Trial Conversion&lt;/strong&gt;, now align more closely with how you actually think about subscriber behavior (e.g. “this user changed products” vs. “this user renewed as normal”).&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-refunds-no-longer-rewrite-history&quot;&gt;Refunds no longer rewrite history&lt;/h3&gt;



&lt;p&gt;Previously, when a payment was refunded, it could change metrics in already-completed periods. That made it harder to trust historic reports, and could cause numbers to ‘wiggle’ days or weeks after the fact.&lt;/p&gt;



&lt;p&gt;With Charts v3, historical data stability is crucial:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Revenue is added on the day the purchase happens&lt;/li&gt;



&lt;li&gt;If that payment is later refunded, the revenue is subtracted on the day of the refund, not retroactively&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;This means historical revenue for completed periods stays stable, and you’ll see negative revenue entries on refund dates.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;The same behavior applies to conversions and LTV. The original purchase contributes to all relevant timeframes, and if it’s refunded, those contributions are removed only in the periods where the refund falls. Completed periods don’t keep shifting under your feet.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-changes-to-cohorting&quot;&gt;Changes to cohorting&lt;/h3&gt;



&lt;p&gt;We’ve also updated the cohorting methodology for &lt;strong&gt;Cohort Explorer&lt;/strong&gt; and &lt;strong&gt;Prediction Explorer&lt;/strong&gt;. Instead of defining big cohorts (like a whole month) using just the first and last calendar days, we now calculate each customer’s lifecycle relative to when they actually started, then aggregate the data.&lt;/p&gt;



&lt;p&gt;In practice, this means:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Late-joining customers no longer have their early revenue ‘pushed’ into the next period&lt;/li&gt;



&lt;li&gt;Cohort-based metrics like 0–30 day LTV are more consistent and easier to compare across time&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-quick-reference-expected-metric-changes&quot;&gt;Quick Reference: expected metric changes&lt;/h3&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Metric&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Expected change&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Reason for change&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Trial Conversion Rate&lt;/td&gt;&lt;td&gt;Likely decrease&lt;/td&gt;&lt;td&gt;Only direct trial-to-paid conversions counted&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Historical Revenue&lt;/td&gt;&lt;td&gt;May shift between periods&lt;/td&gt;&lt;td&gt;Refunds impact the refund date, not purchase date&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Active Subscriptions&lt;/td&gt;&lt;td&gt;Minimal change&lt;/td&gt;&lt;td&gt;Counting method changed, not actual subscribers&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;MRR/ARR&lt;/td&gt;&lt;td&gt;Minimal change&lt;/td&gt;&lt;td&gt;Based on same active subscription count&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-revenuecat-mobile-app-charts-may-look-different&quot;&gt;RevenueCat mobile app charts may look different&lt;/h3&gt;



&lt;p&gt;The official RevenueCat mobile app has not yet switched to Charts v3, so you may see slightly different data until we have switched that over as well.&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-new-charts-and-capabilities-unlocked&quot;&gt;New charts and capabilities unlocked&lt;/h2&gt;



&lt;p&gt;Because the data model is now more flexible, we’ve been able to ship a bunch of new charts and features on top of Charts v3 already — with more on the way.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-period-over-period-comparisons&quot;&gt;Period-over-period comparisons&lt;/h3&gt;



&lt;p&gt;A big upgrade built on Charts v3 is &lt;strong&gt;period-over-period comparisons&lt;/strong&gt;. You can now compare your selected date range against the previous period with a single toggle in the &lt;strong&gt;Compare&lt;/strong&gt; dropdown.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;763&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-19-1024x763.png&quot; alt=&quot;&quot; class=&quot;wp-image-53135&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-19-1024x763.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-19-300x223.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-19-768x572.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-19-1536x1144.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-19-50x37.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-19-54x40.png 54w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-19-623x464.png 623w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-19-696x518.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-19-560x417.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-19-398x296.png 398w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-19-634x472.png 634w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-19-80x60.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-19-48x36.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-19.png 2048w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;em&gt;Churn rate over the last 12 months compared to the previous 12 months.&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;When enabled, charts will:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Plot both the &lt;strong&gt;current period&lt;/strong&gt; and &lt;strong&gt;comparison period&lt;/strong&gt; as separate lines&lt;/li&gt;



&lt;li&gt;Show total values and percentage change in the summary&lt;/li&gt;



&lt;li&gt;Let you hover over any point to see the percentage change vs. the previous period at that moment in time&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Period-over-period is available on key charts like Active Subscriptions, MRR, ARR, Churn, New Customers, New Trials, Conversion to Paying, Refund Rate, and more.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-new-and-improved-dimensions&quot;&gt;New and improved dimensions&lt;/h3&gt;



&lt;p&gt;Charts v3 introduces new dimensions and tightens some existing ones, so segmentation matches how you actually reason about your business.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;590&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-20-1024x590.png&quot; alt=&quot;&quot; class=&quot;wp-image-53137&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-20-1024x590.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-20-300x173.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-20-768x442.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-20-1536x884.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-20-50x29.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-20-69x40.png 69w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-20-696x401.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-20-560x322.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-20-514x296.png 514w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-20-820x472.png 820w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-20-80x46.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-20-48x28.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-20.png 2048w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;em&gt;The segment picker has new grouping and now includes search to make it easier to find the right dimension.&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;New dimensions include:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Custom attributes&lt;/strong&gt;: segment by the custom attributes you set on customers&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Experiment&lt;/strong&gt;: filter/segment charts by experiment and variant&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;App version&lt;/strong&gt;: analyze metrics by the first app version a customer used&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Attribution&lt;/strong&gt;: filter/segment using Source, Campaign, Keyword, etc.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;We’ve also improved existing dimensions:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Platform&lt;/strong&gt; now refers to the customer’s &lt;strong&gt;first seen&lt;/strong&gt; platform (where they originated), not the last platform they touched — so segmenting by platform is more stable over time&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Country&lt;/strong&gt; now prioritizes the app store storefront over IP-based location, aligning charts more closely with how revenue and subscribers are actually distributed across markets&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;For full definitions and edge cases, see the &lt;a href=&quot;https://www.revenuecat.com/docs/dashboard-and-metrics/charts/real-time-charts&quot;&gt;Charts v3 docs&lt;/a&gt;.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-new-active-customers-chart&quot;&gt;New Active Customers Chart&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;584&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-16-1024x584.png&quot; alt=&quot;&quot; class=&quot;wp-image-53129&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-16-1024x584.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-16-300x171.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-16-768x438.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-16-1536x876.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-16-50x29.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-16-70x40.png 70w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-16-696x397.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-16-560x319.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-16-519x296.png 519w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-16-828x472.png 828w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-16-80x46.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-16-48x27.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-16.png 2048w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The new &lt;strong&gt;Active Customers&lt;/strong&gt; chart plots all users that were seen in the period being measured, regardless of whether they’ve made a purchase. This works well to plot out your daily active users (DAU). An important note is that this chart does not yet correct for aliased customers, so in cases where the same customer appears under multiple linked app user IDs, active customer counts may be overstated.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-trial-conversion-rate&quot;&gt;Trial Conversion Rate&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;591&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-17-1024x591.png&quot; alt=&quot;&quot; class=&quot;wp-image-53131&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-17-1024x591.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-17-300x173.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-17-768x443.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-17-1536x887.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-17-50x29.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-17-69x40.png 69w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-17-696x402.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-17-560x323.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-17-513x296.png 513w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-17-818x472.png 818w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-17-80x46.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-17-48x28.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-17.png 2048w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The new &lt;strong&gt;Trial Conversion Rate&lt;/strong&gt; chart is cohorted by trial start date and focuses purely on the trial-to-paid step conversion, making it easier to understand how changes to acquisition, pricing, or paywalls affect payment behavior over time.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-updated-active-subscriptions-movement-state-bar-chart&quot;&gt;Updated Active Subscriptions Movement (state bar chart)&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;659&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-18-1024x659.png&quot; alt=&quot;&quot; class=&quot;wp-image-53133&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-18-1024x659.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-18-300x193.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-18-768x494.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-18-1536x989.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-18-50x32.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-18-62x40.png 62w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-18-696x448.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-18-560x360.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-18-460x296.png 460w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-18-733x472.png 733w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-18-80x51.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-18-48x31.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-18.png 2048w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;We’ve refreshed the &lt;strong&gt;Active Subscriptions Movement&lt;/strong&gt; chart to better visualize how subscribers move between states (new, renewed, churned, product changes, resubscriptions, etc.) using a more intuitive state bar format.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-paywall-charts&quot;&gt;Paywall charts&lt;/h3&gt;



&lt;p&gt;New &lt;strong&gt;Paywall Charts&lt;/strong&gt; give you a dedicated place to understand paywall performance: conversion, drop-off, and downstream value, all segmented by the same dimensions you already use across RevenueCat.&lt;/p&gt;



&lt;p&gt;You can also now filter and segment other charts by &lt;strong&gt;RevenueCat Paywalls&lt;/strong&gt;, making it much easier to tie conversion and revenue outcomes back to specific paywall experiences and experiments.&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-try-charts-v3&quot;&gt;Try Charts v3&lt;/h2&gt;



&lt;p&gt;Charts v3 is available in your dashboard today for apps using the supported stores.&lt;/p&gt;



&lt;p&gt;If you notice differences in your metrics after switching, refer to the &lt;a href=&quot;https://www.revenuecat.com/docs/dashboard-and-metrics/charts/real-time-charts&quot;&gt;Charts v3 docs&lt;/a&gt; for a chart-by-chart breakdown of what’s changed and why — and, as always, &lt;a href=&quot;https://form.typeform.com/to/iuAUBGNC&quot;&gt;we’d love your feedback&lt;/a&gt; as you start using it in your day-to-day decision making.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Why a hard paywall is the right answer for your app (until it isn’t)]]></title><description><![CDATA[On the podcast: how AI can turn your onboarding from a chore into magic, hyper-personalized experiences that drive both retention and revenue, and why your value-to-noise ratio matters more than how many features you ship.]]></description><link>https://www.revenuecat.com/blog/growth/phil-carter-elemental-growth-sub-club-podcast-2026/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/phil-carter-elemental-growth-sub-club-podcast-2026/</guid><pubDate>Wed, 15 Apr 2026 12:52:51 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/RC-Blog-Cover-Phil-Carter-1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;As an independent growth advisor and angel investor, Phil Carter helps consumer subscription companies scale their growth engines. In a conversation with David Barnard on the Sub Club podcast, he breaks down the tension between maximizing short-term revenue with hard paywalls and building massive businesses through freemium models—and why the most powerful AI features might not need the most expensive LLMs.&lt;/p&gt;


&lt;div class=&quot;lazyblock-d7d847878df0-Z26nLoG wp-block-lazyblock-d7d847878df0&quot;&gt;&lt;blogpostyoutube embed-url=&quot;https://www.youtube.com/watch?v=UYIgu02h8cs&quot;&gt;
&lt;/blogpostyoutube&gt;&lt;/div&gt;


&lt;iframe loading=&quot;lazy&quot; width=&quot;100%&quot; height=&quot;180&quot; frameborder=&quot;no&quot; scrolling=&quot;no&quot; seamless=&quot;&quot; src=&quot;https://share.transistor.fm/e/e1ad64f6?color=FFFFFF&amp;amp;background=30343C&quot;&gt;&lt;/iframe&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-moving-from-checkers-to-chess-the-multi-step-paywall&quot;&gt;&lt;strong&gt;Moving from checkers to chess: The multi-step paywall&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;For the vast majority of subscription apps, a hard paywall is the right answer. The data is clear: hard paywalls often convert five times better than freemium models. If you’re a bootstrapped startup operating with limited capital, it’s the most reliable and low-risk way to grow your business.&lt;/p&gt;



&lt;p&gt;But for companies trying to build a billion-dollar business, freemium is often the only way to attract a massive user base at the top of the funnel. Phil Carter calls the transition from a hard paywall to freemium “moving from playing checkers to playing chess” because it requires significantly more sophistication.&lt;/p&gt;



&lt;p&gt;Recently, Carter worked with a client to navigate this transition. Instead of simply dropping the paywall, they implemented a “multi-step paywall.” The product is free, but users are offered a seven-day trial of the best version. After the trial, they are prompted to subscribe to maintain that maximum value. Combined with pricing and packaging optimizations, this shift resulted in a 75% increase in LTV per user. The business moved from excluding users with a hard paywall to growing much more quickly through organic acquisition.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-trap-of-the-value-to-noise-ratio&quot;&gt;&lt;strong&gt;The trap of the value-to-noise ratio&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;With AI dramatically lowering the cost of software development, the pace of innovation has accelerated. It’s easier than ever to ship new features constantly. But this speed can become a trap.&lt;/p&gt;



&lt;p&gt;“A fallacy that a lot of companies fall into is like, well, more products and more features equals more value and therefore we should just ship products and features as fast as we possibly can,” Carter explains.&lt;/p&gt;



&lt;p&gt;The bottleneck isn’t development speed; it’s the capacity of the human brain to absorb the product experience. As an app becomes bloated with new capabilities, the absolute value might go up, but the complexity and noise increase alongside it. This causes the “value-to-noise ratio” to plummet. To combat this, teams must rigorously analyze which features actually drive long-term retention and aggressively prune the rest.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-why-cheaper-llms-can-build-better-products&quot;&gt;&lt;strong&gt;Why cheaper LLMs can build better products&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;It’s tempting to default to the most powerful frontier models from OpenAI or Anthropic when building AI features. But Carter points to Gamma, an AI-powered presentation tool that reached profitability within six months of launching its AI features in early 2023.&lt;/p&gt;



&lt;p&gt;One of the reasons for Gamma’s rapid path to profitability was their savvy use of underlying LLMs. They didn’t always use the most powerful models. Instead, they found that for their specific use cases, longer-tail models provided performance that was “good enough” while delivering significantly faster response times and drastically lower compute costs.&lt;/p&gt;



&lt;p&gt;“The product experience is a function not just of the output that the LLM provides, but also how fast it provides that output and how expensive it is to generate that output,” Carter notes. For many consumer apps, speed and affordability are more critical to the user experience than peak AI performance.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-400-creative-per-month-advantage&quot;&gt;&lt;strong&gt;The 400-creative-per-month advantage&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;AI isn’t just changing the core product experience; it’s fundamentally altering user acquisition. Carter highlights Runna, a running app that used AI tools to exponentially increase their creative testing volume.&lt;/p&gt;



&lt;p&gt;Runna went from producing tens of creative concepts per month to over 400. This massive increase in volume isn’t just about lowering CAC by finding winning ads faster. It creates a much more rapid learning cycle. By testing hundreds of permutations—using tools like ElevenLabs for voiceovers or Suno for background music—the marketing team learns exactly what resonates with users. Those insights don’t just optimize ad spend; they feed directly back into product roadmap decisions.&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;



&lt;p&gt;In &lt;a href=&quot;https://www.youtube.com/watch?v=UYIgu02h8cs&quot;&gt;the full episode&lt;/a&gt;, Phil also discusses how AI can turn the first 60 seconds of onboarding into a magical experience, why nicheification is the new strategy for crowded app categories, and the importance of building extrinsic triggers to form user habits.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-guest-links&quot;&gt;Guest links:&lt;/h2&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Phil Carter on &lt;a href=&quot;https://www.linkedin.com/in/philgcarter/&quot;&gt;LinkedIn&lt;/a&gt;&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.philgcarter.com/&quot;&gt;Elemental Growth&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/@SubversivePodcast&quot;&gt;Subversive Podcast&lt;/a&gt;&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://maven.com/philcarter/consumer-subscription-growth&quot;&gt;Consumer Subscription Growth Course (Maven)&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://x.com/philgcarter&quot;&gt;@philgcarter&lt;/a&gt; on X&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Frederik Riedel expected 12%. His app cut screen time by 57%.]]></title><description><![CDATA[On the podcast: how Frederik Riedel built one sec as a weekend prototype, accidentally triggered it 20 seconds later, and turned it into a research-backed screen time app with a proven 57% reduction. From a viral tweet with 700 followers to partnerships with Stanford, Cambridge, and three national governments — plus why he filed a US patent as an indie dev.]]></description><link>https://www.revenuecat.com/blog/growth/frederik-riedel-expected-12-his-app-cut-screen-time-by-57/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/frederik-riedel-expected-12-his-app-cut-screen-time-by-57/</guid><pubDate>Wed, 15 Apr 2026 10:37:16 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/LD-Blog-Cover-Frederik-Riedel-1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;After building between 50 and 100 apps, Frederik Riedel coded a weekend prototype to solve his own social media habit. When he accidentally triggered the app’s blocker just 20 seconds after installing it, he knew he had a real business. In a conversation with Charlie Chapman, the one sec founder breaks down how a single tweet drove months of growth, why ironic social media advertising works, and how an indie developer ended up with peer-reviewed research and a US patent.&lt;/p&gt;


&lt;div class=&quot;lazyblock-d7d847878df0-9O7hS wp-block-lazyblock-d7d847878df0&quot;&gt;&lt;blogpostyoutube embed-url=&quot;https://www.youtube.com/watch?v=kE-DTun0CbM&quot;&gt;
&lt;/blogpostyoutube&gt;&lt;/div&gt;


&lt;iframe loading=&quot;lazy&quot; width=&quot;100%&quot; height=&quot;180&quot; frameborder=&quot;no&quot; scrolling=&quot;no&quot; seamless=&quot;&quot; src=&quot;https://share.transistor.fm/e/ee05ccb7?color=FFFFFF&amp;amp;background=30343C&quot;&gt;&lt;/iframe&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-weekend-prototype-that-proved-itself-in-20-seconds&quot;&gt;The weekend prototype that proved itself in 20 seconds&lt;/h3&gt;



&lt;p&gt;Frederik Riedel had been building apps since he was 14 years old. By 2020, he had shipped somewhere between 50 and 100 apps—at one point releasing a new app every week, and even breaking App Store Connect tools that didn’t expect developers to have that many products.&lt;/p&gt;



&lt;p&gt;But his most successful app started simply as a tool to solve his own problem during the COVID-19 lockdowns. Frustrated by how much time he was spending on Instagram and Twitter, but unwilling to go cold turkey, he built a prototype that intercepted social media app openings and forced him to do a brief breathing exercise.&lt;/p&gt;



&lt;p&gt;The validation was immediate. “I built the first prototype on a weekend, put it on my own phone,” Frederik recalls. “Actually, when I installed the app on my own phone, 20 seconds afterwards, I accidentally ended up opening Twitter and I ran into my own app. And I was like, really, okay, I’m onto something here.”&lt;/p&gt;



&lt;p&gt;Even the developer who had just written the code was operating on autopilot. Within two weeks of using his own prototype, his screen time dropped by 50%. He spent another two weeks polishing the app and released it as one sec.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-why-the-best-screen-time-ads-belong-on-social-media&quot;&gt;Why the best screen-time ads belong on social media&lt;/h3&gt;



&lt;p&gt;When one sec launched, a simple screen recording of the app in action on Twitter went viral, driving thousands of downloads in the first few days. That single organic tweet fueled growth for months. But when Frederik wanted to scale, he turned to an ironic strategy: paying for ads on the very platforms his app was designed to block.&lt;/p&gt;



&lt;p&gt;He started running ads on Instagram, and the results were explosive. “My revenue was kind of like doubling every single month,” he says.&lt;/p&gt;



&lt;p&gt;The strategy worked because it was the ultimate form of targeted advertising. “Of course on social media, I find my target group of people that spend a lot of time on social media and want to spend less,” Frederik explains. Every single person scrolling through Instagram was a potential customer, and the ads caught them in the exact moment they were experiencing the problem one sec solves. It was the digital equivalent of his earlier strategy for a climbing app: putting physical posters up in climbing gyms.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-57-constant-and-the-power-of-peer-reviewed-indie-apps&quot;&gt;The 57% constant and the power of peer-reviewed indie apps&lt;/h3&gt;



&lt;p&gt;Most indie developers rely on App Store reviews for social proof. Frederik went a different route: he partnered with the Max Planck Institute to conduct rigorous scientific research on one sec’s effectiveness.&lt;/p&gt;



&lt;p&gt;The collaboration started when a researcher who used the app reached out. They set up an opt-in study where users donated their usage data. Frederik was hoping for a statistically significant 12% reduction in screen time. Instead, the data showed a massive 57% drop.&lt;/p&gt;



&lt;p&gt;“All the experiments that we ran, they were always showing numbers around 57% reduction, which is kind of like almost seems like a nature constant of attention that you can steal from someone without noticing it,” he says.&lt;/p&gt;



&lt;p&gt;That research became a massive competitive advantage. In a market flooded with snake-oil productivity apps, one sec had peer-reviewed evidence. Therapists began recommending it to patients. The app became a proxy for researchers who couldn’t get data directly from Meta or Snapchat, leading to partnerships with Stanford, Cambridge, and the governments of Germany, Denmark, and the UK.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-why-an-indie-dev-filed-a-us-patent&quot;&gt;Why an indie dev filed a US patent&lt;/h3&gt;



&lt;p&gt;With the research proving the app’s massive effectiveness, a friend from Silicon Valley pushed Frederik to do something unusual for a solo developer: file a patent.&lt;/p&gt;



&lt;p&gt;The logic was simple. If the intervention worked this well, the big tech companies would eventually notice. A patent wouldn’t necessarily stop them from building their own version, but it would change the dynamic.&lt;/p&gt;



&lt;p&gt;“This is the only way you can protect yourself from getting copied at some point,” Frederik says. “At least I wanted to give the big companies a reason to talk to me first before just copying or stealing my idea.”&lt;/p&gt;



&lt;p&gt;It was an expensive and energy-intensive process, but having the peer-reviewed research data made the application much stronger. The US Patent Office approved it, giving this bootstrapped indie app a protective moat usually reserved for venture-backed startups.&lt;/p&gt;



&lt;p&gt;In the full episode, Frederik also talks about getting an email from Apple for being an underage developer, how he manages a team of 18 people with zero management layer, and why he thinks Mastodon is the perfect non-addictive social network.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-guest-links&quot;&gt;Guest links:&lt;/h2&gt;



&lt;p&gt;•&lt;a href=&quot;https://mastodon.social/@frederik&quot; rel=&quot;noreferrer noopener&quot; target=&quot;_blank&quot;&gt;Frederik Riedel on Mastodon&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;•&lt;a href=&quot;https://one-sec.app/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;one sec&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[RevenueCat supports app-to-web checkout — here’s why you shouldn’t use it]]></title><description><![CDATA[A debate on whether the financial upside is worth the operational headache]]></description><link>https://www.revenuecat.com/blog/growth/why-you-shouldnt-use-app-to-web/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/why-you-shouldnt-use-app-to-web/</guid><pubDate>Tue, 14 Apr 2026 13:38:58 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Heres-why-you-shouldnt-use-RevenueCats-app-to-web-checkout.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;There is a version of this post that would probably perform better on social. It would say app-to-web is finally here, the economics are obvious, the app stores have been weakened, and every subscription app should rush to move checkout to the browser&lt;/p&gt;



&lt;p&gt;I do not think that version would be very helpful&lt;/p&gt;



&lt;p&gt;The honest version is simpler: &lt;strong&gt;yes, we support app-to-web checkout&lt;/strong&gt;. We support it today with &lt;strong&gt;RevenueCat Billing / Web Billing&lt;/strong&gt;, we support it with &lt;strong&gt;Paddle&lt;/strong&gt;, we support &lt;strong&gt;Stripe Billing&lt;/strong&gt; as a web billing system that can sync into RevenueCat, and we support &lt;strong&gt;Stripe Managed Payments&lt;/strong&gt; in private beta&lt;/p&gt;



&lt;p&gt;The other honest part is the one fewer people want to say out loud: &lt;strong&gt;most apps probably should not do app-to-web checkout&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Not because it is impossible. Not because it is non-compliant in every case. Not because the tooling is not real. But because the financial upside is often overstated, while the operational, conversion, support, and retention side effects are understated. If you’re a large app with meaningful leverage, sophisticated lifecycle marketing, strong experimentation capabilities, and enough margin pressure to justify the work, app-to-web can make sense. If you are not, there is a good chance you are trading a simple problem for a much messier one&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-first-what-we-actually-support-today&quot;&gt;First, what we actually support today&lt;/h2&gt;



&lt;p&gt;If you strip away the noise and just look at the platform, RevenueCat Web is now a real product category for us. It includes a &lt;a href=&quot;https://www.revenuecat.com/docs/web/web-billing/web-sdk&quot;&gt;&lt;strong&gt;Web SDK&lt;/strong&gt;&lt;/a&gt;, &lt;a href=&quot;https://www.revenuecat.com/docs/web/web-billing/web-purchase-links&quot;&gt;&lt;strong&gt;Web Purchase Links&lt;/strong&gt;&lt;/a&gt;, a &lt;a href=&quot;https://www.revenuecat.com/docs/tools/paywalls/creating-paywalls/web-purchase-button&quot;&gt;&lt;strong&gt;Web Purchase Button&lt;/strong&gt;&lt;/a&gt; to link out from in-app paywalls, &lt;a href=&quot;https://www.revenuecat.com/docs/web/paywalls&quot;&gt;&lt;strong&gt;Web Paywalls&lt;/strong&gt;&lt;/a&gt;, &lt;a href=&quot;https://www.revenuecat.com/feature/funnels&quot;&gt;&lt;strong&gt;Web Funnels&lt;/strong&gt;&lt;/a&gt; for web-to-app flows, and &lt;a href=&quot;https://www.revenuecat.com/docs/web/redemption-links&quot;&gt;&lt;strong&gt;Redemption Links&lt;/strong&gt;&lt;/a&gt; that help tie an anonymous web purchase back to the correct app user&lt;/p&gt;



&lt;p&gt;The app-to-web flow we promote is straightforward in concept. A user starts on a paywall in your app, taps through to a web checkout, completes the purchase there, then comes back to the app via deep link or redemption flow and gets access unlocked. We keep entitlements in sync across app and web once the purchase is recognized&lt;/p&gt;



&lt;p&gt;That sounds clean on a diagram because, to be fair, it is fairly clean on a diagram&lt;/p&gt;



&lt;p&gt;In practice, the capability picture depends heavily on &lt;strong&gt;which billing engine&lt;/strong&gt; you choose&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;Billing option&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;What we support today&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;Important caveat&lt;/strong&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;RevenueCat Billing / Web Billing&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Our own web billing engine with Web SDK and Web Purchase Links support, plus hosted purchase flows, subscription lifecycle handling, and customer management portal support&lt;/td&gt;&lt;td&gt;It uses Stripe as the payment processor underneath, but is a separate RevenueCat billing engine. Some limitations still apply, including localization gaps in some surfaces and country-specific billing-data limitations&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Paddle Billing&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;We support importing Paddle purchases and support Paddle across Web SDK, Web Purchase Links, Web Paywalls, Web Funnels, and Redemption Links&lt;/td&gt;&lt;td&gt;Paddle-specific operational constraints still exist; for example, our Paddle integration does not currently support Paddle’s abandoned cart emails&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Stripe Billing&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;We support importing external purchases from Stripe Billing and syncing entitlements back to the app&lt;br&gt;Very soon, we’ll also support Web SDK, WPLs, Funnels, and Redemption Links&lt;/td&gt;&lt;td&gt;The main caveat is “which Stripe path are you actually choosing?.” Stripe Billing, Stripe Checkout, and Stripe Managed Payments solve slightly different problems, so teams should be precise about the implementation path they want&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Stripe Managed Payments&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;We support this through the &lt;strong&gt;Stripe Billing integration&lt;/strong&gt;, with Stripe acting as merchant-of-record for eligible transactions&lt;/td&gt;&lt;td&gt;It is currently a &lt;strong&gt;private beta / invite-only&lt;/strong&gt; feature&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;That is the part I want to be very clear about, because ‘supports app-to-web’ can mean a few different things depending on what people hear. We do not just mean ‘you can hack a link into a button’. We mean &lt;strong&gt;there is now an actual product set for hosted web checkout, redemption, and entitlement sync&lt;/strong&gt;. But it also does &lt;em&gt;not&lt;/em&gt; mean every billing provider has identical maturity, identical feature coverage, or identical rollout status&lt;/p&gt;



&lt;p&gt;There is another important nuance here. In the US, iOS developers are now permitted to guide users to web-based payment flows without additional Apple fees or restrictive design requirements following the &lt;a href=&quot;https://www.revenuecat.com/blog/engineering/can-you-use-stripe-for-in-app-purchases/&quot;&gt;Epic v. Apple ruling from early 2025&lt;/a&gt;. That’s &lt;strong&gt;in the US and on iOS only&lt;/strong&gt;. For other platforms and other markets, app-to-web is &lt;em&gt;sometimes&lt;/em&gt; possible, but always comes with additional fees, and reporting requirements. That means app-to-web is not a blanket ‘turn this on everywhere’ strategy. You need to make sure you control exactly who sees it and where&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-so-why-should-most-people-not-use-app-to-web&quot;&gt;So why should most people not use app-to-web?&lt;/h2&gt;



&lt;p&gt;When people say ‘app-to-web’, what they often mean is ‘save 15% or 30% on store fees’. And what they often forget is that the &lt;em&gt;fee&lt;/em&gt;&lt;strong&gt; &lt;/strong&gt;is not the only thing that dictates how much money you take home at the end of the day&lt;/p&gt;



&lt;p&gt;The first issue is the most obvious one:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-conversion-usually-gets-worse&quot;&gt;1. Conversion usually gets worse&lt;/h3&gt;



&lt;p&gt;Every additional step between intent and payment hurts. Sending someone out of an app, into a browser or hosted checkout, through another authentication context, into a billing form, then back into the app is simply more fragile than native in-app purchase. Even if the flow is well designed, you are introducing context switching, more points of abandonment, more places for attribution to break, and more opportunities for a user to decide they’ll do it later. You might recover margin on the users who complete checkout, but if enough of them fail to complete it, the math stops looking clever&lt;/p&gt;



&lt;p&gt;This is one of those areas where teams can accidentally fool themselves. If you only look at &lt;strong&gt;completed payer margin&lt;/strong&gt;, web checkout looks great. If you look at &lt;strong&gt;paywall visitor to activated subscriber&lt;/strong&gt;, it can look much worse. And for most subscription apps, the second number is the one that matters&lt;/p&gt;



&lt;p&gt;The second issue is more uncomfortable because it can make your retention chart look better for the wrong reason:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-people-are-often-less-aware-of-how-to-cancel-web-subscriptions&quot;&gt;2. People are often less aware of how to cancel web subscriptions&lt;/h3&gt;



&lt;p&gt;That can create the appearance of stronger retention or lower churn, but in many cases what you are really seeing is lower customer clarity. App store subscription management is not perfect, but users broadly understand where to go. The moment you split billing systems, some of your customers now manage on Apple, some on Google, some in Stripe, some in Paddle, some in RevenueCat Billing-backed web flows. That can absolutely reduce voluntary churn. It can also absolutely increase frustration, support load, refund requests, chargebacks, and a long tail of unhappy users who feel like billing became harder the moment they gave you money&lt;/p&gt;



&lt;p&gt;In May of 2025, &lt;a href=&quot;https://www.revenuecat.com/blog/growth/iap-vs-web-purchases-conversion-test/&quot;&gt;we launched a (much publicized) in-app purchase vs. web checkout experiment&lt;/a&gt; with an app we own. That experiment saw &lt;strong&gt;6% fewer paying customers&lt;/strong&gt; when we added web checkout. That same experiment currently has &lt;strong&gt;2.7x (+170%!) more subscribers set to renew&lt;/strong&gt; on web&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;IAP only&lt;/td&gt;&lt;td&gt;IAP + web&lt;/td&gt;&lt;td&gt;Difference&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Conversion to paying&lt;/td&gt;&lt;td&gt;7.8%&lt;/td&gt;&lt;td&gt;7.4%&lt;/td&gt;&lt;td&gt;– 5.1%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Active subscribers&lt;/td&gt;&lt;td&gt;211&lt;/td&gt;&lt;td&gt;209&lt;/td&gt;&lt;td&gt;-1%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Active subscribers (set to renew)&lt;/td&gt;&lt;td&gt;46&lt;/td&gt;&lt;td&gt;101&lt;/td&gt;&lt;td&gt;+ 119.4%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Churned subscribers&lt;/td&gt;&lt;td&gt;121&lt;/td&gt;&lt;td&gt;104&lt;/td&gt;&lt;td&gt;– 15%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Refunded customers&lt;/td&gt;&lt;td&gt;28&lt;/td&gt;&lt;td&gt;38&lt;/td&gt;&lt;td&gt;+ 35.7%&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;Those subscribers &lt;em&gt;aren’t&lt;/em&gt; set to renew because, by paying on the web, they enjoy the app much more than they would if they paid via in-app purchase. They’re set to renew because they’ve forgotten to opt out of renewal&lt;/p&gt;



&lt;p&gt;And that brings us to the third issue:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-chargebacks-and-disputes-tend-to-become-more-material-when-you-own-more-of-the-payment-experience&quot;&gt;3. Chargebacks and disputes tend to become more material when you own more of the payment experience&lt;/h3&gt;



&lt;p&gt;App stores absorb a lot of mess for you. Once you move payment to the web, you get more control, but you also inherit more exposure. Tax handling, billing descriptor clarity, payment recovery behavior, lifecycle comms, cancellation UX, and support all become more consequential. Paddle and Stripe Managed Payments can help with the merchant-of-record and tax side for eligible flows, which is precisely why they exist, but that does not magically remove the conversion or support complexity of app-to-web. It just moves one painful category of operational burden off your plate&lt;/p&gt;



&lt;p&gt;The fourth issue is the one small teams underestimate most:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-4-the-savings-are-often-not-that-dramatic-once-you-include-all-costs&quot;&gt;4. The savings are often not that dramatic once you include all costs&lt;/h3&gt;



&lt;p&gt;We do not charge extra for RevenueCat Web itself, but the payment rails still do. In the US you pay &lt;strong&gt;2.9% + 30¢&lt;/strong&gt; for Stripe processing, plus optional Stripe Tax fees where relevant. For Stripe Billing, our docs cite the same transaction fee plus &lt;strong&gt;Stripe Billing fees of 0.7% of volume&lt;/strong&gt;, again before any tax tooling you may need. So say you’re selling a weekly subscription of $5 — &lt;strong&gt;you’d effectively pay Stripe close to 9%&lt;/strong&gt;. Add the fee for Managed Payments, and you’re getting awfully close to the 15% most developers pay&lt;/p&gt;



&lt;p&gt;If you are on &lt;a href=&quot;https://www.revenuecat.com/blog/engineering/small-business-program/&quot;&gt;Apple’s &lt;strong&gt;Small Business Program&lt;/strong&gt;&lt;/a&gt; and paying that &lt;strong&gt;15%&lt;/strong&gt;, that is where the simplistic ‘save 12 percentage points’ narrative starts to fall apart. Between processor fees, billing software fees, tax tooling, engineering time, experimentation time, support cost, revenue leakage from lower conversion, dispute loss, and the long tail of operating multiple billing systems, your net improvement can get very small very quickly. In some businesses it will still be worth it. In many, it will not&lt;/p&gt;



&lt;p&gt;And even if it works in a narrow segment, the fifth issue remains:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-5-you-are-creating-permanent-complexity-not-a-temporary-experiment&quot;&gt;5. You are creating permanent complexity, not a temporary experiment&lt;/h3&gt;



&lt;p&gt;This is the part that almost nobody models properly&lt;/p&gt;



&lt;p&gt;If you run an app-to-web experiment for three months and decide it was a bad idea, your web-billed users do not politely disappear. You still have to support them. You still have to honor their renewals, manage their cancellations, answer their billing questions, reconcile their subscription state, and maintain enough infrastructure so their access remains correct. Congratulations: your test is now a durable second billing stack&lt;/p&gt;



&lt;p&gt;The app stores are opinionated, expensive, and frustrating. They are also operationally simple in ways people stop appreciating once they leave them&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-hidden-cost-is-organizational-not-technical&quot;&gt;The hidden cost is organizational, not technical&lt;/h2&gt;



&lt;p&gt;Most discussions about app-to-web are framed as product or finance decisions. In reality, they are &lt;strong&gt;company decisions&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;You need product and growth to redesign the purchase journey. You need engineering to build routing, redemption, instrumentation, and edge-case handling. You need support to answer “Where do I cancel?” forever. You need lifecycle marketing to own the web renewal and churn experience. You need finance and ops to reason about taxes, disputes, reconciliations, and payout differences. You need legal or policy confidence on where you can and cannot show external payment paths. And you need analytics clean enough to tell whether the whole thing actually worked&lt;/p&gt;



&lt;p&gt;That is a lot of machinery to spin up in order to maybe improve unit economics&lt;/p&gt;



&lt;p&gt;This is why I think the average team should be much more conservative than the current conversation implies. The relevant question is not “Can I avoid app store fees?” The question is: “&lt;strong&gt;Am I capable of operating a better billing business than Apple or Google for this segment of users?”&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;For a lot of teams, the honest answer is no&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-when-app-to-web-probably-does-make-sense&quot;&gt;When app-to-web probably does make sense&lt;/h2&gt;



&lt;p&gt;All this being said, there are real cases where I would absolutely consider using app-to-web&lt;/p&gt;



&lt;p&gt;If you have a large US user base, high average revenue per paying user, meaningful paid acquisition economics, strong experimentation infrastructure, and enough support capacity to absorb billing fragmentation, then app-to-web can be rational. If you already have a serious web business, or if the web is strategically important beyond payments, it becomes even more attractive. If your app category naturally supports account-based behavior and cross-platform usage, users may tolerate the extra checkout friction better than they would in a lightweight impulse-purchase app&lt;/p&gt;



&lt;p&gt;Likewise, if merchant-of-record complexity is the blocker, the fact that &lt;strong&gt;Stripe Managed Payments&lt;/strong&gt; now exists, is genuinely interesting. If you want the most integrated RevenueCat-native route, &lt;strong&gt;RevenueCat Billing / Web Billing&lt;/strong&gt; is what we support most directly today. If Paddle fits your tax and merchant-of-record preferences better, our Paddle path is a very capable option&lt;/p&gt;



&lt;p&gt;If this topic is top of mind for you, on Tuesday April 28 (the day before &lt;a href=&quot;https://stripesessions.com/&quot;&gt;Stripe Sessions&lt;/a&gt;) we’re co-hosting &lt;a href=&quot;https://luma.com/webforapps?utm_source=RC_Blog&quot;&gt;The Web for Apps Opportunity&lt;/a&gt; in downtown San Francisco:&lt;/p&gt;



&lt;p&gt;A full day event that includes talks by RevenueCat and Stripe on how, where, and when to use web payments for your app. ​The afternoon concludes with a private executive dinner at 54 Mint&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;a href=&quot;https://luma.com/webforapps?utm_source=RC_Blog&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2560&quot; height=&quot;1429&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/webforapps_landscape_blog_v2_compressed-1-scaled.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-53105&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/webforapps_landscape_blog_v2_compressed-1-scaled.jpg 2560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/webforapps_landscape_blog_v2_compressed-1-300x167.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/webforapps_landscape_blog_v2_compressed-1-1024x572.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/webforapps_landscape_blog_v2_compressed-1-768x429.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/webforapps_landscape_blog_v2_compressed-1-1536x857.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/webforapps_landscape_blog_v2_compressed-1-2048x1143.jpg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/webforapps_landscape_blog_v2_compressed-1-50x28.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/webforapps_landscape_blog_v2_compressed-1-72x40.jpg 72w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/webforapps_landscape_blog_v2_compressed-1-696x388.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/webforapps_landscape_blog_v2_compressed-1-560x313.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/webforapps_landscape_blog_v2_compressed-1-530x296.jpg 530w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/webforapps_landscape_blog_v2_compressed-1-840x469.jpg 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/webforapps_landscape_blog_v2_compressed-1-80x45.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/webforapps_landscape_blog_v2_compressed-1-48x27.jpg 48w&quot; sizes=&quot;auto, (max-width: 2560px) 100vw, 2560px&quot;&gt;&lt;/a&gt;&lt;/figure&gt;



&lt;p&gt;Apply to attend &lt;a href=&quot;https://luma.com/webforapps?utm_source=RC_Blog&quot;&gt;here&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;So this is not me saying never do app-to-web. It is me saying &lt;strong&gt;do it for the right reasons, with open eyes&lt;/strong&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-my-actual-recommendation&quot;&gt;My actual recommendation&lt;/h2&gt;



&lt;p&gt;If you are curious about app-to-web, do not start by trying to replace in-app purchases broadly. Start by treating it like a constrained experiment, with a proper hypothesis&lt;/p&gt;



&lt;p&gt;Pick a narrow, eligible segment. Measure full-funnel conversion, not just net revenue on completed purchases. Track refunds, disputes, support tickets, cancellation confusion, and cohort quality. Check back one month, 3 months, 12 months after the experiment ends. Assume your support burden will be higher than the first spreadsheet suggests. Assume that billing fragmentation will last longer than the experiment does. Assume fee savings will compress after you include everything&lt;/p&gt;



&lt;p&gt;And if, after all of that, the economics still work out, great. You probably have a real business case&lt;/p&gt;



&lt;p&gt;But most teams will arrive at a less exciting and more useful conclusion: app-to-web can work, but not well enough to justify everything that comes with it&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Stop measuring downloads: what to track before product-market fit]]></title><description><![CDATA[The early-stage metrics that actually predict whether your app will succeed]]></description><link>https://www.revenuecat.com/blog/growth/pre-product-market-fit-metrics/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/pre-product-market-fit-metrics/</guid><pubDate>Tue, 14 Apr 2026 13:36:11 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Blog_38_Stop-measuring-downloads-—-what-to-track-before-product-market-fit.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;It’s such an exciting moment when you launch your app. You finally put it out into the world… now what?&lt;/p&gt;



&lt;p&gt;It’s tempting to focus on what &lt;em&gt;feels&lt;/em&gt; productive: building new features, testing prices, running ads. But if you don’t know whether you’re actually solving a real problem, most of that is just optimisation in the dark.&lt;/p&gt;



&lt;p&gt;The metrics that feel good in that early phase — downloads, signups, even revenue — don’t necessarily tell you if you’re on the right track. They tell you people are showing up and trying the app, not whether they’re getting real value from it.&lt;/p&gt;



&lt;p&gt;I see this constantly in growth audits. One client had over 90% onboarding completion, which sounds fantastic. But most users were gone by day two. Onboarding wasn’t the issue, but value was.&lt;/p&gt;



&lt;p&gt;In this first, exciting phase of launching your new app or finding product-market fit, it’s critical to focus on metrics that reflect real value creation, not the shiny, ego-boosting ones.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;We’ll talk about how to make that mindset shift, and from there:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Which metrics to ignore so you don’t get distracted&lt;/li&gt;



&lt;li&gt;What metrics you simply can’t measure yet&lt;/li&gt;



&lt;li&gt;What to focus on instead&lt;/li&gt;



&lt;li&gt;How to find the one overarching metric to guide you.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;We’ll also cover some traps and risks along the way, such as why retention alone doesn’t equal product-market fit.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;And despite focusing on metrics here, please (she begs politely) don’t ignore qualitative signals. At this stage, qualitative feedback will guide you just as much — if not more — than quantitative data. You don’t have the luxury of large data sets yet, and that’s okay.&lt;/p&gt;



&lt;p&gt;From there, I’ll help you define what finding product-market fit actually looks like for your app, so you leave with a clear list of metrics to focus on. This is the super-quick crash course version. If you want more depth, I highly recommend checking out my free course, &lt;em&gt;&lt;a href=&quot;https://www.startapp.school/courses/how-to-make-an-app-people-will-pay-for&quot;&gt;How to make an app people will pay for&lt;/a&gt;&lt;/em&gt;, where I walk through this in detail and give you a full Product Strategy Canvas to apply to your own app.&lt;/p&gt;



&lt;p&gt;Focusing on the right metrics helps you learn faster and move forward with confidence. At this early stage, that clarity makes everything feel a lot less overwhelming.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-really-matters-pre-product-market-fit&quot;&gt;What really matters pre-product market fit&lt;/h2&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/product-market-fit-subscription-apps/&quot;&gt;Product-market fit&lt;/a&gt; means building an app that solves a specific problem for a specific audience — with a solution that genuinely fits their needs.&lt;/p&gt;



&lt;p&gt;It’s the point where you’re no longer persuading people to use your product — they &lt;em&gt;want&lt;/em&gt; it. They love it, get consistent value from it, and choose to keep using it.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;532&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-9-1024x532.png&quot; alt=&quot;&quot; class=&quot;wp-image-53074&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-9-1024x532.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-9-300x156.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-9-768x399.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-9-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-9-77x40.png 77w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-9-696x361.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-9-560x291.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-9-840x436.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-9-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-9-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-9.png 1306w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;em&gt;What finding product-market fit is about&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;The reality is that &lt;strong&gt;pre-product-market fit isn’t about growth&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;Yes, you need some growth, enough to generate data, learn, and validate what’s working. But the core questions you’re trying to answer are:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Does my solution actually solve the problem?&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Who values it the most?&amp;nbsp;&lt;/li&gt;



&lt;li&gt;What makes them come back?&amp;nbsp;&lt;/li&gt;



&lt;li&gt;What would they pay for?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;A common trap at this stage is getting pulled into growth too early. Sometimes that pressure comes from investors. Sometimes it comes from a few early wins that make you feel ready to scale. You rush into paid ads, burn through runway, watch users churn, panic… and try to acquire even more users.&lt;/p&gt;



&lt;p&gt;This is what &lt;a href=&quot;https://www.revenuecat.com/blog/growth/eric-seufert-sub-club-podcast-2025/&quot;&gt;Eric Seufert&lt;/a&gt; calls The Growth Trap.&lt;/p&gt;



&lt;p&gt;Ironically, an over-focus on growth won’t help you grow. Product-market fit will.&lt;/p&gt;



&lt;p&gt;When you fixate on growth metrics too soon, you might achieve short-term spikes, but not long-term, sustainable growth.&lt;/p&gt;



&lt;p&gt;Instead, shift your mindset. At this stage, your job is to learn and to look for strong signals that product-market fit is emerging.&lt;/p&gt;



&lt;p&gt;And here’s the good news: there are so many metrics you could track that I give you full permission to ignore most of them.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-metrics-to-ignore&quot;&gt;What metrics to ignore&lt;/h2&gt;



&lt;p&gt;It’s buzzword bingo for an early-stage founder; millions of metrics and fancy phrases thrown at you, from &lt;a href=&quot;https://www.revenuecat.com/blog/growth/two-key-metrics-you-wont-find-in-the-state-of-subscription-apps-benchmarks/&quot;&gt;Cost of Acquisition to Lifetime Value&lt;/a&gt;. The problem? Not all of them actually matter at this stage.&lt;/p&gt;



&lt;p&gt;So here are some of the most common metrics I give you &lt;strong&gt;100% permission to ignore, or at least not obsess over&lt;/strong&gt;:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Total downloads&lt;/strong&gt;: Just because people download your app doesn’t mean they even open it or get value from it.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Total signups&lt;/strong&gt;: Same idea.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Social media followers&lt;/strong&gt;: Great for the ego, but meaningless if it isn’t actually driving awareness or value.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;App store ranking&lt;/strong&gt;: Might help growth a little, but it tells you nothing about whether you’re solving a real problem.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Day 1 download spikes:&lt;/strong&gt; Don’t over-interpret early spikes; first users often behave differently than your eventual audience.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Other metrics, like time in app or number of sessions, can feel encouraging; they make free users look active, but none of them truly reflect value.&lt;/p&gt;



&lt;p&gt;And that’s the key at this stage: are a specific group of users getting repeated value? If a metric doesn’t help answer that, toss it out.&lt;/p&gt;



&lt;p&gt;Now, there are metrics that reflect value, but at launch, you often can’t measure them yet.&lt;/p&gt;



&lt;p&gt;What metrics should you measure instead?&lt;/p&gt;



&lt;p&gt;With this mindset shift, the metrics that matter pre-product-market fit are behavioral. It’s not about whether users showed up; it’s about whether they did the things that indicate they’re actually getting value.&lt;/p&gt;



&lt;p&gt;Ask yourself:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Are users coming back on their own?&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Are they using the core feature?&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Are they willing to pay?&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Are they telling others?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Together, these behaviors give you a clear picture of &lt;strong&gt;where users are dropping off&lt;/strong&gt; and what you need to focus on.&lt;/p&gt;



&lt;p&gt;The key concept here is activation. If you’re activating users, they’re more likely to retain and pay. Activation has a domino effect in early-stage startups. People won’t pay for an app they haven’t truly experienced; they haven’t reached the moment where the value clicks.&lt;/p&gt;



&lt;p&gt;You’re looking for the behaviors that, over time, predict whether someone will stay and pay. Look for patterns across at least 2–3 cohorts before drawing conclusions. Even with small numbers, consistency matters more than volume.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-time-to-first-value-and-time-to-core-value&quot;&gt;Time to first value and time to core value&lt;/h3&gt;



&lt;p&gt;Two useful &lt;a href=&quot;https://www.revenuecat.com/blog/growth/activation-metrics/&quot;&gt;activation metrics&lt;/a&gt; building on product-led growth thinking popularised by Wes Bush:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Time to first value&lt;/strong&gt; – Did the user experience something valuable?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Time to core value&lt;/strong&gt; – Did they start building a habit?&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;For example, in a meditation app:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Time to first value&lt;/strong&gt; might be the time to complete their first meditation session&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Time to core value&lt;/strong&gt; is when they’ve meditated at least four times in a week and started building a routine&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;These metrics help you understand not just whether users are signing up, but whether they’re actually engaging with and benefiting from your product.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;922&quot; height=&quot;679&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/engaging-and-benefiting-post-image.png&quot; alt=&quot;&quot; class=&quot;wp-image-53096&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/engaging-and-benefiting-post-image.png 922w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/engaging-and-benefiting-post-image-300x221.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/engaging-and-benefiting-post-image-768x566.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/engaging-and-benefiting-post-image-50x37.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/engaging-and-benefiting-post-image-54x40.png 54w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/engaging-and-benefiting-post-image-630x464.png 630w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/engaging-and-benefiting-post-image-696x513.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/engaging-and-benefiting-post-image-560x412.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/engaging-and-benefiting-post-image-402x296.png 402w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/engaging-and-benefiting-post-image-641x472.png 641w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/engaging-and-benefiting-post-image-80x59.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/engaging-and-benefiting-post-image-48x35.png 48w&quot; sizes=&quot;auto, (max-width: 922px) 100vw, 922px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The goal isn’t to over-index on speed, as some actions naturally take time. But in the early days, it usually takes too long, so you need to help users reach that value moment faster. It’s more about relative timing than absolute speed.&lt;/p&gt;



&lt;p&gt;For example, in a food-scanning app, users who scanned at least 7 foods in a week were much more likely to stay than those who took 2-3 weeks to reach the same milestone.&lt;/p&gt;



&lt;p&gt;The scanning feature was the main way users could check whether a food was safe to eat.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;So the team could focus on how to help more users complete that action within a defined period, rather than just letting it happen organically, e.g., more in-app nudges to scan, examples of what you can scan with it, etc.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-active-users&quot;&gt;Active users&lt;/h3&gt;



&lt;p&gt;Alongside activation, having a measure of active users, defined by meaningful behaviors rather than just app opens, is extremely important.&lt;/p&gt;



&lt;p&gt;Tracking whether you’re activating a higher percentage of users and doing it faster gives you a clear signal that you’re on the right track.&lt;/p&gt;



&lt;p&gt;And, as always, this should be tied to the key behaviors you’ve identified as indicators of value.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-percentage-of-customers-through-word-of-mouth&quot;&gt;Percentage of customers through word of mouth&lt;/h3&gt;



&lt;p&gt;Referrals are huge. If 15% or more of new users come through referrals, that’s a strong signal of product-market fit.&lt;/p&gt;



&lt;p&gt;Word of mouth takes time to build in a new app, but if you start seeing more people talking about your product and your percentage of users acquired through word of mouth grows, that’s another clear positive signal.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-what-you-can-t-measure-yet-at-launch-nbsp&quot;&gt;What you can’t measure yet at launch&amp;nbsp;&lt;/h3&gt;



&lt;p&gt;We’ve covered what you should ignore and what you should focus on.&lt;/p&gt;



&lt;p&gt;Not to add confusion, but there are also &lt;strong&gt;valuable metrics that are hard to measure at launch&lt;/strong&gt;:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/dashboard-and-metrics/charts/subscription-retention-chart&quot;&gt;Retention curves&lt;/a&gt; need weeks&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/dashboard-and-metrics/charts/realized-ltv-per-customer-chart&quot;&gt;Realized lifetime value per customer&lt;/a&gt; can take months to start to pin down&lt;/li&gt;



&lt;li&gt;Same with sustainable growth&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;It’s not that you shouldn’t measure these metrics at all; it’s just that &lt;strong&gt;at launch, you can’t judge success by them yet&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;Instead, focus on leading indicators — the behaviors that signal value early — rather than lagging indicators, which reflect outcomes further down the line.&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Leading indicators:&lt;/strong&gt; activation, early retention, qualitative feedback&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Lagging indicators:&lt;/strong&gt; lifetime value, revenue, long-term retention&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Leading indicators act as your early warning system. They show whether something might be off track before the final results are in, letting you be &lt;em&gt;proactive&lt;/em&gt; rather than &lt;em&gt;reactive&lt;/em&gt;.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-retention&quot;&gt;Retention&lt;/h3&gt;



&lt;p&gt;One of the most common metrics people tell you to track in this early phase is retention.&lt;/p&gt;



&lt;p&gt;While it takes time to really understand your retention curves, you can start by looking at 7- and 30-day retention.&lt;/p&gt;



&lt;p&gt;But here’s the trap: &lt;strong&gt;over-indexing on retention too early can be dangerous&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;Apologies for the upcoming rant, but honestly, it felt much-needed. We can’t talk about pre-PMF metrics without diving deeper into the risks of equating retention with PMF.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-retention-trap&quot;&gt;The retention trap&lt;/h2&gt;



&lt;p&gt;Often, it feels like product-market fit is the same as retaining customers. But you can keep people around without actually solving their problem.&lt;/p&gt;



&lt;p&gt;Strange, but I’ve seen it happen. &lt;strong&gt;Good retention can make an app feel like it has product-market fit before it really does.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;There are four ways this can happen.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-gamification-over-value&quot;&gt;1. Gamification over value&lt;/h3&gt;



&lt;p&gt;The first trap is relying on mechanics — streaks, reminders, badges — to drive retention without delivering real value. These are classic forms of &lt;a href=&quot;https://www.revenuecat.com/blog/growth/gamification-in-apps-complete-guide/&quot;&gt;gamification&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;I’ve experienced this myself. I got completely hooked on a game, loving the streaks that kept me coming back. But eventually, I realized I wasn’t really enjoying myself anymore. I was returning because of the mechanics, not the value. And yet, I couldn’t bring myself to delete the app until I quit cold turkey.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-retention-is-driven-by-a-small-group-of-power-users&quot;&gt;2. Retention is driven by a small group of power users&lt;/h3&gt;



&lt;p&gt;This isn’t inherently bad, but it’s something to watch closely.&lt;/p&gt;



&lt;p&gt;It’s all about balance: are you too specific, or is your core group too small to scale? If growth only happens within this small group, your product-market fit might not be ready to scale.&lt;/p&gt;



&lt;p&gt;You need to be specific enough to stand out, but not so niche that you’re building for only a handful of users who aren’t representative of a larger market.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-pricing-that-masks-weak-product-market-fit&quot;&gt;3. Pricing that masks weak product-market fit&lt;/h3&gt;



&lt;p&gt;This happens when heavy discounts or extended trials are offered. Sure, it attracts a lot of users, but often bargain hunters. You might see strong retention numbers from users who signed up for an annual subscription at a very low price, but they’re not actively using your app.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-4-annual-subscriptions-can-delay-churn-rather-than-prevent-it&quot;&gt;4. Annual subscriptions can delay churn rather than prevent it&lt;/h3&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/annual-subscriptions-apps-pros-cons/&quot;&gt;Annual subscriptions&lt;/a&gt; are great for cash flow and have plenty of benefits. But if most users aren’t actively engaging with your app, &lt;strong&gt;locking them in doesn’t mean they value it&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;The lesson: &lt;strong&gt;commitment isn’t the same as conviction&lt;/strong&gt;. Someone locked into an annual plan is not the same as someone who would be devastated to lose your app.&lt;/p&gt;



&lt;p&gt;To avoid this trap:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Pair retention data with engagement data&lt;/strong&gt;: if users are renewing but not actually using the app, dig deeper before celebrating&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Rely on qualitative signals&lt;/strong&gt; to understand your users’ experience and motivations&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-qualitative-signals-to-focus-on&quot;&gt;Qualitative signals to focus on&lt;/h2&gt;



&lt;p&gt;In the early days, you don’t have massive numbers, and that’s completely normal. With small sample sizes, it’s hard to distinguish noise from signal, and the variance in metrics can make even the steadiest founders nervous.&lt;/p&gt;



&lt;p&gt;This is why qualitative signals are extremely valuable. Remember: &lt;strong&gt;product-market fit is qualitative first, quantitative second. &lt;/strong&gt;You’ll feel it before you can measure it: users reaching out unprompted with feedback, telling you how much they love it, asking when features are coming, referring friends without being asked. It’s little moments like that, where growth also feels easier that tell you long before you hit statistical significance that you’re on the right track.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-sean-ellis-test&quot;&gt;The Sean Ellis test&lt;/h3&gt;



&lt;p&gt;Sean Ellis studied hundreds of startups to find what separated the ones that went on to succeed. He discovered that &lt;strong&gt;successful startups typically had at least 40% of users who would be very disappointed if the product no longer existed&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;He created &lt;a href=&quot;https://learningloop.io/glossary/sean-ellis-score&quot;&gt;a simple PMF test&lt;/a&gt; to measure this:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Ask users: ‘How would you feel if you could no longer use [app name]?’
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Very disappointed&lt;/li&gt;



&lt;li&gt;Somewhat disappointed&lt;/li&gt;



&lt;li&gt;Not disappointed&lt;/li&gt;



&lt;li&gt;I no longer use this&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;



&lt;li&gt;Follow up with: ‘Could you explain your answer?’&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;That second question is critical; it helps you understand what actually drives product-market fit, even if your sample size is too small for statistical significance.&lt;/p&gt;



&lt;p&gt;That second question means that even if you don’t have enough data for significance, you can start to understand what drives PMF.&lt;/p&gt;



&lt;p&gt;A few practical tips:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;You need enough responses to get meaningful insight: at least 100 for a general sense, and 500–1,000 if you want to segment by signup reason, main feature used, or other factors&lt;/li&gt;



&lt;li&gt;Survey the right users at the right time, ask those who should have reached their &lt;em&gt;aha!&lt;/em&gt; moment:
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Don’t survey day-one users if it normally takes 7 days to get value&lt;/li&gt;



&lt;li&gt;Don’t limit it to users who’ve been around for months, either, or you risk skewed optimism&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;This test gives you a qualitative measure of product-market fit, helping you identify both the level of engagement and the reasons behind it.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-net-promoter-score-nps&quot;&gt;Net Promoter Score (NPS)&lt;/h3&gt;



&lt;p&gt;The &lt;a href=&quot;https://www.revenuecat.com/blog/growth/net-promoter-score-nps-for-subscription-apps/&quot;&gt;Net Promoter Score&lt;/a&gt; correlates strongly with this. For example, &lt;a href=&quot;https://youtu.be/HiVO4RK7KAw?si=ySFAFajZ6frzNezE&quot;&gt;Ladder found that users&lt;/a&gt; who said they’d be ‘somewhat disappointed’ had much lower NPS scores than those who said ‘very disappointed’.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;It can be valuable to ask, alongside your PMF question, why users would or wouldn’t promote your app. This gives insight not only into how much people value your product, but also what drives advocacy and highlights areas you can improve to turn more users into promoters.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;542&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-10-1024x542.png&quot; alt=&quot;&quot; class=&quot;wp-image-53076&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-10-1024x542.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-10-300x159.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-10-768x407.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-10-1536x814.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-10-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-10-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-10-696x369.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-10-560x296.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-10-840x445.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-10-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-10-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-10.png 1731w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-user-interviews&quot;&gt;User interviews&lt;/h3&gt;



&lt;p&gt;If you don’t have enough users for the Sean Ellis test or measuring NPS, the best recommendation I can give you is to conduct user interviews to hear first hand from customers why they love and don’t love your product.&lt;/p&gt;



&lt;p&gt;Starting with even just 5-10 &lt;a href=&quot;https://www.revenuecat.com/blog/growth/what-drives-users-to-pay-jobs-to-be-done/&quot;&gt;Jobs-to-be-Done (JTBD) interviews&lt;/a&gt; will teach you so much about:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;What drives users to stay&lt;/li&gt;



&lt;li&gt;What matters most to them&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;I recommend prioritizing users with whom you suspect you might have product-market fit as well as recently churned users with a similar need. That way you can understand what the difference is and what to prioritise to improve.&lt;/p&gt;



&lt;p&gt;This also ensures you don’t get distracted by noisy users and keeps your focus on the behaviors and needs that really indicate product-market fit.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-finding-your-north-star-metric&quot;&gt;Finding your North Star Metric&lt;/h2&gt;



&lt;p&gt;As you start to narrow down which metrics actually predict value and gain insights from qualitative research, it’s incredibly helpful to have an overarching metric to guide you.&lt;/p&gt;



&lt;p&gt;This is known as the &lt;a href=&quot;https://www.revenuecat.com/blog/growth/north-star-metrics-subscription-growth/&quot;&gt;North Star Metric&lt;/a&gt;: the single best metric that indicates whether users are getting value, whether you’re getting value, and whether you’re building a sustainable business.&lt;/p&gt;



&lt;p&gt;Post-product-market fit, North Star Metrics often look like active subscribers or monthly recurring revenue. But pre-product-market fit, it’s crucial that this metric is behavioral, focused on the actions that show users are truly experiencing value.&lt;/p&gt;



&lt;p&gt;For example:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Spotify focuses on time spent listening&lt;/li&gt;



&lt;li&gt;Slack focuses on messages sent&lt;/li&gt;



&lt;li&gt;Dropbox on files uploaded.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;They’re all measuring core actions that signal value.&lt;/p&gt;



&lt;p&gt;These are companies that have already found product-market fit. For you, the goal isn’t to copy their metric; it’s to find the equivalent for your app at your stage. Start with a core hypothesis:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;What is the core problem you’re solving?&lt;/li&gt;



&lt;li&gt;What behaviors would indicate it’s being solved?&amp;nbsp;&lt;/li&gt;



&lt;li&gt;And how often should that behavior occur?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;For instance, a &lt;strong&gt;budget-tracking app&lt;/strong&gt; might hypothesize that users who &lt;strong&gt;categorize at least 5 transactions per week&lt;/strong&gt; are deriving value. Ideally, your metric includes &lt;strong&gt;both the specific action and the time frame&lt;/strong&gt; you want to see.&lt;/p&gt;



&lt;p&gt;Post-product-market fit, your North Star Metric should remain stable unless you make a major pivot. But pre-product-market fit, it’s okay to refine it as you learn more. You probably won’t know with confidence exactly what that action is or what the North Star Metric should be, and that’s completely fine.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-defining-pmf-for-your-app&quot;&gt;Defining PMF for your app&lt;/h2&gt;



&lt;p&gt;Now it’s time to get practical. You’ll want to write down what your PMF definition looks like in behavioral terms.&lt;/p&gt;



&lt;p&gt;The template I use and share in my ‘Make an app people will pay for’ course is the following:&amp;nbsp;&lt;/p&gt;



&lt;p&gt;I’ll know I’m approaching PMF when [specific user type] repeatedly [specific behavior] because my app helps them [specific outcome].&lt;/p&gt;



&lt;p&gt;For example:&amp;nbsp;&lt;/p&gt;



&lt;p&gt;I’ll know I’m approaching product-market fit when &lt;strong&gt;busy parents&lt;/strong&gt; repeatedly &lt;strong&gt;open the app after dinner to plan tomorrow’s meals &lt;/strong&gt;because my app helps them&lt;strong&gt; save 20 minutes of decision-making stress.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Or:&lt;/p&gt;



&lt;p&gt;I’ll know I’m approaching PMF when &lt;strong&gt;people trying to build new habits repeatedly log at least one habit daily&lt;/strong&gt; &lt;strong&gt;for 10 days &lt;/strong&gt;because my app helps them &lt;strong&gt;make it satisfying to see their streak grow.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;One important note: PMF signals are directional. At this stage, you might see them in just one segment, one use case, or one geography, and that’s perfectly fine. You’ll probably start niche and expand.&lt;/p&gt;



&lt;p&gt;If you find PMF in an unexpected segment, that’s actually valuable information. It might mean doubling down on that audience rather than trying to force-fit your original target.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-stress-testing-your-pmf-definition&quot;&gt;Stress testing your PMF definition&lt;/h3&gt;



&lt;p&gt;To test whether your definition is strong enough, ask yourself:&amp;nbsp;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Do activated users who engage in that behavior retain significantly better?&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Does the pattern hold across cohorts?&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Does improving the metric improve downstream outcomes?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;In case you haven’t noticed, I love making you ask yourself questions. It’s so easy to rush as a startup, so it is important to force yourself to reflect on your decisions.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-when-to-move-on-from-this-phase&quot;&gt;When to move on from this phase&lt;/h2&gt;



&lt;p&gt;So how do you know when you’ve done enough to get PMF and it’s time to shift focus?&lt;/p&gt;



&lt;p&gt;There’s no perfect moment, but there are signals that suggest you’re ready:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;40% or more of users say they’d be ‘very disappointed’ without your app&lt;/li&gt;



&lt;li&gt;Your retention curve starts to flatten after a few weeks rather than dropping off completely&lt;/li&gt;



&lt;li&gt;Users are coming back on their own without push notifications or reminders&lt;/li&gt;



&lt;li&gt;You’re seeing organic referrals — people telling others without being asked&lt;/li&gt;



&lt;li&gt;Users are willing to pay without heavy discounts or extended trials&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;You don’t need all of these, but if you’re seeing a few of them consistently, especially within a specific segment, that’s a good sign you’ve found something worth building on.&lt;/p&gt;



&lt;p&gt;From here, you move into what’s often called product-model fit, making sure your monetization model matches how users experience value. That’s where pricing, packaging, trials versus paywalls, and funnel decisions come in.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;You also start to focus more on channel metrics, trying to work out which channels will drive scale for you.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;But those decisions around monetization and channels are so much easier when you’ve already validated that you’re solving a real problem for a specific group of people.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;667&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-11-1024x667.png&quot; alt=&quot;&quot; class=&quot;wp-image-53078&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-11-1024x667.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-11-300x195.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-11-768x500.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-11-1536x1000.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-11-50x33.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-11-61x40.png 61w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-11-696x453.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-11-560x364.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-11-455x296.png 455w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-11-725x472.png 725w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-11-80x52.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-11-48x31.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-11.png 2048w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-time-to-define-your-metrics&quot;&gt;Time to define your metrics&lt;/h2&gt;



&lt;p&gt;Pre-product-market fit, your job isn’t to grow. It’s to learn. That means ignoring the metrics that feel good but don’t tell you anything and focusing on the behavioral signals that show whether users are actually getting value:&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Ignore&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Focus on&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Total downloads&lt;/td&gt;&lt;td&gt;Users returning on their own&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Total signups&lt;/td&gt;&lt;td&gt;Core feature usage&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Social media followers&lt;/td&gt;&lt;td&gt;Willingness to pay&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;App store ranking&lt;/td&gt;&lt;td&gt;Users telling others&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Day 1 spikes&lt;/td&gt;&lt;td&gt;Repeat usage in the first week&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Time in app (without context)&lt;/td&gt;&lt;td&gt;Active users (defined by behavior)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;Here’s a quick checklist to keep you on track in this pre-PMF phase:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Shift your mindset from growth to learning&lt;/li&gt;



&lt;li&gt;Identify the vanity metrics you’re going to ignore&lt;/li&gt;



&lt;li&gt;Define what time to first value and time to core value look like for your app&lt;/li&gt;



&lt;li&gt;Set a behavioral North Star hypothesis&lt;/li&gt;



&lt;li&gt;Write your PMF definition in behavioral terms&lt;/li&gt;



&lt;li&gt;Talk to users → PMF surveys, NPS, user interviews&lt;/li&gt;



&lt;li&gt;Focus on leading indicators, not lagging ones&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;It’s hard to resist the pull of growth, especially right after launch when the numbers are moving. But if you nail product-market fit first, everything that comes after — your funnel, your pricing, your ads — will work so much better.&lt;/p&gt;



&lt;p&gt;If you want to go deeper on defining your strategy and finding the right audience before diving into metrics, that’s exactly what I cover in the StartApp School course: &lt;em&gt;&lt;a href=&quot;https://www.startapp.school/courses/how-to-make-an-app-people-will-pay-for&quot;&gt;Early product decisions: How to build an app people will pay for&lt;/a&gt;. &lt;/em&gt;I’m excited to hear what you think!&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Daphne_SocialCard-1024x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-53080&quot; style=&quot;width:400px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Daphne_SocialCard-1024x1024.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Daphne_SocialCard-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Daphne_SocialCard-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Daphne_SocialCard-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Daphne_SocialCard-1536x1536.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Daphne_SocialCard-2048x2048.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Daphne_SocialCard-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Daphne_SocialCard-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Daphne_SocialCard-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Daphne_SocialCard-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Daphne_SocialCard-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Daphne_SocialCard-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Daphne_SocialCard-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Daphne_SocialCard-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Daphne_SocialCard-48x48.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;
</content:encoded></item><item><title><![CDATA[Track in-app ad revenue alongside purchases: get the full picture on monetization]]></title><description><![CDATA[Track and analyze your ad revenue alongside subscriptions and IAP all in one place.]]></description><link>https://www.revenuecat.com/blog/growth/track-in-app-ad-revenue-alongside-purchases-get-the-full-picture-on-monetization/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/track-in-app-ad-revenue-alongside-purchases-get-the-full-picture-on-monetization/</guid><pubDate>Mon, 13 Apr 2026 14:09:18 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/in-app-ads.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;For apps monetizing through a mix of ads and in-app purchases, understanding your total revenue has historically been a fragmented, frustrating process. You’re forced to stitch together dashboards, export CSVs, and build custom pipelines just to answer basic questions: What is my actual revenue across all channels? How valuable is a user who never subscribes but watches ads for six months? What percentage of my revenue comes from ads versus subscriptions?&lt;/p&gt;



&lt;p&gt;The result is a blind spot in your data. You’re left making slow decisions based on incomplete Lifetime Value (LTV) metrics and guesswork.&lt;/p&gt;



&lt;p&gt;That’s why we’re excited to release &lt;strong&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/getting-started/ad-monetization&quot;&gt;In-App Ad Revenue Tracking&lt;/a&gt;&lt;/strong&gt; in RevenueCat in public beta. You can see your complete monetization health, blending ads alongside subscriptions and one-time purchases, all in one place.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;RevenueCat Ad Revenue Tracking&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/Zu5vRrxyA_c?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-one-dashboard-for-your-complete-revenue-picture&quot;&gt;One dashboard for your complete revenue picture&lt;/h2&gt;



&lt;p&gt;RevenueCat now ingests ad revenue events in real time alongside your purchase data. This means no more bouncing between ad network dashboards and RevenueCat to understand your total revenue.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;675&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-5-1024x675.png&quot; alt=&quot;&quot; class=&quot;wp-image-53055&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-5-1024x675.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-5-300x198.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-5-768x506.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-5-50x33.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-5-61x40.png 61w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-5-696x459.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-5-560x369.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-5-449x296.png 449w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-5-716x472.png 716w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-5-80x53.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-5-48x32.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-5.png 1173w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Here is what you can explore as part of the beta:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-unified-revenue-and-realized-ltv&quot;&gt;Unified revenue and realized LTV&lt;/h3&gt;



&lt;p&gt;Ad revenue is now folded directly into your main &lt;em&gt;Revenue Chart&lt;/em&gt;. ‘Total revenue’ finally means &lt;em&gt;total&lt;/em&gt; revenue. Furthermore, your &lt;em&gt;Realized LTV&lt;/em&gt; now incorporates ad revenue, giving you a complete picture of cohort value. You can finally understand the true worth of your users, not just what your subscribers paid.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-dedicated-ads-reporting&quot;&gt;Dedicated ads reporting&lt;/h3&gt;



&lt;p&gt;We’ve added a dedicated Ads section in the Charts tab. Here, you can track the metrics that matter most to your ad monetization strategy:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Ad Revenue:&lt;/strong&gt; The foundational number of total revenue generated from ads.&lt;/li&gt;
&lt;/ul&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;599&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-7-1024x599.png&quot; alt=&quot;&quot; class=&quot;wp-image-53059&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-7-1024x599.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-7-300x175.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-7-768x449.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-7-1536x898.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-7-50x29.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-7-68x40.png 68w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-7-696x407.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-7-560x327.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-7-506x296.png 506w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-7-808x472.png 808w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-7-80x47.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-7-48x28.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-7.png 2048w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;ARPDAU (Ad Users):&lt;/strong&gt; Average Revenue Per Daily Active User, the key blended health metric for hybrid apps&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Ad Monetized Users:&lt;/strong&gt; track the number of times users clicked on ads in your app — clicks indicate user engagement with ads and can help you understand which ad placements and formats are most effective&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Ad Impressions &amp;amp; Fill Rate:&lt;/strong&gt; total ad displays and the percentage of ad requests successfully filled, letting you keep an eye on targeting issues or limited ad inventory&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Ad RPM &amp;amp; CTR:&lt;/strong&gt; revenue per thousand impressions and click-through rate to measure monetization efficiency and engagement quality&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;eCPM: &lt;/strong&gt;compare monetization efficiency across different time periods, countries, or platforms regardless of total impression volume&lt;/li&gt;
&lt;/ul&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;677&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-6-1024x677.png&quot; alt=&quot;&quot; class=&quot;wp-image-53057&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-6-1024x677.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-6-300x198.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-6-768x507.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-6-1536x1015.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-6-50x33.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-6-61x40.png 61w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-6-696x460.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-6-560x370.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-6-448x296.png 448w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-6-714x472.png 714w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-6-80x53.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-6-48x32.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-6.png 2048w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-per-user-ad-visibility&quot;&gt;Per-user ad visibility&lt;/h3&gt;



&lt;p&gt;The Customer Details page now includes a dedicated Ads tab. You can dive into individual user profiles to see their Total Ad Revenue, Impressions, Clicks, Fill Rate, CTR, eCPM, and impression timestamps.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-it-works-one-sdk-one-integration&quot;&gt;How it works: one SDK, one integration&lt;/h2&gt;



&lt;p&gt;It’s incredibly simple to set up with the RevenueCat SDK. If you’re using Google AdMob, you simply replace your standard AdMob loading calls with the loadAndTrack methods from the RevenueCat SDK and that’s it. All ad events are tracked automatically.&lt;/p&gt;



&lt;p&gt;If you’re using any other mediation platform that provides impression-level revenue data — such as AppLovin MAX, ironSource, Unity Ads, and many more — you simply call RevenueCat’s AdTracker methods in your ad SDK callbacks at the right time.&lt;/p&gt;



&lt;p&gt;Whether you use AdMob or another platform, it’s still the same reliable RevenueCat SDK under the hood. For full integration details and code examples, &lt;a href=&quot;https://www.revenuecat.com/docs/getting-started/ad-monetization&quot;&gt;check out our ad monetization docs.&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-s-next-for-ad-revenue-tracking&quot;&gt;What’s next for Ad Revenue Tracking&lt;/h2&gt;



&lt;p&gt;This beta is focused on getting the foundational data right and giving you a unified view of their revenue. While we do not measure campaign attribution (we are not an MMP) and we aren’t replacing your mediation platform, we are adding the crucial subscription context to your ad data.&lt;/p&gt;



&lt;p&gt;&lt;em&gt;Note: Because RevenueCat uses real-time SDK data and mediation platforms like AdMob use post-processed, fraud-filtered data, you may see slight discrepancies in the exact numbers. This is expected and fully documented.&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;Looking ahead, we’re working on bringing even more powerful insights to this feature. Fast-follows will include blended ARPDAU across all users, and future updates will introduce predicted LTV with ads and analytics showing how ad exposure impacts subscription conversion and churn.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-unify-your-data-and-start-making-better-decisions-based-on-the-full-picture-get-started-today&quot;&gt;Unify your data and start making better decisions based on the full picture — get started today&lt;/h2&gt;



&lt;p&gt;If your app monetizes with ads through platforms like Google AdMob or AppLovin, you can start sending ad events to RevenueCat today.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/getting-started/ad-monetization&quot;&gt;Check out the docs for more &amp;gt; &lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Any customer can request access to the feature by navigating to the Ads page in their RevenueCat dashboard.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Russia’s App Store payment block: how it impacts your MRR and what to do next]]></title><description><![CDATA[Why your Russian subscriptions are about to churn]]></description><link>https://www.revenuecat.com/blog/growth/russia-app-store-payment-block/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/russia-app-store-payment-block/</guid><pubDate>Thu, 09 Apr 2026 17:07:21 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Russia-app-store-block.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Following a recent &lt;a href=&quot;https://www.themoscowtimes.com/2026/04/01/russians-lose-access-to-apple-id-mobile-payments-a92396&quot;&gt;Russian government directive&lt;/a&gt;, as of April 1, &lt;a href=&quot;https://support.apple.com/en-us/126891&quot;&gt;Apple has officially stopped processing payments for all App Store purchases and Apple Media Services in Russia&lt;/a&gt;. This means Russian users can no longer make new purchases or renew existing subscriptions using traditional payment methods.&lt;/p&gt;



&lt;p&gt;While card payments have been blocked for some time, a popular loophole allowed users to top up their Apple ID balance via mobile phone operators. This new change firmly ties that loophole closed. &lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-status-quo&quot;&gt;The status quo&lt;/h2&gt;



&lt;p&gt;For subscription app developers, this is a hard stop on a major revenue channel in the region. Unless a user already has existing funds in their Apple Account balance, their subscription will not renew.&lt;/p&gt;



&lt;p&gt;The good news for users is that they won’t immediately lose everything. Apps and content previously purchased will remain available, and Apple has confirmed that iCloud+ data will remain accessible even after a subscription lapses. However, premium features tied to active subscriptions will inevitably be cut off once the current billing cycle ends and the renewal fails.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-we-know-about-the-block&quot;&gt;What we know about the block&lt;/h2&gt;



&lt;p&gt;According to reports, the Russian government ordered mobile operators to disable the Apple ID top-up option. This move is &lt;a href=&quot;https://www.reuters.com/technology/russia-goes-after-vpns-great-crackdown-gathers-pace-2026-03-31/&quot;&gt;widely seen as part of a broader crackdown&lt;/a&gt; on online information, specifically targeting the use of paid VPN apps that allow citizens to bypass internet censorship.&lt;/p&gt;



&lt;p&gt;By cutting off the ability to pay for these services, the government effectively restricts access to them. As a result, this blanket ban catches &lt;em&gt;all&lt;/em&gt; subscription apps in its net, regardless of their developer HQ, app category or purpose.&lt;/p&gt;



&lt;p&gt;Some users have already found workarounds by using gift cards to top up their Apple balance, while others are changing the country of their Apple account, or even making a second account in another country with a different bank account. The consequences (from the Russian government or Apple) of pursuing either of these methods remains unclear.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-developers-can-do-now&quot;&gt;What developers can do now&lt;/h2&gt;



&lt;p&gt;For most developers, the impact on global MRR will be minimal. However, if you have a significant user base in Russia, you stand to lose a chunk of revenue. Here are a few practical steps you can take right now:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Assess the impact:&lt;/strong&gt; check your RevenueCat dashboard to see exactly how much of your active MRR comes from Russia. This will help you forecast the upcoming drop in revenue as renewals begin to fail.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Communicate with users:&lt;/strong&gt; send an in-app message or email to your Russian subscribers. Inform them of the change and remind them that they can still use existing Apple Account balances or redeem any App Store codes they already have.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Offer alternative payment routes:&lt;/strong&gt; if your app is multi-platform (e.g. accessible via the web), you can direct users to complete their purchases outside the App Store ecosystem. Just keep in mind that international sanctions and financial regulations around Russia are complex and constantly shifting – make sure you understand the rules that apply to your business before accepting payments from the region.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;While the situation is largely out of developers’ hands, proactive communication, a clear understanding of the data, and alternative methods (like web-to-app) can help cushion the blow. &lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-ZI7Tq2 wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Process payments freely via the web&quot; text=&quot;&lt;p&gt;Reach users outside of the App Store with RevenueCat Funnels: build no-code custom onboarding, surveys, and checkout flows that unlock seamless in-app access. &lt;a class=&amp;quot;notion-link-token notion-focusable-token notion-enable-hover&amp;quot; tabindex=&amp;quot;0&amp;quot; href=&amp;quot;https://www.revenuecat.com/feature/funnels/&amp;quot; rel=&amp;quot;noopener noreferrer&amp;quot; data-token-index=&amp;quot;1&amp;quot;&gt;&lt;span class=&amp;quot;link-annotation-unknown-block-id--717331513&amp;quot;&gt;Learn more &amp;amp;gt; &lt;/span&gt;&lt;/a&gt;&lt;!-- notionvc: ad91ee33-48cc-4201-aeab-fa1baa8f0206 --&gt;&lt;/p&gt;&quot; icon=&quot;bulb&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[Inside Noom’s web-to-app onboarding funnel: how 113 screens build commitment before the paywall]]></title><description><![CDATA[A step-by-step UX teardown of one of the longest onboarding flows in health and wellness apps]]></description><link>https://www.revenuecat.com/blog/growth/web-to-app-onboarding-funnel/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/web-to-app-onboarding-funnel/</guid><pubDate>Thu, 09 Apr 2026 14:00:03 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Blog-37_Inside-Nooms-web-to-app-funnel_-how-personalization-drives-commitment.png" length="0" type="image/*"/><content:encoded>&lt;div class=&quot;lazyblock-e525b3a3ae6c-Z1Bepg0 wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Build no-code web funnels in RevenueCat&quot; text=&quot;&lt;p&gt;Unlock the flexibility and profit of web-to-app with our new funnel builder: create custom onboarding, surveys, and checkout flows in an instant. Free and included in your regular plan. &lt;a href=&amp;quot;https://www.revenuecat.com/feature/funnels&amp;quot;&gt;Learn more&lt;/a&gt;.&lt;/p&gt;&quot; icon=&quot;star&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;p&gt;Noom’s web-to-app funnel is extensive, like &lt;em&gt;really&lt;/em&gt; extensive. The weight loss subscription app has one of the longest app onboarding funnels I’ve ever analyzed. Walking through it carefully and taking notes took around an hour and a half, and even a faster ‘quick’ run-through as a typical user still clocked in at 10-15 minutes, with up to 113 screens along the way.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Yet somehow, it never feels exhausting.&lt;/p&gt;



&lt;p&gt;Instead, the experience feels personal, thoughtful, and surprisingly educational.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-is-noom-s-onboarding-flow-so-long&quot;&gt;Why is Noom’s onboarding flow so long?&lt;/h2&gt;



&lt;p&gt;What makes Noom’s approach worth studying isn’t just the length of the funnel, but how intentionally that length is used. Every question clearly builds toward a payoff, sensitive moments are met with reassurance, and by the end, you genuinely feel as though the plan was designed specifically for you. Noom strikes a rare balance between asking for input and delivering value, and that’s what makes the funnel work.&lt;/p&gt;



&lt;p&gt;Before we dive in, one important note: I’m human. I know, &lt;em&gt;shocking&lt;/em&gt;. While I’ve worked to walk through as many variations of Noom’s flow as possible, there are inevitably moments I may have missed or paths I couldn’t fully test.&lt;/p&gt;



&lt;p&gt;At one point, users are asked ten questions with four possible answers each, that’s 262,144 potential combinations. But fear not: this human did the homework to surface the most meaningful patterns and takeaways, testing roughly 20 different paths to ensure the core learnings are well represented.&lt;/p&gt;



&lt;p&gt;So let’s walk through what makes this quiz-based onboarding funnel work and see what you can apply to your own web-to-app funnel. You can &lt;a href=&quot;https://www.figma.com/board/eVPk59TBh7djQ89O3h7aJJ/Noom-Web-to-App-Breakdown?node-id=0-1&amp;amp;t=7rM57d2mXegZFbVt-1&quot;&gt;check out the full flow here&lt;/a&gt;.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-1-goal-selection-that-reduces-pressure&quot;&gt;1. Goal selection that reduces pressure&lt;/h2&gt;



&lt;p&gt;Noom opens with a question that’s refreshingly direct: What’s your weight loss goal? That clarity matters. If you’re a weight-loss app, hiding it creates uncertainty later.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;597&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Noom1-597x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-52926&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Noom1-597x1024.png 597w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Noom1-175x300.png 175w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Noom1-29x50.png 29w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Noom1-23x40.png 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Noom1-271x464.png 271w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Noom1-327x560.png 327w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Noom1-173x296.png 173w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Noom1-275x472.png 275w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Noom1-47x80.png 47w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Noom1-28x48.png 28w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Noom1.png 608w&quot; sizes=&quot;auto, (max-width: 597px) 100vw, 597px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;But the clever part lies in the options themselves. It’s not just “lose weight.” Users can also choose “maintain weight and get fit” or “I haven’t decided.” That final option may seem small, but it does important work: it removes the pressure to have a perfect answer on the very first screen and prevents users from feeling like they’ve already ‘failed’ before they’ve even started, especially critical when the first step is often where drop-off is highest.&lt;/p&gt;



&lt;p&gt;Noom also allows users to switch units (stones or kilos). It sounds minor, but it matters. Confusion at this stage leads to inaccurate inputs, and inaccurate inputs erode trust. I may live in the UK, but I still couldn’t confidently tell you how much a stone is, and Noom smartly removes that friction before it becomes a problem.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-2-handling-sensitive-questions-with-care&quot;&gt;2. Handling sensitive questions with care&lt;/h2&gt;



&lt;p&gt;Where Noom really stands out is in how they handle personal, potentially uncomfortable questions. The flow next asks about:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Sex assigned at birth&lt;/li&gt;



&lt;li&gt;Gender identity&lt;/li&gt;



&lt;li&gt;Pregnancy status&lt;/li&gt;



&lt;li&gt;Current weight&lt;/li&gt;



&lt;li&gt;Medical conditions&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;These aren’t casual questions. In a category like weight loss, where vulnerability and self-judgment often show up early, the way questions are framed is critical. Noom addresses this by consistently doing four things:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-a-they-explain-why-before-you-can-overthink-it&quot;&gt;A. They explain &lt;em&gt;why&lt;/em&gt; before you can overthink it&lt;/h3&gt;



&lt;p&gt;Noom asks sex assigned at birth. This can easily feel intrusive or irrelevant:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;935&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom2-935x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-52928&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom2-935x1024.png 935w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom2-274x300.png 274w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom2-768x841.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom2-46x50.png 46w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom2-37x40.png 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom2-424x464.png 424w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom2-696x762.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom2-511x560.png 511w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom2-270x296.png 270w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom2-431x472.png 431w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom2-73x80.png 73w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom2-44x48.png 44w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom2.png 1218w&quot; sizes=&quot;auto, (max-width: 935px) 100vw, 935px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;strong&gt;Noom does something many apps skip: it explains why, and it does it on the same screen. &lt;/strong&gt;The framing is straightforward: hormones can affect how our bodies metabolize food. Whether or not every user fully agrees with the science, the key point is that it doesn’t feel like a random data grab.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;They also introduce a progress indicator early on, which matters because at this stage, users are silently asking one question: How long is this going to take?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;This isn’t just UX politeness, it’s trust-building. When users understand why information is being collected and how it will be used, they’re far more willing to share personal details.&lt;/p&gt;



&lt;p&gt;Next, Noom asks about gender identity, separate from sex assigned at birth.&lt;strong&gt; This is one of those subtle moments where product design quietly signals: we’ve thought about real people.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Asking this way reduces the risk of mispersonalization and makes users more comfortable sharing personal information, because the app demonstrates care in how questions are framed.&lt;/p&gt;



&lt;p&gt;Since I selected “woman,” Noom followed with a pregnancy question. They don’t let you simply continue if you indicate you are pregnant; instead, they clearly explain the app isn’t designed for that situation and require you to sign a waiver to proceed. This thoughtful approach balances user safety with transparency.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-b-they-reduce-the-mental-load-to-keep-you-moving&quot;&gt;B. They reduce the mental load to keep you moving&lt;/h3&gt;



&lt;p&gt;I loved the age banding here:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;577&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom3-1024x577.png&quot; alt=&quot;&quot; class=&quot;wp-image-52930&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom3-1024x577.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom3-300x169.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom3-768x433.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom3-1536x866.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom3-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom3-71x40.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom3-696x392.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom3-560x316.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom3-525x296.png 525w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom3-837x472.png 837w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom3-80x45.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom3-48x27.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom3.png 1848w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Instead of forcing users to enter exact ages or navigate fiddly brackets (20–24, 25–29, etc.), Noom uses broad ranges like twenties, thirties, and forties. I mean, 21 vs. 29 years old… very different, but at least they are making it easy for us.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;In a long onboarding flow, this kind of simplification matters. &lt;/strong&gt;It maintains momentum without sacrificing the usefulness of the data, and it reduces the pressure or overthinking that can come with sharing personal information.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-c-they-reassure-you-right-after-the-hardest-moment&quot;&gt;C. They reassure you right after the hardest moment&lt;/h3&gt;



&lt;p&gt;Next comes height and current weight. Noom knows this can be sensitive, so they soften the request with: “We don’t mean to pry, we just need this to build a plan that’s right for you.”&lt;/p&gt;



&lt;p&gt;When you submit your weight, the app responds immediately with: “Thank you for sharing. That’s an important and hard first step.” This isn’t just polite copy, it’s a micro-moment of emotional safety, arriving right when a user might feel judged.&lt;/p&gt;



&lt;p&gt;One interesting choice: there’s no ‘I don’t know’ option for weight. That could create friction for users who avoid weighing themselves, but my guess is that weight serves as the anchor for the results graph later. In this case, Noom prioritizes data completeness over comfort. But perhaps that same clarification it offered earlier would be helpful here, so users understand the need.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-d-personalization-that-feels-real-even-when-it-isn-t&quot;&gt;D. Personalization that feels real (even when it isn’t)&lt;/h3&gt;



&lt;p&gt;Noom asks about health conditions next, with a multi-select list and a simple UI pattern that makes it clear you can choose more than one.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;828&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom4-828x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-52932&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom4-828x1024.png 828w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom4-243x300.png 243w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom4-768x949.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom4-40x50.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom4-32x40.png 32w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom4-375x464.png 375w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom4-696x860.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom4-453x560.png 453w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom4-239x296.png 239w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom4-382x472.png 382w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom4-65x80.png 65w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom4-39x48.png 39w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom4.png 1016w&quot; sizes=&quot;auto, (max-width: 828px) 100vw, 828px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;What stood out is what happens after you select something: you get a supportive message (“We’re so glad you shared…”), and it works even though it’s probably not truly personalized to your exact condition (the message remains the same no matter what you fill in).&lt;/p&gt;



&lt;p&gt;That’s a smart tradeoff. With dozens of possible condition combinations, you don’t need custom copy for every branch. A single, well-written reassurance screen can still feel personal because it addresses &lt;a href=&quot;https://www.revenuecat.com/blog/growth/solve-app-problems-emotionally/&quot;&gt;the emotional reality&lt;/a&gt; of what just happened: the user admitted something vulnerable.&lt;/p&gt;



&lt;p&gt;Noom also continues to explain &lt;em&gt;why&lt;/em&gt; questions are being asked as they get more serious (e.g., diabetes, eating disorders). Not every condition needs the same level of explanation, but the consistency builds trust.&lt;/p&gt;



&lt;p&gt;Additionally, Noom adapts follow-up questions based on your answers. For example, if you indicate you have diabetes, the app asks up to two additional questions tailored to the type.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;790&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-1-1024x790.png&quot; alt=&quot;&quot; class=&quot;wp-image-53025&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-1-1024x790.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-1-300x232.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-1-768x593.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-1-50x39.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-1-52x40.png 52w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-1-601x464.png 601w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-1-696x537.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-1-560x432.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-1-384x296.png 384w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-1-612x472.png 612w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-1-80x62.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-1-48x37.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-1.png 1288w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;These moments of conditional logic make the experience feel tailored without requiring every question to branch infinitely.&lt;/p&gt;



&lt;p&gt;The eating disorder question that follows is a tricky one:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;742&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-2-1-1024x742.png&quot; alt=&quot;&quot; class=&quot;wp-image-53027&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-2-1-1024x742.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-2-1-300x217.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-2-1-768x557.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-2-1-1536x1113.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-2-1-50x36.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-2-1-55x40.png 55w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-2-1-640x464.png 640w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-2-1-696x504.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-2-1-560x406.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-2-1-408x296.png 408w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-2-1-651x472.png 651w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-2-1-80x58.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-2-1-48x35.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-2-1.png 1610w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;As someone with close friends who have struggled with eating disorders, the waiver alone doesn’t feel sufficient. I understand that if the flow stopped entirely, some users might be tempted to skip ahead, but even with the additional confirmation step, it still feels a bit too easy.&lt;/p&gt;



&lt;p&gt;Notably, if you answer ‘no,’ the app doesn’t ask about any previous eating disorders, so that’s something to be aware of. This feels more like a moral consideration than a UX flaw, but I do appreciate that Noom at least doesn’t continue as if nothing happened when someone answers ‘yes.’ It shows some level of responsibility in handling sensitive health information.&lt;/p&gt;



&lt;p&gt;Their slight redemption in my eyes? Two steps later, if I enter a weight that isn’t medically healthy, they won’t let me continue until I enter a weight that isn’t classified as underweight.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-3-turn-a-long-form-into-a-series-of-small-wins&quot;&gt;3. Turn a long form into a series of small wins&lt;/h2&gt;



&lt;p&gt;After filling in a lot of personal questions, Noom takes a moment to pause and shows the following screen:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;458&quot; height=&quot;1023&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom7.png&quot; alt=&quot;&quot; class=&quot;wp-image-52938&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom7.png 458w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom7-134x300.png 134w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom7-22x50.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom7-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom7-208x464.png 208w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom7-251x560.png 251w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom7-133x296.png 133w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom7-211x472.png 211w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom7-36x80.png 36w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom7-21x48.png 21w&quot; sizes=&quot;auto, (max-width: 458px) 100vw, 458px&quot;&gt;&lt;/figure&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;The image of people on a hand is playful and approachable, especially paired with the phrase ‘you are in trusted hands.’&lt;/li&gt;



&lt;li&gt;The visual of climbing the line subtly signals that weight loss isn’t a straight downward journey, showing that Noom will support users through the hardest parts, like when weight temporarily increases.&lt;/li&gt;



&lt;li&gt;The statistic, “we’ve helped 3,627,436 people lose weight,” is both &lt;strong&gt;specific and significant&lt;/strong&gt;, giving the claim credibility.&lt;/li&gt;



&lt;li&gt;The stat is backed with a data source and &lt;strong&gt;a defined minimum result&lt;/strong&gt; (at least 2%), which further strengthens trust.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;One minor issue: the stat is dated October 2021. Specificity builds credibility, but &lt;strong&gt;an older timestamp can create tension, slightly undermining the message.&lt;/strong&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-4-set-expectations-early-then-repeat-them-on-purpose&quot;&gt;4. Set expectations early, then repeat them on purpose&lt;/h2&gt;



&lt;p&gt;Throughout the flow, Noom constantly manages your expectations for what the app can and can’t do. There are three clever ways they do this:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-a-the-goal-weight-becomes-the-backbone-of-everything&quot;&gt;A. The goal weight becomes the backbone of everything&lt;/h3&gt;



&lt;p&gt;Now Noom asks for your ideal weight and explains how it will use that number to predict a timeline and build a custom plan:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;921&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom8-921x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-52940&quot; style=&quot;width:400px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom8-921x1024.png 921w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom8-270x300.png 270w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom8-768x854.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom8-45x50.png 45w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom8-36x40.png 36w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom8-417x464.png 417w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom8-696x774.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom8-504x560.png 504w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom8-266x296.png 266w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom8-425x472.png 425w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom8-72x80.png 72w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom8-43x48.png 43w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom8.png 984w&quot; sizes=&quot;auto, (max-width: 921px) 100vw, 921px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;When you enter something unrealistic or unhealthy, the flow blocks you:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img decoding=&quot;async&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-21-285x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-52902&quot; style=&quot;width:200px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;That’s a rare and important signal. Noom is willing to sacrifice a conversion rather than encourage harmful behavior, as noted earlier. It stands out as one of the clearest examples in the entire experience of the principle: we won’t optimize conversion at any cost.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-b-the-0-5-1-kg-message-is-repeated-strategically&quot;&gt;B. The 0.5-1 kg message is repeated strategically&lt;/h3&gt;



&lt;p&gt;This is where Noom starts repeating a key expectation: &lt;strong&gt;subscribers typically lose 0.5-1 kg per week. &lt;/strong&gt;They say it:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;On the goal screen&lt;/li&gt;



&lt;li&gt;Next to testimonials&amp;nbsp;&lt;/li&gt;



&lt;li&gt;With your projected timeline&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Normally, repetition can be a UX sin. Here, it’s strategic and serves as clear expectation management. If users expected to lose three kilos a week, they’d assume the product was broken.&lt;strong&gt; Noom anchors users to a healthier, realistic pace before they ever pay a dime.&lt;/strong&gt;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-c-the-graph-reframes-the-competition&quot;&gt;C. The graph reframes the competition&lt;/h3&gt;



&lt;p&gt;Noom then shows the projected journey: a steady trend line versus the yo-yo effect of restrictive dieting:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img decoding=&quot;async&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-26.png&quot; alt=&quot;&quot; class=&quot;wp-image-52912&quot; style=&quot;width:400px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;This is a subtle but important move: &lt;strong&gt;Noom’s competitor isn’t just ‘another app.’ It’s crash dieting, inconsistency, and short-term motivation.&lt;/strong&gt; The graph makes that comparison visual, which is far more persuasive than simply stating it in copy.&lt;/p&gt;



&lt;p&gt;Next, Noom asks what you want to focus on: nutrition, movement, habits, or ‘other.’ I noticed a few of these practical questions appear throughout the flow. At first, they felt a bit random, but it soon became clear that this is likely strategic: spacing out the practical, must-ask questions keeps users engaged and prevents them from getting ‘bored’ with the flow.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-5-make-the-payoff-visible-before-you-ask-for-the-email&quot;&gt;5. Make the payoff visible before you ask for the email&lt;/h2&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-a-the-event-question-creates-a-deadline&quot;&gt;A. The event question creates a deadline&lt;/h3&gt;



&lt;p&gt;Next, &lt;strong&gt;Noom tries to identify a motivator&lt;/strong&gt;, often framed as an upcoming event such as a holiday, wedding, or reunion. This makes sense: events create deadlines, and deadlines create urgency.&lt;/p&gt;



&lt;p&gt;It can feel a bit superficial if a user’s true motivator is health, confidence, or energy. Noom softens this by including a ‘no event’ option, but the flow still nudges users to pick something, even asking them to specify a date.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;976&quot; height=&quot;922&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-event-deadline.png&quot; alt=&quot;&quot; class=&quot;wp-image-53467&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-event-deadline.png 976w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-event-deadline-300x283.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-event-deadline-768x726.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-event-deadline-50x47.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-event-deadline-42x40.png 42w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-event-deadline-491x464.png 491w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-event-deadline-696x657.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-event-deadline-560x529.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-event-deadline-313x296.png 313w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-event-deadline-500x472.png 500w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-event-deadline-80x76.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-event-deadline-48x45.png 48w&quot; sizes=&quot;auto, (max-width: 976px) 100vw, 976px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-b-pace-gives-you-control&quot;&gt;B. Pace gives you control&lt;/h3&gt;



&lt;p&gt;Then you choose your pace: fast, slow, and steady, or in between.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;782&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom12-782x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-52922&quot; style=&quot;width:400px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom12-782x1024.png 782w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom12-229x300.png 229w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom12-768x1006.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom12-38x50.png 38w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom12-31x40.png 31w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom12-354x464.png 354w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom12-696x912.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom12-427x560.png 427w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom12-226x296.png 226w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom12-360x472.png 360w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom12-61x80.png 61w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom12-37x48.png 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom12.png 974w&quot; sizes=&quot;auto, (max-width: 782px) 100vw, 782px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;This is a simple control mechanism that addresses a common objection: ‘This won’t fit my life.’ Even if it doesn’t drastically change the plan, it gives users a sense of agency.&lt;/p&gt;



&lt;p&gt;Noom follows with a testimonial and repeats the weight-loss pace statistic. Here, repetition is intentional as they want that expectation firmly embedded before users even see their results.&lt;/p&gt;



&lt;p&gt;Interestingly, how fast I indicated I wanted to lose weight didn’t seem to affect the projected end date, even though I might have expected it to.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-c-the-loader-does-conversion-work&quot;&gt;C. The loader does conversion work&lt;/h3&gt;



&lt;p&gt;Noom shows a short ‘calculating your plan’ screen before asking for your email.&lt;/p&gt;



&lt;p&gt;That pause does two things.&lt;strong&gt; It makes the result feel earned, and it gives them a natural moment to introduce the idea that something valuable is about to be revealed.&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;507&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-loader-conversion-work-507x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-53465&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-loader-conversion-work-507x1024.png 507w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-loader-conversion-work-148x300.png 148w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-loader-conversion-work-25x50.png 25w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-loader-conversion-work-20x40.png 20w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-loader-conversion-work-230x464.png 230w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-loader-conversion-work-277x560.png 277w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-loader-conversion-work-146x296.png 146w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-loader-conversion-work-233x472.png 233w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-loader-conversion-work-40x80.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-loader-conversion-work-24x48.png 24w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-loader-conversion-work.png 650w&quot; sizes=&quot;auto, (max-width: 507px) 100vw, 507px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-d-the-email-gate-appears-at-exactly-the-right-time&quot;&gt;D. The email gate appears at exactly the right time&lt;/h3&gt;



&lt;p&gt;About a third of the way through, Noom asks for my email, right before showing the results graph. &lt;strong&gt;The timing is smart: I’ve already invested enough in the flow that I want to continue, but I’m not so deep that I feel frustrated they’re only asking now.&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img decoding=&quot;async&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-24.png&quot; alt=&quot;&quot; class=&quot;wp-image-52908&quot; style=&quot;width:400px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;strong&gt;The CTA isn’t a generic “Submit,” it’s “See my results.”&lt;/strong&gt; They immediately clarify what I’ll get: a personalized weight-loss timeline and an estimate of how much I can lose before my holiday, a goal I indicated earlier.&lt;/p&gt;



&lt;p&gt;They also separate the marketing opt-in into its own step, framed as “occasional research, advice, and special offers,” signaling both low volume and higher value.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-6-deliver-the-this-was-built-for-me-moment&quot;&gt;6. Deliver the ‘this was built for me’ moment&lt;/h2&gt;



&lt;p&gt;Then Noom delivers the payoff: a results screen with your goal date, your event marker, and a realistic projection.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img decoding=&quot;async&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-11.png&quot; alt=&quot;&quot; class=&quot;wp-image-52882&quot; style=&quot;width:300px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Tone matters here. Noom doesn’t overpromise; for example, if your event is in two months, they don’t suggest you’ll magically hit your ultimate goal by then. &lt;strong&gt;That realism builds more trust than aggressive promises ever could.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;This is also where you see why some of the earlier questions were non-negotiable. Without a starting weight, a goal weight, and a deadline, this personalized results screen couldn’t exist.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-7-use-an-onboarding-quiz-to-increase-buy-in-not-just-collect-data&quot;&gt;7. Use an onboarding quiz to increase buy-in, not just collect data&lt;/h2&gt;



&lt;p&gt;After the initial health questions, Noom shifts into what they call a ‘behavioral profile quiz.’&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;590&quot; height=&quot;763&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz.png&quot; alt=&quot;&quot; class=&quot;wp-image-53469&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz.png 590w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-232x300.png 232w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-39x50.png 39w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-31x40.png 31w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-359x464.png 359w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-433x560.png 433w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-229x296.png 229w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-365x472.png 365w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-62x80.png 62w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-37x48.png 37w&quot; sizes=&quot;auto, (max-width: 590px) 100vw, 590px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;It uses sliders between two statements, repeated across 10 questions. The structure is deliberately consistent:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;You always know what to do&lt;/li&gt;



&lt;li&gt;You always see progress (“Question X of 10”)&lt;/li&gt;
&lt;/ul&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;865&quot; height=&quot;756&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-2.png&quot; alt=&quot;&quot; class=&quot;wp-image-53471&quot; style=&quot;width:500px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-2.png 865w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-2-300x262.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-2-768x671.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-2-50x44.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-2-46x40.png 46w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-2-531x464.png 531w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-2-696x608.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-2-560x489.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-2-339x296.png 339w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-2-540x472.png 540w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-2-80x70.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-2-48x42.png 48w&quot; sizes=&quot;auto, (max-width: 865px) 100vw, 865px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;There are also subtle visual cues built in. For example, if you choose “Agree a little more,” the background color is slightly lighter than if you select “Agree most.” &lt;strong&gt;These small touches guide the user’s perception without being overt.&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-4 is-layout-flex wp-block-gallery-is-layout-flex&quot;&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;479&quot; data-id=&quot;53473&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-3-1024x479.png&quot; alt=&quot;&quot; class=&quot;wp-image-53473&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-3-1024x479.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-3-300x140.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-3-768x359.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-3-50x23.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-3-85x40.png 85w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-3-696x326.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-3-560x262.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-3-840x393.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-3-80x37.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-3-48x22.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-3.png 1141w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;501&quot; data-id=&quot;53475&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-4-1024x501.png&quot; alt=&quot;&quot; class=&quot;wp-image-53475&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-4-1024x501.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-4-300x147.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-4-768x375.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-4-50x24.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-4-82x40.png 82w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-4-696x340.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-4-560x274.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-4-840x411.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-4-80x39.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-4-48x23.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-onboarding-quiz-4.png 1117w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;
&lt;/figure&gt;



&lt;p&gt;The end result is an analysis of my profile, this time with a shorter loader and no message, followed by the presentation of my personalized profile.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;527&quot; height=&quot;730&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-peak-performer.png&quot; alt=&quot;&quot; class=&quot;wp-image-53477&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-peak-performer.png 527w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-peak-performer-217x300.png 217w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-peak-performer-36x50.png 36w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-peak-performer-29x40.png 29w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-peak-performer-335x464.png 335w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-peak-performer-404x560.png 404w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-peak-performer-214x296.png 214w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-peak-performer-341x472.png 341w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-peak-performer-58x80.png 58w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-peak-performer-35x48.png 35w&quot; sizes=&quot;auto, (max-width: 527px) 100vw, 527px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;I tested extreme answers, including negative self-image, to see if Noom would respond poorly. What impressed me is that it frames the results constructively, acknowledging what you said without reinforcing shame.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;612&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-different-names-612x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-53479&quot; style=&quot;width:400px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-different-names-612x1024.png 612w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-different-names-179x300.png 179w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-different-names-30x50.png 30w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-different-names-24x40.png 24w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-different-names-277x464.png 277w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-different-names-335x560.png 335w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-different-names-177x296.png 177w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-different-names-282x472.png 282w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-different-names-48x80.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-different-names-29x48.png 29w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-different-names.png 620w&quot; sizes=&quot;auto, (max-width: 612px) 100vw, 612px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;They’re not ignoring what I said, but they’re also not reinforcing negative self-talk. This feels like a careful balance.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-8-teach-the-method-inside-onboarding&quot;&gt;8. Teach the ‘method’ inside onboarding&lt;/h2&gt;



&lt;p&gt;Rather than waiting until you have the app to start learning, Noom integrates small learning moments throughout the onboarding flow in various ways.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-a-selective-empathy-screens&quot;&gt;A. Selective empathy screens&lt;/h3&gt;



&lt;p&gt;After the profile, Noom asks practical questions about things like gym memberships, apps, and meal kits, another small, seemingly random question checked off early in the flow.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;509&quot; height=&quot;671&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom22.png&quot; alt=&quot;&quot; class=&quot;wp-image-52964&quot; style=&quot;width:400px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom22.png 509w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom22-228x300.png 228w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom22-38x50.png 38w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom22-30x40.png 30w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom22-352x464.png 352w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom22-425x560.png 425w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom22-225x296.png 225w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom22-358x472.png 358w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom22-61x80.png 61w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom22-36x48.png 36w&quot; sizes=&quot;auto, (max-width: 509px) 100vw, 509px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Next, the flow moves into agreement statements covering habit barriers, social impact, convenience, and decision fatigue. Interestingly, some answers trigger an additional reassurance screen, while others do not.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;487&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom23-487x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-52966&quot; style=&quot;width:400px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom23-487x1024.png 487w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom23-143x300.png 143w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom23-24x50.png 24w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom23-19x40.png 19w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom23-221x464.png 221w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom23-266x560.png 266w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom23-141x296.png 141w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom23-224x472.png 224w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom23-38x80.png 38w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom23-23x48.png 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom23.png 521w&quot; sizes=&quot;auto, (max-width: 487px) 100vw, 487px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;This creates a sense of responsiveness without forcing the flow to branch endlessly. It’s selective empathy, applied where it’s most likely to reduce drop-off.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-b-the-plan-starts-to-feel-more-achievable&quot;&gt;B. The plan starts to feel more achievable&lt;/h3&gt;



&lt;p&gt;They also ask about lesson timing — “When would you like daily lessons?”—which is &lt;strong&gt;a smart operational detail disguised as personalization.&lt;/strong&gt; In reality, it’s about choosing a routine that will stick.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;764&quot; height=&quot;746&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom24.png&quot; alt=&quot;&quot; class=&quot;wp-image-52968&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom24.png 764w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom24-300x293.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom24-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom24-41x40.png 41w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom24-475x464.png 475w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom24-696x680.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom24-560x547.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom24-303x296.png 303w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom24-483x472.png 483w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom24-80x78.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom24-48x48.png 48w&quot; sizes=&quot;auto, (max-width: 764px) 100vw, 764px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The flow returns to the graph, with the dates moving forward, interspersed with a few practical questions along the way.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img decoding=&quot;async&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-30-925x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-52920&quot; style=&quot;width:600px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-c-a-product-demo-without-showing-the-product&quot;&gt;C. A product demo without showing the product&lt;/h3&gt;



&lt;p&gt;This is where Noom’s onboarding effectively becomes a product demo, without ever showing the app interface.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;They introduce the green/yellow/red system through questions about what you’ve eaten, then explain calorie density. The messaging is carefully non-shaming: there are no ‘bad foods,’ only foods that help you feel fuller for longer.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;659&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom26-1024x659.png&quot; alt=&quot;&quot; class=&quot;wp-image-52972&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom26-1024x659.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom26-300x193.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom26-768x494.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom26-50x32.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom26-62x40.png 62w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom26-696x448.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom26-560x360.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom26-460x296.png 460w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom26-734x472.png 734w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom26-80x51.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom26-48x31.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom26.png 1090w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Even the cravings question — mine was sweet, so I picked honey (though I wished chocolate had been listed) — becomes a teaching moment: “There’s room for it. Just be mindful.”&lt;/p&gt;



&lt;p&gt;This is objection handling at scale, addressing questions like:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;‘Will I be hungry?’&lt;/li&gt;



&lt;li&gt;‘Will I have to give up foods I like?’&lt;/li&gt;



&lt;li&gt;‘Is this going to be restrictive?’&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Noom answers these before you even reach the paywall.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;810&quot; height=&quot;654&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-answers-before-paywall.png&quot; alt=&quot;&quot; class=&quot;wp-image-53481&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-answers-before-paywall.png 810w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-answers-before-paywall-300x242.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-answers-before-paywall-768x620.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-answers-before-paywall-50x40.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-answers-before-paywall-575x464.png 575w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-answers-before-paywall-696x562.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-answers-before-paywall-560x452.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-answers-before-paywall-367x296.png 367w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-answers-before-paywall-585x472.png 585w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-answers-before-paywall-80x65.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-answers-before-paywall-48x39.png 48w&quot; sizes=&quot;auto, (max-width: 810px) 100vw, 810px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The flow then returns to another slow loader, which Noom uses again as a teaching moment to explain how the app works.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;319&quot; height=&quot;778&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-psychology.png&quot; alt=&quot;&quot; class=&quot;wp-image-53483&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-psychology.png 319w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-psychology-123x300.png 123w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-psychology-21x50.png 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-psychology-16x40.png 16w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-psychology-190x464.png 190w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-psychology-230x560.png 230w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-psychology-121x296.png 121w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-psychology-194x472.png 194w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-psychology-33x80.png 33w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-psychology-20x48.png 20w&quot; sizes=&quot;auto, (max-width: 319px) 100vw, 319px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The screen slowly switches as it continues to build your plan:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;739&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom29-739x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-52978&quot; style=&quot;width:400px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom29-739x1024.png 739w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom29-217x300.png 217w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom29-768x1064.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom29-36x50.png 36w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom29-29x40.png 29w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom29-335x464.png 335w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom29-696x964.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom29-404x560.png 404w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom29-214x296.png 214w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom29-341x472.png 341w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom29-58x80.png 58w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom29-35x48.png 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom29.png 797w&quot; sizes=&quot;auto, (max-width: 739px) 100vw, 739px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-d-personalization-only-feels-real-when-it-cashes-the-cheque&quot;&gt;D. Personalization only feels real when it cashes the cheque&lt;/h3&gt;



&lt;p&gt;When Noom asks about dietary restrictions or physical limitations, you naturally expect an immediate follow-up.&lt;/p&gt;



&lt;p&gt;Earlier in the flow, every meaningful answer led to a tailored next step. When that doesn’t happen here, it stands out.&lt;/p&gt;



&lt;p&gt;It’s a reminder that personalization isn’t just about collecting data; it’s about showing users how their answers shape what they see next.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;620&quot; height=&quot;712&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-personalization-graph.png&quot; alt=&quot;&quot; class=&quot;wp-image-53485&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-personalization-graph.png 620w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-personalization-graph-261x300.png 261w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-personalization-graph-44x50.png 44w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-personalization-graph-35x40.png 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-personalization-graph-404x464.png 404w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-personalization-graph-488x560.png 488w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-personalization-graph-258x296.png 258w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-personalization-graph-411x472.png 411w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-personalization-graph-70x80.png 70w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-personalization-graph-42x48.png 42w&quot; sizes=&quot;auto, (max-width: 620px) 100vw, 620px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;This creates a sense of progress and reward: the more I share, the faster I can achieve my goal.&lt;/p&gt;



&lt;p&gt;It doesn’t feel manipulative. Instead, it’s as if Noom is saying, “Based on what you’ve told us, we think you can do this faster than we initially thought.”&lt;/p&gt;



&lt;p&gt;Interestingly, even when I indicate a limitation or provide ‘negative’ answers, the goal always moves forward.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-9-use-a-relevant-bonus-to-turn-intent-into-action&quot;&gt;9. Use a relevant bonus to turn intent into action&lt;/h2&gt;



&lt;p&gt;From there, it asks about what else you want to achieve:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;503&quot; height=&quot;715&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-relevant-bonus.png&quot; alt=&quot;&quot; class=&quot;wp-image-53487&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-relevant-bonus.png 503w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-relevant-bonus-211x300.png 211w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-relevant-bonus-35x50.png 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-relevant-bonus-28x40.png 28w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-relevant-bonus-326x464.png 326w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-relevant-bonus-394x560.png 394w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-relevant-bonus-208x296.png 208w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-relevant-bonus-332x472.png 332w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-relevant-bonus-56x80.png 56w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-relevant-bonus-34x48.png 34w&quot; sizes=&quot;auto, (max-width: 503px) 100vw, 503px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Interestingly, even if you don’t provide answers about reducing stress or emotional wellbeing, you still go through a mini quiz on the topic.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;804&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom32-1024x804.png&quot; alt=&quot;&quot; class=&quot;wp-image-52984&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom32-1024x804.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom32-300x235.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom32-768x603.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom32-50x39.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom32-51x40.png 51w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom32-591x464.png 591w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom32-696x546.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom32-560x440.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom32-377x296.png 377w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom32-601x472.png 601w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom32-80x63.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom32-48x38.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom32.png 1102w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Noom uses this to calculate a stress score and offers to add stress management to your plan, using a low-pressure line: you can remove it later.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;472&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom33-472x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-52986&quot; style=&quot;width:400px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom33-472x1024.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom33-138x300.png 138w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom33-23x50.png 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom33-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom33-214x464.png 214w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom33-258x560.png 258w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom33-137x296.png 137w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom33-218x472.png 218w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom33-37x80.png 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom33-22x48.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom33.png 542w&quot; sizes=&quot;auto, (max-width: 472px) 100vw, 472px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;This immediately raises a question: What does it cost?&lt;/p&gt;



&lt;p&gt;Strategically, that uncertainty works in Noom’s favor, because the pricing reveal comes later — paired with a time-limited incentive. At this point, I don’t know the cost, but I’m willing to continue because the framing feels low-pressure.&lt;/p&gt;



&lt;p&gt;This becomes important during the pricing step, where the stress management course is offered as a ‘free enhancement’ if I sign up within 15 minutes. This approach is smart for two reasons:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;The 15-minute countdown creates urgency.&lt;/li&gt;



&lt;li&gt;A free course feels more believable than a discount — I’m less likely to think ‘this countdown is fake.’&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;The flow then continues with a few questions about motivation and emotions, mainly to reinforce the value of the plan being offered.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;684&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom34-1024x684.png&quot; alt=&quot;&quot; class=&quot;wp-image-52988&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom34-1024x684.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom34-300x200.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom34-768x513.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom34-50x33.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom34-60x40.png 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom34-694x464.png 694w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom34-696x465.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom34-560x374.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom34-443x296.png 443w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom34-706x472.png 706w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom34-80x53.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom34-48x32.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom34.png 1359w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Finally, they check about other goals too:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;513&quot; height=&quot;679&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-relevant-bonus-2.png&quot; alt=&quot;&quot; class=&quot;wp-image-53489&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-relevant-bonus-2.png 513w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-relevant-bonus-2-227x300.png 227w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-relevant-bonus-2-38x50.png 38w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-relevant-bonus-2-30x40.png 30w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-relevant-bonus-2-351x464.png 351w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-relevant-bonus-2-423x560.png 423w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-relevant-bonus-2-224x296.png 224w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-relevant-bonus-2-357x472.png 357w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-relevant-bonus-2-60x80.png 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-relevant-bonus-2-36x48.png 36w&quot; sizes=&quot;auto, (max-width: 513px) 100vw, 513px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Before moving into another mini quiz on nutrition, which ties back to the earlier point about teaching the method during onboarding.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;434&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-nutrition-quiz-434x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-53491&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-nutrition-quiz-434x1024.png 434w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-nutrition-quiz-127x300.png 127w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-nutrition-quiz-21x50.png 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-nutrition-quiz-17x40.png 17w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-nutrition-quiz-197x464.png 197w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-nutrition-quiz-237x560.png 237w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-nutrition-quiz-125x296.png 125w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-nutrition-quiz-200x472.png 200w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-nutrition-quiz-34x80.png 34w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-nutrition-quiz-20x48.png 20w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-nutrition-quiz.png 500w&quot; sizes=&quot;auto, (max-width: 434px) 100vw, 434px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;I love how, even when you get an answer wrong, Noom stays positive and non-judgmental, maintaining a consistent tone of voice throughout the entire flow.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;692&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom37-692x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-52994&quot; style=&quot;width:400px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom37-692x1024.png 692w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom37-203x300.png 203w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom37-34x50.png 34w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom37-27x40.png 27w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom37-314x464.png 314w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom37-696x1030.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom37-378x560.png 378w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom37-200x296.png 200w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom37-319x472.png 319w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom37-54x80.png 54w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom37-32x48.png 32w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom37.png 740w&quot; sizes=&quot;auto, (max-width: 692px) 100vw, 692px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Another final standard question to check off, and the flow is almost complete. My main thoughts: 1) Why so many options? 2) The order feels a bit random.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;255&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-how-did-you-hear-255x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-53493&quot; style=&quot;width:200px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-how-did-you-hear-255x1024.png 255w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-how-did-you-hear-75x300.png 75w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-how-did-you-hear-10x40.png 10w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-how-did-you-hear-74x296.png 74w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-how-did-you-hear-20x80.png 20w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-how-did-you-hear-12x48.png 12w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-how-did-you-hear.png 289w&quot; sizes=&quot;auto, (max-width: 255px) 100vw, 255px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-10-show-how-the-insights-are-used&quot;&gt;10. Show how the insights are used&lt;/h2&gt;



&lt;p&gt;Believe it or not, after about 100 screens, we’re nearly there! The final act brings everything together into the ultimate plan.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-a-when-questions-turn-into-a-plan&quot;&gt;A. When questions turn into a plan&lt;/h3&gt;



&lt;p&gt;You see the loading screen that says Noom is ‘building your plan,’ but it’s more than just a spinner. In the background, the product is combining everything you’ve shared so far, from weight-loss goals to eating and nutrition habits.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;This moment matters because it shifts the psychological contract.&lt;/strong&gt; Up until now, you’ve mainly been answering questions; now it feels like Noom is actively working for you.&lt;/p&gt;



&lt;p&gt;That shift is what makes the next section feel earned, rather than frustrating after a long flow.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;738&quot; height=&quot;741&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-questions-turn-plan.png&quot; alt=&quot;&quot; class=&quot;wp-image-53495&quot; style=&quot;width:400px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-questions-turn-plan.png 738w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-questions-turn-plan-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-questions-turn-plan-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-questions-turn-plan-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-questions-turn-plan-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-questions-turn-plan-462x464.png 462w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-questions-turn-plan-696x699.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-questions-turn-plan-558x560.png 558w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-questions-turn-plan-295x296.png 295w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-questions-turn-plan-470x472.png 470w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-questions-turn-plan-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-questions-turn-plan-48x48.png 48w&quot; sizes=&quot;auto, (max-width: 738px) 100vw, 738px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-b-the-fake-loader-that-actually-does-real-work&quot;&gt;B. The fake loader that actually does real work&lt;/h3&gt;



&lt;p&gt;Noom uses loading screens in two ways throughout the flow:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Short loaders that create a brief pause after effort.&lt;/li&gt;



&lt;li&gt;Longer loaders that mix in additional questions, like this section.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;&lt;strong&gt;Even if the ‘processing’ is partly theatrical, it feels more believable because the interruptions show your inputs actively shaping the plan.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;They further reinforce credibility by referencing “millions of successful users,” using social proof framed as evidence of model quality.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;721&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom40-1024x721.png&quot; alt=&quot;&quot; class=&quot;wp-image-53000&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom40-1024x721.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom40-300x211.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom40-768x541.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom40-50x35.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom40-57x40.png 57w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom40-659x464.png 659w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom40-696x490.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom40-560x394.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom40-420x296.png 420w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom40-670x472.png 670w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom40-80x56.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom40-48x34.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom40.png 1529w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Even after this, the app loads again, but this time it feels conversational, almost like “We’ve heard you. Now we’re doing something with it.”&lt;/p&gt;



&lt;p&gt;It gradually reveals what’s happening and builds excitement for the final result.&lt;/p&gt;



&lt;figure class=&quot;wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-5 is-layout-flex wp-block-gallery-is-layout-flex&quot;&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;868&quot; data-id=&quot;53497&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-fake-loader-1-1024x868.png&quot; alt=&quot;&quot; class=&quot;wp-image-53497&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-fake-loader-1-1024x868.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-fake-loader-1-300x254.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-fake-loader-1-768x651.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-fake-loader-1-50x42.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-fake-loader-1-47x40.png 47w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-fake-loader-1-547x464.png 547w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-fake-loader-1-696x590.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-fake-loader-1-560x475.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-fake-loader-1-349x296.png 349w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-fake-loader-1-557x472.png 557w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-fake-loader-1-80x68.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-fake-loader-1-48x41.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-fake-loader-1.png 1343w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;623&quot; data-id=&quot;53499&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-fake-loader-2-1024x623.png&quot; alt=&quot;&quot; class=&quot;wp-image-53499&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-fake-loader-2-1024x623.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-fake-loader-2-300x182.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-fake-loader-2-768x467.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-fake-loader-2-50x30.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-fake-loader-2-66x40.png 66w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-fake-loader-2-696x423.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-fake-loader-2-560x341.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-fake-loader-2-487x296.png 487w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-fake-loader-2-776x472.png 776w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-fake-loader-2-80x49.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-fake-loader-2-48x29.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-fake-loader-2.png 1291w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;
&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-11-the-pay-what-you-want-trial&quot;&gt;11. The ‘pay what you want’ trial&lt;/h2&gt;



&lt;p&gt;Then comes one of the most unusual pricing moments I’ve ever seen: Noom asks how much you’re willing to pay for a &lt;a href=&quot;https://www.revenuecat.com/blog/growth/7-day-trial-subscription-app/&quot;&gt;14-day trial&lt;/a&gt;, offering three options.&lt;/p&gt;



&lt;p&gt;It’s framed with cost transparency (“it costs us X to offer this trial”) and an altruistic nudge (“help others access Noom”). Functionally, your choice doesn’t change the offer, but psychologically, it reframes pricing as a contribution rather than an extraction.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;425&quot; height=&quot;954&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-pay-what-you-want-trial-1.png&quot; alt=&quot;&quot; class=&quot;wp-image-53501&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-pay-what-you-want-trial-1.png 425w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-pay-what-you-want-trial-1-134x300.png 134w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-pay-what-you-want-trial-1-22x50.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-pay-what-you-want-trial-1-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-pay-what-you-want-trial-1-207x464.png 207w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-pay-what-you-want-trial-1-249x560.png 249w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-pay-what-you-want-trial-1-132x296.png 132w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-pay-what-you-want-trial-1-210x472.png 210w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-pay-what-you-want-trial-1-36x80.png 36w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom-pay-what-you-want-trial-1-21x48.png 21w&quot; sizes=&quot;auto, (max-width: 425px) 100vw, 425px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;That said, I did notice the outdated date (September 2021)… yes, I’m nitpicking. On one hand, it probably costs them more now, so I’m getting a deal. On the other hand, it made me wonder why it hasn’t been updated in over three years.&lt;/p&gt;



&lt;p&gt;Regardless of which trial price you choose, you proceed to the same offer in terms of costs after the trial.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;560&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom45-560x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-53008&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom45-560x1024.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom45-164x300.png 164w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom45-27x50.png 27w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom45-22x40.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom45-254x464.png 254w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom45-306x560.png 306w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom45-162x296.png 162w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom45-258x472.png 258w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom45-44x80.png 44w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom45-26x48.png 26w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom45.png 636w&quot; sizes=&quot;auto, (max-width: 560px) 100vw, 560px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;573&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom46-573x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-53010&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom46-573x1024.png 573w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom46-168x300.png 168w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom46-28x50.png 28w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom46-22x40.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom46-259x464.png 259w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom46-313x560.png 313w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom46-166x296.png 166w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom46-264x472.png 264w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom46-45x80.png 45w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom46-27x48.png 27w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/noom46.png 689w&quot; sizes=&quot;auto, (max-width: 573px) 100vw, 573px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-12-what-the-app-actually-looks-like-unclear&quot;&gt;12. What the app actually looks like? Unclear.&lt;/h2&gt;



&lt;p&gt;&lt;strong&gt;My biggest critique: after all of this, I still don’t know what the app experience actually looks like.&lt;/strong&gt; I understand the plan, the psychology, the framework, and the promise, but I haven’t seen:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;What food logging looks like&lt;/li&gt;



&lt;li&gt;What the daily lesson experience looks like&lt;/li&gt;



&lt;li&gt;What ‘success’ looks like day-to-day inside the product&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;For a flow this long, one or two UI glimpses could likely increase confidence right before purchase, especially for users wondering, ‘Will I actually use this?’&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-makes-noom-s-quiz-funnel-effective-nbsp&quot;&gt;What makes Noom’s quiz funnel effective?&amp;nbsp;&lt;/h2&gt;



&lt;p&gt;Here’s a quick recap on the key takeaways from Noom’s web-to-app onboarding funnel:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Reduce pressure at the first step.&lt;/strong&gt; Let users ease into commitment. An ‘I haven’t decided yet’ option can prevent early drop-off without weakening intent.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Explain why you’re asking personal questions. &lt;/strong&gt;Sensitive questions feel safer when users understand how their answers will be used to help them.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Offer reassurance immediately after vulnerable moments. &lt;/strong&gt;A simple ‘thank you for sharing’ at the right time can dramatically increase trust.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Use progress indicators to make long flows feel lighter.&lt;/strong&gt; Showing how far someone has come reduces perceived effort and keeps momentum high.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Set expectations early and repeat them on purpose&lt;/strong&gt;. Repetition isn’t a UX failure when it anchors users to realistic outcomes.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Visualize the alternative you’re competing against.&lt;/strong&gt; Noom doesn’t just sell itself. It shows why crash dieting fails and reframes the &lt;em&gt;real&lt;/em&gt; competitor.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Make the payoff visible before asking for commitment details. &lt;/strong&gt;Show users what they’ll get before asking for their email. Results first, data second.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Reward effort with visible progress. &lt;/strong&gt;As users invest more, Noom moves dates forward and sharpens projections. That feedback loop motivates completion.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Use quizzes to increase buy-in, not just collect data.&lt;/strong&gt; Consistent structure, clear progress, and non-judgmental framing turn quizzes into commitment devices.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Teach your framework during onboarding.&lt;/strong&gt; Introducing the green/yellow/red system early removes objections before pricing ever appears.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Build commitment before introducing price.&lt;/strong&gt; By the time Noom shows pricing, users have already invested time, effort, and emotional energy — a proven driver of paywall conversion.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Show the product, not just the promise: &lt;/strong&gt;After such a long, thoughtful flow, users still need clarity on what day-to-day app usage actually looks like, a key area where Noom falls short.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Noom’s funnel is a masterclass in onboarding conversion — building commitment through personalization, education, and empathy. It’s long, but it never feels tedious — every step serves a clear purpose. By the end, you genuinely feel like this plan was built just for you, even while knowing some of it is smoke and mirrors. When &lt;a href=&quot;https://www.revenuecat.com/blog/growth/subscription-app-trends-benchmarks-2026/&quot;&gt;55% of trial cancellations happen on Day 0&lt;/a&gt;, Noom’s investment in pre-paywall commitment-building looks less like a quirk and more like a calculated response to that reality.For subscription apps, especially in sensitive categories like health, finance, or mental wellness, Noom’s approach offers valuable lessons in trial-to-paid conversion: how to ask for personal information thoughtfully, build trust, and convert users through education rather than pressure — making it a blueprint for any wellness app funnel.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[The blended ARPU framework: how to measure hybrid monetization]]></title><description><![CDATA[Why ads and subscriptions don't have to be a tug-of-war (you just need a new metric)]]></description><link>https://www.revenuecat.com/blog/growth/measure-hybrid-monetization/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/measure-hybrid-monetization/</guid><pubDate>Thu, 02 Apr 2026 12:31:04 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/Blog_17_Blended-ARPU.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Hybrid monetization may be a hot topic, but it’s not a passing fad. Today, utilizing multiple avenues for revenue is a survival tactic — a lever to counter AI-induced variable costs, increased UA pressure and rising competition from the new 14,000 subscription apps joining the market each month.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Yet according to the &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps/&quot;&gt;State of Subscription Apps 2026&lt;/a&gt;, only 10% of apps run true hybrid models (subscriptions + ads, consumable, or lifetime subscriptions). Why? Because there’s a barrier, not a technical one, but a &lt;em&gt;measurement &lt;/em&gt;challenge. Without a unified metric, teams default to evaluating the performance of hybrid monetization in silos. In this blog, I’ll provide a solution to that exact problem.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-clash-of-ads-vs-subscription-mental-models&quot;&gt;The clash of ads vs. subscription mental models&lt;/h2&gt;



&lt;p&gt;Part of the difficulty in measuring &lt;a href=&quot;https://www.revenuecat.com/blog/growth/hybrid-monetization-techniques/&quot;&gt;hybrid monetization&lt;/a&gt; is the divided mental models between ad-first and subscription-first teams — and the subsequent division that comes with monitoring hybrid performance.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;The mental model for ads-first teams is: &lt;strong&gt;more sessions = more impressions = more revenue.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;So when subscriptions become a strategic priority, the first reaction is usually caution. Typical concerns sound like:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;“If we push paywalls, impressions will drop”&lt;/li&gt;



&lt;li&gt;“If users subscribe, we lose high-value ad traffic”&lt;/li&gt;



&lt;li&gt;“Retention might fall if we add friction”&lt;/li&gt;



&lt;li&gt;“We shouldn’t disturb what’s already working”&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Teams panic when ads ARPU dips, even if total revenue per user is rising. There can be concern that introducing stronger monetization would:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Hurt retention&lt;/li&gt;



&lt;li&gt;Trigger uninstall spikes&lt;/li&gt;



&lt;li&gt;Reduce session depth&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;And because ads performance responds instantly while subscriptions compound, ads movement often shows up first in dashboards.&lt;/p&gt;



&lt;p&gt;On the flip side, if you introduce ads into a subscription-heavy culture, you’ll often hear:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;“Leaning into ads discourages higher-value subscriber growth”&lt;/li&gt;



&lt;li&gt;“Ads revenue hides product problems”&lt;/li&gt;



&lt;li&gt;“Free users aren’t our priority”&lt;/li&gt;



&lt;li&gt;“Free users get too comfortable”&lt;/li&gt;



&lt;li&gt;“The funnel isn’t pushing hard enough”&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Tracking &lt;strong&gt;blended ARPU&lt;/strong&gt; is one way to solve this. It becomes your primary &lt;a href=&quot;https://www.revenuecat.com/blog/growth/okrs-kpis-subscription-apps/&quot;&gt;subscription app KPI&lt;/a&gt;, while ads and subscriptions become supporting metrics. When you monitor total revenue per user instead of individual streams, you stop killing good subscription experiments because of short-term ads volatility.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-do-ads-and-iap-behave-differently&quot;&gt;&lt;strong&gt;Why do ads and IAP behave differently?&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;In &lt;a href=&quot;https://www.revenuecat.com/blog/growth/ai-hybrid-monetization/&quot;&gt;hybrid monetization apps&lt;/a&gt;, advertising and in-app purchases operate on fundamentally different time horizons, yet this distinction is often overlooked in how teams measure and optimize revenue.&lt;/p&gt;



&lt;p&gt;Advertising revenue responds immediately — users see ads, clicks generate income, and the impact shows up in your metrics within hours or days. Subscription revenue, on the other hand, compounds gradually over time as users renew month after month, building predictable recurring revenue that may take quarters to fully materialize.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;When you evaluate these revenue streams separately, as some teams do, they naturally appear to compete with each other. You might see that showing more ads increases ad ARPU but seems to hurt subscription conversion, or that pushing subscriptions harder reduces ad impressions. This apparent tension is reinforced by how some analytics dashboards are structured: Ad ARPU lives in one report, IAP ARPU sits in another, and the two rarely interact.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;This organizational split encourages teams to optimize locally — the ads team pushes for more impressions, the subscription team advocates for aggressive or contextual paywalls — rather than thinking globally about total user &lt;a href=&quot;https://www.revenuecat.com/glossary/#lifetime-value-ltv&quot;&gt;lifetime value&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;In a recent monetization review across a large utility app portfolio, we made a deliberate shift in our approach: ads and IAP would no longer be evaluated as competing channels, but rather as &lt;strong&gt;one unified revenue system&lt;/strong&gt;.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Making this shift required developing a shared metric that could capture the combined contribution of both streams and reflect their true interdependencies. This allowed us to move beyond the misleading choice between ad revenue and subscription revenue, and instead optimize for the mix that maximized total value per user.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-is-blended-arpu&quot;&gt;&lt;strong&gt;What is blended ARPU?&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;When you’re running an app with hybrid monetization, you need a way to see the complete picture of how much revenue each user is generating on average. That’s where ‘blended ARPU’ comes in. ARPU (or average revenue per user) is one of the most fundamental metrics in the app business. The ‘blended’ part means we’re combining all your different revenue sources into one number, rather than looking at them separately.&lt;/p&gt;



&lt;p&gt;The formula itself is straightforward:&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Blended ARPU = ad ARPU × % free users + IAP ARPPU × % paid users.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Let’s break down what this means:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Ad ARPU is the average ad revenue you make per user (usually the free users who see ads)&lt;/li&gt;



&lt;li&gt;You multiply that by the percentage of your user base that’s on the free tier&lt;/li&gt;



&lt;li&gt;Then you take IAP ARPPU (the average revenue per paying user from subscriptions or purchases) and multiply it by the percentage of users who’ve paid for something&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Add those two pieces together, and you get your blended ARPU: the true average revenue you’re making per active user across your entire app, regardless of whether they’re paying subscribers or ad-supported free users. This is the exact structure we use in our internal tracking spreadsheet to monitor monetization health across different apps.&lt;/p&gt;



&lt;p&gt;What makes this metric so powerful is how it reframes the questions you ask. Instead of fragmenting your analysis by asking “Did ad revenue drop this month?” and separately “Did subscriptions increase?”, you can ask one unified question: &lt;strong&gt;“Did total revenue per active user increase?”&lt;/strong&gt;. That shift in perspective changes everything about how you make decisions. It prevents you from accidentally optimizing one revenue stream at the expense of overall profitability, and it helps you see whether changes you’re making, like adjusting ad frequency or changing paywall triggers, are &lt;em&gt;actually&lt;/em&gt; improving your business or just shifting money around between buckets.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;How to implement a blended ARPU tracker&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;You can talk about unified monetization strategy all you want, but until you actually build it into your regular cadence of meetings and reviews, teams will default back to optimizing in silos. That’s why we introduced a biweekly blended ARPU tracker across our focus apps and committed to reviewing it consistently with product managers. The key word is &lt;em&gt;‘consistently’ &lt;/em&gt;— this isn’t a metric you check once a quarter when someone asks about it. It’s the framework for every monetization conversation, reviewed every two weeks.&lt;/p&gt;



&lt;p&gt;Each app snapshot in our tracker includes a carefully-chosen set of metrics that tell the complete story:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;We track monthly IAP revenue and monthly ad revenue separately so we can see the individual components&lt;/li&gt;



&lt;li&gt;We calculate free user ARPU (how much ad revenue we’re generating from non-paying users) and subscriber ARPU (how much paying users contribute)&amp;nbsp;&lt;/li&gt;



&lt;li&gt;We include paid user percentage because the mix between free and paid users dramatically affects your blended number — an app with 5% paid users will look very different from one with 20% subscribers, even if both have similar total revenue&lt;/li&gt;



&lt;li&gt;Then we calculate the blended ARPU itself using the formula we discussed&lt;/li&gt;



&lt;li&gt;We also include D1 retention (the percentage of users who come back the day after installing) because monetization changes always need to be balanced against user experience and engagement&lt;/li&gt;



&lt;li&gt;Finally, we track biweekly deltas (the change from the previous period) so we can immediately see if experiments or product changes are moving the needle in the right direction&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;What’s crucial about this structure is the hierarchy: &lt;strong&gt;blended ARPU is the primary KPI&lt;/strong&gt;. Everything else is &lt;strong&gt;context&lt;/strong&gt;. When we sit down for a review, we don’t start by debating whether ad revenue went up, or whether a new paywall performed well. We start with one question: did blended ARPU improve? Then we use all the other metrics to understand &lt;em&gt;why&lt;/em&gt; it moved and what levers we can pull to improve it further.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;For example, the tracker may look like this:&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;App&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Active users&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;% Paid&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Ads revenue&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;IAP revenue&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Ad ARPU&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Sub ARPPU&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Blended ARPU&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Key insight&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;App 1&lt;/td&gt;&lt;td&gt;8.3M&lt;/td&gt;&lt;td&gt;0.23%&lt;/td&gt;&lt;td&gt;$567k&lt;/td&gt;&lt;td&gt;$20k&lt;/td&gt;&lt;td&gt;$0.07&lt;/td&gt;&lt;td&gt;$2.82&lt;/td&gt;&lt;td&gt;$0.07&lt;/td&gt;&lt;td&gt;Sub share stabilizes blended ARPU despite install decline&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;App 2&lt;/td&gt;&lt;td&gt;5.4M&lt;/td&gt;&lt;td&gt;0.44%&lt;/td&gt;&lt;td&gt;$171k&lt;/td&gt;&lt;td&gt;$72k&lt;/td&gt;&lt;td&gt;$0.05&lt;/td&gt;&lt;td&gt;$3.29&lt;/td&gt;&lt;td&gt;$0.06&lt;/td&gt;&lt;td&gt;Higher sub penetration clearly lifts blended ARPU&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;App 3&lt;/td&gt;&lt;td&gt;2.3M&lt;/td&gt;&lt;td&gt;0.08%&lt;/td&gt;&lt;td&gt;$82.7k&lt;/td&gt;&lt;td&gt;$13.5k&lt;/td&gt;&lt;td&gt;$0.04&lt;/td&gt;&lt;td&gt;$7.71&lt;/td&gt;&lt;td&gt;$0.05&lt;/td&gt;&lt;td&gt;Even low penetration adds measurable lift&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;Even at low paid percentages, subscriber ARPPU is dramatically higher than ad ARPU. That means small increases in paid share can meaningfully shift total revenue per user. That insight alone reshaped prioritization across the portfolio.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-hybrid-monetization-framework-how-to-tell-the-difference-between-revenue-cannibalization-vs-false-alarms&quot;&gt;&lt;strong&gt;Hybrid monetization framework: how to tell the difference between revenue cannibalization vs. false alarms&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Once you’ve committed to blended ARPU as your &lt;a href=&quot;https://www.revenuecat.com/blog/growth/north-star-metrics-subscription-growth/&quot;&gt;north star metric&lt;/a&gt;, you need a clear system for monitoring it — not just tracking the number, but understanding &lt;strong&gt;when to react and when to stay the course&lt;/strong&gt;. We formalized our monitoring system into three distinct layers that create a structured escalation process, preventing both overreaction to normal fluctuations and delayed response to genuine problems.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-primary-kpi-blended-arpu&quot;&gt;Primary KPI: blended ARPU&lt;/h3&gt;



&lt;p&gt;At the top sits the primary KPI: blended ARPU. This is what we care about most, the ultimate measure of whether our monetization is getting stronger or weaker. Beneath that, we track a set of monitoring metrics that help us diagnose what’s happening under the hood. These include:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Ads revenue per free user (are we monetizing our free tier effectively?)&lt;/li&gt;



&lt;li&gt;Impressions per DAU or daily active user (are users seeing the right volume of ads?)&lt;/li&gt;



&lt;li&gt;Retention metrics at key intervals: D1, D3, and D7&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;These monitoring metrics aren’t goals in themselves; they’re diagnostic tools that explain movements in blended ARPU and help us identify which specific lever might be broken or underperforming.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-escalation-triggers&quot;&gt;Escalation triggers&lt;/h3&gt;



&lt;p&gt;The third layer consists of escalation triggers: the conditions that prompt us to actually intervene or reverse a change. We escalate when:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Blended ARPU &lt;strong&gt;falls meaningfully and stays suppressed&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;Ad ARPU drops &lt;strong&gt;without a corresponding lift in subscription revenue&lt;/strong&gt; to compensate for it&lt;/li&gt;



&lt;li&gt;We see a &lt;strong&gt;sustained retention collapse&lt;/strong&gt; that threatens the underlying health of the app&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;em&gt;Sustained &lt;/em&gt;is important here — we expect volatility in app metrics, that’s the nature of the business, so minor dips in ad impressions from one week to the next are completely normal. Small retention fluctuations during funnel optimization experiments are par for the course. What matters is the &lt;em&gt;trend&lt;/em&gt;, not the daily noise.&lt;/p&gt;



&lt;p&gt;This discipline is what prevents us from making costly mistakes. When you run a subscription experiment that reduces ad impressions, e.g. by showing an earlier paywall, ad revenue will naturally dip in the short term. Teams that only monitor ad metrics in isolation will panic and roll back the change prematurely, never giving the subscription revenue time to compound and overtake the lost ad income. By anchoring to blended ARPU and only escalating when it remains meaningfully suppressed, we &lt;strong&gt;give experiments the runway they need to prove themselves&lt;/strong&gt; while still catching genuinely harmful changes before they do lasting damage.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;584&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1024x584.png&quot; alt=&quot;&quot; class=&quot;wp-image-52757&quot; style=&quot;width:700px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1024x584.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-300x171.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-768x438.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1536x876.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-50x29.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-70x40.png 70w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-696x397.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-560x320.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-519x296.png 519w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-827x472.png 827w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-80x46.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-48x27.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-revenue-vs-ads-calculator-how-many-subscribers-do-you-need-to-offset-ad-revenue-loss&quot;&gt;&lt;strong&gt;Revenue vs. ads calculator: how many subscribers do you need to offset ad revenue loss?&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;One of the biggest obstacles to unified monetization thinking is that the tradeoffs feel abstract and therefore scary. When you’re considering a change that might reduce ad impressions — like introducing a paywall earlier in the user journey or limiting interstitial frequency — the ad revenue loss is immediate and visible, while the subscription gain is hypothetical and delayed. This asymmetry paralyzes decision-making.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;To make these tradeoffs tangible and give teams confidence to experiment, we built a simple calculator that answers one critical question: &lt;strong&gt;if ad revenue dips, how many new subscribers do we actually need to offset that loss?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;The math is straightforward:&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Subscriber ARPPU ÷ ad ARPU = the number of free users equivalent to one subscriber.&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;In other words, this tells you how many ad-supported users one paying subscriber is ‘worth’ in pure revenue terms.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Let’s walk through a real example from one of our apps: in this case, subscriber ARPPU is approximately $2.82 per month. Ad ARPU is about $0.07 per month. Divide $2.82 by $0.07, and you get ~40.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;That means one subscriber generates the same monthly revenue as 40 free users watching ads. Put another way, if you convert just one user out of every 40 free users into a subscriber, you’ve maintained exactly the same revenue — &lt;em&gt;while dramatically improving your monetization quality and reducing your dependence on ad networks&lt;/em&gt;.&lt;/p&gt;



&lt;p&gt;Note that this ratio varies significantly across different apps depending on their monetization mix, subscription pricing, and ad density. In our portfolio, we’ve seen numbers ranging from as low as 60 free users per subscriber in apps with lighter ad loads and premium subscription tiers, all the way up to nearly 190 free users per subscriber in apps with aggressive ad monetization but lower-priced subscriptions.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Regardless of where your specific app falls, knowing this number transforms the conversation. When product managers see that converting a relatively small number of users — say, improving your paywall conversion rate by just 2–3% — can offset the loss of thousands of ad impressions, the fear of “losing ad revenue” to push subscriptions becomes manageable. The tradeoff is no longer a vague anxiety;&lt;strong&gt; it’s a quantifiable bet with clear success criteria&lt;/strong&gt;. You know exactly what conversion rate you need to hit to break even, and anything above that is pure upside.&lt;/p&gt;



&lt;p&gt;Let’s look at how this would look in practice:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-core-exchange-rate-example&quot;&gt;1. Core exchange rate example&lt;/h3&gt;



&lt;p&gt;Here, there’s a subscriber vs. ads tradeoff:&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Metric&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Value&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Explanation&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Subscriber ARPPU&lt;/td&gt;&lt;td&gt;$2.82&lt;/td&gt;&lt;td&gt;Avg monthly revenue per subscriber&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Ad ARPU (free users)&lt;/td&gt;&lt;td&gt;$0.07&lt;/td&gt;&lt;td&gt;Avg monthly ad revenue per free user&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Free users per one subscriber&lt;/td&gt;&lt;td&gt;40.3&lt;/td&gt;&lt;td&gt;$2.82 ÷ $0.07&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;In this scenario, one subscriber generates the same revenue as ~40 free users. So if you convert one out of every 40 free users, revenue remains flat. Anything above that is incremental upside.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-breakeven-scenario-example&quot;&gt;2. Breakeven scenario example&lt;/h3&gt;



&lt;p&gt;For this example, imagine ads dip but there’s subscriber lift:&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Scenario variable&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Value&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Monthly active users&lt;/td&gt;&lt;td&gt;5,000,000&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;% Free users&lt;/td&gt;&lt;td&gt;99.7%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Ad ARPU&lt;/td&gt;&lt;td&gt;$0.07&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Subscriber ARPPU&lt;/td&gt;&lt;td&gt;$2.82&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Hypothetical ad ARPU drop&lt;/td&gt;&lt;td&gt;-$0.005&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;After this, the revenue impact would be:&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Calculation step&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Result&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Revenue loss from ad ARPU drop&lt;/td&gt;&lt;td&gt;$24,925&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Required new subscribers to break even&lt;/td&gt;&lt;td&gt;8,841&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Formula used&lt;/td&gt;&lt;td&gt;$24,925 ÷ $2.82&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;For this scenario, if your experiment generates more than 8,841 additional subscribers, it is revenue-positive — even if ads ARPU dips slightly.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-blended-arpu-benefit-revenue-stability&quot;&gt;&lt;strong&gt;Blended ARPU benefit: revenue stability&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;One of the often-overlooked benefits of using blended ARPU as your primary metric is that it’s inherently more stable than looking at ad revenue or subscription revenue in isolation — and that stability is what allows you to make better decisions with more confidence.&lt;/p&gt;



&lt;p&gt;Ads ARPU fluctuates wildly on a daily basis. Ad network fill rates change, eCPMs (effective cost per thousand impressions) vary based on advertiser demand and seasonality, and even small changes in user behavior — like slightly fewer sessions per day — can cause noticeable swings in ad revenue. If you’re monitoring ads ARPU closely, you’ll see it jump up and down constantly, which creates anxiety and makes it difficult to distinguish between meaningful trends and random noise. &lt;/p&gt;



&lt;p&gt;Similarly, IAP ARPU fluctuates with the rhythm of your promotional calendar and trial cycles. When you run a discount campaign or offer a special trial period, you might see a short-term spike in conversions followed by a drop-off once the promotion ends. You’ll also see natural cycles tied to when trials convert to full subscriptions or when annual renewals come through. Each of these creates peaks and valleys that can look alarming if you’re only tracking subscription metrics.&lt;/p&gt;



&lt;p&gt;Blended ARPU smooths those movements because &lt;strong&gt;it’s averaging across two revenue streams that often move in different directions or on different timescales&lt;/strong&gt;:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;When ad revenue dips slightly one week, subscription revenue might be steady or growing&lt;/li&gt;



&lt;li&gt;When a promotion ends and new subscription sign-ups slow down, ad revenue from your stable free user base continues flowing&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The result is a much clearer signal of your total monetization health — one that cuts through daily volatility and helps you see the actual trend. This doesn’t mean blended ARPU never moves or that you should ignore changes in it. Rather, it means that when blended ARPU does move significantly, you can have &lt;strong&gt;much higher confidence that something meaningful is happening&lt;/strong&gt;, not just normal statistical noise. That clarity is what enables disciplined decision-making and prevents teams from overreacting to the everyday ups and downs that are simply part of running a hybrid monetization business.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;877&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-1024x877.png&quot; alt=&quot;&quot; class=&quot;wp-image-52759&quot; style=&quot;width:700px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-1024x877.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-300x257.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-768x658.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-1536x1315.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-50x43.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-47x40.png 47w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-542x464.png 542w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-696x596.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-560x480.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-346x296.png 346w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-551x472.png 551w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-80x69.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1-48x41.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-1.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The chart shows ads and IAP moving independently while blended ARPU remains comparatively stable. &lt;strong&gt;That stability allows teams to make rational long-term decisions.&lt;/strong&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-embracing-blended-arpu&quot;&gt;&lt;strong&gt;Embracing blended ARPU&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Ads and subscriptions do not have to compete with each other, cannibalizing revenue in an endless internal tug-of-war. &lt;strong&gt;They can and should work together as complementary parts of a single, coherent monetization strategy.&lt;/strong&gt; The problem is that without a unified metric to measure their combined contribution, teams will inevitably optimize in silos — the ads team pushing for maximum impressions, the subscription team advocating for aggressive paywalls — each defending their own territory and reacting to short-term noise in their individual metrics rather than long-term trends in overall business health.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Blended ARPU gives you a stable lens through which to view total revenue health.&lt;/strong&gt; It cuts through the confusion of competing dashboards and contradictory signals. It tells you, in one number, whether the changes you’re making are actually improving your business. And perhaps most importantly,&lt;strong&gt; it creates alignment across &lt;/strong&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/build-app-growth-team/&quot;&gt;&lt;strong&gt;subscription app growth teams&lt;/strong&gt;&lt;/a&gt; — everyone is now optimizing for the same thing, which means product decisions can be made faster and with more confidence.&lt;/p&gt;



&lt;p&gt;The beauty of this approach is that it isn’t complicated. You don’t need sophisticated machine learning models or expensive analytics platforms. The formula fits in a single spreadsheet cell. What it requires instead is discipline: to review the metric consistently, to let experiments run their course instead of panicking at the first sign of volatility, and to escalate only when blended ARPU shows sustained weakness (rather than reacting to every minor fluctuation!).&amp;nbsp;In hybrid monetization, &lt;strong&gt;discipline beats fear every time&lt;/strong&gt;. Fear tells you to protect your existing ad revenue at all costs. Discipline tells you to &lt;strong&gt;measure holistically&lt;/strong&gt;, &lt;strong&gt;experiment thoughtfully&lt;/strong&gt;, and &lt;strong&gt;trust the data&lt;/strong&gt;. That shift in mindset is what ultimately unlocks the full potential of a hybrid model, allowing you to serve both free and paying users well while maximizing the lifetime value of everyone who comes through your door.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Google Play’s billion-dollar billing leak: How to recover the subscribers you’re losing to payment failures]]></title><description><![CDATA[A third of your Google Play cancellations aren't real churn – here's how to get them back]]></description><link>https://www.revenuecat.com/blog/growth/google-play-billing-error-churn-how-to-fix/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/google-play-billing-error-churn-how-to-fix/</guid><pubDate>Thu, 02 Apr 2026 10:51:51 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/google-play-billing-error-churn-how-to-fix.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;When a subscription cancels on Google Play, most developers assume the user decided to leave. The billing infrastructure is Google’s problem, right? You build the product, Google handles the payments. If a charge doesn’t go through, that’s between the user and their bank.&lt;/p&gt;



&lt;p&gt;The data tells a very different story.&lt;/p&gt;



&lt;p&gt;In our &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps/&quot;&gt;2026 State of Subscription Apps report&lt;/a&gt; – covering 115,000+ apps and over $16 billion in tracked revenue – &lt;strong&gt;32.3% of all Google Play cancellations are involuntary billing errors&lt;/strong&gt;. Not users churning. Not users who decided your app isn’t worth it. Users whose credit card expired, whose prepaid balance ran out, or whose bank flagged a routine charge. They wanted to keep paying. They just couldn’t.&lt;/p&gt;



&lt;p&gt;On the App Store, that number is 15.2%. Still significant, but less than half the Google Play rate.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;852&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/cancellation-reasons-app-store-sosa-26-1024x852.png&quot; alt=&quot;&quot; class=&quot;wp-image-52777&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/cancellation-reasons-app-store-sosa-26-1024x852.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/cancellation-reasons-app-store-sosa-26-300x250.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/cancellation-reasons-app-store-sosa-26-768x639.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/cancellation-reasons-app-store-sosa-26-1536x1278.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/cancellation-reasons-app-store-sosa-26-50x42.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/cancellation-reasons-app-store-sosa-26-48x40.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/cancellation-reasons-app-store-sosa-26-558x464.png 558w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/cancellation-reasons-app-store-sosa-26-696x579.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/cancellation-reasons-app-store-sosa-26-560x466.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/cancellation-reasons-app-store-sosa-26-356x296.png 356w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/cancellation-reasons-app-store-sosa-26-567x472.png 567w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/cancellation-reasons-app-store-sosa-26-80x67.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/cancellation-reasons-app-store-sosa-26.png 1596w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;As we put it in the report: &lt;strong&gt;“The primary platform difference is not unsubscribe behavior – it’s billing reliability.”&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;For a $1M ARR Android app, a 32% involuntary cancellation rate translates to north of $300K/year walking out the door. And unlike voluntary churn – which requires product changes, retention experiments, and long feedback loops – involuntary churn is a &lt;strong&gt;recoverable revenue stream&lt;/strong&gt; with well-documented playbooks and near-immediate ROI.&lt;/p&gt;



&lt;p&gt;This is probably the highest-return retention work most Android developers aren’t doing. We’ll walk through why the gap exists, what Google Play gives you to fix it, what you need to build yourself, and what recovery actually looks like.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-google-play-leaks-more-than-apple&quot;&gt;Why Google Play leaks more than Apple&lt;/h2&gt;



&lt;p&gt;The 2x gap between Google Play and the App Store isn’t a quality problem on Google’s end. It’s structural – a consequence of how each platform’s users interact with payments.&lt;/p&gt;



&lt;p&gt;As Jacob Eiting discussed on the &lt;a href=&quot;https://subclub.com/episode/the-2026-state-of-subscription-apps-report&quot;&gt;Sub Club podcast episode&lt;/a&gt; covering the report: “The Apple platform is way more oriented around keeping your credit card up to date. Everything is Apple Pay. You’ve got your Apple subscription to keep your photo library in the cloud. It feels like as a platform, they do kind of more strongly incentivize you to keep your billing updated, keep money flowing through their systems.”&lt;/p&gt;



&lt;p&gt;Google Play users, particularly in developing markets, often don’t have that same web of tied services. Their Play Store payment method can go stale for months before they notice. Google also allows prepaid cards and carrier billing in markets where balances frequently run dry – payment methods that Apple doesn’t support at the same scale. As Jacob put it: “Your balance runs out and then the billing fails. The physics are just very different.”&lt;/p&gt;



&lt;p&gt;Our report’s retention data reinforces this pattern. Jeff Morris Jr., writing in the expert commentary section, notes that the challenge in emerging markets isn’t long-term retention of a good user – it’s “overcoming initial billing or usage friction.” By the 3rd renewal cycle, all geographies converge to within a few percentage points of each other. The users are there, the payment infrastructure just isn’t keeping up.&lt;/p&gt;



&lt;p&gt;The underlying decline categories tell you everything about why this is recoverable. The vast majority of billing failures are “soft” declines – generic declines, insufficient funds, expired cards – that are temporary, situational, and recoverable with retries and a little nudging. By some industry estimates, roughly a quarter to a third of US payment cards are reissued annually, creating a constant background rate of stale credentials even among engaged, willing-to-pay subscribers.&lt;/p&gt;



&lt;p&gt;The user didn’t leave, their card did.&lt;/p&gt;



&lt;p&gt;The practical upshot: Android developers have both a bigger problem &lt;em&gt;and&lt;/em&gt; more granular tools to fix it. The question is whether they’ve configured those tools.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-60-minute-fix-platform-tools-most-developers-haven-t-touched&quot;&gt;The 60-minute fix: platform tools most developers haven’t touched&lt;/h2&gt;



&lt;p&gt;Here’s the thing that makes involuntary churn different from almost every other retention problem: the highest-impact interventions are configuration changes, not code. Google provides a 60-day total recovery window with built-in retry logic, payment update prompts, and user notifications. But the default settings leave significant recovery on the table.&lt;/p&gt;



&lt;p&gt;If you do nothing else after reading this post, do what’s in this section.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-grace-periods-keep-the-user-subscribed-while-google-retries&quot;&gt;Grace periods: keep the user subscribed while Google retries&lt;/h3&gt;



&lt;p&gt;Google structures its recovery window into two phases. The &lt;strong&gt;grace period&lt;/strong&gt; keeps the user subscribed with full access while Google retries the payment. If recovery fails during that window, the &lt;strong&gt;account hold&lt;/strong&gt; suspends access but continues retry attempts. As of Google’s December 2025 policy change, the total window is capped at 60 days, with the account hold duration auto-calculated as 60 minus whatever grace period you configure.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;683&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/google-play-recovery-window-1024x683.png&quot; alt=&quot;&quot; class=&quot;wp-image-52780&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/google-play-recovery-window-1024x683.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/google-play-recovery-window-300x200.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/google-play-recovery-window-768x512.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/google-play-recovery-window-50x33.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/google-play-recovery-window-60x40.png 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/google-play-recovery-window-696x464.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/google-play-recovery-window-560x373.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/google-play-recovery-window-444x296.png 444w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/google-play-recovery-window-708x472.png 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/google-play-recovery-window-80x53.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/google-play-recovery-window-48x32.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/google-play-recovery-window.png 1300w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Grace periods are now enabled by default on all auto-renewing base plans and can be set for &lt;strong&gt;up to 30 days&lt;/strong&gt; (expanded from earlier limits at Google I/O 2025). During this period, Google retries the charge, emails the user, and sends notifications prompting a payment update. Your app still returns the subscription as active via queryPurchasesAsync(), meaning apps that check entitlements through the standard API handle grace periods automatically with no code changes. If payment recovers during the grace period, the original billing date is preserved – the user never knows anything went wrong.&lt;/p&gt;



&lt;p&gt;Google’s published data on the impact is hard to argue with: enabling grace periods delivers a &lt;strong&gt;57% higher recovery rate&lt;/strong&gt; from renewal declines.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-account-holds-the-second-chance-window&quot;&gt;Account holds: the second-chance window&lt;/h3&gt;



&lt;p&gt;Account holds kick in when the grace period expires. The user loses access, the subscription state shifts to &lt;code&gt;SUBSCRIPTION_STATE_ON_HOLD&lt;/code&gt;, and &lt;code&gt;queryPurchasesAsync()&lt;/code&gt; stops returning the subscription. This is important – you need to explicitly check for the on-hold state to show the right messaging in your app. Google continues retrying in the background for the remainder of the 60-day window. If the user fixes their payment during account hold, access resumes but the billing date resets to the recovery date.&lt;/p&gt;



&lt;p&gt;Google reports that adding account hold on top of grace periods produces &lt;strong&gt;35% higher payment decline recovery&lt;/strong&gt; and &lt;strong&gt;8% lower involuntary churn&lt;/strong&gt;. In early cohort data, combining grace period and account hold tripled the decline recovery rate from roughly 10% to 33%.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-in-app-messaging-api-two-lines-of-code-2x-recovery&quot;&gt;The In-App Messaging API: two lines of code, 2x recovery&lt;/h3&gt;



&lt;p&gt;Now, the tool that almost nobody uses. The &lt;strong&gt;In-App Messaging API&lt;/strong&gt; is a single call – &lt;code&gt;BillingClient.showInAppMessages()&lt;/code&gt; with &lt;code&gt;InAppMessageCategoryId.TRANSACTIONAL&lt;/code&gt; – that displays a Google-rendered snackbar when a user in grace period or account hold opens your app. It shows once per day, includes a direct link to fix payment on Google Play, and requires no custom UI work on your end.&lt;/p&gt;



&lt;p&gt;Google’s data shows this produces a &lt;strong&gt;2x increase in user recovery&lt;/strong&gt; and growth in overall subscriber spend. Two lines of code. Call it on every app launch. If you implement one thing from this post, make it this.&lt;/p&gt;



&lt;p&gt;If you’re using RevenueCat, this is already handled – the SDK shows Google Play’s In-App Messages automatically starting in v7. No additional code needed. You can disable it via &lt;code&gt;.showInAppMessagesAutomatically(false)&lt;/code&gt; if you want to manage it yourself, but for most apps, the default behavior is exactly what you want.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-what-about-apple&quot;&gt;What about Apple?&lt;/h3&gt;



&lt;p&gt;The App Store’s involuntary churn rate is less than half of Google Play’s, and more of the recovery happens automatically – billing retry is always on for all auto-renewable subscriptions, and since iOS 16.4, Apple shows a Billing Problem Message to users without any API call on your end. The one thing you should actively opt into is the &lt;strong&gt;Billing Grace Period&lt;/strong&gt; in App Store Connect – set it to 28 days. Apple’s own data shows 90% of billing issues resolve within that window. That’s it for iOS. The rest of this post focuses on Google Play, where the problem is bigger and the developer toolkit is more hands-on.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-google-play-configuration-checklist&quot;&gt;The Google Play configuration checklist&lt;/h3&gt;



&lt;p&gt;The total time investment here is about an hour: verify grace periods are enabled and set to the maximum appropriate duration for each base plan (up to 30 days), confirm account hold is set to auto-calculated for a full 60-day window, and add the In-App Messaging API call to your app launch flow.&lt;/p&gt;



&lt;p&gt;That’s it. You’ve just recovered a meaningful chunk of your involuntary churn.&lt;/p&gt;



&lt;p&gt;If you’re using RevenueCat, grace period and account hold states configured in the Play Console are detected automatically – subscriptions in a grace period remain “active” in your entitlement checks, and a&lt;a href=&quot;https://www.revenuecat.com/docs/subscription-guidance/how-grace-periods-work&quot;&gt; BILLING_ISSUE event&lt;/a&gt; fires to your webhooks and connected integrations the moment a payment fails. The&lt;a href=&quot;https://www.revenuecat.com/docs/dashboard-and-metrics/charts/subscription-status-chart&quot;&gt; Subscription Status chart&lt;/a&gt; in the dashboard also surfaces a dedicated “Billing Issue” status, so you can see at a glance what percentage of your active MRR is currently at risk from payment failures. It’s a useful gut check after you’ve made configuration changes – you can watch the billing issue cohort shrink in real time.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;566&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-3-1024x566.png&quot; alt=&quot;&quot; class=&quot;wp-image-52771&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-3-1024x566.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-3-300x166.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-3-768x425.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-3-1536x850.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-3-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-3-72x40.png 72w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-3-696x385.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-3-560x310.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-3-535x296.png 535w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-3-840x465.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-3-80x44.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-3-48x27.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/image-3.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;em&gt;Subscription Status chart in RevenueCat&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;But platform-level tools are a floor, not a ceiling.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-full-dunning-stack-push-email-and-deep-links&quot;&gt;The full dunning stack: push, email, and deep links&lt;/h2&gt;



&lt;p&gt;Once you’ve configured the platform defaults, the next layer of recovery comes from developer-side &lt;strong&gt;dunning&lt;/strong&gt; – the industry term for communicating with users about failed payments and prompting them to fix it. This is where you move from “configuration” to “engineering investment,” but the ROI remains strong.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-push-notifications-and-in-app-messaging&quot;&gt;Push notifications and in-app messaging&lt;/h3&gt;



&lt;p&gt;The timing cadence matters more than the copy. Fire the first push notification on &lt;strong&gt;Day 0&lt;/strong&gt; when the decline is detected via Google’s Real-Time Developer Notifications (RTDN). Follow up on Days 1–3, then Day 7, then Day 14. After that, diminishing returns set in.&lt;/p&gt;



&lt;p&gt;Keep the tone helpful, not alarming. “We’re having trouble renewing your subscription – tap to update your payment method” works better than anything that sounds like a warning siren. The user didn’t do anything wrong; their card did.&lt;/p&gt;



&lt;p&gt;Calibrate your in-app messaging to the subscription state. During the grace period, the user still has access – a non-blocking banner or snackbar is appropriate. During account hold, escalate to a more prominent modal explaining that access is suspended, with a clear call-to-action.&lt;/p&gt;



&lt;p&gt;Google’s In-App Messaging API already handles a once-daily in-app prompt during grace period and account hold, so your developer-side push notifications serve as a complementary channel – catching users who haven’t opened the app.&lt;/p&gt;



&lt;p&gt;To trigger all of this, you need &lt;strong&gt;Real-Time Developer Notifications&lt;/strong&gt; set up via Google Cloud Pub/Sub. The billing-related notification types to handle are &lt;code&gt;SUBSCRIPTION_IN_GRACE_PERIOD&lt;/code&gt; (type 6), &lt;code&gt;SUBSCRIPTION_ON_HOLD&lt;/code&gt; (type 5), &lt;code&gt;SUBSCRIPTION_RECOVERED&lt;/code&gt; (type 1), and &lt;code&gt;SUBSCRIPTION_EXPIRED&lt;/code&gt; (type 13). After receiving any RTDN, call &lt;code&gt;purchases.subscriptionsv2.get&lt;/code&gt; to fetch the full subscription state – RTDNs signal that something changed but don’t carry complete details.&lt;/p&gt;



&lt;p&gt;If you’re using RevenueCat, this plumbing is already done for you. The &lt;a href=&quot;https://www.revenuecat.com/docs/integrations/webhooks/event-flows&quot;&gt;BILLING_ISSUE event&lt;/a&gt; fires automatically to your &lt;a href=&quot;https://www.revenuecat.com/docs/integrations/third-party-integrations&quot;&gt;connected integrations&lt;/a&gt; – Braze, OneSignal, Iterable, Customer.io, and others – so you can trigger dunning campaigns directly from the tools you’re already using without building your own RTDN processing pipeline. The event includes grace_period_expiration_at, giving your campaigns the exact deadline to work with.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-deep-linking-to-payment-settings&quot;&gt;Deep linking to payment settings&lt;/h3&gt;



&lt;p&gt;Every extra tap between your dunning message and the payment update screen costs you recovered subscribers. The best recovery flows route users directly to the right screen with a single tap.&lt;/p&gt;



&lt;p&gt;On Android, link to: &lt;code&gt;https://play.google.com/store/account/subscriptions?package={packageName}&amp;amp;sku={skuId}&lt;/code&gt; – this takes users directly to their specific subscription on Google Play.&lt;/p&gt;



&lt;p&gt;On iOS (for your cross-platform setup), use &lt;code&gt;AppStore.showManageSubscriptions(in:)&lt;/code&gt; in StoreKit 2 (iOS 15+) to display the subscription management sheet without leaving your app.&lt;/p&gt;



&lt;p&gt;If you’re using RevenueCat, the &lt;a href=&quot;https://www.revenuecat.com/docs/subscription-guidance/how-grace-periods-work&quot;&gt;managementURL property on CustomerInfo&lt;/a&gt; returns the correct platform-specific URL automatically. This means your in-app billing error UI can include a one-tap “Fix payment” button that works across both stores without hardcoding store-specific URLs or maintaining platform branching logic.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-email-dunning-sequences&quot;&gt;Email dunning sequences&lt;/h3&gt;



&lt;p&gt;Email catches users who aren’t opening your app or aren’t seeing push notifications. A 3–5 message sequence over 14–28 days works well, shifting from friendly notification (“Heads up – we couldn’t process your payment”) to urgency (“Your subscription is at risk”) to final warning (“Last chance to keep your subscription”). Personalize with the user’s name and the specific features they’ll lose access to. Make the call-to-action button prominent and link directly to payment update.&lt;/p&gt;



&lt;p&gt;One nuance worth flagging: pre-dunning emails that warn about upcoming card expirations – sent &lt;em&gt;before&lt;/em&gt; a failure happens – sound good in theory but can backfire in practice. They can prompt users to reconsider whether they want the subscription at all, especially if the app isn’t top-of-mind. For active users, in-app prompts about expiring cards tend to be safer than email.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-recovery-benchmarks-what-to-expect&quot;&gt;Recovery benchmarks: what to expect&lt;/h2&gt;



&lt;p&gt;Recovery rates vary based on how many of these tools you actually activate. Here’s what Google’s published data suggests, supplemented by their developer case studies:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Platform defaults only&lt;/strong&gt; (no grace period optimization, no developer intervention): roughly &lt;strong&gt;10–15% recovery&lt;/strong&gt; of failed payments. This is where most apps sit today.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Optimized grace periods + account holds + In-App Messaging API&lt;/strong&gt; (about an hour of configuration): roughly &lt;strong&gt;30–35% recovery&lt;/strong&gt; on Google Play. Google’s published data shows the combined effect of grace period and account hold triples recovery from the baseline. The In-App Messaging API doubles user recovery on top of that.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Full dunning stack&lt;/strong&gt; (push notifications + email sequences + deep links on top of the platform tools): the incremental gains from each channel compound. In&lt;a href=&quot;https://developer.android.com/stories/apps/truecaller&quot;&gt; Google’s published Truecaller case study&lt;/a&gt;, implementing RTDN-triggered messaging alongside grace periods and account hold recovered &lt;strong&gt;40% of at-risk subscribers&lt;/strong&gt; – up from 15% before the changes.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Now consider what a recovered subscriber is actually worth. Our 2026 State of Subscription Apps data shows that a subscriber who survives their 1st monthly renewal has a 73–82% chance of making it to their 3rd. Every billing failure you recover in cycle 1 is a subscriber who gets the chance to become one of those high-retention renewals. Conversely, our reactivation data shows that once a monthly subscriber actually churns, only about 20% come back within a year – and for annual subscribers, it’s a dismal 5%. &lt;strong&gt;Preventing the loss is dramatically more valuable than winning the user back later.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Whichever tier you’re operating at, make sure you’re measuring the impact. Track your billing error cancellation rate by platform (RevenueCat’s &lt;a href=&quot;https://www.revenuecat.com/docs/dashboard-and-metrics/charts/subscription-retention-chart&quot;&gt;Subscription Retention chart&lt;/a&gt; excludes unresolved grace period transactions, so your retention numbers reflect actual recovered subscribers). Compare cohorts before and after you extend grace periods. The feedback loop here is fast – you should see movement within a single billing cycle.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-fix-billing-before-you-buy-more-users&quot;&gt;Fix billing before you buy more users&lt;/h2&gt;



&lt;p&gt;Involuntary churn is one of those rare problems where the diagnosis is clear, the tools already exist, and the returns are immediate. The instinct to treat billing failures as the platform’s problem is understandable – but the data is unambiguous. A third of your Google Play cancellations are subscribers who wanted to keep paying.&lt;/p&gt;



&lt;p&gt;The highest-impact work is configuration, not code. Extend your grace periods. Enable account hold. Add Google’s In-App Messaging API. That’s an afternoon of work that recovers real revenue starting the next billing cycle.&lt;/p&gt;



&lt;p&gt;Fix billing before you buy more users.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[“Money will come” – How Super Unlimited built the #1 VPN by not optimizing for revenue]]></title><description><![CDATA[On the podcast: the product-driven growth loop behind the #1 VPN app in the world, why they intentionally leave money on the table, and how the prettiest design often loses in their A/B tests.]]></description><link>https://www.revenuecat.com/blog/growth/tanuj-chatterjee-super-unlimited-vpn-sub-club-podcast-2026/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/tanuj-chatterjee-super-unlimited-vpn-sub-club-podcast-2026/</guid><pubDate>Wed, 01 Apr 2026 12:56:35 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/04/RC-Blog-Cover-Tanuj-Chatterjee-1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Tanuj Chatterjee is the CEO of Super Unlimited VPN — the #1 VPN app in the world by downloads, with over a billion installs and more than a million new downloads every day, almost entirely organic. In a conversation with David Barnard and RevenueCat CEO Jacob Eiting, he breaks down the product-driven growth loop that got them there, the deliberate decision to leave money on the table, and what five years of A/B testing has taught him about the gap between what looks good and what actually converts.&lt;/p&gt;


&lt;div class=&quot;lazyblock-d7d847878df0-Z2oSQw5 wp-block-lazyblock-d7d847878df0&quot;&gt;&lt;blogpostyoutube embed-url=&quot;https://www.youtube.com/watch?v=Y16aBkMc6hk&quot;&gt;
&lt;/blogpostyoutube&gt;&lt;/div&gt;


&lt;iframe loading=&quot;lazy&quot; width=&quot;100%&quot; height=&quot;180&quot; frameborder=&quot;no&quot; scrolling=&quot;no&quot; seamless=&quot;&quot; src=&quot;https://share.transistor.fm/e/30db3644?color=FFFFFF&amp;amp;background=30343C&quot;&gt;&lt;/iframe&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-screenshot-redesign-that-kept-losing&quot;&gt;The screenshot redesign that kept losing&lt;/h2&gt;



&lt;p&gt;Super Unlimited’s App Store screenshots are, by Tanuj’s own admission, a little stale. The team has spent years trying to fix that. They’ve tested modern layouts, updated colors, new content arrangements, and contemporary design trends. The results have been consistent: 80% of the time, the new version loses.&lt;/p&gt;



&lt;p&gt;“People just like to see what they were used to seeing,” Tanuj says. “In many cases, we have gone back to the original ones that we had.”&lt;/p&gt;



&lt;p&gt;The finding cuts against one of the most common instincts in app growth: that better design means better conversion. For an app sitting at the top of App Store search, the risk of a major visual overhaul is asymmetric. Disrupting a proven asset is more dangerous than the upside of a marginal lift. The team still tests — methodically, one variable at a time — but they’ve learned to treat the data as the authority, not their aesthetic judgment.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-a-low-conversion-rate-is-part-of-the-strategy&quot;&gt;Why a low conversion rate is part of the strategy&lt;/h2&gt;



&lt;p&gt;Super Unlimited’s free-to-paid conversion rate is, by most subscription app standards, quite low. Tanuj is fine with it.&lt;/p&gt;



&lt;p&gt;“Our free version is that good,” he says. “You don’t want to throttle or take things away from the free version. There’s a reason we have the word unlimited in our name.”&lt;/p&gt;



&lt;p&gt;Free users can access dozens of countries and cities, watch a couple of ads, and use the VPN without restrictions. The paywall exists — premium subscribers get no ads, top-tier servers, multi-platform access, and priority support — but it’s designed to be easy to dismiss. There’s a large X in the corner. No dark patterns.&lt;/p&gt;



&lt;p&gt;The logic is a numbers game. Super Unlimited’s LTV is modest compared to a Spotify or a Netflix. But their top of funnel is enormous, and it’s almost entirely organic. The free experience generates the ratings volume and return-visit signals that feed the App Store algorithm, which keeps the downloads coming. “Our top of the funnel is our superpower,” Tanuj says. “Don’t mess with it.”&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-countries-where-they-lose-money-on-purpose&quot;&gt;The countries where they lose money on purpose&lt;/h2&gt;



&lt;p&gt;Super Unlimited serves users in countries where the economics don’t work. Turkey, Myanmar, and other markets with low CPMs, high infrastructure costs, or active internet censorship are not profitable. The team knows this and serves them anyway.&lt;/p&gt;



&lt;p&gt;When Turkey banned Instagram for 11 days last year, Super Unlimited received 15 million downloads in four days — roughly 30-40% of Turkey’s internet population. The revenue from those users didn’t cover the cost of serving them.&lt;/p&gt;



&lt;p&gt;“We just think it’s the right thing to do,” Tanuj says. “People should have access to information. They should not be constrained by just propaganda.”&lt;/p&gt;



&lt;p&gt;This isn’t purely altruistic. The geopolitical spikes that come with being a global VPN have a compounding effect: each spike drives the app to a new normal at a higher baseline once the event passes. But the decision to serve loss-making markets is a deliberate one, made on values grounds, not just financial ones.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-happened-when-support-moved-into-the-product-team&quot;&gt;What happened when support moved into the product team&lt;/h2&gt;



&lt;p&gt;At most companies, customer support is a separate organization. It presents KPIs to the product team once a month. The feedback loop between user pain and product fix takes weeks.&lt;/p&gt;



&lt;p&gt;At Super Unlimited, the head of support reports directly to the head of product.&lt;/p&gt;



&lt;p&gt;“I have been at companies where product and support was a totally separate organization,” Tanuj says. “The pace at which the feedback loop goes into the product side is a lot less.”&lt;/p&gt;



&lt;p&gt;When a spike in support tickets from Uganda signals a service quality issue, the product team knows the same day — not next month. A recurring question about a feature becomes a UX fix in the next sprint, not a FAQ entry. For an app where service quality is the primary competitive advantage, the speed of that loop is the speed of improvement.&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Y16aBkMc6hk&quot;&gt;The episode&lt;/a&gt; also covers how Super Unlimited thinks about paid search when you’re already the #1 organic result, why they’re betting on Windows as their next growth vector, and the infrastructure decision — bare metal servers for the data plane, cloud for surge capacity — that makes their unit economics work at scale.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-guest-links&quot;&gt;Guest links:&lt;/h2&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.linkedin.com/in/tanujchatterjee/&quot;&gt;Tanuj Chatterjee on LinkedIn&lt;/a&gt;&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://superunlimitedvpn.com/&quot;&gt;Super Unlimited VPN&lt;/a&gt;&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Hiring in Asia and Europe: &lt;a href=&quot;mailto:jobs@superunlimited.com&quot;&gt;jobs@superunlimited.com&lt;/a&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title><![CDATA[Kotlin Coroutine bridges: converting any callback-based Android API to suspend functions]]></title><description><![CDATA[This article explores the suspendCoroutine bridge pattern, showing how to convert callback APIs into clean suspend functions, handle diverse callback shapes, design proper error propagation, and how SDKs like RevenueCat apply it at scale.]]></description><link>https://www.revenuecat.com/blog/engineering/kotlin-coroutine-bridge/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/kotlin-coroutine-bridge/</guid><pubDate>Tue, 31 Mar 2026 23:26:22 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Blog-40_Kotlin-Coroutines-bridges.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Most Android platform APIs and third party SDKs were designed around callbacks. The Google Play Billing Library uses&amp;nbsp;&lt;code&gt;PurchasesUpdatedListener&lt;/code&gt;. Location Services uses&amp;nbsp;&lt;code&gt;LocationCallback&lt;/code&gt;. Bluetooth GATT uses&amp;nbsp;&lt;code&gt;BluetoothGattCallback&lt;/code&gt;. Camera2 uses&amp;nbsp;&lt;code&gt;CameraCaptureSession.StateCallback&lt;/code&gt;. If you have been writing Android code for more than a few months, you have written deeply nested callback chains that are hard to read, hard to test, and hard to reason about when errors occur at any stage. Kotlin coroutines solve this with&amp;nbsp;&lt;code&gt;suspend&lt;/code&gt;&amp;nbsp;functions, but the platform and most SDKs do not hand you suspend functions out of the box. You need a bridge.&lt;/p&gt;



&lt;p&gt;In this article, you’ll explore the suspend coroutine bridge pattern in detail, tracing how it converts callback based APIs into clean suspend functions, how to handle different callback shapes from single value results to multi parameter success and error pairs, how to design exception hierarchies that preserve error semantics across the bridge, why you should always reach for&amp;nbsp;&lt;code&gt;suspendCancellableCoroutine&lt;/code&gt;&amp;nbsp;rather than the older&amp;nbsp;&lt;code&gt;suspendCoroutine&lt;/code&gt;&amp;nbsp;— even when the underlying callback API has no native cancellation — and how production SDKs like RevenueCat apply these patterns at scale across 20+ API surfaces.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-fundamental-problem-callbacks-do-not-compose&quot;&gt;&lt;strong&gt;The fundamental problem: Callbacks do not compose&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Consider a common billing flow on Android. You need to connect to the billing service, query products, then initiate a purchase. With the raw callback API, this looks like:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZE6roB wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;billingClient.startConnection(object : BillingClientStateListener {\n    override fun onBillingSetupFinished(result: BillingResult) {\n        if (result.responseCode == BillingClient.BillingResponseCode.OK) {\n            val params = QueryProductDetailsParams.newBuilder()\n                .setProductList(listOf(\/* ... *\/))\n                .build()\n            billingClient.queryProductDetailsAsync(params) { billingResult, productDetails -&gt;\n                if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {\n                    \/\/ Now launch the purchase flow...\n                }\n            }\n        }\n    }\n\n    override fun onBillingServiceDisconnected() {\n        \/\/ Retry? Log? Both callbacks share no structured error path.\n    }\n})&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Each callback nests inside the previous one. Error handling is scattered across&amp;nbsp;&lt;code&gt;if&lt;/code&gt;&amp;nbsp;checks and separate override methods. There is no structured way to propagate failures up the chain. And this is only two callbacks deep. A full billing flow, connecting, querying, purchasing, acknowledging, involves four or five nested levels.&lt;/p&gt;



&lt;p&gt;The suspend function equivalent reads like sequential code:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1tGw0l wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;val connected = billingClient.awaitConnect()\nval products = billingClient.awaitQueryProducts(productIds)\nval result = billingClient.awaitPurchase(activity, products.first())\nbillingClient.awaitAcknowledge(result.purchaseToken)&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This is not a language feature you get for free. Each of those&amp;nbsp;&lt;code&gt;await&lt;/code&gt;&amp;nbsp;functions requires a bridge that converts the underlying callback into a coroutine suspension point. Let’s trace through exactly how that bridge works.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-core-bridge-the-core-bridge-suspendcancellablecoroutine&quot;&gt;&lt;strong&gt;The core bridge:&amp;nbsp;&lt;code&gt;The core bridge: &lt;code&gt;suspendCancellableCoroutine&lt;/code&gt;&lt;/code&gt;&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Kotlin provides two primitives for bridging between callback based code and coroutines:&amp;nbsp;&lt;code&gt;suspendCoroutine&lt;/code&gt;&amp;nbsp;and&amp;nbsp;&lt;code&gt;suspendCancellableCoroutine&lt;/code&gt;. They look almost identical — both suspend the current coroutine and hand you a continuation that you later&amp;nbsp;&lt;code&gt;resume&lt;/code&gt;&amp;nbsp;with a result or&amp;nbsp;&lt;code&gt;resumeWithException&lt;/code&gt;&amp;nbsp;with an error — but only one of them is safe to use in real code:&amp;nbsp;&lt;code&gt;suspendCancellableCoroutine&lt;/code&gt;.&lt;/p&gt;



&lt;p&gt;The plain rule, stated up front:&amp;nbsp;&lt;strong&gt;do not use&amp;nbsp;&lt;code&gt;suspendCoroutine&lt;/code&gt;&amp;nbsp;in application or library code.&lt;/strong&gt;&amp;nbsp;Its continuation is not tied to coroutine cancellation, so when a parent&amp;nbsp;&lt;code&gt;Job&lt;/code&gt;&amp;nbsp;is cancelled the leaf cannot tear down. The coroutine stays parked, holding references to its scope and context, until (or unless) the callback eventually fires. That is a structured concurrency hole and, in practice, a latent memory and resource leak. &lt;/p&gt;



&lt;p&gt;Worse, cancellation and exceptions further up the tree can’t propagate past a coroutine that refuses to finish, which is how a single stuck bridge wedges a whole screen’s scope.&amp;nbsp;&lt;code&gt;suspendCancellableCoroutine&lt;/code&gt;&amp;nbsp;closes the hole by giving you a&amp;nbsp;&lt;code&gt;CancellableContinuation&lt;/code&gt;&amp;nbsp;that participates in cancellation, even when the underlying callback based API has no cancellation support of its own. Every example in this article uses it.&lt;/p&gt;



&lt;p&gt;The simplest bridge handles a single value callback:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1c3NcC wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;suspend fun BillingClient.awaitConnect(): Boolean {\n    return suspendCancellableCoroutine { continuation -&gt;\n        startConnection(object : BillingClientStateListener {\n            override fun onBillingSetupFinished(result: BillingResult) {\n                continuation.resume(\n                    result.responseCode == BillingClient.BillingResponseCode.OK\n                )\n            }\n\n            override fun onBillingServiceDisconnected() {\n                \/\/ Connection lost after setup, not during initial connect\n            }\n        })\n        continuation.invokeOnCancellation { endConnection() }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The pattern has three parts. First, call&amp;nbsp;&lt;code&gt;suspendCancellableCoroutine&lt;/code&gt;&amp;nbsp;to pause the coroutine and receive a&amp;nbsp;&lt;code&gt;CancellableContinuation&lt;/code&gt;. Second, call the callback based API, passing an anonymous implementation that captures the continuation. Third, inside the callback, call&amp;nbsp;&lt;code&gt;resume&lt;/code&gt;&amp;nbsp;or&amp;nbsp;&lt;code&gt;resumeWithException&lt;/code&gt;&amp;nbsp;to deliver the result and unfreeze the coroutine. When the underlying API supports teardown, register a cleanup block through&amp;nbsp;&lt;code&gt;invokeOnCancellation&lt;/code&gt;&amp;nbsp;so cancellation actually releases the resource instead of waiting on a callback that may never come back.&lt;/p&gt;



&lt;p&gt;One important rule: you must call&amp;nbsp;&lt;code&gt;resume&lt;/code&gt;&amp;nbsp;or&amp;nbsp;&lt;code&gt;resumeWithException&lt;/code&gt;&amp;nbsp;at most once per non cancelled continuation. Calling it zero times means the coroutine hangs forever (unless cancelled from outside). Calling it twice on a live continuation throws&amp;nbsp;&lt;code&gt;IllegalStateException&lt;/code&gt;. After cancellation,&amp;nbsp;&lt;code&gt;CancellableContinuation.resume&lt;/code&gt;&amp;nbsp;simply drops the value, so you do not need to guard every resume with an&amp;nbsp;&lt;code&gt;isActive&lt;/code&gt;&amp;nbsp;check — but every non-cancelled code path through your callback must reach exactly one resume call.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;success-and-error-callbacks-the-two-path-bridge&quot;&gt;&lt;strong&gt;Success and error callbacks: The two-path bridge&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Most SDK APIs split their callbacks into success and error paths. This maps naturally to&amp;nbsp;&lt;code&gt;resume&lt;/code&gt;&amp;nbsp;and&amp;nbsp;&lt;code&gt;resumeWithException&lt;/code&gt;. Let’s examine how RevenueCat’s Android SDK bridges its offerings API.&lt;/p&gt;



&lt;p&gt;Looking at the&amp;nbsp;&lt;code&gt;awaitOfferings&lt;/code&gt;&amp;nbsp;extension function:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z2d6hso wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@JvmSynthetic\n@Throws(PurchasesException::class)\nsuspend fun Purchases.awaitOfferings(): Offerings {\n    return suspendCancellableCoroutine { continuation -&gt;\n        getOfferingsWith(\n            onSuccess = continuation::resume,\n            onError = { continuation.resumeWithException(PurchasesException(it)) },\n        )\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Notice the structure. The&amp;nbsp;&lt;code&gt;onSuccess&lt;/code&gt;&amp;nbsp;path uses a method reference&amp;nbsp;&lt;code&gt;continuation::resume&lt;/code&gt;&amp;nbsp;directly. When the callback signature matches&amp;nbsp;&lt;code&gt;(T) -&amp;gt; Unit&lt;/code&gt;&amp;nbsp;and the continuation expects&amp;nbsp;&lt;code&gt;T&lt;/code&gt;, a method reference is the cleanest form. The&amp;nbsp;&lt;code&gt;onError&lt;/code&gt;&amp;nbsp;path wraps the raw&amp;nbsp;&lt;code&gt;PurchasesError&lt;/code&gt;&amp;nbsp;in a&amp;nbsp;&lt;code&gt;PurchasesException&lt;/code&gt;&amp;nbsp;before passing it to&amp;nbsp;&lt;code&gt;resumeWithException&lt;/code&gt;. This is necessary because&amp;nbsp;&lt;code&gt;resumeWithException&lt;/code&gt;&amp;nbsp;expects a&amp;nbsp;&lt;code&gt;Throwable&lt;/code&gt;, but the SDK’s error type is a plain data object, not an exception.&lt;/p&gt;



&lt;p&gt;The&amp;nbsp;&lt;code&gt;@JvmSynthetic&lt;/code&gt;&amp;nbsp;annotation prevents this extension function from appearing in Java code, since Java callers should use the callback version. The&amp;nbsp;&lt;code&gt;@Throws&lt;/code&gt;&amp;nbsp;annotation generates the&amp;nbsp;&lt;code&gt;throws&lt;/code&gt;&amp;nbsp;clause in the bytecode so Java interop and documentation tools correctly report what this function can throw.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;the-callback-factory-abstracting-interface-boilerplate&quot;&gt;&lt;strong&gt;The callback factory: Abstracting interface boilerplate&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Before the suspend bridge can work, there is another layer of bridging. Many Android SDK APIs accept typed callback interfaces, not lambda pairs. For example, Google Play Billing uses&amp;nbsp;&lt;code&gt;PurchaseCallback&lt;/code&gt;&amp;nbsp;with&amp;nbsp;&lt;code&gt;onCompleted&lt;/code&gt;&amp;nbsp;and&amp;nbsp;&lt;code&gt;onError&lt;/code&gt;&amp;nbsp;methods. RevenueCat’s internal API uses&amp;nbsp;&lt;code&gt;ReceiveOfferingsCallback&lt;/code&gt;&amp;nbsp;with&amp;nbsp;&lt;code&gt;onReceived&lt;/code&gt;&amp;nbsp;and&amp;nbsp;&lt;code&gt;onError&lt;/code&gt;.&lt;/p&gt;



&lt;p&gt;Writing anonymous implementations of these interfaces inside every suspend function creates noise. The solution is a set of factory functions that convert lambda pairs into typed callback objects.&lt;/p&gt;



&lt;p&gt;Looking at the callback factory for offerings:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-zhQdI wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;internal fun receiveOfferingsCallback(\n    onSuccess: (offerings: Offerings) -&gt; Unit,\n    onError: (error: PurchasesError) -&gt; Unit,\n) = object : ReceiveOfferingsCallback {\n    override fun onReceived(offerings: Offerings) {\n        onSuccess(offerings)\n    }\n\n    override fun onError(error: PurchasesError) {\n        onError(error)\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This is a small function, but it matters at scale. RevenueCat’s SDK has factory functions for offerings, customer info, store products, purchases, login, sync, and more. Each one converts the&amp;nbsp;&lt;code&gt;(onSuccess, onError)&lt;/code&gt;&amp;nbsp;lambda pair into the specific callback interface the underlying API expects.&lt;/p&gt;



&lt;p&gt;The purchase callback factory handles a more complex shape:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z242Q9N wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;internal fun purchaseCompletedCallback(\n    onSuccess: (purchase: StoreTransaction, customerInfo: CustomerInfo) -&gt; Unit,\n    onError: (error: PurchasesError, userCancelled: Boolean) -&gt; Unit,\n) = object : PurchaseCallback {\n    override fun onCompleted(storeTransaction: StoreTransaction, customerInfo: CustomerInfo) {\n        onSuccess(storeTransaction, customerInfo)\n    }\n\n    override fun onError(error: PurchasesError, userCancelled: Boolean) {\n        onError(error, userCancelled)\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Notice the asymmetry. The success callback delivers two values: the transaction and the updated customer info. The error callback also delivers two values: the error and a boolean indicating whether the user cancelled. This is not a simple&amp;nbsp;&lt;code&gt;(T) -&amp;gt; Unit&lt;/code&gt;&amp;nbsp;shape. Bridging this to a suspend function requires additional design decisions.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;multi-value-callbacks-wrapper-classes&quot;&gt;&lt;strong&gt;Multi-value callbacks: Wrapper classes&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;When a callback delivers multiple values, you need a container to return them from a single suspend function. The approach is straightforward: define a data class that bundles the values.&lt;/p&gt;



&lt;p&gt;Looking at RevenueCat’s&amp;nbsp;&lt;code&gt;PurchaseResult&lt;/code&gt;:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Zps5I3 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Poko\nclass PurchaseResult(\n    val storeTransaction: StoreTransaction,\n    val customerInfo: CustomerInfo,\n)&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The suspend bridge then constructs this wrapper in the success path:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-A4Fk9 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@JvmSynthetic\n@Throws(PurchasesTransactionException::class)\nsuspend fun Purchases.awaitPurchase(purchaseParams: PurchaseParams): PurchaseResult {\n    return suspendCancellableCoroutine { continuation -&gt;\n        purchase(\n            purchaseParams = purchaseParams,\n            callback = purchaseCompletedCallback(\n                onSuccess = { storeTransaction, customerInfo -&gt;\n                    continuation.resume(PurchaseResult(storeTransaction, customerInfo))\n                },\n                onError = { purchasesError, userCancelled -&gt;\n                    continuation.resumeWithException(\n                        PurchasesTransactionException(purchasesError, userCancelled)\n                    )\n                },\n            ),\n        )\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Two things are worth noting here. First, the success path wraps both values into a&amp;nbsp;&lt;code&gt;PurchaseResult&lt;/code&gt;&amp;nbsp;so the caller gets a single typed return value. Second, the error path uses&amp;nbsp;&lt;code&gt;PurchasesTransactionException&lt;/code&gt;&amp;nbsp;instead of the regular&amp;nbsp;&lt;code&gt;PurchasesException&lt;/code&gt;. This is because the error callback carries an extra&amp;nbsp;&lt;code&gt;userCancelled&lt;/code&gt;&amp;nbsp;boolean that callers need to distinguish user initiated cancellation from actual errors. The exception hierarchy preserves this information.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;exception-hierarchies-preserving-error-semantics&quot;&gt;&lt;strong&gt;Exception hierarchies: Preserving error semantics&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;A common mistake when bridging callbacks to coroutines is losing error information. Wrapping every error in a generic&amp;nbsp;&lt;code&gt;Exception(message)&lt;/code&gt;&amp;nbsp;throws away the structured error code that callers need for programmatic error handling.&lt;/p&gt;



&lt;p&gt;Looking at RevenueCat’s exception design:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1YYNT9 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;open class PurchasesException internal constructor(\n    val error: PurchasesError,\n    internal val overridenMessage: String? = null,\n) : Exception() {\n\n    val code: PurchasesErrorCode\n        get() = error.code\n\n    val underlyingErrorMessage: String?\n        get() = error.underlyingErrorMessage\n\n    override val message: String\n        get() = overridenMessage ?: error.message\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The exception wraps the original&amp;nbsp;&lt;code&gt;PurchasesError&lt;/code&gt;&amp;nbsp;object, preserving the typed&amp;nbsp;&lt;code&gt;PurchasesErrorCode&lt;/code&gt;&amp;nbsp;enum. Callers can use a&amp;nbsp;&lt;code&gt;when&lt;/code&gt;&amp;nbsp;expression on the code to handle specific error conditions:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1uyyf3 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;try {\n    val offerings = Purchases.sharedInstance.awaitOfferings()\n    showPaywall(offerings)\n} catch (e: PurchasesException) {\n    when (e.code) {\n        PurchasesErrorCode.NetworkError -&gt; showRetryDialog()\n        PurchasesErrorCode.StoreProblemError -&gt; showStoreErrorMessage()\n        else -&gt; showGenericError(e.message)\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The transaction exception extends this with the cancellation flag:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-19v5LP wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;class PurchasesTransactionException(\n    purchasesError: PurchasesError,\n    val userCancelled: Boolean,\n) : PurchasesException(purchasesError)&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This hierarchy means callers can catch&amp;nbsp;&lt;code&gt;PurchasesException&lt;/code&gt;&amp;nbsp;for all errors, or catch&amp;nbsp;&lt;code&gt;PurchasesTransactionException&lt;/code&gt;&amp;nbsp;specifically for purchase errors where they need to check whether the user cancelled. The&amp;nbsp;&lt;code&gt;is&lt;/code&gt;&amp;nbsp;check works naturally:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z2tAT4s wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;try {\n    val result = Purchases.sharedInstance.awaitPurchase(params)\n    grantEntitlement(result.customerInfo)\n} catch (e: PurchasesTransactionException) {\n    if (e.userCancelled) {\n        \/\/ User tapped back or dismissed the sheet. Not an error.\n        return\n    }\n    showPurchaseError(e.message)\n} catch (e: PurchasesException) {\n    showGenericError(e.message)\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The key observation: the exception hierarchy mirrors the callback signature shapes. A callback with&amp;nbsp;&lt;code&gt;(error)&lt;/code&gt;&amp;nbsp;maps to&amp;nbsp;&lt;code&gt;PurchasesException&lt;/code&gt;. A callback with&amp;nbsp;&lt;code&gt;(error, userCancelled)&lt;/code&gt;&amp;nbsp;maps to&amp;nbsp;&lt;code&gt;PurchasesTransactionException&lt;/code&gt;. This is not accidental. It is a deliberate design that makes the suspend API as expressive as the callback API.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;the-resultlesstgreater-variant-exceptions-are-not-always-what-you-want&quot;&gt;&lt;strong&gt;The&amp;nbsp;&lt;code&gt;Result&amp;lt;T&amp;gt;&lt;/code&gt;&amp;nbsp;variant: Exceptions are not always what you want&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Not every caller wants to use try/catch. Some prefer&amp;nbsp;&lt;code&gt;kotlin.Result&amp;lt;T&amp;gt;&lt;/code&gt;&amp;nbsp;for composable error handling. RevenueCat provides a second variant for every suspend bridge:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1hpsfP wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@JvmSynthetic\nsuspend fun Purchases.awaitOfferingsResult(): Result&lt;Offerings&gt; =\n    suspendCancellableCoroutine { continuation -&gt;\n        getOfferingsWith(\n            onSuccess = { continuation.resume(Result.success(it)) },\n            onError = { continuation.resume(Result.failure(PurchasesException(it))) },\n        )\n    }&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The key difference: the error path calls&amp;nbsp;&lt;code&gt;continuation.resume(Result.failure(...))&lt;/code&gt;&amp;nbsp;instead of&amp;nbsp;&lt;code&gt;continuation.resumeWithException(...)&lt;/code&gt;. From the coroutine’s perspective, the function always completes successfully. It returns a&amp;nbsp;&lt;code&gt;Result&lt;/code&gt;&amp;nbsp;that the caller unwraps:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1ltwJx wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;val result = Purchases.sharedInstance.awaitOfferingsResult()\nresult.fold(\n    onSuccess = { offerings -&gt; showPaywall(offerings) },\n    onFailure = { error -&gt; showError(error.message) },\n)&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This pattern is useful in pipelines where you want to chain operations without try/catch blocks:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1grRYH wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;suspend fun loadPaywallData(): Result&lt;PaywallData&gt; {\n    return Purchases.sharedInstance.awaitOfferingsResult()\n        .mapCatching { offerings -&gt;\n            val currentOffering = offerings.current\n                ?: throw IllegalStateException(\&amp;quot;No current offering\&amp;quot;)\n            PaywallData(currentOffering)\n        }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The purchase&amp;nbsp;&lt;code&gt;Result&lt;/code&gt;&amp;nbsp;variant follows the same pattern:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZNTXgz wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;suspend fun Purchases.awaitPurchaseResult(\n    purchaseParams: PurchaseParams\n): Result&lt;PurchaseResult&gt; {\n    return suspendCancellableCoroutine { continuation -&gt;\n        purchase(\n            purchaseParams = purchaseParams,\n            callback = purchaseCompletedCallback(\n                onSuccess = { storeTransaction, customerInfo -&gt;\n                    continuation.resume(\n                        Result.success(PurchaseResult(storeTransaction, customerInfo))\n                    )\n                },\n                onError = { purchasesError, userCancelled -&gt;\n                    continuation.resume(\n                        Result.failure(\n                            PurchasesTransactionException(purchasesError, userCancelled)\n                        )\n                    )\n                },\n            ),\n        )\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The error information is not lost. The&amp;nbsp;&lt;code&gt;PurchasesTransactionException&lt;/code&gt;&amp;nbsp;is still inside the&amp;nbsp;&lt;code&gt;Result.failure&lt;/code&gt;, so callers who need the&amp;nbsp;&lt;code&gt;userCancelled&lt;/code&gt;&amp;nbsp;flag can check it:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-2m3CN1 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;val result = Purchases.sharedInstance.awaitPurchaseResult(params)\nresult.onFailure { error -&gt;\n    if (error is PurchasesTransactionException &amp;amp;&amp;amp; error.userCancelled) {\n        return\n    }\n    showError(error.message)\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This dual API approach, throwing suspend functions and&amp;nbsp;&lt;code&gt;Result&lt;/code&gt;&amp;nbsp;returning suspend functions, gives consumers the choice without forcing one style. The SDK does not pick winners. It supports both.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;the-lambda-convenience-layer-bridging-before-the-bridge&quot;&gt;&lt;strong&gt;The lambda convenience layer: Bridging before the bridge&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;There is a middle layer between the raw callback interface API and the suspend bridge that is worth examining. RevenueCat provides extension functions that accept lambda pairs instead of typed callback objects:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1fKmN1 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;fun Purchases.getOfferingsWith(\n    onError: (error: PurchasesError) -&gt; Unit = ON_ERROR_STUB,\n    onSuccess: (offerings: Offerings) -&gt; Unit,\n) {\n    getOfferings(receiveOfferingsCallback(onSuccess, onError))\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This is a two step bridge design. The lambda extension (&lt;code&gt;getOfferingsWith&lt;/code&gt;) converts lambdas to a typed callback. The suspend extension (&lt;code&gt;awaitOfferings&lt;/code&gt;) converts the lambda extension to a coroutine. Each layer does one thing.&lt;/p&gt;



&lt;p&gt;Notice the default error handler:&lt;/p&gt;



&lt;pre class=&quot;wp-block-code&quot;&gt;&lt;code&gt;internal val ON_ERROR_STUB: (error: PurchasesError) -&amp;gt; Unit = {}
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;This allows callers who do not care about errors to omit the error handler. This is useful for fire and forget operations, but should be used carefully since silently swallowing errors is a common source of bugs.&lt;/p&gt;



&lt;p&gt;The purchase version has its own stub:&lt;/p&gt;



&lt;pre class=&quot;wp-block-code&quot;&gt;&lt;code&gt;internal val ON_PURCHASE_ERROR_STUB: (error: PurchasesError, userCancelled: Boolean) -&amp;gt; Unit =
    { _, _ -&amp;gt; }
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Two separate stubs for two different callback shapes. Each matches the exact lambda signature its callback requires.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;real-world-application-bridging-google-play-billing-directly&quot;&gt;&lt;strong&gt;Real-world application: Bridging Google Play Billing directly&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The same&amp;nbsp;&lt;code&gt;suspendCancellableCoroutine&lt;/code&gt;&amp;nbsp;pattern applies to any callback based Android API. Here is how you would bridge Google Play Billing’s acknowledgment API:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-JCH2J wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;suspend fun BillingClient.awaitAcknowledge(purchaseToken: String): Boolean {\n    return suspendCancellableCoroutine { continuation -&gt;\n        val params = AcknowledgePurchaseParams.newBuilder()\n            .setPurchaseToken(purchaseToken)\n            .build()\n        acknowledgePurchase(params) { billingResult -&gt;\n            continuation.resume(\n                billingResult.responseCode == BillingClient.BillingResponseCode.OK\n            )\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;And the consume API follows the same structure:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z2ehRCQ wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;suspend fun BillingClient.awaitConsume(purchaseToken: String): Boolean {\n    return suspendCancellableCoroutine { continuation -&gt;\n        val params = ConsumeParams.newBuilder()\n            .setPurchaseToken(purchaseToken)\n            .build()\n        consumeAsync(params) { billingResult, _ -&gt;\n            continuation.resume(\n                billingResult.responseCode == BillingClient.BillingResponseCode.OK\n            )\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Even the billing client connection, which has two separate callback methods (&lt;code&gt;onBillingSetupFinished&lt;/code&gt;&amp;nbsp;and&amp;nbsp;&lt;code&gt;onBillingServiceDisconnected&lt;/code&gt;), bridges cleanly:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z2cF9aP wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;suspend fun BillingClient.awaitConnect(): Boolean {\n    if (isReady) return true\n    return suspendCancellableCoroutine { continuation -&gt;\n        startConnection(object : BillingClientStateListener {\n            override fun onBillingSetupFinished(billingResult: BillingResult) {\n                continuation.resume(\n                    billingResult.responseCode == BillingClient.BillingResponseCode.OK\n                )\n            }\n\n            override fun onBillingServiceDisconnected() {\n                \/\/ Called when connection is lost after setup, not during setup.\n                \/\/ The continuation has already been resumed by onBillingSetupFinished.\n            }\n        })\n        continuation.invokeOnCancellation { endConnection() }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The&amp;nbsp;&lt;code&gt;onBillingServiceDisconnected&lt;/code&gt;&amp;nbsp;method is called after a successful setup when the connection is later lost, not as an alternative to&amp;nbsp;&lt;code&gt;onBillingSetupFinished&lt;/code&gt;&amp;nbsp;during the initial connection. This is an important subtlety. If both methods could fire during setup, you would need additional state tracking to ensure exactly one resume call.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-suspendcancellablecoroutine-is-always-the-right-default&quot;&gt;&lt;strong&gt;Why&amp;nbsp;&lt;code&gt;suspendCancellableCoroutine&lt;/code&gt;&amp;nbsp;is always the right default&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The earlier rule — “do not use&amp;nbsp;&lt;code&gt;suspendCoroutine&lt;/code&gt;&amp;nbsp;in application or library code” — deserves its own section, because it’s easy to look at the two function names and assume they are equally valid tools for different jobs. They are not.&amp;nbsp;&lt;code&gt;suspendCoroutine&lt;/code&gt;&amp;nbsp;is a low level primitive whose semantics predate the structured concurrency model we actually build on today, and its behavior is fundamentally incompatible with cancellation.&lt;/p&gt;



&lt;p&gt;Here is what actually happens when you call&amp;nbsp;&lt;code&gt;suspendCoroutine&lt;/code&gt;&amp;nbsp;inside a cancellable scope. The continuation you receive is a plain&amp;nbsp;&lt;code&gt;Continuation&amp;lt;T&amp;gt;&lt;/code&gt;. It has no knowledge of the&amp;nbsp;&lt;code&gt;Job&lt;/code&gt;&amp;nbsp;that invoked it. When the parent&amp;nbsp;&lt;code&gt;Job&lt;/code&gt;&amp;nbsp;is cancelled — because a&amp;nbsp;&lt;code&gt;ViewModel&lt;/code&gt;&amp;nbsp;is cleared, a&amp;nbsp;&lt;code&gt;LaunchedEffect&lt;/code&gt;&amp;nbsp;leaves composition, a&amp;nbsp;&lt;code&gt;coroutineScope { }&lt;/code&gt;&amp;nbsp;block throws, or the user navigates away — the cancellation signal travels to every child that participates in structured concurrency. Your&amp;nbsp;&lt;code&gt;suspendCoroutine&lt;/code&gt;&amp;nbsp;leaf does not participate. It cannot be cancelled, so&amp;nbsp;&lt;code&gt;Job.cancelAndJoin()&lt;/code&gt;&amp;nbsp;cannot complete, sibling failures cannot propagate past it, and the entire scope is held open waiting for a callback that may never fire.&lt;/p&gt;



&lt;p&gt;The practical consequences are the ones you would expect from a leak:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;The continuation retains the calling coroutine’s context, including references to lifecycle-scoped objects like&amp;nbsp;&lt;code&gt;ViewModel&lt;/code&gt;s,&amp;nbsp;&lt;code&gt;Activity&lt;/code&gt;s, or&amp;nbsp;&lt;code&gt;Composer&lt;/code&gt;s. Those objects can no longer be garbage collected.&lt;/li&gt;



&lt;li&gt;Any resource registered in the surrounding scope — a database session, a Bluetooth GATT handle, an open socket — stays alive until the callback eventually comes back.&lt;/li&gt;



&lt;li&gt;Exceptions in sibling coroutines cannot be delivered in a timely way; the scope can’t finish cancelling its other children while the leaf is stuck, so failures silently disappear or surface seconds (or hours) later, detached from their cause.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;code&gt;suspendCancellableCoroutine&lt;/code&gt;&amp;nbsp;is the fix, and it is the fix even when the underlying callback based API has no native cancellation to hook into. Its continuation participates in the coroutine’s&amp;nbsp;&lt;code&gt;Job&lt;/code&gt;&amp;nbsp;graph: cancellation of the parent immediately resumes the continuation with a&amp;nbsp;&lt;code&gt;CancellationException&lt;/code&gt;, the leaf tears down, the scope unwinds, and references are released. The underlying callback can still fire later — you just ignore it, because&amp;nbsp;&lt;code&gt;CancellableContinuation.resume&lt;/code&gt;&amp;nbsp;on an already-cancelled continuation is a safe no-op. The in-flight network request or SDK call keeps running to completion on its own, but it no longer holds your coroutine hostage.&lt;/p&gt;



&lt;p&gt;The upgrade from&amp;nbsp;&lt;code&gt;suspendCoroutine&lt;/code&gt;&amp;nbsp;to&amp;nbsp;&lt;code&gt;suspendCancellableCoroutine&lt;/code&gt;&amp;nbsp;is almost always free. For callbacks you have no control over, the change is a single-word rename:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1G5QXh wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/\/ Before: structured concurrency hole\nsuspend fun Purchases.awaitOfferings(): Offerings = suspendCoroutine { continuation -&gt;\n    getOfferingsWith(\n        onSuccess = continuation::resume,\n        onError = { continuation.resumeWithException(PurchasesException(it)) },\n    )\n}\n\n\/\/ After: cancellation-safe\nsuspend fun Purchases.awaitOfferings(): Offerings = suspendCancellableCoroutine { continuation -&gt;\n    getOfferingsWith(\n        onSuccess = continuation::resume,\n        onError = { continuation.resumeWithException(PurchasesException(it)) },\n    )\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;For callbacks whose underlying operation can be cancelled or whose resources should be released eagerly, add&amp;nbsp;&lt;code&gt;invokeOnCancellation&lt;/code&gt;&amp;nbsp;for cleanup:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z3AMDB wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;suspend fun BillingClient.awaitConnect(): Boolean {\n    if (isReady) return true\n    return suspendCancellableCoroutine { continuation -&gt;\n        startConnection(object : BillingClientStateListener {\n            override fun onBillingSetupFinished(billingResult: BillingResult) {\n                continuation.resume(\n                    billingResult.responseCode == BillingClient.BillingResponseCode.OK\n                )\n            }\n\n            override fun onBillingServiceDisconnected() {}\n        })\n        continuation.invokeOnCancellation { endConnection() }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;That’s it. You get correctness at no complexity cost. There is no category of “short lived, non cancellable” callback where&amp;nbsp;&lt;code&gt;suspendCoroutine&lt;/code&gt;&amp;nbsp;is the pragmatic choice — short lived operations still need to honor cancellation, because the thing that is actually short lived is only short lived&amp;nbsp;&lt;em&gt;on average&lt;/em&gt;. Network calls stall. App processes freeze mid request. An SDK callback that “always fires quickly” has a long tail of cases where it doesn’t, and those are exactly the cases where a leaked scope matters most.&lt;/p&gt;



&lt;p&gt;Treat&amp;nbsp;&lt;code&gt;suspendCoroutine&lt;/code&gt;&amp;nbsp;as a platform primitive that exists mainly so that&amp;nbsp;&lt;code&gt;suspendCancellableCoroutine&lt;/code&gt;&amp;nbsp;can be built on top of it. In the code you write, always reach for&amp;nbsp;&lt;code&gt;suspendCancellableCoroutine&lt;/code&gt;.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;applying-the-pattern-beyond-billing&quot;&gt;&lt;strong&gt;Applying the pattern beyond billing&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The bridge pattern is not limited to billing APIs. The same approach works for any callback based Android API. A few examples:&lt;/p&gt;



&lt;p&gt;For FusedLocationProviderClient, which delivers location through&amp;nbsp;&lt;code&gt;LocationCallback&lt;/code&gt;:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1izfX7 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;suspend fun FusedLocationProviderClient.awaitLastLocation(): Location? {\n    return suspendCancellableCoroutine { continuation -&gt;\n        lastLocation\n            .addOnSuccessListener { location -&gt; continuation.resume(location) }\n            .addOnFailureListener { e -&gt; continuation.resumeWithException(e) }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The Google Tasks API doesn’t expose a cancellation hook on&amp;nbsp;&lt;code&gt;lastLocation&lt;/code&gt;, but the bridge still uses&amp;nbsp;&lt;code&gt;suspendCancellableCoroutine&lt;/code&gt;: when the caller’s scope is cancelled, the continuation tears down immediately and the in-flight Task is left to complete on its own — its eventual callback simply finds an already-cancelled continuation and is a no-op.&lt;/p&gt;



&lt;p&gt;For SharedPreferences, which uses&amp;nbsp;&lt;code&gt;OnSharedPreferenceChangeListener&lt;/code&gt;&amp;nbsp;for change notifications:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-pAG11 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;suspend fun SharedPreferences.awaitChange(key: String): String? {\n    return suspendCancellableCoroutine { continuation -&gt;\n        val listener = SharedPreferences.OnSharedPreferenceChangeListener { prefs, changedKey -&gt;\n            if (changedKey == key) {\n                continuation.resume(prefs.getString(key, null))\n            }\n        }\n        registerOnSharedPreferenceChangeListener(listener)\n        continuation.invokeOnCancellation {\n            unregisterOnSharedPreferenceChangeListener(listener)\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The common structure is always the same: wrap with&amp;nbsp;&lt;code&gt;suspendCancellableCoroutine&lt;/code&gt;, register the callback, resume when the callback fires. What changes is the callback shape, how many values you need to capture, and whether cancellation cleanup is needed.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;common-mistakes-to-avoid&quot;&gt;&lt;strong&gt;Common mistakes to avoid&lt;/strong&gt;&lt;/h2&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;resuming-zero-times&quot;&gt;&lt;strong&gt;Resuming zero times&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;If there is a code path where the callback never fires, the coroutine suspends forever. This is especially common with connection listeners that have multiple callback methods:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1xdAHK wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/\/ Dangerous: if onBillingServiceDisconnected fires before onBillingSetupFinished,\n\/\/ the coroutine never resumes\nsuspend fun BillingClient.awaitConnectBroken(): Boolean {\n    return suspendCancellableCoroutine { continuation -&gt;\n        startConnection(object : BillingClientStateListener {\n            override fun onBillingSetupFinished(billingResult: BillingResult) {\n                continuation.resume(true)\n            }\n\n            override fun onBillingServiceDisconnected() {\n                \/\/ Bug: in rare edge cases this might fire first,\n                \/\/ and onBillingSetupFinished never fires\n            }\n        })\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Using&amp;nbsp;&lt;code&gt;suspendCancellableCoroutine&lt;/code&gt;&amp;nbsp;here means a parent-scope cancellation can still tear the coroutine down, but if no cancellation arrives the bridge is still wedged forever waiting on a callback that never came. The right primitive doesn’t save you from a missing resume path.&lt;/p&gt;



&lt;p&gt;The fix is to ensure every callback path reaches a resume call, or use&amp;nbsp;&lt;code&gt;suspendCancellableCoroutine&lt;/code&gt;&amp;nbsp;with a timeout:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1kghsu wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;suspend fun BillingClient.awaitConnectSafe(): Boolean {\n    return withTimeout(5_000) {\n        suspendCancellableCoroutine { continuation -&gt;\n            startConnection(object : BillingClientStateListener {\n                override fun onBillingSetupFinished(billingResult: BillingResult) {\n                    if (continuation.isActive) {\n                        continuation.resume(\n                            billingResult.responseCode == BillingClient.BillingResponseCode.OK\n                        )\n                    }\n                }\n\n                override fun onBillingServiceDisconnected() {\n                    if (continuation.isActive) {\n                        continuation.resume(false)\n                    }\n                }\n            })\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;resuming-twice&quot;&gt;&lt;strong&gt;Resuming twice&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;If a callback can fire multiple times (like a location listener that delivers updates continuously), the suspend bridge is the wrong tool entirely. Each call to&amp;nbsp;&lt;code&gt;resume&lt;/code&gt;&amp;nbsp;after the first throws&amp;nbsp;&lt;code&gt;IllegalStateException&lt;/code&gt;, regardless of whether you used&amp;nbsp;&lt;code&gt;suspendCoroutine&lt;/code&gt;&amp;nbsp;or&amp;nbsp;&lt;code&gt;suspendCancellableCoroutine&lt;/code&gt;. For repeating callbacks, use&amp;nbsp;&lt;code&gt;callbackFlow&lt;/code&gt;&amp;nbsp;instead:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-2kqP7T wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;fun FusedLocationProviderClient.locationUpdates(\n    request: LocationRequest\n): Flow&lt;Location&gt; = callbackFlow {\n    val callback = object : LocationCallback() {\n        override fun onLocationResult(result: LocationResult) {\n            result.lastLocation?.let { trySend(it) }\n        }\n    }\n    requestLocationUpdates(request, callback, Looper.getMainLooper())\n    awaitClose { removeLocationUpdates(callback) }\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;&lt;code&gt;suspendCancellableCoroutine&lt;/code&gt;&amp;nbsp;is for one shot callbacks.&amp;nbsp;&lt;code&gt;callbackFlow&lt;/code&gt;&amp;nbsp;is for streaming callbacks. Choosing the wrong primitive leads to crashes or hangs.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;losing-error-type-information&quot;&gt;&lt;strong&gt;Losing error type information&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Wrapping all errors as&amp;nbsp;&lt;code&gt;Exception(error.message)&lt;/code&gt;&amp;nbsp;strips away the structured error data callers need:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZVnN4q wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/\/ Bad: caller cannot programmatically distinguish error types\nonError = { error -&gt;\n    continuation.resumeWithException(Exception(error.message))\n}\n\n\/\/ Good: caller can match on error code\nonError = { error -&gt;\n    continuation.resumeWithException(PurchasesException(error))\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The extra work of defining a typed exception class pays for itself every time a caller needs to handle specific error conditions differently.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;conclusion&quot;&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;In this article, you’ve explored the&amp;nbsp;&lt;code&gt;suspendCancellableCoroutine&lt;/code&gt;&amp;nbsp;bridge pattern from its simplest form, a single value callback, through the production patterns used in RevenueCat’s Android SDK: multi value wrapper classes, typed exception hierarchies, callback factory functions, and dual API styles with both throwing and&amp;nbsp;&lt;code&gt;Result&lt;/code&gt;&amp;nbsp;returning variants. The pattern is always the same three steps: suspend the coroutine, register the callback, and resume exactly once. And it always uses&amp;nbsp;&lt;code&gt;suspendCancellableCoroutine&lt;/code&gt;, never the older&amp;nbsp;&lt;code&gt;suspendCoroutine&lt;/code&gt;, so every leaf in your coroutine tree honors structured concurrency.&lt;/p&gt;



&lt;p&gt;Understanding this bridge is practical knowledge for any Android developer. Most of the platform APIs you use daily, billing, location, Bluetooth, camera, were designed around callbacks. Converting them to suspend functions makes your code sequential, testable, and composable. The patterns covered here, especially the callback factory layer, the typed exception hierarchy, and the&amp;nbsp;&lt;code&gt;Result&amp;lt;T&amp;gt;&lt;/code&gt;&amp;nbsp;variant, are directly reusable in your own projects.&lt;/p&gt;



&lt;p&gt;Whether you’re bridging Google Play Billing’s&amp;nbsp;&lt;code&gt;PurchasesUpdatedListener&lt;/code&gt;, wrapping a legacy networking library, or building a suspend friendly API for your own SDK, these patterns provide the foundation for clean, correct coroutine integration on Android.&lt;/p&gt;



&lt;p&gt;As always, happy coding!&lt;/p&gt;



&lt;p&gt;— &lt;a href=&quot;https://github.com/skydoves/&quot;&gt;Jaewoong (skydoves)&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[AI features are eroding your subscription app’s margins — here’s how to fix it]]></title><description><![CDATA[On the hidden cost of AI features, and why you should treat AI usage like paid media spend]]></description><link>https://www.revenuecat.com/blog/growth/ai-feature-cost-subscription-app-margins/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/ai-feature-cost-subscription-app-margins/</guid><pubDate>Thu, 26 Mar 2026 13:16:10 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Your-AI-feature-is-probably-destroying-margin.png" length="0" type="image/*"/><content:encoded>&lt;p id=&quot;h-right-now-many-subscription-apps-are-adding-ai-features-as-quickly-as-possible-and-it-s-working-the-product-demo-looks-impressive-engagement-spikes-the-feature-quickly-becomes-central-to-the-app-and-user-experience-but-something-else-starts-happening-underneath-the-surface-with-every-generation-every-prompt-and-every-generate-again-button-click-the-cost-of-serving-your-users-is-quietly-but-rapidly-increasing&quot;&gt;Right now, many subscription apps are adding AI features as quickly as possible. And it’s working — the product demo looks impressive, engagement spikes, the feature quickly becomes central to the app and user experience. But something else starts happening underneath the surface. With every generation, every prompt, and every “generate again” button click, the cost of serving your users is quietly (but rapidly) increasing.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Working with several AI-powered subscription apps recently, I started noticing this pattern. The very behavior you are trying to encourage — more usage, more exploration, more interaction — can now compress your margins if monetization and infrastructure are not designed in tandem.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;AI is not just another product feature. It is &lt;em&gt;infrastructure&lt;/em&gt;. So if you’re not modeling AI usage against ARPU, churn, and LTV before you ship it, you may be &lt;strong&gt;increasing engagement while quietly destroying your economics&lt;/strong&gt;.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-user-engagement-isn-t-free-anymore&quot;&gt;User engagement isn’t free anymore&lt;/h2&gt;



&lt;p&gt;Subscription businesses are structurally efficient. Or they used to be. Once you’ve built the core product experience, the marginal cost of serving an additional subscriber inside the app is typically close to zero, and the economics compound as you scale. (Thomas Petit talks about this in his blog on &lt;a href=&quot;https://www.revenuecat.com/blog/growth/ai-hybrid-monetization/#h-why-now-the-variable-cost-of-ai-is-an-ignition-towards-hybrid-monetization&quot;&gt;&lt;em&gt;why hybrid monetization should now be the default for subscription apps&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;)&lt;/p&gt;



&lt;p&gt;AI, on the other hand, disrupts that elegance. By introducing AI-powered features, &lt;strong&gt;you introduce variable cost at the feature level&lt;/strong&gt;. Every time a user triggers an AI interaction, tokens are consumed, inference endpoints are called, and a third-party provider bills you for compute (the hardware resources used to make AI models work).&lt;/p&gt;



&lt;p&gt;In short, your cost structure becomes inextricably linked to usage.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;This creates a subtle but important tension — the same engagement you’ve worked so hard to increase now &lt;strong&gt;drives incremental cost&lt;/strong&gt;. Higher engagement increases AI calls → more AI calls increase infrastructure spend. And unless revenue expands proportionally, your gross margin begins to shrink.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-5-ways-to-reduce-ai-spend-in-your-app&quot;&gt;5 Ways to reduce AI spend in your app&lt;/h2&gt;



&lt;p&gt;So what does this mean? AI features are inherently a margin shrinker? No, not quite. AI means subscription businesses need to think more like cloud infrastructure businesses. Meaning usage is no longer just a growth metric, but also a cost driver.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-apps-should-buy-ai-infrastructure-rather-than-build-it&quot;&gt;1. Apps should buy AI infrastructure, rather than build it&lt;/h3&gt;



&lt;p&gt;I recently spoke with a portfolio Ops Manager working across several AI products and they described a familiar problem — the music generation API powering one of their apps became unstable, and suddenly even paying users couldn’t access the core feature. Complaints rose, reviews worsened, and monetization performance became harder to interpret.&lt;/p&gt;



&lt;p&gt;This is what makes AI different from traditional app features. The question isn’t just whether users &lt;em&gt;want&lt;/em&gt; the feature, it’s whether your infrastructure can deliver it reliably enough to support retention and revenue (without breaking your economics).&lt;/p&gt;



&lt;p&gt;This is why I’d generally encourage thinking carefully about the infrastructure you choose. Training large datasets or creating your own models can make sense if you’re running a large-scale AI platform, but most subscription apps are far better served by using third-party APIs (e.g. Open AI’s ChatGPT, Google’s Gemini, Anthropic’s Claude) — particularly if you’re still experimenting with monetization and feature or &lt;a href=&quot;https://www.revenuecat.com/blog/growth/product-market-fit-subscription-apps/&quot;&gt;product-market fit&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;Running your own models introduces a number of challenges:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;GPU overhead&lt;/li&gt;



&lt;li&gt;DevOps complexity&lt;/li&gt;



&lt;li&gt;Model maintenance risk&lt;/li&gt;



&lt;li&gt;Fixed monthly burn (regardless of usage)&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;It’s a dangerous position to be in. So for many growth-stage subscription apps, using API-based foundation models makes more sense:&amp;nbsp;&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Paying per token converts AI into a variable cost that scales with actual usage&lt;/li&gt;



&lt;li&gt;If a feature fails to move install-to-paid conversion, trial starts, ARPU, or retention, you can shut it down and your cost disappears with it&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;TL;DR: Variable cost preserves strategic agility. Fixed infrastructure locks you into experiments that may not justify themselves.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-treat-ai-usage-like-paid-media-spend&quot;&gt;2. Treat AI usage like paid media spend&lt;/h3&gt;



&lt;p&gt;Subscription teams are usually obsessive about acquisition cost. They track CAC, payback periods, and &lt;a href=&quot;http://revenuecat.com/blog/growth/creative-fatigue-mobile-apps-roas&quot;&gt;ROAS&lt;/a&gt; down to the decimal. But many of the same teams treat AI usage casually, even though &lt;strong&gt;AI tokens are just another form of spend&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;Every time a user triggers an AI feature, you pay for it. The longer the prompt, the longer the response, and the more often users hit ‘regenerate’, the higher your cost becomes. Think of it the same way you think about paid ads: every impression costs money, every click costs money. AI works the same way — every request has a price.&lt;/p&gt;



&lt;p&gt;One AI team I spoke with saw this effect immediately when they changed their credit system. They moved from a restrictive daily allowance to a flexible monthly pool. Generation volume increased overnight. Some users burned through a large portion of their credits on the first day. The feature hadn’t changed, the &lt;strong&gt;usage constraints&lt;/strong&gt; had. And with AI products, &lt;strong&gt;usage constraints directly affect infrastructure cost.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Smart teams design AI features with cost in mind. They limit how long responses can be, and avoid unnecessary explanations from the model unless the user actually needs them. Small decisions here matter more than you think. For example, asking an AI model to write a 600-word explanation is far more expensive than asking it to return a structured, 30-word answer.&lt;/p&gt;



&lt;p&gt;At scale, those choices can significantly reduce AI costs. Across millions of requests, that is not a small optimization. &lt;strong&gt;It is a meaningful gross margin lever.&lt;/strong&gt;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-use-the-cheapest-ai-model-that-gets-the-job-done&quot;&gt;3. Use the cheapest AI model that gets the job done&lt;/h3&gt;



&lt;p&gt;Another common cost leak is sending every AI request to the most powerful model available. It feels safe. Teams assume the best model will produce the best experience. But in many cases, it just produces the highest bill.&lt;/p&gt;



&lt;p&gt;Not every task requires a powerful model. Many AI features are doing relatively simple work; things like tagging content, formatting text, summarizing information, or generating short outputs. Smaller, cheaper models can handle these tasks perfectly well and deliver the same user satisfaction. Users won’t be able to tell the difference between a premium and mid-tier model, but your infrastructure bill will definitely show it.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Reserve expensive models for complex work that genuinely requires deeper reasoning, and use cheaper models for everything else.&lt;/strong&gt; Choosing the right model for each task is one of the highest-leverage cost optimizations available to AI-powered apps.&lt;/p&gt;


&lt;div class=&quot;lazyblock-dd0db17b8671-Z10Ar8h wp-block-lazyblock-dd0db17b8671&quot;&gt;&lt;blogpostpodcastcta title=&quot; 12 AI Growth Lessons for Subscription Apps&quot; description=&quot;Phil Carter (Elemental Growth) explains why the speed and cost-efficiency of smaller models outweigh the benefits of newer models. Plus 11 other lessons for growing your app with AI.&quot; links=&quot;[{&amp;quot;link-title&amp;quot;:&amp;quot;YouTube&amp;quot;,&amp;quot;link-url&amp;quot;:&amp;quot;https:\/\/www.youtube.com\/watch?v=UYIgu02h8cs&amp;quot;,&amp;quot;link-image&amp;quot;:&amp;quot;youtube&amp;quot;},{&amp;quot;link-title&amp;quot;:&amp;quot;Spotify&amp;quot;,&amp;quot;link-url&amp;quot;:&amp;quot;https:\/\/open.spotify.com\/episode\/74hESsillo6m6vwenqQ7eb?si=3c54a5fb27b344f7&amp;quot;,&amp;quot;link-image&amp;quot;:&amp;quot;spotify&amp;quot;},{&amp;quot;link-title&amp;quot;:&amp;quot;Apple Podcasts&amp;quot;,&amp;quot;link-url&amp;quot;:&amp;quot;https:\/\/podcasts.apple.com\/us\/podcast\/feed\/id1538057974?ls=1&amp;quot;,&amp;quot;link-image&amp;quot;:&amp;quot;apple-podcasts&amp;quot;}]&quot;&gt;
&lt;/blogpostpodcastcta&gt;&lt;/div&gt;


&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-4-reuse-ai-results-instead-of-regenerating-them&quot;&gt;4. Reuse AI results instead of regenerating them&lt;/h3&gt;



&lt;p&gt;User behavior is more repetitive than most teams expect. Especially in productivity and utility apps, users tend to ask for the same kinds of things again and again. Similar prompts, similar transformations, similar workflows. If your app generates a brand new AI response every time, you may be paying repeatedly for answers that have already been generated. Similarly, users may ask something then come back another time and ask again, rather than scrolling back to find the original conversation.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;These are prime times to &lt;strong&gt;reuse results whenever possible&lt;/strong&gt;: save common outputs, store reusable templates, and pre-generate responses for frequent requests so they can be served instantly instead of regenerated. Even small improvements here can have a big impact. If you can reuse results for just 20% of requests, your AI costs can drop significantly.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-5-gate-ai-features-behind-monetization&quot;&gt;5. Gate AI features behind monetization&lt;/h3&gt;



&lt;p&gt;We’re already seeing a pattern of apps limiting AI usage in their free tier and gating advanced capabilities behind subscription plans — typically spread across pricing tiers to reflect compute cost, as well. Changes like this are not shocking to users, but can make a big financial impact to you.&lt;/p&gt;



&lt;p&gt;Some apps even implement daily or monthly usage caps to prevent a small group of heavy users from driving disproportionate infrastructure cost. Consider a heavy AI user that costs you $0.15 per month, but later purchases an annual plan that generates $29.99; the economics are comfortable. But if that same user never converts and continues consuming AI indefinitely, the economics quietly deteriorate.&lt;/p&gt;



&lt;p&gt;One team I spoke with introduced a quota system in their AI-powered learning product. New users received an initial credit allowance, with additional usage unlocked through paid packages. Models like this understand that usage and cost are relative.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Another AI app team I worked with chose not to offer a traditional free trial, since trial users were able to generate large volumes of output, consume API cost, then churn before ever paying. Instead, the team tested a one-time credit allowance that let users evaluate the quality of the product without exposing the business to unlimited inference cost.&lt;/p&gt;



&lt;p&gt;The real risk with free AI credits is not simply that users use them. It’s that they use them before the product is good enough to make them convert. In that case, you’re funding churn, not activation.&lt;/p&gt;



&lt;p&gt;This is what makes &lt;a href=&quot;https://www.revenuecat.com/blog/growth/ai-subscription-app-pricing/&quot;&gt;AI monetization for subscription apps&lt;/a&gt; fundamentally different from traditional subscription packaging — you’re not just pricing access to value. Every change made to monetization or pricing and packaging affects a wider infrastructure economy. Usage and retention analysis are invaluable; work to understand who uses what, how often, and why, then revisit your P&amp;amp;P and compute costs hand-in-hand.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-unit-economics-of-ai&quot;&gt;The unit economics of AI&lt;/h2&gt;



&lt;p&gt;The whole conversation around AI’s hidden cost is difficult to quantify, though it’s easier if you already have your own AI features or app running, so let’s anchor it in familiar subscription metrics.&lt;/p&gt;



&lt;p&gt;Assume you have a subscription app with these stats:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Monthly &lt;a href=&quot;https://www.revenuecat.com/blog/growth/subscription-app-expand-value/&quot;&gt;ARPU&lt;/a&gt;: $6.00&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Normalized annual ARPU: $4.20&lt;/li&gt;



&lt;li&gt;Blended ARPU across the user base: $5.10&lt;/li&gt;



&lt;li&gt;Monthly churn: 5%&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Gross margin (before AI): 85%&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;You then introduce an AI feature. The average AI-active user makes 10 requests per month, each consuming 1,000 tokens. Each token costs you $0.002, making the cost per active AI user (and 1,000 tokens) $0.02.&lt;/p&gt;



&lt;p&gt;With 300,000 MAU and 15 percent AI engagement, you have 45,000 AI-active users. That results in a monthly AI cost of $900, or $10,800 annually. That is manageable.&lt;/p&gt;



&lt;p&gt;&lt;em&gt;Now&lt;/em&gt; imagine usage increases and routing shifts toward more expensive models. Cost per active AI user rises to $0.10 per month. With the same 45,000 AI-active users, monthly cost becomes $4,500, or $54,000 annually.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Whether or not that sounds like a lot depends on many factors. But ultimately, it depends on whether the AI feature increases LTV more than it increases cost per user. In other words…&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-is-the-ai-feature-worth-the-cost&quot;&gt;Is the AI feature worth the cost?&lt;/h3&gt;



&lt;p&gt;Suppose install-to-paid conversion is 4% across one million annual installs, producing 40,000 paying users. With an average LTV of $42, baseline annual subscription revenue is $1.68 million.&lt;/p&gt;



&lt;p&gt;If the AI feature increases install-to-paid conversion by just 0.5 percentage points, paid users rise to 45,000. That is 5,000 incremental subscribers, representing $210,000 in additional revenue.&lt;/p&gt;



&lt;p&gt;Against $54,000 in annual AI infrastructure cost, the feature generates far more revenue than it costs to run. Ergo, &lt;strong&gt;it’s worth the cost&lt;/strong&gt;.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;However, if conversion doesn’t move &lt;em&gt;enough &lt;/em&gt;and retention does not improve, &lt;strong&gt;you’re spending $54,000 to increase engagement metrics that do not affect revenue&lt;/strong&gt;. Gross margin declines, contribution margin per MAU shrinks, and the feature becomes an expensive distraction.&lt;/p&gt;



&lt;p&gt;This is how AI quietly kills subscription businesses.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-everyone-is-fixated-on-ai-but-no-one-is-fixing-retention&quot;&gt;Everyone is fixated on AI, but no one is fixing retention&lt;/h3&gt;



&lt;p&gt;Does this mean AI needs to increase conversion in order to justify its cost? Ideally, yes. But it can also improve retention.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;With monthly ARPU of $6 and churn of 5%, theoretical steady-state LTV is approximately $120. If AI reduces churn to 4.6%, LTV rises to roughly $130. That is a $10 increase per subscriber, and across 20,000 subscribers, that’s $200,000 in incremental value.&lt;/p&gt;



&lt;p&gt;Going back to the original figure, if AI costs $54,000 annually but produces even modest retention improvements (in the example, a 0.4% reduction), &lt;strong&gt;it can be one of the highest-return investments available&lt;/strong&gt;.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Before getting too excited and adding new AI features, it’s worth remembering that retention improvements need to be observed in cohort data, not inferred from engagement alone. The improvements from AI need to be &lt;em&gt;measurable&lt;/em&gt;.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-reading-ai-s-value-ai-cost-belongs-in-your-revenue-dashboard&quot;&gt;Reading AI’s value: AI cost belongs in your revenue dashboard&lt;/h2&gt;



&lt;p&gt;RevenueCat already gives you a clear view of the metrics that drive subscription performance: ARPU, churn, LTV, and cohort retention. That’s half of the puzzle. If your app includes AI features, you need to be analyzing your AI infrastructure costs alongside those metrics.&lt;/p&gt;



&lt;p&gt;In practice, this means combining your AI usage data with your subscription metrics to understand how usage affects margins.&lt;/p&gt;



&lt;p&gt;You should know things like:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;AI cost per MAU&lt;/li&gt;



&lt;li&gt;AI cost per AI-active user&lt;/li&gt;



&lt;li&gt;AI cost per paying user&lt;/li&gt;



&lt;li&gt;AI cost as a percentage of ARPU&lt;/li&gt;



&lt;li&gt;AI cost relative to blended ARPU&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Looking at these numbers next to your subscription metrics makes it much easier to understand whether AI is strengthening your business or quietly eroding your margins.&lt;/p&gt;



&lt;p&gt;At $6 ARPU and $0.18 AI cost, you’re spending ~3% of revenue. Fine. At $3.50 ARPU and $0.60 cost, that jumps to 17%. That’s not a feature cost, it’s a structural margin problem.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-blended-arpu-in-hybrid-monetization&quot;&gt;Blended ARPU in hybrid monetization&lt;/h3&gt;



&lt;p&gt;In &lt;a href=&quot;https://www.revenuecat.com/blog/growth/hybrid-monetization-techniques/&quot;&gt;hybrid monetization models&lt;/a&gt; combining ads and subscriptions, the analysis becomes more nuanced — if AI cost applies broadly to free users as well as subscribers, then cost per MAU needs to be evaluated against blended ARPU.&lt;/p&gt;



&lt;p&gt;Putting that into numbers, imagine subscriber ARPU is $6, ad ARPU is $0.20, and blended ARPU across MAU is $0.95. If AI costs $0.06 per MAU, then that is ~6% of revenue. If AI costs $0.20 per MAU, it consumes &amp;gt;20% of blended revenue.&lt;/p&gt;



&lt;p&gt;Analyzing the metrics is crucial in understanding how AI is reshaping your monetization model. Hybrid operators must be especially disciplined in protecting blended margin, but any teams working with AI features must be conscious of how it impacts margins.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-operator-checklist-before-shipping-ai&quot;&gt;Operator checklist: before shipping AI&lt;/h2&gt;



&lt;p&gt;Before launching any AI feature, you should be able to answer the following &lt;strong&gt;with numbers&lt;/strong&gt;:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Which metric are you targeting? Install-to-paid conversion, trial starts, trial conversion, retention, or ARPU expansion?&lt;/li&gt;



&lt;li&gt;What lift do you hypothesize? A 0.3 conversion increase? A 0.2 churn reduction?&lt;/li&gt;



&lt;li&gt;What is the projected AI cost per active user and per paying user?&lt;/li&gt;



&lt;li&gt;What percentage of ARPU will AI consume at expected usage levels?&lt;/li&gt;



&lt;li&gt;At what usage threshold does AI push gross margin below your acceptable range?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;If you can’t answer these questions, shipping isn’t strategic.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-ai-only-works-if-the-economics-do&quot;&gt;AI only works if the economics do&lt;/h2&gt;



&lt;p&gt;For years, subscription apps benefited from a simple economic model, and more engagement usually meant more value and better retention, with barely any increased cost. AI has changed that for good.&lt;/p&gt;



&lt;p&gt;This doesn’t mean AI is bad for subscription businesses. In many cases, it can improve retention, increase conversion, and expand LTV. But those outcomes aren’t guarantees; they happen &lt;strong&gt;when teams treat AI as both a product feature and a cost layer&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;Teams need to manage AI the same way they manage acquisition spend or infrastructure. Reuse results, route tasks to cheaper models, gate access behind monetization, and track AI cost alongside subscription metrics like ARPU and LTV. The most successful AI apps are not simply adding features, they are designing the entire system around the economics of usage.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[“Solve time, and they’ll pay you”]]></title><description><![CDATA[On the podcast: Antoine shares how he built RocketSim from an internal tool into a thriving business, the challenges of scaling as an indie developer, and the key marketing insights that drove growth—without relying on traditional ads or influencer campaigns.]]></description><link>https://www.revenuecat.com/blog/growth/antoine-van-der-lee-rocketsim-launched-podcast-2026/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/antoine-van-der-lee-rocketsim-launched-podcast-2026/</guid><pubDate>Wed, 25 Mar 2026 14:30:28 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/LD-Blog-Cover-Antoine-van-der-Lee-1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Antoine van der Lee is the developer behind SwiftLee, a wildly popular iOS development blog, and RocketSim, a developer tool that supercharges the Xcode simulator. In a conversation with Charlie Chapman on the Launched podcast, he explains how RocketSim grew from a personal side project into a business approaching $100K ARR, entirely without traditional marketing. It’s a masterclass in building for your own needs, listening to your users, and understanding that the most powerful thing a developer tool can sell is time.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;From a Personal Side Project to $100K ARR —  Antoine van der Lee, RocketSim &amp;amp; SwiftLee&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/LrbXvsUQ44w?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;iframe loading=&quot;lazy&quot; width=&quot;100%&quot; height=&quot;180&quot; frameborder=&quot;no&quot; scrolling=&quot;no&quot; seamless=&quot;&quot; src=&quot;https://share.transistor.fm/e/d9e13107?color=FFFFFF&amp;amp;background=30343C&quot;&gt;&lt;/iframe&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-pitch-that-writes-itself&quot;&gt;&lt;strong&gt;The pitch that writes itself&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;When it comes to selling developer tools, the value proposition can sometimes get muddy. Are you selling a better UI? A new workflow? For Antoine, the pitch for RocketSim is much simpler, and it comes directly from his head of sales.&lt;/p&gt;



&lt;p&gt;“He just tells me it’s so easy to sell RocketSim,” Antoine says. “And the reason is RocketSim is focused on reducing time spent, and it creates more time to work on actual features. There are so many solved problems in the world, but if you manage to solve the one limitation factor, which is time, and give more time to people, they will pay you.”&lt;/p&gt;



&lt;p&gt;It’s a framing that cuts through the noise. When you pitch a “network monitor” or a “recording tool,” you’re asking developers to change their habits. When you pitch “five minutes saved every day,” multiplied across a team of engineers over a year, the ROI becomes undeniable. You aren’t selling a feature; you’re selling the ability for developers to get back to the work they actually enjoy.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-2-year-open-github-issue&quot;&gt;&lt;strong&gt;The 2-year open GitHub issue&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;In an era of AI agents and instant answers, it’s easy to feel like every technical problem should be solvable in an afternoon. But Antoine’s journey with RocketSim proves that some problems just require you to grow into the solution.&lt;/p&gt;



&lt;p&gt;For two years, he had an open GitHub issue for a feature that would allow developers to slow down the network specifically for the simulator, without affecting the rest of the Mac’s connection. “Every single answer you would basically find on Stack Overflow,” he recalls. “But I created that issue like, ‘Okay, I want to create a solution that works just for the simulator.’ And that issue has been open for two years. I just couldn’t find the answer.”&lt;/p&gt;



&lt;p&gt;Instead of forcing a bad solution, he let it sit. He went to conferences, talked to other developers, and waited for new APIs. When he finally cracked it, the payoff was immense. “The moment that it worked was so amazing because I was literally thinking about it for two years,” he says. It’s a reminder that persistence is often just as important as raw technical skill.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-how-40-trials-became-120&quot;&gt;&lt;strong&gt;How 40 trials became 120&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;When deciding what to build next, it’s easy to get distracted by shiny new APIs or personal pet features. Antoine took a different approach: he maintained a public roadmap and let his users vote.&lt;/p&gt;



&lt;p&gt;The top-voted feature was a network monitor. When he finally released it, the impact was immediate and measurable. “I saw the active trials going from 40 a day to 120 a day,” he notes.&lt;/p&gt;



&lt;p&gt;The lesson is straightforward but often ignored: building exactly what your users are asking for doesn’t just satisfy your current audience—it acts as a powerful re-engagement tool for developers who churned because the app lacked a specific capability. “That really just proves if you build what your users want, the real fields will follow,” he explains.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-focus-trap-of-going-full-time&quot;&gt;&lt;strong&gt;The focus trap of going full-time&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The dream of going “full-time indie” is having five uninterrupted days a week to work on your app. But when Antoine finally made the leap—having already matched his salary and built RocketSim to nearly $100K in recurring revenue—he discovered a counterintuitive truth: more time doesn’t automatically mean more output.&lt;/p&gt;



&lt;p&gt;“When I was full-time indie, I let loose of all the things that I learned as a side hustle,” he admits. “So I didn’t prioritize anymore. I didn’t plan anymore. I just started the day and I was like, ‘Okay, let’s see what I’m going to do today.’”&lt;/p&gt;



&lt;p&gt;When you’re building a side project on nights and weekends, the extreme scarcity of time forces you to be ruthless about prioritization. When those constraints vanish, it’s easy to fall into the trap of doing everything at once and finishing nothing. To succeed as a full-time indie, Antoine had to consciously rebuild the strict habits and boundaries that made him effective when he only had a few hours a week to spare.&lt;/p&gt;



&lt;p&gt;In the full episode, Antoine also discusses the irony of AI agents killing the blogs they were trained on, why he actively cross-promotes with competing newsletters, and the time he tried to become a world champion in darts.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-guest-links&quot;&gt;Guest links:&lt;/h2&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://twitter.com/twannl&quot;&gt;Antoine van der Lee on X&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://rocketsim.app/&quot;&gt;RocketSim&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.avanderlee.com/&quot;&gt;SwiftLee Blog&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title><![CDATA[The Android paywall conversion gap: why the problem isn’t your trial, it’s your funnel entrance]]></title><description><![CDATA[This article breaks down the Android paywall funnel, including where users drop off and how subscription options are actually selected.]]></description><link>https://www.revenuecat.com/blog/engineering/android-paywall-gap/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/android-paywall-gap/</guid><pubDate>Wed, 25 Mar 2026 06:46:34 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Blog-39_The-Android-paywall-conversion-gap.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Android’s subscription conversion rate, compared to iOS, looks like a platform problem. When RevenueCat analyzed over 115,000 apps and $16 billion in revenue for the&amp;nbsp;&lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps/&quot;&gt;2026 State of Subscription Apps report&lt;/a&gt;, the numbers were clear: on Android, the median download to paid conversion at day 35 sits at 0.9%, while iOS lands at 2.6%. That’s a nearly threefold gap. The instinct is to blame the trial, or the audience, or some fundamental difference in how Android users behave. The data says otherwise.&lt;/p&gt;



&lt;p&gt;Looking one level deeper in the same dataset, trial to paid conversion on Android is 32.5%. On iOS, it’s 32.6%. Once a user starts a trial on either platform, they convert at statistically the same rate. There is an important caveat: Android’s trial-starter pool is likely more filtered. Because Android surfaces fewer trials overall, the users who do start one tend to be higher-intent. That selection effect partly explains why the rates equalize. Even so, the primary lever is clear: Android apps are sending far fewer users into that first stage. Closing the gap starts with getting more users to begin a trial in the first place.&lt;/p&gt;



&lt;p&gt;In this article, you’ll explore the two-stage Android paywall funnel and where Android apps lose users, how Google Play’s offer and tag system controls which subscription option is surfaced to users, how RevenueCat’s&amp;nbsp;&lt;code&gt;SubscriptionOptions&lt;/code&gt;&amp;nbsp;selection works and where silent misconfigurations occur, what the data shows about hard paywalls versus freemium models, and how to use &lt;a href=&quot;https://www.revenuecat.com/docs/tools/experiments-v1&quot;&gt;RevenueCat Experiments&lt;/a&gt; to close the gap systematically.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-fundamental-problem-two-stages-one-broken&quot;&gt;&lt;strong&gt;The fundamental problem: Two stages, one broken&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The download to paid journey has two distinct stages, and they behave differently.&lt;/p&gt;



&lt;p&gt;The first stage is download to trial start: the user installs your app, reaches your paywall, and decides whether to begin a free trial. The second stage is trial start to paid: the trial ends, and the user decides whether to continue as a subscriber.&lt;/p&gt;



&lt;p&gt;The RevenueCat data shows these two stages behave very differently on Android. A user who starts a trial converts at 32.5%, close to the 32.6% on iOS. But Android apps are sending far fewer users into that first stage. The bulk of the conversion gap lives in stage one.&lt;/p&gt;



&lt;p&gt;One data point makes this concrete: 89.4% of all trial starts happen on the day of install. Users who download with high intent act immediately. Users who do not start a trial on install day rarely return to do so later. That makes the first paywall impression on Android the moment that determines most subscription revenue. Everything downstream from that moment, including your trial experience, your onboarding, your product, performs about as well on Android as on iOS. The question is whether users reach that moment at all.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-stage-one-what-determines-whether-users-see-a-trial&quot;&gt;&lt;strong&gt;Stage one: What determines whether users see a trial&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Two things control whether a user is presented with a free trial on Android: what you show (the paywall type) and when you show it (the timing). Both are fully within your control.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-paywall-type-gap&quot;&gt;&lt;strong&gt;The paywall type gap&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The RevenueCat data breaks down paywall models by D35 download to paid conversion, RevenueCat’s measurement window for capturing conversion across trial lengths up to one month. Hard paywalls, where users must interact with a subscription offer before accessing core features, achieve a median D35 conversion of 10.7%. The top 10% of hard paywall apps reach 38.7%. Freemium models, where users get some access without paying, convert at a median of 2.1%.&lt;/p&gt;



&lt;p&gt;That’s a fivefold difference in conversion with nearly identical annual retention. Hard paywalls retain 27% of subscribers at 12 months. Freemium retains 28%. For most app categories, the hard paywall numbers are substantially better. If your product delivers clear, immediate value in a single session, a hard paywall is almost certainly the right model. Categories where freemium remains appropriate are those with network effects or long value-discovery cycles, such as social apps and community tools, where acquiring a broad user base matters before monetization.&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Paywall model&lt;/th&gt;&lt;th&gt;Median D35 conversion&lt;/th&gt;&lt;th&gt;Top 10% D35 conversion&lt;/th&gt;&lt;th&gt;12 month retention&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Hard paywall&lt;/td&gt;&lt;td&gt;10.7%&lt;/td&gt;&lt;td&gt;38.7%&lt;/td&gt;&lt;td&gt;27%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Freemium&lt;/td&gt;&lt;td&gt;2.1%&lt;/td&gt;&lt;td&gt;—&lt;/td&gt;&lt;td&gt;28%&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;There is one case where freemium shows a late-conversion advantage: at week six, freemium apps convert 22.9% of that cohort compared to 15.3% for hard paywalls. If your product has a long discovery cycle where value builds gradually over weeks, freemium captures users that a hard paywall would lose.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-paywall-timing-gap&quot;&gt;&lt;strong&gt;The paywall timing gap&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The 89.4% Day 0 trial start rate has a direct implication for timing: show your paywall in the first session. Every session after the first is a sharply diminishing return.&lt;/p&gt;



&lt;p&gt;This doesn’t mean presenting the paywall before any onboarding. Apps that show a paywall before a user understands the product’s value typically see worse opt-in rates. The pattern that works is: deliver one compelling value moment first (a single completed task, a key feature reveal, a concrete output), then present the paywall. On Day 0.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-hidden-failure-when-offer-misconfiguration-silently-suppresses-trials&quot;&gt;&lt;strong&gt;The hidden failure: When offer misconfiguration silently suppresses trials&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Even if your paywall type and timing are right, there’s a second source of trial failures on Android that is harder to spot: the subscription offer itself may not be visible. This is a Google Play configuration issue, and it can happen without any error.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-how-google-play-structures-subscription-offers&quot;&gt;&lt;strong&gt;How Google Play structures subscription offers&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Every subscription on Google Play consists of a base plan and, optionally, one or more offers. An offer defines a promotional pricing phase (a free trial, an introductory price, or both) that precedes the base plan price. Offers are represented in the Billing Library as&amp;nbsp;&lt;code&gt;ProductDetails.SubscriptionOfferDetails&lt;/code&gt;.&lt;/p&gt;



&lt;p&gt;Each&amp;nbsp;&lt;code&gt;SubscriptionOfferDetails&lt;/code&gt;&amp;nbsp;object has a list of pricing phases, a set of offer tags, and an offer token used to initiate the purchase. The pricing phases tell you the price and duration of each stage. The offer tags are strings you define in the Play Console at either the base plan level or the offer level. The Billing Library returns the union of both sets in&amp;nbsp;&lt;code&gt;getOfferTags()&lt;/code&gt;, so a tag set on the base plan automatically appears on all offers under it.&lt;/p&gt;



&lt;p&gt;When RevenueCat fetches your products, each&amp;nbsp;&lt;code&gt;SubscriptionOfferDetails&lt;/code&gt;&amp;nbsp;is converted to a&amp;nbsp;&lt;code&gt;GoogleSubscriptionOption&lt;/code&gt;. Looking at the conversion in&amp;nbsp;&lt;code&gt;subscriptionOptionConversions.kt&lt;/code&gt;:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-15Fi0y wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;internal fun ProductDetails.SubscriptionOfferDetails.toSubscriptionOption(\n    productId: String,\n    productDetails: ProductDetails,\n): GoogleSubscriptionOption {\n    val pricingPhases = pricingPhases.pricingPhaseList.map { it.toRevenueCatPricingPhase() }\n    return GoogleSubscriptionOption(\n        productId,\n        basePlanId,\n        offerId,\n        pricingPhases,\n        offerTags,\n        productDetails,\n        offerToken,\n        presentedOfferingContext = null,\n        installmentPlanDetails?.installmentsInfo,\n    )\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The&amp;nbsp;&lt;code&gt;offerId&lt;/code&gt;&amp;nbsp;is null for base plans and set for offer-based options. The&amp;nbsp;&lt;code&gt;offerToken&lt;/code&gt;&amp;nbsp;is what gets passed to the billing flow when the user taps “Start free trial.” The&amp;nbsp;&lt;code&gt;offerTags&lt;/code&gt;&amp;nbsp;carry the labels you assigned in the Play Console.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;how-revenuecat-selects-the-default-offer&quot;&gt;&lt;strong&gt;How RevenueCat selects the default offer&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Once your product has a list of&amp;nbsp;&lt;code&gt;GoogleSubscriptionOption&lt;/code&gt;&amp;nbsp;objects, RevenueCat groups them in a&amp;nbsp;&lt;code&gt;SubscriptionOptions&lt;/code&gt;&amp;nbsp;collection and exposes a&amp;nbsp;&lt;code&gt;defaultOffer&lt;/code&gt;&amp;nbsp;property. This is the option your paywall shows unless you explicitly select a different one.&lt;/p&gt;



&lt;p&gt;The selection algorithm in&amp;nbsp;&lt;code&gt;SubscriptionOptions.kt&lt;/code&gt;&amp;nbsp;works as follows:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z19m7a4 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;public val defaultOffer: SubscriptionOption?\n    get() {\n        val basePlan = this.firstOrNull { it.isBasePlan } ?: return null\n\n        val validOffers = this\n            .filter { !it.isBasePlan }\n            .filter { !it.tags.contains(RC_IGNORE_OFFER_TAG) }\n            .filter { !it.tags.contains(SharedConstants.RC_CUSTOMER_CENTER_TAG) }\n\n        return findLongestFreeTrial(validOffers) ?: findLowestNonFreeOffer(validOffers) ?: basePlan\n    }&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The algorithm filters out any offer tagged&amp;nbsp;&lt;code&gt;rc-ignore-offer&lt;/code&gt;&amp;nbsp;or&amp;nbsp;&lt;code&gt;rc-customer-center&lt;/code&gt;, then selects the offer with the longest free trial. If there is no free trial, it selects the offer with the lowest introductory price. If no offers pass those checks, it falls back to the base plan with no promotional phase at all.&lt;/p&gt;



&lt;p&gt;That fallback is the silent failure. If your trial offer is tagged&amp;nbsp;&lt;code&gt;rc-ignore-offer&lt;/code&gt;, if it is not attached to the right base plan, or if it simply has no offer tags at all and your app relies on tag-based filtering,&amp;nbsp;&lt;code&gt;defaultOffer&lt;/code&gt;&amp;nbsp;returns the base plan. Your paywall renders. Everything looks fine. No error appears. But the trial is gone.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;detecting-what-your-paywall-is-actually-showing&quot;&gt;&lt;strong&gt;Detecting what your paywall is actually showing&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Before optimizing anything else, verify that&amp;nbsp;&lt;code&gt;defaultOffer&lt;/code&gt;&amp;nbsp;on your product resolves to an offer with a free trial. The&amp;nbsp;&lt;code&gt;SubscriptionOption&lt;/code&gt;&amp;nbsp;interface exposes a&amp;nbsp;&lt;code&gt;freePhase&lt;/code&gt;&amp;nbsp;property for exactly this check:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZhSNd0 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;val freePhase: PricingPhase?\n    get() = pricingPhases.dropLast(1).firstOrNull {\n        it.price.amountMicros == 0L\n    }&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;A non-null&amp;nbsp;&lt;code&gt;freePhase&lt;/code&gt;&amp;nbsp;means the option includes a free trial phase.&amp;nbsp;&lt;code&gt;introPhase&lt;/code&gt;&amp;nbsp;similarly checks for introductory paid phases. If your&amp;nbsp;&lt;code&gt;defaultOffer&lt;/code&gt;&amp;nbsp;has a null&amp;nbsp;&lt;code&gt;freePhase&lt;/code&gt;&amp;nbsp;and a null&amp;nbsp;&lt;code&gt;introPhase&lt;/code&gt;, no promotional phase will be shown. You can also check&amp;nbsp;&lt;code&gt;defaultOffer?.isBasePlan&lt;/code&gt;&amp;nbsp;directly: a true value means the SDK found no eligible offer and fell back to the base plan. Either way, inspect your offer configuration in the Play Console.&lt;/p&gt;



&lt;p&gt;You can check this in code after fetching offerings:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZdVpqT wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;Purchases.sharedInstance.getOfferingsWith(\n    onError = { error -&gt; \/* handle *\/ },\n    onSuccess = { offerings -&gt;\n        val currentOffering = offerings.current ?: return@getOfferingsWith\n        val monthlyPackage = currentOffering.monthly ?: return@getOfferingsWith\n        val subscriptionOptions = monthlyPackage.product.subscriptionOptions\n\n        val defaultOffer = subscriptionOptions?.defaultOffer\n        val hasFreeTrialOption = defaultOffer?.freePhase != null\n        val hasIntroductoryOffer = defaultOffer?.introPhase != null\n\n        Log.d(\&amp;quot;Paywall\&amp;quot;, \&amp;quot;Default offer: ${defaultOffer?.id}\&amp;quot;)\n        Log.d(\&amp;quot;Paywall\&amp;quot;, \&amp;quot;Has free trial: $hasFreeTrialOption\&amp;quot;)\n        Log.d(\&amp;quot;Paywall\&amp;quot;, \&amp;quot;Has intro offer: $hasIntroductoryOffer\&amp;quot;)\n    }\n)&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Run this during development and confirm the output matches your Play Console offer configuration. If&amp;nbsp;&lt;code&gt;hasFreeTrialOption&lt;/code&gt;&amp;nbsp;is false and you expected a trial, the offer is not being selected. Check offer tags, verify the offer is in the correct base plan, and confirm the offer is active in the Play Console.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;one-structural-difference-to-be-aware-of&quot;&gt;&lt;strong&gt;One structural difference to be aware of&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Before moving to tracking and experimentation, it is worth naming one platform-level difference that the Android-iOS comparison does not fully capture.&lt;/p&gt;



&lt;p&gt;On iOS, Apple 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 system notification. This means iOS gets a built-in re-engagement nudge at the critical trial to paid moment, and Android does not. On Android, that reminder is entirely your responsibility: an in-app banner, a push notification from your own backend, or a re-engagement flow triggered when the user returns near the end of their trial.&lt;/p&gt;



&lt;p&gt;This structural difference partially explains why the trial to paid rates look similar despite the very different trial-starter pool sizes: iOS has a platform assist at the conversion moment. On Android, the same result requires explicit implementation. 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.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;tracking-paywall-performance-with-presentedofferingcontext&quot;&gt;&lt;strong&gt;Tracking paywall performance with PresentedOfferingContext&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Once your offer configuration is correct, the next step is understanding which paywall placement drives the most trial starts. RevenueCat’s&amp;nbsp;&lt;code&gt;PresentedOfferingContext&lt;/code&gt;&amp;nbsp;lets you attach a placement identifier to every purchase, so your analytics can segment by where in the app the paywall appeared.&lt;/p&gt;



&lt;p&gt;&lt;code&gt;PresentedOfferingContext&lt;/code&gt;&amp;nbsp;carries three fields:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Zzfk9i wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;public class PresentedOfferingContext(\n    public val offeringIdentifier: String,\n    public val placementIdentifier: String?,\n    public val targetingContext: TargetingContext?,\n)&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The&amp;nbsp;&lt;code&gt;offeringIdentifier&lt;/code&gt;&amp;nbsp;is the offering from your RevenueCat dashboard. The&amp;nbsp;&lt;code&gt;placementIdentifier&lt;/code&gt;&amp;nbsp;is a string you define to label the surface:&amp;nbsp;&lt;code&gt;&quot;onboarding_paywall&quot;&lt;/code&gt;,&amp;nbsp;&lt;code&gt;&quot;settings_upgrade&quot;&lt;/code&gt;,&amp;nbsp;&lt;code&gt;&quot;feature_gate&quot;&lt;/code&gt;, and so on. The&amp;nbsp;&lt;code&gt;targetingContext&lt;/code&gt;&amp;nbsp;carries rule data when you are using RevenueCat’s targeting feature.&lt;/p&gt;



&lt;p&gt;When you initiate a purchase, this context travels with the transaction and appears in your RevenueCat dashboard and webhook events. You can then compare trial start rates and D35 conversion across placements and determine which surface is worth optimizing first.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;trial-length-the-overlooked-variable&quot;&gt;&lt;strong&gt;Trial length: The overlooked variable&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Beyond offer visibility and paywall type, trial duration has a measurable impact on trial to paid conversion. The RevenueCat data shows a clear pattern:&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Trial length&lt;/th&gt;&lt;th&gt;Trial-to-paid conversion&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;4 days or fewer&lt;/td&gt;&lt;td&gt;25.5%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;17 to 32 days&lt;/td&gt;&lt;td&gt;42.5%&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;Apps offering longer trials show roughly 17 percentage points higher trial to paid conversion in the dataset. This is a correlation: apps that offer longer trials tend to be more deliberate productivity and creative tools where longer trials reflect a conscious product strategy, not just an arbitrary setting. Extending your trial duration does not guarantee a 17-point improvement. Yet the pattern suggests that for apps where value compounds over time, a 4-day trial may end before a user has had a meaningful product experience, while a 14 or 30-day trial gives the product enough time to demonstrate its value.&lt;/p&gt;



&lt;p&gt;Yet 55% of all trials in the dataset are now 4 days or shorter, up from 42% the previous year. Only 5% of apps offer 17 or more days.&lt;/p&gt;



&lt;p&gt;If your trial to paid rate is below the 32.5% Android median, trial length is worth testing. It is one of the higher-leverage variables to run through RevenueCat Experiments without needing to ship new code.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;measuring-and-iterating-with-revenuecat-experiments&quot;&gt;&lt;strong&gt;Measuring and iterating with RevenueCat Experiments&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;All of the variables discussed so far (paywall type, timing, trial length, offer selection) interact in ways that are hard to reason about without measurement. What works depends on your specific product, your audience, and your category.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/tools/experiments-v1&quot;&gt;RevenueCat Experiments&lt;/a&gt; lets you run A/B tests against these variables without shipping code changes or building backend infrastructure. You create a variant offering in the RevenueCat dashboard with a different configuration: a different trial length, a different default offer, or a different package lineup. RevenueCat randomly assigns users to control or variant, tracks their behavior through the full trial and conversion cycle, and surfaces D35 conversion, LTV, and trial start rate broken down by variant.&lt;/p&gt;



&lt;p&gt;Once your experiment is running, you can monitor trial state per user via&amp;nbsp;&lt;code&gt;EntitlementInfo.periodType&lt;/code&gt;&amp;nbsp;in&amp;nbsp;&lt;code&gt;CustomerInfo&lt;/code&gt;:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1DVofP wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;Purchases.sharedInstance.getCustomerInfoWith(\n    onError = { error -&gt; \/* handle *\/ },\n    onSuccess = { customerInfo -&gt;\n        val premiumEntitlement = customerInfo.entitlements[\&amp;quot;premium\&amp;quot;]\n\n        when (premiumEntitlement?.periodType) {\n            PeriodType.TRIAL -&gt; {\n                \/\/ User is in an active trial\n                val trialEnds = premiumEntitlement.expirationDate\n                showTrialExpirationReminder(trialEnds)\n            }\n            PeriodType.INTRO -&gt; {\n                \/\/ User is in an introductory paid phase\n            }\n            PeriodType.NORMAL -&gt; {\n                \/\/ User is a full subscriber\n            }\n            null -&gt; {\n                \/\/ No active entitlement\n                showPaywall()\n            }\n        }\n    }\n)&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The&amp;nbsp;&lt;code&gt;periodType&lt;/code&gt;&amp;nbsp;tells you the current phase of the user’s subscription. This is useful for building trial-aware UI: showing a banner when a trial is about to expire, adjusting messaging based on subscription phase, or triggering a re-engagement paywall for users whose trial ended without converting.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;putting-it-together&quot;&gt;&lt;strong&gt;Putting it together&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The Android conversion gap is primarily a funnel-entrance problem with identifiable causes. The threefold difference in D35 download to paid between Android and iOS does not reflect a platform ceiling. It reflects the aggregate effect of offer misconfiguration, freemium models that suppress trial uptake, and paywalls shown too late or not at all. A structural platform difference also contributes: Android does not send system-level trial expiration reminders the way iOS does, so re-engaging users near trial end requires explicit implementation on your side.&lt;/p&gt;



&lt;p&gt;The path to closing the gap follows a specific sequence. First, confirm that&amp;nbsp;&lt;code&gt;defaultOffer&lt;/code&gt;&amp;nbsp;on your active offering resolves to an option with a non-null&amp;nbsp;&lt;code&gt;freePhase&lt;/code&gt;. If it doesn’t, fix the Play Console offer configuration before changing anything else. Second, if you are running freemium, run an experiment against a hard paywall variant and measure both trial start rate and 12-month retention. Third, if you are already running a hard paywall, test a longer trial duration. Fourth, add&amp;nbsp;&lt;code&gt;placementIdentifier&lt;/code&gt;&amp;nbsp;to your&amp;nbsp;&lt;code&gt;PresentedOfferingContext&lt;/code&gt;&amp;nbsp;so you can attribute trial starts to specific surfaces.&lt;/p&gt;



&lt;p&gt;Each of these changes is measurable. RevenueCat Experiments gives you the infrastructure to test without guessing, and the D35 and trial to paid metrics give you the signal to act on.&lt;/p&gt;



&lt;p&gt;In this article, you’ve explored how the Android paywall conversion problem lives primarily in stage one of a two-stage funnel, how Google Play’s offer and tag system determines which subscription option is surfaced, how RevenueCat’s&amp;nbsp;&lt;code&gt;SubscriptionOptions.defaultOffer&lt;/code&gt;&amp;nbsp;algorithm selects a trial and where silent misconfigurations occur, what the data shows about paywall model choice and trial length, the structural platform difference around trial reminders, and how to diagnose and iterate using RevenueCat’s tooling.&lt;/p&gt;



&lt;p&gt;Understanding where the gap lives changes what you build. Most of the work is in stage one: getting users to see and start a trial. The Android user who starts a trial converts at nearly the same rate as the iOS user. The work is making sure they get the chance to start, and giving them a reason to convert before that trial ends.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Why free trials don’t make sense anymore (and what user acquisition tactic to try instead)]]></title><description><![CDATA[Why short trials, AI costs, and web funnels are forcing UA teams to rethink free trials]]></description><link>https://www.revenuecat.com/blog/growth/free-trials-dont-make-sense-anymore/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/free-trials-dont-make-sense-anymore/</guid><pubDate>Mon, 23 Mar 2026 17:54:54 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Blog-35_Why-free-trials-dont-make-sense-anymore.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Since subscription apps first started to gain in popularity, free trials have been a foundation for most user acquisition (UA) marketers, serving as the main proxy event to attract real long-term subscribers. But this tactic, like so many other elements of our industry, has been changed by AI and vibe-coding. It’s now harder than ever to run campaigns optimizing towards a free trial, largely due to the enormous competition and overall declining &lt;a href=&quot;https://www.revenuecat.com/glossary/#trial-conversion-rate&quot;&gt;trial conversion rates&lt;/a&gt;.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;As the &lt;a href=&quot;http://revenuecat.com/report&quot;&gt;State of Subscription Apps 2026&lt;/a&gt; shows, there’s a growing trend of trials shortening to three days — despite data encouraging the opposite; showing that trials with 17+ days convert 70% better (42.5% paid conversion rate vs. 25.5%).&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;622&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-24-1024x622.png&quot; alt=&quot;&quot; class=&quot;wp-image-52468&quot; style=&quot;width:700px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-24-1024x622.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-24-300x182.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-24-768x466.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-24-1536x932.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-24-50x30.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-24-66x40.png 66w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-24-696x422.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-24-560x340.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-24-488x296.png 488w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-24-778x472.png 778w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-24-80x49.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-24-48x29.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-24.png 1766w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;State of Subscription Apps 2026 — trial-to-paid, by trial duration&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;Even with this huge discrepancy, nearly half of all apps now use trials of four days or less, seeking immediate revenue and shorter payback periods that make publishers’ margins more affordable from the UA perspective.&lt;/p&gt;



&lt;p&gt;This is not a coincidence. AI has drastically changed the whole market: by adding variable and rising costs to the use of its technology, AI has forced publishers and developers to look for &lt;a href=&quot;https://www.revenuecat.com/blog/growth/subscription-app-expand-value/&quot;&gt;higher average revenue per user (ARPU)&lt;/a&gt; in the shortest time possible, in order to can’t cover these costs and sustain the business. Otherwise, the apps become unmarketable themselves, making the &lt;a href=&quot;https://www.revenuecat.com/blog/growth/product-market-fit-subscription-apps/&quot;&gt;product-market fit&lt;/a&gt; (PMF) process harder than ever.&lt;/p&gt;



&lt;p&gt;If you also consider the popularity of how &lt;a href=&quot;https://www.revenuecat.com/blog/growth/web-to-app-funnels/&quot;&gt;web-to-app campaigns&lt;/a&gt; can help you to nail &lt;a href=&quot;https://www.revenuecat.com/webinars/signal-engineering-how-to-optimize-ad-campaigns-with-smarter-events/&quot;&gt;signal engineering&lt;/a&gt;, we can easily draw the conclusion that &lt;strong&gt;free trials don’t make much sense anymore&lt;/strong&gt;. But is that a fair blanket statement? I think it’s true, but that doesn’t mean free trials are &lt;em&gt;over&lt;/em&gt;. We can still play with a more advanced version of this conversion event.&lt;/p&gt;



&lt;p&gt;Before exploring what that looks like, let’s dive into the reasons why free trials became so popular on subscription apps.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-free-trials-the-purchase-proxy-event&quot;&gt;Free trials: the purchase proxy event&lt;/h2&gt;



&lt;p&gt;The title speaks for itself: The free trial event has been the foundation of endless companies’ UA strategies for a simple reason — &lt;strong&gt;a free trial is the closest event to purchase&lt;/strong&gt;. What’s more, the event can filter purchase intention, without sacrificing the volume that ad networks need to optimize performance efficiently.&lt;/p&gt;



&lt;p&gt;When AI didn’t exist and the offer of apps was more limited, free trials were widely used as a technique to convince the user to convert, with publishers heavily relying on their products and UX to make the conversion effective. But that doesn’t apply anymore. Today, &lt;a href=&quot;https://www.revenuecat.com/glossary/#hard-paywall&quot;&gt;&lt;strong&gt;hard paywalls&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt; with direct subscriptions are becoming more present&lt;/strong&gt;, with data showing they generate close to double the upfront revenue vs. freemium apps.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;617&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-22-1024x617.png&quot; alt=&quot;&quot; class=&quot;wp-image-52464&quot; style=&quot;width:700px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-22-1024x617.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-22-300x181.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-22-768x462.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-22-1536x925.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-22-50x30.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-22-66x40.png 66w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-22-696x419.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-22-560x337.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-22-492x296.png 492w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-22-784x472.png 784w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-22-80x48.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-22-48x29.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-22.png 2048w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;State of Subscription Apps 2026 — day 35 download-to-paid, freemium vs. hard paywall&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;This growing shift away from free trials is clearly visible when you compare 2026’s report vs. 2024. We can see how all categories have seen a &lt;strong&gt;14% increase in the non-trial strategies&lt;/strong&gt; (28% in 2024 in non-trial strategies vs. 32% in 2026) where free trials are non-existent.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;978&quot; height=&quot;594&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-20.png&quot; alt=&quot;&quot; class=&quot;wp-image-52460&quot; style=&quot;width:700px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-20.png 978w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-20-300x182.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-20-768x466.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-20-50x30.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-20-66x40.png 66w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-20-696x423.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-20-560x340.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-20-487x296.png 487w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-20-777x472.png 777w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-20-80x49.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-20-48x29.png 48w&quot; sizes=&quot;auto, (max-width: 978px) 100vw, 978px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;State of Subscription Apps 2024 — trial strategy &lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;620&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-25-1024x620.png&quot; alt=&quot;&quot; class=&quot;wp-image-52470&quot; style=&quot;width:700px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-25-1024x620.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-25-300x182.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-25-768x465.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-25-1536x930.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-25-50x30.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-25-66x40.png 66w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-25-696x421.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-25-560x339.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-25-489x296.png 489w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-25-780x472.png 780w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-25-80x48.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-25-48x29.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-25.png 1764w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;State of Subscription Apps 2026 — trial strategy, by category &lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;With such a fast evolution, publishers need to adapt to the new reality since ChatGPT normalised paying $20/month for an AI chatbot. And the shortest path for that is playing with pricing, which explains this change in the overall trial strategy.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-web-campaigns-a-lever-pushing-free-trial-extinction&quot;&gt;Web campaigns: a lever pushing free trial extinction&lt;/h2&gt;



&lt;p&gt;At this point, it’s no longer a new topic: web and &lt;a href=&quot;https://www.revenuecat.com/blog/growth/web-to-app-funnel-examples/&quot;&gt;web-to-app funnels&lt;/a&gt; are now the norm for the biggest publishers due to multiple reasons:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;The &lt;a href=&quot;https://www.revenuecat.com/blog/engineering/small-business-program/&quot;&gt;30% fee you save due to Apple&lt;/a&gt; or Google’s commissions&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Higher flexibility and speed to run multiple &lt;a href=&quot;https://www.revenuecat.com/blog/growth/should-your-app-stop-offering-free-trials/&quot;&gt;A/B tests&lt;/a&gt; with the onboarding and pricing&lt;/li&gt;



&lt;li&gt;Higher accuracy on campaign attribution &lt;a href=&quot;https://www.revenuecat.com/blog/growth/enhanced-app-campaigns/&quot;&gt;without relying on SKAN&lt;/a&gt; and its limitations&lt;/li&gt;



&lt;li&gt;Higher purchase intention in users&lt;/li&gt;



&lt;li&gt;More and new inventories where you have more control to filter purchase intention&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/offering-customization-examples-targeting/&quot;&gt;Retargeting&lt;/a&gt; is real for iOS users&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Although it’s true that, at the moment, web onboarding doesn’t make too much sense for small publishers that are under the 15% commission — due to the additional complexities you have to handle (tax compliance, 3% fee to Stripe or similar, managing refunds internally, platforms to build onboarding, etc.) — the change in strategy of the biggest players has directly affected the trends in the market. Now, even small devs are pushing to copy these strategies.&lt;/p&gt;



&lt;p&gt;With this current outlook, the question is no longer &lt;em&gt;whether&lt;/em&gt; to move away from the classic free trial, it’s about &lt;strong&gt;what you replace it with, and when&lt;/strong&gt;. The market has split:&amp;nbsp;&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Hard paywalls with direct subscriptions: for apps with strong PMF and vitality&lt;/li&gt;



&lt;li&gt;A more sophisticated version of the free trial mechanic, that preserves the volume ad networks need while dramatically improving signal quality&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;The second option is what I like to work with — and in my opinion, it will be the future standard when it comes to signal engineering.&lt;/p&gt;



&lt;p&gt;At &lt;a href=&quot;https://www.revenuecat.com/blog/company/lessons-from-app-growth-annual-2025/&quot;&gt;App Growth Annual 2025&lt;/a&gt;, I did a workshop where I explained the immediate effect that paid trials (&lt;a href=&quot;https://www.revenuecat.com/blog/growth/introductory-offers-apps/&quot;&gt;introductory offers&lt;/a&gt;) have in your &lt;a href=&quot;https://www.revenuecat.com/blog/growth/activation-metrics/&quot;&gt;activation metrics&lt;/a&gt; and UA performance. Today, I see more and more companies applying this strategy on their web campaigns, as these normally target users with real purchase intention easier than app campaigns.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-trial-qualifier-or-paid-trial-events-aren-t-mutually-exclusive&quot;&gt;Trial qualifier or paid trial events aren’t mutually-exclusive&lt;/h2&gt;



&lt;p&gt;As shown in my article on intro offers, introducing paid trials in your app or web campaigns can drastically change your numbers. &lt;em&gt;But&lt;/em&gt; you have to pay close attention to monitoring the conversion rate after the paid trial — this strategy effectively harms your short-term &lt;a href=&quot;https://www.revenuecat.com/glossary/#lifetime-value-ltv&quot;&gt;lifetime value (LTV)&lt;/a&gt;, compared to a hard paywall with a direct subscription.&lt;/p&gt;



&lt;p&gt;The State of Subscription Apps report shows that ~30% of new subscribers now enter through intro offers (median).&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;614&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-26-1024x614.png&quot; alt=&quot;&quot; class=&quot;wp-image-52472&quot; style=&quot;width:700px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-26-1024x614.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-26-300x180.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-26-768x461.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-26-1536x921.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-26-50x30.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-26-67x40.png 67w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-26-696x417.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-26-560x336.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-26-494x296.png 494w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-26-787x472.png 787w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-26-80x48.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-26-48x29.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-26.png 1774w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;State of Subscription Apps 2026 — share of new payers acquired via an intro offer, by category and revenue tier&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;The $0.99 first month model doesn’t just improve conversion — it fundamentally changes what signal you’re feeding the algorithm. You’re no longer training the network on “users who clicked a free button”. You’re training it on users who handed over a credit card, which is a completely different behavioral profile. That’s a gamechanger if you’re able to target those users efficiently with a correct creative strategy in your paid campaigns.&lt;/p&gt;



&lt;p&gt;This started to become more popular on web and web-to-app campaigns since you could use specific channels to filter purchase intent in the upper funnel part of the metric, just by launching channels with inventories with high control capabilities — unlike the automated app campaigns which are now the norm in all ad networks that offer app campaigns promotion.&lt;/p&gt;



&lt;p&gt;For example, when launching Google Ads with a search campaign, you have the possibility of creating specific ad groups for each audience segment. Within these, you can target different purchase intent levels by just playing with the keywords. A good strategy would be using keywords with and without “free” in the term, to see what’s the performance towards that trial qualifier event.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Using this type of advanced targeting with a paid trial has become a really successful tool for many publishers that wanted to boost the algorithm with real paying signals on day 0, instead of proxy events whose median averages 30–35% vs. the real subscription (source: SOSA).&lt;/p&gt;



&lt;p&gt;But for me, this isn’t going to be the norm in the near future. &lt;strong&gt;Trial qualifiers will take this role&lt;/strong&gt;. And the most positive news is that you don’t have to do one or the other, you can keep paid trials for your web campaigns where you have more control over the intention of the users, while utilizing trial qualifiers for app campaigns.&lt;/p&gt;



&lt;p&gt;Looking again at the State of Subscription Apps 2026, we see that nearly all trial starts happen on day 0 across categories. Users who don’t try immediately during the onboarding rarely try at all.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;616&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-21-1024x616.png&quot; alt=&quot;&quot; class=&quot;wp-image-52462&quot; style=&quot;width:700px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-21-1024x616.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-21-300x181.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-21-768x462.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-21-1536x924.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-21-50x30.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-21-66x40.png 66w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-21-696x419.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-21-560x337.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-21-492x296.png 492w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-21-784x472.png 784w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-21-80x48.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-21-48x29.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-21.png 1768w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;State of Subscription Apps 2026 — time to trial, by category&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;With this data, the main takeaway is clear: trial qualifier events are the best tool for advertisers right now. Here’s why:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;You still feed the algorithm with signals on day 0, but without forcing the user to use a credit card&lt;/li&gt;



&lt;li&gt;You still optimize towards an event that happens immediately before the purchase, but with a deeper intent than the classic trial&lt;/li&gt;



&lt;li&gt;And most importantly (in my opinion) you have &lt;em&gt;full&lt;/em&gt; control to play with the signals that you send for this trial qualifier event, because you have access to the purchase behaviour of your users&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;So how do you get started implementing this in your campaigns?&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-new-free-trial-how-to-set-up-an-advanced-free-trial&quot;&gt;The new free trial: how to set up an advanced free trial&lt;/h2&gt;



&lt;p&gt;Personalisation of the trial qualifier event will heavily depend on the app category, subscription tiers offered in the paywall, and the historical behaviour and data you can analyze from the classic trial start event. But as an initial setup, you can create the trial qualifier event based on the following conditions:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-time-without-cancelling-the-free-trial-nbsp&quot;&gt;1. Time without cancelling the free trial&amp;nbsp;&lt;/h3&gt;



&lt;p&gt;Most trial cancellations happened within the first two hours after starting the trial. The data shows cancellation is at its highest on day 0, closely followed by day 1.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;618&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-23-1024x618.png&quot; alt=&quot;&quot; class=&quot;wp-image-52466&quot; style=&quot;width:700px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-23-1024x618.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-23-300x181.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-23-768x464.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-23-1536x927.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-23-50x30.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-23-66x40.png 66w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-23-696x420.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-23-560x338.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-23-490x296.png 490w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-23-782x472.png 782w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-23-80x48.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-23-48x29.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-23.png 1766w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;State of Subscription Apps — % of trial cancellations, by day and trial duration&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;These cancellations are users who just want to see what’s behind the paywall but they will never purchase. However, they will contaminate the signals you send to ad networks when working with the trial, making your overall performance worse — so &lt;strong&gt;these are the first users that need to be filtered out&lt;/strong&gt;. In this case, you should analyze the historical data to see which time filter accommodates better to your app.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-time-without-cancelling-the-free-trial-engagement&quot;&gt;2. Time without cancelling the free trial + engagement&lt;/h3&gt;



&lt;p&gt;Some products have drastic differences in LTV, retention, and payback periods between users; specifically those who stick to the product and use it actively, versus those who just subscribe and forget about the app. So a smart way of nailing the trial qualifier is to &lt;strong&gt;add engagement signals&lt;/strong&gt; [that happened in the first session] to the time without cancelling metric. This creates a more robust and reliable signal that you can send to the ad network to optimize your campaigns.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;One word of warning is to avoid being very picky with the engagement points during this first session, otherwise you will sacrifice too much signal volume and your campaigns will struggle to optimize.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-time-without-cancelling-the-free-trial-sending-an-additional-signal-the-day-after-the-trial-started&quot;&gt;3. Time without cancelling the free trial + sending an additional signal the day after the trial started&lt;/h3&gt;



&lt;p&gt;This is similar to the first point, but with a deeper complexity, as you send two signals per user instead of just one. This strategy is based on &lt;strong&gt;sending the initial signal two hours after trial starts&lt;/strong&gt;, and then &lt;strong&gt;another extra signal the day before the trial ends.&lt;/strong&gt; For example, if you have a 3-day trial, you would send one initial signal two hours after the trial starts, and another signal if the user keeps the trial active on day 2. This helps with the volume of events, making the optimization of campaigns easier for ad networks. At the same time, it adds difficulty to calculate the real trial conversion rate and incrementality.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-4-automate-trial-qualifier-mapping&quot;&gt;4. Automate trial qualifier mapping&lt;/h3&gt;



&lt;p&gt;If you want to go one step further, you can now use the new RevenueCat integration with &lt;a href=&quot;https://www.revenuecat.com/blog/engineering/revenuecat-now-integrates-with-appstack/&quot;&gt;Appstack&lt;/a&gt;, and &lt;strong&gt;automate mapping your trial qualifier events&lt;/strong&gt; in just a couple of clicks. With this integration you’re able to send campaign users to specific paywalls made with RevenueCat, allowing you to fully customize the user experience, from when they watch an ad all the way to completing onboarding in your app. I think this is a unique feature in the market which will dramatically change the way paywalls are made and tested, since you can now feed these tests to users with deep purchase intent.&lt;/p&gt;



&lt;p&gt;Ultimately, I suggest you take these initial ideas and start playing with the trial qualifier event, then compare the performance of these campaigns against your classic free trial campaigns. Once you find a winning path, you can start an ongoing process of filtering your signals until you reach the perfect balance between signal quality and quantity for the ad network.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-ready-to-revamp-your-free-trial&quot;&gt;Ready to revamp your free trial?&lt;/h2&gt;



&lt;p&gt;I know this article may sound somewhat dramatic, and of course there will be cases where you still get a better performance with classic free trials. However, according to what I see everyday working with different apps, we’re rapidly moving to the immediate pursuit of results (thanks to the increasing marginal costs attached to AI). So I believe in the near future we’ll have most apps refining their free trial signals in this way, allowing them to be more accurate with ad delivery — and overall maximizing the efficiency of every dollar invested in their UA.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[The State of Subscription Apps in 10 minutes: lessons, trends, and benchmarks for 2026]]></title><description><![CDATA[Essential insights from the world’s largest subscription app dataset]]></description><link>https://www.revenuecat.com/blog/growth/subscription-app-trends-benchmarks-2026/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/subscription-app-trends-benchmarks-2026/</guid><pubDate>Thu, 19 Mar 2026 16:16:53 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/SOSA26-Blog-Cover-1600x850-1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Each year, our &lt;a href=&quot;/state-of-subscription-apps/&quot;&gt;State of Subscription Apps&lt;/a&gt; report sets out to understand what’s changing in the industry; what’s new, what’s over, and what’s on its way.&amp;nbsp;This year, our dataset grew again: over 115,000 apps, representing more than $16 billion in revenue. And we analyzed the data from all 115k+ of them. &lt;/p&gt;



&lt;p&gt;If you thought last year’s report was a behemoth, look away now. This year, we’ve delivered 338 pages, ready to give you every metric, benchmark, or trend you could possibly need.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;To summarize David Barnard’s own words, “There’s a lot of apps making a &lt;em&gt;lot &lt;/em&gt;of money.”&amp;nbsp;&lt;/p&gt;



&lt;p&gt;But, if you (shockingly) don’t have time to read every single page (&lt;a href=&quot;https://www.youtube.com/watch?v=UO0NQNfICwo&quot;&gt;like David and Jacob did&lt;/a&gt;), then this rundown’s for you. Strap in.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-1-s-ubscription-app-growth-is-no-longer-a-spectrum&quot;&gt;1. S&lt;strong&gt;ubscription app growth is no longer a spectrum&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;2026 shows a huge polarization in app growth. Where maintaining steady growth (e.g. 5–15% YoY) was previously considered safe and healthy for an app business, today’s data shows &lt;strong&gt;this middle ground evaporating beneath our feet&lt;/strong&gt;.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Market dynamics — user acquisition costs, algorithm changes, platform fees, AI unit economics — now heavily reward the top performers, creating a mobile app economy that mirrors broader wealth inequality: the rich get richer, and indie developers struggle to stay afloat.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-data&quot;&gt;&lt;strong&gt;The data:&lt;/strong&gt;&lt;/h3&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Top quartile: &lt;/strong&gt;the top 25% of subscription apps grew their monthly recurring revenue (MRR) by 80% or more year-on-year&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Bottom quartile: &lt;/strong&gt;the bottom 25% of apps saw their MRR shrink by more than 33%&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;The divide: &lt;/strong&gt;this creates a massive 113-point gap between the winners scaling aggressively and the apps bleeding revenue&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Comparison to 2025: &lt;/strong&gt;last year’s data saw the revenue gap increase between the top 5% and bottom 25% (with the top earning 400x more, up from 200x in 2024) – a trend the 2026 data confirms and quantifies for the first time in growth rate&lt;/li&gt;
&lt;/ul&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;617&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-13-1024x617.png&quot; alt=&quot;&quot; class=&quot;wp-image-52430&quot; style=&quot;width:700px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-13-1024x617.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-13-300x181.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-13-768x463.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-13-1536x925.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-13-50x30.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-13-66x40.png 66w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-13-696x419.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-13-560x337.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-13-491x296.png 491w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-13-783x472.png 783w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-13-80x48.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-13-48x29.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-13.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;&lt;em&gt;Median year-on-year monthly recurring revenue growth rate, by developer HQ — State of Subscription Apps 2026&lt;/em&gt;&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-what-next-nbsp&quot;&gt;&lt;strong&gt;What next?&amp;nbsp;&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;App teams can no longer rest on ‘good enough’. There is no safety blanket. If you’re growing at the median rate (5–17%), you’re at risk of falling into the bottom quartile and slipping through the cracks. Teams need to shift from maintenance mode to aggressive growth optimization.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;→ Your next step: &lt;/strong&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/the-subscription-value-loop-a-framework-for-subscription-app-growth/&quot;&gt;learn about the Subscription Value Loop, a framework for app growth&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-2-h-ard-paywalls-convert-5x-better-than-freemium&quot;&gt;2. H&lt;strong&gt;ard paywalls convert 5x better than freemium&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;We’ve all heard the rhetoric that “hard paywalls kill user experience”. Well, consider that mythbusted. Across categories, Day 35 trial-to-paid conversion is &lt;strong&gt;5x better when apps feature a hard paywall&lt;/strong&gt;.&amp;nbsp;Contrary to popular belief, hard paywalls are not scaring users away or ‘forcing’ them into buying before ready — this narrative only belittles users, who are subscription-savvy and will only convert when &lt;em&gt;they &lt;/em&gt;want to. Today, users are engaging with hard paywalls, and it’s giving apps faster payback.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;This choice [hard paywall vs. freemium] changes your unit economics completely. Same ad spend. Dramatically different revenue on day one. — Sven Jürgens, Mobile Growth Consultant&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;While paywall type impacts conversion, long-term retention equalizes across both access methods. Freemium apps continue to convert well into Week 6 and beyond, meaning the full conversion picture is a longer game than you may think.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;So freemium doesn’t mean &lt;em&gt;less &lt;/em&gt;success — and there are many successful freemium apps that prove this — but the data definitively proves that hard paywalls convert better, and convert quicker. In 2026, freemium may feel like the safer option, but it’s not necessarily the best choice.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-data&quot;&gt;&lt;strong&gt;The data:&lt;/strong&gt;&lt;/h3&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Conversion:&lt;/strong&gt; hard paywalls have a median Day-35 trial-to-paid conversion rate of &lt;strong&gt;10.7%&lt;/strong&gt;, compared to just &lt;strong&gt;2.1%&lt;/strong&gt; for freemium apps — this is roughly a 5x advantage&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Retention:&lt;/strong&gt; freemium apps retain &lt;strong&gt;28%&lt;/strong&gt; of yearly subscribers after 1 year, while hard paywall apps retain &lt;strong&gt;27%&lt;/strong&gt;, making the difference statistically negligible&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Revenue per install: &lt;/strong&gt;hard paywall apps generate 8x higher RPI at day 60, compared to freemium ($3.09 vs. $0.38)&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Comparison to 2025: &lt;/strong&gt;while freemium D35 conversion has &lt;strong&gt;remained&lt;/strong&gt; at 2.1% since 2025, hard paywall conversion has &lt;strong&gt;gone down&lt;/strong&gt; ~2% (12.1% in 2025), suggesting a broader reluctance to convert&lt;/li&gt;
&lt;/ul&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;616&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-19-1024x616.png&quot; alt=&quot;&quot; class=&quot;wp-image-52442&quot; style=&quot;width:700px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-19-1024x616.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-19-300x181.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-19-768x462.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-19-1536x924.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-19-50x30.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-19-66x40.png 66w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-19-696x419.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-19-560x337.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-19-492x296.png 492w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-19-784x472.png 784w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-19-80x48.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-19-48x29.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-19.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Day 35 download-to-paid, freemium vs. hard paywall — State of Subscription Apps 2026&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-what-next&quot;&gt;&lt;strong&gt;What next?&lt;/strong&gt;&lt;/h3&gt;



&lt;p id=&quot;h-what-next-switch-to-a-hard-paywall-if-you-dare-hard-paywalls-offer-an-upfront-roi-giving-you-a-chunk-of-cash-to-reinvest-in-growth-if-you-re-relying-on-a-freemium-model-to-build-goodwill-you-re-sacrificing-massive-top-of-funnel-revenue-for-a-just-1-retention-bump-a-year-later-given-the-aggressive-market-it-s-a-risky-move-to-take&quot;&gt;Switch to a hard paywall (if you dare 😈). Hard paywalls offer an upfront ROI, giving you a chunk of cash to reinvest in growth. If you’re relying on a freemium model to build goodwill, you’re sacrificing massive top-of-funnel revenue for a just 1% retention bump a year later. Given the aggressive market, it’s a risky move to take.&amp;nbsp;&lt;/p&gt;



&lt;p id=&quot;h-what-next-switch-to-a-hard-paywall-if-you-dare-hard-paywalls-offer-an-upfront-roi-giving-you-a-chunk-of-cash-to-reinvest-in-growth-if-you-re-relying-on-a-freemium-model-to-build-goodwill-you-re-sacrificing-massive-top-of-funnel-revenue-for-a-just-1-retention-bump-a-year-later-given-the-aggressive-market-it-s-a-risky-move-to-take&quot;&gt;&lt;strong&gt;→ Your next step: &lt;/strong&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/how-top-apps-approach-paywalls/&quot;&gt;discover what the best subscription apps get right about paywalls&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-3-t-he-day-0-buyer-s-remorse-window&quot;&gt;3. T&lt;strong&gt;he Day 0 buyer’s remorse window&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Plot twist: your 3-day trial is actually a 1-hour trial. Yep. &lt;strong&gt;55% of all trial cancellations happen on Day 0. &lt;/strong&gt;So while developers are designing a three-day experience, the modern consumer’s attention span is demanding instant proof of value.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Teams can no longer assume users spend days exploring all app features before making a decision; the reality is that users treat app trials like impulsive retail purchases. They subscribe to get past the paywall, immediately experience and assess the core features, then cancel to prevent being charged. If you don’t deliver an &lt;em&gt;aha!&lt;/em&gt; moment in the first 60 minutes, the subscriber is already gone.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-data-2&quot;&gt;&lt;strong&gt;The data:&lt;/strong&gt;&lt;/h3&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Day 0 cancellations:&lt;/strong&gt; exactly &lt;strong&gt;55.4%&lt;/strong&gt; of all 3-day trial cancellations occur on Day 0&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;The drop-off:&lt;/strong&gt; an overwhelming &lt;strong&gt;84%&lt;/strong&gt; of 3-day trial cancellations happen between Day 0 and Day 1&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Comparison to 2025: &lt;/strong&gt;last year, ~51% of 3-day trial cancellations happened on Day 0 (showing a ~4% increase this year), suggesting users quickfire cancel instinct is only &lt;strong&gt;increasing&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;618&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-18-1024x618.png&quot; alt=&quot;&quot; class=&quot;wp-image-52440&quot; style=&quot;width:700px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-18-1024x618.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-18-300x181.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-18-768x463.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-18-1536x926.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-18-50x30.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-18-66x40.png 66w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-18-696x420.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-18-560x338.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-18-491x296.png 491w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-18-783x472.png 783w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-18-80x48.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-18-48x29.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-18.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;% of trial cancellations, by day and trial duration — State of Subscription Apps 2026&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;what-next&quot;&gt;&lt;strong&gt;What next?&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Treat your onboarding flow as your primary retention mechanism. If a user doesn’t hit the &lt;em&gt;aha!&lt;/em&gt; moment in their very first session, they’re going to quickly toggle off auto-renew. Revisit your trial length — does it need to be three days? (More on this next.)) Consider the features you give access to in a trial — what shows value instantly, and what takes up space? Figure out the most direct route to proving value, then build it.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;→ Your next step: &lt;/strong&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/fix-onboarding-funnels/&quot;&gt;stop chasing growth hacks — learn how how to fix your onboarding first&lt;/a&gt;&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-4-t-he-7-day-trial-is-alive-and-kicking-sometimes&quot;&gt;4. T&lt;strong&gt;he 7 day trial is alive and kicking&lt;/strong&gt; (sometimes)&lt;/h2&gt;



&lt;p&gt;The subscription app industry is obsessed with short trials, but what do the numbers actually show? Is the 7-day trial really dead?&amp;nbsp;&lt;/p&gt;



&lt;p&gt;In short, &lt;em&gt;no&lt;/em&gt;.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Trials of &lt;strong&gt;17-32 days convert 70% better than 3-day trials &lt;/strong&gt;(42.5% vs 25.5%). Yet, &lt;strong&gt;46% of apps are moving to trials of 4 days or less.&lt;/strong&gt; Why? Growth teams are under market and economic pressure to show fast revenue. &lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;Most developers do 3-day free trials for cashflow. You want the money in three days, not 30 days. [Or you’re looking to] get conversion data faster, to compound onboarding and paywall experiments. — &lt;a href=&quot;https://www.youtube.com/watch?v=UO0NQNfICwo&quot;&gt;David Barnard and Jacob Eiting speak about on Sub Club&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Short trials force a fast decision from users, often resulting in high abandonment (see the Day 0 cancellation rate of 3-day trial vs. longer), while longer trials give users time to integrate an app into their daily habits, and reduces nerves about accidental auto-renewal. 3-day trials are useful for app teams, but the reality is you’re sacrificing long-term conversion for a short-term dopamine dashboard spike.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-data-3&quot;&gt;&lt;strong&gt;The data:&lt;/strong&gt;&lt;/h3&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Long-trial conversion:&lt;/strong&gt; trials of 17–32 days convert at an incredibly high median of &lt;strong&gt;42.5%&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Short trial conversion:&lt;/strong&gt; trials of &amp;lt;4 days convert at just &lt;strong&gt;25.5%&lt;/strong&gt;, meaning long trials convert ~70% better&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Comparison to 2025: &lt;/strong&gt;last year, trials were increasing in length, but today, despite the data, trials of &amp;lt;4 days rose from 42.1% in 2025 to &lt;strong&gt;46.5%&lt;/strong&gt; in 2026&lt;/li&gt;
&lt;/ul&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;616&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-14-1024x616.png&quot; alt=&quot;&quot; class=&quot;wp-image-52432&quot; style=&quot;width:700px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-14-1024x616.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-14-300x181.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-14-768x462.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-14-1536x924.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-14-50x30.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-14-66x40.png 66w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-14-696x419.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-14-560x337.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-14-492x296.png 492w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-14-784x472.png 784w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-14-80x48.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-14-48x29.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-14.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Trial-to-paid, by trial duration — State of Subscription Apps 2026&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;what-next-2&quot;&gt;&lt;strong&gt;What next?&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Deep dive into your category’s trial and retention data. Watch the crowd, but don’t feel locked in to follow them. Try experimenting with longer trial length and see how your conversion and retention changes. Show value upfront, then give users adequate time to experience it.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;→ Your next step: &lt;/strong&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/7-day-trial-subscription-app/&quot;&gt;determine the optimum trial length for your app&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-5-a-nnual-subscriptions-aren-t-the-guarantee-you-think-they-are&quot;&gt;5. A&lt;strong&gt;nnual subscriptions aren’t the guarantee you think they are&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;When users buy an annual subscription, it feels like a sigh of relief for the developer. You relax, assuming that annual sub means 12 months to prove the app’s value. 12 months to demonstrate each carefully-designed feature, and deliver a clear message of “I should keep using this app” come Year 2.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;But the data reveals a harsh truth: &lt;strong&gt;over one third of users cancel auto-renewal within the first month.&lt;/strong&gt; Users aren’t stupid, and they don’t think of an annual subscription as a rolling purchase — they consider it a one-off payment for this year, then immediately protect their wallet. Meaning that Year 2 revenue you’d already relied on? It’s gone before Year 1 has even really begun.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-data-4&quot;&gt;&lt;strong&gt;The data:&lt;/strong&gt;&lt;/h3&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Month 1 churn:&lt;/strong&gt; the first month accounts for &lt;strong&gt;35%&lt;/strong&gt; of all annual cancellations&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;The cancellation curve:&lt;/strong&gt; after the Month 1 spike, cancellations drop to just 3–10% for the middle of the year, before spiking again in Month 12 (pre-renewal)&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Comparison to 2025: &lt;/strong&gt;~56% of annual subscribers cancelled in Year 1 in 2025, while this &lt;strong&gt;worsened &lt;/strong&gt;to ~72% in 2026; however the Month 1 cancellation spike remains fairly comparable between years&lt;/li&gt;
&lt;/ul&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;616&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-17-1024x616.png&quot; alt=&quot;&quot; class=&quot;wp-image-52438&quot; style=&quot;width:700px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-17-1024x616.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-17-300x180.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-17-768x462.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-17-1536x924.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-17-50x30.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-17-67x40.png 67w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-17-696x418.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-17-560x337.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-17-492x296.png 492w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-17-785x472.png 785w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-17-80x48.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-17-48x29.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-17.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Cancellation timeline for annual subscriptions — State of Subscription Apps 2026&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;what-next-3&quot;&gt;&lt;strong&gt;What next?&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;App teams can no longer rely on users ‘forgetting’ about an annual subscription. The battle for Year 2 starts in Week 1. You don’t have 11 months to win an annual renewal, you need to preemptively convince users to &lt;em&gt;not &lt;/em&gt;cancel auto-renew. This means intensive value reinforcement from the moment they download, and win-back campaigns throughout the first two months to persuade users to toggle auto-renew back on, while they’re first engaged.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;→ Your next step: &lt;/strong&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/annual-subscriptions-apps-pros-cons/&quot;&gt;explore the pros and cons of annual subscriptions&lt;/a&gt;, then &lt;a href=&quot;https://www.revenuecat.com/blog/growth/how-to-increase-your-annual-subscription-uptake/&quot;&gt;learn how to improve your annual subscription uptake&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-6-the-google-play-tax&quot;&gt;6. &lt;strong&gt;The Google Play tax&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;For Android devs, growth is actually an engineering problem. 31% of Google Play cancellations are involuntary billing failures — over double the rate of the App Store (14%).&amp;nbsp;&lt;/p&gt;



&lt;p&gt;When an app loses a subscriber, blame usually falls to the product features or pricing. However, for Android apps, nearly a third of churn isn’t because the user hated the app, it’s simply because their credit card failed, expired, or was declined, and the app’s billing infrastructure wasn’t robust enough to recover it.&lt;/p&gt;



&lt;p&gt;This money is unclaimed revenue: growth isn’t just about ads; it’s about plugging the technical leaks in Google Play’s ecosystem through better retry logic and grace periods.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-data-5&quot;&gt;&lt;strong&gt;The data:&lt;/strong&gt;&lt;/h3&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Google Play billing failures:&lt;/strong&gt; a massive &lt;strong&gt;31%&lt;/strong&gt; of all subscription cancellations on Google Play are due to billing errors&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;App Store comparison:&lt;/strong&gt; on the App Store, billing errors account for only &lt;strong&gt;14%&lt;/strong&gt; of cancellations&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Comparison to 2025: &lt;/strong&gt;Google Play’s billing errors have &lt;strong&gt;worsened&lt;/strong&gt;, from 28.2% in 2025 to 31% this year; meanwhile the App Store’s &lt;strong&gt;improved, &lt;/strong&gt;reducing billing errors by 1.1% (15.1% in 2025 vs. 14% in 2026)&lt;/li&gt;
&lt;/ul&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;619&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-16-1024x619.png&quot; alt=&quot;&quot; class=&quot;wp-image-52436&quot; style=&quot;width:700px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-16-1024x619.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-16-300x181.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-16-768x464.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-16-1536x928.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-16-50x30.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-16-66x40.png 66w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-16-696x421.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-16-560x338.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-16-490x296.png 490w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-16-781x472.png 781w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-16-80x48.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-16-48x29.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-16.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Cancellation reasons, by app store — State of Subscription Apps 2026&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;what-next-4&quot;&gt;&lt;strong&gt;What next?&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;If you have a significant Android user base, your highest ROI activity is optimizing your dunning process (billing retries) and enabling grace periods. Handled appropriately, Android apps can almost instantly recover 15-20% of lost revenue, without acquiring a single new user.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;→ Your next step: &lt;/strong&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/google-play-billing-error-churn-how-to-fix/&quot;&gt;learn how to counteract the Google Play billing leak&lt;/a&gt;, and &lt;a href=&quot;https://www.revenuecat.com/blog/growth/win-back-campaign-examples-ideas/&quot;&gt;set up winback campaigns for lapsed subscribers&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-7-the-ai-paradox-acquisition-beast-retention-nightmare&quot;&gt;7. &lt;strong&gt;The AI paradox: acquisition beast, retention nightmare&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;AI sells like crazy, but it doesn’t stick. While AI-powered apps generate &lt;strong&gt;41% more revenue-per-user&lt;/strong&gt;, those same apps &lt;strong&gt;churn 36% faster than non-AI apps. &lt;/strong&gt;The problem isn’t convincing users to download your AI app (clearly, users &lt;em&gt;want&lt;/em&gt; to pay for AI), the challenge is keeping them invested.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Amidst the vibe coding hype and established developers watching as new apps dilute market real estate, the data proves AI apps aren’t in it for the long haul (yet). AI features are driving massive trial revenue, yet many AI apps suffer from an alarming lack of product-market fit. Users may be willing to pay a premium to try AI tools, but once they download, they’re not finding the long-term utility to justify its hefty pricetag.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Yes, vibe coded apps can ship fast. Yes, AI features act as a massive top-of-funnel magnet, but this doesn’t guarantee the same audience further down the line. It doesn’t mean they can sustain a user base. Experienced developers still have an edge: stamina. They know how to maintain an app, build trust with an audience, and grow revenue. That is the real differentiator between what apps succeed and which fall behind — not who can build an app fastest, what AI features it has, or whether a human or agent wrote the lines of code.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-data-6&quot;&gt;&lt;strong&gt;The data:&lt;/strong&gt;&lt;/h3&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;The AI premium:&lt;/strong&gt; AI apps sustain a &lt;strong&gt;41%&lt;/strong&gt; Year 1 realized LTV premium compared to non-AI apps ($30.16 median vs. $21.37 median)&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;The churn problem:&lt;/strong&gt; Despite the high revenue, AI monthly plans retain &lt;strong&gt;36% worse&lt;/strong&gt; over 12 months than traditional apps&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Comparison to 2025: &lt;/strong&gt;AI apps showed 12-month payer retention of 9.2% (App Store) and 11.5% (Google Play), comparable to traditional apps in respective categories; suggesting 2026’s sharp dip in retention is a problem emerging after AI apps settled into mainstream and users had longer to assess them&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;616&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-15-1024x616.png&quot; alt=&quot;&quot; class=&quot;wp-image-52434&quot; style=&quot;width:700px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-15-1024x616.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-15-300x180.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-15-768x462.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-15-1536x924.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-15-50x30.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-15-67x40.png 67w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-15-696x418.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-15-560x337.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-15-492x296.png 492w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-15-785x472.png 785w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-15-80x48.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-15-48x29.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-15.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Retained subscribers after 12 months, by AI vs. non-AI — State of Subscription Apps 2026&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;what-next-5&quot;&gt;&lt;strong&gt;What next?&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Shipping fast or relying on AI hype isn’t enough. If you add AI to your app, use the influx of cash to build a genuine user experience and robust backend. Don’t rely on novelty or one-off AI gimmicks. These will only churn in a few months. Look to established apps for retention and growth lessons, then use AI to make them happen fast. The long game will be won not by AI vs. non-AI, but by whoever can utilize AI &lt;em&gt;and &lt;/em&gt;human expertise.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;→ Your next step: &lt;/strong&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/product-market-fit-subscription-apps/&quot;&gt;revisit core value offered to users and secure product-market fit&lt;/a&gt;&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-looking-to-2027&quot;&gt;&lt;strong&gt;Looking to 2027&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The data from 2026’s State of Subscription Apps report highlights emerging shifts in the app industry, from the influx of new apps (14,000+ a month!) to the rapid dissolving of the average app’s revenue safety net. But many of these trends are not surprising — Google’s billing leak has been a prominent issue for several years, and the relationship between trial length and conversion isn’t new either. What &lt;em&gt;is &lt;/em&gt;clear from 2026’s data is that &lt;strong&gt;apps can no longer afford to ignore these accumulating changes and known issues&lt;/strong&gt;.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;‘Good enough’ is no longer good enough. Just as quickly as top apps are growing their revenue, the lower quartile are churning it. Subscription apps that are designed with user value as the core and marketed with intention have found their place in the ecosystem. Their success compounds over time, and the rest of the app store is left fighting over scraps. All that’s left is for teams to decide which side of the line they wish to sit on come 2027’s report.&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-Z1ENtcA wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Dig into the data yourself&quot; text=&quot;&lt;p&gt;&lt;a href=&amp;quot;/sosa-26-insights/&amp;quot;&gt;Click here to browse the full State of Subscription Apps 2026 report online or download the PDF.&lt;/a&gt;&lt;/p&gt;&quot; icon=&quot;star&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[The 7-day trial, and other free trial myths: how to choose the right trial length for your subscription app]]></title><description><![CDATA[How to design trials that build habits, reduce churn, and drive revenue]]></description><link>https://www.revenuecat.com/blog/growth/7-day-trial-subscription-app/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/7-day-trial-subscription-app/</guid><pubDate>Thu, 19 Mar 2026 14:28:56 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Blog_33_The-right-trial-length-isnt-7-days.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;I once got a &lt;strong&gt;34-day free trial&lt;/strong&gt;. Not 30 days, not ‘one month’, but thirty-four days.&lt;/p&gt;



&lt;p&gt;It was for &lt;a href=&quot;https://www.revenuecat.com/blog/growth/web-to-app-funnel-examples/#h-4-ynab-workshop-funnel&quot;&gt;YNAB, a personal budgeting app&lt;/a&gt;. At first, it felt completely random. Most free trials hover between five and nine days, so why 34?&lt;/p&gt;



&lt;p&gt;But when I opened the app, it all made sense.&lt;/p&gt;



&lt;p&gt;Budgeting doesn’t deliver instant value; you need a full cycle:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;A payday&lt;/li&gt;



&lt;li&gt;Bills going out&lt;/li&gt;



&lt;li&gt;Real behavior over time&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;YNAB wasn’t trying to impress me in a week. They were giving me &lt;strong&gt;enough time to actually experience the product&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;That moment really stuck with me. It made me wonder: are we, as an industry, selling ourselves short by defaulting to seven-day trials?&lt;/p&gt;



&lt;p&gt;In 2024, just over half of all trials fell within the 5–9 day range, up from 2023. In 2025, trials are getting even shorter. Trials of four days or less gained share, rising to almost half (46.5%) of all trials.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;616&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Trial-durations-year-on-year-1024x616.png&quot; alt=&quot;&quot; class=&quot;wp-image-52421&quot; style=&quot;width:700px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Trial-durations-year-on-year-1024x616.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Trial-durations-year-on-year-300x180.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Trial-durations-year-on-year-768x462.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Trial-durations-year-on-year-1536x923.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Trial-durations-year-on-year-50x30.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Trial-durations-year-on-year-67x40.png 67w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Trial-durations-year-on-year-696x418.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Trial-durations-year-on-year-560x337.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Trial-durations-year-on-year-492x296.png 492w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Trial-durations-year-on-year-785x472.png 785w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Trial-durations-year-on-year-80x48.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Trial-durations-year-on-year-48x29.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Trial-durations-year-on-year.png 1780w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Trial duration, year-on-year — State of Subscription Apps 2026&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;While we’ve all heard “the 7-day trial is dead” generalization thrown around, that seems to be because trials are only getting &lt;em&gt;shorter&lt;/em&gt;. So, despite all the nuance we’re about to explore, the industry default is becoming more entrenched, not less.&lt;/p&gt;



&lt;p&gt;And that’s the problem. A seven-day trial isn’t inherently bad; it’s just rarely questioned. Trial length deserves the same level of thought as onboarding, activation, and retention.&lt;/p&gt;



&lt;p&gt;Because at the end of the day, &lt;strong&gt;trial length isn’t a pricing decision. It’s a product decision&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.linkedin.com/in/hnpvz/&quot;&gt;Hannah Parvaz,&lt;/a&gt; Founder of &lt;a href=&quot;https://aperture.london/&quot;&gt;Aperture&lt;/a&gt;, puts it:&lt;/p&gt;



&lt;p&gt;“I’m very much in the ‘trial length is a design decision, not a default’ camp. Across multiple subscription apps, the biggest mistake I see is treating trial length as a growth lever in isolation, rather than anchoring it to time-to-value and confidence-building.”&lt;/p&gt;



&lt;p&gt;That idea — that trial length is a product decision — sent me down a classic Daphne rabbit hole: &lt;strong&gt;what actually determines the right free-trial length?&lt;/strong&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-before-trial-length-should-you-even-offer-a-trial&quot;&gt;Before trial length: should you even offer a trial?&lt;/h2&gt;



&lt;p&gt;Before we dive into different trial lengths, there’s a more important question to answer first:&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Do you even need a trial?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Optimising trial length is meaningless if the trial itself is the wrong strategy.&lt;/p&gt;



&lt;p&gt;I used to think trials were a must. After all, most apps across categories offer some form of trial, according to the &lt;strong&gt;State of Subscription Apps 2026&lt;/strong&gt;:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;620&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-6-1024x620.png&quot; alt=&quot;&quot; class=&quot;wp-image-52407&quot; style=&quot;width:700px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-6-1024x620.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-6-300x182.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-6-768x465.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-6-1536x930.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-6-50x30.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-6-66x40.png 66w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-6-696x421.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-6-560x339.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-6-489x296.png 489w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-6-780x472.png 780w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-6-80x48.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-6-48x29.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-6.png 1784w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Trial strategy, by category — State of Subscription Apps 2026&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;Not a single category has a majority of apps &lt;strong&gt;without some form of trial&lt;/strong&gt;. The closest is from Social, who have the highest no-trial strategy at 43.6%.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;I read &lt;a href=&quot;https://www.revenuecat.com/blog/growth/should-your-app-stop-offering-free-trials/&quot;&gt;an article by David Vargas&lt;/a&gt; that completely changed how I think about trials — he frames it this way:&lt;/p&gt;



&lt;p&gt;“We have to remember that a free trial is just one strategy. It relies on how ‘sticky’ the product and features are to convince users to subscribe.”&lt;/p&gt;



&lt;p&gt;What really caught my attention was an experiment where David &lt;strong&gt;removed the free trial entirely&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;It felt bold (my favorite type of experiment) and slightly terrifying. But the context mattered. They were seeing strong trial-to-paid conversion, yet paid acquisition wasn’t working; the &lt;strong&gt;cost per acquisition was too high&lt;/strong&gt; once they factored in how many trial starts were needed to land a single paying customer.&lt;/p&gt;



&lt;p&gt;Removing the trial &lt;strong&gt;nearly doubled lifetime value&lt;/strong&gt; and unlocked paid growth.&lt;/p&gt;



&lt;p&gt;That’s an important consideration, even if you keep a trial. Unless your trial is very short, you’ll usually end up optimising paid channels for trial starts rather than purchases. And if conversions occur outside the attribution window, ad platforms optimize for &lt;strong&gt;people who like starting trials&lt;/strong&gt;, not for those who actually pay.&lt;/p&gt;



&lt;p&gt;So the first principle is this:&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Don’t touch trial length until you’re clear on whether a trial should exist at all.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Testing removal sounds scary, but if your trial isn’t pulling its weight, it’s worth questioning the assumption or focusing first on &lt;strong&gt;adding real value with your trial&lt;/strong&gt;. As Dan Layfield, Founder of Subscription Index (ex-Codeacademy and Uber), puts it:&lt;/p&gt;



&lt;p&gt;“Trials are your friend so long as they are visible, clear, and appealing to your users.”&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Once you’re convinced your trial should exist, then it’s time to debunk some trial myths.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-myth-shorter-trials-convert-better&quot;&gt;The myth: shorter trials convert better&lt;/h2&gt;



&lt;p&gt;Our instinct is simple: &lt;strong&gt;shorter trials create urgency, urgency drives action, and action drives conversion.&lt;/strong&gt; Simple, right?&lt;/p&gt;



&lt;p&gt;It’s the same line of thinking as running a 24-hour sale or telling users an item is almost sold out. It’s a massive kick up the rump.&lt;/p&gt;



&lt;p&gt;And sure, there are situations where short trials help, especially if you want to quickly optimize paid campaigns for purchases. But the data shows it’s more nuanced.&lt;/p&gt;



&lt;p&gt;According to &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps-2025/&quot;&gt;RevenueCat’s State of Subscription Apps report&lt;/a&gt;, shorter trials come with huge day 0-1 cancellation spikes. For three-day trials, over 55% of users cancel almost immediately. Compare that to around 31% for 30-day trials.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;618&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-4-1024x618.png&quot; alt=&quot;&quot; class=&quot;wp-image-52403&quot; style=&quot;width:700px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-4-1024x618.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-4-300x181.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-4-768x464.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-4-1536x927.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-4-50x30.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-4-66x40.png 66w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-4-696x420.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-4-560x338.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-4-490x296.png 490w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-4-782x472.png 782w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-4-80x48.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-4-48x29.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-4.png 1766w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;% of trial cancellations, by day and trial duration — State of Subscription Apps 2026&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;That early cancellation &lt;strong&gt;doesn’t automatically mean poor intent&lt;/strong&gt;. Often it’s driven by:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Lack of trust&lt;/li&gt;



&lt;li&gt;Fear of forgetting to cancel&lt;/li&gt;



&lt;li&gt;And the classic: “I’ll cancel now just in case”&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;What’s interesting is that the longer the trial, the less cancellations. 84% of 3-day trial cancellations and 64% of 7-day trial cancellations happen between day 0–1. The risk isn’t late, it’s right at the start.&lt;/p&gt;



&lt;p&gt;So no, &lt;strong&gt;shorter isn’t automatically better&lt;/strong&gt;. But now I’ll get annoying: &lt;strong&gt;longer isn’t automatically smarter either.&lt;/strong&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-longer-trials-when-they-help-and-when-they-hurt&quot;&gt;Longer trials: when they help, and when they hurt&lt;/h2&gt;



&lt;p&gt;When people hear this, they often jump straight to: &lt;strong&gt;“Longer must be better.”&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;But blindly following aggregate data is just as dangerous as defaulting to a seven-day trial.&lt;/p&gt;



&lt;p&gt;Yes, 17–32 day trials do show higher trial-to-paid conversion on average (a 42.5% median conversion vs. &amp;lt;4 day trials’ 25.5% conversion rate):&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;622&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-5-1024x622.png&quot; alt=&quot;&quot; class=&quot;wp-image-52405&quot; style=&quot;width:700px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-5-1024x622.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-5-300x182.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-5-768x466.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-5-1536x932.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-5-50x30.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-5-66x40.png 66w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-5-696x422.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-5-560x340.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-5-488x296.png 488w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-5-778x472.png 778w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-5-80x49.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-5-48x29.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-5.png 1766w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Trial-to-paid, by trial duration — State of Subscription Apps 2026&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;That sounds great, but we often assume trial-to-paid conversion automatically equals a better outcome, and that’s where things get tricky.&lt;/p&gt;



&lt;p&gt;For example, I worked with a wellness app where our key &lt;a href=&quot;https://www.revenuecat.com/blog/growth/activation-metrics/&quot;&gt;activation metric&lt;/a&gt; was consuming two long-form content pieces within 14 days. Each piece lasted about 45 minutes and was tied to (but not exclusively) a weekly live session. That behaviour was a strong predictor of long-term retention.&lt;/p&gt;



&lt;p&gt;So we asked the obvious question: &lt;strong&gt;why run a seven-day trial when our activation window is 14 days?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Time for an experiment: we A/B tested a 7-day vs 14-day trial. While the longer trial drove slightly more trial starts, fewer people converted overall.&lt;/p&gt;



&lt;p&gt;Not because people were abusing it or needed more time, but because activation didn’t improve. People weren’t consuming more content; they were delaying. Classic procrastination. It performed worse in converting to paid, and we reverted to the 7-day trial.&lt;/p&gt;



&lt;p&gt;That’s the dark side of long trials we’ve all experienced. A long gym trial feels painless to postpone, but a short, paid intro lesson you need to book within seven days forces action. “I’ll use it later” quietly becomes “I never really did.”&lt;/p&gt;



&lt;p&gt;The takeaway: &lt;strong&gt;trial conversion is just a leading metric. &lt;/strong&gt;What actually matters is:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Revenue per user over time&lt;/li&gt;



&lt;li&gt;Retention&lt;/li&gt;



&lt;li&gt;Sustained engagement&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;There’s even a great &lt;a href=&quot;https://pubsonline.informs.org/doi/10.1287/mnsc.2022.4507&quot;&gt;SaaS study&lt;/a&gt; by Hema Yoganarasimhan, Ebrahim Barzegary, and Abhishek Pani showing that shorter trials (seven days) &lt;em&gt;can&lt;/em&gt; outperform 30-day trials on acquisition, retention, and profitability.&lt;/p&gt;



&lt;p&gt;That being said, &lt;strong&gt;a user who converts on day seven and churns on day eight is not a win&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;So if you’re feeling a little confused right now, that’s fair, I’ve just dismantled both extremes (sorry!). But fear not, there is an answer: &lt;strong&gt;trial length only makes sense in context&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;Across teams, Hannah Parvaz has seen a few consistent patterns emerge:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;“If the core value is experienced in one session, long trials often hurt paid conversion. In these cases, shorter trials (or even no trial at all, with strong reassurance) outperform because users either get it quickly or they never will.&lt;/li&gt;



&lt;li&gt;“If value compounds over time (habits, learning, behaviour change), a longer trial can work, but only if the onboarding actively guides users to the &lt;em&gt;aha!&lt;/em&gt; rather than passively waiting for it to happen.&lt;/li&gt;



&lt;li&gt;Seven days is rarely optimal by default. It’s often too long for fast-value products and too short for slower, trust-based ones. We’ve seen better outcomes with everything from three days to 30 days, depending on how quickly users hit a meaningful milestone.”&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Let’s dive deeper into that context to better understand the nuances, then we’ll outline a framework to determine the right trial length for your app.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-pricing-matters-for-trial-length&quot;&gt;Pricing matters for trial length&lt;/h2&gt;



&lt;p&gt;One thing that’s easy to forget when discussing trial length is &lt;strong&gt;how closely it’s linked to pricing and packaging&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;A 14-day trial before a $5 monthly plan behaves very differently from a 14-day trial before a $120 annual commitment. In the first case, the user’s risk is low. In the second, the psychological bar is much higher: users need more proof, more confidence, or simply more time before paying feels justified.&lt;/p&gt;



&lt;p&gt;This is why you’ll often see &lt;strong&gt;longer trials attached to annual plans&lt;/strong&gt;, or trials offered only on annual pricing. It’s not about generosity, it’s about reducing perceived risk. A higher price or longer plan requires potentially a longer trial.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://subclub.com/episode/how-headspace-optimized-revenue-by-gating-content-shreya-oswal-and-keya-patel-headspace&quot;&gt;Headspace saw a strong conversion lift&lt;/a&gt; by offering a 14-day free trial with its annual plan, while offering seven days with its monthly plan. It sounds like it made users more comfortable to commit to a longer plan and helped make their annual plan more attractive.&lt;/p&gt;



&lt;figure class=&quot;wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex&quot;&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;451&quot; height=&quot;1024&quot; data-id=&quot;52417&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-11-451x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-52417&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-11-451x1024.png 451w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-11-132x300.png 132w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-11-677x1536.png 677w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-11-22x50.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-11-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-11-204x464.png 204w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-11-696x1580.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-11-247x560.png 247w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-11-130x296.png 130w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-11-208x472.png 208w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-11-35x80.png 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-11-21x48.png 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-11.png 705w&quot; sizes=&quot;auto, (max-width: 451px) 100vw, 451px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;451&quot; height=&quot;1024&quot; data-id=&quot;52415&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-10-451x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-52415&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-10-451x1024.png 451w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-10-132x300.png 132w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-10-677x1536.png 677w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-10-22x50.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-10-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-10-204x464.png 204w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-10-696x1580.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-10-247x560.png 247w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-10-130x296.png 130w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-10-208x472.png 208w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-10-35x80.png 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-10-21x48.png 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-10.png 705w&quot; sizes=&quot;auto, (max-width: 451px) 100vw, 451px&quot;&gt;&lt;/figure&gt;
&lt;/figure&gt;



&lt;p&gt;Not only that, but with shorter subscription periods, adding a trial can almost be overkill and may even devalue your app. &lt;a href=&quot;https://www.revenuecat.com/blog/growth/weekly-subscriptions/&quot;&gt;Weekly subscriptions&lt;/a&gt;, for example, already act like a trial, so you might not need another free trial on top of that. For apps that do offer a free trial with a weekly plan, they often offer only three days vs. a full week, since giving a full week free essentially devalues the subscription.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-category-matters-more-than-you-think&quot;&gt;Category matters more than you think&lt;/h2&gt;



&lt;p&gt;There is no universal ‘best’ trial length (though the data would suggest leaning towards longer). When you break down trial data by category, the differences are striking:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;616&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-8-1024x616.png&quot; alt=&quot;&quot; class=&quot;wp-image-52410&quot; style=&quot;width:700px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-8-1024x616.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-8-300x181.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-8-768x462.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-8-1536x925.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-8-50x30.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-8-66x40.png 66w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-8-696x419.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-8-560x337.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-8-492x296.png 492w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-8-784x472.png 784w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-8-80x48.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-8-48x29.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-8.png 1774w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Trial durations, by category — State of Subscription Apps 2026&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;Gaming apps overwhelmingly favor very short trials, often under four days. Longer trials invite abuse, with players optimising for completion rather than habit formation.&lt;/p&gt;



&lt;p&gt;Photo &amp;amp; Video apps also skew short, because value is immediate; users can edit meaningful content quickly and see the tool’s benefits.&lt;/p&gt;



&lt;p&gt;By contrast, Health &amp;amp; Fitness, Education, and Travel apps require more time for progress or focus on more serious commitments (e.g. booking a vacation). Trials of 5–9 days are far more common here, which helps explain why seven days became the industry default.&lt;/p&gt;



&lt;p&gt;But common doesn’t mean correct. Hence my polite begging: please don’t default to seven days. The key principle is that &lt;strong&gt;trial length should align with activation time, not pricing norms or industry practices.&lt;/strong&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-engagement-is-the-silent-killer-of-long-trials&quot;&gt;Engagement is the silent killer of long trials&lt;/h2&gt;



&lt;p&gt;Long trials often look good on the surface, but in reality, they’re much harder to manage. It’s a classic case of Instagram versus reality — the gorgeous holiday photo versus the food poisoning that left you bedbound.&lt;/p&gt;



&lt;p&gt;A long trial with YNAB works because the burden shifts to the product; they actively guide users through workshops, live sessions, and a clear methodology.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;391&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-3-1024x391.png&quot; alt=&quot;&quot; class=&quot;wp-image-52401&quot; style=&quot;width:900px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-3-1024x391.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-3-300x114.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-3-768x293.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-3-50x19.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-3-105x40.png 105w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-3-696x265.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-3-560x214.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-3-840x320.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-3-80x31.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-3-48x18.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-3.png 1455w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;YNAB’s web-to-app funnel is focused on you attending a live free workshop&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;The trial isn’t passive. Rather, it’s structured, and sadly, that’s rare.&lt;/p&gt;



&lt;p&gt;For most apps, the question isn’t: “Can we get someone to try it once?” It’s: “Can we build a habit before they lose momentum?”&lt;/p&gt;



&lt;p&gt;To do that, you need to:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Drive repeat usage&lt;/li&gt;



&lt;li&gt;Prevent procrastination&lt;/li&gt;



&lt;li&gt;Continuously build perceived value&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;I experienced this recently with GOWOD, a mobility app offering a 14-day trial. The onboarding was strong; they started with a mobility assessment, which is great (my hip mobility definitely needs some work).&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;662&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-9-1024x662.png&quot; alt=&quot;&quot; class=&quot;wp-image-52413&quot; style=&quot;width:900px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-9-1024x662.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-9-300x194.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-9-768x497.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-9-1536x994.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-9-50x32.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-9-62x40.png 62w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-9-696x450.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-9-560x362.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-9-458x296.png 458w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-9-730x472.png 730w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-9-80x52.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-9-48x31.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-9.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;But mobility is one of those things we know we should do, but rarely prioritize. A long trial made it easy to delay. I started the trial during a busy period, thinking I’d surely find time to complete some sessions.&lt;/p&gt;



&lt;p&gt;In reality, I didn’t manage more than two in 14 days, definitely not enough to build the habit. If I’d had a clearer goal or challenge, I might have stuck to it, e.g. committing to X sessions per week for the two weeks and measuring my mobility again afterwards.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-freemium-and-free-trials&quot;&gt;Freemium and free trials&lt;/h3&gt;



&lt;p&gt;Freemium complicates things even further. I’ve seen apps offer such generous freemium access and long trials that I honestly start wondering if they want people to pay at all.&lt;/p&gt;



&lt;p&gt;A &lt;a href=&quot;https://pmc.ncbi.nlm.nih.gov/articles/PMC12217587/&quot;&gt;study&lt;/a&gt; by Ling Zhang and Jiang Duan, focused on a freemium SaaS company, found that longer trials &lt;strong&gt;increase trial starts but don’t necessarily improve conversion&lt;/strong&gt;. If users aren’t getting enough value to pay, trial length won’t save you. But here is where the study gets interesting: longer trials did boost &lt;em&gt;delayed&lt;/em&gt; conversion: users who had more time to test premium features come back to convert later on.&lt;/p&gt;



&lt;p&gt;This explains why apps like Strava and Medium deliberately offer 30-day trials despite appearing ‘simple’. They’re not optimizing for immediate conversion — they’re playing a longer game.&lt;/p&gt;



&lt;figure class=&quot;wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-2 is-layout-flex wp-block-gallery-is-layout-flex&quot;&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;451&quot; height=&quot;1024&quot; data-id=&quot;52409&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-7-451x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-52409&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-7-451x1024.png 451w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-7-132x300.png 132w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-7-677x1536.png 677w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-7-22x50.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-7-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-7-204x464.png 204w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-7-696x1580.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-7-247x560.png 247w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-7-130x296.png 130w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-7-208x472.png 208w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-7-35x80.png 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-7-21x48.png 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-7.png 705w&quot; sizes=&quot;auto, (max-width: 451px) 100vw, 451px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;451&quot; height=&quot;1024&quot; data-id=&quot;52419&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-12-451x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-52419&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-12-451x1024.png 451w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-12-132x300.png 132w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-12-676x1536.png 676w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-12-22x50.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-12-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-12-204x464.png 204w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-12-696x1582.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-12-246x560.png 246w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-12-130x296.png 130w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-12-208x472.png 208w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-12-35x80.png 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-12-21x48.png 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-12.png 704w&quot; sizes=&quot;auto, (max-width: 451px) 100vw, 451px&quot;&gt;&lt;/figure&gt;
&lt;/figure&gt;



&lt;p&gt;Take into consideration the various factors that impact a lot of freemium apps:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;The value of network effects: &lt;/strong&gt;a lot of freemium apps depend on word of mouth for growth — and also for valuable data, e.g. Strava needs enough users in an area for a sport to segment leaderboards. Medium readers feed the algorithm on which content is engaging and which isn’t.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Value accrues over time: &lt;/strong&gt;in Strava’s case, I can also imagine that many of their data features (e.g. analyzing your performance) take more than a week to appear. Freemium apps tend to be ‘slow burns’, and if you’re offering premium features only behind a paywall (vs. allowing a taster of features upfront) a longer trial may add value. The same goes for Medium, where readers build up a list of writers and content they like. This also increases the switching costs over time.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;So there’s an additional layer of complexity: does a longer trial create network effects or switching costs that outweigh lower immediate conversion? For platform businesses, the answer is often yes.&lt;/p&gt;



&lt;p&gt;If you’re freemium, the real question isn’t trial length — it’s how much value must be locked behind the paywall for paying to make sense, while still keeping free users engaged enough to strengthen the ecosystem.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-psychology-behind-trial-length&quot;&gt;The psychology behind trial length&lt;/h2&gt;



&lt;p&gt;Once you zoom out, &lt;strong&gt;trial length is really about psychology&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;Loss aversion is the big one. Ending a trial can feel like losing something you already own, especially when users have:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Invested time&lt;/li&gt;



&lt;li&gt;Created data&lt;/li&gt;



&lt;li&gt;Built routines&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;This isn’t strictly about duration; it’s about investment. Photo editing apps can create loss aversion in just a few days. Games can do it even faster. Other products need longer.&lt;/p&gt;



&lt;p&gt;That links closely to the endowment effect. The more effort users put in, the harder it feels to walk away. Think IKEA furniture: frustrating to build, yet weirdly hard to get rid of once assembled (unless, like me, you manage to break it while building).&lt;/p&gt;



&lt;p&gt;But &lt;strong&gt;longer trials only work if investment feels natural and repeatable&lt;/strong&gt;, not a one-off setup task, but something that builds over time.&lt;/p&gt;



&lt;p&gt;On the flip side, urgency is where shorter trials shine. They force early engagement and reduce procrastination.&lt;/p&gt;



&lt;p&gt;Every trial sits on a tension line:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://phiture.com/mobilegrowthstack/the-subscription-stack-how-to-optimize-trial-length/&quot;&gt;Urgency vs. habit formation&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;Speed vs. depth&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Usage frequency matters:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Daily-use apps can build habits quickly.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Weekly or monthly cadence products need longer exposure.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Now add &lt;strong&gt;cognitive load&lt;/strong&gt; into the mix (slight psychology 101 here, but bear with me!):&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Complex products require learning time&lt;/li&gt;



&lt;li&gt;Simple products don’t — causing unnecessary friction&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The simplest way to frame it is this: &lt;strong&gt;your trial should be long enough to form a habit, but short enough to avoid being forgotten.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;A practical framework to choose your trial length&lt;/p&gt;



&lt;p&gt;To make this actionable, I like thinking in terms of natural usage habits — a concept popularized by &lt;a href=&quot;https://phiture.com/mobilegrowthstack/&quot;&gt;Phiture’s Mobile Growth Stack&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;Before choosing a trial length, ask three key questions inspired by this model:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;How often must users engage to experience value? &lt;/strong&gt;Consider the balance of usage frequency and number of engagement moments. For example, with one app, helping users make five new friends vs. just one hugely improved retention.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;When does the first real &lt;/strong&gt;&lt;strong&gt;&lt;em&gt;aha!&lt;/em&gt;&lt;/strong&gt;&lt;strong&gt; moment happen? &lt;/strong&gt;This isn’t the end goal (like running a marathon with Strava), it’s the point where users see clear progress, like completing the first few workouts, or achieving some measurable milestone.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;What behavior must exist before paying makes sense? &lt;/strong&gt;Identify the minimum meaningful behaviour that signals the product is valuable and worth paying for. This is the threshold where the trial converts into a paying experience.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Even then, I can’t recommend enough that you should run a test: measure both the short and long-term impact of any trial duration change. That’s why thinking through the questions above first is so important.&lt;/p&gt;



&lt;p&gt;If you’re still unsure, here are some rough guidelines (not rules!) to help:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;3–7 days: &lt;/strong&gt;simple utilities, games, and quick-value apps&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;7–14 days: &lt;/strong&gt;daily-use apps where time is needed for habit formation&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;14–30 days: &lt;/strong&gt;weekly cadence tools, like a project management app, where users need 2–3 cycles to see value&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;30+ days: &lt;/strong&gt;complex analytics or reporting tools, where onboarding, guidance, and meaningful data collection take time&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Advanced thinking: not all users need the same trial&lt;/p&gt;



&lt;p&gt;If you have a big enough user base, you can take trial experimentation further. Different users may benefit from different trial lengths:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Fast activators vs. slow starters&lt;/li&gt;



&lt;li&gt;Freemium-activated users vs. cold starts&lt;/li&gt;



&lt;li&gt;Monthly vs. annual plans (some teams only offer trials on annual plans)&lt;/li&gt;



&lt;li&gt;Trials as part of win-back flows&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The caveat: complexity only helps if you execute it well. Over-engineering monetization often creates confusion rather than clarity.&lt;/p&gt;



&lt;p&gt;It’s also worth noting that there are &lt;a href=&quot;https://www.revenuecat.com/blog/growth/app-trial-conversion-rate-insights/&quot;&gt;App Store limitations around trial length and setup&lt;/a&gt;. To get fancy like YNAB, you may need a web-based trial (luckily, &lt;a href=&quot;https://www.revenuecat.com/blog/growth/web-to-app-funnels/&quot;&gt;web-to-app&lt;/a&gt; is all the rage these days). Just ensure the user experience matches what users see in-app—otherwise, &lt;a href=&quot;https://developer.apple.com/forums/thread/129010&quot;&gt;Apple may reject your app&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;Alternatively, if you want to test extended trials for specific users, you could use &lt;a href=&quot;https://docs.revenuecat.com/docs/ios-subscription-offers&quot;&gt;promotional offers on iOS&lt;/a&gt;. On Android, you can &lt;a href=&quot;https://docs.revenuecat.com/reference#defer-a-google-subscription&quot;&gt;defer a subscription’s expiry via code&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;This kind of segmentation is typically only viable once you have strong activation signals and enough volume to avoid muddying your results.&lt;/p&gt;



&lt;p&gt;Beyond the 7-day default&lt;/p&gt;



&lt;p&gt;So please don’t default to seven days. While it isn’t a bad starting point for most apps, there are plenty of cases where shorter or longer trials could have a more meaningful impact.&lt;/p&gt;



&lt;p&gt;First, decide whether a trial should exist at all, and ensure it effectively activates users. Be bold, like David, and test removing it entirely. If you test trial length, use the right measures of success: trial starts, and trial-to-paid conversion rates aren’t the full scorecard — activation, retention, and revenue are.&lt;/p&gt;



&lt;p&gt;Next, understand your users’ psychology. Do they need urgency or time to invest? Does loss aversion play a role? Context matters, as gaming thrives on short trials, while Health &amp;amp; Fitness apps often default to longer ones for good reason.At the end of the day, the right trial length isn’t the one that converts the most users. &lt;strong&gt;It’s the one that creates customers who actually stick around&lt;/strong&gt;.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Announcing StartApp School: Free courses from the experts who’ve scaled what you’re building]]></title><description><![CDATA[Turn your app idea into a durable, profitable business with free courses from industry experts.]]></description><link>https://www.revenuecat.com/blog/company/announcing-startapp-school/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/company/announcing-startapp-school/</guid><pubDate>Thu, 19 Mar 2026 09:24:10 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/announcing-startapp-school.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;At RevenueCat, we get a front-row seat to what separates the apps that scale from the ones that stall. We see the pricing experiments that work, the paywalls that convert, and the retention strategies that keep users coming back month after month. We wanted to package those insights into something builders can learn from directly – so we’re launching &lt;strong&gt;&lt;a href=&quot;https://www.startapp.school/&quot;&gt;StartApp School&lt;/a&gt;&lt;/strong&gt;, a completely free educational resource to help you turn your app into a profitable, lasting business.&lt;/p&gt;



&lt;p&gt;We’ve partnered with operators who’ve done this work firsthand to build practical, strategy-focused courses covering the pillars of app growth. No fluff, no theory for theory’s sake — just the frameworks and decisions that matter at each stage.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-four-courses-available-now&quot;&gt;Four courses, available now&lt;/h2&gt;



&lt;p&gt;We’re launching with four courses that cover the ground where most apps either break through or break down: monetization, acquisition, retention, and product strategy.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-finding-the-idea-worth-building&quot;&gt;&lt;a href=&quot;https://www.startapp.school/courses/how-to-make-an-app-people-will-pay-for&quot;&gt;Finding the idea worth building&lt;/a&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;a href=&quot;https://www.startapp.school/courses/how-to-make-an-app-people-will-pay-for&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;760&quot; height=&quot;420&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/daphne-course.png&quot; alt=&quot;&quot; class=&quot;wp-image-52385&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/daphne-course.png 760w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/daphne-course-300x166.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/daphne-course-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/daphne-course-72x40.png 72w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/daphne-course-696x385.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/daphne-course-560x309.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/daphne-course-536x296.png 536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/daphne-course-80x44.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/daphne-course-48x27.png 48w&quot; sizes=&quot;auto, (max-width: 760px) 100vw, 760px&quot;&gt;&lt;/a&gt;&lt;/figure&gt;



&lt;p&gt;Most apps don’t fail because of bad code – they fail because nobody validated whether people would pay. &lt;strong&gt;Daphne Tideman&lt;/strong&gt; (Growth Advisor &amp;amp; Consultant) walks you through finding your niche, pressure-testing willingness to pay, and building a launch roadmap that doesn’t waste your first six months.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-turning-your-paywall-into-a-revenue-engine&quot;&gt;&lt;a href=&quot;https://www.startapp.school/courses/paywall-optimization-for-apps&quot;&gt;Turning your paywall into a revenue engine&lt;/a&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;a href=&quot;https://www.startapp.school/courses/paywall-optimization-for-apps&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;760&quot; height=&quot;420&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/vahe-course.png&quot; alt=&quot;&quot; class=&quot;wp-image-52387&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/vahe-course.png 760w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/vahe-course-300x166.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/vahe-course-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/vahe-course-72x40.png 72w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/vahe-course-696x385.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/vahe-course-560x309.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/vahe-course-536x296.png 536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/vahe-course-80x44.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/vahe-course-48x27.png 48w&quot; sizes=&quot;auto, (max-width: 760px) 100vw, 760px&quot;&gt;&lt;/a&gt;&lt;/figure&gt;



&lt;p&gt;Most apps leave serious money on the table at the paywall. &lt;strong&gt;Vahe Baghdasaryan&lt;/strong&gt; (Founder &amp;amp; CEO, Tangent) breaks down the psychology behind when and why users pay, and teaches you how to run repeatable pricing and placement experiments that compound over time.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-acquiring-users-without-burning-your-budget&quot;&gt;&lt;a href=&quot;https://www.startapp.school/courses/paid-user-acquisition-for-apps&quot;&gt;Acquiring users without burning your budget&lt;/a&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;a href=&quot;https://www.startapp.school/courses/paid-user-acquisition-for-apps&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;760&quot; height=&quot;420&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/natalie-course.png&quot; alt=&quot;&quot; class=&quot;wp-image-52389&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/natalie-course.png 760w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/natalie-course-300x166.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/natalie-course-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/natalie-course-72x40.png 72w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/natalie-course-696x385.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/natalie-course-560x309.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/natalie-course-536x296.png 536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/natalie-course-80x44.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/natalie-course-48x27.png 48w&quot; sizes=&quot;auto, (max-width: 760px) 100vw, 760px&quot;&gt;&lt;/a&gt;&lt;/figure&gt;



&lt;p&gt;Paid UA is easy to start and expensive to get wrong. &lt;strong&gt;Natalia Drozd&lt;/strong&gt; (Marketing &amp;amp; Growth Lead) covers how to pick the right channels, build creatives that actually convert, and scale spend without watching your CAC spiral out of control.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-keeping-the-users-you-already-have&quot;&gt;&lt;a href=&quot;https://www.startapp.school/courses/lifecycle-marketing-for-apps&quot;&gt;Keeping the users you already have&lt;/a&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;a href=&quot;https://www.startapp.school/courses/lifecycle-marketing-for-apps&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;760&quot; height=&quot;420&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/alice-course.png&quot; alt=&quot;&quot; class=&quot;wp-image-52391&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/alice-course.png 760w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/alice-course-300x166.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/alice-course-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/alice-course-72x40.png 72w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/alice-course-696x385.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/alice-course-560x309.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/alice-course-536x296.png 536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/alice-course-80x44.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/alice-course-48x27.png 48w&quot; sizes=&quot;auto, (max-width: 760px) 100vw, 760px&quot;&gt;&lt;/a&gt;&lt;/figure&gt;



&lt;p&gt;Acquisition gets the glory, but retention pays the bills. &lt;strong&gt;Alice Muir Kocourková&lt;/strong&gt; (Growth Consultant) teaches you how to build lifecycle messaging that converts free users, reduces churn, and wins back the ones who slipped away.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-built-for-people-who-are-already-busy&quot;&gt;Built for people who are already busy&lt;/h2&gt;



&lt;p&gt;Each course is made up of short video lessons you can work through at your own pace – binge a full course in an afternoon or knock out one lesson over coffee. Complete a course and pass the quizzes to earn a certificate.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1005&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/startapp-school-quiz-example-1005x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-52398&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/startapp-school-quiz-example-1005x1024.png 1005w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/startapp-school-quiz-example-295x300.png 295w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/startapp-school-quiz-example-768x782.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/startapp-school-quiz-example-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/startapp-school-quiz-example-39x40.png 39w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/startapp-school-quiz-example-456x464.png 456w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/startapp-school-quiz-example-696x709.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/startapp-school-quiz-example-550x560.png 550w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/startapp-school-quiz-example-291x296.png 291w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/startapp-school-quiz-example-463x472.png 463w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/startapp-school-quiz-example-48x48.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/startapp-school-quiz-example.png 1304w&quot; sizes=&quot;auto, (max-width: 1005px) 100vw, 1005px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;Test your understanding as you work through the lessons&lt;/figcaption&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-more-courses-coming-throughout-2026&quot;&gt;More courses coming throughout 2026&lt;/h2&gt;



&lt;p&gt;We’re starting with four, but we’re not stopping here. We’ll be adding new courses throughout the year covering more of the problems you’re actually dealing with as you grow.&lt;/p&gt;



&lt;p&gt;Enrollment is free and open now.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://www.startapp.school/&quot;&gt;Explore StartApp School →&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;&lt;em&gt;Have a topic you want us to cover? Tell us on &lt;a href=&quot;https://x.com/RevenueCat/status/2033921788699197621&quot;&gt;Twitter&lt;/a&gt; or &lt;a href=&quot;https://www.linkedin.com/posts/revenuecat_startapp-school-by-revenuecat-activity-7439687344187830273-1qYt?utm_source=share&amp;amp;utm_medium=member_desktop&amp;amp;rcm=ACoAAAzMmVgBUxDjift40fZ7QZBorscad_ESP2A&quot;&gt;LinkedIn&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;/project/019d0035-dd45-77e0-ab77-eefe9ac98a71&quot;&gt;&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[How Coconote hit $1M ARR in 4 months with no paid ads]]></title><description><![CDATA[On the podcast: about hitting $1M ARR in four months with no paid ads, why trial extensions beat discounts for saving cancellations, and why you should be hiring content creators, not influencers.]]></description><link>https://www.revenuecat.com/blog/growth/brett-zack-coconote-sub-club-podcast-2026/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/brett-zack-coconote-sub-club-podcast-2026/</guid><pubDate>Wed, 18 Mar 2026 13:41:04 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/RC-Blog-Cover-Coconote-1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;As co-founders of the AI-powered note-taking app Coconote, Brett Bauman and Zack Hargett bootstrapped their way to $6.7M in ARR and an exit to Quizlet in under two years. In a recent episode of Sub Club, they explained the counterintuitive growth engine that got them there: a disciplined focus on organic content, a premium pricing model that built trust, and a series of small product bets that delivered huge conversion wins. It’s a playbook for anyone trying to build a durable consumer subscription business in a world where paid acquisition is no longer the default answer.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;$6.7M ARR, No Paid Ads, and an Exit to Quizlet in 2 Years – Brett Bauman &amp;amp; Zack Hargett, Coconote&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/Wg70HlO-5gY?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;iframe loading=&quot;lazy&quot; width=&quot;100%&quot; height=&quot;180&quot; frameborder=&quot;no&quot; scrolling=&quot;no&quot; seamless=&quot;&quot; src=&quot;https://share.transistor.fm/e/07d90e73?color=FFFFFF&amp;amp;background=30343C&quot;&gt;&lt;/iframe&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-growth-engine-wasn-t-ads-it-was-creators&quot;&gt;&lt;strong&gt;The growth engine wasn’t ads — it was creators&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;From day one, the Coconote team made a critical decision: they would not rely on paid ads. Instead, they went all-in on organic content, building a small, agile team of about 25 part-time content creators. Their insight was that in an algorithm-driven world, the quality of the content matters more than the size of the audience.&lt;/p&gt;



&lt;p&gt;“The strategy wasn’t to find an influencer who had an audience,” Zack explained. “The strategy was to find a content creator who produces great content.”&lt;/p&gt;



&lt;p&gt;They actively avoided creators represented by agencies, which they saw as a signal that the “alpha” was already gone. Instead, they looked for creators with 5-10K followers and a personal email in their bio — a sweet spot for finding raw talent. This hands-on approach allowed them to build a growth engine that was not only cost-effective but also more authentic and resilient than a traditional ad-based model.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-for-retention-trial-extensions-beat-discounts&quot;&gt;&lt;strong&gt;For retention, trial extensions beat discounts&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;When it came to retaining users, the team tested the standard playbook of offering discounts to users who tried to cancel. But the data revealed a more powerful strategy: offering a trial extension. They found that many users weren’t canceling because of the price; they just hadn’t had enough time to fully experience the product’s value.&lt;/p&gt;



&lt;p&gt;“We’re able to retain 25% of people from canceling,” Brett noted. “And [the trial extension] was the most successful one by far, and it really keeps people on that auto-renew.”&lt;/p&gt;



&lt;p&gt;By offering seven more days, they addressed the user’s real objection without devaluing the product. It was a simple, non-obvious insight that had a significant impact on their conversion and retention rates, proving that sometimes the best way to keep a user is to give them more time, not a lower price.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-small-onboarding-changes-big-conversion-wins&quot;&gt;&lt;strong&gt;Small onboarding changes, big conversion wins&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Coconote’s growth wasn’t just about marketing; it was also driven by a relentless focus on product optimization. The team ran numerous experiments to improve their onboarding flow, and two changes, in particular, stood out.&lt;/p&gt;



&lt;p&gt;First, they doubled the length of their onboarding to 15 screens. While this might seem like adding friction, it actually increased trial starts by 16% by giving users a more personalized and value-driven introduction to the app. Second, they moved the login screen from the beginning of the onboarding to after the paywall. This simple change eliminated a 10% drop-off from users who were unwilling to create an account before seeing the product’s value.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-takeaway&quot;&gt;&lt;strong&gt;The takeaway&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;In the full episode, Brett and Zack go deeper on their pricing strategy, the psychology of building a premium brand for a student audience, and the emotional journey of navigating an acquisition while still running the business day-to-day.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-guest-links&quot;&gt;&lt;strong&gt;Guest links:&lt;/strong&gt;&lt;/h3&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Brett Bauman: &lt;a href=&quot;https://www.linkedin.com/in/brett-bauman&quot;&gt;LinkedIn&lt;/a&gt;, &lt;a href=&quot;https://x.com/brttbmn&quot;&gt;X/Twitter&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;Zack Hargett: &lt;a href=&quot;https://www.linkedin.com/in/zackaryhargett&quot;&gt;LinkedIn&lt;/a&gt;, &lt;a href=&quot;https://x.com/zackhargett&quot;&gt;X/Twitter&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://quizlet.com/careers&quot;&gt;Quizlet Careers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Apple guidelines explained: remote testing your iOS app (without getting your account banned)]]></title><description><![CDATA[Where Apple draws the line on remote config: safe experiments vs. violations]]></description><link>https://www.revenuecat.com/blog/engineering/ios-remote-testing-ban/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/ios-remote-testing-ban/</guid><pubDate>Wed, 18 Mar 2026 13:00:14 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Remote-testing-in-your-iOS-app-without-getting-your-account-banned.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;If you’re a developer trying to optimize your app’s revenue, A/B testing and remote configuration aren’t just nice-to-haves – they’re how you find your edge. You need to test paywalls, tweak onboarding flows, and roll out features gradually to see what actually moves the needle&lt;/p&gt;



&lt;p&gt;But there’s a lingering fear: &lt;em&gt;If I change my app remotely without going through App Review, will Apple ban my account?&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;Short answer: No, as long as you understand the rules of the game&lt;/p&gt;



&lt;p&gt;Apple isn’t against A/B testing. In fact, they offer their own Product Page Optimization tools for testing App Store assets. The key to testing safely inside your app comes down to understanding the difference between changing &lt;em&gt;data&lt;/em&gt; and changing &lt;em&gt;code&lt;/em&gt; – and respecting the spirit of the review process&lt;/p&gt;



&lt;p&gt;Let’s break down what you can (and should) be testing remotely, how to do it safely, and where the hard lines are drawn&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-green-light-what-you-should-be-testing&quot;&gt;The green light: what you should be testing&lt;/h2&gt;



&lt;p&gt;The golden rule for remote testing is Guideline 2.5.2. It states that apps “may not download, install, or execute code which introduces or changes features or functionality of the app”&lt;/p&gt;



&lt;p&gt;Notice the word &lt;em&gt;code&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;If you are using remote config (like Firebase or RevenueCat Offerings) to change &lt;em&gt;data&lt;/em&gt; – JSON payloads that tell your existing, pre-compiled code how to behave – you are generally in the clear. Here are the high-impact areas you should absolutely be testing:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Paywall UI and copy&lt;/strong&gt;: changing the background color of your paywall, swapping out the hero image, or testing “Start Free Trial” versus “Subscribe Now” is perfectly fine. The code to render a button is already in the app; you’re just telling it what text to display. This is the lowest-hanging fruit for conversion optimization&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Pricing and packaging&lt;/strong&gt;: swapping which StoreKit products are shown on your paywall (e.g., testing an annual vs. monthly default, or introducing a new tier) is standard practice. As long as the products themselves are approved in App Store Connect, dynamically choosing which ones to display is safe and encouraged&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Feature flags for gradual rollouts&lt;/strong&gt;: if you’ve built a new feature, included the code in the binary you submitted to Apple (and made sure the reviewer could actually access it), and just want to turn it on for 10% of your users to monitor crash rates or engagement, you’re safe. The feature was there during review, even if it was dormant&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Onboarding flows&lt;/strong&gt;: re-ordering the screens in your onboarding flow or changing the text on those screens to better explain your value proposition is a great use of remote config. You’re optimizing the user journey using existing components&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-nuance-it-s-about-the-spirit-of-the-review&quot;&gt;The nuance: it’s about the spirit of the review&lt;/h2&gt;



&lt;p&gt;Where developers get into trouble isn’t usually the &lt;em&gt;mechanism&lt;/em&gt; of remote config, but &lt;em&gt;what&lt;/em&gt; they are configuring. The most common trap is bypassing the spirit of the App Review process&lt;/p&gt;



&lt;p&gt;Let’s look at a classic example: testing a hard paywall versus a soft paywall&lt;/p&gt;



&lt;p&gt;A soft paywall allows users to dismiss it and use some limited version of the app. A hard paywall blocks all access until the user subscribes. Developers often want to A/B test these two approaches to see which yields higher LTV&lt;/p&gt;



&lt;p&gt;The problem? A hard paywall fundamentally changes the nature of the app. If your App Store metadata and screenshots show a free app with optional premium features, but a remote config flag suddenly locks 50% of your users out of the app entirely, you’ve created a discrepancy&lt;/p&gt;



&lt;p&gt;Apple reviewed and approved a freemium app. You are now delivering a paid-upfront experience. This violates Guideline 2.3.1 (Accurate Metadata) because customers don’t know what they’re getting when they download the app&lt;/p&gt;



&lt;p&gt;It’s not the remote config that gets you rejected here; it’s the bait-and-switch. If you want to test a hard paywall, the safest approach is to submit the app with the hard paywall active for review, ensuring your App Store presence accurately reflects that experience&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-red-light-what-will-actually-get-you-banned&quot;&gt;The red light: what will actually get you banned&lt;/h2&gt;



&lt;p&gt;While Apple is generally fine with data-driven A/B testing, there are a few lines you absolutely cannot cross. Apple’s Introduction to the guidelines is very clear: “If you attempt to cheat the system (for example, by trying to trick the review process… your apps will be removed from the store and you will be expelled from the Apple Developer Program”. Here’s what to watch out for.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-review-detection-pattern&quot;&gt;&lt;strong&gt;The ‘Review Detection’ pattern&lt;/strong&gt; &lt;/h3&gt;



&lt;p&gt;This is the most common fatal mistake. Developers use remote config to detect when their app is being reviewed by Apple (often by checking IP addresses or looking for specific test accounts) and show a clean, compliant version of the app. Once approved, they flip a switch and turn on aggressive monetization tactics. Apple actively looks for this, and if they catch you, your account is gone&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-web-checkout-swap&quot;&gt;&lt;strong&gt;The web checkout swap&lt;/strong&gt; &lt;/h3&gt;



&lt;p&gt;Following the Epic v. Apple ruling, developers in the US can now link to external web checkouts. But many developers misinterpret this ruling and use remote config to swap their IAP paywall for a web checkout after review. This is a fast track to rejection for several reasons:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;The ruling requires most apps to still offer IAP &lt;em&gt;alongside&lt;/em&gt; the external link. You can’t just replace it entirely&lt;/li&gt;



&lt;li&gt;The ruling only applies to the US storefront. If your remote config enables web checkout globally, you’re violating guidelines in every other country&lt;/li&gt;



&lt;li&gt;Changing the fundamental payment mechanism post-review is seen as hiding functionality&lt;/li&gt;
&lt;/ol&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-native-stripe-sdk-trap&quot;&gt;&lt;strong&gt;The native Stripe SDK trap&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Another common misunderstanding of the Epic ruling is thinking you can now use Stripe’s native mobile SDK (like Payment Sheet) to process digital subscriptions inside your app. You can’t. Apple allows a &lt;em&gt;link&lt;/em&gt; that opens the &lt;em&gt;default browser&lt;/em&gt; (not a WebView) to an external checkout page. If you use remote config to turn on a native Stripe checkout for digital goods, you will be rejected. If you turn it on after passing review with an app that didn’t show this checkout, you risk an account ban&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-downloading-executable-code&quot;&gt;&lt;strong&gt;Downloading executable code&lt;/strong&gt; &lt;/h3&gt;



&lt;p&gt;You cannot download new JavaScript or native code that adds entirely new screens or functionality that wasn’t in the reviewed binary. You can change the data that populates a screen, but you can’t download the screen itself&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-yellow-light-navigating-the-grey-area&quot;&gt;The yellow light: navigating the grey area&lt;/h2&gt;



&lt;p&gt;Even when you’re playing by the rules, you might stumble into Guideline 5.6: Developer Code of Conduct. This guideline states that apps should not engage in “manipulative practices” to trick users into making unwanted purchases&lt;/p&gt;



&lt;p&gt;Because “manipulative” is subjective, this creates a grey area for certain types of tests:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Exit offers&lt;/strong&gt;: when a user tries to close your paywall, you pop up a secondary offer with a discount. Is this a smart e-commerce win-back strategy, or is it manipulative? We’ve seen apps get rejected for this under Guideline 5.6, yet many top-grossing apps do it every day&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Aggressive back-to-back paywalls&lt;/strong&gt;: showing a paywall during onboarding, and then immediately showing another one if the user declines, often triggers a 5.6 rejection&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;If you’re going to experiment in these grey areas, transparency is your best friend. Never try to hide your experiments from App Review. If you’re testing an exit offer, make sure it’s active in the build you submit. Use your App Review notes to explain your A/B testing setup: “We are currently running an A/B test on our paywall flow. The reviewer may see either Variant A or Variant B”&lt;/p&gt;



&lt;p&gt;Remote testing is a powerful tool for growth. As long as you’re using it to optimize the user experience and find the right pricing – rather than trying to sneak unapproved features past Apple – you can test with confidence.&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;A loving note from our editor:&lt;/strong&gt;&amp;nbsp;you may have noticed this blog post is missing periods at the end of many paragraphs. Please don’t be thrown off or think we haven’t spotted this; it is simply the signature trademark of Rik Haandrikman, VP of Marketing at RevenueCat.&lt;/em&gt;&amp;nbsp;&lt;em&gt;For more of his antics,&amp;nbsp;&lt;a href=&quot;https://x.com/HHaandr&quot;&gt;follow Rik on X&lt;/a&gt;&amp;nbsp;(you’ll know you’ve found the right account when you stop seeing periods).&lt;/em&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Build web-to-app funnels to convert more traffic]]></title><description><![CDATA[RevenueCat Funnels is in public beta.]]></description><link>https://www.revenuecat.com/blog/company/funnels-public-beta/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/company/funnels-public-beta/</guid><pubDate>Tue, 17 Mar 2026 13:45:33 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Blog_33_Funnels-public-beta.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;The path from ad click to paying subscriber is rough. Users move through app store listings, download waits, onboarding screens, and a paywall. Each step bleeds users, and by the time someone reaches your paywall, you’ve already lost most of the people you paid to acquire.&lt;/p&gt;



&lt;p&gt;Web-to-app funnels flip this. You capture, qualify, and convert users on the web before they ever touch the App Store. But building one has always meant stitching together landing page tools, payment processors, analytics platforms, and custom code to connect it all back to your app.&lt;/p&gt;



&lt;p&gt;RevenueCat Funnels is now in public beta, and it replaces that entire DIY stack.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;Introducing RevenueCat Funnels&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/E5OFGHfkX-I?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-a-no-code-builder-for-web-to-app-onboarding-funnels&quot;&gt;A no-code builder for web-to-app onboarding funnels&lt;/h2&gt;



&lt;p&gt;RevenueCat Funnels lets you design multi-step web experiences in a visual editor, connect them with branching logic, and deploy them to a hosted URL — build and deploy without touching web development, infrastructure, or engineering queues.&lt;/p&gt;



&lt;p&gt;If you’ve used the RevenueCat Paywall Builder, the editor will feel familiar. It’s the same drag-and-drop system, expanded into a full canvas where you connect multiple screens into complete acquisition journeys.&lt;/p&gt;



&lt;p&gt;Here’s what the end-user experience looks like: a prospect clicks your ad, lands on your funnel, taps through onboarding screens and survey questions, hits a web checkout, and completes their purchase. They get a Redemption Link, download your app, tap the link, and their subscription is already active.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-inside-the-editor&quot;&gt;Inside the editor&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;689&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/6-1-1024x689.png&quot; alt=&quot;&quot; class=&quot;wp-image-52207&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/6-1-1024x689.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/6-1-300x202.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/6-1-768x517.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/6-1-1536x1033.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/6-1-50x34.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/6-1-59x40.png 59w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/6-1-690x464.png 690w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/6-1-696x468.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/6-1-560x377.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/6-1-440x296.png 440w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/6-1-702x472.png 702w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/6-1-80x54.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/6-1-48x32.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/6-1.png 1784w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;You build funnels by placing steps on a canvas and connecting them. A step can be either a screen (a customizable page with text, images, buttons and surveys), a checkout (powered by RevenueCat, Paddle or soon Stripe Billing), or even your own custom authentication flow.&lt;/p&gt;



&lt;p&gt;Connect steps with triggers like button taps or form submissions. Then layer in branching logic to personalize the journey:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Show a different offer to visitors arriving from a specific ad campaign by branching on URL parameters&lt;/li&gt;



&lt;li&gt;Route users to different onboarding paths based on their survey answers&lt;/li&gt;



&lt;li&gt;Detect a visitor’s country via IP and localize the experience automatically&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;When you’re happy with the flow, hit publish. You’ll get a hosted URL to point your ads, emails, and social posts at.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-templates-get-you-live-fast&quot;&gt;Templates get you live fast&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;689&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/3-1-1024x689.png&quot; alt=&quot;&quot; class=&quot;wp-image-52209&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/3-1-1024x689.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/3-1-300x202.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/3-1-768x517.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/3-1-1536x1033.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/3-1-50x34.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/3-1-59x40.png 59w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/3-1-690x464.png 690w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/3-1-696x468.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/3-1-560x377.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/3-1-440x296.png 440w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/3-1-702x472.png 702w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/3-1-80x54.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/3-1-48x32.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/3-1.png 1784w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;You don’t have to start from a blank canvas. RevenueCat Funnels ships with pre-built templates you can customize. Pick one, drop in your branding, tweak the copy and flow, and publish. Going from zero to a live funnel takes minutes.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-analytics-that-show-where-the-money-goes&quot;&gt;Analytics that show where the money goes&lt;/h2&gt;



&lt;p&gt;Every funnel includes built-in analytics right in the RevenueCat dashboard.&lt;/p&gt;



&lt;p&gt;The General Metrics tab shows unique sessions, conversion rate, and revenue over time. Segment the data by traffic source, campaign, country, or other dimensions to understand which channels drive the highest-value subscribers.&lt;/p&gt;



&lt;p&gt;The Step-by-Step Metrics tab breaks down conversion and drop-off at every step, so if users are dropping off at a specific screen, you’ll know exactly where to focus. This view is early in the beta and will get more detailed over time.&lt;/p&gt;



&lt;p&gt;The analytics also include a customer lifetime selector, letting you measure revenue from a given day’s sessions over a defined window (day 0, 7-day, 14-day, and more). This is the same concept as Realized LTV in Charts, useful when you’re running trials and need to compare true ROI across campaigns.&lt;/p&gt;



&lt;p&gt;Funnels captures UTM parameters (source, medium, campaign, content, term) automatically, so you can tie every dollar of funnel revenue back to the campaign that generated it.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-who-should-try-revenuecat-funnels&quot;&gt;Who should try RevenueCat Funnels&lt;/h2&gt;



&lt;p&gt;&lt;strong&gt;Running paid acquisition?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Build a funnel that takes ad traffic through a quiz, presents a tailored offer, collects payment on the web, and sends users to your app with their subscription already active. You keep full attribution visibility and skip app store commissions.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Growth marketer tired of waiting on engineering?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Swap screens, test different survey questions, and adjust branching logic yourself. Check results in the analytics dashboard. Ship changes in minutes, not sprints.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Indie developer without a web team?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;RevenueCat hosts everything and handles checkout through Web Billing. This makes it much easier to get started.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Running influencer or campaign-specific promotions?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Create one funnel, then add a branch where visitors with a specific campaign code see a special discount or promotional content. A single funnel can serve multiple audiences by branching on campaign codes.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-s-included-in-the-public-beta&quot;&gt;What’s included in the public beta&lt;/h2&gt;



&lt;p&gt;The public beta includes everything you need to build, deploy, and measure web-to-app funnels:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Visual funnel editor with drag-and-drop screen builder&lt;/li&gt;



&lt;li&gt;Pre-built templates&lt;/li&gt;



&lt;li&gt;Survey components (multi-select and single-select)&lt;/li&gt;



&lt;li&gt;Branching logic based on URL params, country, browser info, and survey answers&lt;/li&gt;



&lt;li&gt;RevenueCat Billing checkout&lt;/li&gt;



&lt;li&gt;Paddle Billing checkout&lt;/li&gt;



&lt;li&gt;Custom domains&lt;/li&gt;



&lt;li&gt;Hosted deployment with a shareable URL&lt;/li&gt;



&lt;li&gt;Redemption Links connecting web purchases to app entitlements&lt;/li&gt;



&lt;li&gt;Analytics dashboard with conversion rates, drop-off, revenue, and customer lifetime value selector&lt;/li&gt;



&lt;li&gt;Automatic UTM parameter tracking&lt;/li&gt;



&lt;li&gt;Integrations with Amplitude, Mixpanel and Meta&lt;/li&gt;



&lt;li&gt;Localization management&lt;/li&gt;



&lt;li&gt;Autosave&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Funnels is included in your RevenueCat plan at no additional fee. Purchases made through Funnels count toward your MTR, same as any other RevenueCat transaction.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-s-on-the-roadmap&quot;&gt;What’s on the roadmap&lt;/h2&gt;



&lt;p&gt;The team is building A/B testing within funnels now. The AppsFlyer integration is on the roadmap. Stripe Billing support is coming shortly after launch. More input types like email collection and freeform text are also on the way. If there is anything missing that you’d like to see us build, &lt;a href=&quot;https://form.typeform.com/to/wPjgRQ7V&quot;&gt;we’d love to hear from you&lt;/a&gt;.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-get-started&quot;&gt;Get started&lt;/h2&gt;



&lt;p&gt;Here’s how to create your first funnel:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Set up RevenueCat Web with Paddle or RevenueCat Billing with a connected Stripe account&lt;/li&gt;



&lt;li&gt;Open the Funnels section in your RevenueCat Web dashboard&lt;/li&gt;



&lt;li&gt;Create a new funnel from a template or start from scratch&lt;/li&gt;



&lt;li&gt;Design your screens, add branching logic, and connect a checkout step&lt;/li&gt;



&lt;li&gt;Publish and share your funnel URL&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;The full setup guide is in the &lt;a href=&quot;https://www.revenuecat.com/docs/tools/funnels&quot;&gt;Funnels documentation&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;RevenueCat Funnels is available now in public beta for RevenueCat customers. Open your dashboard and build your first funnel.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Firebender now supports RevenueCat MCP and OAuth]]></title><description><![CDATA[In this article, you'll explore how Firebender integrates with RevenueCat's MCP server, including how OAuth sign-in establishes the connection.]]></description><link>https://www.revenuecat.com/blog/company/firebender-revenuecat-mcp/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/company/firebender-revenuecat-mcp/</guid><pubDate>Tue, 17 Mar 2026 02:17:41 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Blog_32_Firebender-now-supports-RevenueCat-MCP-and-OAuth.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Android developers spend most of their time in Android Studio, but managing a subscription business has always required a browser. You write code in the IDE, then switch to a tab to check MRR, open another to configure offerings, and switch again to design a paywall. Each switch breaks your flow and fragments your attention. &lt;a href=&quot;https://firebender.com/&quot;&gt;Firebender&lt;/a&gt; eliminates this by connecting to RevenueCat’s MCP server directly from the IDE, letting the AI agent create paywalls, manage offerings, packages, and entitlements, and query revenue metrics through conversation.&lt;/p&gt;



&lt;p&gt;In this article, you’ll explore how Firebender integrates with RevenueCat’s MCP server, including how OAuth sign-in establishes the connection, how you manage offerings, packages, and entitlements through natural language, how AI paywall generation works end-to-end, and how you can query revenue analytics using the Charts API without leaving Android Studio.&lt;/p&gt;



&lt;figure class=&quot;wp-block-video&quot;&gt;&lt;video height=&quot;1084&quot; style=&quot;aspect-ratio: 1080 / 1084;&quot; width=&quot;1080&quot; controls=&quot;&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/1.mov&quot;&gt;&lt;/video&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-getting-started-oauth-sign-in&quot;&gt;&lt;strong&gt;Getting started: OAuth sign-in&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Firebender connects to RevenueCat’s MCP server using OAuth 2.0. To get started, open Firebender’s settings inside Android Studio or IntelliJ and add the RevenueCat MCP server. Once added, you’ll see an option to sign in with your RevenueCat account.&lt;/p&gt;



&lt;p&gt;Clicking sign in opens your browser for authorization. Firebender handles the token exchange automatically and stores your credentials securely. After authorization, the agent fetches your projects and prompts you to select which one to work with. From that point on, the agent operates within the scope of that project.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;645&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/2-1024x645.png&quot; alt=&quot;&quot; class=&quot;wp-image-52195&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/2-1024x645.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/2-300x189.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/2-768x483.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/2-50x31.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/2-64x40.png 64w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/2-696x438.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/2-560x353.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/2-470x296.png 470w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/2-750x472.png 750w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/2-80x50.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/2-48x30.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/2.png 1409w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The OAuth flow requests scoped permissions for project configuration, charts and metrics, and customer information. This means the agent can read and modify your offerings, packages, entitlements, and paywall configuration, and query your revenue data, but only within the bounds of the permissions you’ve granted. Tokens refresh automatically when they expire, so you stay connected across sessions without manual intervention.&lt;/p&gt;



&lt;p&gt;Once you connect your RevenueCat account to the Firebender, then you’ll see the result below with the available MCP tasks:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;521&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/3-1024x521.png&quot; alt=&quot;&quot; class=&quot;wp-image-52197&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/3-1024x521.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/3-300x153.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/3-768x391.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/3-50x25.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/3-79x40.png 79w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/3-696x354.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/3-560x285.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/3-840x428.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/3-80x41.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/3-48x24.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/3.png 1106w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;managing-your-subscription-infrastructure-through-conversation&quot;&gt;&lt;strong&gt;Managing your subscription infrastructure through conversation&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Once connected, you can manage your entire RevenueCat project configuration through conversation. The agent supports creating, reading, updating, and deleting offerings, packages, entitlements, and products. You describe what you want, and the agent takes care of the API calls.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;creating-offerings-and-packages&quot;&gt;&lt;strong&gt;Creating offerings and packages&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;To set up a new offering with packages, you can ask the agent directly:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“Create a new offering called Premium with a monthly package at $9.99 and an annual package at $79.99”&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;The agent creates the offering, sets up both packages, and attaches the appropriate products. If any of these resources already exist, the agent detects the duplicates and reuses them instead of creating new ones.&lt;/p&gt;



&lt;p&gt;You can also add products to existing packages without having to rebuild the entire structure:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“Add a weekly package to my existing Premium offering”&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;The agent fetches your current offering structure, confirms what’s already configured, and adds the new package without touching anything else.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;configuring-entitlements&quot;&gt;&lt;strong&gt;Configuring entitlements&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Entitlements connect your products to feature access in your app. Setting them up manually through the dashboard involves navigating through multiple screens and attaching each product one by one. Through conversation, the same setup takes a single prompt:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“Set up an entitlement called pro_access and attach it to all my subscription products”&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;The agent creates the entitlement, lists your existing products, and attaches each one. If some products are already attached to a different entitlement, the agent reports that back so you can decide how to proceed.&lt;/p&gt;



&lt;p&gt;You can also set up entitlements for specific products only:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“Create an entitlement called premium_features and attach it to my annual and monthly products”&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;The agent handles the lookup, creation, and attachment in sequence without requiring you to provide product identifiers manually.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;querying-your-project&quot;&gt;&lt;strong&gt;Querying your project&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Beyond creating and modifying resources, you can ask the agent to describe what’s currently configured in your project. This is useful for auditing your setup or understanding what might be missing before submitting a build for review.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“Show me all my offerings and which ones have paywalls”&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;The agent fetches your offerings and paywall data and presents a summary of what’s configured and what’s missing. Offerings without paywalls are called out explicitly.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“What products do I have configured? Which ones aren’t attached to any package?”&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;The agent cross references your products, packages, and offerings to surface orphaned resources. Finding these manually through the dashboard is time consuming, especially as your project grows. The agent does it in a single query.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;ai-paywall-generation&quot;&gt;&lt;strong&gt;AI Paywall generation&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The most direct use of the Firebender and RevenueCat MCP connection is end to end AI paywall generation. You describe what you want, and the agent handles every step: creating the offering, setting up the packages, attaching products, and triggering AI paywall generation with your app context.&lt;/p&gt;



&lt;p&gt;A prompt like this is all you need to get started:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“Generate a paywall for my fitness tracker app targeting health conscious users”&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;The agent creates the supporting offering and package structure if it doesn’t exist, then submits the paywall generation job with context from your prompt. RevenueCat’s AI uses that context to generate copy, imagery, styling, and template selection suited to your app and audience.&lt;/p&gt;



&lt;p&gt;The agent monitors the generation job in the background. When the paywall is ready, a notification appears with a direct link to the paywall builder where you can review the design and publish it. You don’t need to poll the dashboard or wait in a tab for the job to finish.&lt;/p&gt;



&lt;p&gt;You can run multiple generation requests in sequence. The agent tracks each job independently, so you can ask for a “premium” paywall and a “freemium” paywall back to back, and both are monitored separately without conflict.&lt;/p&gt;



&lt;p&gt;If you want to iterate on a paywall for a specific promotion or seasonal campaign, you can generate a new one based on an existing offering:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“Generate an AI paywall for my existing Premium offering. The campaign is a summer fitness challenge with a discount on the annual plan.”&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;The agent picks up the existing offering and package structure and submits the generation job with the campaign context you’ve described. Once Firebender generates a new paywall, you will see the result in the paywall editor like below:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;789&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/4-1024x789.png&quot; alt=&quot;&quot; class=&quot;wp-image-52199&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/4-1024x789.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/4-300x231.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/4-768x592.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/4-1536x1184.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/4-50x39.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/4-52x40.png 52w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/4-602x464.png 602w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/4-696x536.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/4-560x431.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/4-384x296.png 384w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/4-613x472.png 613w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/4-80x62.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/4-48x37.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/4.png 1717w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;analyzing-revenue-with-the-charts-api&quot;&gt;&lt;strong&gt;Analyzing revenue with the Charts API&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The agent has access to 21 chart types from RevenueCat’s Charts API, including MRR, ARR, churn rate, trial conversions, active subscriptions, new paid subscriptions, and retention cohorts. You can ask analytical questions in plain English and get data backed answers without opening a browser.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“What’s my MRR trend over the last 6 months?”&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;The agent queries the MRR chart with the appropriate date range and resolution, then presents the trend in a readable format. If there are notable changes in the data, you can follow up with more specific questions.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“Show me trial to paid conversion rate by week”&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;The agent queries the trial conversion chart with weekly resolution and returns the breakdown. You can then compare specific weeks or ask for the overall rate across a custom date range.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“Compare revenue this month vs last month”&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;The agent fetches revenue data for both periods and presents the comparison. This kind of quick check is useful between code reviews, before a release, or when you’re iterating on paywall design and want to see whether recent changes have affected revenue.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“What’s my churn rate for annual subscribers?”&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;The agent queries the churn chart and applies any available segment filters to narrow the results to annual subscribers. Segmented churn data gives you a clearer picture of how different subscription tiers are performing independently.&lt;/p&gt;



&lt;p&gt;Because the agent can combine analytical queries with project configuration, you can move from a data question directly into action:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“My trial conversion rate dropped this week. Show me what paywalls I have live and which one is attached to my default offering.”&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;The agent pulls the chart data and your current paywall configuration in the same session, giving you both the signal and the context to act on it without switching tools.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;conclusion&quot;&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;In this article, you’ve explored how Firebender connects to RevenueCat’s MCP server through OAuth 2.0 sign-in, how you can manage offerings, packages, and entitlements through natural language conversation, how the agent handles end-to-end AI paywall generation, including job monitoring and notification, and how the Charts API integration lets you query revenue data directly from the IDE.&lt;/p&gt;



&lt;p&gt;This changes the shape of the workflow. Checking MRR, creating a new offering for an A/B test, or generating a paywall for a seasonal campaign used to require opening a browser, navigating through the dashboard, and context switching back to the IDE. With the MCP connection in place, all of those operations happen inside Firebender through conversation. The agent carries out the API calls, monitors async jobs, and brings results back to where you’re already working.&lt;/p&gt;



&lt;p&gt;Whether you’re launching a new app and setting up your subscription infrastructure for the first time, iterating on a paywall to improve conversion, or tracking churn after a pricing change, Firebender keeps you in your development flow. You spend less time switching tabs and more time building.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Beyond SKAN: why standard app campaigns no longer define mobile UA]]></title><description><![CDATA[How enhanced app campaigns reshape attribution, reach, and control]]></description><link>https://www.revenuecat.com/blog/growth/enhanced-app-campaigns/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/enhanced-app-campaigns/</guid><pubDate>Mon, 16 Mar 2026 11:22:31 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Blog_14_Enhanced-app-campaigns.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;For years, mobile app user acquisition (UA) was built almost entirely around SKAdNetwork (SKAN), Apple’s privacy-first attribution framework. While SKAN is still required for iOS compliance, modern app teams are now embracing &lt;a href=&quot;https://www.revenuecat.com/blog/growth/web-to-app-funnels/&quot;&gt;web-to-app funnels&lt;/a&gt;, experimenting with &lt;a href=&quot;https://www.revenuecat.com/blog/growth/subscription-app-creative-testing/&quot;&gt;creative testing&lt;/a&gt;, and exploring &lt;a href=&quot;https://www.revenuecat.com/blog/growth/how-did-you-hear-about-us-surveys/&quot;&gt;first-party attribution methods&lt;/a&gt;. UA has evolved, and SKAN is no longer its center of gravity. It’s a baseline signal, rather than a source of truth.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Today, teams are moving beyond standard app campaigns and rebuilding their campaign structures. Read on to understand the user acquisition strategy from top-performing app studios in the world, and how they run enhanced ad campaigns to make more money.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-app-campaigns-under-the-hood-what-isn-t-working&quot;&gt;&lt;strong&gt;App campaigns under the hood: what isn’t working&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;As everyone knows, if you work with a mobile app and plan to spend money on paid ads, ad networks (Meta, Google, TikTok, etc.) offer a dedicated campaign type for advertisers to use.&lt;strong&gt; &lt;/strong&gt;While each ad network has different naming — e.g. Meta and TikTok call it ‘App promotion’, while Google calls it ‘Google app campaigns’ — the goal is the same: &lt;strong&gt;to offer a dedicated advertising product for mobile apps looking to drive installs&lt;/strong&gt; or specific user actions, like purchases.&lt;/p&gt;



&lt;p&gt;For the sake of this article, I’ll refer to this type of campaign as a ‘&lt;strong&gt;standard app campaign&lt;/strong&gt;’ (SAC).&lt;/p&gt;



&lt;p&gt;SACs have been the standard way for almost every single app to run ads. They are pretty straightforward to set up, easy to understand, and designed specifically for mobile apps by sending all users to the same place: the app store product page.&lt;/p&gt;



&lt;p&gt;Surrounding that moment, there are three crucial levers to make profitable paid ads:&amp;nbsp;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Pre-app store: &lt;strong&gt;test new ad creatives&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;App store: &lt;strong&gt;app store optimization (ASO)&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;Post-app store: &lt;strong&gt;onboarding and paywall optimization&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;But, even if you successfully use those levers, SACs have four main problems that impact all app advertisers:&amp;nbsp;&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Measurement and attribution problems,&lt;/strong&gt; caused by the implementation of SKAN and native models like Meta’s aggregated event measurement (AEM)&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Limited reach&lt;/strong&gt;, since most app campaigns’ inventory cannot reach what web campaigns do — &lt;a href=&quot;https://www.businessofapps.com/insights/winning-web-revenue-in-the-evolving-app-landscape/&quot;&gt;based on Paddle data&lt;/a&gt;, there is only a 15% overlap between app campaigns and web campaigns&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Limited control over ad placement and campaign types,&lt;/strong&gt; caused by campaign automation&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Retargeting constraints on iOS &lt;/strong&gt;due to privacy limitations, which make it hard to target with precision&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Because of these problems and consequences, a new trend has emerged in the last two to three years: web-to-app.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-web-to-app-trend&quot;&gt;&lt;strong&gt;The web-to-app trend&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;So, what the hell is web-to-app?&amp;nbsp;&lt;/p&gt;



&lt;p&gt;A good definition is: &lt;em&gt;it is a marketing approach that brings users to a dedicated &lt;/em&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/web-to-app-funnel-examples/&quot;&gt;&lt;em&gt;web-to-app funnel&lt;/em&gt;&lt;/a&gt;&lt;em&gt; before guiding them to a mobile app.&lt;/em&gt; Here, users complete a personalized onboarding flow, subscribe, and then install the app.&lt;/p&gt;



&lt;p&gt;Over the past few years, more and more apps have been testing and adopting web-to-app campaigns. By doing so, some companies have come to view SACs as no longer part of their marketing strategy.&lt;/p&gt;



&lt;p&gt;Nathan Hudson, Founder &amp;amp; CEO at Perceptycs, wrote a good article on &lt;a href=&quot;https://www.revenuecat.com/blog/growth/the-pros-and-cons-of-web-to-app-funnels/&quot;&gt;the reasons web-to-app became popular&lt;/a&gt;:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Don’t pay any fees to Apple or Google&lt;/li&gt;



&lt;li&gt;Get your money faster&lt;/li&gt;



&lt;li&gt;Say goodbye to SKAN and ATT attribution struggles&lt;/li&gt;



&lt;li&gt;Build and deploy onboarding experiments faster&lt;/li&gt;



&lt;li&gt;Reach new audiences&lt;/li&gt;



&lt;li&gt;More control and more customization&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;For these reasons, lately, many app growth teams are focused on web-to-app. And new startups have emerged offering no-code tools to build and customize your web onboarding experience.&lt;/p&gt;



&lt;p&gt;However, as Thomas &lt;a href=&quot;https://www.revenuecat.com/blog/growth/thomas-petit-sub-club-podcast-2024-web-to-app/&quot;&gt;stated on the Sub Club podcast&lt;/a&gt;, some apps are adopting this trend for the wrong reason: just to avoid app store fees. What these apps don’t know is that web-to-app also has a set of hidden costs, like:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Managing your transactions online introduces a host of additional complexities that can outweigh the benefits for many businesses&lt;/li&gt;



&lt;li&gt;Apps still have to pay a 3% (often higher) fee to a payment processor like Stripe&lt;/li&gt;



&lt;li&gt;Paying for expensive third-party tools to build the web onboarding experience&lt;/li&gt;



&lt;li&gt;Dealing with global tax compliance and legal structures&lt;/li&gt;



&lt;li&gt;ASO rankings will take a hit because fewer people see your product page and download the app&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Based on my personal experience, web-to-app can become a nightmare for apps making less than $1M a year — since they pay app stores just 15% (rather than 30% like &amp;gt;$1M apps), the savings are almost non-existent.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Based on &lt;a href=&quot;https://appfigures.com/resources/insights/20250124/amp?f=1&quot;&gt;this report&lt;/a&gt; from AppFigures, only 0.28% of new apps made more than $1M a year in 2024, which basically means — if you’re pursuing web-to-app solely for the purpose of avoiding app store fees — then for 99% of apps it doesn’t make much financial sense.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;But what if there’s a middle ground? A user acquisition strategy that could combine the best of both worlds between standard and web-to-app campaigns&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-enhanced-app-campaigns-8-benefits&quot;&gt;&lt;strong&gt;Enhanced app campaigns: 8 benefits&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Enhanced app campaign (EACs) is a new marketing protocol we’ve developed at &lt;a href=&quot;https://www.appstack.tech/blog/introducing-enhanced-app-campaigns&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Appstack&lt;/a&gt;. They consist of &lt;strong&gt;web campaigns that redirect all users to the app stores, without needing a website.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Enhanced app campaigns aim to combine the top benefits of standard app campaigns with the flexibility and control of web-to-app, giving you a new way to run paid ads for your mobile app.&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Standard app campaigns&lt;/th&gt;&lt;th&gt;Web-to-app&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;No impact on ASO rankings ✅&lt;/td&gt;&lt;td&gt;No more attribution struggles ✅&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;No web funnel is needed ✅&lt;/td&gt;&lt;td&gt;Reach new audiences ✅&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;No tax or legal complications ✅&lt;/td&gt;&lt;td&gt;More control and customization ✅&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;The results for enhanced app campaigns speak for themselves: looking at a dataset containing data from dozens of subscription apps, we saw an average &lt;strong&gt;decrease in cost per subscription of 25%&lt;/strong&gt;, and an average &lt;strong&gt;decrease in cost per start trial of 20%&lt;/strong&gt;. One fact worth noting is that, in most cases, these numbers were achieved even after increasing daily ad spending.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;438&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-cost-per-sub-1024x438.png&quot; alt=&quot;&quot; class=&quot;wp-image-50918&quot; style=&quot;width:800px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-cost-per-sub-1024x438.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-cost-per-sub-300x128.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-cost-per-sub-768x329.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-cost-per-sub-1536x658.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-cost-per-sub-50x21.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-cost-per-sub-93x40.png 93w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-cost-per-sub-696x298.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-cost-per-sub-560x240.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-cost-per-sub-840x360.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-cost-per-sub-80x34.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-cost-per-sub-48x21.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-cost-per-sub.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Enhanced app campaigns are great for apps looking to:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Expand paid reach&lt;/li&gt;



&lt;li&gt;Improve profitability&lt;/li&gt;



&lt;li&gt;Target B2B or specific niches&lt;/li&gt;



&lt;li&gt;Engage older audiences&lt;/li&gt;



&lt;li&gt;Improve attribution or seek clarity&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;We’ve seen great success with EACs, and it’s fast becoming the dominant way to run ads for mobile apps. Let’s break down these reasons why.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-superior-attribution&quot;&gt;&lt;strong&gt;1. Superior attribution&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;If you believe the term ‘superior attribution’ is misleading, you are wrong. EACs genuinely have far superior attribution than standard app campaigns run through ad networks. Let me explain:&amp;nbsp;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Firstly, to run enhanced app campaigns, apps only need to install the Appstack SDK. This enables running ads across multiple ad networks simultaneously with consistent measurement.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Enhanced app campaigns rely on probabilistic matching with an accuracy rate of +95%, allowing app advertisers to pass encrypted PII (Personally Identifiable Information) to improve the quality of the signal (optional), which is as good as it can be. EACs don’t rely on SKAN for iOS attribution, enabling apps to get real-time, high-precision data.&lt;/li&gt;



&lt;li&gt;EACs rely on APIs to send in-app event postbacks (signals) to ad networks, creating a more stable and reliable way to keep the signals pipeline in the correct numbers compared to the SDK method.&lt;/li&gt;



&lt;li&gt;Since EACs rely on ad links (tracking links), they enable data at the most granular level (ad or keyword, depending on the campaign type). This means apps can see &lt;a href=&quot;https://www.revenuecat.com/blog/growth/creative-fatigue-mobile-apps-roas/&quot;&gt;ROAS&lt;/a&gt;, profit, rLTV, and many other metrics with greater precision than ever before.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Enhanced app campaigns have unified measurement, enabling apps to get the clearest picture of their app’s success. You can see the entire user history, including all engagements before and after installation — and it works with the most popular ad networks, including Meta, Google, and TikTok. It also lets apps see multiple attribution models, such as last-click, multi-touch or first-click.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;350&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-user-history-1024x350.png&quot; alt=&quot;&quot; class=&quot;wp-image-50903&quot; style=&quot;width:800px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-user-history-1024x350.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-user-history-300x103.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-user-history-768x263.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-user-history-50x17.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-user-history-117x40.png 117w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-user-history-696x238.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-user-history-560x192.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-user-history-840x287.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-user-history-80x27.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-user-history-48x16.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-user-history.png 1272w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;2-fast-integration&quot;&gt;&lt;strong&gt;2. Fast integration&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;All apps that use RevenueCat can benefit from a quick, easy implementation to start running enhanced app campaigns &lt;a href=&quot;https://www.revenuecat.com/blog/engineering/revenuecat-now-integrates-with-appstack/&quot;&gt;with the RevenueCat and Appstack integration&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;Using RevenueCat to run EACs will help you to unlock:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;A light-speed integration process: no need for developers to map any in-app events or debug to ensure that client-side events (Appstack SDK events) are triggered properly&lt;/li&gt;



&lt;li&gt;Avoid untrustworthy data caused by poor implementation or changes to the codebase that could affect in-app events mapped by the Appstack SDK&lt;/li&gt;



&lt;li&gt;Easily access server-to-server events like trial_converted or renewals to use them for paid ads&lt;/li&gt;
&lt;/ul&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;815&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-95-1024x815.png&quot; alt=&quot;&quot; class=&quot;wp-image-52171&quot; style=&quot;width:800px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-95-1024x815.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-95-300x239.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-95-768x612.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-95-50x40.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-95-583x464.png 583w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-95-696x554.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-95-560x446.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-95-372x296.png 372w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-95-593x472.png 593w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-95-80x64.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-95-48x38.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-95.png 1536w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-Z1PnoHM wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Try the Appstack integration today&quot; text=&quot;&lt;p&gt;Get started with enhanced app campaigns in seconds using RevenueCat&apos;s integration with Appstack. &lt;a href=&amp;quot;https://www.revenuecat.com/blog/engineering/revenuecat-now-integrates-with-appstack/#:~:text=With%20the%20Appstack%20integration%20you,using%20the%20%24appstackId%20subscriber%20attribute.&amp;quot;&gt;Learn more here.&lt;/a&gt;&lt;/p&gt;&quot; icon=&quot;bulb&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;3-paywall-customization&quot;&gt;&lt;strong&gt;3. Paywall customization&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Apps running enhanced app campaigns can show ad-targeted paywalls based on where your users came from, using RevenueCat targeting capabilities and paywalls.&lt;/p&gt;



&lt;p&gt;Mobile apps can show a paywall depending on five different paid ads parameters:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Ad network (Meta Ads, TikTok Ads, Google Ads, etc.)&lt;/li&gt;



&lt;li&gt;Ad campaign name&lt;/li&gt;



&lt;li&gt;Ad set name&lt;/li&gt;



&lt;li&gt;Ad name&lt;/li&gt;



&lt;li&gt;Keyword&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;This opens up entirely new testing opportunities, such as:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Keeping organic users with free trials and paid ads users with hard paywalls&lt;/li&gt;



&lt;li&gt;Showing a trial-only paywall for campaigns optimizing for trial starts&lt;/li&gt;



&lt;li&gt;Customizing design and copy for gender-targeted or interest-targeted campaigns&lt;/li&gt;



&lt;li&gt;Presenting higher pricing to users coming from high-intent keywords&lt;/li&gt;



&lt;li&gt;Matching the tone and visual language of the ad, the user originally clicked&lt;/li&gt;
&lt;/ul&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;652&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-persona-1024x652.png&quot; alt=&quot;&quot; class=&quot;wp-image-50905&quot; style=&quot;width:800px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-persona-1024x652.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-persona-300x191.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-persona-768x489.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-persona-50x32.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-persona-63x40.png 63w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-persona-696x443.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-persona-560x356.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-persona-465x296.png 465w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-persona-742x472.png 742w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-persona-80x51.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-persona-48x31.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-persona.png 1411w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Follow &lt;/em&gt;&lt;a href=&quot;https://docs.appstack.tech/Integrations/revenuecat&quot;&gt;&lt;em&gt;Appstack’s docs&lt;/em&gt;&lt;/a&gt;&lt;em&gt; to send user attributes to RevenueCat and start customizing your paywalls.&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-4-campaign-control&quot;&gt;&lt;strong&gt;4. Campaign control&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Over the last few years, ad networks have shifted towards automation. This means app advertisers have less control over ad placements during campaign setup, with the algorithm deciding where to allocate the budget.&lt;/p&gt;



&lt;p&gt;With EACs, you can take back control and choose where your money is spent. This makes a lot of sense for apps looking to spend money on Google and TikTok Ads.&lt;/p&gt;



&lt;p&gt;For example, on Google Ads, an EAC can let you:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Unlock search-to-app campaigns that allow apps to bid on specific keywords or search terms to acquire users. The reporting capabilities enable apps to see revenue and ROAS at the keyword level.&lt;/li&gt;



&lt;li&gt;Run YouTube Shorts only, by selecting demand gen as campaign objective and choosing shorts as the only placement on YouTube. This enables apps with traction on Meta or TikTok to deploy the same creatives in a new channel, using the same ad format, to keep growing.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;On the other hand, TikTok search-to-app is a new campaign type that allows apps to select a specific set of keywords while using the same ads. Currently, only apps running EACs can run this campaign type.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-5-expanded-reach&quot;&gt;&lt;strong&gt;5. Expanded reach&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;As Daphne commented in her guide to &lt;a href=&quot;https://www.revenuecat.com/blog/growth/web-to-app-funnels/&quot;&gt;web-to-app funnels&lt;/a&gt;, “Paid optimization looks very different for app campaigns compared to web campaigns. By focusing on the web, you can unlock an entirely new audience you may not have reached before.”&lt;/p&gt;



&lt;p&gt;Like Daphne, even after working with dozens of mobile apps, I rarely see an app campaign advertised to me on Meta or TikTok. So I’m definitely in that web audience bucket!&lt;/p&gt;



&lt;p&gt;Just like web-to-app campaigns, EACs unlock a new inventory of potential users. This is great for apps of all sizes. Either because their current audience is not performing well, or because apps are saturating an audience and need to look for new users.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-6-retargeting&quot;&gt;&lt;strong&gt;6. Retargeting&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;If you thought that retargeting on iOS was dead in 2026… well, you were right. But EACs are bringing it back. The question is: how is it possible now, given that before everyone said running retargeting campaigns on iOS after the end of IDFA was no longer viable?&lt;/p&gt;



&lt;p&gt;The enhanced app campaign protocol allows sending enriched signals to the ad network, which can be used to create custom audiences for retargeting.&lt;/p&gt;



&lt;p&gt;For example, these are some of the parameters that the signal includes (data encrypted), which EACs send to Meta for campaign optimization:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Email&lt;/li&gt;



&lt;li&gt;Phone number&lt;/li&gt;



&lt;li&gt;First name&lt;/li&gt;



&lt;li&gt;Last name&lt;/li&gt;



&lt;li&gt;Date birth&lt;/li&gt;



&lt;li&gt;IP address&lt;/li&gt;



&lt;li&gt;User agent&lt;/li&gt;



&lt;li&gt;Browser ID&lt;/li&gt;



&lt;li&gt;External ID&lt;/li&gt;



&lt;li&gt;Zip code&lt;/li&gt;



&lt;li&gt;City&lt;/li&gt;



&lt;li&gt;State&lt;/li&gt;



&lt;li&gt;Click ID&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;As you can see, there are many parameters that help Meta (and the other ad networks) to identify the right users.&lt;/p&gt;



&lt;p&gt;Using these retargeting capabilities, you can leverage EACs to:&amp;nbsp;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Use custom audiences as an exclusion to avoid showing ads to users who already have your app&lt;/li&gt;



&lt;li&gt;Reduce the CPM and ad frequency&lt;/li&gt;



&lt;li&gt;Launch retargeting campaigns for users who installed the app but didn’t complete the target event, such as a purchase or sign-up (highly recommended for e-commerce or gaming apps!)&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-7-aso-friendly&quot;&gt;&lt;strong&gt;7. ASO friendly&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Everyone knows that most users only install the app that ranks between the top three results after a search.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;So investing money in ads through web-to-app campaigns means you are also investing in minimizing your chances of improving your ranks and getting more app reviews, because fewer users see your product page.&lt;/p&gt;



&lt;p&gt;Since EACs redirect users directly to the app store and let everyone install the advertised app, you won’t be hurting your ASO efforts.&lt;/p&gt;



&lt;p&gt;This is a strong point for small- to medium-sized apps considering the web-to-app option, given better measurement capabilities.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-8-zero-overheads&quot;&gt;&lt;strong&gt;8. Zero overheads&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;I know how hard it is to actually make a living out of a mobile app. So imagine adding extra responsibility and problems to it. EACs are built so apps focus on what matters most for your business in 2026: actually reaching customers.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;419&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-comparison-1024x419.png&quot; alt=&quot;&quot; class=&quot;wp-image-50907&quot; style=&quot;width:800px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-comparison-1024x419.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-comparison-300x123.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-comparison-768x315.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-comparison-50x20.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-comparison-98x40.png 98w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-comparison-696x285.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-comparison-560x229.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-comparison-840x344.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-comparison-80x33.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-comparison-48x20.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/eac-comparison.png 1062w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;There’s three key benefits to EACs for your UA strategy:&amp;nbsp;&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Frictionless&lt;/strong&gt;: apps remove the need for a website and maintain it; saving money.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Smart economics&lt;/strong&gt;: incremental revenue without the need to implement third-party services like an onboarding builder or new payment provider. With EACs, apps don’t need to change their existing stacks; they pair easily with what’s already in place.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Operational efficiency&lt;/strong&gt;: Eliminate the need for web funnels, global tax compliance, and legal structures. Since all users are redirected to the app stores, users use the app stores’ payment systems.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Sounds good, right?&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-key-takeaways&quot;&gt;&lt;strong&gt;Key takeaways&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Enhanced app campaigns equip apps with an infrastructure that runs quickly and helps apps focus on optimizing the two most important things: ad creatives and their actual product (including onboarding and paywall optimization).&lt;/p&gt;



&lt;p&gt;The good news is that, technically speaking, every company can build an infrastructure like this, giving them total control over their own data, vendor independence, and a strong moat that few app companies can achieve. (However, it’ll be fairly expensive, so — even if I’m biased — I’d recommend looking at Appstack’s SDK to get started.)&amp;nbsp;&lt;/p&gt;



&lt;p&gt;To wrap up, here are the main things to remember:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Standard app campaigns are structurally broken&lt;/strong&gt;: attribution is unreliable, reach is capped, and automation removed real control from advertisers&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Web-to-app has underlying complexities&lt;/strong&gt; that most apps ignore, and can cause ASO damage&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Enhanced app campaigns fix the real problem&lt;/strong&gt;: they restore device-level insight without adding web funnels, fees, or compliance overhead&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;EACs give advertisers back what automation took away&lt;/strong&gt;: control over targeting, placements, keywords, and retargeting&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Winning apps will not out-hack SKAN or dodge fees&lt;/strong&gt;; they will own their data and optimize creatives and products with clarity&lt;/li&gt;
&lt;/ol&gt;
</content:encoded></item><item><title><![CDATA[The Turkish government now pays 50% of your RevenueCat bill]]></title><description><![CDATA[RevenueCat joins Türkiye's approved software list — here's what that means for you]]></description><link>https://www.revenuecat.com/blog/company/turkiye-approved-software/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/company/turkiye-approved-software/</guid><pubDate>Thu, 12 Mar 2026 15:07:01 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Turkey-approved-software.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Every so often, a government does something that makes the entire app industry sit up and take notice. We saw it with the Digital Markets Act in the EU, and we’ve seen it with the ongoing antitrust debates in the US. But it’s rare to see a government step in not to regulate, but to &lt;em&gt;accelerate&lt;/em&gt;.&lt;/p&gt;



&lt;p&gt;That’s what’s happening in Türkiye right now. And it’s a big deal.&lt;/p&gt;



&lt;p&gt;As of January 1, 2026, &lt;a href=&quot;https://www.resmigazete.gov.tr/eskiler/2026/02/20260227-10.pdf&quot;&gt;a new presidential decree (No. 10962)&lt;/a&gt; has gone into effect, completely overhauling the country’s support for service-based exports. While some of these supports have been around for a while, this new decree consolidates them, simplifies the rules, and in many cases, massively increases the amount of money developers can get back.&lt;/p&gt;



&lt;p&gt;And the big news for RevenueCat users? &lt;strong&gt;RevenueCat is now on the official “approved software” list&lt;/strong&gt;, which means if you’re an eligible Turkish company, you can get &lt;strong&gt;50% of your RevenueCat subscription fees reimbursed by the government&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;This isn’t just another tax credit. It’s a direct subsidy on the cost of growth. Let’s break down what’s changed, and why it matters for developers both inside and outside of Türkiye.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-bigger-better-simpler-what-s-new-in-2026&quot;&gt;Bigger, better, simpler: what’s new in 2026&lt;/h3&gt;



&lt;p&gt;For years, Türkiye has offered support to its IT sector. But the old system (under Decree 5447) was a complex web of tiered limits and inflation-adjusted caps. The new Decree 10962 sweeps that away in favor of a simpler, more generous framework. The support rate is still 50% for most programs, but the annual limits have been substantially increased across the board.&lt;/p&gt;



&lt;p&gt;Here’s a quick comparison of the old vs. new annual limits for a typical app developer:&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;Support Program&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;Old Decree 5447 (2024 limits)&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;New Decree 10962&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;Change&lt;/strong&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Software License&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;50%, ~1.83M TL/yr&lt;/td&gt;&lt;td&gt;50%, 2.5M TL/yr&lt;/td&gt;&lt;td&gt;&lt;strong&gt;+37%&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Platform Commission&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;50%, 2.5M TL/app (top 3), 600K TL/app (rest)&lt;/td&gt;&lt;td&gt;50%, 4M TL/app (all 10), 20M TL total&lt;/td&gt;&lt;td&gt;&lt;strong&gt;~70% effective increase&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Digital Product Promo&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;50%, 10M TL/app (top 3), 1.2M TL/app (rest)&lt;/td&gt;&lt;td&gt;50%, 15M TL/app (all 10), 50M TL total&lt;/td&gt;&lt;td&gt;&lt;strong&gt;~50% per-product increase&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Hosting&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;50%, 1M TL/yr&lt;/td&gt;&lt;td&gt;50%, 5M TL/yr&lt;/td&gt;&lt;td&gt;&lt;strong&gt;5x increase&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;General Marketing&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;50%, ~11M TL/yr&lt;/td&gt;&lt;td&gt;50%, 25M TL/yr&lt;/td&gt;&lt;td&gt;&lt;strong&gt;~2.3x increase&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;Two changes are particularly massive:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;The end of tiered limits:&lt;/strong&gt; Under the old system, support for platform commissions and marketing dropped off a cliff after your first few apps. Now, every app (up to 10) gets the same high per-product cap. This is a huge win for studios with a portfolio of apps.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Huge cap increases:&lt;/strong&gt; The total amount you can claim for platform commissions has nearly doubled, and the hosting support has gone up 5x. This is a direct injection of capital into the growth loop of an app business.&lt;/li&gt;
&lt;/ol&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-revenuecat-is-now-on-the-approved-software-list&quot;&gt;RevenueCat is now on the approved software list&lt;/h3&gt;



&lt;p&gt;The Software License Support program isn’t new, but our inclusion on the approved list is. As of the latest update to the “Desteklenen Yazılım Lisansları Listesi” (Supported Software Licenses List), RevenueCat is now officially included.&lt;/p&gt;



&lt;p&gt;What this means is simple: &lt;strong&gt;If you are an eligible Turkish company, you can now get 50% of your RevenueCat subscription fees reimbursed by the government&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;This fundamentally changes the ROI of using RevenueCat for Turkish developers. The best-in-class infrastructure for managing subscriptions, analyzing data, and running experiments now comes with a 50% government-funded discount. It makes the decision to build, measure, and grow your app with proper tooling a no-brainer.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-it-s-about-more-than-just-a-discount&quot;&gt;It’s about more than just a discount&lt;/h3&gt;



&lt;p&gt;Getting 50% back on your RevenueCat bill is great. But the real power here is how these incentives work together. The Turkish government isn’t just giving you a discount on tools; it’s subsidizing the entire engine of your app’s growth.&lt;/p&gt;



&lt;p&gt;Think about it:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;You use &lt;strong&gt;RevenueCat&lt;/strong&gt; to manage your subscription infrastructure and get a single source of truth for your revenue data&lt;/li&gt;



&lt;li&gt;The government reimburses you for &lt;strong&gt;50% of your RevenueCat subscription&lt;/strong&gt; under the Software License Support program&lt;/li&gt;



&lt;li&gt;You use RevenueCat’s charts and analytics to create the reports you need to claim &lt;strong&gt;50% of your App Store and Play Store commissions back&lt;/strong&gt; from the government&lt;/li&gt;



&lt;li&gt;You use RevenueCat’s Experiments and Paywalls to optimize your pricing and increase conversion, growing your top-line revenue&lt;/li&gt;



&lt;li&gt;You take that extra revenue and the money you got back from commissions and reinvest it into user acquisition, knowing the government will reimburse you for &lt;strong&gt;50% of that marketing spend&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;This is a virtuous cycle. RevenueCat becomes the system of record that not only helps you grow faster but also unlocks the government funding to fuel that growth. The data you need to claim your commission and marketing reimbursements is right there in your RevenueCat dashboard.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;559&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Gemini_Generated_Image_e1rappe1rappe1ra-1024x559.png&quot; alt=&quot;&quot; class=&quot;wp-image-52116&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Gemini_Generated_Image_e1rappe1rappe1ra-1024x559.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Gemini_Generated_Image_e1rappe1rappe1ra-300x164.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Gemini_Generated_Image_e1rappe1rappe1ra-768x419.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Gemini_Generated_Image_e1rappe1rappe1ra-1536x838.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Gemini_Generated_Image_e1rappe1rappe1ra-2048x1117.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Gemini_Generated_Image_e1rappe1rappe1ra-50x27.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Gemini_Generated_Image_e1rappe1rappe1ra-73x40.png 73w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Gemini_Generated_Image_e1rappe1rappe1ra-696x380.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Gemini_Generated_Image_e1rappe1rappe1ra-560x305.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Gemini_Generated_Image_e1rappe1rappe1ra-543x296.png 543w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Gemini_Generated_Image_e1rappe1rappe1ra-840x458.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Gemini_Generated_Image_e1rappe1rappe1ra-80x44.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Gemini_Generated_Image_e1rappe1rappe1ra-48x26.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-how-to-take-advantage-of-this-program&quot;&gt;How to take advantage of this program&lt;/h3&gt;



&lt;p&gt;If you’re a developer in Türkiye, you’re probably wondering how to get started. The program is administered through the Ministry of Trade, and requires membership in the &lt;a href=&quot;https://hib.org.tr/en/uyelik/basvuru&quot;&gt;Service Exporters’ Association (HİB)&lt;/a&gt; and applications via the Destek Yönetim Sistemi (DYS).&lt;/p&gt;



&lt;p&gt;Navigating government programs can be complex, but the opportunity is too big to ignore. To make it easier for local developers, we’ve been working closely with &lt;a href=&quot;https://www.revenuecat.com/blog/company/revenuecat-turkiye-partnership/&quot;&gt;our partners in Istanbul, &lt;strong&gt;Neon Apps&lt;/strong&gt;&lt;/a&gt;. The Neon Apps team provides free, local-language support to RevenueCat users, and they have deep expertise in helping Turkish companies navigate these incentive programs. If you’re a RevenueCat customer in Türkiye and want hands-on help to make sure you’re getting every lira you’re entitled to, get in touch with us and we’ll connect you with the team at Neon.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-future-is-bright-for-turkish-apps&quot;&gt;The future is bright for Turkish apps&lt;/h3&gt;



&lt;p&gt;This new decree is a clear signal that the Turkish government understands the power of the app economy and is willing to make serious investments in its growth. For developers in Türkiye, it’s a golden opportunity to scale faster and more profitably than ever before. For the rest of us, it’s a fascinating development to watch – and a reminder that the next great app can come from anywhere.&lt;/p&gt;



&lt;p&gt;We’re incredibly excited to be a part of this new chapter for the Turkish app community and to help them build the next generation of globally successful apps.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[From spite-driven development to community-powered success]]></title><description><![CDATA[On the podcast: Adrian Eves about his path from Apple’s accessibility team to indie app development, building Pediapal and Auralog from personal health challenges. We cover lessons from launching, redesigning with Liquid Glass, navigating App Store features, and how community—from iOS Dev Happy Hour to Swift Sonic—has fueled his growth.]]></description><link>https://www.revenuecat.com/blog/growth/adrian-eves-pediapal-launched-podcast-2026/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/adrian-eves-pediapal-launched-podcast-2026/</guid><pubDate>Wed, 11 Mar 2026 18:47:43 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/LD-Blog-Cover-Adrian-Eves-1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;What happens when you get laid off from your dream job at Disney? If you’re Adrian Eves, you take some advice from Paul Hudson, add a dash of spite, and finally launch the indie app you’ve always talked about making.&lt;/p&gt;



&lt;p&gt;In the latest episode of Launched, host Charlie Chapman sat down with the developer and community organizer to discuss his journey from working on Apple’s accessibility team to building apps rooted in his own life. His story is a candid look at the messy, non-linear, and deeply rewarding path of an indie creator.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;How a Layoff and an Ice Cream Bet Launched 2 Indie Apps — Adrian Eves, Pediapal &amp;amp; Auralog&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/Dcqg4tPtMfw?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;iframe loading=&quot;lazy&quot; width=&quot;100%&quot; height=&quot;180&quot; frameborder=&quot;no&quot; scrolling=&quot;no&quot; seamless=&quot;&quot; src=&quot;https://share.transistor.fm/e/8cd9cbe8?color=FFFFFF&amp;amp;background=30343C&quot;&gt;&lt;/iframe&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-push-you-didn-t-know-you-needed&quot;&gt;The push you didn’t know you needed&lt;/h2&gt;



&lt;p&gt;For years, Adrian was the developer who was going to ship an app. “Oh, I’m going to do it this year,” he’d say. But it took an unexpected layoff from Disney to turn the idea into a reality. Feeling “pretty mopey,” he got some crucial advice from a friend. “Paul [Hudson] said, ‘At the very least, you need to make an indie app so that way you always have something you can fall back on.’”&lt;/p&gt;



&lt;p&gt;That conversation was the spark. The problem to solve came from his own life: a chaotic jumble of Apple Notes trying to track his child’s health data. “I kept getting lost in all these notes that my partner and I would share,” Adrian recalls. “I was like, ‘My child who’s like three years old, I know she’s not like 11 inches.’ So that’s like an old note.” That frustration became PediaPal, a health hub for kids and his first real foray into indie development.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-bet-that-built-an-app-in-a-month&quot;&gt;The bet that built an app in a month&lt;/h2&gt;



&lt;p&gt;After the emotional rollercoaster of launching PediaPal—and the subsequent letdown of not getting featured by Apple after a massive redesign—Adrian found a new, more potent form of motivation: spite.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“Paul encouraged me to get into something he called spite driven development and I made a second app out of it.”&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;This time, the problem was even more personal: managing his chronic, debilitating migraines. He needed a tracker that was effortless to use in a moment of intense pain. The idea for Auralog was born. But it was a friendly challenge that got it over the finish line. “One of my friends issued a challenge and they said they bet that I couldn’t release my app in a month,” Adrian laughs. “The stakes were real high. Let me tell you, it was ice cream.”&lt;/p&gt;



&lt;p&gt;He won the bet. By focusing on a single, search-driven problem and designing for a moment of extreme user need (the core feature is a giant “Save Now, Log Later” button), Auralog quickly found traction and became his first project to generate meaningful, growing revenue.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-building-spaces-for-others-to-succeed&quot;&gt;Building spaces for others to succeed&lt;/h2&gt;



&lt;p&gt;Adrian’s story isn’t just about apps; it’s about the community that surrounds them. He’s a natural organizer, driven by a desire to pay forward the support he’s received. “This community has given me so much,” he says. “It would not be right to be like a dragon and hoard a bunch of gold.”&lt;/p&gt;



&lt;p&gt;From helping run iOS Dev Happy Hour to co-founding CommunityKit—the unofficial “glue” of WWDC week—he creates spaces for developers to connect and learn. Now, he’s channeling that passion into his own conference, Swift Sonic, a music-festival-inspired event with a unique twist: pairing veteran “headliner” speakers with first-time “opener” speakers.&lt;/p&gt;



&lt;p&gt;It’s this commitment to building up others that defines his journey. Adrian Eves’s story is a powerful reminder that indie success isn’t just about shipping features or hitting revenue goals. It’s about solving real problems, learning in public, and building relationships that lift everyone up.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[RevenueCat now integrates with Appstack]]></title><description><![CDATA[Integrate RevenueCat with Appstack for attribution and targeting]]></description><link>https://www.revenuecat.com/blog/engineering/revenuecat-now-integrates-with-appstack/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/revenuecat-now-integrates-with-appstack/</guid><pubDate>Wed, 11 Mar 2026 05:23:02 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/appstack-cover.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Running paid acquisition without connecting it to subscription revenue means flying blind. Attribution data lives in one tool, subscription events in another, and the relationship between your ad spend and actual LTV stays murky. RevenueCat’s new Appstack integration closes that gap.&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-Z2nqBo0 wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;What is Appstack?&quot; text=&quot;&lt;p&gt;Appstack is an ad attribution platform that&apos;s been gaining popularity, especially among subscription app developers who want cleaner visibility into which campaigns are actually driving LTV.&amp;nbsp;&lt;/p&gt;&quot; icon=&quot;circle-info&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-using-revenuecat-s-appstack-integration&quot;&gt;Using RevenueCat’s Appstack integration&lt;/h2&gt;



&lt;p&gt;With the Appstack integration you can:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Send RevenueCat subscription events directly to your Appstack webhook endpoint (optional).&lt;/li&gt;



&lt;li&gt;Attribute subscription revenue to campaigns tracked by Appstack using the Purchases SDK.&lt;/li&gt;



&lt;li&gt;Identify users in Appstack using the&amp;nbsp;&lt;code&gt;$appstackId&lt;/code&gt;&amp;nbsp;subscriber attribute.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Integrating with Appstack requires that Appstack SDK is installed in your app. &lt;a href=&quot;https://docs.appstack.tech/introduction&quot;&gt;Refer to the Appstack developer documentation&lt;/a&gt; for the latest installation instructions.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-sdk-attribution-mapping&quot;&gt;&lt;strong&gt;1. SDK attribution mapping&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;A single call — &lt;code&gt;setAppstackAttributionParams()&lt;/code&gt; — pulls attribution data from the Appstack SDK and forwards it to RevenueCat. Under the hood, it sets $appstackId, campaign attribution attributes ($mediaSource, $campaign, $adGroup, $ad, $keyword), click IDs, and device identifiers. No need to call&amp;nbsp;&lt;code&gt;collectDeviceIdentifiers()&lt;/code&gt;&amp;nbsp;separately.&lt;/p&gt;



&lt;p&gt;The call also syncs attributes to the RevenueCat backend &lt;em&gt;and&lt;/em&gt; fetches fresh offerings before returning. That means by the time the callback fires, your paywall is already reflecting the user’s Appstack targeting data.&lt;/p&gt;



&lt;p&gt;Set the following attributes after configuring the Purchases SDK and before the first purchase occurs.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z6Pg3y wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;swift&quot; content=&quot;&amp;quot;import AdSupport\n\/\/ ...\nPurchases.configure(withAPIKey: \&amp;quot;public_sdk_key\&amp;quot;)\n\/\/ ...\n\n\/\/ Retrieve attribution params from the Appstack SDK\nlet attributionParams = AppstackAttributionSdk.shared.getAttributionParams()\n\n\/\/ Forward to RevenueCat \u2014 syncs attributes and fetches fresh offerings\n\/\/ so Appstack-based targeting is applied before the await returns.\ndo {\n    let offerings = try await Purchases.shared.attribution.setAppstackAttributionParams(attributionParams)\n    \/\/ Use `offerings` to present the correct paywall for this user\n} catch {\n    \/\/ handle error\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This is enough for RevenueCat to start storing attribute subscription revenue information from Appstack.&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-Z1KzB0u wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Device identifiers with iOS App Tracking Transparency (iOS 14.5+)&quot; text=&quot;&lt;div&gt;
&lt;div class=&amp;quot;theme-admonition theme-admonition-danger admonition_xJq3 alert alert--danger&amp;quot;&gt;
&lt;div class=&amp;quot;admonitionContent_BuS1&amp;quot;&gt;
&lt;p&gt;&lt;span style=&amp;quot;font-weight: 400;&amp;quot;&gt;One thing to watch for on iOS: i&lt;/span&gt;f you are requesting the App Tracking permission through ATT to access the IDFA, call&amp;nbsp;&lt;code&gt;setAppstackAttributionParams()&lt;/code&gt;&amp;nbsp;again after the customer grants permission, passing the latest params from&amp;nbsp;&lt;code&gt;AppstackAttributionSdk.shared.getAttributionParams()&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&quot; icon=&quot;warning&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;p&gt;Keep in mind that  &lt;code&gt;AdSupport&lt;/code&gt; framework is required to collect the IDFA on iOS.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;649&quot; height=&quot;155&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-1.png&quot; alt=&quot;&quot; class=&quot;wp-image-52077&quot; style=&quot;aspect-ratio:4.187241997040268;width:840px;height:auto&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-1.png 649w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-1-300x72.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-1-50x12.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-1-125x30.png 125w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-1-560x134.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-1-80x19.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-1-48x11.png 48w&quot; sizes=&quot;auto, (max-width: 649px) 100vw, 649px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-subscription-lifecycle-event-forwarding&quot;&gt;&lt;strong&gt;2. Subscription lifecycle event forwarding&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The Appstack integration uses a reserved &lt;a href=&quot;https://www.revenuecat.com/docs/customers/customer-attributes&quot;&gt;subscriber attribute&lt;/a&gt; to associate RevenueCat events with users in Appstack if the integration is configured to send events. Event forwarding supports following properties:&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Includes Revenue&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Supports Negative Revenue&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Sends Sandbox Events&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Includes Customer Attributes&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Sends Transfer Events&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Optional Event Types&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;❌&lt;/td&gt;&lt;td&gt;❌&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;❌&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;Configure Appstack in the RevenueCat dashboard under Integrations → Attribution → Appstack. You’ll need your &lt;strong&gt;webhook URL&lt;/strong&gt; and an &lt;strong&gt;authorization header&lt;/strong&gt; from Appstack.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;815&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-10-at-22.10.12-1024x815.png&quot; alt=&quot;&quot; class=&quot;wp-image-52075&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-10-at-22.10.12-1024x815.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-10-at-22.10.12-300x239.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-10-at-22.10.12-768x611.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-10-at-22.10.12-1536x1223.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-10-at-22.10.12-2048x1630.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-10-at-22.10.12-50x40.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-10-at-22.10.12-583x464.png 583w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-10-at-22.10.12-696x554.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-10-at-22.10.12-560x446.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-10-at-22.10.12-372x296.png 372w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-10-at-22.10.12-593x472.png 593w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-10-at-22.10.12-80x64.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-10-at-22.10.12-48x38.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Once set up, RevenueCat forwards the full event suite. This lets you measure subscription revenue and LTV from your acquisition campaigns in Appstack, rather than just top-of-funnel installs. Following events are sent to Appstack&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Initial Purchase&lt;/li&gt;



&lt;li&gt;Renewal&lt;/li&gt;



&lt;li&gt;Cancellation&lt;/li&gt;



&lt;li&gt;Uncancellation&lt;/li&gt;



&lt;li&gt;Non-Renewing Purchase&lt;/li&gt;



&lt;li&gt;Subscription Paused&lt;/li&gt;



&lt;li&gt;Expiration&lt;/li&gt;



&lt;li&gt;Billing Issue&lt;/li&gt;



&lt;li&gt;Product Change&lt;/li&gt;



&lt;li&gt;Transfer&lt;/li&gt;



&lt;li&gt;Subscriber Alias&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-get-started-today&quot;&gt;Get started today&lt;/h2&gt;



&lt;p&gt;Integrate RevenueCat with Appstack for attribution and targeting to get a clear picture from ad click to paying subscriber to long-term LTV. The integration is live now on iOS and Android SDKs, available for all apps from the Attribution section of your RevenueCat dashboard. &lt;a href=&quot;https://www.revenuecat.com/docs/integrations/attribution/appstack&quot;&gt;Check out the full docs&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Inside the product org at RevenueCat]]></title><description><![CDATA[A peek under the hood of our product org (we’re hiring!)]]></description><link>https://www.revenuecat.com/blog/company/inside-product-engineering/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/company/inside-product-engineering/</guid><pubDate>Mon, 09 Mar 2026 12:42:53 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Blog_31_Inside-our-product-team.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;RevenueCat’s&lt;a href=&quot;https://www.revenuecat.com/blog/company/values/&quot;&gt;mission&lt;/a&gt; is to &lt;strong&gt;help developers make more money&lt;/strong&gt;. Our CEO, &lt;a href=&quot;https://www.linkedin.com/in/jeiting&quot;&gt;Jacob&lt;/a&gt;, reminds us in every biweekly all-hands meeting that we do this by “building a winning team” and “shipping and selling stuff that helps developers make more money”. The latter, &lt;em&gt;shipping stuff, &lt;/em&gt;is the remit of Engineering, Product &amp;amp; Design (EPD), and one of the three pillars of the &lt;em&gt;winning team &lt;/em&gt;is our team of product engineers.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;That product team currently consists of five product engineers, with several roles open and more to be hired over 2026. So I want to share a bit more about what it’s like to be a product engineer (PE) at RevenueCat, what it takes to be a successful PE here, and what challenges we’re facing.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-makes-the-revenuecat-product-special&quot;&gt;&lt;strong&gt;What makes the RevenueCat product special&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;There are many products you could work on as a product person, from consumer products everybody knows (including your parents!) to niche products that baffle anyone not privy to the specific industry. RevenueCat definitely falls into the second category, but nonetheless, it’s a very special product.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-obscure-problems-meaningful-impact&quot;&gt;&lt;strong&gt;Obscure problems, meaningful impact&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;One of the defining features of RevenueCat is that we’re solving really complex, somewhat-arcane problems. Understanding what each field in an in-app purchase payload represents, what edge cases exist across Apple, Google, and Stripe, and how to best handle them is complicated and rarely glamorous.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;We often say&lt;em&gt; we eat pain for a living &lt;/em&gt;— meaning, &lt;strong&gt;we solve painful infrastructure problems so developers don’t have to. &lt;/strong&gt;That alone would make RevenueCat a complex product to work on. But what makes it meaningful is the reason behind all that work: we help app developers monetize their apps, because…&amp;nbsp;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;We believe that more software is (when averaged out), a net good for the world&lt;/li&gt;



&lt;li&gt;We believe that allowing people to create software and make a living from that is the best way to help humanity create more software&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;If you buy into these beliefs, then RevenueCat is a great product to work on, because the problems we solve help tens of thousands of developers monetize their apps.&lt;/p&gt;



&lt;p&gt;Many of us at RevenueCat come from app backgrounds and/or still have indie apps on the app stores. We relate to the problems we solve and the value we bring to the industry, simply because we’ve been in the shoes of our customers. That makes us unique.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-a-product-loved-by-its-customers&quot;&gt;&lt;strong&gt;A product loved by its customers&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;RevenueCat is a product with many fans. Not every customer is a fan, of course — some have legitimate gripes with the product, and for some it’s just a tool for their day-to-day work. But we have many customers who really love the product, because they see us enable them to get paid doing what they love: building apps.&lt;/p&gt;



&lt;p&gt;Whether it’s meeting customers at conferences who seek our booth out to talk about the app, or people coming to App Growth Annual, it’s wonderful hearing people love the product you work on. We regularly see customers proudly post on social media about their first RevenueCat invoice — this means they’ve crossed the threshold of our free plan and are now making real money from their app. There aren’t many products customers are so happy to pay for!&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-rich is-provider-twitter wp-block-embed-twitter&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;blockquote class=&quot;twitter-tweet&quot; data-width=&quot;500&quot; data-dnt=&quot;true&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;The bill we all want to pay — and paying it is an achievement for mobile developers. Our first invoice paid to RevenueCat! &lt;a href=&quot;https://t.co/pThxeErMcN&quot;&gt;pic.twitter.com/pThxeErMcN&lt;/a&gt;&lt;/p&gt;— Camilo Peñalver (@camilopenalver) &lt;a href=&quot;https://twitter.com/camilopenalver/status/1983177355872088188?ref_src=twsrc%5Etfw&quot;&gt;October 28, 2025&lt;/a&gt;&lt;/blockquote&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;This kind of feedback makes working on RevenueCat extremely rewarding, and also provides that motivation to help customers who run into issues.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-aligned-business-customer-incentives&quot;&gt;&lt;strong&gt;Aligned business-customer incentives&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Speaking of first invoices, one of the best features about RevenueCat and its business model is how it aligns our incentives with those of our customers. We charge customers a percentage of their revenue. This means that &lt;strong&gt;when they grow, we grow.&lt;/strong&gt; When they make money, we make money.&lt;/p&gt;



&lt;p&gt;There is almost no purer business model. We want our customers to succeed because we will, too. &lt;strong&gt;Our incentives and the incentives of our customers are perfectly aligned.&lt;/strong&gt; This makes decisions about the business viability of product choices much easier.&lt;/p&gt;



&lt;p&gt;A few years ago, we decided to simplify our pricing structure so every customer gets access to all features, regardless of whether they’re on the free tier or an enterprise plan. We can do this because our revenue scales with our customers’ revenue anyway, so naturally, bigger customers will pay us more. We also believe that &lt;strong&gt;everyone should be able to benefit from the growth tools we provide&lt;/strong&gt;. If we limited access to those tools to smaller developers on a cheaper plan, we would be limiting our own growth potential.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-different-surface-areas-and-challenges&quot;&gt;&lt;strong&gt;Different surface areas and challenges&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The last distinct characteristic of the product that I want to highlight is the different surface areas we have; all of which come with their unique (technical) challenges.&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Backend: &lt;/strong&gt;our backend is critical infrastructure for our customers. We need to prioritize reliability to ensure we don’t jeopardize our customers’ revenue streams, and we need the backend to be ultra-scalable. Our backend processes billions of API requests every day. Our most used API endpoints need to be fully&lt;a href=&quot;https://www.revenuecat.com/blog/engineering/data-caching-revenuecat/&quot;&gt; cached&lt;/a&gt; or our database would be a smoldering wreck in an instant.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;SDKs and APIs: &lt;/strong&gt;these need to be designed in a way that they remain stable for years to come, since developers will build their apps and backends relying on them. For the SDKs in particular, the quality bar is extremely high, because a buggy SDK that gets implemented by a developer could be out in the wild for a very long time if someone installs an app using that SDK and never updates it.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Web dashboard&lt;/strong&gt;: here we have a much higher degree of freedom to innovate and iterate quickly, and therefore deploy changes extremely rapidly.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Consumer-facing UI: &lt;/strong&gt;recently, we’ve shipped more and more consumer-facing UI: our&lt;a href=&quot;https://www.revenuecat.com/docs/tools/paywalls&quot;&gt; paywalls&lt;/a&gt;,&lt;a href=&quot;https://www.revenuecat.com/docs/tools/customer-center&quot;&gt; customer center&lt;/a&gt;,&lt;a href=&quot;https://www.revenuecat.com/docs/web/web-billing/customization&quot;&gt; web checkout&lt;/a&gt;, and&lt;a href=&quot;https://www.revenuecat.com/docs/web/web-billing/customer-portal&quot;&gt; web customer portal&lt;/a&gt; are all used by our customers’ customers and therefore need a high degree of polish in order to inspire trust.&lt;/li&gt;
&lt;/ol&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-we-approach-product-work&quot;&gt;&lt;strong&gt;How we approach product work&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Our approach to product work is shaped by our values as well as our talent vision. &lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-product-engineering-not-product-management&quot;&gt;Product engineering, not product management&lt;/h3&gt;



&lt;p&gt;We recently made the decision to change the roles from product &lt;em&gt;managers&lt;/em&gt; to product &lt;em&gt;engineers&lt;/em&gt;, and folded product engineers into the engineering org. In a world where AI assisted development is making &lt;em&gt;writing code&lt;/em&gt; less of a bottleneck, product and engineering need to move even closer together: product people can ship changes to the product without involving a software engineer, and when writing code no longer becomes the main task of software engineers, they need to show greater product sense and judgment in order to be successful. It also means a greater need than ever for product people and software engineers to be aligned and walk in lock step, and this role change is strengthening that alignment.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-deciding-what-to-build&quot;&gt;&lt;strong&gt;Deciding what to build&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Every year, we decide on a product strategy. The product strategy determines the main focus areas for the coming year. In general, the yearly product strategy is an evolution of the one that came before it, rather than a revolution or radical pivot. The strategy is set at leadership level, and PEs provide critical input as it is being shaped.&lt;/p&gt;



&lt;p&gt;In line with the strategy, we also revisit our team setup. We have relatively stable cross-functional teams where a PE works together with a team of engineers, reporting to an engineering manager (EM), as well as a designer.&lt;/p&gt;



&lt;p&gt;The roadmap is mostly determined in our quarterly planning process. We’ve gone through a number of iterations of this process over the years. Currently, the process is as follows:&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Each team, represented by its PE, EM and designer, proposes a set of priorities for the team These are then reviewed and discussed with leadership (CEO, CTO, Head of Product). There can be some adjustments to the roadmap in these discussions, but by and large, the teams own their roadmap and prioritization. Product engineers play a pivotal role in this process — often, they are the ones who have the most holistic view of their product area and the value that we can deliver to our customers through product improvements.&lt;/p&gt;



&lt;p&gt;On a day-to-day and week-to-week basis, product managers work closely with their EM and designer counterparts, with at least weekly meetings and even more frequent interactions via async communication. The discovery and delivery of features in the team is owned by the whole team, and achieved through tight collaboration.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-living-our-values-in-the-product-team&quot;&gt;&lt;strong&gt;Living our values in the product team&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;As mentioned, the other aspect that shapes our approach to product are the company values. These aren’t a list of values stuck in a Notion doc and forgotten about, they’re an ethos we actively work toward and measure ourselves against.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-customer-obsession&quot;&gt;&lt;strong&gt;Customer obsession&lt;/strong&gt;&lt;/h4&gt;



&lt;p&gt;At RevenueCat, we believe in focusing on &lt;strong&gt;delivering value to our customers above everything else&lt;/strong&gt;. This means several things:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;PEs are expected to talk and interact with customers frequently&lt;/strong&gt;: this includes 1:1 conversations and research calls, but also support tickets, social media posts, sales conversations, shared Slack channels with customers, conference booth chats, etc.
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;There is &lt;strong&gt;no barrier between PEs and customers&lt;/strong&gt;: if a conversation is going to help you make a better product decision, just set it up&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Customer anecdotes&lt;/strong&gt; are often the most convincing way to argue for product decisions at RevenueCat. Of course, we don’t blindly build everything that customers ask for, but we try to find the underlying needs and problems. Generally, we believe that if a customer cares enough about the product to tell you their issues and unsolved problems, it’s wise to listen.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Teams will be attentive to customer needs&lt;/strong&gt;, regardless of problem scale — even the small issues that bug our customers. Our strategy is important, our roadmap is important, but if we can show a customer we care by quickly fixing a bug they encountered or removing a limitation they ran into, that will often make their day and turn doubters into fans (or fans into evangelists).&lt;/li&gt;
&lt;/ul&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-always-be-shipping&quot;&gt;&lt;strong&gt;Always be shipping&lt;/strong&gt;&lt;/h4&gt;



&lt;p&gt;&lt;em&gt;Always be shipping&lt;/em&gt; impacts our approach to product by pushing us to reduce the scope of whatever we are planning to the MVP version. There’s a couple reasons to do so:&amp;nbsp;&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;It means delivering value to customers more quickly&lt;/li&gt;



&lt;li&gt;It allows us to get feedback and validation from customers as early as possible&lt;/li&gt;
&lt;/ol&gt;



&lt;h5 class=&quot;wp-block-heading&quot; id=&quot;h-shipping-goals&quot;&gt;&lt;strong&gt;Shipping goals&lt;/strong&gt;&lt;/h5&gt;



&lt;p&gt;One way of forcing us to truly always be shipping and minimize scope is setting internal deadlines. &lt;/p&gt;



&lt;p&gt;When we have set such a shipping goal, we’ll do everything we can to ship it by the internal deadline, like adding resources to allow the team to go faster. It often also forces us to make painful scope cuts, where we reduce some aspect from a ‘must-have’ to a ‘nice-to-have’ (which, if you know anything about software development, more often than not means it won’t &lt;em&gt;actually &lt;/em&gt;get done).&lt;/p&gt;



&lt;p&gt;What frequently happens is that once we launch a feature and get it into customers’ hands, the first requests we get aren’t for the thing we deprioritized, but for something completely different. This proves the value of shipping quickly: neither us nor our customers are good at predicting how they will actually interact with a feature once it’s actually live in the product. The only reliable way to determine that is to ship fast and iterate after.&lt;/p&gt;



&lt;h5 class=&quot;wp-block-heading&quot; id=&quot;h-bias-for-action&quot;&gt;&lt;strong&gt;Bias for action&lt;/strong&gt;&lt;/h5&gt;



&lt;p&gt;One other aspect of &lt;em&gt;always be shipping&lt;/em&gt; is our bias for action. We’re always acting with imperfect information. If we waited for perfect information, we would never make any decisions. Therefore, as product engineers, &lt;strong&gt;we’re responsible for pushing decisions forward, even in the face of uncertainty&lt;/strong&gt;. It is rare that decisions can’t be corrected later on, so moving forward beats endlessly deliberating. Act, don’t talk.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-own-it&quot;&gt;&lt;strong&gt;Own it&lt;/strong&gt;&lt;/h4&gt;



&lt;p&gt;Ownership is very important at RevenueCat. For product engineers, it means that nothing is someone else’s problem. We all win together, we all lose together. If you notice a problem, do something about it — even if it’s not your area.&lt;/p&gt;



&lt;p&gt;Of course, that doesn’t mean that PEs have to &lt;em&gt;fix all problems&lt;/em&gt;. However, since they’re often the ones with the broadest, most end-to-end understanding (from customer problem to solution design to technical approach), they’re often the ones who are best positioned to &lt;em&gt;notice problems&lt;/em&gt; (and are expected to do so).&lt;/p&gt;



&lt;p&gt;RevenueCat product engineers also have &lt;a href=&quot;https://x.com/shreyas/status/1276956836856393728?s=20&quot;&gt;high agency&lt;/a&gt;, meaning we believe in their ability to affect change even in adverse conditions. Our PEs will do everything they can to address the problems they see, and sometimes even a bit more than that (i.e. learn something new to better solve problems). They dig through the code base to see if they can find the root cause of a bug, they query our data warehouse to better understand our data, or they get on a call with a customer on short notice to debug their issues.&lt;/p&gt;



&lt;p&gt;AI-assisted development also means that product managers are now making contributions to our code base on a somewhat regular basis. In cases where the changes are straightforward, it is often significantly faster for a PE to make a change directly via Cursor or Claude Code and get it reviewed and shipped, versus writing a ticket for an engineer to pick up.&lt;/p&gt;



&lt;p&gt;TL;DR: there’s a lot going on, and it’s all hands on-deck.&amp;nbsp;&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-balance&quot;&gt;&lt;strong&gt;Balance&lt;/strong&gt;&lt;/h4&gt;



&lt;p&gt;Our &lt;em&gt;balance&lt;/em&gt; value is perhaps the most misunderstood — it doesn’t mean we’re slacking off (on the contrary, RevenueCat is still a startup and working here is deliberately intense). &lt;strong&gt;We only win if we continue to move fast.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;However, our balance value reminds us that there is a fine line between moving fast and burning out. Hard work can be extremely rewarding &lt;em&gt;if&lt;/em&gt; we are working on interesting problems with teams of highly-motivated people. PEs are often pivotal in upholding the motivation and interest level of the team; it’s their job to connect the problems we’re solving with the customer impact, e.g. sharing customer ‘good feels’ and showcasing contagious excitement.&lt;/p&gt;



&lt;p&gt;Our balance value also covers being empathetic and kind toward others, and building a cohesive team environment where there’s mutual trust and appreciation of everyone as a human being. Product engineers, as natural leaders, can play a key role in modeling and facilitating these behaviors.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-revenuecat-s-talent-vision&quot;&gt;&lt;strong&gt;RevenueCat’s talent vision&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;RevenueCat’s talent vision is to build a &lt;a href=&quot;https://www.revenuecat.com/blog/engineering/engineering-strategy/#h-on-growth&quot;&gt;winning team&lt;/a&gt; of high-caliber team members. This means that we have a high standard for all team members, which we uphold through our hiring and performance management processes.&lt;/p&gt;



&lt;p&gt;There are a few implications of that on our approach to product work. Firstly, our teams consist of relatively senior and product-minded engineers and engineering managers. This means that PEs at RevenueCat generally need to be less in-the-weeds in managing projects, creating super detailed tickets, etc. Instead, they need to be better at &lt;strong&gt;communicating the necessary context and understanding of the problem space&lt;/strong&gt;, in order for engineers to not get bottlenecked by PE decision making.&lt;/p&gt;



&lt;p&gt;It also means that our team is rather lean. We believe that smaller teams of high-caliber people can move much faster than bigger teams with a lower talent bar.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-main-challenges-our-product-team-is-facing&quot;&gt;&lt;strong&gt;The main challenges our product team is facing&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Here are some of the main challenges that we face as product engineers at RevenueCat.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-too-much-to-do-too-little-time&quot;&gt;&lt;strong&gt;Too much to do, too little time&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;This might be the quintessential startup issue, and it’s definitely true at RevenueCat: we always have more ideas, and more customer problems to solve than we have the capacity to work on. This means that as a company, as individual teams, and as PEs, we have to prioritize well, and be able to communicate that prioritization to the market, to customers, and to internal stakeholders. We solve this through our strategy and planning process to make sure we continuously focus on the highest-impact opportunities.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-balancing-customer-obsession-and-strategic-priorities&quot;&gt;&lt;strong&gt;Balancing customer obsession and strategic priorities&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Related to the need for prioritization outlined above, we’re often drawn in different directions by our &lt;em&gt;customer obsession&lt;/em&gt; value and our strategic priorities. Strategic projects can take a while before showing impact, and our customer obsession value makes us consider smaller customer requests with urgency. Getting drawn to either extreme is not great: if we deprioritize customer feedback completely to focus on long-term strategic priorities, we will seem unresponsive and risk losing the customer love we’ve built up. On the other hand, if we only prioritize being attentive to customer feedback, we miss out on big swings, following the market, or unlocking the next big opportunities for the product and the company.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-growth-means-increasing-coordination&quot;&gt;&lt;strong&gt;Growth means increasing coordination&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;RevenueCat has shown a great growth trajectory over the past few years. We have grown our team less quickly than our revenue (part of the &lt;em&gt;winning team &lt;/em&gt;talent vision), but we still have grown and are planning to continue to do so. A bigger EPD team means more capacity to improve our products, but it also means increased coordination needed. Doubling our engineering team doesn’t mean we can ship twice as many changes, since some of that capacity will need to go toward coordinating work. Plus, adding more teams increases the risk of building experiences that are inconsistent between different corners of the product (which again requires coordination to prevent).&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-becoming-a-multi-product-company&quot;&gt;&lt;strong&gt;Becoming a multi-product company&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The biggest strategic challenge we have in front of us is moving from a single-product company to a multi-product company. RevenueCat has long been the best way of adding in-app purchases to your app. This means that a large proportion of subscription apps on the app stores launch with RevenueCat today. However, the market of new subscription apps is limited.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;To keep growing, we need to both be able to provide more value to our existing target market, and sell to customers for which the current RevenueCat product is not a good fit. Both of these require becoming a multi-product company: either adding completely new products or unbundling our existing product into pieces that can be sold separately.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;We’re planning both, and that means fundamentally changing the process for how we make product decisions. We need to build experiences that make sense when you are using only part of the platform. We need to set up pricing and billing models. We need to conceive onboarding flows that find the right product and set it up.&lt;/p&gt;



&lt;p&gt;We are only at the beginning of this journey, and it will keep us busy for the foreseeable future.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-makes-for-a-good-revenuecat-product-engineers&quot;&gt;&lt;strong&gt;What makes for a good RevenueCat &lt;/strong&gt;product engineers&lt;/h2&gt;



&lt;p&gt;Still with me? Okay, let’s jump into what makes a good fit for product engineers at RevenueCat. Maybe you’re the right fit, or perhaps you know someone who is?&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Builders, not managers:&lt;/strong&gt; RevenueCat PEs see themselves as product builders. We don’t manage backlogs or juggle stakeholders — we collaborate, advocate for the best solutions, and help our teams move faster.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Missionaries:&lt;/strong&gt; Our mission is to help developers make more money, and PEs embrace that fully. We’re customer-obsessed because we believe more software is good for the world, and thriving developers means more software.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Extreme ownership:&lt;/strong&gt; RevenueCat PEs do everything it takes to solve customer problems and make the product successful. They don’t point fingers, blame others, or accept failure; they find a way forward while contributing as true teammates and carrying shared weight, rather than being a lone wolf.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Decisive with imperfect info:&lt;/strong&gt; In a fast-paced startup, PEs gather just enough information to make a decision quickly. They act based on current data, commit to the action path, and rally the team, but stay open to changing course if needed when new information arrives.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Deep technical understanding:&lt;/strong&gt; RevenueCat meets multiple personas, but at its core it’s a developer tool. PEs need to have deep technical knowledge and be able to explain and evaluate decisions about APIs, distributed systems, SDK constraints, and data models.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Strong asynchronous communicator:&lt;/strong&gt; As a globally remote team, RevenueCat PEs excel at clear async communication — whether through docs, Looms, or FigJams — and they know when to switch to real-time conversations to keep the team aligned.&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-we-re-hiring&quot;&gt;&lt;strong&gt;We’re hiring!&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;We’re almost constantly growing the product engineering team at RevenueCat. If you’re a builder who loves solving hard problems with meaningful impact — and you want to help tens of thousands of developers make a living doing what they love — we’d love to talk. Check out our &lt;a href=&quot;https://jobs.ashbyhq.com/revenuecat&quot;&gt;open roles on our careers page&lt;/a&gt;!&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Exit Offers in RevenueCat Paywalls]]></title><description><![CDATA[Everything you need to know about implementing exit offers in RevenueCat Paywalls, including the App Review gray area you can't afford to ignore]]></description><link>https://www.revenuecat.com/blog/engineering/exit-offers-in-revenuecat-paywalls/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/exit-offers-in-revenuecat-paywalls/</guid><pubDate>Fri, 06 Mar 2026 21:07:45 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Blog_26_Exit-offers-in-paywalls.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;RevenueCat Paywalls offer a powerful feature for earning the business of more price-sensitive users: &lt;strong&gt;exit offers&lt;/strong&gt;. With exit offers you can present an alternative offering, usually a discounted plan, to users the moment they dismiss a paywall, giving you a second chance to convert a user who might otherwise be lost.&lt;/p&gt;



&lt;p&gt;This is a common and effective strategy used in e-commerce to reduce cart abandonment, and it is a valuable capability for mobile app developers. However, the implementation of such offers on the App Store has been a topic of much discussion and some confusion. In this post, we’ll walk you through how to use Exit Offers, discuss the potential for App Review issues with Apple, and provide our recommendation on how to proceed.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-are-exit-offers&quot;&gt;What are Exit Offers?&lt;/h2&gt;



&lt;p&gt;An exit offer is a secondary offer you present to a user when they attempt to close your primary paywall without making a purchase. Instead of simply losing a potential subscriber, you can present them with an alternative, such as a lower price, a longer trial, or a different subscription term.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;500&quot; height=&quot;984&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/exit-offers.gif&quot; alt=&quot;&quot; class=&quot;wp-image-51562&quot;&gt;&lt;/figure&gt;



&lt;p&gt;For example, if your main paywall promotes an annual plan, your exit offer could be a monthly plan. This allows you to capture users who may have been interested but were not ready to commit to a full year.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-to-implement-exit-offers-with-revenuecat&quot;&gt;How to Implement Exit Offers with RevenueCat&lt;/h2&gt;



&lt;p&gt;We’ve integrated Exit Offers directly into the Paywall Builder in the RevenueCat dashboard, so you can enable them without any code changes. When editing a paywall, you can now designate another one of your offerings to be presented as an exit offer.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;728&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-1024x728.png&quot; alt=&quot;&quot; class=&quot;wp-image-51560&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-1024x728.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-300x213.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-768x546.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-1536x1092.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-50x36.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-56x40.png 56w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-652x464.png 652w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-696x495.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-560x398.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-416x296.png 416w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-664x472.png 664w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-80x57.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image-48x34.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/image.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;This makes it easy to experiment with different win-back strategies and measure their impact on your conversion rates and revenue.&lt;/p&gt;



&lt;p&gt;An important implementation note is that exit offers only work when using the presentPaywall or presentPaywallIfNeeded functions that display paywalls in iOS and cross-platform SDKs. On Android, they are automatically enabled when utilizing the PaywallDialog and PaywallActivity classes.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Crucially, exit offers will not work if you manually embed paywall views or components directly into your UI&lt;/strong&gt; (e.g., PaywallView, Paywall composable, &amp;lt;RevenueCatUI.Paywall&amp;gt; component, etc.). Full details can be found in the &lt;a href=&quot;https://www.revenuecat.com/docs/tools/paywalls/displaying-paywalls#exit-offers&quot;&gt;paywalls documentation&lt;/a&gt;.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-a-note-on-apple-s-app-store-review&quot;&gt;A Note on Apple’s App Store Review&lt;/h2&gt;



&lt;p&gt;While exit offers are a standard practice on the web, their use on the App Store has been inconsistent. Some developers have reported that their apps have been rejected for using them, with Apple’s App Review citing &lt;strong&gt;Guideline 5.6 – Developer Code of Conduct&lt;/strong&gt;. This guideline states that apps should not engage in “manipulative practices” to trick users into making unwanted purchases.&lt;/p&gt;



&lt;p&gt;The rejection messages are often similar to this one &lt;a href=&quot;https://www.reddit.com/r/iOSProgramming/comments/1pa71k5/guideline_56_rejection_manipulation_for_showing_a/&quot;&gt;reported by a developer on Reddit&lt;/a&gt;:&lt;/p&gt;



&lt;p&gt;“The app attempts to manipulate customers into making unwanted in-app purchases. Specifically, your app still displayed an additional discount offer when we attempted to exit the subscription page.”&lt;/p&gt;



&lt;p&gt;Here’s what Apple’s &lt;a href=&quot;https://developer.apple.com/app-store/review/guidelines/&quot;&gt;App Review Guidelines&lt;/a&gt; explicitly say in Guideline 5.6:&lt;br&gt;&lt;br&gt;&lt;em&gt;Apps should never prey on users or attempt to rip off customers, &lt;/em&gt;&lt;strong&gt;&lt;em&gt;trick them into making unwanted purchases,&lt;/em&gt;&lt;/strong&gt;&lt;em&gt; force them to share unnecessary data, raise prices in a tricky manner, charge for features or content that are not delivered, or engage in any other manipulative practices within or outside of the app.&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;This has created a gray area for developers. The guideline itself does not explicitly forbid exit offers, and the term “manipulative” is subjective. Many popular apps currently use exit offers, yet some App Reviewers do seem to be rejecting apps based on this guideline.&lt;/p&gt;



&lt;p&gt;Note that we have not heard any reports of rejections from developers submitting Android apps to the Google Play app store. As of this writing, exit offers seem to be in compliance with &lt;a href=&quot;https://transparency.google/intl/en/our-policies/product-terms/google-play/&quot;&gt;Google Play Policies and Guidelines&lt;/a&gt;.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-our-recommendation-try-on-android-but-be-careful-on-ios&quot;&gt;Our Recommendation: Try on Android but be careful on iOS&lt;/h2&gt;



&lt;p&gt;At RevenueCat, we believe that a well-implemented exit offer is a legitimate marketing tool that can provide value to users by giving them more options. However, given the current ambiguity and the risk of rejection from Apple’s App Review, &lt;strong&gt;we advise developers to use this feature at their own risk for their iOS apps.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;It is worth trying on your Android apps to see how it impacts your conversion before running the risk on iOS. You can use RevenueCat’s &lt;a href=&quot;https://www.revenuecat.com/docs/tools/targeting&quot;&gt;Targeting&lt;/a&gt; feature to only send paywalls with exit offers to your Android users.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-do-not-try-to-trick-app-review&quot;&gt;DO NOT try to trick App Review&lt;/h2&gt;



&lt;p&gt;We want to be very clear on this point: &lt;strong&gt;you absolutely should not attempt to circumvent App Review by remotely enabling this feature after your app has been approved.&lt;/strong&gt; This is a direct violation of the Apple Developer Program License Agreement and could result in the termination of your developer account. The risk is not worth the reward, we promise.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-conclusion&quot;&gt;Conclusion&lt;/h2&gt;



&lt;p&gt;Exit offers are a powerful new tool in your monetization arsenal. They can help you recapture lost subscribers and increase your revenue. However, the current App Review landscape means that you must be cautious when implementing them.&lt;/p&gt;



&lt;p&gt;We will continue to monitor the situation and provide updates as we learn more. We encourage you to be prepared for a potential rejection if you use this feature and to have a plan to address it. We look forward to hearing about your experiences with exit offers and App Review.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[What Google Play’s new merchandising and optimization page means for Android developers]]></title><description><![CDATA[In this article, you'll explore what the three existing out of app merchandizing features are and how they work, what Google Play is changing by unifying them into the new Merchandizing and optimization page.]]></description><link>https://www.revenuecat.com/blog/engineering/google-play-merchandising/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/google-play-merchandising/</guid><pubDate>Thu, 05 Mar 2026 23:35:13 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Blog_25_What-Google-Plays-new-merchandising-and-optimization-page-means-for-Android-developers.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Most Android developers think about monetization in terms of what happens inside their app: launching a billing flow, presenting a paywall, handling purchase results. But Google Play also merchandises your products outside your app, recommending them to users on store surfaces, in notifications, and during the browsing experience. These out-of-app surfaces drive purchases that many developers never actively manage. Now, Google is consolidating three separate merchandising features into a single ML-driven page, and there is a hard deadline to prepare.&lt;/p&gt;



&lt;p&gt;In this article, you’ll explore what the three existing out of app merchandising features are and how they work, what Google Play is changing by unifying them into the new Merchandizing and optimization page, the timeline and March 16 cutoff that affects your existing configurations, special considerations for each feature during the migration, concrete steps you should take before the deadline, and how out of app purchases connect to your billing stack.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-background-how-google-play-merchandises-your-products-outside-your-app&quot;&gt;&lt;strong&gt;Background: How Google Play merchandises your products outside your app&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Before diving into what is changing, it is important to understand what Google Play already does to promote your products beyond your app’s own UI. Out-of-app merchandising is significant because it reaches users who are not currently inside your app. A user browsing the Play Store, receiving a notification, or exploring related content may encounter your products without ever opening your app first. This creates an additional acquisition and conversion channel that operates independently of your in-app purchase UI.&lt;/p&gt;



&lt;p&gt;There are three distinct features that handle out-of-app merchandising today, each configured separately in the Google Play Console.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-purchase-flow-recommendations&quot;&gt;&lt;strong&gt;Purchase flow recommendations&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Purchase flow recommendations allow Google Play to suggest your products to users as they browse the Play Store. When a user is exploring apps, viewing related content, or navigating purchase surfaces, Google Play can display your in-app products or subscriptions as recommendations. These suggestions are based on the user’s purchase history, browsing behavior, and contextual signals.&lt;/p&gt;



&lt;p&gt;You configure purchase flow recommendations by selecting which SKUs are eligible for promotion and optionally targeting specific countries. Google Play then decides when and where to show these recommendations to relevant users. The configuration lives on its own dedicated&amp;nbsp;&lt;a href=&quot;https://support.google.com/googleplay/android-developer/answer/15317027&quot;&gt;purchase flow recommendations page&lt;/a&gt;&amp;nbsp;in the Google Play Console.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-featured-products&quot;&gt;&lt;strong&gt;Featured products&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Featured products give you more direct control over promotion. Rather than letting Google Play choose which products to surface, you explicitly configure which products to highlight on Google Play surfaces. You can set start and end dates for promotions, associate them with specific offers or events, target specific audiences and countries, and limit them to licensed testers during development.&lt;/p&gt;



&lt;p&gt;Featured products are useful for time-limited promotions, seasonal campaigns, or highlighting new premium content. They give you granular control over what gets promoted, to whom, and for how long.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-cart-abandonment-reminders&quot;&gt;&lt;strong&gt;Cart abandonment reminders&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Cart abandonment reminders address a different part of the purchase funnel. When a user begins a purchase flow but does not complete it, Google Play can send a notification reminding them to finish the transaction. This is a common e-commerce pattern adapted for the app store context.&lt;/p&gt;



&lt;p&gt;For cart abandonment reminders, you do not configure individual products. Instead, Google Play automatically tracks abandoned purchase attempts and sends reminders for users who started but did not finish a transaction. You can opt out of this feature entirely using a form in the Google Play Console if you prefer not to have reminders sent for your products. Currently, the opt-out is managed separately for one-time products and subscriptions.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-s-changing-a-unified-ml-driven-approach&quot;&gt;&lt;strong&gt;What’s changing: A unified, ML-driven approach&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Google is replacing these three separate tools with a single&amp;nbsp;&lt;a href=&quot;https://support.google.com/googleplay/android-developer/answer/16431369&quot;&gt;Merchandising and optimization page&lt;/a&gt;&amp;nbsp;in the Google Play Console. Instead of managing purchase flow recommendations, featured products, and cart abandonment reminders independently, you will configure everything from one place.&lt;/p&gt;



&lt;p&gt;The fundamental shift is from manual configuration to algorithmic optimization. Here is how the new approach works:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;You select eligible SKUs&lt;/strong&gt;: On the new page, you choose which of your products are eligible for out-of-app promotion.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Google’s ML decides the rest&lt;/strong&gt;: Google Play’s machine learning models determine the optimal surfaces, timing, and audiences for displaying your selected products.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Broader reach, less manual control&lt;/strong&gt;: The ML system can place your products across all out-of-app purchase flows that Google Play supports, potentially reaching more users than manually configured promotions would.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;This means you lose some of the granular control that the featured products provided. You will no longer be able to set audience targeting, country targeting, or associate promotions with specific offers and events at the merchandising level. If you need country-level restrictions, you must configure them at the SKU level instead.&lt;/p&gt;



&lt;p&gt;The trade-off is straightforward. You give up manual configuration in exchange for Google’s ML optimizing placement across a broader set of surfaces. For most developers, this should result in better performance because the ML models can test and iterate on placement strategies far faster than any manual configuration can.&lt;/p&gt;



&lt;p&gt;For developers who have never configured any of these features, the new page is an opportunity. Previously, managing three separate configuration surfaces was enough friction to discourage many developers from engaging with out-of-app merchandising at all. A single page with a simpler interface lowers the barrier to entry. If you have products that could benefit from being promoted on Google Play surfaces, the new Merchandising and optimization page makes it easier to opt in.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-timeline-what-happens-and-when&quot;&gt;&lt;strong&gt;The timeline: What happens and when&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The migration follows a phased approach with a clear cutoff date. Here is what happens at each stage:&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Date&lt;/th&gt;&lt;th&gt;What happens&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Before March 16&lt;/td&gt;&lt;td&gt;Last chance to modify existing purchase flow recommendations and featured products configurations. Last chance to use the cart abandonment reminder opt out form for one time products.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;March 16&lt;/td&gt;&lt;td&gt;Existing purchase flow recommendations and featured products pages become frozen. The cart abandonment reminder opt out form is disabled for one time products. No further changes can be made on these pages.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;After March 16&lt;/td&gt;&lt;td&gt;Existing selections remain active according to the migration rules described below. Your configurations continue to function but cannot be modified.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;New page launches&lt;/td&gt;&lt;td&gt;Google Play automatically migrates your existing selections to the new Merchandizing and optimization page. You can then modify your selections on the new page. The old pages for purchase flow recommendations and featured products are deprecated. The cart abandonment reminders opt out form for one time products is also deprecated.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;The key takeaway is that March 16 is the hard deadline for any changes to your current setup. If you need to adjust your merchandising configurations, do it before that date.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-special-considerations-for-featured-products&quot;&gt;&lt;strong&gt;Special considerations for featured products&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Featured products have the most complex migration path because they support the most configuration options. Here is what happens to each aspect of your featured products configurations:&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Configuration aspect&lt;/th&gt;&lt;th&gt;What happens after March 16&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;No end date set&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;The featured product remains in place and continues to be merchandized. No action needed.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;End date after March 16&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;You have two options before March 16: make the product available indefinitely by removing the end date, or delete it if you do not want it merchandized past March 16.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Offers and events&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Offers and events associated with featured products will no longer be supported. If you rely on these associations, plan accordingly before the cutoff.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Audience and country targeting&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Audience and country targeting associated with existing featured products will not be supported. If you need to restrict country selection, you must configure that at the SKU level.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Licensed testers&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Products that only target licensed testers will no longer be available for merchandizing. If you have products in a testing only configuration, they will be excluded from out of app promotion.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Performance reporting&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Performance reporting and associated metrics remain visible on the featured products page until it is deprecated when the new Merchandizing and optimization page launches.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;The most impactful change for developers who actively use featured products is the loss of audience and country targeting. If your merchandising strategy depends on showing different products to different regions, you need to rethink that approach. Moving country restrictions to the SKU level is the only remaining option.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-special-considerations-for-purchase-recommendations&quot;&gt;&lt;strong&gt;Special considerations for purchase recommendations&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Purchase recommendations have a simpler migration path because they offer fewer configuration options than featured products:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Active SKUs remain active&lt;/strong&gt;: Any SKUs you have configured for purchase flow recommendations will continue to be eligible for out-of-app purchases after March 16.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Country targeting removed&lt;/strong&gt;: Country targeting associated with your purchase recommendations will no longer be supported. Like featured products, you must handle country restrictions at the SKU level if needed.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Licensed testers excluded&lt;/strong&gt;: Products that only target licensed testers will no longer be available for merchandising.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Performance reporting visible&lt;/strong&gt;: Performance reporting and associated metrics remain on the purchase recommendations page until they are deprecated when the new page launches.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;For most developers using purchase recommendations, the migration is straightforward. Your products continue to be recommended. You just lose the ability to fine-tune which countries see those recommendations.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-special-considerations-for-cart-abandonment-reminders&quot;&gt;&lt;strong&gt;Special considerations for cart abandonment reminders&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Cart abandonment reminders have the simplest migration considerations, but there is one important detail to understand:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;One-time products only in initial launch&lt;/strong&gt;: The new Merchandising and optimization page will initially only include&amp;nbsp;&lt;a href=&quot;https://support.google.com/googleplay/android-developer/answer/16430488&quot;&gt;one-time products&lt;/a&gt;&amp;nbsp;for cart abandonment functionality. Subscriptions are not part of the initial launch scope.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Subscription blocklist unchanged&lt;/strong&gt;: If you have an existing blocklist for subscription cart abandonment reminders, it remains in place and is not affected by this migration.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Opt out mechanics&lt;/strong&gt;: You can opt out of cart abandonment reminders for one-time products using the existing form until March 16. After that, you will need to wait until the Merchandising and optimization page launches to opt out. If you have already opted out, your opt-out remains in effect. If you want to stay opted in, no action is required.&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-you-should-do-before-march-16&quot;&gt;&lt;strong&gt;What you should do before March 16&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Here is a concrete checklist of actions to take before the cutoff:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Audit your featured products&lt;/strong&gt;: Open the featured products page in Google Play Console and review all active configurations. Identify any that have end dates after March 16 and decide whether to make them indefinite or delete them.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Remove reliance on offers and events&lt;/strong&gt;: If any of your featured products are associated with specific offers or events, note that these associations will stop being supported. Plan alternative promotion strategies for those products.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Move country restrictions to the SKU level&lt;/strong&gt;: If you currently use country targeting on featured products or purchase recommendations, reconfigure those restrictions at the SKU level before March 16. This ensures your geographic targeting strategy survives the migration.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Review licensed tester configurations&lt;/strong&gt;: If you have products configured only for licensed testers, understand that they will be excluded from merchandising. If you want these products to be promoted to real users, update the targeting before the cutoff.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Decide on cart abandonment opt out&lt;/strong&gt;: If you want to opt out of cart abandonment reminders for one-time products, submit the opt-out form before March 16. After that date, you will need to wait for the new page to launch.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Save performance data&lt;/strong&gt;: Export or screenshot any performance metrics from the featured products and purchase recommendations pages that you want to retain for historical analysis. These metrics will remain visible until the pages are deprecated, but it is good practice to save them now.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Communicate with your team&lt;/strong&gt;: Make sure anyone on your team who manages Google Play Console configurations is aware of the March 16 deadline and the changes that are coming.&lt;/li&gt;
&lt;/ol&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-out-of-app-purchases-connect-to-your-billing-stack&quot;&gt;&lt;strong&gt;How out-of-app purchases connect to your billing stack&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;A common question when discussing out-of-app merchandising is how these purchases actually flow through your billing infrastructure. The good news is that out-of-app purchases initiated from Google Play surfaces go through the same Play Billing Library flow as any in-app purchase.&lt;/p&gt;



&lt;p&gt;When a user taps on a recommended product, a featured product, or a cart abandonment reminder on a Google Play surface, the resulting purchase is processed through the standard Google Play Billing infrastructure. Your app receives the purchase through the same&amp;nbsp;&lt;code&gt;PurchasesUpdatedListener&lt;/code&gt;&amp;nbsp;or&amp;nbsp;&lt;code&gt;queryPurchasesAsync&lt;/code&gt;&amp;nbsp;calls that handle in-app purchases. The purchase token, product ID, and acknowledgment requirements are all identical. If your backend processes Real Time Developer Notifications (RTDN), you will receive the same notification types for out-of-app purchases as you do for in-app ones.&lt;/p&gt;



&lt;p&gt;This means if you are using RevenueCat to manage your billing infrastructure, out-of-app purchases are processed automatically. RevenueCat’s SDK and backend handle purchase verification, entitlement granting, and acknowledgment for these transactions just like they do for purchases initiated within your app. There is no special SDK integration or code change needed to support purchases originating from out-of-app surfaces.&lt;/p&gt;



&lt;p&gt;RevenueCat Charts can also track revenue from out-of-app surfaces alongside your in-app revenue. Since all purchases flow through the same billing pipeline, your existing analytics and reporting infrastructure captures these transactions without additional configuration. This is particularly useful after the migration, when you want to monitor whether the ML-driven approach is producing more or fewer out-of-app conversions compared to your previous manual configurations.&lt;/p&gt;



&lt;p&gt;The important point is that the Merchandising and optimization page is a Console-side change. It affects how Google Play promotes your products to users, not how those purchases are processed once they happen. Your billing code, RevenueCat integration, and backend systems continue to work exactly as they do today.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-conclusion&quot;&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;In this article, you’ve explored Google Play’s upcoming consolidation of three separate merchandising features, purchase flow recommendations, featured products, and cart abandonment reminders, into a single ML-driven Merchandising and optimization page. The March 16 cutoff is the deadline for modifying any existing configurations, and understanding the migration rules for each feature ensures your products continue to be promoted effectively.&lt;/p&gt;



&lt;p&gt;The shift from manual merchandising configuration to ML-driven optimization reflects a broader trend in how app stores manage product discovery. For most developers, the reduced manual control is offset by the potential for broader, algorithmically optimized reach across Google Play surfaces. The key is to prepare before the deadline by auditing your existing configurations, moving country restrictions to the SKU level, and making deliberate decisions about featured product end dates.&lt;/p&gt;



&lt;p&gt;Whether you manage your billing with the Play Billing Library directly or use RevenueCat, the merchandising changes happen entirely on the Console side. Your billing code, purchase processing, and entitlement logic remain unchanged. Focus your effort on the Console configurations before March 16, and let Google’s ML handle the optimization from there.&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[How to personalize your paywalls with Custom Variables]]></title><description><![CDATA[Learn how to personalize your paywalls by passing values from your app using RevenueCat's Custom Variables.]]></description><link>https://www.revenuecat.com/blog/engineering/how-to-personalize-your-paywalls-with-custom-variables-in-react-native/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/how-to-personalize-your-paywalls-with-custom-variables-in-react-native/</guid><pubDate>Tue, 03 Mar 2026 19:55:08 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/custom_variables_blog.png" length="0" type="image/*"/><content:encoded>&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;How to personalize Paywalls with RevenueCat Custom Variables&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/ZnWOs4lSWOw?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;Paywalls that feel personal convert better. With Custom Variables, you can now pass values from your app directly into your paywall, letting you customize the experience for each customer.&lt;/p&gt;



&lt;p&gt;In this tutorial, I’ll walk you through setting up Custom Variables in a React Native app. We’ll take a simple tipping feature and personalize the paywall title with the customer’s name.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-prerequisites&quot;&gt;Prerequisites&lt;/h2&gt;



&lt;p&gt;Before getting started, make sure your app is running a compatible version of the RevenueCat SDK. Custom Variables require the following minimum package versions:&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;SDK&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Mimimum version&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/RevenueCat/purchases-ios&quot;&gt;purchases-ios&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/RevenueCat/purchases-ios/releases/tag/5.57.0&quot;&gt;5.57.0&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/RevenueCat/purchases-android&quot;&gt;purchases-android&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/RevenueCat/purchases-android/releases/tag/9.21.0&quot;&gt;9.21.0&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/RevenueCat/react-native-purchases&quot;&gt;react-native-purchases&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/RevenueCat/react-native-purchases/releases/tag/9.10.0&quot;&gt;9.10.0&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/RevenueCat/purchases-flutter&quot;&gt;purchases-flutter&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/RevenueCat/purchases-flutter/releases/tag/9.12.0&quot;&gt;9.12.0&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;If you’re working with a platform other than React Native, check out the &lt;a href=&quot;https://www.revenuecat.com/docs/tools/paywalls/displaying-paywalls#custom-variables&quot;&gt;Custom Variables documentation&lt;/a&gt; for platform-specific instructions.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;the-example-app&quot;&gt;The example app&lt;/h2&gt;



&lt;p&gt;Here’s what we’re working with. I’ve built a simple app with a tipping feature that lets customers tip the developer if they enjoy the app. When the user taps the “Tip the developer” button, it presents a paywall configured in RevenueCat.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;576&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/tip--1024x576.png&quot; alt=&quot;Screenshot: the example app showing the &amp;quot;Tip the developer&amp;quot; button&quot; class=&quot;wp-image-51496&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/tip--1024x576.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/tip--300x169.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/tip--768x432.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/tip--1536x864.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/tip--2048x1152.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/tip--50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/tip--71x40.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/tip--696x392.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/tip--560x315.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/tip--526x296.png 526w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/tip--840x472.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/tip--80x45.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/tip--48x27.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Right now, the paywall title is generic, showing only “Hey, You. You should buy me a pizza”. What I want to do is display the customer’s actual name in the paywall title to make it feel more personal.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;creating-a-custom-variable-in-the-paywall-editor&quot;&gt;Creating a Custom Variable in the Paywall Editor&lt;/h2&gt;



&lt;p&gt;To get started, open the Paywall Editor in your RevenueCat dashboard. In the left sidebar, select the &lt;strong&gt;Variables&lt;/strong&gt; section. You’ll see a new “Create variable” button at the top.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;461&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.24.00-1024x461.png&quot; alt=&quot;Screenshot: the Paywall Editor sidebar showing the Variables section with the &amp;quot;Create variable&amp;quot; button&quot; class=&quot;wp-image-51504&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.24.00-1024x461.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.24.00-300x135.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.24.00-768x345.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.24.00-1536x691.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.24.00-2048x921.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.24.00-50x22.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.24.00-89x40.png 89w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.24.00-696x313.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.24.00-560x252.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.24.00-840x378.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.24.00-80x36.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.24.00-48x22.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Click it to define a new custom variable. I’ll name mine &lt;code&gt;customerName&lt;/code&gt;, since that’s what we’ll be passing from the app.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;461&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.24.22-1024x461.png&quot; alt=&quot;Screenshot: creating the customerName variable with &amp;quot;You&amp;quot; as the default value&quot; class=&quot;wp-image-51502&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.24.22-1024x461.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.24.22-300x135.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.24.22-768x346.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.24.22-1536x691.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.24.22-2048x921.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.24.22-50x22.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.24.22-89x40.png 89w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.24.22-696x313.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.24.22-560x252.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.24.22-840x378.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.24.22-80x36.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.24.22-48x22.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;You’re required to provide a default value. This is important because it ensures the paywall still looks good even if the variable isn’t set for some reason. In this case, I’ll use “You” as the fallback, so the title reads naturally either way.&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;using-the-variable-in-your-paywall&quot;&gt;Using the variable in your paywall&lt;/h2&gt;



&lt;p&gt;Now that the variable exists, we can reference it in the paywall content. Switch back to the &lt;strong&gt;Layers&lt;/strong&gt; view, select the title text layer, and find the spot where you want to insert the variable. Replace the static word “You” with the new &lt;code&gt;customerName&lt;/code&gt; variable using the “Add variable” button.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;604&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.25.26-1024x604.png&quot; alt=&quot;Screenshot: the title text layer with the customerName variable inserted via the &amp;quot;Add variable&amp;quot; button&quot; class=&quot;wp-image-51500&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.25.26-1024x604.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.25.26-300x177.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.25.26-768x453.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.25.26-1536x906.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.25.26-2048x1208.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.25.26-50x29.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.25.26-68x40.png 68w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.25.26-696x410.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.25.26-560x330.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.25.26-502x296.png 502w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.25.26-800x472.png 800w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.25.26-80x47.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/Screenshot-2026-03-03-at-20.25.26-48x28.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Once you’re happy with how it looks, publish the changes.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;passing-the-variable-from-your-app&quot;&gt;Passing the variable from your app&lt;/h2&gt;



&lt;p&gt;With the paywall side ready, let’s update the app code. The &lt;code&gt;presentPaywall&lt;/code&gt; function now accepts a &lt;code&gt;customVariables&lt;/code&gt; key, which takes an array of objects. Each object needs a &lt;code&gt;key&lt;/code&gt; that matches the variable name you defined in the Paywall Editor, and a value wrapped in &lt;code&gt;CustomVariableValue.string&lt;/code&gt;.&lt;/p&gt;



&lt;p id=&quot;h-&quot;&gt;Here’s what the code looks like:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1Goxbr wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;import { CustomVariableValue } from \&amp;quot;react-native-purchases-ui\&amp;quot;;\n\n\/\/ When presenting the paywall:\nawait presentPaywall({\n  customVariables: {\n      customerName: CustomVariableValue.string(\&amp;quot;Perttu\&amp;quot;),\n    },\n});&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;key&lt;/code&gt; here is &lt;code&gt;&quot;customerName&quot;&lt;/code&gt;, which matches exactly what we defined in the editor. The value can be anything you pull from your app’s user data, authentication state, or wherever you store customer information.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;the-result&quot;&gt;The result&lt;/h2&gt;



&lt;p&gt;Save the changes and force a refresh so the app fetches the latest version of the paywall. Now when the customer taps “Tip the developer” and the paywall appears, you’ll see their name displayed right in the title.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;576&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/result-1024x576.png&quot; alt=&quot;Screenshot: the paywall showing the personalized title with the customer&apos;s name&quot; class=&quot;wp-image-51498&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/result-1024x576.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/result-300x169.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/result-768x432.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/result-1536x864.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/result-2048x1152.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/result-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/result-71x40.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/result-696x392.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/result-560x315.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/result-526x296.png 526w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/result-840x472.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/result-80x45.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/03/result-48x27.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;That’s all it takes. A few lines of code in your app, a quick setup in the Paywall Editor, and your paywalls feel like they were built for each individual customer.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;whats-next&quot;&gt;What’s next&lt;/h2&gt;



&lt;p&gt;Custom Variables open up a lot of possibilities beyond just names. Think about passing subscription status, usage stats, or any other value that might make your paywall more relevant and compelling.&lt;/p&gt;



&lt;p&gt;For more details on Custom Variables and other RevenueCat features, check out the &lt;a href=&quot;https://www.revenuecat.com/docs/tools/paywalls/displaying-paywalls#custom-variables&quot;&gt;full documentation&lt;/a&gt;.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Meet the AI agent that creates paywalls, writes code, and tracks revenue in your Android Studio]]></title><description><![CDATA[In this article, you'll explore the key features of the RevenueCat IntelliJ Plugin, including AI paywall generation, and analyze charts.]]></description><link>https://www.revenuecat.com/blog/engineering/android-studio-ai/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/android-studio-ai/</guid><pubDate>Fri, 27 Feb 2026 00:13:11 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Blog_24_RevenueCat-AI-Agent-in-Android-Studio.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Managing subscriptions, paywalls, and revenue metrics typically involves constant context switching between your IDE and the RevenueCat dashboard. You write code in Android Studio, switch to a browser tab to check MRR, open another tab to configure offerings, and switch again to design a paywall. Each context switch breaks your flow and fragments your attention. The &lt;a href=&quot;https://plugins.jetbrains.com/plugin/29265-revenuecat-dashboard/&quot;&gt;RevenueCat IntelliJ Plugin&lt;/a&gt; eliminates this friction by bringing your entire subscription business directly into your development environment.&lt;/p&gt;



&lt;p&gt;But this plugin is more than a dashboard mirror. It includes a full-featured AI agent that understands your RevenueCat project and can take action on your behalf. You can ask it to create offerings, generate paywalls with AI, analyze your revenue charts, debug integration issues, and even edit your source code, all through natural language prompts without leaving your IDE.&lt;/p&gt;



&lt;p&gt;In this article, you’ll explore the key features of the RevenueCat IntelliJ Plugin, including how OAuth sign in replaces manual API key configuration, how the dashboard panel surfaces real time metrics without browser context switching, how the AI agent generates paywalls and manages your entire project through conversation, and how AI powered code editing lets the agent modify your project files with full diff preview and undo support.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-getting-started-oauth-sign-in&quot;&gt;&lt;strong&gt;Getting started: OAuth sign-in&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The plugin uses OAuth 2.0 authorization with PKCE flow, replacing the older API key configuration. When you open the RevenueCat tool window for the first time, you’ll see a welcome screen with a “Sign in with RevenueCat” button.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;362&quot; height=&quot;138&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/1.png&quot; alt=&quot;&quot; class=&quot;wp-image-51330&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/1.png 362w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/1-300x114.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/1-50x19.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/1-105x40.png 105w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/1-80x30.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/1-48x18.png 48w&quot; sizes=&quot;auto, (max-width: 362px) 100vw, 362px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Clicking the sign-in button opens your browser for authorization. The plugin starts a local callback server, handles the token exchange automatically, and stores your credentials securely. Once authorized, the plugin fetches your projects and lets you select which one to work with.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;470&quot; height=&quot;680&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/2.png&quot; alt=&quot;&quot; class=&quot;wp-image-51332&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/2.png 470w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/2-207x300.png 207w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/2-35x50.png 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/2-28x40.png 28w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/2-321x464.png 321w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/2-387x560.png 387w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/2-205x296.png 205w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/2-326x472.png 326w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/2-55x80.png 55w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/2-33x48.png 33w&quot; sizes=&quot;auto, (max-width: 470px) 100vw, 470px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The OAuth flow requests scoped permissions for project configuration, charts and metrics, and customer information. Tokens refresh automatically when they expire, so you stay authenticated across sessions without manual intervention.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;282&quot; height=&quot;136&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/3.png&quot; alt=&quot;&quot; class=&quot;wp-image-51334&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/3.png 282w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/3-50x24.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/3-83x40.png 83w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/3-80x39.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/3-48x23.png 48w&quot; sizes=&quot;auto, (max-width: 282px) 100vw, 282px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;ai-agent-code-editing-agent-powered-file-modifications&quot;&gt;&lt;strong&gt;AI Agent code editing: Agent-powered file modifications&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Beyond querying data, the AI agent can read, search, and edit your project’s source files directly. This enables workflows like “Add the RevenueCat SDK initialization to my Application class” or “Update my paywall screen to use the new offering ID.”&lt;/p&gt;



&lt;figure class=&quot;wp-block-video&quot;&gt;&lt;video height=&quot;1220&quot; style=&quot;aspect-ratio: 1732 / 1220;&quot; width=&quot;1732&quot; controls=&quot;&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/3.mp4&quot;&gt;&lt;/video&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;staged-edit-system&quot;&gt;&lt;strong&gt;Staged edit system&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;When the agent proposes code changes, they appear as staged edits with inline diff preview. You can review each change before applying it:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Accept individual edits&lt;/strong&gt;: Apply specific changes while rejecting others&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Accept all&lt;/strong&gt;: Apply all proposed changes at once&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Reject&lt;/strong&gt;: Discard proposed changes without modifying your files&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;ai-paywall-generation&quot;&gt;&lt;strong&gt;AI paywall generation&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The most powerful feature of the AI agent is end-to-end paywall generation. You describe what you want, and the agent handles everything: creating the offering, setting up packages, attaching products, and generating a fully designed paywall with AI, complete with copy, images, styling, and template selection.&lt;/p&gt;



&lt;figure class=&quot;wp-block-video&quot;&gt;&lt;video height=&quot;1222&quot; style=&quot;aspect-ratio: 1732 / 1222;&quot; width=&quot;1732&quot; controls=&quot;&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/4.mp4&quot;&gt;&lt;/video&gt;&lt;/figure&gt;



&lt;p&gt;he agent monitors the generation job in the background. When the paywall is ready, a notification appears with a direct link to the paywall builder where you can review and publish the design. The monitoring works reliably even when OAuth tokens expire, using your API key as an independent fallback.&lt;/p&gt;



&lt;p&gt;You can generate multiple paywalls in sequence. The agent tracks each job independently, so you can ask for a “premium” paywall, then a “freemium” paywall, and the monitoring handles both without conflicts.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;managing-your-project-through-conversation&quot;&gt;&lt;strong&gt;Managing your project through conversation&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The agent supports full create, read, update, and delete operations across your RevenueCat resources. Here are some examples of what you can ask:&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Creating resources:&lt;/strong&gt;&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;code&gt;&quot;Create a new offering called Premium with a monthly package at $9.99 and an annual package at $79.99&quot;&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;The agent creates the offering, creates both packages, and attaches the appropriate products. If any of these resources already exist, the agent detects the duplicates and reuses them instead of failing.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;code&gt;&quot;Set up an entitlement called pro_access and attach it to all my subscription products&quot;&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;The agent creates the entitlement, lists your existing products, and attaches each one.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Querying your project:&lt;/strong&gt;&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;code&gt;&quot;Show me all my offerings and which ones have paywalls&quot;&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;The agent fetches your offerings and paywall data, presenting a clear summary of what’s configured and what’s missing.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;code&gt;&quot;What products do I have configured? Which ones aren&apos;t attached to any package?&quot;&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;The agent cross references your products, packages, and offerings to find orphaned resources.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Paywall management:&lt;/strong&gt;&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;code&gt;&quot;Generate an AI paywall for my premium offering. The app is a fitness tracker called FitCat targeting health conscious millennials.&quot;&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;The agent uses your app context to generate a paywall with relevant copy, styling, and design that matches your brand.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;code&gt;&quot;Duplicate my current paywall and name it Holiday Promo&quot;&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;The agent duplicates the paywall through the API and provides the builder link for customization.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;analyzing-your-revenue-with-charts-api&quot;&gt;&lt;strong&gt;Analyzing your revenue with Charts API&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The agent has access to 21 chart types including revenue, MRR, ARR, churn rate, trial conversions, active subscriptions, and retention cohorts. You can ask analytical questions and get data driven answers:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;code&gt;&quot;What&apos;s my MRR trend over the last 6 months?&quot;&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;code&gt;&quot;Show me my trial to paid conversion rate broken down by weekly&quot;&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;code&gt;&quot;Compare my revenue this month vs last month&quot;&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;code&gt;&quot;What&apos;s my churn rate for annual subscribers?&quot;&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;The agent queries the Charts API with the appropriate parameters, including date ranges, resolutions, and segment filters, and presents the results in a readable format.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;debugging-and-integration-help&quot;&gt;&lt;strong&gt;Debugging and integration help&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The agent isn’t limited to CRUD operations. It understands RevenueCat’s SDK and can help you debug integration issues:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;code&gt;&quot;I&apos;m getting a &apos;Configuration not found&apos; error when presenting my paywall. What&apos;s wrong?&quot;&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;The agent checks your project configuration, verifies that your offerings have packages with products attached, and identifies the root cause.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;code&gt;&quot;Walk me through setting up RevenueCat in my Kotlin Multiplatform project&quot;&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;The agent has access to &lt;a href=&quot;https://revenuecat.github.io/&quot;&gt;Codelabs content&lt;/a&gt; and can provide step-by-step guidance tailored to your platform.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;code&gt;&quot;What&apos;s the difference between offering lookup keys and offering IDs? Which one should I use in my code?&quot;&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;The agent explains concepts with context from your actual project configuration, not just generic documentation.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;model-selection&quot;&gt;&lt;strong&gt;Model selection&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The AI agent supports multiple models that you can switch between using the gear icon in the input bar. Available models include GPT-4.1, GPT-4.1 Mini, Claude Sonnet 4, and Claude Haiku 4.5, letting you balance capability and response speed based on your needs.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;189&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/5-1024x189.png&quot; alt=&quot;&quot; class=&quot;wp-image-51340&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/5-1024x189.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/5-300x55.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/5-768x142.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/5-50x9.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/5-125x23.png 125w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/5-696x129.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/5-560x103.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/5-840x155.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/5-80x15.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/5-48x9.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/5.png 1316w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;dashboard-panel-metrics-without-context-switching&quot;&gt;&lt;strong&gt;Dashboard panel: Metrics without context switching&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The dashboard panel gives you a live view of your RevenueCat project without opening a browser. It organizes your subscription data into collapsible sections that load when you open the tool window.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;702&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/6-1024x702.png&quot; alt=&quot;&quot; class=&quot;wp-image-51342&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/6-1024x702.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/6-300x206.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/6-768x527.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/6-50x34.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/6-58x40.png 58w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/6-677x464.png 677w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/6-696x477.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/6-560x384.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/6-432x296.png 432w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/6-688x472.png 688w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/6-80x55.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/6-48x33.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/6.png 1050w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;revenue-overview&quot;&gt;&lt;strong&gt;Revenue overview&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The top section shows your key metrics at a glance: active subscribers, active trials, MRR, and revenue. These numbers pull directly from the RevenueCat API, so you’re always looking at current data.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;milestones&quot;&gt;&lt;strong&gt;Milestones&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Below the metrics, a milestones section tracks your subscription business achievements. These are the same milestones you’d see on the RevenueCat dashboard: first subscriber, revenue thresholds, and trial milestones, all surfaced directly in your IDE.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;configured-offerings&quot;&gt;&lt;strong&gt;Configured offerings&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The offerings section lists all your offerings with their packages and attached products. You can expand each offering to see its package structure, which products are attached, and whether it has a paywall configured. Offerings with paywalls show a direct link to the paywall builder.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;paywalls-section&quot;&gt;&lt;strong&gt;Paywalls section&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;A dedicated paywalls section shows all your paywalls with colored status badges: Published (green), Draft (yellow), and Has Unpublished Changes (orange). Each paywall has context-aware action buttons based on its status: Edit, Publish, Unpublish, Discard, Duplicate, and Delete. The Edit button opens the paywall builder in your browser. Lifecycle actions call the API directly and auto-refresh the panel.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;541&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/7-1024x541.png&quot; alt=&quot;&quot; class=&quot;wp-image-51344&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/7-1024x541.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/7-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/7-768x406.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/7-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/7-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/7-696x368.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/7-560x296.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/7-840x444.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/7-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/7-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/7.png 1045w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;conclusion&quot;&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The RevenueCat IntelliJ Plugin transforms your IDE into a complete subscription management environment. OAuth sign-in eliminates manual API key configuration. The dashboard panel surfaces metrics, milestones, offerings, and paywalls without browser context switching. The AI agent goes far beyond a simple chatbot. It creates offerings, generates paywalls with AI, analyzes your revenue data through the Charts API, debugs integration issues, and edits your source code with safe, reviewable changes.&lt;/p&gt;



&lt;p&gt;The AI paywall generation alone saves significant time. Instead of navigating through the dashboard to create an offering, set up packages, attach products, and design a paywall manually, you describe what you want in one sentence, and the agent handles every step. The result is a fully designed paywall ready for review in the builder.&lt;/p&gt;



&lt;p&gt;Whether you’re checking your MRR between code reviews, generating a paywall for a new offering, analyzing churn trends, or asking the agent to scaffold your SDK integration, the plugin keeps you in your development flow. The goal is simple: spend less time switching tabs and more time building your subscription business. You can install the RevenueCat IntelliJ Plugin from the&amp;nbsp;&lt;a href=&quot;https://plugins.jetbrains.com/plugin/29265-revenuecat-dashboard/&quot;&gt;JetBrains Marketplace: RevenueCat Dashboard&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Announcing the Shipyard: Creator Contest 2026 winners]]></title><description><![CDATA[Explore the winning apps of Shipyard: Creator Contest]]></description><link>https://www.revenuecat.com/blog/company/shipyard-2026-winners/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/company/shipyard-2026-winners/</guid><pubDate>Thu, 26 Feb 2026 15:01:09 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Winners-v1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;What happens when real influencers hand you a brief and say, “&lt;em&gt;Build the app my audience actually needs&lt;/em&gt;“? &lt;strong&gt;Shipyard: Creator Contest&lt;/strong&gt; set out to answer that question. In just four weeks, more than &lt;strong&gt;900 builders&lt;/strong&gt; competed to design, launch, and monetize an MVP for seven creators ready for long-term app partnerships. Now, we’re proud to introduce the seven winners.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-eitan-bernath&quot;&gt;Eitan Bernath&lt;/h2&gt;



&lt;p&gt;In Eitan Bernath’s category, the task was to help people actually cook what they’ve been meaning to make. Think of tools that turn inspiration into action: an app that can generate a grocery list from a recipe video/link, organize what you want to cook, and make it simple to get started.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-winning-app-preplo-turning-cooking-videos-into-actionable-recipes&quot;&gt;Winning app: Preplo – turning cooking videos into actionable recipes&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;576&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-6D97-1024x576.png&quot; alt=&quot;&quot; class=&quot;wp-image-51379&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-6D97-1024x576.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-6D97-300x169.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-6D97-768x432.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-6D97-1536x864.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-6D97-2048x1152.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-6D97-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-6D97-71x40.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-6D97-696x392.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-6D97-560x315.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-6D97-526x296.png 526w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-6D97-840x472.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-6D97-80x45.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-6D97-48x27.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Preplo turns cooking inspiration into something you can actually make. Drop in a YouTube, TikTok, or Instagram link and it instantly generates a structured recipe with quantities, step-by-step instructions (with timestamps), estimated costs, and nutrition info. It makes the jump from “I saved this” to “it’s on the table” much easier.&lt;/p&gt;



&lt;p&gt;You can also tweak recipes on the fly — make it spicier, vegan, or low-carb, and everything updates accordingly. Built with Expo React Native and a Next.js backend, Preplo also caches processed videos so the same clip is never analyzed twice.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://devpost.com/software/preplo&quot;&gt;Devpost link&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-gabby-beckford-nbsp&quot;&gt;Gabby Beckford&amp;nbsp;&lt;/h2&gt;



&lt;p&gt;In Gabby Beckford’s brief the goal was to build an upbeat, motivating app that turns goals into daily micro-actions, with challenges, streaks/wins, tracking, and gamified moments that make progress feel fun. Designed for ambitious women who want to embark on dream trips and life upgrades, but often get held back by the mundane day-to-day, or stuck between inspiration and action.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-winning-app-bloom-turning-big-dreams-into-daily-wins&quot;&gt;Winning app: Bloom – turning big dreams into daily wins&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;576&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-D92D-1024x576.png&quot; alt=&quot;&quot; class=&quot;wp-image-51381&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-D92D-1024x576.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-D92D-300x169.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-D92D-768x432.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-D92D-1536x864.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-D92D-2048x1152.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-D92D-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-D92D-71x40.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-D92D-696x392.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-D92D-560x315.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-D92D-526x296.png 526w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-D92D-840x472.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-D92D-80x45.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-D92D-48x27.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Bloom is a gamified personal growth app for women who need help taking the steps to turn dreams into daily life. Instead of another to-do list, Bloom connects goals, money confidence, mindset, and travel into one motivating system.&lt;/p&gt;



&lt;p&gt;At the center is the Digital Garden: daily habits fuel visible growth, so progress feels real. Users can set ‘Dreams’, play bite-sized financial mini-games, journal with AI guidance, and track travels on an interactive map. Built with Flutter and powered by Supabase and Mapbox, Bloom focuses on making self-development feel encouraging rather than overwhelming.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://devpost.com/software/bloom-rhmx46&quot;&gt;Devpost link&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-quin-gable-nbsp&quot;&gt;Quin Gable&amp;nbsp;&lt;/h2&gt;



&lt;p&gt;Dating and making friends on the road is hard when you’re always moving. Digital nomad Quin Gable wanted a van-life app with nomadic dating, activity-based friend finding, and even a paid ‘builder help’ section for van projects. To keep the community protected, the app needed to be invite-only or verified access to ensure the app remained safe and connection was intentional.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-winning-app-wanderbase-dating-and-community-for-life-on-the-road&quot;&gt;Winning app: WanderBase – dating and community for life on the road&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;576&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-DC98-1024x576.png&quot; alt=&quot;&quot; class=&quot;wp-image-51383&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-DC98-1024x576.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-DC98-300x169.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-DC98-768x432.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-DC98-1536x864.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-DC98-2048x1152.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-DC98-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-DC98-71x40.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-DC98-696x392.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-DC98-560x315.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-DC98-526x296.png 526w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-DC98-840x472.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-DC98-80x45.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-DC98-48x27.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;WanderBase is a dating and community app built specifically for van-lifers and nomads. Instead of endless swiping, users explore hand-illustrated, customizable van avatars that reflect your lifestyle and travel vibe; a playful twist that feels true to life on the road.&lt;/p&gt;



&lt;p&gt;It’s invite-only, with route-based matching, mutual chat unlocks, and a help-finding forum for van projects. Built with React Native and Firebase, with server-side matching and strict security rules, WanderBase guarantees trust, and prioritizes safety and fun in equal measure.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://devpost.com/software/wanderbase-the-van-life-community&quot;&gt;Devpost link&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-sam-beckman&quot;&gt;Sam Beckman&lt;/h2&gt;



&lt;p&gt;Sam lives by reminders, but switching between Android and iOS means rebuilding his entire system from scratch. His brief was to build a beautiful, fully-functional reminders app on both iOS + Android. It needed custom snoozes from notifications, powerful recurring rules, and true sync, so dismissing once clears everywhere.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-winning-app-remy-reminders-cross-platform-reminders-finally-in-sync&quot;&gt;Winning app: Remy Reminders – cross-platform reminders, finally in sync&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;576&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-2913-1024x576.png&quot; alt=&quot;&quot; class=&quot;wp-image-51385&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-2913-1024x576.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-2913-300x169.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-2913-768x432.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-2913-1536x864.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-2913-2048x1152.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-2913-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-2913-71x40.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-2913-696x392.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-2913-560x315.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-2913-526x296.png 526w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-2913-840x472.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-2913-80x45.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-2913-48x27.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Remy solves a real frustration: switching between iOS and Android without rebuilding your reminder system from scratch. It delivers a polished reminders app regardless of your platform choice, offers simple but effective rule-making, built-in notification pauses, and more. &lt;/p&gt;



&lt;p&gt;Behind the scenes is a custom offline-first sync engine and a notification system that talks directly to APNs and FCM to keep everything aligned. Built with React Native (Expo), and Convex, Remy focuses on making reminders reliable, no matter what device you’re using.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://devpost.com/software/remy-reminders&quot;&gt;Devpost link&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-simon-from-better-creating&quot;&gt;​​Simon from Better Creating&lt;/h2&gt;



&lt;p&gt;Simon’s audience loves productivity, great design, and building systems for self improvement. Coaching is a key part of this, so Simon wanted to make the growth and self-assurance that comes from coaching accessible. This meant creating&amp;nbsp;a clean, minimal mobile app where users can browse, create, and share AI coaches, add personal context/values, and start chatting immediately.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-winning-app-editor-nbsp-decide-with-clarity&quot;&gt;Winning app: Editor&amp;nbsp;– decide with clarity&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;576&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/editor-1024x576.png&quot; alt=&quot;&quot; class=&quot;wp-image-51398&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/editor-1024x576.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/editor-300x169.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/editor-768x432.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/editor-1536x864.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/editor-2048x1152.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/editor-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/editor-71x40.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/editor-696x392.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/editor-560x315.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/editor-526x296.png 526w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/editor-840x472.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/editor-80x45.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/editor-48x27.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Editor flips the typical coaching or AI chat experience on its head. Instead of encouraging endless conversation, it’s designed to help builders and creators reach decisions quickly and deliberately. Going beyond a coaching app, users choose structured thinking modes like prioritizing, reviewing ideas, or weighing trade-offs. &lt;/p&gt;



&lt;p&gt;Each session is built to get you to a decision quickly, then end. Outcomes can be turned into decision briefs or roadmaps and exported to Notion. Built as a native SwiftUI app, Editor stays intentionally minimal and focused.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://devpost.com/software/editor-decide-with-clarity&quot;&gt;Devpost link&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-rebecca-louise&quot;&gt;Rebecca Louise&lt;/h2&gt;



&lt;p&gt;Rebecca hears it constantly: mums are short on time, want financial independence, and need practical help. Her brief was to build an app that offers everyday money-saving guidance (shopping swaps, batch cooking, cost comparisons, home reno savings) plus an approachable path into investing basics, so users can grow what they have without overwhelm.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-winning-app-sunny-money-financial-confidence-for-busy-mums&quot;&gt;Winning app: Sunny Money – Financial confidence for busy mums&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;576&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-15DD-1024x576.png&quot; alt=&quot;&quot; class=&quot;wp-image-51387&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-15DD-1024x576.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-15DD-300x169.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-15DD-768x432.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-15DD-1536x864.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-15DD-2048x1152.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-15DD-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-15DD-71x40.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-15DD-696x392.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-15DD-560x315.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-15DD-526x296.png 526w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-15DD-840x472.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-15DD-80x45.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Rotato-Image-15DD-48x27.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Sunny Money helps busy mums build financial confidence in just a few minutes a day. It combines everyday money-saving guidance with simple introductions to saving and investing. &lt;/p&gt;



&lt;p&gt;Bite-sized lessons, practical calculators, daily challenges, and an AI assistant make financial progress feel manageable. Built with React Native and Expo, Sunny Money respects mums’ time while still delivering real, useful tools.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://devpost.com/software/sunnier&quot;&gt;Devpost link&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-josh-from-visualfaktory&quot;&gt;Josh from VisualFaktory&lt;/h2&gt;



&lt;p&gt;Investors juggle stocks, gold, funds, fixed income, real estate, and more across multiple platforms. It’s messy to track and hard to understand at a glance. Josh wanted a single app where users can log everything, get real-time price updates where possible, set amortization/reminder alerts for non-listed products, and unlock premium risk + diversification analysis (like country/sector exposure).&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-winning-app-folio-see-your-entire-portfolio-at-a-glance&quot;&gt;Winning app: Folio – see your entire portfolio at a glance&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;576&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/folio-1024x576.png&quot; alt=&quot;&quot; class=&quot;wp-image-51392&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/folio-1024x576.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/folio-300x169.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/folio-768x432.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/folio-1536x864.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/folio-2048x1152.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/folio-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/folio-71x40.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/folio-696x392.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/folio-560x315.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/folio-526x296.png 526w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/folio-840x472.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/folio-80x45.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/folio-48x27.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Folio brings scattered investments into one clean iOS dashboard. Stocks, ETFs, crypto, property, savings — everything in one place so you can see your full net worth and understand your exposure on one screen.&lt;/p&gt;



&lt;p&gt;It includes live pricing, performance breakdowns, widgets, alerts, and an AI assistant that understands your actual holdings and can help rebalance or adjust positions. Built with React Native and Supabase, Folio keeps portfolio tracking straightforward and actionable.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://devpost.com/software/folio-n7mugb&quot;&gt;Devpost link&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-that-s-a-wrap&quot;&gt;That’s a wrap&lt;/h2&gt;



&lt;p&gt;Across seven very different briefs, the winning apps had something in common: focus.&lt;/p&gt;



&lt;p&gt;They didn’t try to do everything. They picked a specific audience, a clear problem, and built around it. The van-life app prioritized trust and safety. The reminders app obsessed over cross-platform sync. The finance apps respected their users’ time. The AI coach constrained itself on simplicity. Each team made deliberate trade-offs instead of chasing features.&lt;/p&gt;



&lt;p&gt;While this is the end, we hope all of you continue building your apps, and most importantly, work on getting them out for people to download.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;How did you find Shipyard? Did you have fun? Were there things you wish we had done differently?&amp;nbsp;&lt;/p&gt;



&lt;p&gt;We’d love to hear your thoughts. Let us know on &lt;a href=&quot;https://x.com/RevenueCat&quot;&gt;Twitter&lt;/a&gt; or &lt;a href=&quot;https://www.linkedin.com/company/revenuecat/&quot;&gt;LinkedIn&lt;/a&gt;, and keep an eye out for a survey we’ll be sending to all participants to gather your feedback.&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Cross-platform subscription state: sharing entitlements between Android and iOS]]></title><description><![CDATA[In this article, you'll explore why cross platform subscription state is so difficult to implement, examine the fundamental incompatibilities between Google Play Billing and StoreKit.]]></description><link>https://www.revenuecat.com/blog/engineering/cross-platform-subscription/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/cross-platform-subscription/</guid><pubDate>Tue, 24 Feb 2026 02:49:36 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Blog_23_Cross-platform-subscription-state.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Subscription apps rarely live on a single platform. A user might subscribe on their iPhone during their morning commute, then open your Android tablet app at home expecting full access. This expectation is intuitive from the user’s perspective, they paid for a subscription, so it should work everywhere. But from a developer’s perspective, making this work is one of the hardest problems in subscription infrastructure. Google Play Billing and Apple’s StoreKit are entirely separate systems with different receipt formats, different verification mechanisms, different notification systems, and fundamentally different assumptions about how purchases are represented. There is no built in interoperability between them.&lt;/p&gt;



&lt;p&gt;In this article, you’ll explore why cross platform subscription state is so difficult to implement, examine the fundamental incompatibilities between Google Play Billing and StoreKit, walk through what it takes to build cross platform entitlement sync from scratch, and see how&amp;nbsp;&lt;a href=&quot;https://www.revenuecat.com/docs/customers/identifying-customers&quot;&gt;RevenueCat’s identity system&lt;/a&gt;&amp;nbsp;provides a natural solution that dramatically reduces the engineering effort required, especially for small teams and indie developers.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-fundamental-problem-one-user-two-ecosystems&quot;&gt;&lt;strong&gt;The fundamental problem: One user, two ecosystems&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Consider a fitness app with a “Premium” subscription. A user subscribes through the App Store on their iPhone. A week later, they buy an Android tablet and download your app. They log in with the same account and expect to see their premium features. What actually happens?&lt;/p&gt;



&lt;p&gt;Without cross platform infrastructure, the Android app has no idea this user has an active subscription. Google Play Billing only knows about purchases made through Google Play. The App Store receipt sitting on Apple’s servers is invisible to the Android app. The user sees a paywall asking them to subscribe again, even though they are already paying.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-GWNAt wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/\/ On the Android side, this returns nothing\nval params = QueryPurchasesParams.newBuilder()\n    .setProductType(BillingClient.ProductType.SUBS)\n    .build()\n\nbillingClient.queryPurchasesAsync(params) { billingResult, purchases -&gt;\n    \/\/ purchases is empty because the user subscribed through Apple\n    \/\/ The Android app has no way to know about the iOS subscription\n    if (purchases.isEmpty()) {\n        showPaywall() \/\/ User sees this despite having an active subscription\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This is not a bug. It is the expected behavior. Each billing system operates in isolation, and bridging them requires significant infrastructure that neither platform provides.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;two-billing-systems-zero-interoperability&quot;&gt;&lt;strong&gt;Two billing systems, zero interoperability&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;To understand why cross platform sync is so difficult, you need to understand how differently Google and Apple represent purchases. These are not minor API differences. They are fundamentally different architectures.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;receipt-formats-and-verification&quot;&gt;&lt;strong&gt;Receipt formats and verification&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Apple and Google use entirely different mechanisms to prove that a purchase happened.&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Aspect&lt;/th&gt;&lt;th&gt;Google Play Billing&lt;/th&gt;&lt;th&gt;Apple StoreKit&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Purchase proof&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Purchase token (opaque string)&lt;/td&gt;&lt;td&gt;Signed receipt (JWS in StoreKit 2)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Verification endpoint&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;purchases.subscriptionsv2.get&lt;/code&gt;&amp;nbsp;REST API&lt;/td&gt;&lt;td&gt;App Store Server API (&lt;code&gt;/inApps/v1/subscriptions&lt;/code&gt;)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Authentication&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Google service account with JSON key&lt;/td&gt;&lt;td&gt;JWT signed with App Store Connect private key&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Response format&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;SubscriptionPurchaseV2&lt;/code&gt;&amp;nbsp;JSON object&lt;/td&gt;&lt;td&gt;&lt;code&gt;JWSTransactionDecodedPayload&lt;/code&gt;&amp;nbsp;(signed JSON)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Subscription ID format&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;productId:basePlanId&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Simple&amp;nbsp;&lt;code&gt;productId&lt;/code&gt;&amp;nbsp;string&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Renewal tracking&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;expiryTime&lt;/code&gt;&amp;nbsp;field on subscription resource&lt;/td&gt;&lt;td&gt;&lt;code&gt;expiresDate&lt;/code&gt;&amp;nbsp;in transaction info&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;Google Play uses a&amp;nbsp;&lt;strong&gt;purchase token&lt;/strong&gt;&amp;nbsp;model. When a user subscribes, your app receives a purchase token. You send this token to the Google Play Developer API, which returns the current subscription state. The token is an opaque string with no inherent meaning.&lt;/p&gt;



&lt;p&gt;Apple uses a&amp;nbsp;&lt;strong&gt;signed transaction&lt;/strong&gt;&amp;nbsp;model. In StoreKit 2, purchase information is delivered as JSON Web Signatures (JWS) that your server can verify using Apple’s public key. Each transaction is a self contained, cryptographically signed record.&lt;/p&gt;



&lt;p&gt;These are not just different APIs wrapping the same concept. They represent different philosophies about where trust lives. Google says “ask our server, we’ll tell you the state.” Apple says “here’s a cryptographically signed proof, verify it yourself.”&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-real-time-notifications&quot;&gt;&lt;strong&gt;Real-time notifications&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Both platforms offer server-to-server notifications for subscription events, but the notification systems differ substantially.&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Aspect&lt;/th&gt;&lt;th&gt;Google Play RTDN&lt;/th&gt;&lt;th&gt;Apple Server Notifications V2&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Delivery mechanism&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Google Cloud Pub/Sub&lt;/td&gt;&lt;td&gt;HTTPS POST to your endpoint&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Notification format&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;DeveloperNotification&lt;/code&gt;&amp;nbsp;with type enum&lt;/td&gt;&lt;td&gt;&lt;code&gt;signedPayload&lt;/code&gt;&amp;nbsp;(JWS) with&amp;nbsp;&lt;code&gt;notificationType&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Event types&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;SUBSCRIPTION_RENEWED&lt;/code&gt;,&amp;nbsp;&lt;code&gt;SUBSCRIPTION_CANCELED&lt;/code&gt;, etc.&lt;/td&gt;&lt;td&gt;&lt;code&gt;DID_RENEW&lt;/code&gt;,&amp;nbsp;&lt;code&gt;DID_CHANGE_RENEWAL_STATUS&lt;/code&gt;, etc.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;User identification&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;purchaseToken&lt;/code&gt;&amp;nbsp;in notification&lt;/td&gt;&lt;td&gt;&lt;code&gt;originalTransactionId&lt;/code&gt;&amp;nbsp;in signed payload&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Setup&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Configure Pub/Sub topic in Play Console&lt;/td&gt;&lt;td&gt;Register URL in App Store Connect&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;Google delivers notifications through Cloud Pub/Sub, requiring you to set up a Pub/Sub subscription and a processing service. Apple sends HTTPS POST requests directly to a URL you configure. The event names differ, the payload structures differ, and the information included in each notification type differs.&lt;/p&gt;



&lt;p&gt;This means your backend needs two completely separate notification processing pipelines with different authentication, different parsing logic, and different state machine interpretations.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;product-configuration&quot;&gt;&lt;strong&gt;Product configuration&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Even the way you define subscription products differs between platforms.&lt;/p&gt;



&lt;p&gt;Google Play introduced&amp;nbsp;&lt;strong&gt;base plans and offers&lt;/strong&gt;&amp;nbsp;in 2022, creating a hierarchical product model: a subscription contains one or more base plans, each of which can have multiple offers with different pricing phases. A single subscription product ID can have monthly and annual base plans, introductory offers, and promotional pricing, all configured through the Play Console.&lt;/p&gt;



&lt;p&gt;Apple’s product model is flatter. Each product ID in App Store Connect represents a single subscription with a single duration. To offer both monthly and annual options, you create two separate product IDs and group them in a&amp;nbsp;&lt;strong&gt;subscription group&lt;/strong&gt;. Introductory offers and promotional offers are configured per product, not as nested objects.&lt;/p&gt;



&lt;p&gt;This structural difference means there is no one to one mapping between a Google Play subscription product and an Apple subscription product. Your backend must maintain a mapping layer that translates platform specific product identifiers into a unified entitlement concept.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;building-cross-platform-sync-yourself&quot;&gt;&lt;strong&gt;Building cross platform sync yourself&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;If you decide to build cross platform subscription sync without a third party service, here is what the architecture looks like. Understanding this effort is important even if you ultimately choose a managed solution, because it reveals why the problem is genuinely hard.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;step-1-unified-user-identity&quot;&gt;&lt;strong&gt;Step 1: Unified user identity&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The first requirement is a user identity system that works across platforms. Each platform has its own notion of a user, but neither knows about the other. You need a server side user account that both platforms can associate purchases with.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1Cqcvg wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/\/ Android client: associate purchase with your user account\nfun postPurchaseToBackend(purchase: Purchase, userId: String) {\n    val request = PurchaseVerificationRequest(\n        platform = \&amp;quot;android\&amp;quot;,\n        purchaseToken = purchase.purchaseToken,\n        productId = purchase.products.first(),\n        userId = userId,\n    )\n\n    backendApi.verifyAndRecordPurchase(request)\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;For iOS, there will not be much difference from the Android side:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-LnNvY wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;swift&quot; content=&quot;&amp;quot;\/\/ iOS client: associate purchase with your user account\nfunc postPurchaseToBackend(transaction: Transaction, userId: String) async {\n    let request = PurchaseVerificationRequest(\n        platform: \&amp;quot;ios\&amp;quot;,\n        transactionId: String(transaction.originalID),\n        productId: transaction.productID,\n        userId: userId\n    )\n\n    await backendAPI.verifyAndRecordPurchase(request)\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Both clients send purchase data to your backend, tagged with the same&amp;nbsp;&lt;code&gt;userId&lt;/code&gt;. Your backend must verify each purchase against the correct platform’s API and record the entitlement against the unified user account.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;step-2-dual-receipt-verification&quot;&gt;&lt;strong&gt;Step 2: Dual receipt verification&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Your backend needs to verify purchases from both platforms, which means integrating with two completely different verification APIs:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-a8KLb wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/\/ Backend: platform-specific verification\nclass PurchaseVerifier(\n    private val playDeveloperApi: AndroidPublisher,\n    private val appStoreServerApi: AppStoreServerAPIClient,\n) {\n    suspend fun verify(request: PurchaseVerificationRequest): VerificationResult {\n        return when (request.platform) {\n            \&amp;quot;android\&amp;quot; -&gt; verifyGooglePurchase(request)\n            \&amp;quot;ios\&amp;quot; -&gt; verifyApplePurchase(request)\n            else -&gt; VerificationResult.InvalidPlatform\n        }\n    }\n\n    private suspend fun verifyGooglePurchase(\n        request: PurchaseVerificationRequest,\n    ): VerificationResult {\n        val subscription = playDeveloperApi\n            .purchases()\n            .subscriptionsv2()\n            .get(packageName, request.purchaseToken)\n            .execute()\n\n        return if (subscription.subscriptionState == \&amp;quot;SUBSCRIPTION_STATE_ACTIVE\&amp;quot;) {\n            VerificationResult.Valid(\n                expiryTime = subscription.lineItems[0].expiryTime,\n                productId = subscription.lineItems[0].productId,\n                platform = \&amp;quot;android\&amp;quot;,\n            )\n        } else {\n            VerificationResult.Expired\n        }\n    }\n\n    private suspend fun verifyApplePurchase(\n        request: PurchaseVerificationRequest,\n    ): VerificationResult {\n        \/\/ Uses Apple&apos;s App Store Server API\n        val statusResponse = appStoreServerApi\n            .getAllSubscriptionStatuses(request.transactionId)\n\n        val activeSubscription = statusResponse.data\n            .flatMap { it.lastTransactions }\n            .find { it.status == Status.ACTIVE }\n\n        return if (activeSubscription != null) {\n            val transactionInfo = activeSubscription.signedTransactionInfo\n            VerificationResult.Valid(\n                expiryTime = transactionInfo.expiresDate,\n                productId = transactionInfo.productId,\n                platform = \&amp;quot;ios\&amp;quot;,\n            )\n        } else {\n            VerificationResult.Expired\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Each verification path has its own authentication setup, error handling, and response parsing. Google requires a service account credential. Apple requires a JWT signed with a private key from App Store Connect. The response formats share no common structure.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;step-3-unified-entitlement-storage&quot;&gt;&lt;strong&gt;Step 3: Unified entitlement storage&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Your backend needs a data model that maps platform-specific products to platform-agnostic entitlements:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZIbcFk wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/\/ Backend entitlement model\ndata class UserEntitlement(\n    val userId: String,\n    val entitlementId: String,         \/\/ e.g., \&amp;quot;premium\&amp;quot;\n    val isActive: Boolean,\n    val sourcePlatform: String,        \/\/ \&amp;quot;android\&amp;quot; or \&amp;quot;ios\&amp;quot;\n    val platformProductId: String,     \/\/ Platform-specific product ID\n    val platformPurchaseToken: String, \/\/ Platform-specific purchase proof\n    val expiresAt: Instant?,\n    val lastVerifiedAt: Instant,\n)\n\n\/\/ Product mapping configuration\nval productToEntitlementMap = mapOf(\n    \/\/ Google Play products\n    \&amp;quot;premium_monthly:monthly-base\&amp;quot; to \&amp;quot;premium\&amp;quot;,\n    \&amp;quot;premium_annual:annual-base\&amp;quot; to \&amp;quot;premium\&amp;quot;,\n    \/\/ App Store products\n    \&amp;quot;com.yourapp.premium.monthly\&amp;quot; to \&amp;quot;premium\&amp;quot;,\n    \&amp;quot;com.yourapp.premium.annual\&amp;quot; to \&amp;quot;premium\&amp;quot;,\n)&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;When either client queries for entitlements, your backend checks whether the user has any active entitlement, regardless of which platform it originated from:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-vtcOk wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/\/ Backend endpoint\nfun getEntitlements(userId: String): EntitlementResponse {\n    val entitlements = entitlementRepository.findActiveByUserId(userId)\n\n    return EntitlementResponse(\n        entitlements = entitlements.map { entitlement -&gt;\n            EntitlementInfo(\n                id = entitlement.entitlementId,\n                isActive = entitlement.isActive &amp;amp;&amp;amp;\n                    (entitlement.expiresAt?.isAfter(Instant.now()) ?: true),\n                expiresAt = entitlement.expiresAt,\n                sourcePlatform = entitlement.sourcePlatform,\n            )\n        }\n    )\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;step-4-dual-notification-processing&quot;&gt;&lt;strong&gt;Step 4: Dual notification processing&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;To keep entitlements in sync in real time, your backend must process notifications from both platforms simultaneously:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-sk9k6 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/\/ Google Play RTDN handler\nfun handleGoogleNotification(message: PubSubMessage) {\n    val notification = parseDeveloperNotification(message)\n    val purchaseToken = notification.subscriptionNotification.purchaseToken\n\n    when (notification.subscriptionNotification.notificationType) {\n        NotificationType.SUBSCRIPTION_RENEWED -&gt; refreshGoogleEntitlement(purchaseToken)\n        NotificationType.SUBSCRIPTION_CANCELED -&gt; markGoogleEntitlementCanceled(purchaseToken)\n        NotificationType.SUBSCRIPTION_EXPIRED -&gt; expireGoogleEntitlement(purchaseToken)\n        NotificationType.SUBSCRIPTION_REVOKED -&gt; revokeGoogleEntitlement(purchaseToken)\n        \/\/ ... handle all notification types\n    }\n}\n\n\/\/ Apple Server Notification handler\nfun handleAppleNotification(signedPayload: String) {\n    val notification = verifyAndDecodeAppleNotification(signedPayload)\n    val transactionInfo = notification.data.signedTransactionInfo\n\n    when (notification.notificationType) {\n        \&amp;quot;DID_RENEW\&amp;quot; -&gt; refreshAppleEntitlement(transactionInfo)\n        \&amp;quot;DID_CHANGE_RENEWAL_STATUS\&amp;quot; -&gt; updateAppleRenewalStatus(transactionInfo)\n        \&amp;quot;EXPIRED\&amp;quot; -&gt; expireAppleEntitlement(transactionInfo)\n        \&amp;quot;REVOKE\&amp;quot; -&gt; revokeAppleEntitlement(transactionInfo)\n        \/\/ ... handle all notification types\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Each notification handler has different event names, different payload structures, and different state machine semantics. Grace periods work differently. Refund flows work differently. Even the concept of “cancellation” has subtle differences between the two platforms.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-true-scope-of-effort&quot;&gt;&lt;strong&gt;The true scope of effort&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;You need an infrastructure, building a cross-platform subscription sync involves. Even both Google and Apple regularly update their billing systems. Google introduced base plans and offers in 2022, requiring significant backend changes. Apple launched StoreKit 2 with an entirely new transaction model. Each major update requires engineering time to adapt your infrastructure.&lt;/p&gt;



&lt;p&gt;For a large team with dedicated backend engineers, this might be manageable. For a small team or an indie developer trying to ship a subscription app on both platforms, this represents months of work that has nothing to do with the core product.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;revenuecats-identity-system-the-natural-solution&quot;&gt;&lt;strong&gt;RevenueCat’s identity system: The natural solution&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;RevenueCat solves the cross platform problem at its foundation through a unified identity and entitlement system. Rather than requiring you to build the infrastructure described above, RevenueCat provides it as a service. The key design decision that makes this work is the&amp;nbsp;&lt;strong&gt;app user ID&lt;/strong&gt;&amp;nbsp;abstraction.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;how-the-identity-system-works&quot;&gt;&lt;strong&gt;How the identity system works&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;When you configure the RevenueCat SDK, you can either provide your own user ID or let RevenueCat generate an anonymous one:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-2mfTl3 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/\/ Android: Configure with your own user ID\nPurchases.configure(\n    PurchasesConfiguration.Builder(context, \&amp;quot;your_revenuecat_api_key\&amp;quot;)\n        .appUserID(\&amp;quot;user_12345\&amp;quot;)\n        .build()\n)&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;For iOS will be like so:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z19KJLv wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;swift&quot; content=&quot;&amp;quot;\/\/ iOS: Configure with the same user ID\nPurchases.configure(\n    with: .builder(withAPIKey: \&amp;quot;your_revenuecat_api_key\&amp;quot;)\n        .with(appUserID: \&amp;quot;user_12345\&amp;quot;)\n        .build()\n)&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The same&amp;nbsp;&lt;code&gt;appUserID&lt;/code&gt;&amp;nbsp;on both platforms creates a single subscriber record in RevenueCat’s backend. When the user subscribes on either platform, RevenueCat verifies the receipt, records the entitlement, and associates it with this user ID. When the other platform’s SDK queries for customer info, it receives the complete entitlement state, including subscriptions from the other platform.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;anonymous-to-identified-user-flow&quot;&gt;&lt;strong&gt;Anonymous to identified user flow&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;RevenueCat also handles the common scenario where users start anonymously and later create an account. When a user first opens your app, RevenueCat generates an anonymous ID in the format&amp;nbsp;&lt;code&gt;$RCAnonymousID:&amp;lt;uuid&amp;gt;&lt;/code&gt;. If the user subscribes before creating an account, the subscription is associated with this anonymous ID.&lt;/p&gt;



&lt;p&gt;When the user later creates an account and logs in, RevenueCat’s&amp;nbsp;&lt;code&gt;logIn&lt;/code&gt;&amp;nbsp;method transfers all purchases from the anonymous user to the identified user:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z2kAcPw wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;Purchases.sharedInstance.logIn(\n    newAppUserID = \&amp;quot;user_12345\&amp;quot;,\n    callback = object : LogInCallback {\n        override fun onReceived(customerInfo: CustomerInfo, created: Boolean) {\n            \/\/ customerInfo now contains entitlements from:\n            \/\/ 1. Any previous purchases made under the anonymous ID\n            \/\/ 2. Any purchases previously associated with \&amp;quot;user_12345\&amp;quot;\n            \/\/ 3. Purchases from ANY platform linked to this user\n\n            val isPremium = customerInfo.entitlements[\&amp;quot;premium\&amp;quot;]?.isActive == true\n        }\n\n        override fun onError(error: PurchasesError) {\n            \/\/ Handle error\n        }\n    }\n)&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The&amp;nbsp;&lt;code&gt;created&lt;/code&gt;&amp;nbsp;boolean indicates whether this was a new user or an existing one. If it is an existing user, RevenueCat merges the purchase histories. This is critical for cross platform scenarios: a user who first subscribed on iOS and later installs the Android app gets their entitlements transferred automatically when they log in with the same user ID.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;customerinfo-one-object-all-platforms&quot;&gt;&lt;strong&gt;CustomerInfo: One object, all platforms&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The&amp;nbsp;&lt;code&gt;CustomerInfo&lt;/code&gt;&amp;nbsp;object is RevenueCat’s answer to the cross platform entitlement problem. It aggregates subscription state from every platform into a single, easy to query object:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZCc8vQ wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;Purchases.sharedInstance.getCustomerInfoWith { customerInfo -&gt;\n    val premiumEntitlement = customerInfo.entitlements[\&amp;quot;premium\&amp;quot;]\n\n    if (premiumEntitlement?.isActive == true) {\n        \/\/ User has premium access, regardless of which platform they subscribed on\n        val store = premiumEntitlement.store\n        \/\/ Could be Store.APP_STORE, Store.PLAY_STORE, Store.AMAZON, etc.\n\n        val expirationDate = premiumEntitlement.expirationDate\n        val willRenew = premiumEntitlement.willRenew\n\n        showPremiumContent()\n    } else {\n        showPaywall()\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The&amp;nbsp;&lt;code&gt;store&lt;/code&gt;&amp;nbsp;property on each entitlement tells you which platform the subscription originated from. But for granting access, you do not need to check it. The&amp;nbsp;&lt;code&gt;isActive&lt;/code&gt;&amp;nbsp;property is the only thing that matters, and it works across all platforms.&lt;/p&gt;



&lt;p&gt;This is the key insight: RevenueCat transforms a cross platform infrastructure problem into a single property check. Your Android app does not need to know how to verify Apple receipts. Your iOS app does not need to know about Google Play purchase tokens. RevenueCat’s backend handles all of that and presents a unified view through&amp;nbsp;&lt;code&gt;CustomerInfo&lt;/code&gt;.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;what-happens-behind-the-scenes&quot;&gt;&lt;strong&gt;What happens behind the scenes&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;When a user subscribes on iOS and later opens the Android app, the following sequence occurs:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;The iOS SDK posts the App Store receipt to RevenueCat’s backend.&lt;/li&gt;



&lt;li&gt;RevenueCat verifies the receipt with Apple’s servers and records the entitlement against the user’s app user ID.&lt;/li&gt;



&lt;li&gt;RevenueCat registers for Apple Server Notifications to track renewals, cancellations, and billing issues.&lt;/li&gt;



&lt;li&gt;When the Android app launches and calls&amp;nbsp;&lt;code&gt;getCustomerInfo&lt;/code&gt;, the SDK sends the same app user ID to RevenueCat’s backend.&lt;/li&gt;



&lt;li&gt;RevenueCat returns the complete entitlement state, including the iOS subscription.&lt;/li&gt;



&lt;li&gt;The Android app sees&amp;nbsp;&lt;code&gt;isActive == true&lt;/code&gt;&amp;nbsp;on the premium entitlement and grants access.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;All renewal events, grace periods, cancellations, and expirations are tracked server side by RevenueCat. Both platforms always see the current subscription state without any platform specific code.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;handling-subscription-management&quot;&gt;&lt;strong&gt;Handling subscription management&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;One practical detail that cross platform subscriptions introduce is management URL routing. A user who subscribed on iOS needs to manage their subscription through the App Store, not Google Play. RevenueCat handles this through the&amp;nbsp;&lt;code&gt;managementURL&lt;/code&gt;&amp;nbsp;property:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1MQS2L wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;Purchases.sharedInstance.getCustomerInfoWith { customerInfo -&gt;\n    val managementUrl = customerInfo.managementURL\n\n    \/\/ This URL points to the correct store based on where the user subscribed\n    \/\/ - App Store subscription settings for iOS purchases\n    \/\/ - Google Play subscription settings for Android purchases\n\n    showManageSubscriptionButton(managementUrl)\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This prevents the confusing scenario where a user tries to cancel their subscription through Google Play but cannot find it because the subscription lives on Apple’s side.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;the-impact-on-development-velocity&quot;&gt;&lt;strong&gt;The impact on development velocity&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The difference in implementation effort between building cross platform sync yourself and using RevenueCat is substantial. Let’s compare the two approaches for a team shipping a subscription app on both Android and iOS.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;without-revenuecat&quot;&gt;&lt;strong&gt;Without RevenueCat&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;You need to build and maintain: a backend server with two receipt verification integrations, two notification processing pipelines, a user identity system, an entitlement database, and client side code on both platforms to communicate with your backend. This is 10 to 18 weeks of initial development, plus ongoing maintenance as both platforms evolve.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;with-revenuecat&quot;&gt;&lt;strong&gt;With RevenueCat&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Your implementation reduces to: configure the SDK with an app user ID on each platform, check&amp;nbsp;&lt;code&gt;CustomerInfo&lt;/code&gt;&amp;nbsp;for active entitlements, and display paywalls. The backend infrastructure is handled entirely by RevenueCat.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1ULPjE wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/\/ The entire Android-side implementation for cross-platform entitlements\nclass SubscriptionManager(private val context: Context) {\n\n    fun initialize(userId: String) {\n        Purchases.configure(\n            PurchasesConfiguration.Builder(context, \&amp;quot;your_api_key\&amp;quot;)\n                .appUserID(userId)\n                .build()\n        )\n    }\n\n    fun checkAccess(onResult: (Boolean) -&gt; Unit) {\n        Purchases.sharedInstance.getCustomerInfoWith { customerInfo -&gt;\n            val isPremium = customerInfo.entitlements[\&amp;quot;premium\&amp;quot;]?.isActive == true\n            onResult(isPremium)\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This is the complete code needed to support cross platform subscriptions on Android. The equivalent iOS code is similarly concise. No backend server, no receipt verification, no notification processing, no entitlement database. RevenueCat manages all of it.&lt;/p&gt;



&lt;p&gt;For indie developers and small teams, this difference is not just about saving time. It is about feasibility. Building cross platform subscription infrastructure from scratch requires backend engineering expertise, server hosting, monitoring, and ongoing maintenance. Many small teams simply cannot afford this investment, which means they either skip cross platform support entirely or build something fragile that breaks when platform APIs change. RevenueCat makes cross platform subscriptions accessible to teams of any size, letting developers focus their limited time on the features that make their app unique.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;conclusion&quot;&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;In this article, you’ve explored why cross platform subscription state is one of the hardest problems in mobile monetization. Google Play Billing and Apple’s StoreKit are fundamentally different systems with incompatible receipt formats, different verification APIs, different notification mechanisms, and different product structures. Bridging them requires a unified identity system, dual receipt verification, platform agnostic entitlement storage, and two parallel notification processing pipelines.&lt;/p&gt;



&lt;p&gt;Building this infrastructure from scratch takes months and requires continuous maintenance as both platforms evolve. For large teams, it is a significant but manageable investment. For small teams and indie developers, it can consume more engineering time than the core product itself.&lt;/p&gt;



&lt;p&gt;RevenueCat’s identity and entitlement system provides a natural solution by abstracting away the platform differences behind a single&amp;nbsp;&lt;code&gt;CustomerInfo&lt;/code&gt;&amp;nbsp;object. A shared app user ID across platforms, combined with RevenueCat’s server side receipt verification and notification processing, transforms a months long infrastructure project into a few lines of SDK configuration. Whether a subscription originated from the App Store, Google Play, Amazon, or the web, your app simply checks&amp;nbsp;&lt;code&gt;isActive&lt;/code&gt;&amp;nbsp;and grants access.&lt;/p&gt;



&lt;p&gt;For teams building subscription apps that serve users across platforms, understanding the scope of this problem helps you make informed build versus buy decisions. The time saved by using a managed solution can be redirected toward improving your app, optimizing your paywall, and building the features that actually differentiate your product.&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Building a hardware-enabled subscription business]]></title><description><![CDATA[On the podcast, I talk with Michael and Mark about the boom in hardware-enabled subscriptions, why nothing worked until they stopped optimizing and started building a better product, and how they doubled their price to $79 even though the data said they could charge more.]]></description><link>https://www.revenuecat.com/blog/growth/mark-michael-skylight-sub-club-podcast-2026/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/mark-michael-skylight-sub-club-podcast-2026/</guid><pubDate>Wed, 18 Feb 2026 13:39:21 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/RC-Blog-Cover-Skylight-1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Hardware alone doesn’t build enterprise value. And layering a subscription on top of hardware only works if the product becomes part of daily life.&lt;/p&gt;



&lt;p&gt;In this episode of Sub Club, Skylight’s CEO and CPO share how they built a profitable hardware business with strong subscription attach — and the hard lessons they learned about daily usage, emotional pricing, product readiness, and retail distribution.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;How Skylight Doubled Subscription Prices to $79 – Michael Segal &amp;amp; Mark Ungerer&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/AilakPuHdf4?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;iframe loading=&quot;lazy&quot; width=&quot;100%&quot; height=&quot;180&quot; frameborder=&quot;no&quot; scrolling=&quot;no&quot; seamless=&quot;&quot; src=&quot;https://share.transistor.fm/e/9673c9c4?color=FFFFFF&amp;amp;background=30343C&quot;&gt;&lt;/iframe&gt;



&lt;p&gt;Here are five takeaways for anyone building a hardware-enabled subscription business.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-hardware-enabled-subscriptions-need-daily-usage-to-work&quot;&gt;Hardware-enabled subscriptions need daily usage to work&lt;/h2&gt;



&lt;p&gt;A hardware device can justify a subscription — but only if it’s used daily.&lt;/p&gt;



&lt;p&gt;If a device sits idle, recurring revenue quickly feels optional. Customers start questioning what they’re paying for. But when a product becomes embedded in daily routines — organizing schedules, surfacing tasks, anchoring family communication — the subscription feels like a natural extension of its value.&lt;/p&gt;



&lt;p&gt;Daily attention creates subscription leverage.&lt;/p&gt;



&lt;p&gt;For Skylight, the turning point came when the Calendar product became the “heartbeat of the home.” Once families relied on it every day, the subscription became less about upselling features and more about unlocking deeper utility.&lt;/p&gt;



&lt;p&gt;Without habitual usage, subscriptions struggle. With it, they compound.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-stop-optimizing-when-you-should-be-building&quot;&gt;Stop optimizing when you should be building&lt;/h2&gt;



&lt;p&gt;A/B testing and funnel optimization can drive incremental gains. But sometimes the biggest growth lever isn’t conversion — it’s product.&lt;/p&gt;



&lt;p&gt;With limited resources, Skylight had to prioritize carefully. Instead of spreading effort across endless micro-experiments, they focused on building genuinely valuable features that strengthened the overall experience.&lt;/p&gt;



&lt;p&gt;Optimization matters. But step-function growth often comes from shipping something that makes the product meaningfully better.&lt;/p&gt;



&lt;p&gt;When resources are constrained, prioritization becomes strategy.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-price-based-on-customer-emotion-not-just-data&quot;&gt;Price based on customer emotion, not just data&lt;/h2&gt;



&lt;p&gt;When Skylight revisited its subscription pricing, testing showed $99/year would maximize revenue.&lt;/p&gt;



&lt;p&gt;On paper, it was the ARPU winner.&lt;/p&gt;



&lt;p&gt;But qualitative research told a different story. While $79 felt fair, $99 approached what the team described as “disgust territory.” That emotional reaction mattered.&lt;/p&gt;



&lt;p&gt;For a company focused on long-term brand equity, short-term revenue optimization wasn’t worth risking customer resentment. They chose $79 — prioritizing goodwill and trust over squeezing every dollar.&lt;/p&gt;



&lt;p&gt;Pricing isn’t just math. It’s emotional positioning.&lt;/p&gt;



&lt;p&gt;The spreadsheet can tell you what maximizes revenue. Only customer conversations tell you what preserves loyalty.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-build-a-great-product-before-scaling-marketing&quot;&gt;Build a great product before scaling marketing&lt;/h2&gt;



&lt;p&gt;Marketing can’t fix a weak product.&lt;/p&gt;



&lt;p&gt;In 2021–22, Skylight tried to scale its Calendar product aggressively. Paid acquisition ramped up. Growth stalled. The numbers didn’t work.&lt;/p&gt;



&lt;p&gt;The problem wasn’t the ads — it was the product.&lt;/p&gt;



&lt;p&gt;Until the team pushed the experience to a 40+ Net Promoter Score, marketing dollars produced false negatives and wasted spend. Once the product truly resonated, scaling became viable.&lt;/p&gt;



&lt;p&gt;If product-market fit isn’t solid, scaling marketing only amplifies friction.&lt;/p&gt;



&lt;p&gt;Get the product right first. Then turn on growth.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-retail-partnerships-are-the-ultimate-influencer&quot;&gt;Retail partnerships are the ultimate influencer&lt;/h2&gt;



&lt;p&gt;In hardware, distribution is influence.&lt;/p&gt;



&lt;p&gt;Retail partnerships with companies like Costco and Best Buy provide a stamp of quality that paid ads can’t replicate. Being on trusted shelves signals credibility to customers at scale.&lt;/p&gt;



&lt;p&gt;While direct-to-consumer channels often drive higher subscription attach rates, multi-channel distribution expands reach and strengthens brand legitimacy.&lt;/p&gt;



&lt;p&gt;Hardware can be copied. Distribution is harder to replicate.&lt;/p&gt;



&lt;p&gt;For Skylight, retail wasn’t just a sales channel — it was a growth engine and a positioning advantage.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-balancing-growth-profit-and-long-term-trust&quot;&gt;Balancing growth, profit, and long-term trust&lt;/h2&gt;



&lt;p&gt;Across all five lessons, a deeper theme emerges: growth and profit often pull in different directions.&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Making subscriptions frictionless can reduce margin.&lt;br&gt;&lt;/li&gt;



&lt;li&gt;Raising prices can increase ARPU but hurt long-term trust.&lt;br&gt;&lt;/li&gt;



&lt;li&gt;Cutting hardware prices could accelerate growth but compress profitability.&lt;br&gt;&lt;/li&gt;



&lt;li&gt;Over-optimizing can distract from building durable value.&lt;br&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Every decision involves trade-offs.&lt;/p&gt;



&lt;p&gt;Skylight’s approach shows that scaling a hardware-enabled subscription business isn’t about maximizing every metric at once. It’s about choosing which levers matter most — and when.&lt;/p&gt;



&lt;p&gt;Hardware-enabled subscriptions aren’t about layering recurring revenue onto a device. They’re about earning daily relevance, pricing with emotional intelligence, and building a product strong enough to deserve scale.&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;p&gt;🎧 &lt;a href=&quot;https://www.youtube.com/watch?v=AilakPuHdf4&quot;&gt;Listen to the full episode of Sub Club&lt;/a&gt; to hear the complete conversation and the experiments behind these lessons.&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Building Helm: turning App Store pain into a product developers love]]></title><description><![CDATA[On the podcast, I sit down with Pol and Hidde to discuss the frustrations developers face with App Store Connect, how they turned their own pain points into Helm, and why automating app launches and translations has become a game-changer for indie developers.]]></description><link>https://www.revenuecat.com/blog/growth/hidde-pol-helm-launched-podcast-2026/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/hidde-pol-helm-launched-podcast-2026/</guid><pubDate>Wed, 11 Feb 2026 13:53:22 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/LD-Blog-Cover-Hidde-Pol-1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;If you’ve shipped more than one iOS app, you already know the feeling: App Store Connect works — but only barely. Releases are slow. Metadata updates are clunky. Translations are painful. And every launch feels harder than it needs to be.&lt;/p&gt;



&lt;p&gt;That frustration is exactly where Helm came from.&lt;/p&gt;



&lt;p&gt;In this episode of Launched, host Charlie Chapman sits down with Hidde van de Ploeg and Pol Piella, the co-founders of Helm, to unpack how a deeply personal pain point turned into a tool indie developers now recommend by name.&lt;/p&gt;



&lt;p&gt;This isn’t a story about chasing a market. It’s a story about improving an experience that was lacking.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;Turning App Store Connect Frustration Into a Tool Developers Love – Hidde &amp;amp; Pol, Helm&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/VpdxiQappZI?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;iframe loading=&quot;lazy&quot; width=&quot;100%&quot; height=&quot;180&quot; frameborder=&quot;no&quot; scrolling=&quot;no&quot; seamless=&quot;&quot; src=&quot;https://share.transistor.fm/e/9ed327c9?color=FFFFFF&amp;amp;background=30343C&quot;&gt;&lt;/iframe&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-build-for-the-pain-not-the-platform&quot;&gt;Build for the pain, not the platform&lt;/h2&gt;



&lt;p&gt;Helm wasn’t born out of market analysis or trend-chasing. It came from Hidde’s repeated frustration shipping his own apps. App Store Connect wasn’t broken enough to replace — but it was broken enough to slow him down every single time.&lt;/p&gt;



&lt;p&gt;Instead of brainstorming abstract opportunities, Hidde and Pol focused on the workflows that consistently caused friction in their own day-to-day work. By starting with problems they personally experienced, they ended up building something instantly useful to the exact audience they belong to: indie app developers.&lt;/p&gt;



&lt;p&gt;That closeness to the problem shaped everything — from what Helm does to what it very intentionally does not do.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-focus-beats-feature-parity&quot;&gt;Focus beats feature parity&lt;/h2&gt;



&lt;p&gt;Helm doesn’t try to replicate App Store Connect. It rebuilds only the parts developers actively dread — and makes them effortless.&lt;/p&gt;



&lt;p&gt;Rather than matching Apple feature-for-feature, Hidde and Pol obsessed over friction points like fast TestFlight access, AI-powered translations, and smoother release workflows. The goal was never completeness. It was relief.&lt;/p&gt;



&lt;p&gt;By doing less, but doing it brilliantly, Helm turns a clunky chore into something developers actually enjoy using. The product succeeds not by breadth, but by precision.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-delight-is-the-best-growth-strategy&quot;&gt;Delight is the best growth strategy&lt;/h2&gt;



&lt;p&gt;Helm didn’t grow through paid ads, SEO funnels, or launch gimmicks. It grew because developers felt seen.&lt;/p&gt;



&lt;p&gt;As Helm spread, a pattern emerged on social media: when someone complained about App Store Connect, another developer would often jump in to recommend Helm. That kind of advocacy only happens when a product genuinely removes pain for the right people.&lt;/p&gt;



&lt;p&gt;Helm’s growth is a reminder that for indie tools, delight can be a far more powerful growth engine than distribution tactics.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-marketing-is-about-memory-not-metrics&quot;&gt;Marketing is about memory, not metrics&lt;/h2&gt;



&lt;p&gt;Some of Helm’s most talked-about moments weren’t designed to convert at all.&lt;/p&gt;



&lt;p&gt;Sponsoring a small amateur football team named Swift wasn’t about customer acquisition. It was about building brand lore. Playful initiatives like Helm Passport followed the same philosophy — they were meant to be fun, human, and memorable.&lt;/p&gt;



&lt;p&gt;In a world of perfectly optimized funnels, Helm stands out by embracing personality. That personality sticks with people long after they forget feature lists.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-mobile-is-a-chance-to-surprise&quot;&gt;Mobile is a chance to surprise&lt;/h2&gt;



&lt;p&gt;When Helm expanded to iOS, the team didn’t simply shrink the desktop experience to fit a smaller screen. They leaned into what mobile does best.&lt;/p&gt;



&lt;p&gt;Features like Helm Passport, built with App Clips, introduced a playful, real-world interaction that sparked conversation and sharing. Mobile wasn’t treated as a secondary surface, but as an opportunity to rethink how the product could show up in people’s lives.&lt;/p&gt;



&lt;p&gt;Great mobile experiences don’t just adapt existing products. They reimagine them.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-shared-ownership-beats-rigid-roles&quot;&gt;Shared ownership beats rigid roles&lt;/h2&gt;



&lt;p&gt;Although Hidde and Pol come from different backgrounds — design and engineering — they don’t operate in silos. Both founders touch the whole product, jump in wherever needed, and stay deeply familiar with the entire codebase.&lt;/p&gt;



&lt;p&gt;That shared ownership keeps Helm fast, resilient, and aligned. For small teams, overlapping responsibility often matters more than clearly defined roles.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-a-product-built-from-real-frustration&quot;&gt;A product built from real frustration&lt;/h2&gt;



&lt;p&gt;Helm’s story is a reminder of why Launched exists in the first place.&lt;/p&gt;



&lt;p&gt;You don’t need a grand vision to start something meaningful. Sometimes, you just need a problem that won’t leave you alone — and the willingness to fix it properly.&lt;/p&gt;



&lt;p&gt;🎧 &lt;a href=&quot;https://www.youtube.com/watch?v=VpdxiQappZI&quot;&gt;Listen to the full episode of Launched&lt;/a&gt; to hear Hidde van de Ploeg and Pol Piella share how they turned everyday frustration into one of the most loved indie tools in the iOS ecosystem — and where Helm is headed next.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[How kotlinx.serialization generates code: a compiler plugin deep dive]]></title><description><![CDATA[In this article, you'll dive deep into the internal mechanisms of the kotlinx.serialization compiler plugin.]]></description><link>https://www.revenuecat.com/blog/engineering/kotlinx-serialization/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/kotlinx-serialization/</guid><pubDate>Wed, 11 Feb 2026 03:56:08 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Blog_20_How-kotlinx.serialization-generates-code.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;&lt;a href=&quot;https://github.com/Kotlin/kotlinx.serialization&quot;&gt;Kotlinx.serialization&lt;/a&gt; has become the standard serialization library for Kotlin, offering compile time code generation, multiplatform support, and format agnostic design. Most developers know the surface level usage: annotate a class with&amp;nbsp;&lt;code&gt;@Serializable&lt;/code&gt;, and the library handles the rest. But the deeper question remains: how does the compiler plugin actually generate serializers? What happens between your&amp;nbsp;&lt;code&gt;@Serializable&lt;/code&gt;&amp;nbsp;annotation and the working&amp;nbsp;&lt;code&gt;KSerializer&amp;lt;T&amp;gt;&lt;/code&gt;&amp;nbsp;implementation?&lt;/p&gt;



&lt;p&gt;In this article, you’ll dive deep into the internal mechanisms of the kotlinx.serialization compiler plugin, exploring how the two pass IR generation pipeline works, how the plugin generates the&amp;nbsp;&lt;code&gt;$serializer&lt;/code&gt;&amp;nbsp;nested class with its descriptor, serialize, and deserialize methods, and the clever optimizations like golden mask validation that make deserialization both safe and performant. Also, you’ll explore with the real use cases of kotlinx.serialization from the &lt;a href=&quot;https://github.com/RevenueCat/purchases-android&quot;&gt;RevenueCat SDK&lt;/a&gt;.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-fundamental-problem-reflection-is-expensive-and-platform-dependent&quot;&gt;&lt;strong&gt;The fundamental problem: Reflection is expensive and platform dependent&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Consider a simple data class that you want to serialize to JSON:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-2kNy0V wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;data class User(\n    val id: Long,\n    val name: String,\n    val email: String?,\n    val createdAt: Date\n)&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Without code generation, serialization libraries must use reflection to discover properties, their types, and their values at runtime. This approach has significant drawbacks:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-19zwCO wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/\/ Reflection-based serialization (simplified)\nfun serializeWithReflection(obj: Any): Map&lt;String, Any?&gt; {\n    val result = mutableMapOf&lt;String, Any?&gt;()\n    obj::class.memberProperties.forEach { prop -&gt;\n        prop.isAccessible = true\n        result[prop.name] = prop.get(obj)\n    }\n    return result\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The problems with this approach are substantial. First, reflection is slow. Discovering properties, checking accessibility, and invoking getters at runtime adds overhead to every serialization operation. Second, reflection is platform dependent. Kotlin/Native and Kotlin/JS have limited or different reflection capabilities than the JVM. Third, there is no compile time safety. Type mismatches and missing properties are only discovered at runtime.&lt;/p&gt;



&lt;p&gt;The kotlinx.serialization plugin solves these problems by generating serialization code at compile time. The generated code knows exactly which properties exist, their types, and how to read and write them, with no reflection required.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;the-compiler-plugin-architecture&quot;&gt;&lt;strong&gt;The compiler plugin architecture&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The kotlinx.serialization compiler plugin operates as an extension to the Kotlin compiler, hooking into multiple stages of the compilation pipeline. The plugin is organized into several components that work together:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Frontend (K1 or K2)&lt;/strong&gt;: Detects&amp;nbsp;&lt;code&gt;@Serializable&lt;/code&gt;&amp;nbsp;annotations and generates synthetic declarations (the&amp;nbsp;&lt;code&gt;$serializer&lt;/code&gt;&amp;nbsp;class, companion methods).&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;IR Generation&lt;/strong&gt;: Transforms the intermediate representation in two passes. Pass 1 creates function stubs, Pass 2 generates method bodies.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Backend&lt;/strong&gt;: Emits platform specific code (JVM bytecode, JavaScript, or Native binaries).&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;The plugin registers itself through a&amp;nbsp;&lt;code&gt;CompilerPluginRegistrar&lt;/code&gt;&amp;nbsp;that hooks into these extension points. The critical registration looks conceptually like this:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-lv73 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;class SerializationComponentRegistrar : CompilerPluginRegistrar() {\n    override fun ExtensionStorage.registerExtensions(configuration: CompilerConfiguration) {\n        \/\/ Register resolve extension for synthetic declarations\n        SyntheticResolveExtension.registerExtension(SerializationResolveExtension())\n\n        \/\/ Register IR generation extension for code generation\n        IrGenerationExtension.registerExtension(SerializationLoweringExtension())\n\n        \/\/ Register K2\/FIR extensions for new compiler frontend\n        FirExtensionRegistrarAdapter.registerExtension(FirSerializationExtensionRegistrar())\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The key observation here is that the plugin operates at multiple levels. It first generates synthetic declarations during the resolve phase, making the compiler aware of generated classes and methods. Then it generates the actual implementation bodies during the IR lowering phase.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;two-pass-ir-generation-stubs-before-bodies&quot;&gt;&lt;strong&gt;Two pass IR generation: Stubs before bodies&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;One of the most interesting aspects of the kotlinx.serialization plugin is its two pass IR generation strategy. Understanding why this is necessary requires understanding how generated code references itself.&lt;/p&gt;



&lt;p&gt;Consider what the plugin needs to generate for a serializable class:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1OQfjj wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Serializable\ndata class User(val name: String, val age: Int)\n\n\/\/ The plugin generates:\n\/\/ 1. A nested $serializer class implementing KSerializer&lt;User&gt;\n\/\/ 2. A companion object with serializer() method\n\/\/ 3. Methods that reference each other&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The generated&amp;nbsp;&lt;code&gt;serialize()&lt;/code&gt;&amp;nbsp;method might call a helper method like&amp;nbsp;&lt;code&gt;write$Self()&lt;/code&gt;. The&amp;nbsp;&lt;code&gt;deserialize()&lt;/code&gt;&amp;nbsp;method needs to call the class constructor. These methods reference each other and reference other generated elements. If the plugin tried to generate everything in a single pass, it would encounter undefined references.&lt;/p&gt;



&lt;p&gt;The solution is a two pass approach:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z39H0Y wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;class SerializationLoweringExtension : IrGenerationExtension {\n    override fun generate(moduleFragment: IrModuleFragment, pluginContext: IrPluginContext) {\n        \/\/ Pass 1: Create all declarations without bodies\n        val preGenerator = SerializerClassPreLowering(pluginContext)\n        moduleFragment.files.forEach { file -&gt;\n            preGenerator.runOnFileInOrder(file)\n        }\n\n        \/\/ Pass 2: Generate implementation bodies\n        val generator = SerializerClassLowering(pluginContext)\n        moduleFragment.files.forEach { file -&gt;\n            generator.runOnFileInOrder(file)\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;In the first pass, the plugin creates function declarations with empty bodies. This establishes all the symbols that generated code might reference. In the second pass, the plugin fills in the actual implementation bodies, now able to reference any symbol created in the first pass.&lt;/p&gt;



&lt;p&gt;This is elegant. The two pass strategy mirrors how compilers handle forward declarations in languages like C, but applied to code generation within a single compilation unit.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;the-generated-serializer-structure&quot;&gt;&lt;strong&gt;The generated serializer structure&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;When you annotate a class with&amp;nbsp;&lt;code&gt;@Serializable&lt;/code&gt;, the plugin generates a nested class named&amp;nbsp;&lt;code&gt;$serializer&lt;/code&gt;&amp;nbsp;that implements&amp;nbsp;&lt;code&gt;GeneratedSerializer&amp;lt;T&amp;gt;&lt;/code&gt;. Let’s trace through what gets generated for a simple class:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z2ixIVr wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Serializable\ndata class Person(\n    val name: String,\n    val age: Int,\n    val email: String? = null\n)&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The plugin generates a structure that conceptually looks like this:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z2nYPpW wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;data class Person(val name: String, val age: Int, val email: String? = null) {\n\n    \/\/ Generated nested serializer class\n    internal object `$serializer` : GeneratedSerializer&lt;Person&gt; {\n\n        override val descriptor: SerialDescriptor = buildClassSerialDescriptor(\&amp;quot;Person\&amp;quot;) {\n            element&lt;String&gt;(\&amp;quot;name\&amp;quot;)\n            element&lt;Int&gt;(\&amp;quot;age\&amp;quot;)\n            element&lt;String?&gt;(\&amp;quot;email\&amp;quot;, isOptional = true)\n        }\n\n        override fun serialize(encoder: Encoder, value: Person) {\n            val composite = encoder.beginStructure(descriptor)\n            composite.encodeStringElement(descriptor, 0, value.name)\n            composite.encodeIntElement(descriptor, 1, value.age)\n            if (value.email != null || composite.shouldEncodeElementDefault(descriptor, 2)) {\n                composite.encodeNullableSerializableElement(\n                    descriptor, 2, String.serializer(), value.email\n                )\n            }\n            composite.endStructure(descriptor)\n        }\n\n        override fun deserialize(decoder: Decoder): Person {\n            val composite = decoder.beginStructure(descriptor)\n            var name: String? = null\n            var age: Int? = null\n            var email: String? = null\n            var seen = 0\n\n            while (true) {\n                when (val index = composite.decodeElementIndex(descriptor)) {\n                    0 -&gt; { name = composite.decodeStringElement(descriptor, 0); seen = seen or 1 }\n                    1 -&gt; { age = composite.decodeIntElement(descriptor, 1); seen = seen or 2 }\n                    2 -&gt; { email = composite.decodeNullableSerializableElement(\n                               descriptor, 2, String.serializer()); seen = seen or 4 }\n                    CompositeDecoder.DECODE_DONE -&gt; break\n                    else -&gt; throw SerializationException(\&amp;quot;Unknown index $index\&amp;quot;)\n                }\n            }\n            composite.endStructure(descriptor)\n\n            \/\/ Validate required fields\n            if (seen and 3 != 3) {\n                throwMissingFieldException(seen, 3, descriptor)\n            }\n\n            return Person(\n                name = name as String,\n                age = age as Int,\n                email = email\n            )\n        }\n\n        override fun childSerializers(): Array&lt;KSerializer&lt;*&gt;&gt; = arrayOf(\n            String.serializer(),\n            Int.serializer(),\n            String.serializer().nullable\n        )\n    }\n\n    companion object {\n        fun serializer(): KSerializer&lt;Person&gt; = `$serializer`\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Notice the structure. The&amp;nbsp;&lt;code&gt;$serializer&lt;/code&gt;&amp;nbsp;class is an object (singleton) that holds the immutable descriptor and implements the serialization logic. The companion object provides a convenient&amp;nbsp;&lt;code&gt;serializer()&lt;/code&gt;&amp;nbsp;accessor.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;descriptor-generation-metadata-for-format-agnostic-serialization&quot;&gt;&lt;strong&gt;Descriptor generation: Metadata for format agnostic serialization&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The&amp;nbsp;&lt;code&gt;SerialDescriptor&lt;/code&gt;&amp;nbsp;is a critical piece of the generated code. It describes the structure of the serializable class in a format independent way, enabling different serialization formats (JSON, Protobuf, CBOR) to use the same serializer implementation.&lt;/p&gt;



&lt;p&gt;The plugin generates descriptor initialization code that builds the complete metadata:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-2a176V wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;override val descriptor: SerialDescriptor =\n    PluginGeneratedSerialDescriptor(\&amp;quot;com.example.Person\&amp;quot;, this, 3).apply {\n        addElement(\&amp;quot;name\&amp;quot;, isOptional = false)\n        addElement(\&amp;quot;age\&amp;quot;, isOptional = false)\n        addElement(\&amp;quot;email\&amp;quot;, isOptional = true)\n        \/\/ Annotations are also copied to the descriptor\n    }&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The descriptor includes the serial name of the class (which might differ from the class name if&amp;nbsp;&lt;code&gt;@SerialName&lt;/code&gt;&amp;nbsp;is used), the number of elements, each element’s name and whether it’s optional, type information for nested serializers, and any&amp;nbsp;&lt;code&gt;@SerialInfo&lt;/code&gt;&amp;nbsp;annotations applied to the class or its properties.&lt;/p&gt;



&lt;p&gt;This design is clever. By separating the structural metadata from the serialization logic, formats can make intelligent decisions about encoding. A JSON encoder might use the element names directly as keys. A Protobuf encoder might use element indices. The serializer implementation remains the same.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;golden-mask-optimization-efficient-required-field-validation&quot;&gt;&lt;strong&gt;Golden mask optimization: Efficient required field validation&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;One of the most important optimizations in the generated code is the golden mask pattern for validating required fields during deserialization. When deserializing, the plugin needs to ensure all required (non optional) fields are present in the input.&lt;/p&gt;



&lt;p&gt;The naive approach would be to check each field individually:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZQYuMk wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/\/ Naive approach\nif (name == null) throw MissingFieldException(\&amp;quot;name\&amp;quot;)\nif (age == null) throw MissingFieldException(\&amp;quot;age\&amp;quot;)\n\/\/ ... for each required field&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Instead, the plugin generates bitmask based validation:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-LumJl wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;var seen = 0\n\n\/\/ During deserialization, set bits as fields are encountered\nwhen (index) {\n    0 -&gt; { name = ...; seen = seen or 0b001 }  \/\/ bit 0\n    1 -&gt; { age = ...;  seen = seen or 0b010 }  \/\/ bit 1\n    2 -&gt; { email = ...; seen = seen or 0b100 } \/\/ bit 2 (optional)\n}\n\n\/\/ Golden mask contains bits for all REQUIRED fields\nval goldenMask = 0b011  \/\/ name (bit 0) and age (bit 1) are required\n\n\/\/ Single comparison validates all required fields\nif (seen and goldenMask != goldenMask) {\n    throwMissingFieldException(seen, goldenMask, descriptor)\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This is a gold. A single bitwise AND operation validates all required fields simultaneously. The golden mask is computed at compile time based on which properties have default values (optional) and which don’t (required).&lt;/p&gt;



&lt;p&gt;For classes with more than 32 properties, the plugin generates multiple mask integers:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZB5A1D wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;var seen0 = 0  \/\/ Properties 0-31\nvar seen1 = 0  \/\/ Properties 32-63\n\nval goldenMask0 = 0b...\nval goldenMask1 = 0b...\n\nif (seen0 and goldenMask0 != goldenMask0 ||\n    seen1 and goldenMask1 != goldenMask1) {\n    throwArrayMissingFieldException(intArrayOf(seen0, seen1),\n                                     intArrayOf(goldenMask0, goldenMask1),\n                                     descriptor)\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The error reporting is also smart. The&amp;nbsp;&lt;code&gt;throwMissingFieldException&lt;/code&gt;&amp;nbsp;function uses the seen mask and golden mask to determine exactly which fields are missing, providing a clear error message without requiring additional bookkeeping.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;serializer-resolution-finding-the-right-serializer-for-each-type&quot;&gt;&lt;strong&gt;Serializer resolution: Finding the right serializer for each type&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;When generating serialization code for a property, the plugin must determine which serializer to use. This resolution follows a priority order:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZTVBzR wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;fun findSerializerForType(type: IrType, property: IrProperty): IrExpression {\n    \/\/ 1. Explicit serializer annotation\n    property.getSerializableWith()?.let { return instantiate(it) }\n\n    \/\/ 2. Contextual serializer\n    if (property.hasContextualAnnotation()) {\n        return getContextualSerializer(type)\n    }\n\n    \/\/ 3. Primitive types have built-in serializers\n    if (type.isPrimitiveType()) {\n        return getBuiltInSerializer(type)  \/\/ Int.serializer(), String.serializer(), etc.\n    }\n\n    \/\/ 4. Collections and maps\n    if (type.isCollection()) {\n        val elementSerializer = findSerializerForType(type.elementType)\n        return ListSerializer(elementSerializer)\n    }\n\n    \/\/ 5. Enum classes\n    if (type.isEnum()) {\n        return getEnumSerializer(type)\n    }\n\n    \/\/ 6. Other @Serializable classes\n    if (type.hasSerializableAnnotation()) {\n        return type.classSerializer()  \/\/ Type.$serializer\n    }\n\n    \/\/ 7. Polymorphic fallback for interfaces\n    if (type.isInterface()) {\n        return PolymorphicSerializer(type)\n    }\n\n    throw SerializationException(\&amp;quot;No serializer found for $type\&amp;quot;)\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This resolution happens at compile time, and the result is baked into the generated code. The generated&amp;nbsp;&lt;code&gt;childSerializers()&lt;/code&gt;&amp;nbsp;method returns an array of all serializers needed for the class’s properties, enabling format implementations to introspect the complete serialization structure.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;real-world-application-custom-serializers-in-production-sdks&quot;&gt;&lt;strong&gt;Real world application: Custom serializers in production SDKs&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Understanding the generated serializer structure helps when building custom serializers. Production SDKs like &lt;a href=&quot;https://github.com/RevenueCat/purchases-android&quot;&gt;RevenueCat’s Android SDK&lt;/a&gt; leverage this knowledge to build robust serialization for complex API responses.&lt;/p&gt;



&lt;p&gt;For example, when dealing with backend responses that might include unknown enum values or polymorphic types, a custom deserializer with defaults becomes necessary:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1SlR81 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;internal abstract class SealedDeserializerWithDefault&lt;T : Any&gt;(\n    private val serialName: String,\n    private val serializerByType: Map&lt;String, () -&gt; KSerializer&lt;out T&gt;&gt;,\n    private val defaultValue: (type: String) -&gt; T,\n    private val typeDiscriminator: String = \&amp;quot;type\&amp;quot;,\n) : KSerializer&lt;T&gt; {\n\n    override val descriptor: SerialDescriptor = buildClassSerialDescriptor(serialName) {\n        element(typeDiscriminator, String.serializer().descriptor)\n    }\n\n    override fun deserialize(decoder: Decoder): T {\n        val jsonDecoder = decoder as? JsonDecoder\n            ?: throw SerializationException(\&amp;quot;Can only deserialize from JSON\&amp;quot;)\n        val jsonObject = jsonDecoder.decodeJsonElement().jsonObject\n        val type = jsonObject[typeDiscriminator]?.jsonPrimitive?.content\n\n        return serializerByType[type]?.let { serializerFactory -&gt;\n            jsonDecoder.json.decodeFromJsonElement(serializerFactory(), jsonObject)\n        } ?: defaultValue(type ?: \&amp;quot;null\&amp;quot;)\n    }\n\n    override fun serialize(encoder: Encoder, value: T) {\n        throw NotImplementedError(\&amp;quot;Serialization not needed for API responses\&amp;quot;)\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This pattern mirrors how the plugin generates deserializers but adds fallback behavior for unknown types. It reads the type discriminator, looks up the appropriate serializer, and falls back to a default when the type is unknown. This is essential for backward compatibility when servers add new types that older clients don’t recognize.&lt;/p&gt;



&lt;p&gt;Similarly, enum deserialization with defaults handles unknown values gracefully:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-2bJjIW wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;internal abstract class EnumDeserializerWithDefault&lt;T : Enum&lt;T&gt;&gt;(\n    private val valuesByType: Map&lt;String, T&gt;,\n    private val defaultValue: T,\n) : KSerializer&lt;T&gt; {\n\n    override val descriptor: SerialDescriptor =\n        PrimitiveSerialDescriptor(defaultValue.javaClass.simpleName, PrimitiveKind.STRING)\n\n    override fun deserialize(decoder: Decoder): T {\n        val key = decoder.decodeString()\n        return valuesByType[key] ?: defaultValue\n    }\n\n    override fun serialize(encoder: Encoder, value: T) {\n        throw NotImplementedError(\&amp;quot;Serialization not needed\&amp;quot;)\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;These patterns work because they follow the same interface contract that the generated serializers implement. Understanding the generated structure makes building compatible custom serializers straightforward.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;k1-vs-k2-supporting-both-compiler-frontends&quot;&gt;&lt;strong&gt;K1 vs. K2: Supporting both compiler frontends&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The Kotlin compiler is undergoing a major transition from the K1 frontend to the K2 frontend (based on FIR, Frontend Intermediate Representation). The kotlinx.serialization plugin must support both during this transition.&lt;/p&gt;



&lt;p&gt;The K1 support uses descriptor based APIs:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-VdXtp wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;class SerializationResolveExtension : SyntheticResolveExtension {\n    override fun getSyntheticNestedClassNames(thisDescriptor: ClassDescriptor): List&lt;Name&gt; {\n        if (thisDescriptor.hasSerializableAnnotation()) {\n            return listOf(Name.identifier(\&amp;quot;\\$serializer\&amp;quot;))\n        }\n        return emptyList()\n    }\n\n    override fun generateSyntheticClasses(\n        thisDescriptor: ClassDescriptor,\n        result: MutableCollection&lt;DeclarationDescriptor&gt;\n    ) {\n        \/\/ Generate synthetic $serializer class descriptor\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The K2 support uses the new FIR based APIs:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1qVoBk wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;class SerializationFirResolveExtension : FirDeclarationGenerationExtension {\n    override fun generateNestedClassLikeDeclaration(\n        owner: FirClassSymbol&lt;*&gt;,\n        name: Name\n    ): FirClassLikeSymbol&lt;*&gt;? {\n        if (name.identifier == \&amp;quot;\\$serializer\&amp;quot; &amp;amp;&amp;amp; owner.hasSerializableAnnotation()) {\n            return generateSerializerClass(owner)\n        }\n        return null\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The key observation is that both frontends ultimately feed into the same IR generation phase. The IR lowering code that generates method bodies is shared between K1 and K2. This separation of concerns allows the plugin to support both frontends while maintaining a single implementation of the actual code generation logic.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;conclusion&quot;&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;In this article, you’ve explored the internal mechanisms of the kotlinx.serialization compiler plugin, from its two pass IR generation strategy to the golden mask optimization for required field validation. The plugin transforms simple&amp;nbsp;&lt;code&gt;@Serializable&lt;/code&gt;&amp;nbsp;annotations into efficient, type safe serializers without requiring reflection or runtime code generation.&lt;/p&gt;



&lt;p&gt;Of course, you don’t have any issues without understanding these internals mechanisms, but it will definitely help you make informed decisions when building custom serializers, debugging serialization issues, or evaluating kotlinx.serialization for your projects in any ways. The design choices, like compile time code generation, format agnostic descriptors, and bitmask validation, reflect careful engineering for both performance and flexibility.&lt;/p&gt;



&lt;p&gt;Whether you’re building a multiplatform application that needs consistent serialization across JVM, JS, and Native, implementing custom serializers for complex API responses, or simply curious about how your&amp;nbsp;&lt;code&gt;@Serializable&lt;/code&gt;&amp;nbsp;classes become working serializers, this knowledge provides the foundation for working effectively with one of Kotlin’s most important libraries.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Running custom built paywalls alongside RevenueCat Paywalls]]></title><description><![CDATA[How to combine custom builts paywalls with RevenueCat paywalls for flexible experiments, targeted offers, and complex user journeys.]]></description><link>https://www.revenuecat.com/blog/engineering/running-custom-paywalls-alongside-revenuecat-paywalls/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/running-custom-paywalls-alongside-revenuecat-paywalls/</guid><pubDate>Tue, 10 Feb 2026 14:24:01 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Blog_22_Running-your-own-paywall-and-RC-paywall-together.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;RevenueCat paywall offers powerful customization of paywalls that render full native views. However, there might be situations where you want to implement your own custom paywall while still leveraging RevenueCat to manage entitlements, offers and packages. This blog post will guide you through how to effectively run your custom paywall alongside a RevenueCat-powered paywall.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-run-multiple-paywalls&quot;&gt;Why run multiple paywalls?&lt;/h2&gt;



&lt;p&gt;You might be wondering why you’d want to manage multiple paywalls simultaneously. Here are a few scenarios where this approach can be highly beneficial:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Transition periods:&lt;/strong&gt; You might have built a custom paywall before and are interested in progressively moving away from it to RevenueCat paywalls.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;A/B testing: &lt;/strong&gt;You have your existing hard coded paywall, and you’ve now built a new paywall in RevenueCat that you want to test against.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Targeted offers:&lt;/strong&gt; For specific user segments, you might have unique pricing or promotional offers that require a highly customized presentations,&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Advanced logic:&lt;/strong&gt; For complex onboarding flows or specific user journeys&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Your app  decides which paywall UI to show, but all purchases still flow through the RevenueCat SDK. This avoids duplicated logic, pricing mismatches, and entitlement bugs while giving you full control over presentation when needed.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-example-end-to-end-flow-with&quot;&gt;Example end-to-end flow with &lt;/h3&gt;



&lt;p&gt;At a high level, an app with two different paywall types functions like this:&lt;/p&gt;



&lt;ol start=&quot;1&quot; class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;User reaches a paywall decision point&lt;/strong&gt;
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;For example: end of onboarding, feature gate, or promotional entry point&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;App requests Offerings for a specific Placement&lt;/strong&gt;
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;The Placement represents &lt;em&gt;where&lt;/em&gt; the paywall is shown in the user journey&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;RevenueCat returns the appropriate Offering&lt;/strong&gt;
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;The returned Offering may vary per user based on targeting rules&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;App inspects Offering metadata&lt;/strong&gt;
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Metadata determines which paywall should be displayed&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;App chooses a paywall UI&lt;/strong&gt;
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;RevenueCat paywall UI&lt;/li&gt;



&lt;li&gt;Or a fully custom built paywall UI&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;User selects a product&lt;/strong&gt;
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Product and pricing data always come from RevenueCat&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Purchase is initiated via the RevenueCat SDK&lt;/strong&gt;
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Identical purchase flow regardless of paywall UI&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;RevenueCat updates entitlements&lt;/strong&gt;
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;App unlocks or restricts content based on CustomerInfo&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;This keeps presentation flexible while keeping the subscription system centralized and consistent. If you make use of RevenueCat’s Experiment feature, you can even test and compare how the different placements and paywalls perform in conversions.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-understanding-revenuecat-paywalls&quot;&gt;Understanding RevenueCat Paywalls&lt;/h2&gt;



&lt;p&gt;RevenueCat’s paywalls are designed to simplify the process of displaying your products to users. As outlined in the &lt;a href=&quot;https://www.revenuecat.com/docs/tools/paywalls&quot;&gt;RevenueCat Paywalls documentation&lt;/a&gt;, they allow you to create, manage, and test different paywall designs directly within the RevenueCat dashboard. They handle the fetching of product information and present it in a user-friendly way. All this without having to create new releases of your app when you make changes to your paywall.&lt;/p&gt;



&lt;p&gt;For most new apps, implementing your paywall with RevenueCat is the best choice, allowing you to iterate and update your paywall without having to push new releases of your app to stores.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-implementing-a-custom-built-paywall&quot;&gt;Implementing a custom built paywall&lt;/h2&gt;



&lt;p&gt;As mentioned earlier, there are cases when RevenueCat paywalls might not be enough. One such case could for example a key design element in your app that you want to also show in your paywalls. In a gamified app this could be for example a broken streak visualisation, that you want to surface in the paywall to communicate to the customer that subscription would allow them to amend the broken streak.&lt;/p&gt;



&lt;p&gt;When you decide to implement a custom built paywall, you’re essentially taking control of the UI/UX. However, you’ll still rely on RevenueCat SDK for the backend operations: fetching product information and making purchases.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-1-fetching-product-information&quot;&gt;Step 1: Fetching Product Information&lt;/h3&gt;



&lt;p&gt;The first step in your custom built paywall implementation is to fetch the product information from RevenueCat. This is crucial for displaying the correct subscription options, prices, and introductory offers to your users. Refer to the &lt;a href=&quot;https://www.revenuecat.com/docs/getting-started/displaying-products&quot;&gt;Displaying Products documentation&lt;/a&gt; for detailed instructions.&lt;/p&gt;



&lt;p&gt;In Swift, you’ll typically use the &lt;code&gt;Purchases.shared.getOfferings()&lt;/code&gt; method to retrieve your configured offerings. Similarly, on Kotlin, you’ll use&lt;code&gt; Purchases.sharedInstance.getOfferingsWith&lt;/code&gt;(). &lt;br&gt;&lt;br&gt;This will provide you with the Offering object, which contains all the necessary product details:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z2ooqIF wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;swift&quot; content=&quot;&amp;quot;        Purchases.shared.getOfferings { (offerings, error) in\n            if let packages = offerings?.current?.availablePackages {\n                self.display(packages)\n            }\n        }&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;

&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1oMGYv wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;Purchases.sharedInstance.getOfferingsWith({ error -&gt;\n  \/\/ An error occurred\n}) { offerings -&gt;\n  offerings.current?.availablePackages?.takeUnless { it.isNullOrEmpty() }?.let {\n    \/\/ Display packages for sale\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-2-making-purchases&quot;&gt;Step 2: making purchases&lt;/h3&gt;



&lt;p&gt;Once a user selects a product on your custom built paywall, you’ll use RevenueCat’s SDK to initiate the purchase. The &lt;a href=&quot;https://www.revenuecat.com/docs/getting-started/making-purchases&quot;&gt;Making Purchases documentation&lt;/a&gt; provides comprehensive guidance on this.&lt;/p&gt;



&lt;p&gt;On iOS, you’ll use &lt;code&gt;Purchases.shared.purchase(package:)&lt;/code&gt;, and on Android, &lt;code&gt;Purchases.sharedInstance.purchaseWith()&lt;/code&gt;. Remember to handle the purchase completion and any potential errors.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-2dAElt wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;swift&quot; content=&quot;&amp;quot;Purchases.shared.purchase(package: package) { (transaction, customerInfo, error, userCancelled) in\n  if customerInfo.entitlements[\&amp;quot;your_entitlement_id\&amp;quot;]?.isActive == true {\n    \/\/ Unlock \&amp;quot;pro\&amp;quot; content              \n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;

&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1JLYCI wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;Purchases.sharedInstance.purchaseWith(\n  PurchaseParams.Builder(this, aPackage).build(),\n  onError = { error, userCancelled -&gt; \/* No purchase *\/ },\n  onSuccess = { storeTransaction, customerInfo -&gt;\n    if (customerInfo.entitlements[\&amp;quot;my_entitlement_identifier\&amp;quot;]?.isActive == true) {\n      \/\/ Unlock \&amp;quot;pro\&amp;quot; content\n    }\n  }\n)&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-3-entitlement-management&quot;&gt;Step 3: Entitlement Management&lt;/h3&gt;



&lt;p&gt;Regardless of whether you use a RevenueCat paywall or a custom one, RevenueCat will handle entitlement management. After a successful purchase, RevenueCat will update the user’s CustomerInfo, which you can then use to grant or restrict access to premium features. In Swift you can do this using the  &lt;code&gt;Purchases.shared.customerInfo()&lt;/code&gt;&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1AiDY2 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;swift&quot; content=&quot;&amp;quot;Purchases.shared.getCustomerInfo { (customerInfo, error) in\n    \/\/ access latest customerInfo\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;In Kotlin &lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z13h99t wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;Purchases.sharedInstance.getCustomerInfoWith(\n    onError = { error -&gt; \/* Optional error handling *\/ },\n    onSuccess = { customerInfo -&gt; \/* Access latest customerInfo *\/ },\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-conditional-display-logic-for-paywalls&quot;&gt;Conditional display logic for paywalls&lt;/h2&gt;



&lt;p&gt;You can control the logic for showing different paywalls and offerings using either &lt;strong&gt;Placement&lt;/strong&gt; or &lt;strong&gt;Offering metadata&lt;/strong&gt;. With Placement you can define where each type offering is shown, and with Offering medata you can attach additional information to the offering that is then used in the app to differentiate between showing a custom built paywall or a RevenueCat paywall.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-targeting-by-placement&quot;&gt;&lt;strong&gt;Targeting by Placement&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Using Targeting by Placement you can define paywalls locations in your app to serve unique Offerings at each paywall location.&amp;nbsp;This could mean for example displaying a different paywall at the following different locations:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;At the end of onboarding (e.g.&amp;nbsp;&lt;code&gt;onboarding_end&lt;/code&gt;)&lt;/li&gt;



&lt;li&gt;When a customer attempts to use a paywalled feature (e.g.&amp;nbsp;&lt;code&gt;feature_gate&lt;/code&gt;)&lt;/li&gt;



&lt;li&gt;When a sale is running (e.g.&amp;nbsp;&lt;code&gt;sale_offer&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The basis for deciding Placements is to understand how they would compliment your ideal customer journey. If you’re running a sale, you most likely want to show a different offer and copy to onboarded customers, compared to those using the app for first time. Do this by defining a &lt;code&gt;sale_offer&lt;/code&gt; placement.&lt;/p&gt;



&lt;p&gt;When your app fetches Offerings by Placement, RevenueCat returns the Offering to be displayed for that customer at that Placement, letting you display unique paywalls based on the customer journey. In Swift you can accomplish this in the following way:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1bp9Gs wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;swift&quot; content=&quot;&amp;quot;Purchases.shared.getOfferings { offerings, error in\n    if let offering = offerings?.currentOffering(forPlacement: \&amp;quot;your_placement_identifier\&amp;quot;) {\n        \/\/ Show paywall\n    } else {\n        \/\/ Do nothing or continue on to next view\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Similarly in Kotlin:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZoGjpt wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;Purchases.sharedInstance.getOfferingsWith({ error -&gt;\n    \/\/ An error occurred\n}) { offerings -&gt;\n    offerings.getCurrentOfferingForPlacement(\&amp;quot;your-placement-identifier\&amp;quot;)?.let {\n        \/\/ show paywall\n    } ?: run {\n        \/\/ Do nothing or continue on to next view\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-targeting-using-offering-metadata-nbsp&quot;&gt;Targeting using &lt;strong&gt;Offering metadata&amp;nbsp;&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The key to running different types of paywalls and customizing what is shown in your custom built paywall is &lt;strong&gt;Offering metadata&lt;/strong&gt;. In the RevenueCat dashboard you can add valid JSON in to the &lt;strong&gt;Metadata&lt;/strong&gt; field, by navigating to an Offering and clicking &lt;strong&gt;Edit&lt;/strong&gt; or &lt;strong&gt;Configure metadata&lt;/strong&gt; (in case you haven’t configured metadata yet):&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;596&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-11-1024x596.png&quot; alt=&quot;&quot; class=&quot;wp-image-51006&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-11-1024x596.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-11-300x175.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-11-768x447.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-11-1536x894.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-11-50x29.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-11-69x40.png 69w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-11-696x405.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-11-560x326.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-11-509x296.png 509w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-11-811x472.png 811w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-11-80x47.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-11-48x28.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-11.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Metadata that you configure in the dashboard could look like this for example:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1IVB3h wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;{\n  \&amp;quot;custom_paywall\&amp;quot;: true,\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This metadata is attached to the Offering data when you call the SDK to get available Offerings. You can then use it to dynamically make changes to how paywalls are displayed in your app.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-using-offering-metadata-with-the-sdk&quot;&gt;Using Offering metadata with the SDK&lt;/h3&gt;



&lt;p&gt;You can access metadata directly from the Offering object in RevenueCat SDK using the offerings method in Swift&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZSlcmJ wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;swift&quot; content=&quot;&amp;quot;do {\n    let offerings = try await Purchases.shared.offerings()\n\n    if let offering = offerings.current {\n        let useCustomPaywall = offering.metadata[\&amp;quot;custom_paywall\&amp;quot;] as? Bool\n\n        if useCustomPaywall == true {\n            \/\/ Show custom paywall UI\n        } else {\n            \/\/ Show RevenueCat Paywalls UI\n        }\n    }\n} catch {\n    \/\/ An error occurred\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;and in Kotlin with the same method:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1Nord7 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;Purchases.sharedInstance.getOfferingsWith({ error -&gt;\n    \/\/ An error occurred\n}) { offerings -&gt;\n    offerings.current?.let { offering -&gt;\n        val useCustomPaywall = offering.metadata[\&amp;quot;custom_paywall\&amp;quot;] as? Boolean\n\n        if (useCustomPaywall == true) {\n            \/\/ Show custom built paywall UI\n        } else {\n            \/\/ Show RevenueCat Paywalls UI\n        }\n    }&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;&lt;br&gt;Metadata values are optional by nature, so all access should be built so that your app and paywalls still work even if the values are not defined in the dashboard.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-example-conditional-logic-nbsp&quot;&gt;Example Conditional Logic&amp;nbsp;&lt;/h3&gt;



&lt;p&gt;Now the last remaining step is to use the logic for showing your custom built paywall or a RevenueCat paywall:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1dAXwP wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;swift&quot; content=&quot;&amp;quot;func shouldShowCustomPaywall(offering: Offering) -&gt; Bool {\n    offering.getMetadataValue(for: \&amp;quot;custom_paywall\&amp;quot;, default: false)\n}\n\nfunc showPaywall(for offering: Offering) {\n    if shouldShowCustomPaywall(offering: offering) {\n        \/\/ Show your custom paywall UI\n        displayCustomPaywall(offering: offering)\n    } else {\n        \/\/ Show RevenueCat&apos;s default paywall or a paywall built with RevenueCat&apos;s templates\n        displayRevenueCatPaywall(offering: offering)\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;and in Kotlin:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1G66VA wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\nfun shouldShowCustomPaywall(offering: Offering): Boolean {\n    return offering.metadata[\&amp;quot;custom_paywall\&amp;quot;] as? Boolean ?: false\n}\n\nfun showPaywall(offering: Offering) {\n    if (shouldShowCustomPaywall(offering)) {\n        \/\/ Show your custom paywall UI\n        displayCustomPaywall(offering)\n    } else {\n        \/\/ Show RevenueCat&apos;s default paywall or a paywall built with RevenueCat&apos;s templates\n        displayRevenueCatPaywall(offering)\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-conclusion&quot;&gt;Conclusion&lt;/h2&gt;



&lt;p&gt;Running your own custom built paywall alongside a RevenueCat paywall provides flexibility for experimentation and targeted offers. By leveraging RevenueCat for product fetching and purchase management, and your engineering skills for custom UI, you can create a highly optimized and engaging subscription experience for your iOS and Android users. This hybrid approach empowers you to maintain control over the front-end presentation while relying on a robust, battle-tested backend for your subscription infrastructure.&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[R.I.P. toggle paywall: we hardly knew ye]]></title><description><![CDATA[Apple is now rejecting apps that use a free trial toggle on their paywalls. Here's the story of the toggle, why it's being killed, and what to build instead]]></description><link>https://www.revenuecat.com/blog/growth/rip-toggle-paywall/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/rip-toggle-paywall/</guid><pubDate>Mon, 09 Feb 2026 15:34:08 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/rip-toggle-paywall-header-21.jpg" length="0" type="image/*"/><content:encoded>&lt;p&gt;&lt;em&gt;UPDATE: APRIL 23, 2026&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;As &lt;a href=&quot;https://x.com/alpennec/status/2047218943333482976&quot;&gt;Axel Le Pennec (@alpennec) pointed out on X&lt;/a&gt;, it seems subscription giant &lt;a href=&quot;https://www.youtube.com/watch?v=EenRStcmZvw&quot;&gt;Flo Health&lt;/a&gt; has found an alternative to the toggle paywall, which appears to be compliant with the latest Apple Guidelines. &lt;/p&gt;



&lt;p&gt;Flo have replaced their “Enable free trial” toggle with a specific 14-day free trial plan option when showing a multi-plan paywall. Keeping the same “Not sure yet?” copy, this feels like the closest subscription apps can get to matching user intent within this paywall moment, while staying within the guidelines Apple has set.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;576&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/image-1-1024x576.png&quot; alt=&quot;&quot; class=&quot;wp-image-53364&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/image-1-1024x576.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/image-1-300x169.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/image-1-768x432.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/image-1-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/image-1-71x40.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/image-1-696x392.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/image-1-560x315.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/image-1-526x296.png 526w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/image-1-840x472.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/image-1-80x45.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/image-1-48x27.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/image-1.png 1200w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Credit: Axel Le Pennec&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;p&gt;It started with a few whispers, then a handful of tweets. Now, it’s a full-blown trend we can’t ignore. Over the past few weeks, we’ve had several industry figures reach out to us, all asking some version of the same question: “Is Apple killing the toggle paywall?”&lt;/p&gt;



&lt;p&gt;Short answer: yes. It sure looks like it&lt;/p&gt;



&lt;p&gt;Developer after developer is getting the same rejection notice from App Review, and it’s always about the same thing: a paywall design that includes a toggle to turn a free trial on or off. If you’re using this pattern on iOS, you need to pay attention. This isn’t a drill&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-is-the-toggle-paywall&quot;&gt;What is the toggle paywall?&lt;/h2&gt;



&lt;p&gt;For the uninitiated: the “toggle paywall” is a paywall design where users are presented with a subscription offer and a toggle switch that lets them add or remove a free trial. In most implementations, the toggle defaults to &lt;strong&gt;off&lt;/strong&gt; – meaning the user sees a plan without a trial. If they flip the switch, they get a different plan (usually weekly instead of annual) that includes a trial period&lt;/p&gt;



&lt;p&gt;The mechanic was popularized by &lt;a href=&quot;https://x.com/adamlyttleapps&quot;&gt;Adam Lyttle&lt;/a&gt; in mid-2024, when he documented how implementing this exact design &lt;a href=&quot;https://www.youtube.com/watch?v=5w3k1Z6ZQzQ&quot;&gt;doubled his weekly app revenue from ~$2,500 to over $5,300&lt;/a&gt;. The numbers were staggering. His introductory offer conversion rate hit 63%, and subscription retention sat at 68%&lt;/p&gt;



&lt;p&gt;It was a masterclass in behavioral psychology. The toggle defaulted to “off,” with the cheaper-looking annual plan pre-selected. Users who wanted the free trial had to actively flip the switch, which then moved them to the more expensive weekly plan. Many users, seeing the lower annual price, would just hit “continue” without toggling, skipping the trial entirely and paying upfront. The result? A massive boost in immediate revenue and a higher average revenue per user (ARPU)&lt;/p&gt;



&lt;p&gt;It was so effective that it spread like wildfire. Within months, you could see variations of the toggle paywall in apps across the App Store. It became &lt;em&gt;the&lt;/em&gt; go-to strategy for developers looking to juice their monetization. We even featured it in our own &lt;a href=&quot;https://www.revenuecat.com/blog/growth/paywall-redesigns-case-studies/&quot;&gt;paywall redesign case studies&lt;/a&gt;, where one app saw a 17% boost in ARPU and another saw a 64% uplift in revenue after implementing it&lt;/p&gt;



&lt;p&gt;But here’s the thing about patterns that feel a little &lt;em&gt;too&lt;/em&gt; effective: eventually, the platforms catch on&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-rejection-wave&quot;&gt;The rejection wave&lt;/h2&gt;



&lt;p&gt;Starting in mid-January 2026, the rejections started rolling in. &lt;a href=&quot;https://x.com/alpennec/status/2012188049728520514&quot;&gt;Axel Le Pennec&lt;/a&gt; was one of the first to post about it publicly, sharing a screenshot of Apple’s rejection notice along with a resigned “My app got rejected for that”. Adam Lyttle himself – the man who popularized the pattern – quote-tweeted it the very next day with a simple, three-word eulogy: &lt;a href=&quot;https://x.com/adamlyttleapps/status/2012661782771622234&quot;&gt;“RIP paywall toggle”&lt;/a&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;a href=&quot;https://x.com/alpennec/status/2012188049728520514&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/tweet-2012188049728520514-1-1024x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-51088&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/tweet-2012188049728520514-1-1024x1024.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/tweet-2012188049728520514-1-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/tweet-2012188049728520514-1-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/tweet-2012188049728520514-1-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/tweet-2012188049728520514-1-1536x1536.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/tweet-2012188049728520514-1-2048x2048.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/tweet-2012188049728520514-1-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/tweet-2012188049728520514-1-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/tweet-2012188049728520514-1-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/tweet-2012188049728520514-1-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/tweet-2012188049728520514-1-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/tweet-2012188049728520514-1-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/tweet-2012188049728520514-1-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/tweet-2012188049728520514-1-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/tweet-2012188049728520514-1-48x48.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/a&gt;&lt;/figure&gt;



&lt;p&gt;Since then, the reports have kept coming. &lt;a href=&quot;https://x.com/Aivars_Meijers/status/2017228629076537604&quot;&gt;Aivars Meijers&lt;/a&gt;, &lt;a href=&quot;https://x.com/seraleev/status/2017597018948895034&quot;&gt;Sergey&lt;/a&gt;, &lt;a href=&quot;https://x.com/ingoa_dev/status/2018612339294257228&quot;&gt;Ingo&lt;/a&gt;, and &lt;a href=&quot;https://x.com/FancyWoodPigeon/status/2019145526894026914&quot;&gt;others&lt;/a&gt; have all shared their rejection stories. A &lt;a href=&quot;https://www.reddit.com/r/AppStoreOptimization/comments/1qeavxq/anyone_else_having_apple_reject_their_app_because/&quot;&gt;Reddit thread&lt;/a&gt; about it has dozens of developers confirming the same experience. It’s not an isolated incident – it’s a pattern&lt;/p&gt;



&lt;p&gt;The rejection notice from Apple is brutally clear:&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Guideline 3.1.2 – Business – Payments – Subscriptions&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;The purchase screen includes a toggle to add or remove a free trial from the subscription purchase. This design is confusing and may prevent users from understanding that they are committing to an auto-renewing subscription that will begin charging them after the free trial period.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Next Steps:&lt;/strong&gt; Remove the toggle for adding or removing a free trial from the subscription purchase screen. Users should be presented with a clear subscription offer that explicitly states whether a free trial is included.&lt;/p&gt;



&lt;p&gt;No ambiguity there&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-now&quot;&gt;Why now?&lt;/h2&gt;



&lt;p&gt;So why is Apple cracking down on this &lt;em&gt;now&lt;/em&gt;, after the pattern has been in wide use for over a year?&lt;/p&gt;



&lt;p&gt;The honest answer is: we’re not 100% sure. Apple hasn’t published an explicit policy update or blog post about it. But we can connect a few dots&lt;/p&gt;



&lt;p&gt;First, Apple has been on a broader mission to clean up subscription practices for a while. Their &lt;a href=&quot;https://developer.apple.com/app-store/review/guidelines/#subscriptions&quot;&gt;guidelines on subscriptions&lt;/a&gt; (3.1.2) have always emphasized transparency, and their scam-prevention rules (3.1.2(a)) specifically call out apps that “trick users into purchasing a subscription under false pretenses” [10]. The toggle, with its default-off state, arguably falls into that bucket. A free trial that you have to &lt;em&gt;opt into&lt;/em&gt; via a hidden toggle is, from Apple’s perspective, a trial that most users will never see – which defeats the purpose of offering one&lt;/p&gt;



&lt;p&gt;Second, the pattern became &lt;em&gt;too&lt;/em&gt; popular. When a handful of indie apps use a clever design, it flies under the radar. When thousands of apps across the store are using the same mechanic- and when YouTube videos about it are racking up tens of thousands of views – it gets noticed. Apple’s App Review team is clearly aware of the trend, and they’ve decided it crosses the line&lt;/p&gt;



&lt;p&gt;Third, and perhaps most importantly: users were getting confused. The whole point of the toggle was that many users &lt;em&gt;wouldn’t&lt;/em&gt; toggle it. That’s not transparency – that’s obfuscation. And Apple, whatever you think of their policies, has a legitimate interest in making sure users understand what they’re signing up for&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-plot-twist-it-s-only-dead-on-ios&quot;&gt;The plot twist: It’s only dead on iOS&lt;/h2&gt;



&lt;p&gt;Okay, so the toggle paywall is dead. Pour one out. We hardly knew ye&lt;/p&gt;



&lt;p&gt;But wait – it’s dead &lt;em&gt;on iOS&lt;/em&gt;. And that’s an important distinction&lt;/p&gt;



&lt;p&gt;As of today, there is &lt;strong&gt;no indication that Google has any issue with this design&lt;/strong&gt;. The same goes for web-based paywalls. If you’re running a multi-platform app, the toggle might still be a viable, high-performing strategy on Android and the web&lt;/p&gt;



&lt;p&gt;This is where having a flexible, remotely configurable paywall setup becomes essential. With a tool like &lt;a href=&quot;https://www.revenuecat.com&quot;&gt;RevenueCat&lt;/a&gt;, you can use &lt;a href=&quot;https://www.revenuecat.com/docs/tools/targeting&quot;&gt;Targeting&lt;/a&gt; to display one paywall on iOS (compliant, toggle-free) and another on Google Play or the web (the classic, high-ARPU toggle design). Don’t throw the baby out with the bathwater – just make sure you’re showing the right paywall on the right platform&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-to-test-instead&quot;&gt;What to test instead&lt;/h2&gt;



&lt;p&gt;So, what’s an iOS developer to do? Get back to the drawing board. The good news is that there are plenty of high-converting, fully compliant paywall designs to test. And some of them might actually convert &lt;em&gt;better&lt;/em&gt; than the toggle ever did&lt;/p&gt;



&lt;p&gt;Here are the patterns we’d recommend testing first:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-the-honest-timeline-paywall&quot;&gt;1. The “honest” timeline paywall&lt;/h3&gt;


&lt;div class=&quot;wp-block-image&quot;&gt;
&lt;figure class=&quot;alignright size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;462&quot; height=&quot;1000&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/blinkist_pw.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-51106&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/blinkist_pw.jpg 462w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/blinkist_pw-139x300.jpg 139w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/blinkist_pw-23x50.jpg 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/blinkist_pw-18x40.jpg 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/blinkist_pw-214x464.jpg 214w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/blinkist_pw-259x560.jpg 259w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/blinkist_pw-137x296.jpg 137w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/blinkist_pw-218x472.jpg 218w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/blinkist_pw-37x80.jpg 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/blinkist_pw-22x48.jpg 22w&quot; sizes=&quot;auto, (max-width: 462px) 100vw, 462px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;The famous ‘Blinkist paywall’&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;/div&gt;


&lt;p&gt;This design, popularized by Blinkist, shows a clear, step-by-step timeline of what happens after the user taps “Start Free Trial.” Something like: &lt;strong&gt;Today: Full Access → Day 5: Reminder → Day 7: You’re Charged.&lt;/strong&gt; Blinkist reported a 23% increase in conversion rate and a 55% drop in complaints after implementing this pattern. It builds immense trust, and in many cases, trust converts better than tricks&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-the-multi-package-selector&quot;&gt;2. The multi-package selector&lt;/h3&gt;



&lt;p&gt;Instead of toggling a trial on and off, present multiple subscription packages side by side – say, weekly, monthly, and annual. Badge the one that includes a trial. Users select the package they want; no toggle needed. The trial is inherent to the package, not a separate mechanic. This uses classic price anchoring to make the annual plan (with the trial) the obvious choice&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-the-value-first-paywall&quot;&gt;3. The value-first paywall&lt;/h3&gt;



&lt;p&gt;This approach front-loads the value proposition. Strong visuals, benefit-oriented copy, social proof, App Store ratings – all before the user ever sees a price. When users are genuinely convinced of the value, the friction of payment decreases significantly. Shift the conversation from “how much does it cost?” to “what am I getting?”&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-4-personalized-paywalls-with-conditional-visibility&quot;&gt;4. Personalized paywalls with conditional visibility&lt;/h3&gt;



&lt;p&gt;This is the more sophisticated play. Use conditional logic to show different paywall content based on user attributes – like whether they’re eligible for an introductory offer. If they are, show trial messaging prominently. If they’re not, show a direct purchase flow. No toggle required, and the experience is tailored to each user. RevenueCat supports this through &lt;a href=&quot;https://www.revenuecat.com/docs/tools/targeting&quot;&gt;Targeting&lt;/a&gt; and conditional visibility in our &lt;a href=&quot;https://www.revenuecat.com/paywalls/&quot;&gt;paywall builder&lt;/a&gt;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-5-the-exit-offer&quot;&gt;5. The exit offer&lt;/h3&gt;


&lt;div class=&quot;wp-block-image&quot;&gt;
&lt;figure class=&quot;alignright size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;462&quot; height=&quot;1000&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/duolingo_pw.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-51109&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/duolingo_pw.jpg 462w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/duolingo_pw-139x300.jpg 139w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/duolingo_pw-23x50.jpg 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/duolingo_pw-18x40.jpg 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/duolingo_pw-214x464.jpg 214w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/duolingo_pw-259x560.jpg 259w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/duolingo_pw-137x296.jpg 137w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/duolingo_pw-218x472.jpg 218w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/duolingo_pw-37x80.jpg 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/duolingo_pw-22x48.jpg 22w&quot; sizes=&quot;auto, (max-width: 462px) 100vw, 462px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Duolingo has been experimenting with a ‘web purchase-first’ paywall design&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;/div&gt;


&lt;p&gt;What if you could get a second chance to convert a user who’s about to leave? That’s the idea behind an exit offer. When a user dismisses your paywall, instead of just closing the screen, you can present them with a different, often better, offer. Think a lower price, a longer trial, or a monthly plan after they’ve rejected an annual one&lt;/p&gt;



&lt;p&gt;We just shipped this feature in our Paywall Builder. It’s all configured remotely, no code changes needed. It’s a great way to capture intent that would otherwise be lost. But be careful: Apple is also getting stricter on instant paywall abandonment offers, so test this one carefully and make sure it doesn’t feel like you’re trapping the user&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-6-the-web-purchase-button&quot;&gt;6. The web purchase button&lt;/h3&gt;



&lt;p&gt;Here’s a curveball: route your US-based iOS users to a web checkout entirely. You avoid Apple’s 30% commission, you have full control over the purchase flow, and you can design whatever paywall you want – toggle included – because Apple’s App Store guidelines don’t apply to web purchases. Note that you still have to include in-app purchases in your in-app screen, but you can offer a discount on web (or increase your prices in-app) to nudge people towards the web option. We’ve shipped a &lt;a href=&quot;https://www.revenuecat.com/blog/growth/meet-the-web-paywall-button/&quot;&gt;Web Checkout Button&lt;/a&gt; component that makes this easy to test. The results have been… &lt;a href=&quot;https://www.revenuecat.com/blog/growth/meet-the-web-paywall-button/&quot;&gt;interesting&lt;/a&gt;.&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;Alternative&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;Key benefit&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;Compliance risk&lt;/strong&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Timeline / “Honest” Paywall&lt;/td&gt;&lt;td&gt;Builds trust, reduces refunds, proven conversion lift&lt;/td&gt;&lt;td&gt;None&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Multi-Package Selector&lt;/td&gt;&lt;td&gt;Clear, uses price anchoring, no toggle needed&lt;/td&gt;&lt;td&gt;None&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Value-First Paywall&lt;/td&gt;&lt;td&gt;Shifts focus from price to value&lt;/td&gt;&lt;td&gt;None&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Personalized / Conditional Paywalls&lt;/td&gt;&lt;td&gt;Tailored experience per user segment&lt;/td&gt;&lt;td&gt;None&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Exit Offer&lt;/td&gt;&lt;td&gt;Second chance to convert abandoning users&lt;/td&gt;&lt;td&gt;Low (if not overly aggressive)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Web Purchase Button&lt;/td&gt;&lt;td&gt;Full design freedom, avoids 30% commission&lt;/td&gt;&lt;td&gt;None (web rules apply)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;The key is to start experimenting &lt;strong&gt;now&lt;/strong&gt;. Don’t wait for your next app update to get rejected. Proactively test these alternatives and find a new champion for your iOS paywall&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-one-more-thing&quot;&gt;One more thing&lt;/h2&gt;



&lt;p&gt;Here’s an interesting data point that might ease the pain. Ludwig Henne, founder of Fits, ran an A/B test comparing a Adam Lyttle-style toggle paywall against a Blinkist-style honest paywall. The toggle paywall won on ARPU (+19%), but when he isolated the toggle mechanic specifically, he found that &lt;strong&gt;the toggle itself wasn’t the main driver&lt;/strong&gt;. The real conversion lift came from the visual hierarchy: normalized yearly pricing, a “Most Popular” badge, and a larger UI for the annual plan&lt;/p&gt;



&lt;p&gt;In other words, you might be able to remove the toggle and keep most of the revenue gains – as long as you maintain the other design elements that made the paywall effective. The toggle was the headline act, but the supporting cast was doing most of the heavy lifting&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-end-of-an-era&quot;&gt;The end of an era&lt;/h2&gt;



&lt;p&gt;The death of the toggle paywall on iOS marks the end of an era. It was a wild ride, and it made a lot of developers a lot of money. But the App Store is Apple’s house, and they make the rules&lt;/p&gt;



&lt;p&gt;Ultimately, this is probably a good thing for users. And what’s good for users is, in the long run, good for the ecosystem. It forces all of us to be more creative, more transparent, and more focused on communicating the genuine value of our products. The best paywalls have always been the ones that make users &lt;em&gt;want&lt;/em&gt; to subscribe, not the ones that trick them into it&lt;/p&gt;



&lt;p&gt;So pour one out for the toggle paywall. And then get back to testing&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;A loving note from our editor:&lt;/strong&gt;&amp;nbsp;you may have noticed this blog post is missing periods at the end of many paragraphs. Please don’t be thrown off or think we haven’t spotted this; it is simply the signature trademark of Rik Haandrikman, VP of Marketing at RevenueCat.&lt;/em&gt;&amp;nbsp;&lt;em&gt;For more of his antics,&amp;nbsp;&lt;a href=&quot;https://x.com/HHaandr&quot;&gt;follow Rik on X&lt;/a&gt;&amp;nbsp;(you’ll know you’ve found the right account when you stop seeing periods).&lt;/em&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[RevenueCat React Native SDK adds React Native Web support]]></title><description><![CDATA[react-native-purchases gets web support; single code-base for subscriptions on three different platforms.]]></description><link>https://www.revenuecat.com/blog/engineering/revenuecat-react-native-sdk-adds-react-native-web-support/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/revenuecat-react-native-sdk-adds-react-native-web-support/</guid><pubDate>Mon, 09 Feb 2026 11:13:50 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Blog_21_RevenueCat-React-Native-SDK-adds-React-Native-Web-support.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Starting from release &lt;a href=&quot;https://github.com/RevenueCat/react-native-purchases/releases/tag/9.7.6&quot;&gt;9.7.6 of react-native-purchases&lt;/a&gt;, teams building with React Native can manage subscriptions across iOS, Android, and web using the same SDK and the same RevenueCat entitlements system. If your app already runs on mobile and you’re extending it to the web — or you’re starting with a shared codebase from day one —&amp;nbsp;this makes it easier to support subscriptions everywhere without rethinking your architecture.&lt;/p&gt;



&lt;p&gt;Add react-native-purchases to your Expo or React Native project, and you have power subscriptions, in-app purchases, entitlement management  on three different platforms with a single code-base.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-we-built-this&quot;&gt;&lt;strong&gt;Why we built this&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;As more React Native apps expand beyond mobile, the web has become part of the product rather than just a marketing surface. Teams want users to sign up, upgrade, or manage subscriptions in a browser, while still unlocking access inside their iOS and Android apps. Until now, that often meant maintaining a separate billing system for web and stitching everything together with custom logic.&lt;/p&gt;



&lt;p&gt;React Native Web support removes that split. Web purchases flow into the same RevenueCat backend as native purchases, so you can rely on a single entitlements system instead of reconciling multiple sources of truth.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-billing-works-on-web&quot;&gt;&lt;strong&gt;How billing works on web&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;On iOS and Android, RevenueCat integrates directly with the App Store and Google Play. On the web, purchases are handled through &lt;strong&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/web/web-billing/overview&quot;&gt;RevenueCat Web Billing&lt;/a&gt;&lt;/strong&gt;, which uses Stripe or Paddle as the payment processor.  Web Billing is separate from native in-app purchases, but it connects to the same entitlements system, making it possible to grant access across platforms using a shared appUserID.&lt;/p&gt;



&lt;p&gt;From your app’s perspective, subscription state stays consistent regardless of where a user originally subscribed. A customer who signs up on the web can immediately access premium features on mobile, without you needing to write platform-specific logic.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-getting-started-with-react-native-web&quot;&gt;&lt;strong&gt;Getting started with React Native Web&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Enabling React Native Web support starts with configuring RevenueCat using the appropriate API key for each platform. When your app runs on the web, you’ll initialize the SDK with a Web Billing public API key, while iOS and Android continue to use their native keys.&lt;/p&gt;



&lt;p&gt;Here’s what that looks like in practice:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1oeQQt wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;import { Platform } from &apos;react-native&apos;;\nimport Purchases from &apos;react-native-purchases&apos;;\n\nif (Platform.OS === &apos;web&apos;) {\n  Purchases.configure({ apiKey: &apos;&lt;public_web_billing_api_key&gt;&apos; });\n} else if (Platform.OS === &apos;ios&apos;) {\n  Purchases.configure({ apiKey: &apos;&lt;public_apple_api_key&gt;&apos; });\n} else if (Platform.OS === &apos;android&apos;) {\n  Purchases.configure({ apiKey: &apos;&lt;public_google_api_key&gt;&apos; });\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Once configured, entitlement checks work the same way across platforms. Your app logic doesn’t need to branch based on where a subscription was purchased.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1jOlnX wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;import Purchases from &apos;react-native-purchases&apos;\n\/\/ all of the following methods work on iOS, Android, and Web\n\n\/\/ Check offerings\ntry {\n  const offerings = await Purchases.getOfferings();\n  if (offerings.current !== null &amp;amp;&amp;amp; offerings.current.availablePackages.length !== 0) {\n    \/\/ Display packages for sale\n  }\n} catch (e) {\n \n}\n\n\/\/ Check entitlements\nconst customerInfo = await Purchases.getCustomerInfo();\nif(typeof customerInfo.entitlements.active[&lt;my_entitlement_identifier&gt;] !== \&amp;quot;undefined\&amp;quot;) {\n  \/\/ Grant user \&amp;quot;pro\&amp;quot; access\n}\n\n\/\/ Purchase a package\ntry {\n  const { customerInfo } = await Purchases.purchasePackage(package);\n  if (\n    typeof customerInfo.entitlements.active[\&amp;quot;my_entitlement_identifier\&amp;quot;] !==\n    \&amp;quot;undefined\&amp;quot;\n  ) {\n    \/\/ Unlock that great \&amp;quot;pro\&amp;quot; content\n  }\n} catch (e) {\n  if (!e.userCancelled) {\n    showError(e);\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;To enable web purchases, you’ll also need to create a &lt;strong&gt;Web Billing app&lt;/strong&gt; in the RevenueCat dashboard and configure your products for web. These live alongside your iOS and Android products, but are billed through Web Billing rather than native stores.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-using-expo&quot;&gt;&lt;strong&gt;Using Expo&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;If you’re building with Expo, React Native Web support also improves the development experience. You can preview subscription UI, test entitlement logic, and validate integration flows directly on the web without immediately creating a custom development client. This makes it easier to iterate early and confirm that your setup works end to end.&lt;/p&gt;



&lt;p&gt;To fully test real in-app purchases on iOS and Android, you’ll still need an Expo development build. Web support doesn’t replace that requirement, but it does remove a lot of friction during early development.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-current-limitations&quot;&gt;&lt;strong&gt;Current limitations&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Because web billing works differently from native app stores, there are a few limitations to be aware of. Web purchases require RevenueCat Web Billing and can’t process native iOS or Android in-app purchases. In addition, some operations that depend on native store APIs aren’t supported on web environments, including &lt;code&gt;getProducts&lt;/code&gt;, &lt;code&gt;purchaseProduct&lt;/code&gt;, and &lt;code&gt;restorePurchases&lt;/code&gt;. Expo Go and similar sandbox enviroments don’t support purchasing either. &lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z9jY5c wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;\/\/ this will not work on web, but works on iOS and Android:\ntry {\n  const restore = await Purchases.restorePurchases();\n  \/\/ ... check restored purchaserInfo to see if entitlement is now active\n} catch (e) {\n\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Users can manage their web subscriptions through the RevenueCat-hosted customer portal, which provides a consistent way to update or cancel subscriptions outside of native app stores.&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-s-next&quot;&gt;&lt;strong&gt;What’s next&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;As subscription apps increasingly span mobile and web, we’re continuing to invest in making cross-platform subscription management simpler and more reliable. React Native Web support is a foundation for that work, and we’ll keep improving the experience as teams push it further in production.&lt;/p&gt;



&lt;p&gt;If you’re already using RevenueCat with React Native on mobile, adding web support is now a natural next step.&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[You can still win Shipyard — multiply your changes by shipping to another brief]]></title><description><![CDATA[Multiply your changes by shipping to another brief]]></description><link>https://www.revenuecat.com/blog/engineering/you-can-still-win-shipyard/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/you-can-still-win-shipyard/</guid><pubDate>Fri, 06 Feb 2026 12:30:16 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Slice-3.jpg" length="0" type="image/*"/><content:encoded>&lt;p&gt;There are less than six days left to submit your final entry to Shipyard, and if you’re thinking you’re already too late, I have just one word for you: wrong.&lt;/p&gt;



&lt;p&gt;Even if you haven’t started building yet, there’s still enough time to get an app to beta and ship it through TestFlight or Google Play’s testing tracks. Shipyard isn’t about perfection, it’s about shipping — and a focused MVP can absolutely be competitive at this stage. And if you already have one app ready to submit, this is your chance to multiply your odds by building and submitting another app for a different brief.&lt;/p&gt;



&lt;p&gt;In this post, we’ll walk through a few of the creator briefs and explore concrete ideas for how you could realistically ship an app for each of them. The goal is to help you move from “maybe” to “shipped,” even if you’re starting late or considering a second (or third) submission.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-make-use-of-the-vibecoding-tools-included-in-the-shipping-container&quot;&gt;Make use of the vibecoding tools included in the Shipping Container&lt;/h2&gt;



&lt;p&gt;Anthropic recently released a new version of their Claude Code Opus 4.6 model, and it’s already supported by the tools included in the Shipping Container. That means you’re not just reading about more powerful AI-assisted coding, you can actually use it right now, as part of Shipyard, without any extra setup.&lt;/p&gt;



&lt;p&gt;With these tools, building an app is no longer about writing everything from scratch or spending weeks on boilerplate. You can scaffold features, iterate on UI, and explore ideas at a pace that simply wasn’t possible before. Shipyard is a perfect excuse to take these tools for a real-world test drive and see how far you can get in a single weekend with focused execution.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-briefs-that-you-could-target-nbsp&quot;&gt;Briefs that you could target&amp;nbsp;&lt;/h2&gt;



&lt;p&gt;Shipyard offers seven different creator briefs for you to choose from, and you’re allowed to submit one app for each brief. That gives you a lot of flexibility — but it also comes with a few important constraints. You can’t submit multiple apps to the same brief, and you can’t submit a single app to multiple briefs. Each submission needs to clearly map to one brief, so it’s worth being deliberate about which problems you decide to tackle.&lt;/p&gt;



&lt;p&gt;With just about a week left to build, it’s easy to assume that the window has already closed — but that’s not the case. To show what’s still possible, we’ve picked a few very different briefs and explored how you might realistically approach each of them in a short time frame. The goal isn’t to overwhelm you with ideas, but to help you see how a focused MVP can still be competitive.&lt;/p&gt;



&lt;p&gt;Whether you’re only now jumping into Shipyard, or you already have one app submitted and are considering building a second — or even a third — these examples should give you a clearer sense of how to scope your work, pick the right brief, and maximize your chances of shipping something meaningful before the deadline.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-investment-tracker-for-all-assets-josh-from-visualfaktory&quot;&gt;“Investment tracker for all assets” — Josh from VisualFaktory&lt;/h3&gt;



&lt;p&gt;&lt;em&gt;Investors juggle stocks, gold, funds, fixed income, real estate, and more across multiple platforms — messy to track and hard to understand at a glance. Josh wants a single app where users can &lt;/em&gt;&lt;strong&gt;&lt;em&gt;log everything&lt;/em&gt;&lt;/strong&gt;&lt;em&gt;, get &lt;/em&gt;&lt;strong&gt;&lt;em&gt;real-time price updates&lt;/em&gt;&lt;/strong&gt;&lt;em&gt; where possible, set &lt;/em&gt;&lt;strong&gt;&lt;em&gt;amortization/reminder alerts &lt;/em&gt;&lt;/strong&gt;&lt;em&gt;for non-listed products, and unlock &lt;/em&gt;&lt;strong&gt;&lt;em&gt;premium risk + diversification analysis&lt;/em&gt;&lt;/strong&gt;&lt;em&gt; (like country/sector exposure).&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;This brief can seem intimidating at first. Supporting many different asset types sounds complex, but it’s exactly the kind of problem modern LLMs excel at: turning messy, unstructured information into clean, usable data.&lt;/p&gt;



&lt;p&gt;A strong approach is to lean on the APIs from OpenAI, Anthropic, or Google and build an app that accepts almost any input — spreadsheets, screenshots, PDFs, or dictated descriptions — and converts them into structured assets your app can work with. The key is designing prompts that normalize the data and then visualizing it clearly. You can also use AI to analyze the portfolio and generate insights, pulling in real-time finance data when needed.&lt;/p&gt;



&lt;p&gt;On the business side, this works naturally with usage based pricing. Using RevenueCat’s virtual currencies, you could offer AI-assisted imports and advanced risk analysis as credit based features, tying monetization directly to value delivered.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-powerful-reminders-with-cross-device-sync-sam-beckman&quot;&gt;“Powerful reminders with cross-device sync.” – Sam Beckman&lt;/h3&gt;



&lt;p&gt;&lt;em&gt;Sam lives by reminders, but switching between Android and iOS means rebuilding his entire system from scratch. He wants a beautiful, fully functional reminders app on both iOS + Android* with custom snoozes from notifications, powerful recurring rules, and true sync so dismissing once clears everywhere.&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;&lt;em&gt;*For the purpose of the hackathon, you only need to build an MVP for iOS or Android&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;This brief is fundamentally about cross-platform thinking. Frameworks like Flutter, Kotlin Multiplatform, and React Native are a natural fit here — and if you’re building with React Native, you’re in especially good shape. Tools like Rork, Blink, Fastshot, Vibecode, and Replit make it surprisingly easy to scaffold and ship polished React Native apps quickly.&lt;/p&gt;



&lt;p&gt;The app itself is once again the easy part. The real challenge — and the real opportunity — lies in reminders and notifications. Doing this well requires reliable sync and state management across devices, which usually means running your own backend. Instead of building everything from scratch, you can lean on tools like Firebase or Supabase to get a real-time database, auth, and sync set up quickly, without spending your limited hackathon time on infrastructure. Supabase especially, has a really good MCP, which you can make use by telling your AI agent to set up everything there&lt;/p&gt;



&lt;p&gt;With a focused MVP, even a single-platform reminder app with rock-solid notifications and sync can stand out. Especially if it’s beautifully designed and clearly solves a problem Sam’s audience deeply cares about.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-social-app-for-van-lifers-on-the-road-quin-gable-nbsp&quot;&gt;“Social app for van-lifers on the road” — Quin Gable&amp;nbsp;&lt;/h3&gt;



&lt;p&gt;&lt;em&gt;Dating and making friends on the road is hard when you’re always moving—and van life is a tight, protective community. Quin wants a van-life app with &lt;/em&gt;&lt;strong&gt;&lt;em&gt;nomadic dating&lt;/em&gt;&lt;/strong&gt;&lt;em&gt;, &lt;/em&gt;&lt;strong&gt;&lt;em&gt;activity-based friend finding&lt;/em&gt;&lt;/strong&gt;&lt;em&gt;, and even a paid ‘&lt;/em&gt;&lt;strong&gt;&lt;em&gt;builder help’ section&lt;/em&gt;&lt;/strong&gt;&lt;em&gt; for van projects, with &lt;/em&gt;&lt;strong&gt;&lt;em&gt;invite-only or verified&lt;/em&gt;&lt;/strong&gt;&lt;em&gt; access to keep it safe and intentional.&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;This brief gives you a chance to flex skills you don’t often get to use: building a social network from scratch. The surface level requirements are fairly simple, but making this work will still require a backend for accounts, messaging, and locationaware discovery. For tooling and infrastructure, it’s worth revisiting the previous brief for suggestions on how to get this set up quickly.&lt;/p&gt;



&lt;p&gt;Where this brief really stands or falls is differentiation. To stand out, you need a clear hook that immediately resonates with van-lifers. One approach could be building a kind of mobile friendship book, where you collect connections as you travel from place to place. Layer in location based discovery and messaging, and you already have a well scoped app that feels built for this community.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-wrap-up&quot;&gt;Wrap up&lt;/h2&gt;



&lt;p&gt;Hopefully this post sparked a few ideas, whether that means submitting your very first app to Shipyard, or doubling down with a second one. If you’re still feeling stuck on what to build, how to scope it, or how to turn your work into a compelling story, I’d recommend checking out another post I wrote for exactly that situation, modestly titled &lt;a href=&quot;https://www.revenuecat.com/blog/engineering/how-to-win-shipyard/&quot;&gt;How to win Shipyard&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;With only a few days left before Devpost submissions close, it’s also worth revisiting the mechanics of a strong submission. I’ve covered that in a separate post,&lt;a href=&quot;https://www.revenuecat.com/blog/engineering/how-to-submit-your-app-for-shipyard/&quot;&gt;How to submit your app for Shipyard&lt;/a&gt;, where I break down what you actually need: a working app, a clear description, and a short three minute video showcasing what you built. That video matters more than most people expect, so make sure you spend some time getting it right.&lt;/p&gt;



&lt;p&gt;Now get hacking.&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Why hybrid monetization is the default model for subscription apps in 2026]]></title><description><![CDATA[Subscription-only monetization models are breaking down in the AI era]]></description><link>https://www.revenuecat.com/blog/growth/ai-hybrid-monetization/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/ai-hybrid-monetization/</guid><pubDate>Thu, 05 Feb 2026 17:38:12 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Blog_16_Hybrid-monetization-trends.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;At the start of the year, we always see a deluge of prediction articles. In January 2022 on this very blog, I mentioned &lt;a href=&quot;https://www.revenuecat.com/blog/growth/mobile-subscription-predictions-for-2022&quot;&gt;the rise of hybrid monetization&lt;/a&gt; for subscription apps. I spoke about this prediction multiple times, for &lt;a href=&quot;https://techcrunch.com/2022/12/10/hybrid-pricing-can-help-app-developers-better-monetize-their-apps/&quot;&gt;Techcrunch&lt;/a&gt; and at in-person events.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;At the time, it didn’t take off. The pressure wasn’t strong enough yet. Fast forward a couple of years, and AI has quietly turned usage into a revenue drag. 2025 showed signs that hybrid monetization was on the rise, but in 2026, pretending otherwise will be fatal for subscription apps. &lt;strong&gt;2026 is the year of take off for hybrid monetization!&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;500&quot; height=&quot;544&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/image.png&quot; alt=&quot;&quot; class=&quot;wp-image-51044&quot; style=&quot;width:400px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/image.png 500w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/image-276x300.png 276w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/image-46x50.png 46w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/image-37x40.png 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/image-426x464.png 426w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/image-272x296.png 272w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/image-434x472.png 434w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/image-74x80.png 74w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/image-44x48.png 44w&quot; sizes=&quot;auto, (max-width: 500px) 100vw, 500px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;br&gt;Incidentally, this 2022 blogpost was also where I discussed non-store payment options — and here we are now in 2026 with new uncertainty following &lt;a href=&quot;https://www.reuters.com/sustainability/boards-policy-regulation/us-appeals-court-partly-reverses-sanctions-against-apple-epic-games-antitrust-2025-12-11/&quot;&gt;App Store’s term changes&lt;/a&gt;…&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Before we jump into what moving your growth model towards hybrid monetization means for subscription apps, let’s look at the ‘why now’. (Spoiler alert: it’s AI again.)&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-pre-ai-subscriptions-won-because-marginal-costs-were-invisible&quot;&gt;&lt;strong&gt;Pre-AI: subscriptions won because marginal costs were invisible&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;For most of the past decade, subscription apps benefited from a hidden advantage: there were virtually no variable costs, whether you served one user or one million users — development and design aside, serving an additional user was effectively free.&lt;/p&gt;



&lt;p&gt;That shaped how the entire pricing ecosystem evolved:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Flat pricing felt fair&lt;/li&gt;



&lt;li&gt;Power users were an upside, not a risk&lt;/li&gt;



&lt;li&gt;Monetization focused on conversion and retention, not cost containment&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;We couldn’t imagine a time where &lt;em&gt;more &lt;/em&gt;users or more &lt;em&gt;active &lt;/em&gt;users could be a bad thing. This is why ‘all you can eat’ subscriptions became the norm outside of gaming. The model worked because the economics were forgiving.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;AI breaks that forgiveness. 2026 is the year this shift becomes impossible to ignore. Not because AI is new, but because its economics are now colliding with a maturing subscription market.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-growing-cracks&quot;&gt;&lt;strong&gt;The growing cracks&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Lately, subscription-based apps are ‘winning’ the App Store. We see non-gaming App Store revenue &lt;a href=&quot;https://www.revenuecat.com/blog/growth/consumer-apps-revenue-surpass-gaming-2025/&quot;&gt;overpassing the flatlined gaming sector&lt;/a&gt; and attracting founders, talent, capital, tools and more (&lt;a href=&quot;https://www.pocketgamer.biz/i-dont-see-app-studios-getting-into-games-i-just-see-game-studios-getting-into-apps/&quot;&gt;many of whom are from the gaming vertical&lt;/a&gt;, ironically). But things are getting harder.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;The cracks in the all-you-can-eat subscription model have been visible for years, but today they’re becoming an increasing headache for app profitability:&amp;nbsp;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Plateauing ARPU&lt;/li&gt;



&lt;li&gt;Converting barely a low single digit of user to premium features&lt;/li&gt;



&lt;li&gt;Rising churn&lt;/li&gt;



&lt;li&gt;Declining marginal returns from optimization&lt;/li&gt;



&lt;li&gt;Growing concerns for subscription fatigue&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-now-three-underlying-factors-accelerating-hybrid-nbsp&quot;&gt;&lt;strong&gt;Why now? Three underlying factors accelerating hybrid&amp;nbsp;&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Predicting hybrid monetization’s rise back in 2022 was early. What’s different in 2026 is that &lt;strong&gt;multiple pressures are converging at once.&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;There are several factors that are making the shift to hybrid monetization not a nice-to-have but a necessity:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-ai-has-massively-increased-competitive-density&quot;&gt;&lt;strong&gt;1. AI has massively increased competitive density&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;AI-assisted development has seen &lt;a href=&quot;https://x.com/HHaandr/status/2009253433073611226?s=20&quot;&gt;the amount of new apps explode.&lt;/a&gt; Vibe coding has lowered the cost of shipping and iterating apps. More teams are building faster, copying proven monetization patterns, and competing in the same categories.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;The result: more apps, similar funnels, and less room for monetization mistakes.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-optimization-is-no-longer-a-lasting-edge&quot;&gt;&lt;strong&gt;2. Optimization is no longer a lasting edge&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Paywall design, pricing tests, and onboarding flows used to be meaningful differentiators. Today, they’re table stakes. Today, paywall optimization is showing declining marginal return: it’s no longer a competitive edge, see it as a base requirement!&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.inc.com/annabel-burba/this-26-year-old-founder-built-a-1-million-business-and-its-all-thanks-to-x/91277926&quot;&gt;Vahe Bagdasaryen once made $1m&lt;/a&gt; selling easy-to-apply paywall layouts in his first year of consulting — great, but now everyone is using the same layouts (hence the limits of &lt;a href=&quot;https://www.revenuecat.com/blog/growth/web-to-app-funnel-examples/#h-2-blinkist-content-led-funnel&quot;&gt;Blinkist&lt;/a&gt;-like paywalls). These tactics are mandatory to master, but they quickly become commoditized; incremental gains shrink while costs keep rising as new apps vie for attention in the same few places.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-user-acquisition-keeps-getting-harder&quot;&gt;&lt;strong&gt;3. User acquisition keeps getting harder&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Attention hasn’t scaled with supply. More apps, same amount of eyeballs on the Tiktok feed or the App Store. &lt;a href=&quot;https://www.revenuecat.com/blog/growth/web-to-app-paid-user-acquisition/&quot;&gt;User acquisition (UA)&lt;/a&gt; costs continue to climb, while conversion rates and ARPU plateau in many non-gaming categories. Ad bids are harder to win, big fish are taking over ASO real estate&lt;a href=&quot;https://www.consultmyapp.com/blog/googles-gemini-blanket-bought-the-app-store-in-dec-2025-apple-search-ads-data-deep-dive&quot;&gt;,&lt;/a&gt; and there’s more competition than ever. Increasing ARPU by 20-25% yearly is just the beginning to compensate for UA inflation, it’s only what comes on top that is a win.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-now-the-variable-cost-of-ai-is-an-ignition-towards-hybrid-monetization&quot;&gt;&lt;strong&gt;Why now? The variable cost of AI is an ignition towards hybrid monetization&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;For a long time, most subscription-based businesses had variable costs of virtually zero. AI-based features make this obsolete. It’s a structural break: apps using AI as part of their core value are actively spending more money with each user they acquire.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;If your most engaged power users cost more than they pay, or free users can generate cost, the model needs to be rewritten.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;While primarily thought for SaaS businesses, Anh Tho Chuong’s article &lt;a href=&quot;https://www.elenaverna.com/p/so-you-want-to-price-your-ai-features&quot;&gt;&lt;em&gt;So you want to price your AI features&lt;/em&gt;&lt;/a&gt; is applicable to any AI app:&amp;nbsp;&lt;/p&gt;



&lt;p&gt;“The zero marginal cost era of software is over the minute you touch LLM APIs. AI has real COGS and it is something we will have to learn to deal with.” — &lt;a href=&quot;https://www.linkedin.com/in/anhthochuong/&quot;&gt;Anh Tho Chuong&lt;/a&gt;, CEO &amp;amp; Co-founder of Lago&lt;/p&gt;



&lt;p&gt;High variable cost means a few outliers can literally bankrupt you. But it also threatens the ‘all-you-can-eat’ nature of most subscription-only models:&amp;nbsp;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Power users were your best asset, now they can become a liability!&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Free users were generating indirect value for free (ratings, virality, late conversions…) but now carry negative unit economics&lt;/li&gt;



&lt;li&gt;Free trials have to be thought very differently&lt;/li&gt;



&lt;li&gt;ARPU averages hide catastrophic tail risk&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;It doesn’t mean subscriptions shouldn’t be the core of monetization for AI-based apps, but there is the need to build on top and adjust to those costs. I’m aligned with Anh Tho’s bet that hybrid pricing will be more common, keeping recurring revenue stable while increasing LTV.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Put together, the variable cost of AI plus the pressures discussed above look like this:&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;More app competition + similar monetization and acquisition playbooks + higher variable costs = a forced evolution of the subscription monetization model.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;But what does that model look like in practice?&amp;nbsp;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Access is predictable:&lt;/strong&gt; subscriptions still anchor revenue, expectations, and retention&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Consumption is bounded: &lt;/strong&gt;usage-heavy behaviors are capped, metered, or monetized separately&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Power users self-select into higher spend: &lt;/strong&gt;instead of being subsidized by everyone else, they fund the costs they generate.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Here are two inspirations to move you to action:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Learn the fundamentals:&lt;/strong&gt; my recent article covers &lt;a href=&quot;https://www.revenuecat.com/blog/growth/hybrid-monetization-techniques/&quot;&gt;how subscription apps can capture more revenue through hybrid monetization&lt;/a&gt;, outlining key techniques and models, with real app examples.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Delve into the specifics:&lt;/strong&gt; Alice Muir Kocourková wrote a detailed explanation of &lt;a href=&quot;https://www.revenuecat.com/blog/growth/ai-subscription-app-pricing/&quot;&gt;how AI has disrupted app pricing models, with examples of how AI apps are pricing their top features&lt;/a&gt;.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-hybrid-monetization-is-the-natural-evolution&quot;&gt;&lt;strong&gt;Hybrid monetization is the natural evolution&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Despite all of the above, I still believe subscriptions are a powerful model — just not in the static, all-you-can-eat form that has dominated monetization, retention, and acquisition for the past decade.&lt;/p&gt;



&lt;p&gt;All these factors are pushing for the natural next phase of model maturity: &lt;strong&gt;it’s not about abandoning subscriptions at all, but getting smarter and building on top&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;AI apps barely have a choice. AI apps &lt;em&gt;need &lt;/em&gt;to better reflect the usage-based costs of heavy users. But this isn’t just for AI apps. Even apps without heavy AI features now compete in markets shaped by these dynamics — even without the variable cost issue, &lt;strong&gt;growth is business model competition.&lt;/strong&gt;&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-to-do-if-you-re-building-a-subscription-app-today&quot;&gt;&lt;strong&gt;What to do if you’re building a subscription app today&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;This blog isn’t a tactical checklist per se, but there are a few directional implications from my observations which are hard to ignore:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;If your app has AI features: &lt;/strong&gt;you’ll eventually need to separate access from consumption; ignoring this early only makes the correction more painful later, and risks you being swamped by competition&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;If your app doesn’t use AI (yet):&lt;/strong&gt; don’t rest on your laurels or think you’re exempt from the pressure — you’re still competing in an ecosystem shaped by AI economics, so expect pricing shifts, faster imitation, and shorter monetization half-lives&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;If you’re early-stage: &lt;/strong&gt;defaulting to all-you-can-eat subscriptions is no longer the safe choice it once was — design pricing that can evolve as usage patterns emerge, but consider the added complexity of hybrid models&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Ultimately, the wisest thing you can do is keep an eye on your revenue streams. Watch for any outliers or heavy users if you have AI variables, and start thinking how you can protect your pricing model against the coming changes.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-bottom-line&quot;&gt;&lt;strong&gt;The bottom line&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Subscriptions aren’t failing. They’re being asked to do a job they were never designed for.&lt;/p&gt;



&lt;p&gt;AI makes usage expensive. Hybrid monetization is how subscription apps adapt, by preserving predictable revenue while aligning pricing with real costs and value. 2026 is the year hybrid monetization stops being an experiment and becomes the default shape of modern subscription businesses.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Your Shipyard: Creator Contest questions answered]]></title><description><![CDATA[Clear answers on building, monetization, submissions, and judging]]></description><link>https://www.revenuecat.com/blog/company/shipyard-2026-questions/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/company/shipyard-2026-questions/</guid><pubDate>Wed, 04 Feb 2026 17:19:28 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Shipyard_Blog_YourShipYardQuestions_1600x800_v1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;It was great to see so many of you join our &lt;a href=&quot;https://www.youtube.com/watch?v=0VemUbPfzQg&amp;amp;t=1s&quot;&gt;Shipyard LIVE&lt;/a&gt; on Tuesday. We didn’t have time to answer every question live, so we’ve pulled together the most commonly-asked ones here.&amp;nbsp;We hope this info helps on your journey to building a monetizable MVP — keep building, and we’ll see you at the finish line!&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-Z1D6x6I wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Still have a question?&quot; text=&quot;&lt;p&gt;Check out the &lt;a href=&amp;quot;https://www.revenuecat.com/blog/engineering/how-to-submit-your-app-for-shipyard/&amp;quot;&gt;submission guide&lt;/a&gt;, or jump into &lt;a href=&amp;quot;https://discord.gg/WAWKegrD&amp;quot;&gt;Discord&lt;/a&gt; to connect directly with the team.&lt;/p&gt;&quot; icon=&quot;circle-info&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-building-your-app&quot;&gt;&lt;strong&gt;Building your app&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;&lt;strong&gt;Q: Can I build for both iOS and Android?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;A: Yes. Cross-platform frameworks like React Native or Flutter are allowed — your app just needs to be a mobile app (iOS or Android).&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Q: How do I get access to the Shipping Container?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;A: Once you register for the contest on Devpost, you will receive an email within 48 business hours with information on how to redeem all of the offers. Reach out to our team in Discord if you encounter any issues.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Q: Do I need to use the tools included in the Shipping Container?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;A: No. You are free to use any tool you want; it’s not a requirement to use the tools contained in the Shipping Container to build your app, and this does not impact judging.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Q: Do I need a working backend, or is it enough to have demo userflows that explain the function and demonstrate how it should work?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;A: Everything in the app should be working. Your backend doesn’t need to scale to a large user base — this is an MVP — but documentation or user flows alone aren’t enough.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Q: Does a TestFlight Expo app that uses WebView for some screens still qualify, or does it need to be fully native to be compliant?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;A: An Expo/React Native app distributed via TestFlight still qualifies, even if some screens use a WebView. More information on using RevenueCat with React Native is available in our documentation &lt;a href=&quot;https://www.revenuecat.com/docs/getting-started/installation/reactnative&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-monetization&quot;&gt;&lt;strong&gt;Monetization&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;&lt;strong&gt;Q: Is a RevenueCat integration required?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;A: Yes, your app must have RevenueCat installed and active to be eligible.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Q: Is an integration with RevenueCat’s Test Store sufficient?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;A: No, this does not count as an integrated SDK. More info &lt;a href=&quot;https://www.revenuecat.com/blog/engineering/how-to-submit-your-app-for-shipyard/&quot;&gt;here&lt;/a&gt;.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Q: Do I have to charge for my app, or can I just use RevenueCat to introduce a ‘Donate to Developer’ experience?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;A: Yes — this is allowed and within the rules. That said, creators are ultimately looking for apps that meaningfully monetize their audience, so you should think carefully about whether this approach aligns with the brief.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Q: How do I decide what features to monetize? How do I price correctly?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;A: This is up to you. You should be pitching how and why you’d monetize your app as part of your submission — not just what you’d charge for. Hear more from our Judges on this &lt;a href=&quot;https://youtu.be/0VemUbPfzQg?t=2516&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-submission-and-testing&quot;&gt;&lt;strong&gt;Submission and testing&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;&lt;strong&gt;Q: Do I need to publish to the App Store?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;A: Apps must be accessible via TestFlight (iOS) or Play Internal Testing (Android). Your app does not need to be on the public stores (App Store or Google Play Store). If your app is also live on an app store, this will not affect the judging of your submission (positively or negatively).&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Q: Can I submit multiple projects for the same brief?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;A: No, you can only submit one submission per brief (seven submissions total). Choose wisely!&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Q: Can changes be made after the Feb 12 deadline? How do we know which version of the app will be judged?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;A: Yes, you can continue working on your app after the Feb 12 submission deadline. The Intellectual Property remains yours, and we can’t (and don’t want to) restrict ongoing development.&lt;/p&gt;



&lt;p&gt;However, you should clearly specify which version of your app is being submitted for judging in your Devpost submission. Judges will evaluate the version you reference there and the one that features in your demo video.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Q: Do I need to upload to GitHub if the app is vibe-coded?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;A: No. You don’t need to upload your code to GitHub.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Q: What tester emails should I use for TestFlight or Play Internal Testing?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;A: All the information on how to submit, including what tester emails to use, is available &lt;a href=&quot;https://www.revenuecat.com/blog/engineering/how-to-submit-your-app-for-shipyard/&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Q: Should I ensure the judges can access and test premium features, or will seeing a paywall suffice?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;A: You should ensure all the features that you want the judges to evaluate are available.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Q: Since the App Store URL is allowed, can we provide instructions to redeem free credits for judges to test the app?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;A: Yes, this is fine.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-judging-nbsp&quot;&gt;&lt;strong&gt;Judging&amp;nbsp;&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;&lt;strong&gt;Q: For the video submission, should I screen record on my phone to demo the app, and do I need to have a face cam?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;A: Up to you! How you record the feature and whether you feature yourself/voice/face in it is entirely your call. The only thing that will affecting judging is the quality of your app and the effort put into submission — better quality videos or more engaging demos might stand out more, but you won’t be penalized for not showing your face. &lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Q: Will the Creators use my app or just watch the demo video I provide?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;A: Due to the expected number of submissions, we can’t guarantee that every app will be fully installed and tested. The only requirement is that judges watch your demo video — this is how all submissions are reviewed before shortlisting. Shortlisted submissions &lt;strong&gt;will &lt;/strong&gt;be fully tested. Make sure your video clearly shows the core experience and value of your app. Hear more about this &lt;a href=&quot;https://youtu.be/0VemUbPfzQg?t=2732&quot;&gt;here&lt;/a&gt;.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Q: How long should my demo video be?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;A: We recommend keeping your demo video to 2–3 minutes. Shorter videos may hold attention spans more, but judges will watch videos of any length. This isn’t a hard limit — longer videos won’t be rejected.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Q: Should we disable paywalls for testing?&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;A: No, don’t worry about this. In TestFlight and Play Internal Testing, the transactions won’t be charged.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Q: Are sandbox purchases sufficient, or do the Judges need to see a real transaction flow?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;A: TestFlight / Sandbox purchases are sufficient.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Q: What would you say matters more, how the app looks and feels, or the level of functionality?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;A: See the response from our judges &lt;a href=&quot;http://youtube.com/watch?t=2017&amp;amp;v=0VemUbPfzQg&amp;amp;feature=youtu.be&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Q: Will it impact the judging if a Creator specifically mentions a preference for iOS vs. Android?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;A: If a creator mentions a platform preference, it’s smart to factor that into what you build. It can help your app better fit their audience.&lt;/p&gt;



&lt;p&gt;That said, you won’t be disqualified for building on the other platform. If you do, make sure to explain your choice and include a clear roadmap for supporting the creator’s preferred platform. Judges will focus on overall audience fit, product quality, and long-term potential — not just the initial platform.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Q: Any bonus points if your app is launched with users?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;A: &lt;/strong&gt;No, judging isn’t based on user numbers. The focus is on the quality of your MVP, how well it fits the creator’s audience, and its monetization potential. Having users won’t hurt, but it won’t give you extra points on its own.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-creator-specific-questions&quot;&gt;&lt;strong&gt;Creator-specific questions&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;&lt;strong&gt;Q: Can you share more information on the Creator’s audience demographics&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;All the information we have is available &lt;a href=&quot;https://revenuecat.notion.site/shipyard-audience-demographics?source=copy_link&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Q: Gabby, do your followers typically DM you, and what sort of questions do they ask?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;See Gabby’s response &lt;a href=&quot;https://youtu.be/0VemUbPfzQg?t=2143&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Q: Gabby, do you think it’d be useful to include a feature that allows users of your app to interact with one another?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;See Gabby’s response &lt;a href=&quot;https://youtu.be/0VemUbPfzQg?t=2247&quot;&gt;here&lt;/a&gt;&lt;strong&gt;.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Q: Eitan, can I use recipes from your website (&lt;/strong&gt;&lt;a href=&quot;https://www.eitanbernath.com/recipes/&quot;&gt;https://www.eitanbernath.com/recipes/&lt;/a&gt;) &lt;strong&gt;in my app?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Yes, you can use recipes from Eitan’s website for the purposes of the hackathon. However, once the competition ends and your app is published to an app store, those recipes will need to be removed. This is to ensure content rights are respected beyond the scope of the contest.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[How ElevenLabs builds and grows consumer AI apps without losing speed or clarity]]></title><description><![CDATA[On the podcast: how earned media can drive paid performance, building features that make for good tweets, and why stripping out your onboarding quiz might beat optimizing it.]]></description><link>https://www.revenuecat.com/blog/growth/jack-tanmay-elevenlabs-sub-club-podcast-2026/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/jack-tanmay-elevenlabs-sub-club-podcast-2026/</guid><pubDate>Wed, 04 Feb 2026 13:50:55 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/RC-Blog-Cover-ElevenLabs-1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;ElevenLabs is best known for pushing the boundaries of voice AI — but what’s just as interesting is &lt;em&gt;how&lt;/em&gt; the team turns powerful technology into consumer products that actually scale.&lt;/p&gt;



&lt;p&gt;In this episode of &lt;strong&gt;Sub Club&lt;/strong&gt;, host David Barnard sits down with &lt;strong&gt;Tanmay Jain&lt;/strong&gt; (Mobile Growth Lead, ElevenLabs) and &lt;strong&gt;Jack McDermott&lt;/strong&gt; (Mobile Growth Lead, ElevenReader) to unpack how ElevenLabs approaches mobile growth, pricing, launches, and team structure in one of the fastest-moving categories in tech.&lt;/p&gt;



&lt;p&gt;What emerges isn’t a story about AI models or technical breakthroughs. It’s a story about &lt;strong&gt;clarity, speed, and systems&lt;/strong&gt; — and the decisions that make those possible.&lt;/p&gt;



&lt;p&gt;Below are the most relevant lessons from the conversation.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;How ElevenLabs Ships So Fast With Small Teams&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/3r8pr9w_lDQ?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;iframe loading=&quot;lazy&quot; width=&quot;100%&quot; height=&quot;180&quot; frameborder=&quot;no&quot; scrolling=&quot;no&quot; seamless=&quot;&quot; src=&quot;https://share.transistor.fm/e/5fbc906e?color=FFFFFF&amp;amp;background=30343C&quot;&gt;&lt;/iframe&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-pricing-should-match-how-users-think-not-how-ai-works&quot;&gt;&lt;strong&gt;Pricing should match how users think — not how AI works&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;One of the biggest wins Tanmay and Jack share came from &lt;strong&gt;simplifying pricing&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;For ElevenReader, the team moved away from tokens and credits — concepts that make sense internally, but confuse consumers — and instead sold &lt;strong&gt;listening time&lt;/strong&gt;. The result was clearer value communication and materially better conversion.&lt;/p&gt;



&lt;p&gt;The lesson is simple but often missed: Abstracting away AI complexity isn’t “dumbing things down.” It’s good product sense.&lt;/p&gt;



&lt;p&gt;If users have to learn a new mental model just to understand pricing, friction is already too high.&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-small-autonomous-pods-turn-speed-into-a-moat&quot;&gt;&lt;strong&gt;Small, autonomous pods turn speed into a moat&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;ElevenLabs doesn’t operate as one large, centralized org. Instead, it functions more like &lt;strong&gt;10–12 small startups&lt;/strong&gt; inside a single company.&lt;/p&gt;



&lt;p&gt;These small, autonomous pods have full ownership — from product decisions to experiments, pricing, and paywalls. That structure allows teams to ship quickly, iterate relentlessly, and stay accountable to real outcomes rather than internal process.&lt;/p&gt;



&lt;p&gt;In fast-moving AI markets, this isn’t just an org preference — it’s a competitive advantage.&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-earned-media-compounds-and-makes-paid-growth-work-better&quot;&gt;&lt;strong&gt;Earned media compounds — and makes paid growth work better&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Jack breaks down how ElevenLabs thinks about launches as &lt;strong&gt;compounding assets&lt;/strong&gt;, not one-off moments.&lt;/p&gt;



&lt;p&gt;Each successful launch generates earned media, which increases branded search, improves trust, and lowers the cost of paid acquisition. Over time, this creates a flywheel where narrative, brand, and performance marketing reinforce each other.&lt;/p&gt;



&lt;p&gt;Growth isn’t paid &lt;em&gt;versus&lt;/em&gt; organic.&lt;br&gt;It’s the interaction between the two that matters.&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-start-launches-with-the-tweet-thread-not-the-feature&quot;&gt;&lt;strong&gt;Start launches with the tweet thread, not the feature&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Before building launch assets, landing pages, or ad creative, ElevenLabs starts with a single test:&lt;/p&gt;



&lt;p&gt;Can the value of this feature be explained clearly in a &lt;strong&gt;tweet thread&lt;/strong&gt;?&lt;/p&gt;



&lt;p&gt;If the answer is no, that’s a red flag. Writing the narrative first forces clarity and keeps teams focused on user value instead of shipping features that look impressive but don’t resonate.&lt;/p&gt;



&lt;p&gt;In practice, the tweet thread becomes the first product spec.&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-consumer-apps-are-a-strategic-advantage-for-platform-companies&quot;&gt;&lt;strong&gt;Consumer apps are a strategic advantage for platform companies&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;ElevenLabs doesn’t see its consumer apps as competing with its platform or API business. They’re a &lt;strong&gt;force multiplier&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;By being their own best customer, the team uncovers UX friction, performance constraints, and emotional use cases that are hard to see from dashboards or API logs alone. Those insights flow back into the core product, making the platform stronger for everyone.&lt;/p&gt;



&lt;p&gt;Mobile isn’t just a distribution channel — it’s a learning surface.&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-conclusion-clarity-speed-and-systems-matter-more-than-hype&quot;&gt;&lt;strong&gt;Conclusion: Clarity, Speed, and systems matter more than hype&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The core lesson from this episode isn’t about AI at all.&lt;/p&gt;



&lt;p&gt;It’s about building systems — pricing, teams, launches, and feedback loops — that let great products move fast without breaking trust or usability.&lt;/p&gt;



&lt;p&gt;For founders, growth leads, and product teams working in fast-moving categories, ElevenLabs offers a clear example of how to scale thoughtfully without slowing down.&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;



&lt;p&gt;🎧 &lt;strong&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=3r8pr9w_lDQ&quot;&gt;Listen to the full episode of Sub Club&lt;/a&gt;&lt;/strong&gt; to hear Tanmay Jain and Jack McDermott break down the experiments, decisions, and trade-offs behind ElevenLabs’ consumer growth strategy.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Handling edge cases in Google Play Billing]]></title><description><![CDATA[Explains how to correctly handle common edge cases in Google Play Billing, including pending purchases, ITEM_ALREADY_OWNED errors, multi-quantity consumables, subscription downgrades, and network failures.]]></description><link>https://www.revenuecat.com/blog/engineering/google-play-edge-cases/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/google-play-edge-cases/</guid><pubDate>Mon, 02 Feb 2026 02:06:07 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/02/Blog_12_Understanding-Google-Plays-subscription-price-changes.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Google Play Billing provides a comprehensive API surface for handling in-app purchases and subscriptions on Android. Most developers are comfortable with the standard purchase flow: launch the billing flow, receive a result, acknowledge the purchase, and grant entitlements. But production billing systems must handle a wider range of scenarios that are often underrepresented in tutorials and sample code. Pending purchases, multi-quantity consumables, subscription downgrades with proration, and the&amp;nbsp;&lt;code&gt;ITEM_ALREADY_OWNED&lt;/code&gt;&amp;nbsp;response are all situations your app will encounter in the real world, and mishandling any of them can result in lost revenue, confused users, or failed purchases.&lt;/p&gt;



&lt;p&gt;In this article, we’ll explore the most common edge cases in Google Play Billing, understand why they occur, examine how to handle each one correctly with the Play Billing Library, and see how RevenueCat simplifies these scenarios so you can focus on your product instead of billing infrastructure.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-fundamental-problem-the-happy-path-is-not-enough&quot;&gt;&lt;strong&gt;The fundamental problem: the happy path is not enough&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Most billing implementations start from the sample code in the Android documentation:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZAiBve wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/\/ The happy path\nbillingClient.launchBillingFlow(activity, params)\n\n\/\/ In PurchasesUpdatedListener\noverride fun onPurchasesUpdated(\n    billingResult: BillingResult,\n    purchases: List&lt;Purchase&gt;?\n) {\n    if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {\n        purchases?.forEach { purchase -&gt;\n            if (purchase.purchaseState == Purchase.PurchaseState.PURCHASED) {\n                acknowledgePurchase(purchase)\n                grantEntitlement(purchase)\n            }\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This handles a successful, immediate purchase. But what happens when the payment is delayed by 48 hours because the user is paying at a convenience store? What happens when the user already owns the item because a previous acknowledgment failed silently? What happens when a subscription downgrade takes effect at the next renewal instead of immediately? Each of these scenarios requires specific handling, and ignoring them leads to support tickets, refund requests, and lost subscribers.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;pending-purchases-when-payment-is-not-immediate&quot;&gt;&lt;strong&gt;Pending purchases: when payment is not immediate&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Not all purchases complete instantly. Certain payment methods, including cash payments at convenience stores, bank transfers, and some carrier billing options, require asynchronous processing. When a user initiates a purchase with one of these methods, Google Play returns a purchase in the&amp;nbsp;&lt;code&gt;PENDING&lt;/code&gt;&amp;nbsp;state rather than the&amp;nbsp;&lt;code&gt;PURCHASED&lt;/code&gt;&amp;nbsp;state.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;why-pending-purchases-happen&quot;&gt;&lt;strong&gt;Why pending purchases happen&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Pending purchases are common in markets where credit card penetration is low:&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Payment method&lt;/th&gt;&lt;th&gt;Common regions&lt;/th&gt;&lt;th&gt;Typical processing time&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Cash payments (convenience stores)&lt;/td&gt;&lt;td&gt;Japan, Mexico, Indonesia&lt;/td&gt;&lt;td&gt;24-48 hours&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Bank transfers&lt;/td&gt;&lt;td&gt;Germany, Netherlands, Brazil&lt;/td&gt;&lt;td&gt;1-3 business days&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Carrier billing (some carriers)&lt;/td&gt;&lt;td&gt;Various&lt;/td&gt;&lt;td&gt;Minutes to hours&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;If your app is available globally, you’re bound to encounter pending purchases. Ignoring this state means users in these regions cannot purchase your products at all — or worse, they see confusing behavior where their purchase ‘disappears’.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;detecting-and-handling-the-pending-state&quot;&gt;&lt;strong&gt;Detecting and handling the pending state&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The&amp;nbsp;&lt;code&gt;PurchasesUpdatedListener&lt;/code&gt;&amp;nbsp;receives pending purchases alongside completed ones. The critical distinction is in the&amp;nbsp;&lt;code&gt;purchaseState&lt;/code&gt;&amp;nbsp;field:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1arljL wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;override fun onPurchasesUpdated(\n    billingResult: BillingResult,\n    purchases: List&lt;Purchase&gt;?\n) {\n    if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {\n        purchases?.forEach { purchase -&gt;\n            when (purchase.purchaseState) {\n                Purchase.PurchaseState.PURCHASED -&gt; {\n                    \/\/ Payment complete, grant access\n                    processPurchase(purchase)\n                }\n                Purchase.PurchaseState.PENDING -&gt; {\n                    \/\/ Payment not yet complete\n                    handlePendingPurchase(purchase)\n                }\n                Purchase.PurchaseState.UNSPECIFIED_STATE -&gt; {\n                    \/\/ Unknown state, query backend for clarification\n                    queryBackendForState(purchase)\n                }\n            }\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The key rule is:&amp;nbsp;do not grant entitlements for pending purchases. The user has not paid yet. Instead, record the pending purchase and communicate the status clearly:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1NnLVc wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;fun handlePendingPurchase(purchase: Purchase) {\n    \/\/ Store the pending purchase token for later verification\n    purchaseRepository.savePendingPurchase(\n        purchaseToken = purchase.purchaseToken,\n        productId = purchase.products.first(),\n        orderId = purchase.orderId,\n        purchaseTime = purchase.purchaseTime,\n    )\n\n    \/\/ Show clear UI to the user\n    showPendingUI(\n        message = \&amp;quot;Your purchase is being processed. \&amp;quot; +\n            \&amp;quot;You&apos;ll get access once payment is confirmed.\&amp;quot;,\n    )\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;completing-a-pending-purchase&quot;&gt;&lt;strong&gt;Completing a pending purchase&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;When the payment is eventually confirmed, your app receives an updated purchase via&amp;nbsp;&lt;code&gt;onPurchasesUpdated&lt;/code&gt;&amp;nbsp;or through&amp;nbsp;&lt;code&gt;queryPurchasesAsync&lt;/code&gt;. The&amp;nbsp;&lt;code&gt;purchaseState&lt;/code&gt;&amp;nbsp;will now be&amp;nbsp;&lt;code&gt;PURCHASED&lt;/code&gt;, and you can proceed with acknowledgment and entitlement granting.&lt;/p&gt;



&lt;p&gt;However, there is a subtlety: the user might not have your app open when the payment completes. Your backend should handle this through Real-Time Developer Notifications (RTDN). When you receive a&amp;nbsp;&lt;code&gt;ONE_TIME_PRODUCT_PURCHASED&lt;/code&gt;&amp;nbsp;or&amp;nbsp;&lt;code&gt;SUBSCRIPTION_PURCHASED&lt;/code&gt;&amp;nbsp;notification for a previously pending token, your backend should update the entitlement and notify the user:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-zkMlz wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/\/ Backend notification handler\nfun handlePurchaseNotification(notification: DeveloperNotification) {\n    val purchaseToken = notification.oneTimeProductNotification?.purchaseToken\n        ?: notification.subscriptionNotification?.purchaseToken\n        ?: return\n\n    val pendingPurchase = purchaseRepository.findPendingPurchase(purchaseToken)\n    if (pendingPurchase != null) {\n        \/\/ Previously pending purchase is now complete\n        val purchaseDetails = playDeveloperApi\n            .purchases()\n            .products()\n            .get(packageName, pendingPurchase.productId, purchaseToken)\n            .execute()\n\n        if (purchaseDetails.purchaseState == 0) { \/\/ 0 = Purchased\n            entitlementRepository.grantEntitlement(\n                userId = pendingPurchase.userId,\n                productId = pendingPurchase.productId,\n            )\n            purchaseRepository.markCompleted(purchaseToken)\n\n            \/\/ Notify user that their purchase is ready\n            notificationService.sendPushNotification(\n                userId = pendingPurchase.userId,\n                title = \&amp;quot;Purchase Complete\&amp;quot;,\n                body = \&amp;quot;Your purchase has been confirmed. Enjoy your content!\&amp;quot;,\n            )\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;enabling-pending-purchases-in-your-billingclient&quot;&gt;&lt;strong&gt;Enabling pending purchases in your BillingClient&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Pending purchase support must be explicitly enabled when building the&amp;nbsp;&lt;code&gt;BillingClient&lt;/code&gt;. Without this, purchases from delayed payment methods will fail entirely:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1ef2z9 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;val billingClient = BillingClient.newBuilder(context)\n    .setListener(purchasesUpdatedListener)\n    .enablePendingPurchases(\n        PendingPurchasesParams.newBuilder()\n            .enableOneTimeProducts()\n            .enablePrepaidPlans()\n            .build()\n    )\n    .build()&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Starting with Play Billing Library 7, calling&amp;nbsp;&lt;code&gt;enablePendingPurchases()&lt;/code&gt;&amp;nbsp;is required. Without it,&amp;nbsp;&lt;code&gt;BillingClient&lt;/code&gt;&amp;nbsp;initialization will fail.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;the-itemalreadyowned-response-a-common-source-of-confusion&quot;&gt;&lt;strong&gt;The&amp;nbsp;&lt;code&gt;ITEM_ALREADY_OWNED&lt;/code&gt;&amp;nbsp;response: a common source of confusion&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;One of the most frequently encountered edge cases is&amp;nbsp;&lt;code&gt;BillingResponseCode.ITEM_ALREADY_OWNED&lt;/code&gt;. This response occurs when a user attempts to purchase a non-consumable product or subscription they already own. While it sounds straightforward, the scenarios that trigger it are often surprising.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;why-itemalreadyowned-happens&quot;&gt;&lt;strong&gt;Why&amp;nbsp;&lt;code&gt;ITEM_ALREADY_OWNED&lt;/code&gt;&amp;nbsp;happens&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The most common cause is not the user deliberately trying to buy something twice. It’s a previous purchase that was not properly acknowledged. Google Play’s acknowledgment requirement means that unacknowledged purchases exist in a limbo state: the user has been charged, but the purchase has not been confirmed by your app. If the user tries to buy the same item again, Google Play returns&amp;nbsp;&lt;code&gt;ITEM_ALREADY_OWNED&lt;/code&gt;&amp;nbsp;because the unacknowledged purchase still exists.&lt;/p&gt;



&lt;p&gt;This happens more often than you might expect:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;The app crashed after receiving the purchase but before acknowledging it&lt;/li&gt;



&lt;li&gt;A network error prevented the acknowledgment call from completing&lt;/li&gt;



&lt;li&gt;The user force-closed the app during the purchase flow&lt;/li&gt;



&lt;li&gt;The acknowledgment API call returned an error that was not retried&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;handling-itemalreadyowned-correctly&quot;&gt;&lt;strong&gt;Handling&amp;nbsp;&lt;code&gt;ITEM_ALREADY_OWNED&lt;/code&gt;&amp;nbsp;correctly&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The correct response to&amp;nbsp;&lt;code&gt;ITEM_ALREADY_OWNED&lt;/code&gt;&amp;nbsp;is not to show an error message. Instead, you should query for existing purchases and process any unacknowledged ones:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z13Texc wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;override fun onPurchasesUpdated(\n    billingResult: BillingResult,\n    purchases: List&lt;Purchase&gt;?\n) {\n    when (billingResult.responseCode) {\n        BillingClient.BillingResponseCode.OK -&gt; {\n            purchases?.forEach { processPurchase(it) }\n        }\n        BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED -&gt; {\n            \/\/ Query existing purchases and process any unacknowledged ones\n            recoverUnacknowledgedPurchases()\n        }\n        BillingClient.BillingResponseCode.USER_CANCELED -&gt; {\n            \/\/ User backed out, no action needed\n        }\n        else -&gt; {\n            handleBillingError(billingResult)\n        }\n    }\n}\n\nprivate fun recoverUnacknowledgedPurchases() {\n    val params = QueryPurchasesParams.newBuilder()\n        .setProductType(BillingClient.ProductType.INAPP)\n        .build()\n\n    billingClient.queryPurchasesAsync(params) { billingResult, purchases -&gt;\n        if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {\n            purchases.forEach { purchase -&gt;\n                if (purchase.purchaseState == Purchase.PurchaseState.PURCHASED &amp;amp;&amp;amp;\n                    !purchase.isAcknowledged\n                ) {\n                    \/\/ Found the unacknowledged purchase, process it\n                    processPurchase(purchase)\n                }\n            }\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This pattern turns a frustrating error into a seamless recovery. The user does not need to know that a previous purchase failed to acknowledge. From their perspective, they tap ‘Buy’ and get the item.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;preventing-itemalreadyowned-proactively&quot;&gt;&lt;strong&gt;Preventing&amp;nbsp;&lt;code&gt;ITEM_ALREADY_OWNED&lt;/code&gt;&amp;nbsp;proactively&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The best approach is to prevent this scenario by processing unacknowledged purchases on app startup:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z62DLl wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;fun processUnacknowledgedPurchasesOnStartup() {\n    val inAppParams = QueryPurchasesParams.newBuilder()\n        .setProductType(BillingClient.ProductType.INAPP)\n        .build()\n\n    val subsParams = QueryPurchasesParams.newBuilder()\n        .setProductType(BillingClient.ProductType.SUBS)\n        .build()\n\n    billingClient.queryPurchasesAsync(inAppParams) { result, purchases -&gt;\n        if (result.responseCode == BillingClient.BillingResponseCode.OK) {\n            purchases.filter {\n                it.purchaseState == Purchase.PurchaseState.PURCHASED &amp;amp;&amp;amp;\n                    !it.isAcknowledged\n            }.forEach { processPurchase(it) }\n        }\n    }\n\n    billingClient.queryPurchasesAsync(subsParams) { result, purchases -&gt;\n        if (result.responseCode == BillingClient.BillingResponseCode.OK) {\n            purchases.filter {\n                it.purchaseState == Purchase.PurchaseState.PURCHASED &amp;amp;&amp;amp;\n                    !it.isAcknowledged\n            }.forEach { processPurchase(it) }\n        }\n    }&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Call this method when the&amp;nbsp;&lt;code&gt;BillingClient&lt;/code&gt;&amp;nbsp;connects successfully. This ensures that any purchases that slipped through the cracks are recovered before the user encounters problems.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;consumable-purchases-acknowledge-vs-consume&quot;&gt;&lt;strong&gt;Consumable purchases:&amp;nbsp;&lt;code&gt;acknowledge&lt;/code&gt;&amp;nbsp;vs.&amp;nbsp;&lt;code&gt;consume&lt;/code&gt;&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;For consumable products like in-game virtual currency, extra lives, or token packs, the distinction between acknowledgment and consumption is a common source of bugs. Both are required for consumable products, but they serve different purposes and have different timing requirements.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-acknowledgment-and-consumption-flow&quot;&gt;&lt;strong&gt;The acknowledgment and consumption flow&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;Acknowledgment&lt;/strong&gt;&amp;nbsp;tells Google Play you’ve delivered the purchased content. It must happen within three days of the purchase, or the purchase is automatically refunded.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Consumption&lt;/strong&gt;&amp;nbsp;resets the purchase so the user can buy the same item again. Without consuming a product, the user cannot repurchase it, and attempting to do so returns&amp;nbsp;&lt;code&gt;ITEM_ALREADY_OWNED&lt;/code&gt;.&lt;/p&gt;



&lt;p&gt;For consumable products, you should consume the purchase, which implicitly acknowledges it:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ayfVU wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;fun processConsumablePurchase(purchase: Purchase) {\n    \/\/ Verify with backend first\n    verifyPurchaseWithBackend(purchase) { isValid -&gt;\n        if (isValid) {\n            \/\/ Grant the consumable content\n            grantConsumableContent(purchase)\n\n            \/\/ Consume the purchase (this also acknowledges it)\n            val consumeParams = ConsumeParams.newBuilder()\n                .setPurchaseToken(purchase.purchaseToken)\n                .build()\n\n            billingClient.consumeAsync(consumeParams) { billingResult, _ -&gt;\n                if (billingResult.responseCode != BillingClient.BillingResponseCode.OK) {\n                    \/\/ Retry consumption, the user cannot rebuy until consumed\n                    scheduleConsumptionRetry(purchase.purchaseToken)\n                }\n            }\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-multi-quantity-edge-case&quot;&gt;&lt;strong&gt;The multi-quantity edge case&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Google Play supports multi-quantity purchases for consumable products. A user can buy multiple units of a consumable in a single transaction. The quantity is available in the&amp;nbsp;&lt;code&gt;Purchase&lt;/code&gt;&amp;nbsp;object:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1P0uNQ wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;fun processConsumablePurchase(purchase: Purchase) {\n    val quantity = purchase.quantity  \/\/ Could be &gt; 1\n\n    verifyPurchaseWithBackend(purchase) { isValid -&gt;\n        if (isValid) {\n            \/\/ Grant the correct quantity\n            grantConsumableContent(purchase.products.first(), quantity)\n\n            val consumeParams = ConsumeParams.newBuilder()\n                .setPurchaseToken(purchase.purchaseToken)\n                .build()\n\n            billingClient.consumeAsync(consumeParams) { billingResult, _ -&gt;\n                if (billingResult.responseCode != BillingClient.BillingResponseCode.OK) {\n                    scheduleConsumptionRetry(purchase.purchaseToken)\n                }\n            }\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;If you ignore the&amp;nbsp;&lt;code&gt;quantity&lt;/code&gt;&amp;nbsp;field and always grant one unit, users who purchase multiple units will receive fewer items than they paid for. This leads to support tickets and refund requests.&lt;/p&gt;



&lt;p&gt;To enable multi-quantity purchases, you must configure the product in the Google Play Console with ‘Allow multi-quantity purchases’ enabled. Additionally, your&amp;nbsp;&lt;code&gt;BillingFlowParams&lt;/code&gt;&amp;nbsp;can specify a maximum quantity the user is allowed to select:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1TznMy wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;val billingFlowParams = BillingFlowParams.newBuilder()\n    .setProductDetailsParamsList(\n        listOf(\n            BillingFlowParams.ProductDetailsParams.newBuilder()\n                .setProductDetails(productDetails)\n                .build()\n        )\n    )\n    .build()&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-consumption-retry-problem&quot;&gt;&lt;strong&gt;The consumption retry problem&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;If the&amp;nbsp;&lt;code&gt;consumeAsync&lt;/code&gt;&amp;nbsp;call fails (due to a network error, for example), the user has received their content but the purchase has not been consumed. This means:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;The user cannot buy the same consumable again&lt;/li&gt;



&lt;li&gt;The purchase may be refunded after three days if not acknowledged (though consumption implicitly acknowledges)&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;You should implement a retry mechanism for failed consumptions:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-2tjwRr wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;class ConsumptionRetryManager(\n    private val billingClient: BillingClient,\n    private val purchaseRepository: PurchaseRepository,\n) {\n    fun scheduleConsumptionRetry(purchaseToken: String) {\n        purchaseRepository.markPendingConsumption(purchaseToken)\n    }\n\n    fun retryPendingConsumptions() {\n        val pendingTokens = purchaseRepository.getPendingConsumptionTokens()\n\n        pendingTokens.forEach { token -&gt;\n            val consumeParams = ConsumeParams.newBuilder()\n                .setPurchaseToken(token)\n                .build()\n\n            billingClient.consumeAsync(consumeParams) { billingResult, _ -&gt;\n                if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {\n                    purchaseRepository.clearPendingConsumption(token)\n                }\n                \/\/ If still failing, it will be retried next time\n            }\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Call&amp;nbsp;&lt;code&gt;retryPendingConsumptions()&lt;/code&gt;&amp;nbsp;each time the&amp;nbsp;&lt;code&gt;BillingClient&lt;/code&gt;&amp;nbsp;connects, alongside your unacknowledged purchase recovery logic.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;subscription-downgrades-and-proration-modes&quot;&gt;&lt;strong&gt;Subscription downgrades and proration modes&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;When a user changes their subscription plan, the billing behavior depends on whether they are upgrading or downgrading and which proration mode you specify. Downgrades in particular have behavior that surprises many developers.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-default-downgrade-behavior&quot;&gt;&lt;strong&gt;The default downgrade behavior&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;When a user downgrades their subscription (moves to a cheaper plan), the default behavior is&amp;nbsp;&lt;code&gt;DEFERRED&lt;/code&gt;: the downgrade takes effect at the&amp;nbsp;&lt;strong&gt;next renewal date&lt;/strong&gt;, not immediately. The user continues to have access to the higher-tier features until their current billing period ends.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z2so6TQ wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;fun launchDowngrade(\n    activity: Activity,\n    newProductDetails: ProductDetails,\n    newOfferToken: String,\n    currentPurchaseToken: String,\n) {\n    val billingFlowParams = BillingFlowParams.newBuilder()\n        .setProductDetailsParamsList(\n            listOf(\n                BillingFlowParams.ProductDetailsParams.newBuilder()\n                    .setProductDetails(newProductDetails)\n                    .setOfferToken(newOfferToken)\n                    .build()\n            )\n        )\n        .setSubscriptionUpdateParams(\n            BillingFlowParams.SubscriptionUpdateParams.newBuilder()\n                .setOldPurchaseToken(currentPurchaseToken)\n                .setSubscriptionReplacementMode(\n                    BillingFlowParams.SubscriptionUpdateParams\n                        .ReplacementMode.DEFERRED\n                )\n                .build()\n        )\n        .build()\n\n    billingClient.launchBillingFlow(activity, billingFlowParams)\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;understanding-replacement-modes&quot;&gt;&lt;strong&gt;Understanding replacement modes&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Each replacement mode has different implications for billing, access, and user experience:&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Mode&lt;/th&gt;&lt;th&gt;When Change Takes Effect&lt;/th&gt;&lt;th&gt;Billing Impact&lt;/th&gt;&lt;th&gt;Best For&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;IMMEDIATE_WITH_TIME_PRORATION&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Immediately&lt;/td&gt;&lt;td&gt;Remaining time credited toward new plan&lt;/td&gt;&lt;td&gt;Upgrades where user gets immediate access&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;IMMEDIATE_AND_CHARGE_PRORATED_PRICE&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Immediately&lt;/td&gt;&lt;td&gt;Prorated charge for remainder of period&lt;/td&gt;&lt;td&gt;Upgrades with fair billing&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;IMMEDIATE_AND_CHARGE_FULL_PRICE&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Immediately&lt;/td&gt;&lt;td&gt;Full new price charged, new billing period starts&lt;/td&gt;&lt;td&gt;Premium upgrades&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;DEFERRED&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Next renewal&lt;/td&gt;&lt;td&gt;No immediate charge&lt;/td&gt;&lt;td&gt;Downgrades&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;IMMEDIATE_WITHOUT_PRORATION&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Immediately&lt;/td&gt;&lt;td&gt;No charge until next renewal&lt;/td&gt;&lt;td&gt;Lateral moves or trials of higher tiers&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-deferred-downgrade-pitfall&quot;&gt;&lt;strong&gt;The deferred downgrade pitfall&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The most common mistake with deferred downgrades is checking the subscription state immediately after the purchase flow completes and expecting to see the new plan. With&amp;nbsp;&lt;code&gt;DEFERRED&lt;/code&gt;&amp;nbsp;mode, the original subscription remains active with the original product ID until the next renewal. The new subscription only appears after renewal.&lt;/p&gt;



&lt;p&gt;This means your entitlement check must account for the transition period:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1SAfbO wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;fun handleDowngradeResult(purchase: Purchase) {\n    \/\/ After a deferred downgrade, the purchase still reflects\n    \/\/ the OLD subscription until the next renewal\n    val currentProductId = purchase.products.first()\n\n    \/\/ Query the subscription status from your backend to check\n    \/\/ if a deferred downgrade is pending\n    checkBackendForPendingDowngrade(purchase.purchaseToken) { pendingDowngrade -&gt;\n        if (pendingDowngrade != null) {\n            \/\/ Show UI indicating the downgrade is scheduled\n            showDowngradeScheduledUI(\n                currentPlan = currentProductId,\n                futurePlan = pendingDowngrade.newProductId,\n                effectiveDate = pendingDowngrade.effectiveDate,\n            )\n        } else {\n            \/\/ Normal subscription state\n            showSubscriptionUI(currentProductId)\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-linked-purchase-token-on-plan-changes&quot;&gt;&lt;strong&gt;The linked purchase token on plan changes&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;When a subscription replacement is processed (whether upgrade or downgrade), a new purchase token is generated. The new purchase includes a&amp;nbsp;&lt;code&gt;linkedPurchaseToken&lt;/code&gt;&amp;nbsp;field pointing to the old subscription. Your backend must handle this correctly to avoid creating duplicate entitlements:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-DF1P8 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/\/ Backend handler for subscription replacement\nfun handleSubscriptionReplacement(newPurchaseToken: String) {\n    val subscription = playDeveloperApi\n        .purchases()\n        .subscriptionsv2()\n        .get(packageName, newPurchaseToken)\n        .execute()\n\n    val linkedToken = subscription.linkedPurchaseToken\n\n    if (linkedToken != null) {\n        \/\/ This is a plan change, not a new purchase\n        val userId = userRepository.findByPurchaseToken(linkedToken)\n\n        \/\/ Update to new token\n        userRepository.updatePurchaseToken(userId, newPurchaseToken)\n\n        \/\/ Invalidate old token to prevent double-counting\n        subscriptionRepository.invalidate(linkedToken)\n    }\n\n    \/\/ Acknowledge the new purchase\n    acknowledgePurchase(newPurchaseToken)\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Failing to invalidate the old purchase token when processing a replacement is a common bug that leads to inflated subscriber counts and incorrect revenue reporting.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;network-failures-and-retry-strategies&quot;&gt;&lt;strong&gt;Network failures and retry strategies&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Billing operations are network dependent, and network failures or low latency are inevitable. The critical operations that can fail are the purchase flow itself, acknowledgment, consumption, and purchase verification.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-acknowledgment-window&quot;&gt;&lt;strong&gt;The acknowledgment window&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Google Play gives you three days to acknowledge a purchase. If you fail to acknowledge within this window, the purchase is automatically refunded. This is a safeguard for users, but it means your acknowledgment logic must be resilient to transient failures:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1gT2T2 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;class AcknowledgmentManager(\n    private val billingClient: BillingClient,\n    private val purchaseRepository: PurchaseRepository,\n) {\n    fun acknowledgePurchaseWithRetry(purchase: Purchase) {\n        if (purchase.isAcknowledged) return\n\n        val params = AcknowledgePurchaseParams.newBuilder()\n            .setPurchaseToken(purchase.purchaseToken)\n            .build()\n\n        billingClient.acknowledgePurchase(params) { billingResult -&gt;\n            when (billingResult.responseCode) {\n                BillingClient.BillingResponseCode.OK -&gt; {\n                    purchaseRepository.markAcknowledged(purchase.purchaseToken)\n                }\n                BillingClient.BillingResponseCode.SERVICE_UNAVAILABLE,\n                BillingClient.BillingResponseCode.SERVICE_DISCONNECTED,\n                BillingClient.BillingResponseCode.ERROR -&gt; {\n                    \/\/ Transient failure, schedule retry\n                    purchaseRepository.markPendingAcknowledgment(\n                        purchase.purchaseToken\n                    )\n                }\n                else -&gt; {\n                    \/\/ Non-retryable error, log for investigation\n                    logAcknowledgmentFailure(purchase, billingResult)\n                }\n            }\n        }\n    }\n\n    fun retryPendingAcknowledgments() {\n        val pendingTokens = purchaseRepository.getPendingAcknowledgmentTokens()\n\n        val inAppParams = QueryPurchasesParams.newBuilder()\n            .setProductType(BillingClient.ProductType.INAPP)\n            .build()\n\n        billingClient.queryPurchasesAsync(inAppParams) { result, purchases -&gt;\n            if (result.responseCode == BillingClient.BillingResponseCode.OK) {\n                purchases\n                    .filter { it.purchaseToken in pendingTokens }\n                    .filter { !it.isAcknowledged }\n                    .forEach { acknowledgePurchaseWithRetry(it) }\n            }\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;billingclient-disconnection&quot;&gt;&lt;strong&gt;BillingClient disconnection&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The&amp;nbsp;&lt;code&gt;BillingClient&lt;/code&gt;&amp;nbsp;can disconnect at any time, and operations performed on a disconnected client will fail. You should implement reconnection logic with exponential backoff:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1PzWhY wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;class BillingClientManager(\n    private val context: Context,\n    private val listener: PurchasesUpdatedListener,\n) {\n    private var billingClient: BillingClient? = null\n    private var retryCount = 0\n\n    fun connect(onConnected: () -&gt; Unit) {\n        billingClient = BillingClient.newBuilder(context)\n            .setListener(listener)\n            .enablePendingPurchases(\n                PendingPurchasesParams.newBuilder()\n                    .enableOneTimeProducts()\n                    .build()\n            )\n            .build()\n\n        billingClient?.startConnection(object : BillingClientStateListener {\n            override fun onBillingSetupFinished(billingResult: BillingResult) {\n                if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {\n                    retryCount = 0\n                    onConnected()\n                } else {\n                    retryConnection(onConnected)\n                }\n            }\n\n            override fun onBillingServiceDisconnected() {\n                retryConnection(onConnected)\n            }\n        })\n    }\n\n    private fun retryConnection(onConnected: () -&gt; Unit) {\n        if (retryCount &lt; MAX_RETRY_COUNT) {\n            retryCount++\n            val delayMs = (1000L * (1 shl retryCount)).coerceAtMost(MAX_RETRY_DELAY_MS)\n            handler.postDelayed({ connect(onConnected) }, delayMs)\n        }\n    }\n\n    companion object {\n        private const val MAX_RETRY_COUNT = 5\n        private const val MAX_RETRY_DELAY_MS = 30_000L\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;how-revenuecat-handles-these-edge-cases&quot;&gt;&lt;strong&gt;How RevenueCat handles these edge cases&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Each of the edge cases described above requires careful implementation, retry logic, and backend infrastructure. This is where RevenueCat provides significant value by abstracting away the complexity and handling these scenarios automatically.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;pending-purchases&quot;&gt;&lt;strong&gt;Pending purchases&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;RevenueCat tracks pending purchase states internally and updates&amp;nbsp;&lt;code&gt;CustomerInfo&lt;/code&gt;&amp;nbsp;when payments are confirmed. Your app only needs to check entitlements:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z2st9Fi wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;Purchases.sharedInstance.getCustomerInfoWith { customerInfo -&gt;\n    val isPremium = customerInfo.entitlements[\&amp;quot;premium\&amp;quot;]?.isActive == true\n\n    if (isPremium) {\n        showPremiumContent()\n    } else {\n        showSubscriptionOptions()\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;RevenueCat’s backend processes RTDN notifications from Google Play, so when a pending purchase completes, the entitlement is updated RevenueCat’s server-side. The next time your app queries&amp;nbsp;&lt;code&gt;CustomerInfo&lt;/code&gt;, the entitlement is active. No custom notification handling or purchase token tracking is needed on your side. If you’re a sole developer, building the overall backend infrastructure is a ton of resources.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;acknowledgment-and-consumption&quot;&gt;&lt;strong&gt;Acknowledgment and consumption&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;RevenueCat handles acknowledgment and consumption automatically. When a purchase is received by the SDK, it is verified with RevenueCat’s backend, and RevenueCat acknowledges the purchase with Google Play on your behalf. For consumable products, RevenueCat handles consumption after verification. You never need to call&amp;nbsp;&lt;code&gt;acknowledgePurchase&lt;/code&gt;&amp;nbsp;or&amp;nbsp;&lt;code&gt;consumeAsync&lt;/code&gt;&amp;nbsp;yourself.&lt;/p&gt;



&lt;p&gt;This eliminates the entire class of bugs related to failed acknowledgments, missed consumption calls, and the&amp;nbsp;&lt;code&gt;ITEM_ALREADY_OWNED&lt;/code&gt;&amp;nbsp;problem.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;subscription-plan-changes&quot;&gt;&lt;strong&gt;Subscription plan changes&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;RevenueCat provides a clean API for subscription upgrades and downgrades through&amp;nbsp;&lt;code&gt;purchaseWith&lt;/code&gt;:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1P5L2c wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;Purchases.sharedInstance.purchaseWith(\n    PurchaseParams.Builder(activity, newPackage)\n        .oldProductId(currentProductId)\n        .googleReplacementMode(GoogleReplacementMode.DEFERRED)\n        .build(),\n    onSuccess = { transaction, customerInfo -&gt;\n        \/\/ CustomerInfo reflects the new subscription state\n        updateUI(customerInfo)\n    },\n    onError = { error, userCancelled -&gt;\n        if (!userCancelled) {\n            showError(error)\n        }\n    }\n)&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;RevenueCat handles the linked purchase token logic, entitlement transitions, and deferred downgrade tracking on the backend. Your app simply checks&amp;nbsp;&lt;code&gt;CustomerInfo&lt;/code&gt;&amp;nbsp;for the current entitlement state.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;network-resilience&quot;&gt;&lt;strong&gt;Network resilience&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;RevenueCat’s SDK includes built-in retry logic for all network operations, caches&amp;nbsp;&lt;code&gt;CustomerInfo&lt;/code&gt;&amp;nbsp;locally for offline access, and synchronizes with the backend when connectivity is restored. This means your app can check entitlements even when the device is offline:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1K16UG wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/\/ This works offline using cached CustomerInfo\nPurchases.sharedInstance.getCustomerInfoWith { customerInfo -&gt;\n    val isPremium = customerInfo.entitlements[\&amp;quot;premium\&amp;quot;]?.isActive == true\n    updateUI(isPremium)\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The SDK distinguishes between stale and fresh data, retries failed operations with exponential backoff, and ensures that entitlements are eventually consistent with the server-side state.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;/h2&gt;



&lt;p&gt;In this article, you’ve explored the edge cases that separate a sample billing integration from a production one.&lt;/p&gt;



&lt;p&gt;Each of these scenarios has a well defined solution using the Play Billing Library directly, but the cumulative implementation effort is significant. You need client-side handling, backend RTDN processing, retry mechanisms, and careful state management across all of them. For teams that want to ship subscription features without building and maintaining this infrastructure, RevenueCat handles these edge cases automatically, letting you check a single&amp;nbsp;&lt;code&gt;CustomerInfo&lt;/code&gt;&amp;nbsp;object instead of managing the complexity yourself.&lt;/p&gt;



&lt;p&gt;Whether you build the billing infrastructure directly or use RevenueCat, understanding these edge cases is essential. They represent the difference between a billing system that works in testing and one that works reliably for millions of users across diverse markets and payment methods.&lt;/p&gt;



&lt;p&gt;As always, happy coding!&lt;/p&gt;



&lt;p&gt;— Jaewoong&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[How to submit your app for Shipyard]]></title><description><![CDATA[Everything you need to know to make your app installable, testable, and ready for Shipyard judging.]]></description><link>https://www.revenuecat.com/blog/engineering/how-to-submit-your-app-for-shipyard/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/how-to-submit-your-app-for-shipyard/</guid><pubDate>Fri, 30 Jan 2026 12:17:47 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Shipyard_Blog_HowToSubmit_1600x800_v1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Submitting your app to Shipyard should be straightforward, as you don’t need to navigate app store reviews or production release requirements to participate. What matters is that judges can install and evaluate your app reliably during the hackathon.&lt;/p&gt;



&lt;p&gt;This article explains exactly what is required, what is optional, and how to submit your app correctly.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-shipyard-rule-recap&quot;&gt;Shipyard rule recap&lt;/h2&gt;



&lt;p&gt;Before you submit your app, make sure your app adheres to the rules of Shipyard:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Mobile apps only — iOS, Android, or cross-platform (no web/desktop apps)&lt;/li&gt;



&lt;li&gt;All projects must be started and completed within the hackathon timeframe&lt;/li&gt;



&lt;li&gt;Participants can only submit one app for one brief — choose wisely!&lt;/li&gt;



&lt;li&gt;RevenueCat integration is mandatory — subscriptions or in-app purchases&lt;/li&gt;



&lt;li&gt;Apps must be on TestFlight (iOS) or Play Internal Testing (Android) — you can have the app live on app stores, but this isn’t required&lt;/li&gt;



&lt;li&gt;Developers retain full ownership of all intellectual property&lt;/li&gt;



&lt;li&gt;If you use an influencer’s name or likeness, you must remove it before public launch (unless agreed with the influencer)&lt;/li&gt;



&lt;li&gt;Any post-hackathon collaboration with influencers is separate from RevenueCat&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Let’s take a closer look at a few key rules next.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-what-can-you-build-your-app-with-nbsp&quot;&gt;What can you build your app with?&amp;nbsp;&lt;/h3&gt;



&lt;p&gt;The main goal of Shipyard: Creator Contest is to build an MVP of a mobile app for the selected creators’ audience. You can use any technology (Swift, Kotlin, Flutter, React Native, etc.) or tool (Cursor, Xcode, Claude, Vibecode, Rork, etc.), as long as it produces a mobile app that can be uploaded to either Apple App Store or Google Play Store. This means that web apps are out of the scope of this hackathon. Tools such as Capacitor are allowed, in case you’re turning a web app into a native mobile app.&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-Z21GYic wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Get ahead with our Shipping Container 📦&quot; text=&quot;&lt;p&gt;When you register for Shipyard, you&apos;ll receive a Shipping Container email within 48 hours that details perks, discounts, and freebies from our partner tools. &lt;a href=&amp;quot;https://revenuecat-shipyard-2026.devpost.com/resources&amp;quot;&gt;More details here.&lt;/a&gt; Enjoy!&lt;/p&gt;&quot; icon=&quot;sparks&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-your-app-must-have-revenuecat-integrated-nbsp&quot;&gt;Your app must have RevenueCat integrated&amp;nbsp;&lt;/h3&gt;



&lt;p&gt;Your app must have a version of the RevenueCat SDK installed on it, and you must have your in-app purchases configured for the platforms your app is targeting, and the in-app purchase products need to be purchasable. Test store configuration &lt;strong&gt;is not counted&lt;/strong&gt; as an integrated SDK.&lt;/p&gt;



&lt;p&gt;Full configuration of RevenueCat requires you to have either an Apple Developer account or Google Play developer account.&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Your app must have RevenueCat SDK integrated&lt;/li&gt;



&lt;li&gt;App must have subscriptions and/or in-app purchases&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Test store integration is not enough&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-apps-must-be-on-testflight-ios-or-a-google-play-testing-track-android&quot;&gt;Apps must be on TestFlight (iOS) or a Google Play testing track (Android)&lt;/h3&gt;



&lt;p&gt;Your app must be distributable through either TestFlight in App Store Connect, for iOS apps; or Google Play Public/Closed/Internal testing track, for Android apps. This means that you need to have an account on at least one of those stores for the app you’re submitting. Sadly RevenueCat is unable to cover the cost of the developer account for participants.&lt;/p&gt;



&lt;p&gt;For TestFlight distribution, at least one app has to have been submitted to App Store Connect, and made available for distribution on the TestFlight tab. The app you submit to Shipyard should have &lt;strong&gt;External testing&lt;/strong&gt; enabled, with a public link. Attach the public link to your Devpost submission.&lt;/p&gt;



&lt;p&gt;For Google Play Console testing tracks, your app has to be uploaded to Google Play Console and made available through an Internal, Closed, or Public testing track so judges can install and evaluate it.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-you-can-publish-your-app-but-it-s-optional&quot;&gt;You CAN publish your app (but it’s optional)&lt;/h3&gt;



&lt;p&gt;Making your app public and publishing for people to download from the App Store and Google Play Store is allowed during and after the hackathon. Doing this will not affect judging, but you’re also not required to wait on publishing your app.&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Publishing during Shipyard is allowed&lt;/li&gt;



&lt;li&gt;Publishing does not disqualify your app&lt;/li&gt;



&lt;li&gt;Publishing does not affect judging&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-to-submit-your-app-to-shipyard&quot;&gt;How to submit your app to Shipyard&lt;/h2&gt;



&lt;p&gt;Your app needs to be testable on either iOS or Android devices, with distribution done either through &lt;a href=&quot;https://developer.apple.com/testflight/&quot;&gt;TestFlight for iOS&lt;/a&gt;, or one of Google Play Console testing tracks for Android.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-app-testing-and-revenuecat-verification&quot;&gt;App testing and RevenueCat verification&lt;/h2&gt;



&lt;p&gt;Due to the number of submissions, we do not guarantee that every app will be fully installed and tested by judges. The required demo video is the primary way judges will be viewing &lt;em&gt;all &lt;/em&gt;apps, before shortlisted apps will be viewed in more detail.&lt;/p&gt;



&lt;p&gt;However, all winning apps will be installed and tested to verify correct integration of the RevenueCat SDK and confirm that subscriptions and/or in-app purchases are implemented as described. If a winning app cannot be installed or does not have a working RevenueCat integration, it may be disqualified and the award reassigned.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;To avoid issues, make sure your submitted build is installable, stable, and matches what is shown in your demo video.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-how-to-submit-your-ios-app-nbsp&quot;&gt;How to submit your iOS app&amp;nbsp;&lt;/h3&gt;



&lt;p&gt;First, upload at least one build of your app to App Store Connect using Xcode. Once the build is processed, go to the TestFlight tab and enable External Testing. Create a public TestFlight link so anyone with the link can install the app without being added manually.&lt;/p&gt;



&lt;p&gt;Make sure the build you share is stable, launches correctly, and allows judges to reach the core functionality of your app. If your app includes subscriptions or in-app purchases, they must be purchasable, meaning that you’ve integrated RevenueCat with App Store connect.&lt;/p&gt;



&lt;p&gt;Finally, copy the public TestFlight link and include it in your Shipyard (Devpost) submission. Judges will use this link to install and evaluate your app.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-how-to-submit-your-android-app&quot;&gt;How to submit your Android app&lt;/h3&gt;



&lt;p&gt;To submit an Android app to Shipyard, your app must be installable by judges through one of Google Play’s testing tracks.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Internal testing&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Upload your app to the &lt;strong&gt;Google Play Console&lt;/strong&gt; and create an &lt;strong&gt;Internal testing&lt;/strong&gt; track. Add &lt;strong&gt;shipyard-android@revenuecat.com&lt;/strong&gt; as a tester email so judges can access the app. Once the build is approved for internal testing, verify that the app installs correctly and that all core functionality is accessible.&lt;/p&gt;



&lt;p&gt;If your app includes subscriptions or in-app purchases, they must be purchasable, meaning that you’ve integrated RevenueCat with Google Play Console.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Closed testing&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Alternatively, you can use a &lt;strong&gt;Closed testing&lt;/strong&gt; track. Upload your build to the closed track and add &lt;strong&gt;shipyard-android@revenuecat.com&lt;/strong&gt; to the tester list (either directly by email or via a Google Group that includes this address). Make sure access is granted before submitting.&lt;/p&gt;



&lt;p&gt;Confirm that the app installs cleanly and that judges can reach the main features without additional setup.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Public testing&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;You may also use &lt;strong&gt;Public testing&lt;/strong&gt;. Upload your app to a public testing track and ensure the app is available for anyone to install without requiring approval. Share a link to your public testing version in the Devpost submission.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-summary&quot;&gt;Summary&lt;/h2&gt;



&lt;p&gt;Shipyard does not require you to launch your app publicly, but it does require that judges can reliably install and test it. As long as your app is available through TestFlight (iOS) or a Google Play testing track (Android) and includes a working RevenueCat integration, you’re good to submit.&lt;/p&gt;



&lt;p&gt;Publishing your app to the App Store or Google Play during or after the hackathon is optional and does not affect judging. Focus on shipping a solid, testable MVP. If judges can install your app and experience its core functionality, you’ve met the submission requirements.&lt;/p&gt;



&lt;p&gt;If anything is unclear, &lt;a href=&quot;https://discord.gg/3aV6EUCYqR&quot;&gt;ask in Discord&lt;/a&gt;. We’re happy to help you get unstuck quickly. Happy shipping!&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[RevenueCat Paywalls changelog]]></title><description><![CDATA[Get the latest updates to RevenueCat Paywalls]]></description><link>https://www.revenuecat.com/blog/engineering/paywalls-changelog/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/paywalls-changelog/</guid><pubDate>Thu, 29 Jan 2026 15:33:17 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Changelog.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/feature/paywalls/&quot;&gt;RevenueCat Paywalls&lt;/a&gt; is our native paywall builder that lets you build and &lt;a href=&quot;https://www.revenuecat.com/blog/growth/paywalls-study-guide/&quot;&gt;optimize paywalls&lt;/a&gt; in real-time through RevenueCat’s dashboard, no app updates or code changes needed. In summer 2025 we rebuilt RevenueCat Paywalls from the ground up. What was once a simple, template-first tool is &lt;strong&gt;now a fully flexible, component-based editor&lt;/strong&gt; where you can design fully custom layouts, localize every string, and tailor the experience to every segment.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;But we’re not stopping there, we’ve been on a particularly rampant shipping spree as of November 2025. We’re shipping the most-requested and most impactful updates to Paywalls with a clear goal to make it the best paywall builder for every app.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;This blog will serve as a living changelog for all-things RevenueCat Paywalls, so bookmark it to follow along and keep up with everything new. &lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-Z2d6oYM wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Keep in the loop with RevenueCat product updates&quot; text=&quot;&lt;p&gt;See every update to RevenueCat and all its features in our &lt;a href=&amp;quot;https://www.revenuecat.com/changelog&amp;quot;&gt;main changelog, right here&lt;/a&gt;.&lt;/p&gt;&quot; icon=&quot;gear&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-a-new-paywalls-editor-layout&quot;&gt;A new Paywalls editor layout&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;538&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-1024x538.png&quot; alt=&quot;&quot; class=&quot;wp-image-50975&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-1024x538.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-768x403.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-696x365.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-560x294.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-840x441.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar.png 1200w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;We’ve refreshed the Paywalls editor with a sidebar-based layout that replaces the old dual-panel interface. Core areas like components, layers, branding, media, and localization now live in clearly labeled tabs, making the editor easier to navigate and simpler to learn.&lt;/p&gt;



&lt;p&gt;The new layout keeps the canvas front and center while giving us room to keep expanding Paywalls over time. As features grow, the editor stays organized instead of crowded, even when you’re working on more complex paywalls.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/tools/paywalls/creating-paywalls#using-the-editor&quot;&gt;Explore the new editor ↗&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-keyboard-shortcuts-for-faster-editing&quot;&gt;Keyboard shortcuts for faster editing&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;538&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Keyboard-Shortcuts-1024x538.png&quot; alt=&quot;&quot; class=&quot;wp-image-50977&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Keyboard-Shortcuts-1024x538.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Keyboard-Shortcuts-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Keyboard-Shortcuts-768x403.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Keyboard-Shortcuts-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Keyboard-Shortcuts-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Keyboard-Shortcuts-696x365.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Keyboard-Shortcuts-560x294.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Keyboard-Shortcuts-840x441.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Keyboard-Shortcuts-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Keyboard-Shortcuts-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Keyboard-Shortcuts.png 1200w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;When you’re iterating quickly, small interactions add up. The Paywalls editor now supports Figma-style keyboard shortcuts for common actions like moving, duplicating, selecting, and deleting components.&lt;/p&gt;



&lt;p&gt;To make shortcuts easy to discover, we added a help icon inside the editor that shows the full list of supported commands. You can open it at any time, pick up shortcuts as you go, and keep your focus on the layout instead of the UI.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/tools/paywalls/creating-paywalls&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;View all shortcuts ↗&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-copy-and-paste-components-between-paywalls&quot;&gt;Copy and paste components between paywalls&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;538&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-CopyPaste-1024x538.png&quot; alt=&quot;&quot; class=&quot;wp-image-50979&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-CopyPaste-1024x538.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-CopyPaste-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-CopyPaste-768x403.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-CopyPaste-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-CopyPaste-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-CopyPaste-696x365.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-CopyPaste-560x294.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-CopyPaste-840x441.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-CopyPaste-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-CopyPaste-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-CopyPaste.png 1200w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;You can now copy and paste components across different paywalls, not just within a single one. This makes it much easier to reuse layouts that already work, like hero sections, benefit lists, or pricing blocks.&lt;/p&gt;



&lt;p&gt;When you paste a component into another paywall, its structure, styling, and bindings come with it. For teams running multiple campaigns or experiments, this cuts down on repetitive work and helps keep designs consistent across variations.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-a-dedicated-branding-tab&quot;&gt;A dedicated Branding tab&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;538&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Brand-Settings-1024x538.png&quot; alt=&quot;&quot; class=&quot;wp-image-50981&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Brand-Settings-1024x538.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Brand-Settings-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Brand-Settings-768x403.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Brand-Settings-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Brand-Settings-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Brand-Settings-696x365.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Brand-Settings-560x294.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Brand-Settings-840x441.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Brand-Settings-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Brand-Settings-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Brand-Settings.png 1200w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;We’ve added a new Branding tab to the Paywalls editor to centralize your visual system. You can now manage saved colors, gradients, and custom fonts in one place and reuse them across all paywalls in your project.&lt;/p&gt;



&lt;p&gt;Branding assets appear directly in color and typography pickers while you edit, which makes it easier to stay on brand and avoid one-off values. This also simplifies collaboration, since teams can standardize styles once and confidently build on top of them.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-a-new-media-gallery&quot;&gt;A new Media gallery&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;538&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Media-Gallery-1024x538.png&quot; alt=&quot;&quot; class=&quot;wp-image-50983&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Media-Gallery-1024x538.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Media-Gallery-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Media-Gallery-768x403.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Media-Gallery-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Media-Gallery-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Media-Gallery-696x365.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Media-Gallery-560x294.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Media-Gallery-840x441.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Media-Gallery-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Media-Gallery-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Media-Gallery.png 1200w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Managing images across paywalls is now smoother with the new Media gallery. You can see all uploaded assets in one place, preview them at a glance, and clean up files you no longer need.&lt;/p&gt;



&lt;p&gt;Uploading images is as simple as dragging and dropping them into the gallery. When editing a paywall, you can reuse existing assets instead of uploading the same file again. This is especially helpful for teams running many paywalls that share artwork or campaign visuals.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-safer-localization-with-out-of-date-alerts&quot;&gt;Safer localization with out-of-date alerts&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;538&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Localization-1024x538.png&quot; alt=&quot;&quot; class=&quot;wp-image-50985&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Localization-1024x538.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Localization-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Localization-768x403.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Localization-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Localization-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Localization-696x365.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Localization-560x294.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Localization-840x441.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Localization-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Localization-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Localization.png 1200w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Localization is now more transparent. When you update text in the default language, the editor automatically detects which translations are out of date.&lt;/p&gt;



&lt;p&gt;A warning badge appears in the sidebar, along with a clear list of affected locales and fields. From there, you can update translations with one click or dismiss the warning if the change is intentional. This helps prevent silent copy drift and keeps global paywalls aligned as content evolves.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/tools/paywalls/creating-paywalls/localization&quot;&gt;Learn more about localization ↗&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-exit-offers-on-paywall-dismissal&quot;&gt;Exit offers on paywall dismissal&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;538&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Exit-Offer-1024x538.png&quot; alt=&quot;&quot; class=&quot;wp-image-50987&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Exit-Offer-1024x538.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Exit-Offer-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Exit-Offer-768x403.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Exit-Offer-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Exit-Offer-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Exit-Offer-696x365.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Exit-Offer-560x294.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Exit-Offer-840x441.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Exit-Offer-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Exit-Offer-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Exit-Offer.png 1200w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;You can now configure an exit offer that appears when a user closes a paywall without purchasing. Instead of ending the flow immediately, you can present a second paywall with an alternative offer.&lt;/p&gt;



&lt;p&gt;This is useful for scenarios like offering a different billing option, a lower price, or a final reminder before the user leaves. Exit offers work across iOS, Android, and hybrid SDKs, and integrate cleanly with existing paywalls and experiments.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/tools/paywalls/displaying-paywalls#exit-offers&quot;&gt;Configure an exit offer ↗&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-auto-save-for-paywall-drafts&quot;&gt;Auto-save for paywall drafts&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;538&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Auto-save-1024x538.png&quot; alt=&quot;&quot; class=&quot;wp-image-50989&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Auto-save-1024x538.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Auto-save-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Auto-save-768x403.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Auto-save-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Auto-save-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Auto-save-696x365.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Auto-save-560x294.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Auto-save-840x441.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Auto-save-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Auto-save-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Sidebar-Auto-save.png 1200w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The Paywalls editor now auto-saves drafts as you work. Changes are saved continuously in the background, which reduces the risk of losing progress if you navigate away or refresh the page.&lt;/p&gt;



&lt;p&gt;Auto-save also surfaces validation issues earlier, since drafts are saved more frequently. Publishing behavior stays the same. Nothing goes live until you choose to publish, but editing feels safer and smoother, especially during longer design sessions.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-export-figma-designs-straight-into-paywalls&quot;&gt;Export Figma designs straight into Paywalls&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;576&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/figma-integration-1-1024x576.png&quot; alt=&quot;&quot; class=&quot;wp-image-48638&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/figma-integration-1-1024x576.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/figma-integration-1-300x169.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/figma-integration-1-768x432.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/figma-integration-1-1536x864.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/figma-integration-1-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/figma-integration-1-71x40.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/figma-integration-1-696x392.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/figma-integration-1-560x315.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/figma-integration-1-526x296.png 526w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/figma-integration-1.png 1920w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Design handoff shouldn’t mean starting over. And now, it doesn’t.&lt;/p&gt;



&lt;p&gt;You can export Figma mockups directly into the Paywall editor. Your layout comes in as native Paywalls components, so you can immediately:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Edit copy without touching the structure&lt;/li&gt;



&lt;li&gt;Swap products and packages&lt;/li&gt;



&lt;li&gt;Localize text&lt;/li&gt;



&lt;li&gt;Add experiments&lt;/li&gt;



&lt;li&gt;Target specific audiences&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The practical win is speed. Designers stay in Figma, and the team shipping paywall tests can go from final mock to live variant, without recreating the layout by hand.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://e.customeriomail.com/e/c/eyJlIjoxNzQzMDMsImVtYWlsX2lkIjoiZXhhbXBsZSIsImhyZWYiOiJodHRwczovL3d3dy5yZXZlbnVlY2F0LmNvbS9ibG9nL2VuZ2luZWVyaW5nL3JldmVudWVjYXQtZmlnbWEtcGx1Z2luLz91dG1fY2FtcGFpZ249Tm92ZW1iZXIrTmV3c2xldHRlclx1MDAyNnV0bV9jb250ZW50PU5vdmVtYmVyK05ld3NsZXR0ZXJcdTAwMjZ1dG1fbWVkaXVtPWVtYWlsX2FjdGlvblx1MDAyNnV0bV9zb3VyY2U9Y3VzdG9tZXIuaW8iLCJ0IjoxNzY0Njk3MDQ3fQ/b7d9d39cf861b68d6a988cd66fe5fd508b68ba0a2a9bb287d78acde049e07132&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Import a Figma &lt;/a&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/engineering/revenuecat-figma-plugin&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;design&lt;/a&gt;&lt;a href=&quot;https://e.customeriomail.com/e/c/eyJlIjoxNzQzMDMsImVtYWlsX2lkIjoiZXhhbXBsZSIsImhyZWYiOiJodHRwczovL3d3dy5yZXZlbnVlY2F0LmNvbS9ibG9nL2VuZ2luZWVyaW5nL3JldmVudWVjYXQtZmlnbWEtcGx1Z2luLz91dG1fY2FtcGFpZ249Tm92ZW1iZXIrTmV3c2xldHRlclx1MDAyNnV0bV9jb250ZW50PU5vdmVtYmVyK05ld3NsZXR0ZXJcdTAwMjZ1dG1fbWVkaXVtPWVtYWlsX2FjdGlvblx1MDAyNnV0bV9zb3VyY2U9Y3VzdG9tZXIuaW8iLCJ0IjoxNzY0Njk3MDQ3fQ/b7d9d39cf861b68d6a988cd66fe5fd508b68ba0a2a9bb287d78acde049e07132&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt; ↗&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-keyboard-shortcuts-in-the-paywalls-editor&quot;&gt;Keyboard shortcuts in the Paywalls editor&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;538&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Shortcuts-1024x538.png&quot; alt=&quot;&quot; class=&quot;wp-image-48626&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Shortcuts-1024x538.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Shortcuts-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Shortcuts-768x403.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Shortcuts-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Shortcuts-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Shortcuts-696x365.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Shortcuts-560x294.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Shortcuts-840x441.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Shortcuts-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Shortcuts-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Shortcuts.png 1200w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;When you’re iterating quickly, little clicks add up.&lt;/p&gt;



&lt;p&gt;The Paywalls editor now supports keyboard shortcuts for the actions you use most, including adding components, duplicating sections, undoing and redoing changes, and deleting blocks. It keeps you in flow and makes fast iteration feel genuinely lightning quick.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/tools/paywalls/creating-paywalls&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;View all shortcuts ↗&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-preview-your-paywall-on-more-devices&quot;&gt;Preview your paywall on more devices&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;538&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Device-Preview-1024x538.png&quot; alt=&quot;&quot; class=&quot;wp-image-48628&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Device-Preview-1024x538.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Device-Preview-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Device-Preview-768x403.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Device-Preview-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Device-Preview-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Device-Preview-696x365.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Device-Preview-560x294.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Device-Preview-840x441.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Device-Preview-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Device-Preview-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Device-Preview.png 1200w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;A paywall can look perfect on one screen and awkward on another. That used to be something you discovered after publishing, but now you can preview paywalls across a wider set of iOS and Android phones and tablets. The canvas updates to real screen sizes, so you can flip through devices in seconds to:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Catch spacing issues early&lt;/li&gt;



&lt;li&gt;Confirm font sizes&lt;/li&gt;



&lt;li&gt;Check crops and media positioning&lt;/li&gt;



&lt;li&gt;Sanity-check scroll behavior&lt;/li&gt;



&lt;li&gt;Make sure your CTA lands where you want it&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;It’s a simple change that prevents a lot of last-minute fixes.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-filter-paywall-templates&quot;&gt;Filter paywall templates&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;538&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywall-gallery-filters-1024x538.png&quot; alt=&quot;&quot; class=&quot;wp-image-48630&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywall-gallery-filters-1024x538.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywall-gallery-filters-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywall-gallery-filters-768x403.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywall-gallery-filters-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywall-gallery-filters-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywall-gallery-filters-696x365.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywall-gallery-filters-560x294.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywall-gallery-filters-840x441.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywall-gallery-filters-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywall-gallery-filters-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywall-gallery-filters.png 1200w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Templates are only helpful if you can find the right one quickly.&lt;/p&gt;



&lt;p&gt;The template gallery now includes filters by purchase method, tier, or package. It’s especially useful when you know the pattern you want up front, like a trial-first layout, a pricing grid, or a promo-ready design. You spend less time searching and more time shipping.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/tools/paywalls/creating-paywalls&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Start with a template ↗&lt;/a&gt;&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-E5Uj7 wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Stuck for inspiration?&quot; text=&quot;&lt;p&gt;&lt;a href=&amp;quot;https://www.paywalls.com/&amp;quot;&gt;paywalls.com&lt;/a&gt; is the definitive source for real app paywalls. Filter by industry, component, or downloads to find examples and inspiration.&amp;nbsp;&lt;/p&gt;&quot; icon=&quot;bulb&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-countdown-component-for-your-paywall&quot;&gt;Countdown component for your paywall&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;538&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Countdown-Component-1-1024x538.png&quot; alt=&quot;&quot; class=&quot;wp-image-48632&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Countdown-Component-1-1024x538.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Countdown-Component-1-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Countdown-Component-1-768x403.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Countdown-Component-1-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Countdown-Component-1-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Countdown-Component-1-696x365.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Countdown-Component-1-560x294.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Countdown-Component-1-840x441.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Countdown-Component-1-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Countdown-Component-1-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Countdown-Component-1.png 1200w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Promos can be a great paywall technique, but they only work best when urgency is clear and real. To help, you can now add a countdown timer to any paywall. Set an end date once and the timer updates automatically. No extra code, no manual updates. &lt;/p&gt;



&lt;p&gt;This is built for campaigns like &lt;a href=&quot;https://www.revenuecat.com/blog/growth/promotional-offers-sales-app/&quot;&gt;Black Friday, launch promos, limited-time discounts, or any offer&lt;/a&gt; where timing helps people decide.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/tools/paywalls/creating-paywalls/components#countdown&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Add a Countdown ↗&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-project-level-brand-color-settings&quot;&gt;Project level brand color settings&lt;/h2&gt;



&lt;figure class=&quot;wp-block-video&quot;&gt;&lt;video height=&quot;1080&quot; style=&quot;aspect-ratio: 1920 / 1080;&quot; width=&quot;1920&quot; controls=&quot;&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/brand-colors-screencapture.mp4&quot;&gt;&lt;/video&gt;&lt;/figure&gt;



&lt;p&gt;Setup brand colors now in project settings that are available in the Paywalls editor (and soon more places).&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-real-prices-displayed-in-the-paywalls-editor&quot;&gt;Real prices displayed in the Paywalls Editor&lt;/h2&gt;



&lt;figure class=&quot;wp-block-video&quot;&gt;&lt;video height=&quot;1080&quot; style=&quot;aspect-ratio: 1920 / 1080;&quot; width=&quot;1920&quot; controls=&quot;&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/real-prices-screencapture.mp4&quot;&gt;&lt;/video&gt;&lt;/figure&gt;



&lt;p&gt;Previously, placeholder values displayed for product prices while being viewed in the dashboard editor. This latest update makes it so that you now see the real prices in the editor. This makes it much easier to get a more realistic version of the paywall while you’re working on it. (The one caveat is we will need to have seen at least one test purchase with this product for it to display).&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-use-ai-to-create-a-paywall&quot;&gt;Use AI to create a paywall&lt;/h2&gt;



&lt;figure class=&quot;wp-block-video&quot;&gt;&lt;video height=&quot;1080&quot; style=&quot;aspect-ratio: 1920 / 1080;&quot; width=&quot;1920&quot; controls=&quot;&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/ai-paywall-screencapture.mp4&quot;&gt;&lt;/video&gt;&lt;/figure&gt;



&lt;p&gt;You can now use artificial intelligence to create a paywall based on data from an app store page. A great way to get inspiration or a solid starting point to adjust from and test. &lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-videos-in-paywalls&quot;&gt;Videos in Paywalls&lt;/h2&gt;



&lt;figure class=&quot;wp-block-video&quot;&gt;&lt;video height=&quot;1080&quot; style=&quot;aspect-ratio: 1920 / 1080;&quot; width=&quot;1920&quot; controls=&quot;&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/video-component-screencapture.mp4&quot;&gt;&lt;/video&gt;&lt;/figure&gt;



&lt;p&gt;Paywalls now support videos being added as their own component, just like images.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-video-backgrounds&quot;&gt;Video backgrounds&lt;/h2&gt;



&lt;p&gt;Videos can now be set as backgrounds on the root paywall, footer, or any parent component (stacks, packages, etc).&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-intercept-purchase-intent&quot;&gt;Intercept purchase intent&lt;/h2&gt;



&lt;p&gt;Native iOS &amp;amp; Android SDKs now offer a method to intercept purchase intent (tapping on the purchase CTA) to display custom UIs before choosing to proceed with the purchase flow. Use cases that apps find for this include: Age gate/parental consent: display a UI that acts as an age gate before letting someone proceed to purchase, Disclosures: If there’s additional info you want/need to present to a customer and have them confirm before proceeding (country specific terms, legal language, etc.)&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-view-all-plans-sheets&quot;&gt;View all plans (sheets)&lt;/h2&gt;



&lt;figure class=&quot;wp-block-video&quot;&gt;&lt;video height=&quot;1080&quot; style=&quot;aspect-ratio: 1920 / 1080;&quot; width=&quot;1920&quot; controls=&quot;&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/sheets-screencapture.mp4&quot;&gt;&lt;/video&gt;&lt;/figure&gt;



&lt;p&gt;You can now choose to have your button navigate to a sheet that can be used to display additional content. When you select a sheet as the destination to navigate to, you’ll see a new&amp;nbsp;&lt;strong&gt;Sheet&lt;/strong&gt;&amp;nbsp;component inside of your button in the Components panel. When the sheet or any component within it is selected, you’ll see the sheet displayed in the paywall preview. You can add components to the sheet just as you would to any other stack.&lt;/p&gt;



&lt;p&gt;Sheet’s can have their own packages &amp;amp; purchase buttons so that customers can directly make a purchase from the options displayed within the sheet. &lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/tools/paywalls/creating-paywalls/components#navigate-to-sheet&quot;&gt;Learn more in our Documentation ↗&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[How Sebastian Röhl built HabitKit by sticking with what worked (and starting over when it didn’t)]]></title><description><![CDATA[On the podcast, I talk with Sebastian about the power of building in public, how persistence pays off when growth is slow, and why focusing on user needs and iterative improvement can lead to unexpected success in indie app development.]]></description><link>https://www.revenuecat.com/blog/growth/sebastian-rohl-habitkit-launched-podcast-2026/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/sebastian-rohl-habitkit-launched-podcast-2026/</guid><pubDate>Wed, 28 Jan 2026 13:50:47 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/LD-Blog-Cover-Sebastian-Rohl-1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Sebastian Röhl didn’t stumble into success as an indie app developer. He shipped an app that went nowhere, burned out, started again, and only then saw momentum compound.&lt;/p&gt;



&lt;p&gt;In the latest Sub Club episode, Sebastian—the indie developer behind &lt;strong&gt;HabitKit&lt;/strong&gt; and &lt;strong&gt;FocusKit&lt;/strong&gt;—walks through the slow, uncertain middle of app building: stalled growth, unclear signals, and the decision to keep going even when nothing looks like it’s working yet.&lt;/p&gt;



&lt;p&gt;This isn’t a story about overnight success. It’s a story about persistence, timing, and doing enough of the basics well that growth eventually has somewhere to land.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;There Is No Easy Mode: Launching Apps After Your First Success — Sebastian Röhl, HabitKit&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/VBYA6gO8weg?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;iframe loading=&quot;lazy&quot; width=&quot;100%&quot; height=&quot;180&quot; frameborder=&quot;no&quot; scrolling=&quot;no&quot; seamless=&quot;&quot; src=&quot;https://share.transistor.fm/e/609158aa?color=FFFFFF&amp;amp;background=30343C&quot;&gt;&lt;/iframe&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-from-a-safe-job-to-a-self-imposed-deadline&quot;&gt;From a safe job to a self-imposed deadline&lt;/h2&gt;



&lt;p&gt;After studying computer science and software engineering in Germany, Sebastian took a stable enterprise software job working with C#, .NET, and Angular. The work wasn’t exciting, but it gave him strong fundamentals and exposure to experienced engineers.&lt;/p&gt;



&lt;p&gt;At the same time, he was quietly drawn to the idea of building his own business. After three years, he quit without a concrete plan and gave himself a clear constraint: &lt;strong&gt;12 months to make something work&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;As Sebastian explains in the episode, he didn’t leave with a polished business idea. He left knowing only that he wanted to build something for himself—and that mobile apps felt like the right medium.&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-first-app-didn-t-fail-but-it-didn-t-work-either&quot;&gt;The first app didn’t fail—but it didn’t work either&lt;/h2&gt;



&lt;p&gt;That first attempt was &lt;strong&gt;LiftBear&lt;/strong&gt;, a workout tracker Sebastian built for his own use. He shipped quickly, skipped beta testing, and marketed it only by sharing progress publicly on Twitter.&lt;/p&gt;



&lt;p&gt;The result was discouraging but instructive.&lt;/p&gt;



&lt;p&gt;LiftBear attracted a small number of users and eventually settled at around &lt;strong&gt;$150 in monthly recurring revenue&lt;/strong&gt;. It wasn’t dead—but it wasn’t growing, either. After six months of updates and incremental improvements, progress had stalled.&lt;/p&gt;



&lt;p&gt;Sebastian describes this period as deeply demotivating. The app wasn’t clearly failing, but it wasn’t giving him any signal that doubling down would change the outcome.&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-habitkit-started-with-one-visual-that-resonated-immediately&quot;&gt;HabitKit started with one visual that resonated immediately&lt;/h2&gt;



&lt;p&gt;HabitKit came from a much simpler idea: Sebastian wanted a habit tracker that visualized consistency using a &lt;strong&gt;GitHub-style contribution grid&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;When he shared the first screenshot publicly, the response was immediate. Engagement spiked, new followers arrived, and for the first time, there was clear interest &lt;em&gt;before&lt;/em&gt; launch.&lt;/p&gt;



&lt;p&gt;That signal changed his energy entirely. He focused fully on HabitKit and released the first version after about two months of development.&lt;/p&gt;



&lt;p&gt;The launch was modest by startup standards, but meaningful for an indie developer: roughly &lt;strong&gt;$150 in revenue on day one&lt;/strong&gt;. More importantly, it showed that people understood the product instantly.&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-building-in-public-helped-early-but-wasn-t-the-long-term-growth-engine&quot;&gt;Building in public helped early—but wasn’t the long-term growth engine&lt;/h2&gt;



&lt;p&gt;Early on, building in public played a critical role. It helped HabitKit get its first users, early ratings, and initial momentum. It also gave Sebastian accountability and motivation during the quiet early months.&lt;/p&gt;



&lt;p&gt;But the biggest growth moment didn’t come from social media.&lt;/p&gt;



&lt;p&gt;Months after launch—after Sebastian had already returned to a four-day-a-week job—HabitKit suddenly began ranking for &lt;strong&gt;“habit tracker”&lt;/strong&gt; in multiple App Store regions, including Germany and the UK. Shortly after, Google Play followed.&lt;/p&gt;



&lt;p&gt;There was no viral post, no major metadata change, and no obvious trigger. Sebastian still isn’t sure why it happened. What &lt;em&gt;was&lt;/em&gt; clear is that once HabitKit crossed a certain threshold, downloads and revenue accelerated quickly.&lt;/p&gt;



&lt;p&gt;This was the moment when earlier work—product quality, reviews, consistency—finally paid off.&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-going-back-to-a-job-wasn-t-the-end-of-the-story&quot;&gt;Going back to a job wasn’t the end of the story&lt;/h2&gt;



&lt;p&gt;When the original 12-month deadline expired, HabitKit still couldn’t support Sebastian full time. He returned to his previous company, working four days a week and reserving Fridays for his apps.&lt;/p&gt;



&lt;p&gt;That fallback plan gave him stability—and time.&lt;/p&gt;



&lt;p&gt;Six to seven months later, HabitKit’s growth was no longer ambiguous. With organic discovery compounding and revenue climbing steadily, Sebastian felt confident quitting again. This time, the decision was grounded in traction, not hope.&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-focuskit-was-about-motivation-not-diversification&quot;&gt;FocusKit was about motivation, not diversification&lt;/h2&gt;



&lt;p&gt;After years focused almost exclusively on HabitKit, Sebastian noticed something else stalling: his own motivation.&lt;/p&gt;



&lt;p&gt;Updates became incremental. Public writing felt repetitive. To reintroduce novelty, he started &lt;strong&gt;FocusKit&lt;/strong&gt;, a minimalist Pomodoro timer built natively with SwiftUI.&lt;/p&gt;



&lt;p&gt;FocusKit wasn’t created to replace HabitKit or immediately match its revenue. It was a way to learn new technologies, lean into native iOS design, and regain creative momentum.&lt;/p&gt;



&lt;p&gt;The launch was intentionally low-pressure. Early revenue has been modest, but the project serves a different purpose: keeping Sebastian engaged, curious, and shipping.&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-sebastian-s-journey-shows-about-indie-app-growth&quot;&gt;What Sebastian’s journey shows about indie app growth&lt;/h2&gt;



&lt;p&gt;Sebastian’s story isn’t built around clever hacks or aggressive growth tactics. It’s built around fundamentals:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Shipping products he personally wants to use&lt;/li&gt;



&lt;li&gt;Sharing progress honestly, especially early on&lt;/li&gt;



&lt;li&gt;Iterating longer than feels comfortable&lt;/li&gt;



&lt;li&gt;Letting distribution compound &lt;em&gt;after&lt;/em&gt; the product earns it&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Growth felt sudden only in hindsight. In reality, it arrived after months of quiet, compounding work.&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;p&gt;🎧 &lt;strong&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=VBYA6gO8weg&quot;&gt;Listen to the full Sub Club episode&lt;/a&gt;&lt;/strong&gt; to hear Sebastian unpack the slow parts, the setbacks, and the decisions that didn’t make sense at the time—but mattered in the end.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Why most activation metrics don’t predict who will stay (and what to use instead)]]></title><description><![CDATA[A framework for predicting retention and revenue in subscription apps]]></description><link>https://www.revenuecat.com/blog/growth/activation-metrics/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/activation-metrics/</guid><pubDate>Wed, 28 Jan 2026 12:13:55 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Blog_15_Activation-metrics.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;If you start researching activation metrics, you’ll find no shortage of suggestions:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Signups&lt;/li&gt;



&lt;li&gt;Trials completed&lt;/li&gt;



&lt;li&gt;Session length&lt;/li&gt;



&lt;li&gt;Onboarding completion&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;On the surface, these all sound like reasonable things you should probably keep an eye on.&lt;/p&gt;



&lt;p&gt;The problem? Most of these metrics focus on volume, not quality. They tell you how many people moved through a step, not whether those people became meaningful users, paying users, or users who actually stuck around.&lt;/p&gt;



&lt;p&gt;In short, they don’t show whether someone truly activated in a way that drives retention or monetization.&lt;/p&gt;



&lt;p&gt;Activation isn’t the same as signing up, and it’s not the same as completing onboarding — which means many ‘activation metrics’ will lead you astray.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-happens-when-you-focus-on-the-wrong-metrics&quot;&gt;What happens when you focus on the wrong metrics&lt;/h2&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-case-1-onboarding-is-performing-but-activation-isn-t-happening&quot;&gt;Case 1: onboarding is performing, but activation isn’t happening&lt;/h3&gt;



&lt;p&gt;I see this all the time in growth audits and client work. In one example, onboarding completion rates were stellar — over 90% on both iOS and Android. The team felt confident that activation was in a good place.&lt;/p&gt;



&lt;p&gt;But when we dug deeper, most of those users were gone by day two.&lt;/p&gt;



&lt;p&gt;The onboarding flow was easy, short, and clear, but users weren’t engaging with the parts of the product that actually mattered or experiencing real value. Onboarding completion looked good, but the activation issue persisted.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-case-2-feature-usage-looks-good-but-only-for-a-segment&quot;&gt;Case 2: feature usage looks good, but only for a segment&lt;/h3&gt;



&lt;p&gt;In another example, activation metrics looked strong at first glance:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Good engagement&lt;/li&gt;



&lt;li&gt;Healthy feature usage&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;But once we segmented free versus paid users, the picture changed entirely. Free users were inflating almost every metric; they were active, engaged, and numerous, but weren’t converting, renewing, or contributing to revenue.&lt;/p&gt;



&lt;p&gt;After we isolated paid cohorts, it became clear that activation quality for the users who actually mattered was much poorer than topline numbers suggested.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;These two cases highlight the risks of misinterpreting activation metrics, either by focusing on the wrong metric or by failing to segment your data meaningfully.&lt;/strong&gt;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-how-to-get-to-the-right-metrics&quot;&gt;How to get to the right metrics&lt;/h3&gt;



&lt;p&gt;We’re going to look at:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Which activation metrics actually matter for subscription apps&lt;/li&gt;



&lt;li&gt;How to avoid metrics that sound useful but don’t predict retention or revenue&lt;/li&gt;



&lt;li&gt;How to define your own activation metric instead of copying someone else’s&lt;/li&gt;



&lt;li&gt;How to test whether your chosen metric is real or just a vanity signal&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;I wish I could give you a magical activation metric and call it a day, but every app and use case requires a slightly different approach. The best I can offer is a framework to distinguish metrics that truly matter from those that merely look good.&lt;/p&gt;



&lt;p&gt;Because here’s the truth: &lt;strong&gt;retention doesn’t happen without activation.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Many apps think they have a retention or monetization problem, but zooming out often reveals that users drop off before they experience meaningful value or form a habit.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;689&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-94-1024x689.png&quot; alt=&quot;&quot; class=&quot;wp-image-50953&quot; style=&quot;width:800px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-94-1024x689.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-94-300x202.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-94-768x517.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-94-50x34.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-94-59x40.png 59w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-94-689x464.png 689w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-94-696x469.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-94-560x377.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-94-440x296.png 440w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-94-701x472.png 701w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-94-80x54.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-94-48x32.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-94.png 1392w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Credit: Diagram created together with Thorsten Strauss, Hello Growth&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/okrs-kpis-subscription-apps/&quot;&gt;The metrics you need to focus on&lt;/a&gt; depend on whether the problem is &lt;strong&gt;activation&lt;/strong&gt; or &lt;strong&gt;retention&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;The real question is: are people not sticking around because your product isn’t useful, or because they &lt;strong&gt;never truly activated&lt;/strong&gt; in the first place?&lt;/p&gt;



&lt;p&gt;That’s exactly what the right activation metrics help you figure out.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-activation-really-means-for-a-subscription-app&quot;&gt;What activation really means for a subscription app&lt;/h2&gt;



&lt;p&gt;Before defining the right activation metric, we need to be clear on what activation actually is, because this is where things often get muddled.&lt;/p&gt;



&lt;p&gt;I frequently see teams conflate activation with acquisition, label generic engagement metrics as activation, or treat it as simply ‘the steps a user completes’ rather than whether those steps actually move them toward becoming a long-term subscriber.&lt;/p&gt;



&lt;p&gt;But we’re not here to get lost in terminology debates. Let’s keep it simple.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Activation happens when a user reaches meaningful value early enough in their journey &lt;/strong&gt;that it becomes likely they will:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Convert &lt;/strong&gt;(if they’re on a trial or freemium path)&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Stay&lt;/strong&gt; through their first renewal&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Retain &lt;/strong&gt;beyond that initial period&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;It’s not about completing an onboarding flow or ticking off a checklist. It’s about &lt;strong&gt;whether early behavior predicts survival and long-term value&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;Or put another way:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Activation isn’t “Did they do the steps?”&lt;/li&gt;



&lt;li&gt;Activation is “Did the steps they took meaningfully increase their odds of getting value and, as a result, staying and paying?”&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;You can test this by comparing &lt;a href=&quot;https://www.revenuecat.com/docs/dashboard-and-metrics/charts/subscription-retention-chart&quot;&gt;retention curves&lt;/a&gt; for users who performed a particular action versus those who didn’t.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;But here’s the catch: &lt;strong&gt;almost any action will look better than doing nothing, so you need to focus on actions that truly predict long-term retention and monetization.&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;670&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-92-1024x670.png&quot; alt=&quot;&quot; class=&quot;wp-image-50949&quot; style=&quot;width:800px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-92-1024x670.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-92-300x196.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-92-768x503.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-92-50x33.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-92-61x40.png 61w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-92-696x456.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-92-560x367.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-92-452x296.png 452w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-92-721x472.png 721w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-92-80x52.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-92-48x31.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-92.png 1037w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Hypothetical retention curves for two different in-app behaviors&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;The real question is whether that specific action is truly predictive of retention and high-value users. The goal isn’t just to track activity; it’s to identify behaviors that correlate with long-term subscribers, versus actions (or inaction) that signal faster churn or low-value usage.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-two-layers-of-activation-first-value-and-core-value&quot;&gt;Two layers of activation: first value and core value&lt;/h2&gt;



&lt;p&gt;When thinking about activation in subscription apps, it helps &lt;strong&gt;not to treat it as a single moment&lt;/strong&gt;. Your first session matters of course, but according to the &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps-2025/&quot;&gt;State of Subscription App Report 2025&lt;/a&gt;, the largest share of trials occurs on Day 0 across both freemium and hard-paywall apps.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;968&quot; height=&quot;584&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-88.png&quot; alt=&quot;&quot; class=&quot;wp-image-50940&quot; style=&quot;width:800px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-88.png 968w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-88-300x181.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-88-768x463.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-88-50x30.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-88-66x40.png 66w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-88-696x420.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-88-560x338.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-88-491x296.png 491w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-88-782x472.png 782w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-88-80x48.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-88-48x29.png 48w&quot; sizes=&quot;auto, (max-width: 968px) 100vw, 968px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;SOSA 2025: Day at which trials are started for freemium vs. hard paywall apps&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;That said, activation is just one moment in building a habit. In subscription apps, it’s rarely a single step.&lt;/p&gt;



&lt;p&gt;I like how &lt;a href=&quot;https://www.amazon.co.uk/Product-Led-Growth-Build-Product-Itself/dp/1798434520/ref=sr_1_1?crid=Q8V1XUD5QPOT&amp;amp;dib=eyJ2IjoiMSJ9.Mbt5BN7n7BQh1-Fe2D0VN3kIIZWPGxqbXmclaMwE94HT1uNoJ2Sp7YqsjjL60oDDIKeii1amIMI2hJbDchWqj-L_8FIZ8W7G52DNVhST1gw.g0bP6T5tHrBOxRypO83N7sPdQ_fnYYL_s1UlXmUPaUg&amp;amp;dib_tag=se&amp;amp;keywords=product+led+growth+by+wes+bush&amp;amp;qid=1767868524&amp;amp;sprefix=product+led+gowth+by+wes+bush%2Caps%2C78&amp;amp;sr=8-1&quot;&gt;Product-Led Growth by Wes Bush&lt;/a&gt; breaks it up into three moments:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Moment of value perception: &lt;/strong&gt;users understand the value, e.g. by seeing an example or visual&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Moment of value experience: &lt;/strong&gt;users experience the value themselves, e.g. using the app’s main feature for the first time&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Moment of value adoption: &lt;/strong&gt;users begin using the app in a meaningful way, e.g. building a habit&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;What we often talk about for apps is this idea of ‘Time to First Value’ and that usually covers the first two moments. The core value only emerges once behavior starts to repeat.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;922&quot; height=&quot;679&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-91.png&quot; alt=&quot;&quot; class=&quot;wp-image-50946&quot; style=&quot;width:800px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-91.png 922w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-91-300x221.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-91-768x566.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-91-50x37.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-91-54x40.png 54w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-91-630x464.png 630w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-91-696x513.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-91-560x412.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-91-402x296.png 402w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-91-641x472.png 641w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-91-80x59.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-91-48x35.png 48w&quot; sizes=&quot;auto, (max-width: 922px) 100vw, 922px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Credit: Slightly adjusted diagram based on original diagram from Product-Led Growth by Wes Bush&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;Let’s dive deeper into those two parts.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-time-to-first-value-ttfv-moment-of-value-perception-and-experience&quot;&gt;1. Time to first value (TTFV): moment of value perception and experience&lt;/h3&gt;



&lt;p&gt;TTFV is the user’s perceived and experienced value. It’s often small, but it matters because:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;The steepest drop-off happens right at the beginning&lt;/li&gt;



&lt;li&gt;Many users decide whether to continue or disengage very early&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;strong&gt;If users don’t see value early, they may never reach meaningful activation, no matter how strong the product becomes later.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;This first-value moment should feel like progress, not just effort or friction for its own sake. &lt;a href=&quot;https://www.revenuecat.com/blog/growth/web-to-app-funnel-examples/#h-4-ynab-workshop-funnel&quot;&gt;Long onboarding flows&lt;/a&gt; might be trendy, but don’t use them just to fill time; they rarely help activation.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-time-to-core-value-habit-or-sustained-usage-moment-of-value-adoption&quot;&gt;2. Time to core value (habit or sustained usage): moment of value adoption&lt;/h3&gt;



&lt;p&gt;Core value usually takes longer to reach. This is where users move from trying the product to using it in ways that predict retention.&lt;/p&gt;



&lt;p&gt;It’s especially important for:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Habit-forming products&lt;/li&gt;



&lt;li&gt;Wellness or tracking apps&lt;/li&gt;



&lt;li&gt;Financial or budgeting tools&lt;/li&gt;



&lt;li&gt;Apps with more complex workflows (e.g. B2B apps)&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;For example, for a language-learning app, completing a single lesson might signal the first value. But core value emerges once someone completes several lessons over multiple days and starts to build a routine. It may be measured by the moment they know 30 words in the new language or can form five complete sentences.&lt;/p&gt;



&lt;p&gt;Many teams get stuck optimising only for the first session, without checking whether users reach the behaviors that matter later. For one app I worked on, we used day-7 retention as a success metric by ensuring experiments extended beyond session one, including push notifications and sessions two and three, to identify what would get users back enough in the first week to stick around.&lt;/p&gt;



&lt;p&gt;When defining activation, don’t just ask: “What happens on day one?”&lt;/p&gt;



&lt;p&gt;Also ask: &lt;strong&gt;“What must occur before a user behaves like a retained user?”&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;The key is that both layers matter, but in different ways.&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;First value helps prevent early drop-off&lt;/li&gt;



&lt;li&gt;Core value predicts whether users will sustain and ultimately retain&lt;/li&gt;
&lt;/ol&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-metrics-that-actually-matter-for-activation&quot;&gt;Metrics that actually matter for activation&lt;/h2&gt;



&lt;p&gt;Now we’ve defined activation, the next question is: which metrics really matter?&lt;/p&gt;



&lt;p&gt;It depends on your app (I know, such an annoying answer!), but if you’ve done the thinking above and run the numbers, you should already have a sense of:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Which behaviors predict retention&lt;/li&gt;



&lt;li&gt;Which features deliver meaningful value&lt;/li&gt;



&lt;li&gt;What your first value and core value moments look like&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;From there, the most important metrics are the ones that show whether users are reaching those value moments in ways that drive retention and conversion, not just ticking off steps or generating volume.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;To help you better distinguish between noise and signal for your subscription app, here are examples of metrics that matter, metrics that inform, and ones that just distract.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-metrics-that-matter&quot;&gt;Metrics that matter&lt;/h3&gt;



&lt;p&gt;These metrics are most likely to reflect real activation quality.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-1-percentage-of-users-reaching-the-first-value&quot;&gt;1. Percentage of users reaching the first value&lt;/h4&gt;



&lt;p&gt;This metric shows how many users reach the initial mini &lt;em&gt;aha!&lt;/em&gt; moment, aka the first value.&lt;/p&gt;



&lt;p&gt;Measuring this early step (perceived value) can be tricky in apps, but you can get a good sense by tracking whether users:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Complete a meaningful setup step&lt;/li&gt;



&lt;li&gt;View a personalized insight&lt;/li&gt;



&lt;li&gt;Return within 24 hours after their first session&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;strong&gt;Why it matters:&lt;/strong&gt; It shows whether drop-offs are happening before users ever reach the value.&lt;/p&gt;



&lt;p&gt;You’re not trying to force everyone to reach it instantly. The goal is to ensure enough users experience value early enough to avoid churning before activation.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;If not enough of your users are reaching the first value moment, you have an activation problem, not a retention problem.&lt;/strong&gt;&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-2-percentage-of-users-reaching-the-core-value&quot;&gt;2. Percentage of users reaching the core value&lt;/h4&gt;



&lt;p&gt;This is the deeper signal, the next step in the journey. It shows &lt;strong&gt;whether users are forming patterns or habits that support retention&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;This metric is often far more predictive of long-term success than anything that happens in the first session. The core value usually doesn’t happen immediately; it often emerges later, once users engage repeatedly with the product.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-3-time-to-first-value-used-thoughtfully&quot;&gt;3. Time to first value (used thoughtfully)&lt;/h4&gt;



&lt;p&gt;Time to first value can be useful, but only as a diagnostic metric, not a goal in itself.&lt;/p&gt;



&lt;p&gt;For first value, faster is generally better, but only if the experience still delivers genuine value. &lt;strong&gt;It’s better to provide meaningful value slightly slower than superficial value quickly&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;For core value, timing matters relative to behavior. If reaching core value in week one versus week two predicts very different retention outcomes, then timing becomes a meaningful signal.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;670&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-90-1024x670.png&quot; alt=&quot;&quot; class=&quot;wp-image-50945&quot; style=&quot;width:800px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-90-1024x670.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-90-300x196.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-90-768x503.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-90-50x33.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-90-61x40.png 61w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-90-696x456.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-90-560x367.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-90-452x296.png 452w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-90-721x472.png 721w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-90-80x52.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-90-48x31.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-90.png 1037w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;How timing of behavior can impact activation and in turn retention&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;The insight here isn’t ‘shorter is always better’. It’s that timing tells you something about activation quality.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-4-how-activation-shows-up-in-your-funnel&quot;&gt;4. How activation shows up in your funnel&lt;/h4&gt;



&lt;p&gt;Once you know how many users reach first and core value, these &lt;a href=&quot;https://www.revenuecat.com/docs/dashboard-and-metrics/overview&quot;&gt;standard subscription metrics&lt;/a&gt; tell you whether that activation is turning into revenue:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Trial start rate (if you offer a trial)&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.revenuecat.com/glossary/#trial-conversion-rate&quot;&gt;Trial-to-paid conversion rate&lt;/a&gt; (if you offer a trial)&lt;/li&gt;



&lt;li&gt;Download-to-paid conversion rate&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The key: &lt;strong&gt;never look at these metrics in isolation.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;For example, you might see a high trial start rate but a &lt;a href=&quot;https://www.revenuecat.com/blog/growth/how-to-increase-trial-conversion-rates-without-adding-new-features/&quot;&gt;low trial-to-paid conversion rate&lt;/a&gt;. That doesn’t necessarily mean the trial itself is the problem. Often, users are starting a trial before they’ve actually experienced value, then canceling quickly ‘just in case’.&lt;/p&gt;



&lt;p&gt;The right move might be to:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Slow down the path to trial&lt;/li&gt;



&lt;li&gt;Improve value delivery first&lt;/li&gt;



&lt;li&gt;Accept lower trial volume in exchange for higher-quality users&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Again, when it comes to activation metrics, &lt;strong&gt;quality over volume is what drives retention.&lt;/strong&gt;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-metrics-that-inform-but-shouldn-t-be-success-kpis&quot;&gt;Metrics that inform (but shouldn’t be success KPIs)&lt;/h3&gt;



&lt;p&gt;Some metrics are useful for understanding activation, but they shouldn’t be treated as proof of success.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-1-onboarding-completion-rate&quot;&gt;1. Onboarding completion rate&lt;/h4&gt;



&lt;p&gt;Onboarding completion is one of the most overused activation metrics. A high completion rate does not guarantee activation is working.&lt;/p&gt;



&lt;p&gt;In some cases, adding &lt;strong&gt;positive friction actually improves activation quality&lt;/strong&gt; by helping you understand users, tailor experiences, and build trust before asking for commitment.&lt;/p&gt;



&lt;p&gt;Instead of asking “How do we increase onboarding completion?”, ask:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Do users who complete onboarding retain better?&lt;/li&gt;



&lt;li&gt;Are we helping the right users progress?&lt;/li&gt;



&lt;li&gt;Are we losing good users too early, or filtering out low-intent users later than we should?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;strong&gt;Completion is a signal, not a goal.&lt;/strong&gt;&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-2-feature-adoption-with-the-right-segmentation&quot;&gt;2. Feature adoption (with the right segmentation)&lt;/h4&gt;



&lt;p&gt;Feature adoption can be insightful, but only if you look at it through the right lens.&lt;/p&gt;



&lt;p&gt;Average adoption rates often hide the story. A feature may appear lightly used overall, but be heavily used by high-&lt;a href=&quot;https://www.revenuecat.com/glossary/#lifetime-value-ltv&quot;&gt;LTV&lt;/a&gt; or paying users. Meanwhile, some features add complexity without contributing to retention.&lt;/p&gt;



&lt;p&gt;Feature adoption is most useful for understanding:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Which features support retention&lt;/li&gt;



&lt;li&gt;Whether free users understand the value of premium features&lt;/li&gt;



&lt;li&gt;Which features are adding noise rather than helping users activate&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;I had an app where very few free users tried the main premium feature (it was available with limited usage to free users). As a result, they weren’t activating properly and were unlikely to pay — they didn’t see the value.&lt;/p&gt;



&lt;p&gt;Feature adoption is also useful for spotting noise. If only 2% of users use a feature, and they aren’t your most valuable users, so ask whether it’s adding complexity rather than contributing to activation.&lt;/p&gt;



&lt;p&gt;On that note, check out this &lt;a href=&quot;https://www.lennysnewsletter.com/p/gibson-biddle-on-the-the-dhm-product&quot;&gt;great podcast&lt;/a&gt; on the adoption thresholds used at Netflix.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-metrics-that-distract&quot;&gt;Metrics that distract&lt;/h3&gt;



&lt;p&gt;These metrics are easy to over-optimize and often pull &lt;a href=&quot;https://www.revenuecat.com/blog/growth/build-app-growth-team/&quot;&gt;growth teams&lt;/a&gt; in the wrong direction.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-1-total-signups&quot;&gt;1. Total signups&lt;/h4&gt;



&lt;p&gt;More signups don’t automatically mean better growth. While signups are necessary to feed volume into the funnel, optimizing for quantity alone can:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Attract lower-quality users&lt;/li&gt;



&lt;li&gt;Mask activation problems&lt;/li&gt;



&lt;li&gt;Give acquisition teams the wrong incentives&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Sometimes the right move is fewer signups, but higher-quality traffic that is more likely to activate and retain.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-2-trials-started&quot;&gt;2. Trials started&lt;/h4&gt;



&lt;p&gt;A high trial start rate doesn’t automatically create more paying customers. In some cases, users start a trial before truly experiencing value, which can lead to:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Low trial-to-paid conversion&lt;/li&gt;



&lt;li&gt;Poor first renewal&lt;/li&gt;



&lt;li&gt;Weaker retention overall&lt;/li&gt;
&lt;/ul&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-3-session-length&quot;&gt;3. Session length&lt;/h4&gt;



&lt;p&gt;Longer sessions can indicate engagement, especially for apps like video platforms or games, but they can also signal confusion or difficulty finding content.&lt;/p&gt;



&lt;p&gt;For many subscription apps, efficient value delivery is more important than raw time spent. Context matters far more than total minutes.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-4-raw-daily-active-users-dau-or-monthly-active-users-mau-without-a-quality-lens&quot;&gt;4. Raw daily active users (DAU) or monthly active users (MAU) without a quality lens&lt;/h4&gt;



&lt;p&gt;DAU and MAU are only meaningful if ‘active’ reflects &lt;em&gt;meaningful&lt;/em&gt; usage, and the frequency matches your product’s natural cadence.&lt;/p&gt;



&lt;p&gt;A common recommendation is to look at the stickiness ratio that measures app stickiness:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;685&quot; height=&quot;254&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-87.png&quot; alt=&quot;&quot; class=&quot;wp-image-50939&quot; style=&quot;width:800px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-87.png 685w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-87-300x111.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-87-50x19.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-87-108x40.png 108w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-87-560x208.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-87-80x30.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-87-48x18.png 48w&quot; sizes=&quot;auto, (max-width: 685px) 100vw, 685px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;However, there are two issues with this standard app stickiness metric:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Your app’s ideal usage frequency might not be daily&lt;/li&gt;



&lt;li&gt;Active users’ often means ‘opened the app’, which isn’t the same as ‘experienced value’&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Once you adjust for these factors, stickiness can still be useful, but it’s better to define your ideal usage frequency and compare it over a longer period to identify what drives retention.&lt;/p&gt;



&lt;p&gt;For example, for a wellness app I worked with that offered workshops and meditations, consuming at least two pieces of content in 14 days was a stronger predictor of retention than using the app once a week.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-to-test-whether-your-activation-metric-is-real-or-vanity&quot;&gt;How to test whether your activation metric is real or vanity&lt;/h2&gt;



&lt;p&gt;Defining an activation metric is just the first step. Next, you need to demonstrate that it reflects real activation, not just a vanity signal.&lt;/p&gt;



&lt;p&gt;A metric only counts as true activation if it passes these tests:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-activated-users-retain-significantly-better-than-non-activated-users&quot;&gt;1. Activated users retain significantly better than non-activated users&lt;/h3&gt;



&lt;p&gt;Compare retention curves for users who reached the activation milestone versus those who didn’t.&lt;/p&gt;



&lt;p&gt;Think back to the diagram I showed earlier:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;670&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-93-1024x670.png&quot; alt=&quot;&quot; class=&quot;wp-image-50951&quot; style=&quot;width:800px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-93-1024x670.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-93-300x196.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-93-768x503.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-93-50x33.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-93-61x40.png 61w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-93-696x456.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-93-560x367.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-93-452x296.png 452w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-93-721x472.png 721w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-93-80x52.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-93-48x31.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-93.png 1037w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Hypothetical retention curves for two different behaviors in-app&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;You’re looking for a sustained difference, not a short-term bump that fades after a few weeks. If the curves reconverge later, the metric is likely just an engagement step, not true activation.&lt;/p&gt;



&lt;p&gt;Put simply: if users who ‘activated’ don’t retain or pay significantly more, your metric isn’t real activation, it’s just noise.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-the-relationship-holds-across-most-cohorts-and-channels&quot;&gt;2. The relationship holds across (most) cohorts and channels&lt;/h3&gt;



&lt;p&gt;Check whether the activation metric predicts retention consistently across:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Cohorts over time&lt;/li&gt;



&lt;li&gt;Acquisition channels&lt;/li&gt;



&lt;li&gt;Web vs. iOS vs. Android&lt;/li&gt;



&lt;li&gt;Device types&lt;/li&gt;



&lt;li&gt;Geography (if relevant)&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;You don’t need perfection, as some variation is normal. You might see:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;A channel where the relationship is weaker&lt;/li&gt;



&lt;li&gt;Users on one platform are activating differently&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;What matters is that the pattern holds broadly, and you understand where and why it breaks. In some cases, you may need different activation metrics for web, iOS, Android, or different regions.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-improving-the-metric-improves-downstream-outcomes&quot;&gt;3. Improving the metric improves downstream outcomes&lt;/h3&gt;



&lt;p&gt;Some activation effects take time to appear in retention curves, especially if you’ve only recently started tracking them. Another key check is whether improving the activation metric drives the outcomes it should influence.&lt;/p&gt;



&lt;p&gt;For example:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;If it’s an early value milestone → does it improve trial-to-paid conversion?&lt;/li&gt;



&lt;li&gt;If it’s a deeper habit milestone → does it improve first renewal?&lt;/li&gt;



&lt;li&gt;If it sits later in the journey → does it reduce early churn?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;If the metric moves but nothing downstream improves, it may look meaningful, but it isn’t actually creating better, more durable users.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-practical-checks-to-strengthen-confidence-in-your-metrics&quot;&gt;Practical checks to strengthen confidence in your metrics&lt;/h3&gt;



&lt;p&gt;If you have enough data, stress-test your activation metrics with a few deeper cuts:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Compare activated vs. non-activated users within the same cohort&lt;/li&gt;



&lt;li&gt;Split by paid vs. free users (if you have a freemium path)&lt;/li&gt;



&lt;li&gt;Break down by channel or device quality&lt;/li&gt;



&lt;li&gt;Check whether high-LTV users follow the same activation pattern&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;This helps you avoid building your activation model around users who were never likely to pay or retain in the first place.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-work-out-your-activation-window&quot;&gt;Work out your activation window&lt;/h3&gt;



&lt;p&gt;Activation is not just about what happens; it’s also about when it happens.&lt;/p&gt;



&lt;p&gt;Look at your retention curve and identify where the steep early drop-off stabilizes. That point often marks the transition from activation to retention and helps define the window where your metric truly matters.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;940&quot; height=&quot;679&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-89.png&quot; alt=&quot;&quot; class=&quot;wp-image-50943&quot; style=&quot;width:800px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-89.png 940w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-89-300x217.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-89-768x555.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-89-50x36.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-89-55x40.png 55w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-89-642x464.png 642w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-89-696x503.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-89-560x405.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-89-410x296.png 410w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-89-653x472.png 653w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-89-80x58.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-89-48x35.png 48w&quot; sizes=&quot;auto, (max-width: 940px) 100vw, 940px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;The activation window&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;If the activation window is very long, it may indicate that users aren’t deriving value quickly enough, or that your product simply requires a longer window to activate. This could mean:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Users aren’t reaching value fast enough&lt;/li&gt;



&lt;li&gt;They need more guidance or support to progress meaningfully early on&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Back to a language-learning app, a single lesson isn’t enough to signal commitment. Users may need to complete several lessons over a week or two before they meaningfully engage as long-term learners (or start fearing the owl enough to keep going). The window isn’t just about capturing that first lesson; it’s also about the time required to significantly increase the user’s likelihood of staying.&lt;/p&gt;



&lt;p&gt;The goal isn’t to force activation sooner than makes sense. It’s to understand when it happens today and whether that timing supports retention.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-to-use-this-in-practice&quot;&gt;How to use this in practice&lt;/h2&gt;



&lt;p&gt;After all that, you might have a long list of metrics you could track, but you don’t need dozens. Stay focused by categorizing metrics into three clear buckets.&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Metrics that matter &lt;/strong&gt;should&lt;strong&gt; &lt;/strong&gt;directly predict conversion, retention, or renewal: optimize these&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Metrics that inform &lt;/strong&gt;help you understand why activation is or isn’t happening: investigate these&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Metrics that distract &lt;/strong&gt;are easy to improve, but often optimize volume over quality — keep an eye on them, but resist chasing them&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;If there’s one takeaway, it’s this: activation is not about getting users through steps. It’s about &lt;strong&gt;helping the right users reach value in a way that makes them likely to stay&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;When teams think they have a retention or monetization problem, it’s often because activation never truly happened. The earlier you define what real activation looks like for your product, the easier everything downstream becomes.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[How to win Shipyard]]></title><description><![CDATA[A hackers guide to building an MVP that can win RevenueCat's Shipyard hackathon]]></description><link>https://www.revenuecat.com/blog/engineering/how-to-win-shipyard/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/how-to-win-shipyard/</guid><pubDate>Tue, 27 Jan 2026 14:14:03 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Shipyard_Blog_HowToWin_1600x800_v1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;RevenueCat has a new hackathon, Shipyard: Creator Contest. Similarly to our previous hackathons, this one is also about building a real, monetized mobile app (MVP is enough, &lt;a href=&quot;https://www.shipyard.fyi/&quot;&gt;check the rules here&lt;/a&gt;). This time, however, your target audience are the community of &lt;strong&gt;real influencers&lt;/strong&gt; — who will also be judging your submission!&lt;/p&gt;



&lt;p&gt;This hackathon is a lot shorter than &lt;a href=&quot;https://apps.shipaton.com/2025&quot;&gt;Shipaton&lt;/a&gt;, so it’s more important than ever that you focus on &lt;strong&gt;building the right thing, quickly&lt;/strong&gt;. RevenueCat wants to support you in doing that, so we’ve written this hackers’ guide to building a winning app, based on four core lessons:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Coming up with a great app idea&lt;/li&gt;



&lt;li&gt;Building your app fast&lt;/li&gt;



&lt;li&gt;Growing your user count&lt;/li&gt;



&lt;li&gt;Telling your story in the final submission&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;On top of these lessons, we’ve curated a bundle of tools, credits, and resources to help you build, launch, and monetize your app in the four weeks of Shipyard. Once registered, check your email (including your junk!) to receive your &lt;strong&gt;Shipping Container&lt;/strong&gt;.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Without wasting any more time, here’s how you win Shipyard.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-1-come-up-with-a-great-app-idea&quot;&gt;Step 1: Come up with a great app idea&lt;/h2&gt;



&lt;p&gt;The first step into winning a hackathon is coming up with an idea for your app. Preferably this idea should be a really good one, as it will make building a great app significantly easier, but that is rarely that easy to do. So how do you come up with a great app idea?&lt;/p&gt;



&lt;p&gt;First, start by watching the creator briefs, there’s seven of them, and they are all quite different. Be open, and don’t use come to this hackathon with an existing idea that you’ll then try to make fit one of the briefs. That rarely works, and to be frank, what you think is a great idea for an, usually isn’t. So take your time with the briefs, and pick the one that resonates the most. At this point your idea can be very simple, and it certainly does not have to be a groundbreaking one, we will distill it into a one next.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;542&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-86-1024x542.png&quot; alt=&quot;&quot; class=&quot;wp-image-50921&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-86-1024x542.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-86-300x159.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-86-768x407.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-86-1536x813.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-86-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-86-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-86-696x368.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-86-560x296.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-86-840x445.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-86-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-86-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-86.png 2048w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-talk-to-people&quot;&gt;Talk to people&lt;/h3&gt;



&lt;p&gt;A common misconception is that people come up with great app ideas on their own. In reality people come up with average ideas on their own, and once they start talking with customers about the problem they have, it gets turned into a great idea. So take your preliminary idea, and go to the potential users with it. Watch the creator brief again, this time focusing on who is the target audience, and figure out where you could find someone that represents the target customer, then simply go talk to them.&lt;/p&gt;



&lt;p&gt;Don’t just pitch your idea to the target customer, instead start with open ended questions. Build empathy to understand what the problem is that your customers are having, and how they feel it could be solved. Your goal is to understand your customers in such a way that you can instantly know what the real problem they are struggling with is, and what kind of solution they would fall in love with.&lt;/p&gt;



&lt;p&gt;With all of this you should aim to get to a state where you feel that you have to build this specific app, because you’re the only one who really understands your customer, and therefore the only one who can get it right. For more pointers about getting to this state and coming up with a great app idea, take a look at our &lt;a href=&quot;https://www.revenuecat.com/blog/engineering/how-to-win-shipaton-part-1-coming-up-with-an-idea/&quot;&gt;How to win Shipaton: coming up with an idea&lt;/a&gt; blog post.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-2-build-your-app-fast&quot;&gt;Step 2: Build your app fast&lt;/h2&gt;



&lt;p&gt;Once you have your problem and idea nailed, it’s time to start building. The first lesson in building quickly is setting a timeline for yourself and sticking to it. Don’t wait for inspiration to start coding your app, that stuff is for amateurs. Winners just get to work and build.&lt;/p&gt;



&lt;p&gt;You can approach your build timeline in multiple ways, but we have one that tends to work very well, and it only has three parts that all have a specific purpose:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-build-your-concept-in-4-hours&quot;&gt;1. &lt;strong&gt;Build your concept in 4 hours&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;In these four hours your focus is on proving that your concept works. The only person you need to convince that your app is great is you yourself. This is the part where you make something that barely works, but works nonetheless. There’s a bit of UI there already, but no polish, and there certainly shouldn’t be big infrastructure in your app at this point.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-build-your-mvp-in-8-hours&quot;&gt;2. &lt;strong&gt;Build your MVP in 8 hours&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Now take what you built in the first 4 hours, and start polishing it so that you could show it to a potential customer. Things don’t have to work at this point, they just have to feel like they work. Use mock data, make fake requests to services, be like the Wizard of Oz: it’s not magic but for users it feels like it is.&lt;br&gt;&lt;br&gt;If you feel embarrassed to show your app, good. That means you’re going to your customer early enough with your idea and getting feedback that will set you on the right track.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-build-your-app-in-24-hours&quot;&gt;3. &lt;strong&gt;Build your app in 24 hours&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;After you’ve shown your 8-hour making to customers, take what they have to say and incorporate it into your app. Drop things that users didn’t care about, add the things that enough people asked for. At this point your app will most likely still be embarrassing. You just need to get it to a stage where you could leave the customer alone with it and check back later how it worked. So launch the app if you can.&lt;/p&gt;



&lt;p&gt;And keep launching and relaunching your app. Multiple times. Every day if it requires it. Add features, fix bugs, but never take more than day or two from getting those improvements in the hands of your customers.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;This process should highlight to you that great apps are built iteratively honing the product, not building it once and leaving it at that. So ship as often as you humanly can. We’ve collected more guidance on building quickly using this same method in this &lt;a href=&quot;https://www.revenuecat.com/blog/engineering/how-to-win-shipaton-part-2-building-fast/&quot;&gt;How to win Shipaton: building your app fast&lt;/a&gt; blog post.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-3-grow-your-user-count&quot;&gt;Step 3: Grow your user count&lt;/h2&gt;



&lt;p&gt;After you’ve built your idea, comes the actual hard part: getting users. Shipyard does not require you to launch your app to app stores, but doing so doesn’t hurt either. After all, customers can only pay you if your app is available to them, and more customers means more revenue.&lt;/p&gt;



&lt;p&gt;However there are other reasons for growing your user count than just converting them to customers. In the beginning especially, the more users you have the more feedback you get, and you might have already learned from the previous two lessons that gathering feedback and acting on it is the best way to build something that wins.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;For a more extensive lesson on growing your app, take a look at this &lt;a href=&quot;https://www.revenuecat.com/blog/engineering/how-to-win-shipaton-part-3-growing-your-app/&quot;&gt;blog post on Winning Shipaton by growing your app&lt;/a&gt;, but here’s a few key points to growing.&lt;/p&gt;



&lt;p&gt;First make use of the &lt;a href=&quot;https://discord.com/invite/3aV6EUCYqR&quot;&gt;Shipyard discord&lt;/a&gt; to recruit users to test your app. Get as many as you can, people will churn, meaning that they’ll stop using your app when it stops being useful to them. With your first version of the app, this will most likely happen with all of the users, that’s why it’s important to continue improving your app and launch it again and again. The most valuable learning you can get is talking to the users who stopped using your app, they know best what features your app is lacking, so try to get a hold of them.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-4-tell-your-story&quot;&gt;Step 4: Tell your story&lt;/h2&gt;



&lt;p&gt;Last lesson to winning Shipyard has actually quite little to do with your app itself, and all to do with how you talk about your app. When you take a look at the submission guidelines for Shipyard, you’ll notice that two of the requirements besides the app are a short video and a written proposal. These are the two things the judges will be scrutinizing the hardest, so it’s important to communicate clearly what your app is about.&lt;/p&gt;



&lt;p&gt;Clear messaging is however only half of the story. If you actually want to win, you need to tell a compelling story. This means framing the problem so that it elicits feelings from the people looking at the video, and in such a way that paints you and your app as the heroes of the story.&lt;/p&gt;



&lt;p&gt;Now this all sounds rather complicated, but fear not, RevenueCat is here to help you with this as well. In our fourth guide &lt;a href=&quot;https://www.revenuecat.com/blog/engineering/how-to-win-shipaton-part-4-pitching-your-app/&quot;&gt;How to win Shipaton: pitching your app guide&lt;/a&gt;, we go through a simple storytelling mechanic called the “&lt;em&gt;Story circle&lt;/em&gt;”. Check out that article, apply it to your video and written submissions (and don’t do it on the last night before submissions close), and making both of them should not take you more than a few hours.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-make-use-of-the-shipping-container&quot;&gt;Make use of the Shipping Container&lt;/h2&gt;



&lt;p&gt;Last but certainly not least, we have partnered up with a group of companies to give you the best tools for building your app, a curated bundle called the Shipping Container. You can of course use any tools you want for building your app, but these freebies will help you a lot if you decide to make use of them.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-get-inspired-and-brainstorm-with-ai&quot;&gt;Get inspired and brainstorm with AI&lt;/h3&gt;



&lt;p&gt;The Shipping Container includes tools for ideation and brainstorming. Study real-world UI and UX patterns in &lt;a href=&quot;https://mobbin.com/&quot;&gt;Mobbin&lt;/a&gt;, and jump over those design hurdles with ease. You can even outright steal the best onboarding and paywall patterns from popular apps, and use them in your app to improve your monetization and app experience.&lt;/p&gt;



&lt;p&gt;Put &lt;a href=&quot;https://manus.im/&quot;&gt;Manus&lt;/a&gt; to work to do analysis in the ideation phase and growth phases, by brainstorming with it and using it to build beautiful looking landing pages. You can essentially use Manus as your team member in this hackathon, and you don’t even have to share the price money with them.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-build-fast-with-vibecoding-tools&quot;&gt;Build fast with vibecoding tools&lt;/h3&gt;



&lt;p&gt;The Shipping Container comes bundled with multiple different AI-assisted tools for building apps as well. You can build your app with &lt;a href=&quot;https://fastshot.ai/&quot;&gt;Fastshot&lt;/a&gt;, &lt;a href=&quot;https://www.createanything.com/&quot;&gt;Anything&lt;/a&gt;, &lt;a href=&quot;https://replit.com/&quot;&gt;Replit&lt;/a&gt;, and &lt;a href=&quot;https://rork.com/&quot;&gt;Rork&lt;/a&gt;, either using the mobile apps or the web based editors they have. All of these tools give you the power to build your idea into a real app, and most importantly all of them make it very fast to do that.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;All these tools also support RevenueCat, it’s enough to authenticate with your RevenueCat account and after that you can start telling the AI to add subscriptions, lifetime upgrades, entitlements, RevenueCat powered paywalls and more into your app with just prompts. If you’re feeling lost, take a look out for an in-depth video guide to doing all of this with Vibecode below.&lt;/p&gt;



&lt;p&gt;Once your in-app purchases are working, you can explore other payment options. The Shipping Container comes bundled with Paddle as well, so you can add web-based payments alongside your in-app purchases, and experiment with additional monetization paths.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-time-to-set-sail&quot;&gt;Time to set sail&lt;/h2&gt;



&lt;p&gt;Now get cracking and go build that winning app. Take a look at the linked and articles and most importantly: build something that people love, but something you love to work on. Don’t lose track of the end goal, building an app, not a concept. Get your app out to people, as soon as you get feedback I guarantee that your productivity will soar higher than in any other way.&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/engineering/how-to-win-shipaton-part-1-coming-up-with-an-idea/&quot;&gt;How to win Shipaton: coming up with an idea&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/engineering/how-to-win-shipaton-part-2-building-fast/&quot;&gt;How to win Shipaton: building your app fast&lt;/a&gt; &lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/engineering/how-to-win-shipaton-part-3-growing-your-app/&quot;&gt;How to win Shipaton: growing your app&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/engineering/how-to-win-shipaton-part-4-pitching-your-app/&quot;&gt;How to win Shipaton: pitching your app guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[The 15% App Store fee you’re probably not paying (but should be)]]></title><description><![CDATA[How a 10-minute enrolment can save you thousands of dollars]]></description><link>https://www.revenuecat.com/blog/engineering/small-business-program/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/small-business-program/</guid><pubDate>Tue, 27 Jan 2026 14:10:39 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/How-you-could-be-saving-1000s-in-app-store-fees.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;As a developer, you’ve probably complained about the 30% App Store fee. It feels like a mandatory slice of your revenue that goes straight to the platform holders, just for the privilege of your app existing&lt;/p&gt;



&lt;p&gt;But here’s the thing nobody talks about enough: &lt;strong&gt;for the vast majority of developers, the 30% fee is a myth&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;For years now, both Apple and Google have had programs that &lt;strong&gt;cut that commission in half,&lt;/strong&gt; to just 15%. Yet every day I talk to developers who have no idea these programs exist, or they think it’s some complicated process they don’t have time for. &lt;strong&gt;They’re leaving tens of thousands of dollars on the table.&lt;/strong&gt; Money that could be used to hire another engineer, run a marketing campaign, or just, you know, pay the bills&lt;/p&gt;



&lt;p&gt;This isn’t some secret loophole. It’s a public program. And if you’re making less than $1 million a year from your apps, you qualify. Today, we’re going to fix this. No more excuses. Here’s your step-by-step guide to claiming the 15% you’ve earned:&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-program-you-need-to-join-right-now&quot;&gt;The program you need to join right now&lt;/h2&gt;



&lt;p&gt;Both Apple and Google call it something different, but the core idea is the same: &lt;strong&gt;if your annual earnings are below $1 million, you get a reduced commission rate of 15%.&lt;/strong&gt; It’s that simple&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-apple-the-app-store-small-business-program&quot;&gt;Apple: the App Store Small Business Program&lt;/h3&gt;



&lt;p&gt;Apple’s program is a lifesaver for indie devs and small studios. It drops the commission from 30% to 15% on everything: paid app downloads, in-app purchases, and subscriptions&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-the-rules&quot;&gt;The rules:&lt;/h4&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;You must have earned no more than $1 million in total proceeds (after Apple’s cut) in the previous calendar year&lt;/li&gt;



&lt;li&gt;All of your ‘Associated Developer Accounts’ count toward that $1 million threshold&lt;/li&gt;



&lt;li&gt;If you’re a new developer, you automatically qualify&lt;/li&gt;
&lt;/ul&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-how-to-enroll-in-apple-s-program-it-takes-10-minutes&quot;&gt;How to enroll in Apple’s program (it takes 10 minutes):&lt;/h4&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Go to the enrollment page: &lt;/strong&gt;first, make sure you are the &lt;strong&gt;Account Holder&lt;/strong&gt; for your Apple Developer account. Then, head straight to the &lt;a href=&quot;https://developer.apple.com/app-store/small-business-program/enroll/&quot;&gt;enrollment page&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Review your accounts:&lt;/strong&gt; Apple will ask you to confirm your developer accounts. If you have multiple, you’ll need to list them&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Accept the terms:&lt;/strong&gt; you’ll need to review and accept the latest Paid Applications agreement in App Store Connect if you haven’t already. Then, accept the terms of the Small Business Program&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;That’s it. Once you’re approved, the 15% rate kicks in. You just gave yourself a massive raise&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-google-the-15-service-fee-tier&quot;&gt;Google: the 15% Service Fee Tier&lt;/h3&gt;



&lt;p&gt;Google’s program is just as crucial. They charge 15% on the first $1 million of your earnings each year. If you cross that threshold, the rate goes to 30% for the rest of the year. For most of us, that means a permanent 15% rate&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-the-rules-0&quot;&gt;The rules:&lt;/h4&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;The 15% rate applies to the first $1 million in revenue you earn each calendar year&lt;/li&gt;



&lt;li&gt;Like Apple, you need to declare your Associated Developer Accounts and create an ‘Account Group’&lt;/li&gt;
&lt;/ul&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-how-to-enroll-in-google-s-program-also-takes-10-minutes&quot;&gt;How to enroll in Google’s Program (also takes 10 minutes):&lt;/h4&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Go to your Play Console:&lt;/strong&gt; log in and navigate to the &lt;a href=&quot;https://play.google.com/console/developers/associated-developer-accounts&quot;&gt;Associated developer accounts&lt;/a&gt; page&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Create an Account Group:&lt;/strong&gt; follow the on-screen prompts to create a group. This is where you’ll link any other developer accounts you own&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Enroll:&lt;/strong&gt; once the group is set up, a banner will appear prompting you to enroll for the 15% service fee. Click ‘Review and enroll’&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Accept the Terms:&lt;/strong&gt; read and accept the Terms of Service&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Done. You’re now enrolled. It’s a few clicks that will fundamentally change your app’s financial trajectory&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-other-secret-subscription-commission-discounts&quot;&gt;The other secret: subscription commission discounts&lt;/h2&gt;



&lt;p&gt;Okay, so the Small Business Programs are the main event. But there’s another layer to this that a surprising number of developers miss, especially when it comes to subscriptions&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-apple-the-year-two-reward&quot;&gt;Apple: the year-two reward&lt;/h3&gt;



&lt;p&gt;For auto-renewing subscriptions, Apple has a built-in discount. For any given subscriber, you pay &lt;strong&gt;30% for their first year&lt;/strong&gt;. But if you can keep them subscribed for a full 12 months, Apple rewards you by dropping the commission to &lt;strong&gt;15% for that subscriber’s second year and beyond&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Of course, if you’re in the Small Business Program, you’re already paying 15% from day one. But if your app grows and you graduate out of the Small Business Program, this year-two discount becomes incredibly important. It’s a direct incentive to focus on long-term retention&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-google-15-from-day-one&quot;&gt;Google: 15% from day one&lt;/h3&gt;



&lt;p&gt;Google simplifies things. For all auto-renewing subscriptions on Google Play, the service fee is &lt;strong&gt;15% from day one&lt;/strong&gt;. It doesn’t matter if you’re in the reduced fee program or not. It doesn’t matter if it’s the subscriber’s first month or their third year. For subscriptions, the rate is 15%&lt;/p&gt;



&lt;p&gt;This is a huge advantage for subscription apps on Android, making the unit economics much more favorable right from the start&lt;/p&gt;



&lt;p&gt;Here’s how that breaks down:&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;Platform &amp;amp; program&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;Subscription commission (year 1)&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;Subscription commission (year 2+)&lt;/strong&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Apple (standard)&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;30%&lt;/td&gt;&lt;td&gt;15%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Apple (Small Business Program)&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;15%&lt;/td&gt;&lt;td&gt;15%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Google Play (all developers)&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;15%&lt;/td&gt;&lt;td&gt;15%&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-telling-revenuecat-about-your-enrollment&quot;&gt;Telling RevenueCat about your enrollment&lt;/h2&gt;



&lt;p&gt;If you’re using RevenueCat, there’s one more step you’ll want to take: letting RevenueCat know you’re enrolled in these programs. This ensures your charts, metrics, and integration data all reflect the correct commission rates&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-for-apple&quot;&gt;For Apple&lt;/h3&gt;



&lt;p&gt;Since a developer could have multiple apps from different companies in their RevenueCat account, the Small Business Program status is set on a per-app basis. Here’s how to set it up:&lt;br&gt;&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Go to your RevenueCat Dashboard:&lt;/strong&gt; select ‘Apps &amp;amp; providers’ at the bottom of the left navigation sidebar&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Select your App Store app:&lt;/strong&gt; scroll down and expand the Apple Small Business Program dropdown&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Enter your entry date: &lt;/strong&gt;this is the effective date your membership began. If you enrolled before December 18, 2020 and were notified by December 30, 2020, then enter January 1, 2021&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Add an exit date (if applicable):&lt;/strong&gt; if you’ve left or been removed from the program, enter that date here&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Once you save, RevenueCat will correctly calculate your proceeds in charts and send accurate pricing data to your integrations. If you set the entry date in the past, charts will recalculate within 24 hours.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-for-google&quot;&gt;For Google&lt;/h3&gt;



&lt;p&gt;Good news: RevenueCat automatically assumes you’re enrolled in Google’s reduced service fee tier. For subscription transactions, RevenueCat uses the 15% rate by default&lt;/p&gt;



&lt;p&gt;If you cross the $1 million threshold during a calendar year, RevenueCat will automatically switch to the 30% rate for the rest of the year. If you have multiple apps or have transferred apps and the calculation seems off, just reach out to RevenueCat support and they can manually adjust your project’s service fee rate&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-stop-leaving-money-on-the-table&quot;&gt;Stop leaving money on the table&lt;/h2&gt;



&lt;p&gt;That’s it. No complex legal battles, no risky side-loading schemes. Just two official, easy-to-join programs and a clear set of rules for subscriptions that can save you half of your commission fees&lt;/p&gt;



&lt;p&gt;If you take one thing away from this post, let it be this: &lt;strong&gt;check your enrollment status right now.&lt;/strong&gt;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;For Apple:&lt;/strong&gt; go to your &lt;a href=&quot;https://appstoreconnect.apple.com/&quot;&gt;App Store Connect&lt;/a&gt; agreements&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;For Google:&lt;/strong&gt; visit the &lt;a href=&quot;https://play.google.com/console/developers/associated-developer-accounts&quot;&gt;Associated developer accounts&lt;/a&gt; page in your Play Console&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;For RevenueCat:&lt;/strong&gt; head to your app settings and confirm your Small Business Program status is set correctly&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;If you’re not enrolled, take the ten minutes to do it. It will be the highest ROI you get all year. You’ve built a great app; you deserve to keep the revenue you’ve earned&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;A loving note from our editor:&lt;/strong&gt; you may have noticed this blog post is missing periods at the end of many paragraphs. Please don’t be thrown off or think we haven’t spotted this; it is simply the signature trademark of Rik Haandrikman, VP of Marketing at RevenueCat.&lt;/em&gt; &lt;em&gt;For more of his antics, &lt;a href=&quot;https://x.com/HHaandr&quot;&gt;follow Rik on X&lt;/a&gt; (you’ll know you’ve found the right account when you stop seeing periods).&lt;/em&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Ship early, learn faster: speed as a strategy for early-stage app growth]]></title><description><![CDATA[When to move fast, when to slow down, and how to learn without breaking trust]]></description><link>https://www.revenuecat.com/blog/growth/fast-shipping/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/fast-shipping/</guid><pubDate>Wed, 21 Jan 2026 16:45:08 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Blog_02_WhyEarlyShipping.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;We’ve all been in a meeting and had this question asked over and over again:&lt;/p&gt;



&lt;p&gt;“When will the experiment go live?”&lt;strong&gt; &lt;/strong&gt;&amp;nbsp;The dream answer: &lt;em&gt;“It already did.”&lt;/em&gt;&amp;nbsp;&lt;/p&gt;



&lt;p&gt;The reality? A familiar list of reasons and delays that you awkwardly have to explain to a Zoom-ful of people:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;We’re waiting on development&lt;/li&gt;



&lt;li&gt;We still need someone else’s sign-off&lt;/li&gt;



&lt;li&gt;Brand isn’t happy with the design yet&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;When this happens once, it’s not the end of the world. But when moving slowly becomes the default, it compounds. Especially for startups, where every delay means &lt;strong&gt;less learning&lt;/strong&gt; and a &lt;strong&gt;shorter runway.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;There’s the ‘ideal world’ we’re often taught: all stakeholders aligned, experiments neatly queued, and decisions made only after lifetime value has fully played out.&lt;/p&gt;



&lt;p&gt;And then there’s reality… every month costs money, most early ideas won’t work, and waiting for perfect data often means waiting too long.&lt;/p&gt;



&lt;p&gt;At some point, you have to let go of rigid rules and choose fast feedback over perfect planning. That’s uncomfortable, but it doesn’t mean being reckless;&lt;strong&gt; it means being intentional about where you move fast, where you slow down, and how quickly you decide what to learn from.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Here’s what you’re about to learn (and hopefully actually use):&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;The hidden risks of waiting for certainty&lt;/li&gt;



&lt;li&gt;Why fast feedback beats false confidence&lt;/li&gt;



&lt;li&gt;When to kill experiments early&lt;/li&gt;



&lt;li&gt;How to ship faster without breaking trust&lt;/li&gt;



&lt;li&gt;And when slowing down is actually the right move&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-certainty-is-what-you-get-after-shipping&quot;&gt;Certainty is what you get after shipping&lt;/h2&gt;



&lt;p&gt;I once worked with a client testing a landing page as part of a pre-launch experiment. The founder was a designer with an incredible eye for detail, and I joined her in double- and triple-checking every element. We’d done the work: months of research, competitor analysis, and even a painted-door test to validate interest before committing to a full build.&lt;/p&gt;



&lt;p&gt;Then the page finally went live. Celebration time!&amp;nbsp;&lt;/p&gt;



&lt;p&gt;We waited for the pre-launch commitments to roll in. The &lt;a href=&quot;https://www.revenuecat.com/blog/growth/customer-validation-subscription-app/&quot;&gt;painted door&lt;/a&gt; test (which gauges interest by showing a feature or offer before it exists) had signaled demand, so expectations were high. But almost nothing happened. No meaningful subscription sign-ups.&lt;/p&gt;



&lt;p&gt;What we &lt;em&gt;did&lt;/em&gt; learn, quickly, was far more valuable:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Meta ads were extremely expensive at that time of year, and we needed more video content to build trust and lower costs&lt;/li&gt;



&lt;li&gt;People hesitated at the subscription price, so &lt;a href=&quot;https://www.revenuecat.com/blog/growth/hybrid-monetization-techniques/&quot;&gt;we introduced an intermediate step first&lt;/a&gt;, and found that it converted better&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;We’d done everything ‘right’ to build confidence before launch. But &lt;em&gt;certainty&lt;/em&gt; about &lt;strong&gt;what worked and what didn’t only came after shipping&lt;/strong&gt;, once real people interacted with the page.&lt;/p&gt;



&lt;p&gt;This is where many &lt;a href=&quot;https://www.revenuecat.com/blog/growth/build-app-growth-team/&quot;&gt;growth teams&lt;/a&gt; get stuck. Early on, most bets are wrong. You’re operating with limited data, few returning subscribers, and barely any meaningful &lt;a href=&quot;https://www.revenuecat.com/glossary/#lifetime-value-ltv&quot;&gt;lifetime value (LTV)&lt;/a&gt; signal. &lt;a href=&quot;https://www.revenuecat.com/blog/growth/ad-monetization-subscription-apps/&quot;&gt;&lt;strong&gt;Monetization metrics&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt; at this stage are directional at best&lt;/strong&gt;, and not something you can wait on with confidence.&lt;/p&gt;



&lt;p&gt;Early monetization decisions aren’t about precision; they’re about momentum. You’re not trying to predict lifetime value; you’re trying to understand whether an offer is viable at all. Signals like &lt;a href=&quot;https://www.revenuecat.com/glossary/#trial-conversion-rate&quot;&gt;trial-to-paid conversion&lt;/a&gt;, &lt;a href=&quot;https://www.revenuecat.com/blog/growth/subscription-app-churn-reasons-how-to-fix&quot;&gt;early churn&lt;/a&gt;, or price sensitivity tell you where to look next, not where you’ll end up. Waiting for perfect LTV before acting assumes a level of certainty that simply doesn’t exist yet.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-your-simple-rule-for-moving-faster&quot;&gt;Your simple rule for moving faster&lt;/h3&gt;



&lt;p&gt;Reid Hoffman describes &lt;a href=&quot;https://www.amazon.co.uk/Blitzscaling-Lightning-Fast-Building-Massively-Companies/dp/0008303630&quot;&gt;blitzscaling&lt;/a&gt; as &lt;em&gt;prioritizing speed over efficiency in the face of uncertainty. &lt;/em&gt;That’s exactly what early growth requires — not recklessness, but a &lt;strong&gt;willingness to accept that clarity comes from exposure&lt;/strong&gt;, not preparation.&lt;/p&gt;



&lt;p&gt;We don’t gain certainty by thinking harder or planning longer. We learn by putting things into the world and observing how they behave. I’d love to build a campaign or feature that’s guaranteed to work. I can’t. No one can.&lt;/p&gt;



&lt;p&gt;So what’s the strategy?&lt;/p&gt;



&lt;p&gt;Your simple rule for moving faster should be as follows:&lt;/p&gt;



&lt;p&gt;&lt;em&gt;If the cost of being wrong is reversible and contained, move fast. &lt;/em&gt;&lt;em&gt;&lt;br&gt;&lt;/em&gt;&lt;em&gt;If it’s irreversible or erodes trust, slow down.&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;Growth isn’t about building confidence before you ship, but about &lt;strong&gt;earning confidence after you do&lt;/strong&gt;, which is why fast feedback is critical.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-fast-feedback-is-a-competitive-advantage&quot;&gt;Fast feedback is a competitive advantage&lt;/h2&gt;



&lt;p&gt;You’ll hear all kinds of stats about early-stage growth: ‘only 20% of what you do drives impact’, ‘only 10% really works’, simply that ‘most experiments fail’… I don’t know the exact number that’s accurate. What I do know, from leading growth at an early-stage startup and working with many others, is how frustrating it is just &lt;em&gt;how much&lt;/em&gt; doesn’t work.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;The teams that win aren’t the ones with a higher success rate. They’re the ones who find out faster.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Fast feedback isn’t about shipping more features or running more experiments. It’s about constantly asking: &lt;strong&gt;what’s the smallest possible way we can test this and learn something meaningful?&lt;/strong&gt; That might mean &lt;a href=&quot;https://www.revenuecat.com/blog/growth/7-meta-ad-testing-frameworks-for-subscription-apps/&quot;&gt;testing a value proposition through Meta ads&lt;/a&gt; before touching the app, or &lt;a href=&quot;https://www.revenuecat.com/blog/growth/testing-strategies-for-low-traffic-apps/&quot;&gt;experimenting with App Store messaging&lt;/a&gt; to see which feature focus actually drives conversion.&lt;/p&gt;



&lt;p&gt;That might mean questions like:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Which engagement behaviors reliably predict retention?&lt;/li&gt;



&lt;li&gt;What early revenue signals indicate higher-value users?&lt;/li&gt;



&lt;li&gt;Where do users hesitate before committing?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Most subscription apps know that annual plans typically produce higher LTV than monthly ones. The default response is to push annual as hard as possible, or remove monthly entirely. That may optimize monetization in the short term, but it slows learning.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://subclub.com/episode/vc-funding-vs-bootstrapping-for-subscription-apps-martin-siniawski-podcast-app&quot;&gt;Streema deliberately did the opposite&lt;/a&gt;. As Martin Siniawski has shared, they kept monthly subscriptions prominent so they could see churn sooner, understand what drove real, repeatable value, and actually talk to users who left.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-rules-for-fast-feedback-in-practice&quot;&gt;Rules for fast feedback in practice&lt;/h3&gt;



&lt;p&gt;That’s what fast feedback looks like in practice: prioritizing learning speed over delayed certainty. It means doing the following:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Design tests to fail quickly&lt;/strong&gt;, not to be statistically significant&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Use proxy metrics intentionally&lt;/strong&gt;, knowing they’re directional, not definitive (but good enough)&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Prefer reversible changes&lt;/strong&gt; over big, one-way launches&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Optimize for insight velocity&lt;/strong&gt;, not just conversion rate and monetization&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Create earlier moments of truth&lt;/strong&gt;, even if they temporarily hurt top-line metrics&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Speak to your users &lt;/strong&gt;rather than just relying solely on quantitative data&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Acting on what you learned, &lt;/strong&gt;even if it isn’t the result you hoped for&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Fast feedback isn’t just a product problem. It breaks down when teams can’t make decisions without multiple sign-offs, or when learning has to be approved before it’s acted on. Too many cooks spoil the broth and all that.&lt;/p&gt;



&lt;p&gt;So the final rule is simple: &lt;strong&gt;build an organization designed for speed&lt;/strong&gt;, creating autonomy and trust instead of relying on complex sign-offs.&lt;/p&gt;



&lt;p&gt;I promise you: fast feedback compounds over time and helps you grow faster.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-kill-your-darlings-fast-but-confidently&quot;&gt;Kill your darlings… fast, but confidently&lt;/h2&gt;



&lt;p&gt;The hardest part of moving fast isn’t shipping. It’s the moment after, when you’ve moved quickly, intentionally built a real alternative, and it simply doesn’t work. Like the pre-launch landing page that just wasn’t performing. It’s heartbreaking, and that’s usually when the temptation to ‘wait it out creeps in.&lt;/p&gt;



&lt;p&gt;Back to the pre-launch experiment I mentioned earlier. We were about a week post-launch. Long enough for people to convert, long enough to have some data, but not nearly enough to feel officially certain. Still, when I ran the numbers, it was hard to ignore what they were telling us. Even if we improved the creatives and lowered the &lt;a href=&quot;https://www.revenuecat.com/blog/growth/metrics-for-scaling-paid-ads/&quot;&gt;cost-per-click&lt;/a&gt; (CPC), we would still land far above our target cost-per-acquisition (CPA) for driving subscriptions.&lt;/p&gt;



&lt;p&gt;At that point, waiting stops being patience and starts just being hope. When early data is that far off, you can be confident it won’t pivot into winner. It might improve a bit, but not enough to justify the time, budget, and attention it would continue to absorb.&lt;/p&gt;



&lt;p&gt;That’s why — thanks to a great suggestion from the founder — we didn’t try to patch it up. We killed it, and moved on to a two-step page instead, a fundamentally different setup.&lt;/p&gt;



&lt;p&gt;But this is where it gets tricky.&lt;/p&gt;



&lt;p&gt;With another client, where I was &lt;a href=&quot;https://www.revenuecat.com/blog/engineering/price-testing-for-mobile-apps/&quot;&gt;running an A/B test&lt;/a&gt;, I did the thing we’re not supposed to do: I peeked early. The results weren’t great. The new variant was tracking slightly worse than the original. I didn’t like what I saw, but I also didn’t kill it. With only a handful of conversions per variant, there simply wasn’t enough signal yet. In &lt;em&gt;that&lt;/em&gt; case, giving it time proved to be the right call, and the variant ultimately won.&lt;/p&gt;



&lt;p&gt;There are instances when you need to give experiments time. This is especially true for &lt;a href=&quot;https://www.revenuecat.com/blog/engineering/price-testing-for-mobile-apps/&quot;&gt;pricing experiments&lt;/a&gt;: the initial conversion rate may suggest a new &lt;a href=&quot;https://www.revenuecat.com/blog/growth/guide-to-app-pricing-research-methods/&quot;&gt;pricing strategy&lt;/a&gt; or package offering is underperforming, but after one–two renewal cycles, you’ll see that overall revenue is up.&lt;/p&gt;



&lt;p&gt;So I’m not saying kill &lt;em&gt;all&lt;/em&gt; your darlings, but I’m also not saying give &lt;em&gt;everything&lt;/em&gt; endless time. Fast shipping and fast learning don’t mean a blanket kill-it-all approach. &lt;strong&gt;There are times when you should stop quickly, and times when you should deliberately wait.&lt;/strong&gt;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-rules-for-killing-your-darlings&quot;&gt;Rules for killing your darlings&lt;/h3&gt;



&lt;p&gt;What helps is being explicit about why you’re continuing or stopping. In practice, this is how we kill our darlings:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Peek strategically, but don’t broadcast early results &lt;/strong&gt;in a way that invites emotion-driven reactions&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Ensure there’s enough data to see direction,&lt;/strong&gt; even if you’re far from statistical certainty&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Run the maths on how far off you are from the target, &lt;/strong&gt;not just whether something is ‘up’ or ‘down’&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;See experiments as part of a bigger system, not one-off tests:&lt;/strong&gt; you can still believe in the hypothesis, even if this execution isn’t it&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Decide in advance which darlings deserve more time, &lt;/strong&gt;such as pricing experiments that need renewal cycles to show their impact&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Killing something early isn’t pessimistic. It’s often the most direct way to protect focus and create space for the next, better bet. There’s a real opportunity cost to not killing: every experiment you keep alive is one you’re choosing instead of something else that might actually move the needle.&lt;/p&gt;



&lt;p&gt;Think of it like pruning a plant. It feels awful to cut off healthy leaves, but you do it knowing the plant will be stronger and grow better because of it.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-speed-doesn-t-have-to-come-at-the-cost-of-quality-or-user-trust&quot;&gt;Speed doesn’t have to come at the cost of quality or user trust&lt;/h2&gt;



&lt;p&gt;One of the biggest fears teams have when they talk about moving faster is that quality will inevitably go down. And while that can happen, it’s not what moving fast actually has to mean. Speed doesn’t mean:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Sloppy work&lt;/li&gt;



&lt;li&gt;Broken experiences&lt;/li&gt;



&lt;li&gt;Shipping things users weren’t ready for&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;I was advising a client with a community-based app who wanted to improve moderation to ensure the community remained a genuinely good place to be. It was a strong idea, but also a big one. There were multiple concepts on the table, each requiring coordination across backend (to build a scoring system), frontend, design, and product. Because of that complexity, the initiative kept getting pushed out, not because it wasn’t important, but because it felt too big to start.&lt;/p&gt;



&lt;p&gt;When we zoomed out, one thing became very clear. The entire moderation system they wanted to build depended on a single assumption: that users would actually provide the input needed to make it work — likes, reactions, or signals about positive and negative interactions. If users weren’t willing to do that, or didn’t behave in the way the system expected, the whole model would either fail or require a fundamental rethink.&lt;/p&gt;



&lt;p&gt;So instead of building the entire moderation system, we focused on &lt;strong&gt;testing that assumption first&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;The first step wasn’t a scoring model or a full moderation flow. It was simply introducing — and observing — whether users would actively use like/reaction buttons when interacting with others. That single behavior would tell us whether the broader idea had a foundation to build on.&lt;/p&gt;



&lt;p&gt;If usage was low, the priority wouldn’t be better moderation logic, but understanding how to encourage or redesign that input. If it worked, the team could move forward with much greater confidence.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-what-does-minimum-viable-product-actually-mean&quot;&gt;What does Minimum Viable Product actually mean?&lt;/h3&gt;



&lt;p&gt;What’s important here is that this didn’t feel half-baked to users. They weren’t exposed to an unfinished system or asked to tolerate a worse experience. From their perspective, they simply had more ways to react and express how interactions felt. In fact, it already gave them a greater sense of control over what good and bad interactions looked like, without needing to know anything about the system being tested behind the scenes.&lt;/p&gt;



&lt;p&gt;This is what speed looks like when it’s done well: not rushing to build everything, but narrowing down &lt;strong&gt;what you actually need to learn first&lt;/strong&gt;. What is the smallest test that meaningfully de-risks the idea? Which assumption, if wrong, would make everything else irrelevant?&lt;/p&gt;



&lt;p&gt;This is why I like how Ethan Gar reframes the idea of a Minimum Viable Product (MVP):&lt;/p&gt;



&lt;p&gt;&lt;em&gt;“People get the minimum viable product idea wrong. They focus on the minimum, but not the viable. If I give you an app whose core functionality is broken, you won’t get value, and it won’t perform. When we are focusing on speed, we are focusing on the simplest viable version that delivers value.”&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;That distinction matters. The moderation example wasn’t about speed for its own sake or cutting corners. It was about delivering value early while learning which assumptions actually mattered — without overcommitting to complexity too soon.&lt;/p&gt;



&lt;p&gt;Of course, as you move faster, things will break more often. That’s part of the trade-off. But most of the time, users won’t even notice. And when you get this right, the value gained from faster learning usually outweighs the cost of the occasional misstep.&lt;/p&gt;



&lt;p&gt;Which brings us to the harder question: &lt;strong&gt;when is speed no longer the right choice&lt;/strong&gt;, and when does slowing down actually protect quality and trust?&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-when-should-perfection-take-priority-over-speed&quot;&gt;When should perfection take priority over speed?&lt;/h2&gt;



&lt;p&gt;Speed isn’t universally correct. There are moments where slowing down isn’t cautious, it’s responsible. Moments when perfection is the right way to ship. These are often situations where a generalist mindset no longer helps, and moving too fast creates more risk than value.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;The mistake teams often make is treating perfection as the standard mode of operation, when in reality it should be reserved for specific moments. To move past that tension, it helps to be explicit about which situations actually deserve slowness.&lt;/p&gt;



&lt;p&gt;Not all of these will apply to every app or brand, but walking through them helps clarify where slowing down is intentional rather than accidental.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-core-functionality-of-your-app&quot;&gt;1. Core functionality of your app&lt;/h3&gt;



&lt;p&gt;When it comes to the core value your app provides, there’s a minimum bar that needs to be met. Not ‘perfect’ in the abstract sense, but good enough that users clearly experience the value early in their journey.&lt;/p&gt;



&lt;p&gt;This aligns closely with Ethan Gar’s idea of &lt;em&gt;minimum viable value&lt;/em&gt;. &lt;strong&gt;The goal isn’t to ship everything, but to make sure what you &lt;/strong&gt;&lt;strong&gt;&lt;em&gt;do&lt;/em&gt;&lt;/strong&gt;&lt;strong&gt; ship genuinely works. &lt;/strong&gt;If users are paying for the app, performance and reliability matter. You can still move fast in how you validate and iterate, but the underlying experience needs to meet a clear standard from the start.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-large-one-way-technical-decisions&quot;&gt;2. Large, one-way technical decisions&lt;/h3&gt;



&lt;p&gt;Some technical choices are hard to undo. For example, when advising an app considering a transition to &lt;a href=&quot;https://flutter.dev/&quot;&gt;Flutter&lt;/a&gt;, it became clear just how much was at stake. Migrations like this touch almost everything and create long-term consequences.&lt;/p&gt;



&lt;p&gt;This is where slowing down is justified. You want clarity on why you’re doing it, what problem it actually solves, and how success will be measured. A common trap is using a technical rewrite as an excuse to ‘fix everything’, which often leads to long delays.&lt;/p&gt;



&lt;p&gt;Perfection here doesn’t mean dramatically improving everything. It often means ensuring the new version performs at least as well as the old one, without introducing instability. That bar is usually lower than teams expect, but still worth protecting.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-data-privacy-and-security&quot;&gt;3. Data privacy and security&lt;/h3&gt;



&lt;p&gt;Whenever you’re handling user data, speed takes a back seat. This includes privacy, consent, tracking, and compliance. Carelessness here erodes trust quickly, and it’s difficult to recover from.&lt;/p&gt;



&lt;p&gt;This is not an area for rough experiments or shortcuts. It’s one of the few places where being overly-cautious is usually the right call.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-4-vulnerable-user-groups&quot;&gt;4. Vulnerable user groups&lt;/h3&gt;



&lt;p&gt;If your app serves vulnerable audiences, extra care is required. I once spoke to someone working on a mental health app for children (a double dimension sensitive topic).&lt;/p&gt;



&lt;p&gt;In cases like this, teams often invest heavily in research and exploration before shipping anything meaningful. That doesn’t mean nothing ever gets released, but it does mean the bar for thoughtfulness and validation is higher, and the cost of getting it wrong is taken very seriously.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-5-brand-defining-moments&quot;&gt;5. Brand-defining moments&lt;/h3&gt;



&lt;p&gt;Some releases don’t just add functionality; they reshape how users perceive the brand. These moments deserve extra care.&lt;/p&gt;



&lt;p&gt;A good example is &lt;a href=&quot;https://www.joinladder.com/&quot;&gt;Ladder&lt;/a&gt;, a fitness app that expanded into nutrition, repositioning itself from purely fitness-focused to a broader health platform. That’s a significant shift in both competitive space and user expectations.&lt;/p&gt;



&lt;p&gt;The first version wasn’t perfect, but it felt deliberately more complete than it strictly needed to be. Features like nutrition input via voice, image, and text were available from the start, rather than offering just one method. That choice wasn’t about speed or scope; it was about ensuring users felt the new positioning immediately.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-6-irreversible-decisions-one-way-doors&quot;&gt;6. Irreversible decisions (one-way doors)&lt;/h3&gt;



&lt;p&gt;Jeff Bezos describes decisions as either one-way or two-way doors. Two-way doors can be reversed; one-way doors cannot.&lt;/p&gt;



&lt;p&gt;Changing your target audience, fundamentally shifting your app’s purpose, or making promises you can’t easily walk back are all one-way doors. These are moments to slow down, pressure-test assumptions, and be honest about the long-term implications.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-7-proven-functionality-being-rebuilt-or-scaled&quot;&gt;7. Proven functionality being rebuilt or scaled&lt;/h3&gt;



&lt;p&gt;Finally, when something has already been validated, rushing the implementation can be counterproductive. That’s how teams end up with fragile systems, spaghetti code, and a growing backlog of bugs.&lt;/p&gt;



&lt;p&gt;I’m painfully aware of this one, partly because my husband works as a developer at an edtech startup and spends a large part of his time untangling exactly these kinds of rushed implementations. The time saved upfront is almost always paid back with interest later.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-speed-is-the-default-perfection-is-selective&quot;&gt;Speed is the default. Perfection is selective.&lt;/h2&gt;



&lt;p&gt;Most subscription teams don’t fail because they move too fast. They fail because they wait too long to learn. &lt;strong&gt;Certainty doesn’t come from better planning, more sign-offs, or cleaner spreadsheets; it comes from shipping, observing, and deciding.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;It’s a balancing act between certainty and risk:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1021&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-85-1024x1021.png&quot; alt=&quot;&quot; class=&quot;wp-image-50863&quot; style=&quot;width:800px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-85-1024x1021.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-85-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-85-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-85-768x766.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-85-1536x1531.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-85-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-85-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-85-465x464.png 465w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-85-696x694.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-85-560x558.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-85-297x296.png 297w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-85-473x472.png 473w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-85-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-85-48x48.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-85.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Fast feedback is a competitive advantage, not because it guarantees success, but because it helps you stop wasting time on the wrong things sooner. Speed doesn’t have to mean sloppy work or broken trust. When done well, it’s about narrowing the learning question, testing the smallest meaningful assumption, and moving on quickly when something isn’t working.&lt;/p&gt;



&lt;p&gt;There are moments where slowing down is not only justified but necessary. When trust, safety, irreversibility, or core values are on the line. But these moments are the exception, not the rule. For most early-stage teams, speed should remain the default. Perfection is something you apply selectively, &lt;strong&gt;when the cost of getting it wrong outweighs the cost of waiting.&lt;/strong&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[How Cem Kansu helped Duolingo scale monetization without breaking freemium]]></title><description><![CDATA[On the podcast, I talk with Cem about the premium trap many apps fall into, why free trials work even for freemium products, and how ‘try for $0.00’ actually outperforms ‘try for free’.]]></description><link>https://www.revenuecat.com/blog/growth/cem-kansu-duolingo-sub-club-podcast-2026/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/cem-kansu-duolingo-sub-club-podcast-2026/</guid><pubDate>Wed, 21 Jan 2026 13:46:55 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/RC-Blog-Cover-Cem-Kansu-1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Duolingo is one of the clearest examples of freemium done &lt;em&gt;right&lt;/em&gt;. Tens of millions of daily users. A massive free experience. And a subscription business that generates the vast majority of its revenue—without gutting what made the product valuable in the first place.&lt;/p&gt;



&lt;p&gt;In this episode of Sub Club, Cem Kansu—former VP of Product at Duolingo—walks through the decisions, trade-offs, and hard calls behind that balance. What stands out isn’t a clever pricing trick or a perfectly tuned paywall. It’s a philosophy: &lt;strong&gt;protect the free experience, even when short-term revenue is tempting&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;Here are the core lessons every subscription app builder can take from Duolingo’s journey.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;Why Your Free Users Are Your Real Growth Engine – Cem Kansu (Duolingo CPO)&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/pqbbyRMssbQ?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;iframe loading=&quot;lazy&quot; width=&quot;100%&quot; height=&quot;180&quot; frameborder=&quot;no&quot; scrolling=&quot;no&quot; seamless=&quot;&quot; src=&quot;https://share.transistor.fm/e/647bf673?color=FFFFFF&amp;amp;background=30343C&quot;&gt;&lt;/iframe&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-protect-the-free-moat-always&quot;&gt;Protect the free moat—always&lt;/h2&gt;



&lt;p&gt;One of the biggest traps in freemium is also the easiest win: take something free, make it paid, and watch revenue spike.&lt;/p&gt;



&lt;p&gt;Cem has seen this play out repeatedly—and warns it rarely works long-term.&lt;/p&gt;



&lt;p&gt;At Duolingo, the free experience wasn’t just a funnel. It was the product’s moat. Locking too much behind a paywall might boost metrics for six months, maybe a year. But it weakens the growth engine and creates space for competitors to offer what you just took away.&lt;/p&gt;



&lt;p&gt;Free value isn’t charity. It’s strategy.&lt;/p&gt;



&lt;p&gt;Duolingo’s early success came from doing something incumbents wouldn’t: offering high-quality language learning completely free. Undoing that advantage would have meant undoing the company’s differentiation. So instead of extracting more from free users, the team focused on preserving—and often expanding—the free experience, even when it meant saying no to revenue-positive ideas.&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-freemium-isn-t-a-trade-off-it-s-the-growth-engine&quot;&gt;Freemium isn’t a trade-off—it’s the growth engine&lt;/h2&gt;



&lt;p&gt;At Duolingo, free users were never treated as freeloaders. They were the primary distribution channel.&lt;/p&gt;



&lt;p&gt;Word of mouth fueled growth, and word of mouth only worked if the free product delighted people. When free users learned more, progressed faster, and felt respected, they told their friends. That loop compounded.&lt;/p&gt;



&lt;p&gt;This is why Duolingo was willing to do something that feels counterintuitive to many subscription teams: &lt;strong&gt;move features from paid back to free&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;When features like Practice Hub or “Explain my answer” didn’t justify their revenue impact—or became cheaper to run thanks to AI efficiency—the team intentionally took a revenue hit to strengthen the free experience. The short-term numbers dipped. The long-term growth engine got stronger.&lt;/p&gt;



&lt;p&gt;That trade-off only makes sense if you believe free users are part of your business, not a cost center.&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-monetize-with-empathy-not-extraction&quot;&gt;Monetize with empathy, not extraction&lt;/h2&gt;



&lt;p&gt;Introducing monetization to a previously free product is as much a cultural shift as a product one.&lt;/p&gt;



&lt;p&gt;When Duolingo added ads, the team expected backlash—and they got some. But instead of reacting emotionally to negative reviews, they zoomed out. They measured everything: retention, app closes, review volume per million DAUs, complaint rates across different issues.&lt;/p&gt;



&lt;p&gt;What they found was grounding. Ads created noise, but they didn’t meaningfully damage the core experience when done carefully.&lt;/p&gt;



&lt;p&gt;The rule was simple: &lt;strong&gt;optimize for trust, not ARPU&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;Ads only appeared after a lesson—never before, never during. Categories that felt off-brand or unsafe were blocked, even if it cost revenue. Over time, Duolingo went further, partnering directly with advertisers to create custom ad formats that fit the product’s tone and even extended its character-driven world.&lt;/p&gt;



&lt;p&gt;The goal wasn’t to squeeze users harder. It was to monetize in ways that felt fair, predictable, and respectful.&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-a-b-test-relentlessly-but-know-when-to-ignore-the-data&quot;&gt;A/B test relentlessly—but know when to ignore the data&lt;/h2&gt;



&lt;p&gt;Duolingo runs hundreds of experiments at any given time. Testing is foundational to how the product evolves.&lt;/p&gt;



&lt;p&gt;But Cem is clear: experimentation isn’t the same as outsourcing judgment to dashboards.&lt;/p&gt;



&lt;p&gt;Many tests surface uncomfortable trade-offs—revenue up, learning quality down; engagement up, trust eroding slowly. In those moments, the job of product leadership isn’t to follow the green line. It’s to decide whether the result aligns with the company’s long-term goals.&lt;/p&gt;



&lt;p&gt;Some of Duolingo’s most important decisions required taking a measurable loss: lower revenue, lower short-term engagement, worse-looking graphs. Those calls often needed senior buy-in because the upside—stronger learning, deeper trust, long-term growth—couldn’t be fully captured by a single metric.&lt;/p&gt;



&lt;p&gt;Data informs decisions. It doesn’t make them.&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-ads-can-be-strategic-and-even-creative&quot;&gt;Ads can be strategic—and even creative&lt;/h2&gt;



&lt;p&gt;Duolingo didn’t just “add ads.” It treated ads as part of the product experience.&lt;/p&gt;



&lt;p&gt;Placement mattered. Timing mattered. Quality mattered.&lt;/p&gt;



&lt;p&gt;Ads only appeared at natural breaks, never interrupting learning. Programmatic categories were aggressively filtered. And increasingly, Duolingo shifted toward direct brand partnerships, embedding its own characters into ads to make them feel less jarring and more native.&lt;/p&gt;



&lt;p&gt;Internally, ads weren’t just monetization. They were another surface to reinforce brand, tone, and user expectations—while still funding free education at scale.&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-build-for-everyone-not-a-persona&quot;&gt;Build for everyone, not a persona&lt;/h2&gt;



&lt;p&gt;One of Cem’s most contrarian takes: personas are often a liability at scale.&lt;/p&gt;



&lt;p&gt;Language learners don’t fit clean buckets. People learn for work, for travel, for family, for identity, for fun. Optimizing for a single “core persona” risks alienating the long tail that actually drives growth.&lt;/p&gt;



&lt;p&gt;Instead of narrowing the audience, Duolingo built systems flexible enough to serve wildly different motivations—without forcing users into rigid paths. That inclusivity is part of how the product scaled from millions to tens of millions of users without fragmenting.&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-throughline-take-the-long-view&quot;&gt;The throughline: take the long view&lt;/h2&gt;



&lt;p&gt;Across monetization, experimentation, ads, subscriptions, and AI, Duolingo followed a consistent principle: &lt;strong&gt;build the company you want to exist in 100 years, not the one that looks best this quarter&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;That mindset made some decisions harder. It meant leaving money on the table. It meant resisting obvious optimizations. But it also built trust, sustained growth, and a freemium model that didn’t collapse under its own incentives.&lt;/p&gt;



&lt;p&gt;For subscription app builders, the lesson is clear:&lt;br&gt;If you burn your free moat, you burn your future.&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;p&gt;🎧 &lt;strong&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=pqbbyRMssbQ&quot;&gt;Listen to the full Sub Club episode with Cem Kansu&lt;/a&gt;&lt;/strong&gt; to hear the stories, experiments, and trade-offs behind Duolingo’s monetization journey—straight from the person who led it.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Understanding Google Play’s subscription price changes: a complete guide]]></title><description><![CDATA[You will cover how to manage subscription price changes—covering opt-in vs. opt-out models, notification requirements, implementation details, and how RevenueCat helps handle the process smoothly for both new and existing subscribers.]]></description><link>https://www.revenuecat.com/blog/engineering/google-play-price-change/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/google-play-price-change/</guid><pubDate>Wed, 21 Jan 2026 01:49:31 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Blog_12_Understanding-Google-Plays-subscription-price-changes.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Subscription pricing is rarely static. Market conditions change, costs fluctuate, and business strategies evolve. At some point, you will likely need to adjust your subscription prices, whether increasing them to reflect added value or decreasing them to attract more users. However, changing subscription prices on Google Play is not as simple as updating a number in a dashboard.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Price changes affect existing subscribers differently than new customers, require specific notification flows, and must be handled carefully to maintain user trust and comply with Google Play’s policies. Luckily, this article will explain how subscription price changes work on Google Play in-depth. We’ll cover:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Mechanics of changing prices for both new and existing subscribers&lt;/li&gt;



&lt;li&gt;Differences between opt-in and opt-out price increases&lt;/li&gt;



&lt;li&gt;Notification requirements and timelines&lt;/li&gt;



&lt;li&gt;Implementation details (with a walk through example)&lt;/li&gt;



&lt;li&gt;How RevenueCat can help manage price changes gracefully across your subscriber base&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-price-changes-affect-different-subscriber-groups&quot;&gt;&lt;strong&gt;How price changes affect different subscriber groups&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;When you modify a subscription price in the Google Play Console or via the API, the change doesn’t affect all users in the same way. Here’s how Google Play handles new subscribers and existing subscribers differently:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-new-subscribers&quot;&gt;&lt;strong&gt;New subscribers&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;For new purchases, price changes take effect relatively quickly, typically within a few hours of making the change. Once the new price is active, anyone who initiates a new subscription purchase will see and pay the updated price. No special handling is required for this group; they simply see the current price when they reach the purchase screen.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-existing-subscribers-the-legacy-price-cohort&quot;&gt;&lt;strong&gt;Existing subscribers: the legacy price cohort&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Existing subscribers are a different matter entirely. By default, when you change a subscription price, current subscribers are placed into what Google calls a &lt;strong&gt;legacy price cohort&lt;/strong&gt;. These users continue paying their original price at each renewal, completely unaffected by the price change. This default behavior protects users from unexpected billing changes and gives you control over when and how to migrate them to new pricing.&lt;/p&gt;



&lt;p&gt;This legacy cohort mechanism means changing a price in the Play Console &lt;strong&gt;does not automatically change what existing subscribers pay&lt;/strong&gt;. You must explicitly choose to migrate subscribers to the new price.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-ending-a-legacy-price-cohort&quot;&gt;&lt;strong&gt;Ending a legacy price cohort&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;When you decide to move existing subscribers from their legacy price to a new price, you use the price migration API. This initiates either a price increase or price decrease flow, depending on whether the new price is higher or lower than what users currently pay.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-using-the-migration-api&quot;&gt;&lt;strong&gt;Using the migration API&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;To migrate subscribers to a new price, you call the &lt;a href=&quot;https://developers.google.com/android-publisher/api-ref/rest/v3/monetization.subscriptions.basePlans/migratePrices&quot;&gt;monetization.subscriptions.basePlans.migratePrices&lt;/a&gt; endpoint on your backend side:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Op87K wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/\/ Backend service for initiating price migration\nclass PriceMigrationService(\n    private val androidPublisher: AndroidPublisher\n) {\n    fun migrateSubscribersToNewPrice(\n        packageName: String,\n        productId: String,\n        basePlanId: String,\n        regions: List&lt;String&gt;,\n        newPriceAmountMicros: Long,\n        currencyCode: String\n    ) {\n        val regionalConfigs = regions.map { regionCode -&gt;\n            RegionalPriceMigrationConfig().apply {\n                this.regionCode = regionCode\n                this.priceIncreaseType = \&amp;quot;OPT_IN\&amp;quot; \/\/ or \&amp;quot;OPT_OUT\&amp;quot; if eligible\n                this.oldestAllowedPriceVersionTime = null \/\/ migrate all legacy cohorts\n            }\n        }\n\n        val request = MigratePricesRequest().apply {\n            this.regionalPriceMigrationConfigs = regionalConfigs\n        }\n\n        androidPublisher\n            .monetization()\n            .subscriptions()\n            .basePlans()\n            .migratePrices(packageName, productId, basePlanId, request)\n            .execute()\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The migration is specific to each region, allowing you to roll out price changes gradually across different markets or handle regional pricing differences independently.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;price-decrease-flow&quot;&gt;&lt;strong&gt;Price decrease flow&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;When the new price is lower than what users currently pay, the migration process is straightforward and easy for users. Price decreases are automatically applied without requiring explicit user acceptance.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;how-price-decreases-work&quot;&gt;&lt;strong&gt;How price decreases work&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;When you migrate subscribers to a lower price, Google Play sends email notifications informing users of the price decrease. Users then begin paying the lower price at their next renewal, and no user action is required since the decrease happens automatically.&lt;/p&gt;



&lt;p&gt;There is one timing nuance to be aware of: Google Play may authorize payment up to 48 hours before renewal (or up to five days in India and Brazil). If a user’s payment was already authorized at the higher price before the decrease was applied, they will pay the higher price for that renewal but will receive the lower price on subsequent renewals.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;handling-price-decreases-in-your-app&quot;&gt;&lt;strong&gt;Handling price decreases in your app&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;From an implementation perspective, price decreases require minimal handling. You may want to communicate the good news to users:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-OQj1W wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;class PriceChangeManager(\n    private val backendApi: BackendApi\n) {\n    suspend fun checkForPriceChanges(userId: String): PriceChangeInfo? {\n        val subscriptionStatus = backendApi.getSubscriptionStatus(userId)\n        val priceChange = subscriptionStatus.pendingPriceChange ?: return null\n\n        return when {\n            priceChange.newPriceMicros &lt; priceChange.currentPriceMicros -&gt; {\n                PriceChangeInfo.Decrease(\n                    currentPrice = formatPrice(priceChange.currentPriceMicros),\n                    newPrice = formatPrice(priceChange.newPriceMicros),\n                    effectiveDate = priceChange.effectiveDate\n                )\n            }\n            else -&gt; {\n                \/\/ Handle price increase (covered in next section)\n                handlePriceIncrease(priceChange)\n            }\n        }\n    }\n}\n\n\/\/ In your UI layer\nfun showPriceDecreaseNotification(info: PriceChangeInfo.Decrease) {\n    showBanner(\n        title = \&amp;quot;Good news!\&amp;quot;,\n        message = \&amp;quot;Your subscription price is decreasing from ${info.currentPrice} \&amp;quot; +\n            \&amp;quot;to ${info.newPrice} starting ${formatDate(info.effectiveDate)}.\&amp;quot;\n    )\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Price decreases are generally positive events for users, so your primary concern is ensuring they are aware of the change rather than managing any acceptance flow.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;price-increase-flow-opt-in-increases&quot;&gt;&lt;strong&gt;Price increase flow: opt-in increases&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Price increases are more complex because they require user awareness and, in most cases, explicit acceptance. The default method for price increases is the &lt;strong&gt;opt-in&lt;/strong&gt; flow, where users must explicitly agree to the new price before being charged.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-opt-in-timeline&quot;&gt;&lt;strong&gt;The opt-in timeline&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The opt-in price increase flow follows a specific timeline with distinct phases:&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Phase&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Duration&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;What Happens&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Freeze period&lt;/td&gt;&lt;td&gt;Days 1 to 7&lt;/td&gt;&lt;td&gt;Google Play sends no notifications; developer can notify users&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Notification period&lt;/td&gt;&lt;td&gt;Days 8 to 37&lt;/td&gt;&lt;td&gt;Google Play sends email and push notifications&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Effective date&lt;/td&gt;&lt;td&gt;Day 37 onwards&lt;/td&gt;&lt;td&gt;Price increase takes effect; charged at next renewal&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;The seven day freeze period at the beginning is intentional. It gives you the opportunity to notify users through your own channels before Google Play’s automated notifications begin. This allows you to control the messaging and potentially explain the value users receive for the increased price.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;user-acceptance-requirement&quot;&gt;&lt;strong&gt;User acceptance requirement&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;For opt-in price increases, users must explicitly accept the new price. They do this through the Play Store subscription management screen, where they see a dialog explaining the price change and can either accept or decline.&lt;/p&gt;



&lt;p&gt;If a user doesn’t accept the price increase before their first renewal at the new price, their subscription is automatically canceled. They retain access until the end of their current billing period, but the subscription will not renew.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;handling-opt-in-increases-in-your-app&quot;&gt;&lt;strong&gt;Handling opt-in increases in your app&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Your app should detect pending price increases and guide users through the acceptance process:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-2vayNc wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;class OptInPriceIncreaseManager(\n    private val billingClient: BillingClient,\n    private val backendApi: BackendApi\n) {\n    sealed class PriceIncreaseState {\n        object None : PriceIncreaseState()\n        data class Pending(\n            val currentPrice: String,\n            val newPrice: String,\n            val effectiveDate: Instant,\n            val inFreezePeriod: Boolean\n        ) : PriceIncreaseState()\n        object Accepted : PriceIncreaseState()\n        object Declined : PriceIncreaseState()\n    }\n\n    suspend fun checkPriceIncreaseStatus(userId: String): PriceIncreaseState {\n        val subscriptionStatus = backendApi.getSubscriptionStatus(userId)\n        val priceChange = subscriptionStatus.pendingPriceChange\n\n        if (priceChange == null || priceChange.newPriceMicros &lt;= priceChange.currentPriceMicros) {\n            return PriceIncreaseState.None\n        }\n\n        return when (priceChange.state) {\n            \&amp;quot;OUTSTANDING\&amp;quot; -&gt; {\n                val freezePeriodEnd = priceChange.initiatedAt.plus(Duration.ofDays(7))\n                PriceIncreaseState.Pending(\n                    currentPrice = formatPrice(priceChange.currentPriceMicros),\n                    newPrice = formatPrice(priceChange.newPriceMicros),\n                    effectiveDate = priceChange.effectiveDate,\n                    inFreezePeriod = Instant.now().isBefore(freezePeriodEnd)\n                )\n            }\n            \&amp;quot;CONFIRMED\&amp;quot; -&gt; PriceIncreaseState.Accepted\n            \&amp;quot;CANCELED\&amp;quot; -&gt; PriceIncreaseState.Declined\n            else -&gt; PriceIncreaseState.None\n        }\n    }\n\n    fun showPriceIncreaseUI(\n        activity: Activity,\n        state: PriceIncreaseState.Pending\n    ) {\n        if (state.inFreezePeriod) {\n            \/\/ During freeze period, show your own messaging\n            showCustomPriceIncreaseDialog(\n                currentPrice = state.currentPrice,\n                newPrice = state.newPrice,\n                effectiveDate = state.effectiveDate,\n                onAcceptClick = { openPlayStoreSubscriptionSettings(activity) }\n            )\n        } else {\n            \/\/ After freeze period, can also use Google&apos;s in app messaging\n            showInAppMessage(activity)\n        }\n    }\n\n    private fun showInAppMessage(activity: Activity) {\n        val params = InAppMessageParams.newBuilder()\n            .addInAppMessageCategoryToShow(\n                InAppMessageParams.InAppMessageCategoryId.SUBSCRIPTION_PRICE_CHANGE\n            )\n            .build()\n\n        billingClient.showInAppMessages(activity, params) { result -&gt;\n            \/\/ Handle the result\n            when (result.responseCode) {\n                InAppMessageResult.InAppMessageResponseCode.NO_ACTION_NEEDED -&gt; {\n                    \/\/ No price change message needed or user already responded\n                }\n                InAppMessageResult.InAppMessageResponseCode.SUBSCRIPTION_STATUS_UPDATED -&gt; {\n                    \/\/ User interacted with the message - refresh subscription status\n                    refreshSubscriptionStatus()\n                }\n            }\n        }\n    }\n\n    private fun openPlayStoreSubscriptionSettings(activity: Activity) {\n        val intent = Intent(Intent.ACTION_VIEW).apply {\n            data = Uri.parse(\n                \&amp;quot;&lt;https:\/\/play.google.com\/store\/account\/subscriptions&gt;\&amp;quot;\n            )\n            setPackage(\&amp;quot;com.android.vending\&amp;quot;)\n        }\n        activity.startActivity(intent)\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;communicating-value-during-price-increases&quot;&gt;&lt;strong&gt;Communicating value during price increases&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The freeze period is your opportunity to communicate directly with users about why the price is increasing. Effective communication can significantly improve acceptance rates:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZS1rSd wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;fun showCustomPriceIncreaseDialog(\n    currentPrice: String,\n    newPrice: String,\n    effectiveDate: Instant,\n    onAcceptClick: () -&gt; Unit\n) {\n    showDialog(\n        title = \&amp;quot;Subscription Update\&amp;quot;,\n        message = \&amp;quot;\&amp;quot;\&amp;quot;\n            Starting ${formatDate(effectiveDate)}, your subscription will change\n            from $currentPrice to $newPrice per month.\n\n            Since you subscribed, we&apos;ve added:\n            \u2022 Advanced analytics dashboard\n            \u2022 Offline mode for all content\n            \u2022 Priority customer support\n            \u2022 And 15+ other features\n\n            To continue enjoying these features, please confirm the new price\n            in your Play Store subscription settings.\n        \&amp;quot;\&amp;quot;\&amp;quot;.trimIndent(),\n        positiveButton = \&amp;quot;Review in Play Store\&amp;quot; to onAcceptClick,\n        negativeButton = \&amp;quot;Maybe Later\&amp;quot; to { \/* dismiss *\/ }\n    )\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;price-increase-flow-opt-out-increases&quot;&gt;&lt;strong&gt;Price increase flow: opt-out increases&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;In certain regions and under specific conditions, Google Play allows &lt;strong&gt;opt-out&lt;/strong&gt; price increases. With opt-out increases, users are notified of the price change but are automatically charged the new price unless they explicitly cancel or change their plan.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;eligibility-requirements&quot;&gt;&lt;strong&gt;Eligibility requirements&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Opt-out price increases are not universally available. Eligibility depends on several factors including regional availability (only certain countries support opt-out increases), frequency limits on how often you can use them, maximum percentage or absolute amount restrictions per country, and additional developer eligibility requirements. Because of these restrictions, opt-out increases should be considered a supplementary option rather than your primary approach to price changes.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;opt-out-timeline&quot;&gt;&lt;strong&gt;Opt-out timeline&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The opt-out timeline differs from opt-in increases:&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Aspect&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Opt In&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;opt-out&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Freeze period&lt;/td&gt;&lt;td&gt;7 days&lt;/td&gt;&lt;td&gt;None&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Notification period&lt;/td&gt;&lt;td&gt;30 days&lt;/td&gt;&lt;td&gt;30 or 60 days (varies by country)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;User action required&lt;/td&gt;&lt;td&gt;Must accept&lt;/td&gt;&lt;td&gt;Can cancel to avoid&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Default behavior&lt;/td&gt;&lt;td&gt;Subscription cancels&lt;/td&gt;&lt;td&gt;New price charged&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;The notification period for opt-out varies by country. Some require 30 days notice, while others require 60 days. Google Play handles these regional requirements automatically when you initiate an opt-out migration.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;handling-opt-out-increases&quot;&gt;&lt;strong&gt;Handling opt-out increases&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;From an implementation perspective, opt-out increases are simpler because users do not need to take action to continue their subscription:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-LIEtI wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;fun handleOptOutPriceIncrease(priceChange: PriceChangeInfo) {\n    \/\/ For opt-out increases, the state will be \&amp;quot;CONFIRMED\&amp;quot; rather than \&amp;quot;OUTSTANDING\&amp;quot;\n    \/\/ Users will be charged the new price automatically unless they cancel\n\n    showNotification(\n        title = \&amp;quot;Subscription Price Update\&amp;quot;,\n        message = \&amp;quot;Starting ${formatDate(priceChange.effectiveDate)}, \&amp;quot; +\n            \&amp;quot;your subscription will be ${priceChange.newPrice}\/month. \&amp;quot; +\n            \&amp;quot;No action needed to continue your subscription.\&amp;quot;\n    )\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;However, you should still communicate clearly with users about the upcoming change, even though their action is not required.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;in-app-notification-requirements&quot;&gt;&lt;strong&gt;In-app notification requirements&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Regardless of whether you use opt-in or opt-out price increases, Google Play requires you to display in-app notices about price changes. This requirement applies across all device types where your app runs.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;mandatory-notification-surfaces&quot;&gt;&lt;strong&gt;Mandatory notification surfaces&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;You must show price change notifications on mobile devices (phones and tablets), Android TV, and other streaming devices. The only exception is watches, where in-app notification is recommended but not strictly required due to the limited screen real estate.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;notification-timing&quot;&gt;&lt;strong&gt;Notification timing&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;For opt-in increases, the recommended approach is to show your own custom messaging explaining the value proposition during the freeze period (days one to seven), then continue showing reminders and use Google’s In App Messaging API after the freeze period ends (days eight onwards).&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z5Gy8E wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;class PriceChangeNotificationManager(\n    private val billingClient: BillingClient\n) {\n    fun showPriceChangeNotificationIfNeeded(\n        activity: Activity,\n        priceIncreaseState: PriceIncreaseState\n    ) {\n        when (priceIncreaseState) {\n            is PriceIncreaseState.Pending -&gt; {\n                \/\/ Always show some form of notification for pending increases\n                if (priceIncreaseState.inFreezePeriod) {\n                    showCustomNotificationBanner(activity, priceIncreaseState)\n                } else {\n                    \/\/ Use Google&apos;s in app messaging\n                    showGoogleInAppMessage(activity)\n                }\n            }\n            else -&gt; {\n                \/\/ No notification needed\n            }\n        }\n    }\n\n    private fun showCustomNotificationBanner(\n        activity: Activity,\n        state: PriceIncreaseState.Pending\n    ) {\n        \/\/ Show a subtle banner at the top of the screen\n        val banner = PriceChangeBanner(activity).apply {\n            setMessage(\n                \&amp;quot;Your subscription price will change to ${state.newPrice} \&amp;quot; +\n                \&amp;quot;on ${formatDate(state.effectiveDate)}. Tap to review.\&amp;quot;\n            )\n            setOnClickListener {\n                openPriceChangeDetails(activity, state)\n            }\n        }\n        banner.show()\n    }\n\n    private fun showGoogleInAppMessage(activity: Activity) {\n        val params = InAppMessageParams.newBuilder()\n            .addInAppMessageCategoryToShow(\n                InAppMessageParams.InAppMessageCategoryId.SUBSCRIPTION_PRICE_CHANGE\n            )\n            .build()\n\n        billingClient.showInAppMessages(activity, params) { \/* handle result *\/ }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;handling-overlapping-price-changes&quot;&gt;&lt;strong&gt;Handling overlapping price changes&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;What happens if you initiate a new price change while a previous one is still pending? Google Play handles this by canceling the previous price change and applying the new one.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-cancellation-and-replacement-flow&quot;&gt;&lt;strong&gt;The cancellation and replacement flow&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;When overlapping price changes occur, the old price migration is marked as CANCELED and you receive a SUBSCRIPTION_PRICE_CHANGE_UPDATED Real-Time Developer Notification (RTDN). The new price migration then takes effect, and users only need to respond to the latest price change. This behavior prevents users from being forced to accept multiple sequential price increases, which would create a poor user experience.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;tracking-price-change-status&quot;&gt;&lt;strong&gt;Tracking price change status&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Your backend should process RTDN notifications to track price change status:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z2ut56L wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/\/ Backend notification handler\nclass PriceChangeNotificationHandler(\n    private val subscriptionRepository: SubscriptionRepository,\n    private val playDeveloperApi: AndroidPublisher\n) {\n    fun handlePriceChangeNotification(notification: DeveloperNotification) {\n        val purchaseToken = notification.subscriptionNotification.purchaseToken\n\n        when (notification.subscriptionNotification.notificationType) {\n            NotificationType.SUBSCRIPTION_PRICE_CHANGE_UPDATED -&gt; {\n                \/\/ Query the current state of the price change\n                val subscription = playDeveloperApi\n                    .purchases()\n                    .subscriptionsv2()\n                    .get(packageName, purchaseToken)\n                    .execute()\n\n                val priceChangeState = subscription.lineItems[0]\n                    .autoRenewingPlan\n                    ?.priceChangeDetails\n\n                if (priceChangeState != null) {\n                    subscriptionRepository.updatePriceChangeStatus(\n                        purchaseToken = purchaseToken,\n                        state = priceChangeState.priceChangeState,\n                        newPriceMicros = priceChangeState.newPrice?.priceMicros,\n                        expectedNewPriceChargeTime = priceChangeState.expectedNewPriceChargeTime\n                    )\n\n                    \/\/ Notify app layer to update UI if needed\n                    notifyPriceChangeUpdated(purchaseToken, priceChangeState)\n                }\n            }\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;recovering-from-accidental-price-changes&quot;&gt;&lt;strong&gt;Recovering from accidental price changes&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Mistakes happen. If you accidentally change a price or initiate a migration you did not intend, the recovery process depends on the type of change and how much time has passed.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;reverting-opt-in-increases&quot;&gt;&lt;strong&gt;Reverting opt-in increases&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;For opt-in price increases, the timing of your revert matters significantly. If you revert within seven days (the freeze period), users will not have received any notifications from Google Play, so the change is essentially invisible to them. After seven days, reverting will cancel the price change for users who have not yet been charged at the new price, but some users may have already received notifications, which could cause confusion.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;reverting-opt-out-increases&quot;&gt;&lt;strong&gt;Reverting opt-out increases&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;For opt-out price increases, reverting to the original price cancels the increase for users who have not yet been charged. Keep in mind the authorization timing. Users whose payment was already authorized (up to five days before renewal in some regions) may still be charged.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;reverting-price-decreases&quot;&gt;&lt;strong&gt;Reverting price decreases&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;If you need to cancel a price decrease and return to the original higher price, start by reverting to the original price in the Play Console and choosing whether the increase should be opt-in or opt-out. The timing relative to user renewals determines the outcome: if the time between revert and user renewal is greater than the notification window (30 to 60 days depending on country), users will pay the original price at their next renewal. If the time is less than the notification window, users will be charged the lower price once, then go through the standard price increase notification flow.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;installment-subscriptions-and-price-changes&quot;&gt;&lt;strong&gt;Installment subscriptions and price changes&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;If your subscription uses installment plans (where users commit to a certain number of payments), price changes behave differently.&lt;/p&gt;



&lt;p&gt;For installment subscriptions, price changes only apply at the end of the active commitment period. You cannot change the price for users in the middle of an installment, and the new price takes effect at the first renewal after the commitment ends. For example, if a user is on a 12 month installment plan followed by monthly auto renewal, any price change you make will only take effect after their 12 month commitment completes and they move to the monthly renewal phase.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;testing-price-changes&quot;&gt;&lt;strong&gt;Testing price changes&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Before rolling out price changes to your production subscriber base, you should thoroughly test the flows using Google Play’s testing tools.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;using-license-testers&quot;&gt;&lt;strong&gt;Using license testers&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;License testers can receive price change notifications without affecting real subscribers. Configure license testers in the Play Console and use them to verify notification delivery and timing, in app messaging display, acceptance and decline flows, and state transitions in your backend.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;play-billing-lab&quot;&gt;&lt;strong&gt;Play Billing Lab&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Google provides the &lt;a href=&quot;https://play.google.com/store/apps/details?id=com.google.android.apps.play.billingtestcompanion&quot;&gt;Play Billing Lab app&lt;/a&gt; for testing billing scenarios. Use it to simulate price change scenarios and verify your app handles each state correctly.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;audit-trail&quot;&gt;&lt;strong&gt;Audit trail&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The Play Console maintains a change log of all price modifications. Use this to review when prices were updated, who initiated the changes, and which regions were affected. This audit trail is invaluable for investigating issues or reviewing the history of accidental changes.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;how-revenuecat-simplifies-price-change-management&quot;&gt;&lt;strong&gt;How RevenueCat simplifies price change management&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Managing price changes across a large subscriber base involves significant complexity. This includes tracking migration status for each user, processing RTDN notifications, displaying appropriate in-app messaging, and handling edge cases. RevenueCat abstracts away much of this complexity while providing additional tools for managing price changes effectively.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;automatic-state-tracking&quot;&gt;&lt;strong&gt;Automatic state tracking&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;RevenueCat processes Google Play’s RTDN notifications on your behalf, maintaining up to date subscription state including pending price changes. Instead of building infrastructure to receive and process notifications, you simply query RevenueCat for the current customer state:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1YQcLX wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;fun checkForPriceChanges() {\n    Purchases.sharedInstance.getCustomerInfoWith { customerInfo -&gt;\n        val entitlement = customerInfo.entitlements[\&amp;quot;premium\&amp;quot;]\n\n        \/\/ RevenueCat&apos;s CustomerInfo reflects current subscription state\n        \/\/ including any pending price changes processed from RTDN\n\n        if (entitlement?.isActive == true) {\n            \/\/ Check for billing issues that might indicate price change problems\n            entitlement.billingIssueDetectedAt?.let { issueDate -&gt;\n                showBillingRecoveryUI(customerInfo.managementURL)\n            }\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;management-url-for-user-actions&quot;&gt;&lt;strong&gt;Management URL for user actions&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;RevenueCat’s CustomerInfo includes a &lt;a href=&quot;https://www.revenuecat.com/docs/subscription-guidance/managing-subscriptions#using-the-managementurl-to-help-customers-cancel-a-subscription&quot;&gt;managementURL&lt;/a&gt; property that provides a direct link to Google Play’s subscription management screen. This is where users can accept or decline price changes:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1dQwsq wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;fun guideToPriceChangeAcceptance(customerInfo: CustomerInfo) {\n    val managementUrl = customerInfo.managementURL\n\n    showDialog(\n        title = \&amp;quot;Action Required\&amp;quot;,\n        message = \&amp;quot;Please review the upcoming changes to your subscription.\&amp;quot;,\n        positiveButton = \&amp;quot;Open Settings\&amp;quot; to {\n            openUrl(managementUrl)\n        }\n    )\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;cross-platform-consistency&quot;&gt;&lt;strong&gt;Cross-platform consistency&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;For apps that span multiple platforms, RevenueCat ensures consistent subscription state across Android, iOS, and other platforms. If a user accepts a price change on one device, the updated status is reflected across all their devices without additional implementation.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;webhooks-for-server-side-handling&quot;&gt;&lt;strong&gt;Webhooks for server side handling&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;RevenueCat provides webhooks that notify your server of subscription events in a normalized format. This is simpler than processing raw RTDN notifications and includes events related to price changes:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1fSgg6 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/\/ Your webhook handler\nfun handleRevenueCatWebhook(event: WebhookEvent) {\n    when (event.type) {\n        \&amp;quot;RENEWAL\&amp;quot; -&gt; {\n            \/\/ Renewal completed - check if price changed\n            val transaction = event.transaction\n            if (transaction.priceInPurchasedCurrency != previousPrice) {\n                \/\/ Price change took effect\n                updateUserPricing(event.appUserId, transaction.priceInPurchasedCurrency)\n            }\n        }\n        \&amp;quot;CANCELLATION\&amp;quot; -&gt; {\n            \/\/ User canceled, might be due to price change rejection\n            val reason = event.cancellationReason\n            if (reason == \&amp;quot;PRICE_INCREASE\&amp;quot;) {\n                \/\/ Track churn related to price changes\n                analytics.trackPriceChangeChurn(event.appUserId)\n            }\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;analytics-for-price-change-impact&quot;&gt;&lt;strong&gt;Analytics for price change impact&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/dashboard-and-metrics/charts&quot;&gt;RevenueCat’s Chart&lt;/a&gt; provides analytics that help you understand the impact of price changes, including churn rates correlated with price change timing, conversion rates for subscribers who received price increase notifications, and revenue impact analysis before and after price changes. These insights help you make informed decisions about pricing strategy and identify the optimal timing and communication approach for future price changes.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;best-practices-with-revenuecat&quot;&gt;&lt;strong&gt;Best practices with RevenueCat&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;When using RevenueCat for price change management, focus on proactive communication by using customer attributes to identify users with pending price changes and send targeted communications during the freeze period. Monitor key metrics such as the conversion rate from price increase notification to acceptance and the churn rate among affected users. Always provide users with an easy path to the Play Store subscription settings via the management URL. Finally, leverage RevenueCat’s normalized data to handle edge cases gracefully, such as users who change plans during a pending price increase.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;best-practices-for-subscription-price-changes&quot;&gt;&lt;strong&gt;Best practices for subscription price changes&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Based on the mechanics we have covered, here are key practices to implement for successful price changes:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;plan-your-communication-strategy&quot;&gt;&lt;strong&gt;Plan your communication strategy&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Before initiating a price change, plan how you will communicate with affected users. Prepare messaging that explains the value users receive, decide whether to use the freeze period for custom outreach, and consider offering alternatives such as annual plans or grandfathered pricing for users sensitive to price changes.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;use-regional-rollouts&quot;&gt;&lt;strong&gt;Use regional rollouts&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;If you are increasing prices globally, consider rolling out changes region by region. Test in smaller markets first to gauge response, adjust messaging based on early feedback, and allow time to address issues before they affect your largest markets.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;monitor-acceptance-rates&quot;&gt;&lt;strong&gt;Monitor acceptance rates&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Track how many users accept opt-in price increases versus letting their subscriptions cancel:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-5wEpm wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;class PriceChangeAnalytics(\n    private val analytics: AnalyticsService\n) {\n    fun trackPriceChangeOutcome(\n        userId: String,\n        originalPrice: Long,\n        newPrice: Long,\n        outcome: PriceChangeOutcome\n    ) {\n        analytics.track(\n            event = \&amp;quot;price_change_outcome\&amp;quot;,\n            properties = mapOf(\n                \&amp;quot;user_id\&amp;quot; to userId,\n                \&amp;quot;original_price_micros\&amp;quot; to originalPrice,\n                \&amp;quot;new_price_micros\&amp;quot; to newPrice,\n                \&amp;quot;increase_percentage\&amp;quot; to calculatePercentage(originalPrice, newPrice),\n                \&amp;quot;outcome\&amp;quot; to outcome.name\n            )\n        )\n    }\n}\n\nenum class PriceChangeOutcome {\n    ACCEPTED,\n    DECLINED,\n    SUBSCRIPTION_CANCELED,\n    NO_RESPONSE_BEFORE_DEADLINE\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;If acceptance rates are lower than expected, you may need to adjust your communication strategy or reconsider the price increase amount.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;provide-alternatives&quot;&gt;&lt;strong&gt;Provide alternatives&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Users who are unwilling to pay the higher price may be willing to continue at a different tier. Consider offering a downgrade path to a plan with lower pricing, providing an annual option at a discounted effective monthly rate, or creating a ‘lite’ tier that retains users who would otherwise churn.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;handle-the-transition-gracefully-in-your-app&quot;&gt;&lt;strong&gt;Handle the transition gracefully in your app&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Ensure your app gracefully handles all states during a price change. Users with pending price increases should see clear messaging, users who decline should not lose access immediately, and the transition between prices should be seamless for users who accept.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;conclusion&quot;&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Subscription price changes on Google Play involve a carefully orchestrated process designed to protect users while giving developers flexibility. The key concepts to understand are the legacy price cohort that shields existing subscribers from automatic price changes, the distinction between opt-in and opt-out price increases and their respective timelines, the notification requirements that apply across device types, and the regional variations that affect timing and eligibility.&lt;/p&gt;



&lt;p&gt;For price decreases, the process is straightforward. Users automatically receive the lower price at their next renewal. For price increases, the default opt-in flow requires explicit user acceptance, with a seven day freeze period followed by 30 days of Google Play notifications before the effective date.&lt;/p&gt;



&lt;p&gt;Implementing price changes directly requires processing RTDN notifications, maintaining subscription state on your backend, and building UI to guide users through the acceptance process. RevenueCat simplifies this by handling notification processing automatically and providing normalized data, analytics, and the management URL for user actions, so you can focus on your business and more important work.&lt;/p&gt;



&lt;p&gt;Whatever approach you take, successful price changes require clear communication with users about the value they receive. The freeze period is your opportunity to control the narrative before automated notifications begin. Use it wisely, and you can maintain user trust while adjusting your pricing to reflect the value your app delivers.For complete documentation on subscription price changes, refer to the &lt;a href=&quot;https://developer.android.com/google/play/billing/price-changes&quot;&gt;official Android Developer documentation&lt;/a&gt; and &lt;a href=&quot;https://www.revenuecat.com/docs/subscription-guidance/managing-subscriptions&quot;&gt;RevenueCat’s subscription management guide&lt;/a&gt;.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[How subscription apps can use hybrid monetization to capture more revenue]]></title><description><![CDATA[How combining revenue models serves different users’ willingness to pay]]></description><link>https://www.revenuecat.com/blog/growth/hybrid-monetization-techniques/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/hybrid-monetization-techniques/</guid><pubDate>Mon, 19 Jan 2026 12:10:22 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Blog_13_Hybrid-monetization-basics.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Hybrid monetization means combining subscriptions and additional ways to earn money from users — think in-app purchase (IAP), consumables, ads, or partnerships.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;But before we go much further, I want to emphasize something: the goal &lt;em&gt;isn’t &lt;/em&gt;to replace subscriptions. It’s about complementing them. As different users discover, use, and leave your app, hybrid monetization captures as many of them as possible.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Why hybrid monetization? The limits of subscription-only models&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;I’ve been advocating for hybrid monetization for a long time because acquisition is essentially a business model &lt;em&gt;competition&lt;/em&gt;: more ARPU = a better position in the paid auctions, faster payback, and more margin to invest in retention, onboarding etc. So while subscriptions are great, they come with a fundamental flaw: a high floor, low ceiling nature (more on this in a moment).&lt;/p&gt;



&lt;p&gt;Subscriptions are binary: pay, or don’t.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;But real demand is not binary — it’s distributed across &lt;strong&gt;willingness to pay&lt;/strong&gt;.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;600&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Day-35-download-to-paid-1024x600.png&quot; alt=&quot;&quot; class=&quot;wp-image-50765&quot; style=&quot;width:800px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Day-35-download-to-paid-1024x600.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Day-35-download-to-paid-300x176.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Day-35-download-to-paid-768x450.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Day-35-download-to-paid-1536x900.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Day-35-download-to-paid-2048x1200.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Day-35-download-to-paid-50x29.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Day-35-download-to-paid-68x40.png 68w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Day-35-download-to-paid-696x408.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Day-35-download-to-paid-560x328.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Day-35-download-to-paid-505x296.png 505w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Day-35-download-to-paid-806x472.png 806w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Day-35-download-to-paid-80x47.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Day-35-download-to-paid-48x28.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Based on the graph above (from the &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps-2025/&quot;&gt;State of Subscription Apps 2025&lt;/a&gt;), it’s expected that 90% of users won’t convert, and for a number of verticals, regions, and non-iOS platforms, it gets even worse. Last year, I saw an app attract over a million users in one country, only to get less than 1,000 paying subscribers!&amp;nbsp;&lt;/p&gt;



&lt;p&gt;The problem is that a single recurring price assumes that most users have roughly the same willingness to pay. But in reality, some users are happy to pay a premium, others get occasional value but can’t justify a recurring commitment, many will never subscribe at all.&lt;/p&gt;



&lt;p&gt;This creates two common blockers:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-high-ceiling-problem&quot;&gt;&lt;strong&gt;The high-ceiling problem&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;A single offer presents too much friction for low-intent users. You can try to discount it or shorten the subscription length, but some users (such as Android users in developing countries) still won’t engage.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Many will &lt;em&gt;never &lt;/em&gt;subscribe. They still generate value (attention, data, virality), and some may be willing to be &lt;em&gt;something&lt;/em&gt; — if offered differently (enter in-app purchases, for example) or at a lower price point.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Problem: &lt;strong&gt;you’re leaving revenue on the table from low-intent users.&lt;/strong&gt; Users who value the app, but won’t cross the psychological or financial barrier of a subscription.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-low-floor-problem&quot;&gt;&lt;strong&gt;The low floor problem&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Maybe even worse than a high ceiling… The majority of subscription models have no ‘whales’ (aka, mega spenders). Gaming apps, who pioneered hybrid monetization (typically IAP + ads), can see a handful of users accounting for a large share of revenue, even if other users contribute less. For example, I once saw numbers from a large ‘match three’ game showing that &amp;lt;2% of its 2% payers (i.e. 0.04%) actually generated more than half of revenue. Subscription-only apps lose this possibility.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Problem: &lt;strong&gt;you under-monetize high-intent users&lt;/strong&gt;, as your subscription price can’t move higher without hurting conversion of other users.&lt;/p&gt;



&lt;p&gt;At its core, hybrid monetization is about &lt;strong&gt;matching price granularity to demand granularity&lt;/strong&gt;.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-adapting-to-the-demand-curve&quot;&gt;&lt;strong&gt;Adapting to the demand curve&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Most apps serve users with very different levels of intent, frequency, and urgency. A single subscription price flattens those differences.&lt;/p&gt;



&lt;p&gt;Visually, you can think of your audience as a demand curve:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;On the left: users willing to pay more for power, speed, or convenience&lt;/li&gt;



&lt;li&gt;On the right: users who won’t pay anything&lt;/li&gt;



&lt;li&gt;In the middle: users who want value occasionally, but resist subscriptions=&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Hybrid monetization places the correct monetization lever at the ideal point on that curve, for &lt;em&gt;every user&lt;/em&gt;, and avoids forcing everyone into the same choice.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;The demand curve of app monetization is extreme, and could be represented this way:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;580&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-61-1024x580.png&quot; alt=&quot;&quot; class=&quot;wp-image-50767&quot; style=&quot;width:800px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-61-1024x580.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-61-300x170.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-61-768x435.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-61-1536x870.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-61-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-61-71x40.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-61-696x394.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-61-560x317.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-61-523x296.png 523w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-61-834x472.png 834w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-61-80x45.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-61-48x27.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-61.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;By choosing a single point on the line, binary subscriptions models are leaving a lot of money on the table:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;576&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-62-1024x576.png&quot; alt=&quot;&quot; class=&quot;wp-image-50769&quot; style=&quot;width:800px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-62-1024x576.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-62-300x169.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-62-768x432.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-62-1536x864.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-62-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-62-71x40.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-62-696x392.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-62-560x315.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-62-526x296.png 526w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-62-840x472.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-62-80x45.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-62-48x27.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-62.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;There are a variety of options to improve the offer and increase ARPU by adapting to your demand curve. Here are some of those levers:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;779&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image4-1024x779.png&quot; alt=&quot;&quot; class=&quot;wp-image-50771&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image4-1024x779.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image4-300x228.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image4-768x584.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image4-50x38.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image4-53x40.png 53w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image4-610x464.png 610w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image4-696x529.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image4-560x426.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image4-389x296.png 389w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image4-620x472.png 620w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image4-80x61.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image4-48x37.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image4.png 1233w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;techniques-for-hybrid-monetization-with-app-examples&quot;&gt;&lt;strong&gt;Techniques for hybrid monetization (with app examples)&amp;nbsp;&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;All the instances of hybrid monetization that I’ve worked on and observed &lt;strong&gt;keep subscriptions as the core center of gravity&lt;/strong&gt;, then add layers on top. Let’s go through some examples.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;1-pricing-and-packaging&quot;&gt;&lt;strong&gt;1. Pricing and packaging&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;I won’t go into this in much depth, but the most obvious and first step towards more sophisticated monetization is adjusting pricing and packaging. This is already happening a lot, thanks to increasingly-easier ways to &lt;a href=&quot;https://www.revenuecat.com/feature/paywalls/&quot;&gt;A/B test paywalls.&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;In this step, developers can (and should) experiment with different pricepoints, combinations of plans (e.g. how many plans do you offer? Are they weekly/monthly/yearly?), segmentation (which I predict will &lt;em&gt;finally&lt;/em&gt; become a thing thanks to AI after years of lag), price localizations etc.&lt;/p&gt;



&lt;p&gt;A fairly extreme example is the discount flow from Headway, which moves offers all the way from €89.99 to €21.99 in my personal case:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;484&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-64-1024x484.png&quot; alt=&quot;&quot; class=&quot;wp-image-50775&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-64-1024x484.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-64-300x142.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-64-768x363.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-64-1536x727.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-64-50x24.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-64-85x40.png 85w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-64-696x329.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-64-560x265.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-64-840x397.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-64-80x38.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-64-48x23.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-64.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;2-subscriptions-tiers&quot;&gt;&lt;strong&gt;2. Subscriptions tiers&amp;nbsp;&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;While offering multiple tiers of subscription isn’t strictly ‘hybrid’ (as it’s still only subscriptions), it moves towards hybrid monetization by adjusting to the demand curve.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Software-as-a-service (SaaS) businesses have done this successfully for some time by offering tiered-features to different user profiles. One example is Photoroom, which offers Photoroom Pro, Max and Ultra to different segments of users , based on usage patterns.&lt;/p&gt;



&lt;figure class=&quot;wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-5 is-layout-flex wp-block-gallery-is-layout-flex&quot;&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;534&quot; height=&quot;1024&quot; data-id=&quot;50779&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-66-534x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-50779&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-66-534x1024.png 534w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-66-157x300.png 157w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-66-768x1472.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-66-802x1536.png 802w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-66-26x50.png 26w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-66-21x40.png 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-66-242x464.png 242w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-66-696x1334.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-66-292x560.png 292w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-66-154x296.png 154w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-66-246x472.png 246w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-66-42x80.png 42w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-66-25x48.png 25w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-66.png 835w&quot; sizes=&quot;auto, (max-width: 534px) 100vw, 534px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;534&quot; height=&quot;1024&quot; data-id=&quot;50777&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-65-534x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-50777&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-65-534x1024.png 534w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-65-156x300.png 156w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-65-768x1473.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-65-801x1536.png 801w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-65-26x50.png 26w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-65-21x40.png 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-65-242x464.png 242w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-65-696x1335.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-65-292x560.png 292w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-65-154x296.png 154w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-65-246x472.png 246w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-65-42x80.png 42w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-65-25x48.png 25w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-65.png 834w&quot; sizes=&quot;auto, (max-width: 534px) 100vw, 534px&quot;&gt;&lt;/figure&gt;
&lt;/figure&gt;



&lt;p&gt;Subscription behemoths Noom and Tinder both user tiers as well:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;451&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-63-1024x451.png&quot; alt=&quot;&quot; class=&quot;wp-image-50773&quot; style=&quot;width:700px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-63-1024x451.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-63-300x132.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-63-768x338.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-63-1536x677.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-63-50x22.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-63-91x40.png 91w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-63-696x307.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-63-560x247.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-63-840x370.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-63-80x35.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-63-48x21.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-63.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;While not strictly a subscription tier per se, many developers with a &lt;a href=&quot;https://www.revenuecat.com/blog/growth/app-portfolio-vs-single-app/&quot;&gt;portfolio of different apps&lt;/a&gt; choose to &lt;strong&gt;bundle&lt;/strong&gt; as a way to upsell a higher pricepoint. Examples include Monkey Taps (in-app and in the app stores) or Reflectly (on web).&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;569&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-67-1024x569.png&quot; alt=&quot;&quot; class=&quot;wp-image-50781&quot; style=&quot;width:700px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-67-1024x569.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-67-300x167.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-67-768x427.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-67-1536x853.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-67-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-67-72x40.png 72w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-67-696x387.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-67-560x311.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-67-533x296.png 533w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-67-840x467.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-67-80x44.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-67-48x27.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-67.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;3-subscriptions-ads&quot;&gt;&lt;strong&gt;3. Subscriptions + ads&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Ads are maybe the most obvious ways to monetize the 90% of users who show zero willingness to pay for anything (regardless of pricepoint). I remember trying a 99% off discount only to have little incremental uplift on conversion rate. If you have users like this, supplementing with ads can be a good technique.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;A well-known example of this use case is subscription role model &lt;a href=&quot;https://subclub.com/episode/how-to-time-reactivation-campaigns-for-maximum-impact-jackson-shuttleworth-duolingo&quot;&gt;Duolingo&lt;/a&gt;, who combine their &lt;a href=&quot;https://www.youtube.com/watch?v=fDJ5qzjSZXI&quot;&gt;core freemium offer with ads&lt;/a&gt;, plus premium plans to remove ads, and IAP. Some case studies &lt;a href=&quot;https://growthgems.substack.com/i/159941562/the-opportunity-is-too-big-to-ignore&quot;&gt;suggest&lt;/a&gt; developers can expect revenue uplift of 10-30% with subs + ads, depending on their user base and execution.&amp;nbsp;&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-Z1NwCYM wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;RevenueCat now tracks your ad revenue alongside subscriptions&quot; text=&quot;&lt;p&gt;Apps using ad mediation platforms like Google AdMob or AppLovin can send ad events directly to RevenueCat via the SDK — giving hybrid monetization apps a complete, &lt;a href=&amp;quot;https://www.revenuecat.com/feature/charts/&amp;quot;&gt;unified view of your business in one dashboard&lt;/a&gt;.&lt;!-- notionvc: 2adc82bf-316e-428d-be77-f0369e459e8a --&gt;&lt;/p&gt;&quot; icon=&quot;bulb&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;p&gt;However, it’s worth bearing in mind that revenue here is limited for hard paywall apps. Spotify, for example, makes less than 5% of its revenue from its majority users: free users who put up with ads. In another case I worked on it was as low as 1%.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot;&gt;&lt;strong&gt;Considerations when implementing subs + ads&lt;/strong&gt;&lt;/h4&gt;



&lt;p&gt;Privacy laws, apps with ad SDKs, effect on churn and many more things should be considered when including ads in your app. Some good resources to look at are:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/revenue-strategies-low-intent-users/&quot;&gt;7 smart ways to monetize low-intent users&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/how-to-turn-freemium-users-into-loyal-subscribers/&quot;&gt;How to turn freemium users into loyal subscribers&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/ad-monetization-subscription-apps/&quot;&gt;Boosting ARPU with ads: How to monetize free users without degrading UX&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://growthgems.substack.com/p/should-you-also-monetize-your-subscription?open=false#%C2%A7the-opportunity-is-too-big-to-ignore&quot;&gt;Sylvain Gauchet’s pros and cons of ads in subscription apps&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;h4 class=&quot;wp-block-heading&quot;&gt;&lt;strong&gt;Techniques for subscription + ads&lt;/strong&gt;&lt;/h4&gt;



&lt;p&gt;Some apps think of ads not as a way to add revenue, but a way to create friction and promote the ad-free offering: a subscription. For instance, Impulse &lt;strong&gt;prompts users to remove ads in different strategic places&lt;/strong&gt;:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;495&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image8-1024x495.png&quot; alt=&quot;&quot; class=&quot;wp-image-50785&quot; style=&quot;width:700px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image8-1024x495.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image8-300x145.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image8-768x371.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image8-1536x742.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image8-50x24.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image8-83x40.png 83w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image8-696x336.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image8-560x270.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image8-840x406.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image8-80x39.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image8-48x23.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image8.png 1787w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;In this flow (from &lt;a href=&quot;https://growthgems.substack.com/p/should-you-also-monetize-your-subscription&quot;&gt;GrowthGems&lt;/a&gt;), you can see how closing the ad triggers a subscription paywall with weekly and lifetime plans. When closed, there’s then a non-renewable IAP to remove ads for $4.99!&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;600&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-68-1024x600.png&quot; alt=&quot;&quot; class=&quot;wp-image-50783&quot; style=&quot;width:700px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-68-1024x600.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-68-300x176.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-68-768x450.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-68-1536x900.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-68-50x29.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-68-68x40.png 68w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-68-696x408.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-68-560x328.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-68-505x296.png 505w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-68-805x472.png 805w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-68-80x47.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-68-48x28.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-68.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Gaming experts Matej Lancaric and Felix Braberg have a&lt;a href=&quot;https://www.youtube.com/watch?v=yfI-rZNCi0M&quot;&gt;good video analyzing Impulse’s hybrid model&lt;/a&gt;. You can also &lt;strong&gt;use ad placements to promote your own subscription&lt;/strong&gt;: &lt;a href=&quot;https://www.youtube.com/watch?v=QBaDsqhFnz8&quot;&gt;this video&lt;/a&gt; shows Duolingo’s ad break — two ads show, one for NYT Games, then one for Duolingo MAX. It’s a bit meta, but it can work!&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;In-house ad for Duolingo Max&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/QBaDsqhFnz8?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;Finally, a simple banner can go a long way, like in this example from park4night (which interestingly drives to an off-store, even outside the US).&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;502&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-78-502x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-50805&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-78-502x1024.png 502w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-78-147x300.png 147w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-78-768x1567.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-78-753x1536.png 753w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-78-25x50.png 25w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-78-20x40.png 20w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-78-227x464.png 227w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-78-696x1420.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-78-274x560.png 274w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-78-145x296.png 145w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-78-231x472.png 231w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-78-39x80.png 39w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-78-24x48.png 24w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-78.png 784w&quot; sizes=&quot;auto, (max-width: 502px) 100vw, 502px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;4-subscriptions-partnerships&quot;&gt;&lt;strong&gt;4. Subscriptions + partnerships&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;By ‘partnership’, I mean an alternative to the common ads model sold via SDK with partners such as Applovin, Unity or Admob. In specific verticals, partnering up with a relevant brand can yield significant impact — and potentially revenue — depending on the vertical, as they may add value, including for premium customers.&lt;br&gt;&lt;br&gt;See for instance &lt;a href=&quot;https://business.strava.com/resources/ultimate-guide-sponsored-challenges&quot;&gt;Strava’s Sponsored Challenges&lt;/a&gt;:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;406&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-73-1024x406.png&quot; alt=&quot;&quot; class=&quot;wp-image-50795&quot; style=&quot;width:700px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-73-1024x406.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-73-300x119.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-73-768x305.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-73-50x20.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-73-101x40.png 101w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-73-696x276.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-73-560x222.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-73-840x333.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-73-80x32.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-73-48x19.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-73.png 1180w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;br&gt;Such partnerships can be &lt;strong&gt;implemented at very different trigger points of the journey,&lt;/strong&gt; as illustrated below with Prematch:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;447&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-77-1024x447.png&quot; alt=&quot;&quot; class=&quot;wp-image-50803&quot; style=&quot;width:700px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-77-1024x447.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-77-300x131.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-77-768x336.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-77-1536x671.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-77-50x22.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-77-92x40.png 92w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-77-696x304.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-77-560x245.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-77-840x367.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-77-80x35.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-77-48x21.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-77.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;5-subscriptions-ecommerceaffiliates&quot;&gt;&lt;strong&gt;5. Subscriptions + ecommerce/affiliates&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;As mentioned earlier, one of the limits of the subscription-only model is that it doesn’t offer your bigger power users and ambassadors any opportunity to engage further with the brand. So one way to supplement subscriptions is by adding ecommerce or affiliate strategies.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;For example, a few mega fans might be willing to &lt;strong&gt;buy brand swag or physical goods&lt;/strong&gt;, like Lingokids:&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;375&quot; height=&quot;277&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-70.png&quot; alt=&quot;&quot; class=&quot;wp-image-50789&quot; style=&quot;width:400px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-70.png 375w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-70-300x222.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-70-50x37.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-70-54x40.png 54w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-70-80x59.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-70-48x35.png 48w&quot; sizes=&quot;auto, (max-width: 375px) 100vw, 375px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Sometimes, the ecommerce opportunity lives within the product, such as the anglers’ social network app, Fishbrain, having a &lt;strong&gt;marketplace&lt;/strong&gt;:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;226&quot; height=&quot;490&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image29.png&quot; alt=&quot;&quot; class=&quot;wp-image-50809&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image29.png 226w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image29-138x300.png 138w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image29-23x50.png 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image29-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image29-214x464.png 214w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image29-137x296.png 137w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image29-218x472.png 218w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image29-37x80.png 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image29-22x48.png 22w&quot; sizes=&quot;auto, (max-width: 226px) 100vw, 226px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;As a more indirect tactic, you can &lt;strong&gt;partner with other businesses to offer deals or discounts&lt;/strong&gt; to your users, like Revolut does:&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;226&quot; height=&quot;491&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-74.png&quot; alt=&quot;&quot; class=&quot;wp-image-50797&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-74.png 226w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-74-138x300.png 138w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-74-23x50.png 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-74-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-74-214x464.png 214w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-74-136x296.png 136w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-74-217x472.png 217w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-74-37x80.png 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-74-22x48.png 22w&quot; sizes=&quot;auto, (max-width: 226px) 100vw, 226px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;6-subscriptions-consumablesone-off-in-app-purchases-iaps&quot;&gt;&lt;strong&gt;6. Subscriptions + consumables/one-off in-app purchases (IAPs)&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Finally, here is the biggest potential uplift (for most apps): offering consumables and one-off IAPs alongside your subscriptions. These have great rewards for app businesses, yet are still vastly underutilized.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps-2025/&quot;&gt;RevenueCat’s State of Subscription Apps 2025&lt;/a&gt; report shows limited use of consumables — except in gaming (~40%) — with only 5–15% of apps using these monetization models.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps-2025/&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;641&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-69-1024x641.png&quot; alt=&quot;&quot; class=&quot;wp-image-50787&quot; style=&quot;width:700px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-69-1024x641.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-69-300x188.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-69-768x481.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-69-50x31.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-69-64x40.png 64w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-69-696x436.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-69-560x351.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-69-473x296.png 473w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-69-754x472.png 754w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-69-80x50.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-69-48x30.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-69.png 1308w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/a&gt;&lt;/figure&gt;



&lt;p&gt;While few apps are taking this route, the few that do monetize much better: a &lt;a href=&quot;https://www.revenuecat.com/blog/growth/key-insights-from-app-growth-annual-2024/&quot;&gt;recent stat&lt;/a&gt; showed that hybrid buyers make up only 7% of buyers, but generate 25% of total revenue.&lt;/p&gt;



&lt;p&gt;Non-renewable/consumable items fit many use cases that subscriptions don’t cover, either substituting for a subscription (which wouldn’t be purchased) or slotting on top as an additional spend. Depending on the app, those consumables may be very different things — one example is ‘boosts’ which are pretty common in dating apps or marketplaces, such as &lt;a href=&quot;https://www.revenuecat.com/blog/growth/ravi-mehta-tinder-sub-club-podcast-2025/&quot;&gt;Tinder&lt;/a&gt; or Wallapop:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;855&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-76-1024x855.png&quot; alt=&quot;&quot; class=&quot;wp-image-50801&quot; style=&quot;width:500px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-76-1024x855.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-76-300x250.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-76-768x641.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-76-50x42.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-76-48x40.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-76-556x464.png 556w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-76-696x581.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-76-560x467.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-76-355x296.png 355w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-76-566x472.png 566w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-76-80x67.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-76.png 1076w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;In-app purchases can also be used to enable price-sensitive users to &lt;strong&gt;unlock premium features individually, or for a limited time&lt;/strong&gt;. For instance, one learning app I worked with added a one-time IAP which granted access to all content for a couple of days (a ‘weekend pass’). We also added IAPs to gain access to very specific lessons without having to unlock the rest of that content tier.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;309&quot; height=&quot;732&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-72.png&quot; alt=&quot;&quot; class=&quot;wp-image-50793&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-72.png 309w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-72-127x300.png 127w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-72-21x50.png 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-72-17x40.png 17w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-72-196x464.png 196w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-72-236x560.png 236w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-72-125x296.png 125w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-72-199x472.png 199w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-72-34x80.png 34w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-72-20x48.png 20w&quot; sizes=&quot;auto, (max-width: 309px) 100vw, 309px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Consumables can also be &lt;strong&gt;upsells&lt;/strong&gt;, which have proven particularly effective in the health and fitness space; for example, guides to train specific body parts, certain individual coaches, dedicated workout or meal programs… These are sometimes even sold as a direct upsell right at onboarding, though this is a tactic I’ve seen work better on web (once the payment is recorded) than in-app.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;929&quot; height=&quot;724&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-75.png&quot; alt=&quot;&quot; class=&quot;wp-image-50799&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-75.png 929w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-75-300x234.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-75-768x599.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-75-50x39.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-75-51x40.png 51w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-75-595x464.png 595w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-75-696x542.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-75-560x436.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-75-380x296.png 380w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-75-606x472.png 606w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-75-80x62.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-75-48x37.png 48w&quot; sizes=&quot;auto, (max-width: 929px) 100vw, 929px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The possibilities for IAP are endless: Nebula sells one-off tarot readings and 1:1 chats with psychics, Duolingo offers individual tests and certifications. Many apps offer tipping, stickers, customization, and more.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;588&quot; height=&quot;590&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-71.png&quot; alt=&quot;&quot; class=&quot;wp-image-50791&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-71.png 588w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-71-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-71-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-71-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-71-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-71-462x464.png 462w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-71-558x560.png 558w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-71-295x296.png 295w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-71-470x472.png 470w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-71-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-71-48x48.png 48w&quot; sizes=&quot;auto, (max-width: 588px) 100vw, 588px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;One caveat for consumables, and probably the elephant in the room here, is AI.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Because AI comes with significant costs, &lt;a href=&quot;https://www.revenuecat.com/blog/growth/ai-subscription-app-pricing/#h-why-do-ai-apps-cost-more-to-run&quot;&gt;the cost of use can vary massively between users&lt;/a&gt; who are charged the same. Maybe the first hybrid AI model I’ve seen was Lensa AI, which was selling 200 AI avatars for $9.99, but entering the subscription allowed you to get 50% off the credit price. (I thought it was interesting that they specify why it’s a paid feature.)&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;301&quot; height=&quot;739&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image7.png&quot; alt=&quot;&quot; class=&quot;wp-image-50807&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image7.png 301w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image7-122x300.png 122w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image7-20x48.png 20w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image7-16x40.png 16w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image7-189x464.png 189w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image7-228x560.png 228w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image7-121x296.png 121w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image7-192x472.png 192w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image7-33x80.png 33w&quot; sizes=&quot;auto, (max-width: 301px) 100vw, 301px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Alongside tiered subscriptions like ChatGPT, these single-payment purchases for extra use are becoming &lt;a href=&quot;https://www.revenuecat.com/blog/growth/ai-subscription-app-pricing/#h-why-do-ai-apps-cost-more-to-run&quot;&gt;more common among AI apps&lt;/a&gt;.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;7-pile-them-up-combine-hybrid-monetization-options&quot;&gt;&lt;strong&gt;7. Pile them up: combine hybrid monetization options&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Hybrid options are additive, not mutually exclusive, so why not stack them? The most advanced subscriptions apps don’t just pick up one way to upsell — they combine several.&lt;/p&gt;



&lt;p&gt;This diagram from &lt;a href=&quot;https://philgcarter.substack.com/p/the-subscription-value-loop&quot;&gt;Phil Carter&lt;/a&gt;, creator of the &lt;a href=&quot;https://www.youtube.com/@SubversivePodcast&quot;&gt;Subversive podcast&lt;/a&gt; and the famous &lt;a href=&quot;https://www.revenuecat.com/blog/growth/the-subscription-value-loop-a-framework-for-subscription-app-growth/&quot;&gt;Subscription Value Loop&lt;/a&gt;, shows how Tinder adapted to the demand curve. Ravi Mehta, Former Chief Product Officer at Tinder, &lt;a href=&quot;https://subclub.com/episode/how-tinder-captures-more-value-with-tiered-pricing-and-consumables-ravi-mehta&quot;&gt;spoke about their strategy in depth on the Sub Club podcast&lt;/a&gt; — I highly recommend giving it a listen for examples of hybrid monetization in action.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;a href=&quot;https://subclub.com/episode/how-tinder-captures-more-value-with-tiered-pricing-and-consumables-ravi-mehta&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;614&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-81-1024x614.png&quot; alt=&quot;&quot; class=&quot;wp-image-50815&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-81-1024x614.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-81-300x180.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-81-768x460.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-81-50x30.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-81-67x40.png 67w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-81-696x417.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-81-560x336.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-81-494x296.png 494w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-81-787x472.png 787w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-81-80x48.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-81-48x29.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-81.png 1176w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/a&gt;&lt;/figure&gt;


&lt;div class=&quot;lazyblock-dd0db17b8671-ZY6KMc wp-block-lazyblock-dd0db17b8671&quot;&gt;&lt;blogpostpodcastcta title=&quot;Listen to the Sub Club episode&quot; description=&quot; How Tinder Captures More Value With Tiered Pricing and Consumables — Ravi Mehta&quot; links=&quot;[{&amp;quot;link-title&amp;quot;:&amp;quot;YouTube&amp;quot;,&amp;quot;link-url&amp;quot;:&amp;quot;https:\/\/www.youtube.com\/watch?v=AWI3rofh0BA&amp;quot;,&amp;quot;link-image&amp;quot;:&amp;quot;youtube&amp;quot;},{&amp;quot;link-title&amp;quot;:&amp;quot;Spotify&amp;quot;,&amp;quot;link-url&amp;quot;:&amp;quot;https:\/\/open.spotify.com\/episode\/2aWtd0a16r42SSIlSrDV8p?si=b663818739c94b39&amp;quot;,&amp;quot;link-image&amp;quot;:&amp;quot;spotify&amp;quot;},{&amp;quot;link-title&amp;quot;:&amp;quot;Apple Podcasts&amp;quot;,&amp;quot;link-url&amp;quot;:&amp;quot;https:\/\/podcasts.apple.com\/us\/podcast\/how-tinder-captures-more-value-with-tiered-pricing\/id1538057974?i=1000738494460&amp;quot;,&amp;quot;link-image&amp;quot;:&amp;quot;apple-podcasts&amp;quot;}]&quot;&gt;
&lt;/blogpostpodcastcta&gt;&lt;/div&gt;


&lt;p&gt;Here are some ways you can combine multiple non-subscription revenue streams.&amp;nbsp;&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot;&gt;&lt;strong&gt;Offer everything!&lt;/strong&gt;&lt;/h4&gt;



&lt;p&gt;For instance, weightloss app Simple offer users an upsell to skip the trial period, then offer different subscription tiers, and then also offer one-off purchases for in-app guides. It’s a &lt;em&gt;lot.&amp;nbsp;&lt;/em&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;592&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-82-1024x592.png&quot; alt=&quot;&quot; class=&quot;wp-image-50817&quot; style=&quot;width:700px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-82-1024x592.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-82-300x173.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-82-768x444.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-82-1536x888.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-82-50x29.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-82-69x40.png 69w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-82-696x402.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-82-560x324.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-82-512x296.png 512w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-82-816x472.png 816w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-82-80x46.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-82-48x28.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-82.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Me app also has a similar pattern, with coaching, goodies, and upsells in addition to the core subscription:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;577&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-80-1024x577.png&quot; alt=&quot;&quot; class=&quot;wp-image-50813&quot; style=&quot;width:700px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-80-1024x577.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-80-300x169.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-80-768x433.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-80-1536x866.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-80-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-80-71x40.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-80-696x392.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-80-560x316.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-80-525x296.png 525w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-80-837x472.png 837w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-80-80x45.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-80-48x27.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-80.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h4 class=&quot;wp-block-heading&quot;&gt;&lt;strong&gt;Bundle physical and digital goods&lt;/strong&gt;&lt;/h4&gt;



&lt;p&gt;Another innovative example, albeit less common, is to bundle digital and physical goods. This feels suited to luxury brands or designers, but it could work for any app. Arya does this in its initial offering and later through store upsells:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;572&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-83-1024x572.png&quot; alt=&quot;&quot; class=&quot;wp-image-50819&quot; style=&quot;width:700px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-83-1024x572.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-83-300x167.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-83-768x429.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-83-1536x857.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-83-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-83-72x40.png 72w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-83-696x388.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-83-560x313.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-83-530x296.png 530w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-83-840x469.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-83-80x45.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-83-48x27.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-83.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;While the specifics of those examples differ, the logic is the same: it’s hard enough to convert users into paid subscribers, so if there’s an opportunity to monetize subscribers in extra ways, take it. Demolish that low floor and find your big spenders, even if they’re few and far between. If there’s an opportunity for a big ARPU increase, whether on the spot (e.g. onboarding) or later (e.g. merch), it’s worth pursuing.&amp;nbsp;&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot;&gt;&lt;strong&gt;Offer them even more&lt;/strong&gt;&lt;/h4&gt;



&lt;p&gt;More and more subscription businesses operate beyond pure B2C models, often with a mix of end consumer, ‘prosumer’, small businesses, and even larger businesses. This is particularly common in graphics, photo, and video tools. One example is Photoroom: on top of its several subscription tiers, Photoroom offers B2B plans for clients that go beyond heavy user requirements:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;721&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-79-1024x721.png&quot; alt=&quot;&quot; class=&quot;wp-image-50811&quot; style=&quot;width:700px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-79-1024x721.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-79-300x211.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-79-768x541.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-79-50x35.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-79-57x40.png 57w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-79-659x464.png 659w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-79-696x490.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-79-560x394.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-79-420x296.png 420w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-79-670x472.png 670w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-79-80x56.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-79-48x34.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-79.png 1382w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;caveats-and-considerations-before-implementing-hybrid-monetization&quot;&gt;&lt;strong&gt;Caveats and considerations before implementing hybrid monetization&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Hybrid monetization isn’t a free win, it takes planning and practice. And like anything in app monetization, there are risks. But the most common blockers are predictable:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;for-users-choice-overload-can-hinder-conversion&quot;&gt;&lt;strong&gt;For users, choice overload can hinder conversion&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Every new monetization path should earn its place, especially at decision points. Otherwise you risk too many options leading to no decisions. How and when the options are offered is critical. For example, Netflix has found when it shows more than seven titles per row, user engagement drops. &lt;a href=&quot;https://growth.design/psychology#hicks-law&quot;&gt;This is also a good blog&lt;/a&gt; detailing examples of Hick’s Law and other choice overload instances, featuring the likes of Duolingo, Zapier, Airbnb and Trello.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;956&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-84-1024x956.png&quot; alt=&quot;&quot; class=&quot;wp-image-50821&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-84-1024x956.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-84-300x280.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-84-768x717.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-84-1536x1434.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-84-50x47.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-84-43x40.png 43w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-84-497x464.png 497w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-84-696x650.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-84-560x523.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-84-317x296.png 317w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-84-506x472.png 506w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-84-80x75.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-84-48x45.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-84.png 2048w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;for-developers-complexity-creeps-up-quickly&quot;&gt;&lt;strong&gt;For developers, complexity creeps up quickly&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;More SKUs = more logic and more edge cases.&lt;br&gt;&lt;br&gt;This might be the biggest caveat: hybrid monetization is definitely not for everyone. Hybrid models fail more from organizational structure than product design: various teams will see their current KPIs affected, so new alignment needs to happen between monetization, UA, and product teams.&lt;/p&gt;



&lt;p&gt;Offering multiple options requires stronger product, data, and ops discipline, and can add up on data and tech debt quickly — especially if many rounds of experimentations are required to find what clicks with your audience from the get-go.&lt;/p&gt;



&lt;p&gt;For many earlier-stage or smaller teams, this is actually a very good reason to stick with a pure subscription model initially.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;hidden-signals-and-risk-of-cannibalization&quot;&gt;&lt;strong&gt;Hidden signals and risk of cannibalization&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Measuring the actual uplift of hybrid monetization might look straightforward, but it isn’t! Discounts can be detrimental. Poorly designed IAPs can undermine subscriptions. Aggressively-priced consumables can just be shifting revenue to earlier (which arguably, is still great for cash flow even under similar LTV), but hurt renewal revenue later and eventually decrease LTV. Ads could inflate short-term ARPU while depressing long term retention and late conversions.&lt;/p&gt;



&lt;p&gt;Even simple pricepoints changes can have multiple, long-lasting impact on renewals, retention, upsell potential.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;In short: be conscious of the analytics required before jumping in — hybrid monetization creates some of the most convincing false positives.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;country-and-culture-dependencies&quot;&gt;&lt;strong&gt;Country and culture dependencies&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;There’s a massive monetization gap in subscriptions between platforms (this is the reason the Google Play team was an &lt;a href=&quot;https://www.youtube.com/watch?v=BgQLwjWTpi8&quot;&gt;early advocate for mixed models&lt;/a&gt;). For example, low-amount IAPs are often more impactful on Android than iOS, due to different user profiles and intent.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Payment habits, ad tolerance, and price sensitivity also vary massively by location. Spotify didn’t scale meaningfully globally for some time, while Tencent music (which offers pay-per-song, one-off purchases, and tipping) is a global success. Some cultures are currently just more reluctant to engage with long-term subscriptions (e.g. China), while others are skeptical of silent auto-renewals (e.g. Germany), so mixed models can benefit hugely in these contexts.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;On top of local habits, you have specific regulations, from Japan and Korea’s &lt;a href=&quot;https://developer.apple.com/news/?id=bo1b122z&quot;&gt;2025 changes&lt;/a&gt; plummeting renewal rates, and &lt;a href=&quot;https://www.arcadian.ai/blogs/news/california-click-to-cancel#:~:text=Bottom%20Line-,California&apos;s%20new%20%22Click%20to%20Cancel%22%20law%20just%20became%20official.,what%20cost%20a%20subscription%20renews.&quot;&gt;California’s ‘click to cancel’ law&lt;/a&gt; being proposed.&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-27ua9R wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Rulings and regulations&quot; text=&quot;&lt;p&gt;Keep up to date with &lt;a href=&amp;quot;https://www.revenuecat.com/blog/engineering/app-to-web-purchase-guidelines/&amp;quot;&gt;global app-to-web regulations and purchase guidelines here&lt;/a&gt;.&lt;/p&gt;&quot; icon=&quot;circle-info&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;wrapping-up-is-your-app-ready-for-hybrid-monetization&quot;&gt;&lt;strong&gt;Wrapping up: is your app ready for hybrid monetization?&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;We’ve covered a lot. You have many potential frameworks for hybrid monetization, and many pros/cons to consider before getting started. So to finish up, here’s the questions to ask yourself before introducing a new revenue stream:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Do we clearly understand who our high-, mid-, and low-intent users are?&lt;/li&gt;



&lt;li&gt;Do we have reliable cohort-based retention and revenue data?&lt;/li&gt;



&lt;li&gt;Can we run clean experiments without stacking changes?&lt;/li&gt;



&lt;li&gt;Do we know which metric we’re willing to trade off — and which we aren’t?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;If you can’t answer these yet, fix that first. Hybrid monetization only works if you introduce it deliberately. Otherwise, it’s messy, chaotic, and reactive. Don’t get caught out misreading misread short-term gains while harming long-term retention.&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Hybrid monetization &lt;strong&gt;works when&lt;/strong&gt;:&lt;/th&gt;&lt;th&gt;Hybrid monetization is &lt;strong&gt;&lt;em&gt;not&lt;/em&gt;&lt;/strong&gt;:&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;You have a large group of users who get value but won’t commit to a recurring price&lt;br&gt;Your users’ willingness to pay varies widely&lt;br&gt;You want to increase ARPU without relying solely on higher subscription prices&lt;/td&gt;&lt;td&gt;Throwing every possible paywall and ad format at users&lt;br&gt;A shortcut to growth without proper measurement&lt;br&gt;A substitute for a strong core subscription offering&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;Remember there is no hack: &lt;strong&gt;Hybrid monetization is not a shortcut to fixing poor ARPU&lt;/strong&gt;. If subscriptions aren’t delivering clear, repeatable value, adding more monetization layers will only make things worse. Bad products monetize badly, and they will only do so in more ways with more sophisticated models.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[NaadSadhana — the app that teaches classical music like a guru]]></title><description><![CDATA[On the podcast, I talk with Sandeep about how a frustrated student’s struggle inspired him to create NaadSadhana, a revolutionary AI-driven app that helps singers perfect their pitch in real time. We dive into how his journey—from Microsoft and Google engineer to Apple Design Award-winning musician—shows what happens when art and technology truly harmonize.]]></description><link>https://www.revenuecat.com/blog/growth/sandeep-ranade-launched-podcast-2025/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/sandeep-ranade-launched-podcast-2025/</guid><pubDate>Wed, 14 Jan 2026 13:51:40 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/LD-Blog-Cover-Sandeep-Ranade-1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;&amp;nbsp;When a long-time student still couldn’t distinguish close intervals, Sandeep Ranade didn’t write another lesson plan — he wrote code. &lt;em&gt;NaadSadhana&lt;/em&gt; blends Indian classical music with real-time, AI-assisted feedback so vocalists can train like professionals. This is how passion, patience, and purpose shaped the product.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;Building a Music App That Speaks to Artists — The NaadSadhana Story with Sandeep Ranade&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/71s5sl68Fgo?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;iframe loading=&quot;lazy&quot; width=&quot;100%&quot; height=&quot;180&quot; frameborder=&quot;no&quot; scrolling=&quot;no&quot; seamless=&quot;&quot; src=&quot;https://share.transistor.fm/e/8ca10aeb?color=FFFFFF&amp;amp;background=30343C&quot;&gt;&lt;/iframe&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-from-microsoft-to-music-mastery&quot;&gt;&lt;strong&gt;From Microsoft to music mastery&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;“I’m from Pune… I did my master’s in computer science from Johns Hopkins University in America in Baltimore. I’ve worked at Microsoft… then at Google,” Sandeep says. After more than a decade in Silicon Valley, he and his wife — then at Apple — moved back to India “to do something that we were interested in, that we wanted to do.”&lt;/p&gt;



&lt;p&gt;He had been teaching Hindustani classical music since 2005. “There was a student … she said, please help me. I’m frustrated with my journey. I’m not making any progress.” That single conversation revealed the problem that would define his next decade.&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-solving-a-real-problem-one-note-at-a-time&quot;&gt;&lt;strong&gt;Solving a real problem, one note at a time&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;“In the first 10 minutes, it became painfully clear that she had major problems in note recognition itself,” Sandeep recalls. “She couldn’t recognize half of them. She would just know the big ones and then all the minor notes she would sort of miss out on.”&lt;/p&gt;



&lt;p&gt;A doctor ruled out tone deafness, leaving Sandeep to diagnose the issue himself. “She had gotten into some bad habits … when she was learning and practicing, she didn’t get enough guidance to course-correct as she was making the mistakes. So those mistakes became the habit.”&lt;/p&gt;



&lt;p&gt;He wanted a tool that could give her feedback whenever she practiced — something a human teacher couldn’t provide around the clock. “I thought, hey, it’s 2017. There must be an app that does this by now.” But, he found, “sadly, there was no single app that did this for human vocals. There were thousands of guitar tuners on the App Store, but not a single app that did human vocal tuning and guidance.”&lt;/p&gt;



&lt;p&gt;To fix that, he dove deep into digital-signal processing and psychoacoustics. “It took my iPhone 7 Plus battery from about two days to 20 minutes. I could have probably made an omelet on my phone,” he laughs. After nine iterations, he finally had “an algorithm that was correct, accurate, fast, and battery efficient.”&lt;/p&gt;



&lt;p&gt;When he tested it with his student, the results astonished him. “She was able to go from a score of 5 percent to 80 percent. It took her two weeks. I was not expecting this.”&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-tech-meets-tradition&quot;&gt;&lt;strong&gt;Tech meets tradition&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;“There was an ancient system of learning in India called the &lt;em&gt;guru-kul&lt;/em&gt;. Guru is the teacher, &lt;em&gt;kul&lt;/em&gt; is the home. So the student would go live with the guru traditionally and learn the craft for years and would be instructed and guided for eight, ten hours a day or more.”&lt;/p&gt;



&lt;p&gt;That continuity, he says, produced extraordinary precision. “Today, students are learning an hour a week, practicing by themselves many times a week without any guidance. And the danger is that if you practice something multiple times without knowing whether you have gotten it right or not, that is where things start to become kind of dangerous.”&lt;/p&gt;



&lt;p&gt;&lt;em&gt;NaadSadhana&lt;/em&gt; became a digital re-creation of that traditional mentorship — a tireless teacher able to correct singers in real time.&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-building-slowly-scaling-sustainably&quot;&gt;&lt;strong&gt;Building slowly, scaling sustainably&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;“I never realized that an app needs to be promoted and there’s marketing involved,” Sandeep says. “I just put it up on the App Store … I probably broke even on my developer fees.”&lt;/p&gt;



&lt;p&gt;Early users spread the word organically. “Some people said to other people that, ‘Hey, I’ve been using this app, my notes are improving.’ I told it to a few people that I know and that was it.”&lt;/p&gt;



&lt;p&gt;In 2021, that quiet persistence led to worldwide recognition. “I attended the Apple Design Award ceremony [as an audience member], looking at all of these beautifully designed apps … and in 2021 &lt;em&gt;NaadSadhana&lt;/em&gt; won for innovation. I’m only the second Indian to ever win this award.”&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-evolving-the-sound-of-the-future&quot;&gt;&lt;strong&gt;Evolving the sound of the future&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;“I’ve had offers to buy out the app, and the only question I ask them every time is: &lt;em&gt;What feature would you add next?&lt;/em&gt; … It now truly seems that I’m the only person who’s passionate enough to evolve this app in the way that I care about.”&lt;/p&gt;



&lt;p&gt;For Sandeep, &lt;em&gt;NaadSadhana&lt;/em&gt; is an artistic calling, not just a product. “There are things that people don’t know that I’ve done that will not matter to the vast majority of people, but it’ll matter to me. From a business point of view it’s not truly necessary, but from an artistic point of view it makes the world of a difference.”&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-app-builders-can-learn-from-naadsadhana&quot;&gt;&lt;strong&gt;What app builders can learn from NaadSadhana&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;“I typically tend to solve problems for me or people who are close to me,” he says. “Because I am the first customer of my solution … there are no compromises.”&lt;/p&gt;



&lt;p&gt;That builder-first mindset shaped every decision. “It has to behave a certain way … nothing less than that will be acceptable.”&lt;/p&gt;



&lt;p&gt;And rather than chase growth, he focused on depth. “I was focused more on the feature set and capability of the app … I thought that the more capable I make the app, the more attractive it’ll be to people … and that has been happening.”&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-final-takeaway&quot;&gt;&lt;strong&gt;Final takeaway&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Sandeep calls &lt;em&gt;NaadSadhana&lt;/em&gt;’s underlying technology &lt;strong&gt;“artistic intelligence.”&lt;/strong&gt; “What my app is doing is enhancing humans. I’m giving them a flight simulator, not a self-driving car.”&lt;/p&gt;



&lt;p&gt;That philosophy extends to accessibility. “Music without any barriers, without any boundaries,” he says. “Just because a person doesn’t have eyesight shouldn’t make it a barrier to be a musician or to create content.”&lt;/p&gt;



&lt;p&gt;&lt;em&gt;NaadSadhana&lt;/em&gt; shows how technology can deepen — not dilute — tradition. Design for mastery, not virality, and you’ll earn trust that lasts.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Introducing one-tap purchases for paywalls on the web]]></title><description><![CDATA[Add native wallet payments to your paywall and skip checkout.]]></description><link>https://www.revenuecat.com/blog/company/express-checkout-for-paywalls-on-the-web/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/company/express-checkout-for-paywalls-on-the-web/</guid><pubDate>Tue, 13 Jan 2026 17:01:11 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Blog_11_Introducing-one-tap-purchases-for-paywalls-on-the-web.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Your customers already decided to buy.&lt;/p&gt;



&lt;p&gt;Checkout is where too many of them slow down, hesitate, or drop off.&lt;/p&gt;



&lt;p&gt;Express Checkout adds a native wallet purchase button directly to your paywall when it’s shown in the browser, so customers can complete a purchase in one tap without being sent to a separate checkout page.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-checkout-slows-customers-after-they-ve-already-decided&quot;&gt;Checkout slows customers after they’ve already decided&lt;/h2&gt;



&lt;p&gt;By the time someone reaches your paywall, the work is mostly done. They understand the value, they’ve accepted the price, and they’re ready to move forward.&lt;/p&gt;



&lt;p&gt;Then the flow asks them to leave.&lt;/p&gt;



&lt;p&gt;They wait for a checkout page to load, choose a payment method, re-enter information their device already knows, and confirm a decision they already made. None of those steps build confidence or clarify value. They only introduce delay.&lt;/p&gt;



&lt;p&gt;Checkout doesn’t persuade. It drains momentum at the exact moment it matters most.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-moving-the-purchase-onto-the-paywall-removes-a-full-step&quot;&gt;Moving the purchase onto the paywall removes a full step&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;524&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/CleanShot-2026-01-13-at-16.34.16@2x-1024x524.png&quot; alt=&quot;&quot; class=&quot;wp-image-50293&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/CleanShot-2026-01-13-at-16.34.16@2x-1024x524.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/CleanShot-2026-01-13-at-16.34.16@2x-300x154.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/CleanShot-2026-01-13-at-16.34.16@2x-768x393.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/CleanShot-2026-01-13-at-16.34.16@2x-1536x787.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/CleanShot-2026-01-13-at-16.34.16@2x-2048x1049.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/CleanShot-2026-01-13-at-16.34.16@2x-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/CleanShot-2026-01-13-at-16.34.16@2x-78x40.png 78w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/CleanShot-2026-01-13-at-16.34.16@2x-696x356.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/CleanShot-2026-01-13-at-16.34.16@2x-560x287.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/CleanShot-2026-01-13-at-16.34.16@2x-840x430.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/CleanShot-2026-01-13-at-16.34.16@2x-80x41.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/CleanShot-2026-01-13-at-16.34.16@2x-48x25.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;In a typical web flow, the paywall creates intent and hands customers off to another page to finish the purchase.&lt;/p&gt;



&lt;p&gt;With Express Checkout, the purchase completes where the decision happens.&lt;/p&gt;



&lt;p&gt;Customers tap a native wallet button on the paywall and the transaction is done. There’s no redirect, no form entry, and no extra decision between “yes” and “paid.”&lt;/p&gt;



&lt;p&gt;That change removes an entire page from the funnel and several chances to abandon. It isn’t a visual tweak or a copy experiment. It’s a structural improvement to how purchases work in the browser.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-express-checkout-does&quot;&gt;What Express Checkout does&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;698&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/CleanShot-2026-01-13-at-16.34.21@2x-1024x698.png&quot; alt=&quot;&quot; class=&quot;wp-image-50295&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/CleanShot-2026-01-13-at-16.34.21@2x-1024x698.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/CleanShot-2026-01-13-at-16.34.21@2x-300x204.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/CleanShot-2026-01-13-at-16.34.21@2x-768x523.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/CleanShot-2026-01-13-at-16.34.21@2x-1536x1046.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/CleanShot-2026-01-13-at-16.34.21@2x-2048x1395.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/CleanShot-2026-01-13-at-16.34.21@2x-50x34.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/CleanShot-2026-01-13-at-16.34.21@2x-59x40.png 59w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/CleanShot-2026-01-13-at-16.34.21@2x-681x464.png 681w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/CleanShot-2026-01-13-at-16.34.21@2x-696x474.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/CleanShot-2026-01-13-at-16.34.21@2x-560x381.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/CleanShot-2026-01-13-at-16.34.21@2x-435x296.png 435w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/CleanShot-2026-01-13-at-16.34.21@2x-693x472.png 693w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/CleanShot-2026-01-13-at-16.34.21@2x-80x54.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/CleanShot-2026-01-13-at-16.34.21@2x-48x33.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Express Checkout adds a native digital wallet button directly to your paywall when it’s shown on the web.&lt;/p&gt;



&lt;p&gt;The component automatically renders the right option for each user, such as Apple Pay on iOS or Google Pay on supported Android devices and browsers. When a customer taps it, the device’s native payment prompt appears immediately and the purchase completes without going through the standard checkout flow.&lt;/p&gt;



&lt;p&gt;On mobile, this feels closer to an in-app purchase than a traditional browser-based flow. The most failure-prone step in the journey disappears.&lt;/p&gt;



&lt;p&gt;See the &lt;a href=&quot;https://www.revenuecat.com/docs/web/web-billing/paywalls&quot;&gt;docs for configuration steps and wallet requirements&lt;/a&gt;.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-it-works-for-web-app-to-web-and-web-to-app-flows&quot;&gt;It works for web, app-to-web, and web-to-app flows&lt;/h2&gt;



&lt;p&gt;Express Checkout improves conversion anywhere a paywall is the moment of decision.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Pure web entry&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;A customer taps an ad, a social post, or a link in your newsletter and lands on a paywall in the browser. They read the offer, decide it’s worth it, and complete the purchase immediately using their device’s native wallet. There’s no detour into checkout and no quiet moment where a new page loads and the impulse fades.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;App-to-web completion&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;A customer starts in your app, hits a paywall, and finishes the purchase on the web. Instead of landing on a checkout page that feels disconnected from the decision they just made, they arrive at a paywall in the browser that mirrors the offer and lets them complete the purchase in one tap. The transition feels continuous rather than transactional.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Web-to-app journeys&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;A customer discovers your product on the web, purchases through a paywall in the browser, and then continues into the app. Even though the journey spans platforms, the purchase step stays fast and familiar. The paywall acts as a clean entry point, not a temporary stop.&lt;/p&gt;



&lt;p&gt;In every case, the benefit is the same. When customers reach your paywall in the browser, Express Checkout removes unnecessary steps at the exact moment they’re ready to buy.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-standard-checkout-stays-available-automatically&quot;&gt;Standard checkout stays available automatically&lt;/h2&gt;



&lt;p&gt;When a native wallet is available and supported on the user’s device and browser, Express Checkout appears on the paywall and completes the purchase directly.&lt;/p&gt;



&lt;p&gt;When a native wallet isn’t available, customers see a standard purchase button and continue through the full checkout flow as usual. Both options can coexist, guiding users to the fastest path while always preserving a reliable fallback.&lt;/p&gt;



&lt;p&gt;Taxes, compliance requirements, and edge cases are handled behind the scenes. You reduce friction when you can, without ever blocking a purchase when one-tap payment isn’t available.&lt;/p&gt;



&lt;p&gt;Full setup details, supported wallets, and fallback behavior are covered in &lt;a href=&quot;https://www.revenuecat.com/docs/tools/paywalls/creating-paywalls/components#express-checkout&quot;&gt;the Express Checkout docs.&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-get-started&quot;&gt;Get started&lt;/h2&gt;



&lt;p&gt;If you’re already using RevenueCat Paywalls on the web, you can add the Express Checkout in the Paywall Builder.&lt;/p&gt;



&lt;p&gt;If you’re new to selling on the web, this is the fastest way to offer a one-tap purchase experience in the browser. It works with your existing products, trials, and offers, you’re changing the last step of the funnel, not your pricing model. We’ll share conversion results once teams start running experiments, and this same button also lays the groundwork for more advanced app-to-web paywall flows coming next.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[5 web-to-app funnel examples that actually convert]]></title><description><![CDATA[Learn what works (and why)]]></description><link>https://www.revenuecat.com/blog/growth/web-to-app-funnel-examples/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/web-to-app-funnel-examples/</guid><pubDate>Mon, 12 Jan 2026 15:11:46 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/web-to-app-funnel-examples.png" length="0" type="image/*"/><content:encoded>&lt;div class=&quot;lazyblock-e525b3a3ae6c-Z1Bepg0 wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Build no-code web funnels in RevenueCat&quot; text=&quot;&lt;p&gt;Unlock the flexibility and profit of web-to-app with our new funnel builder: create custom onboarding, surveys, and checkout flows in an instant. Free and included in your regular plan. &lt;a href=&amp;quot;https://www.revenuecat.com/feature/funnels&amp;quot;&gt;Learn more&lt;/a&gt;.&lt;/p&gt;&quot; icon=&quot;star&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;p&gt;We all say you shouldn’t copy your competitors, but the truth is, a handful of great examples can save you a &lt;em&gt;lot&lt;/em&gt; of time. When it comes to web-to-app, some subscription apps have been doing this long before it was trendy, tirelessly testing and optimizing their funnels along the way. Besides, didn’t our parents always say imitation is the sincerest form of flattery?&lt;/p&gt;



&lt;p&gt;To help you on your own &lt;a href=&quot;https://www.revenuecat.com/blog/growth/web-to-app-funnels/&quot;&gt;web-to-app&lt;/a&gt; journey, here are a few of my favourite examples — plus what you can learn from them. Because there’s no point copying a funnel if you don’t understand why it works, or how to adapt it to your own brand. And don’t worry, this isn’t just a list of quiz funnels. There are plenty of ways to approach &lt;a href=&quot;https://www.revenuecat.com/blog/growth/web-to-app-paid-user-acquisition/&quot;&gt;web-to-app&lt;/a&gt;, so we’ll cover a variety of funnel types.&lt;/p&gt;



&lt;p&gt;That said, let me start with one of my favourite quizzes, and then I promise we’ll move on to some alternative approaches.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-1-calm-s-web-to-app-quiz-funnel&quot;&gt;1: Calm’s web-to-app quiz funnel&lt;/h2&gt;



&lt;p&gt;&lt;strong&gt;Web funnel type: web quiz → trial offer → app install&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Let’s start with what Gen Z would call the &lt;em&gt;GOAT&lt;/em&gt; of quiz funnels (Greatest Of All Time, according to my little sister). &lt;a href=&quot;https://www.calm.com/&quot;&gt;Calm&lt;/a&gt;, the meditation app has long been a standout example of a web-to-app quiz funnel: simple, elegant, and remarkably effective.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;I reviewed every quiz variant to understand why this flow has remained largely unchanged for years. Here’s what the full funnel looks like, but don’t panic at the sheer detail. I’ll walk you through it step by step. If you want to explore this flow (or any of the other examples) at your own pace, you can &lt;a href=&quot;https://www.figma.com/design/trdPEQFNv7bfqCp0mO9GdQ/5-Web-to-App-Examples?node-id=0-1&amp;amp;t=8kXPXwjJluKwtQte-1&quot;&gt;see them all in their full flowchart glory here&lt;/a&gt;.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;293&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Calm-Web-2-app-flow-1024x293.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-52034&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Calm-Web-2-app-flow-1024x293.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Calm-Web-2-app-flow-300x86.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Calm-Web-2-app-flow-768x220.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Calm-Web-2-app-flow-1536x439.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Calm-Web-2-app-flow-2048x586.jpg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Calm-Web-2-app-flow-50x14.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Calm-Web-2-app-flow-125x36.jpg 125w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Calm-Web-2-app-flow-696x199.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Calm-Web-2-app-flow-560x160.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Calm-Web-2-app-flow-840x240.jpg 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Calm-Web-2-app-flow-80x23.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Calm-Web-2-app-flow-48x14.jpg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The first thing to note is that Calm only truly personalizes the sleep flow; the other four options all lead to a standardized journey. This is a great example of intent-based segmentation, dividing up users according to their goals. Sleep is a high-urgency, emotionally-charged problem, so it makes sense to invest in deeper personalization. The other goals are more exploratory, so a lighter-touch flow is a pragmatic choice.&lt;/p&gt;



&lt;p&gt;This is a tactic I often recommend to app testing teams: &lt;strong&gt;don’t try to personalize everything at once&lt;/strong&gt;. Start with your highest-priority audience, then measure, learn, and iterate from there.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;857&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-59-857x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-50242&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-59-857x1024.png 857w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-59-251x300.png 251w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-59-768x918.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-59-1285x1536.png 1285w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-59-42x50.png 42w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-59-33x40.png 33w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-59-388x464.png 388w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-59-696x832.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-59-469x560.png 469w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-59-248x296.png 248w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-59-395x472.png 395w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-59-67x80.png 67w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-59-40x48.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-59.png 1339w&quot; sizes=&quot;auto, (max-width: 857px) 100vw, 857px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-sleep-quiz-flow&quot;&gt;The sleep quiz flow&lt;/h3&gt;



&lt;p&gt;Let’s walk through the sleep flow first. It starts by asking how frequently you face this challenge.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;553&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image31-1024x553.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-50245&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image31-1024x553.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image31-300x162.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image31-768x415.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image31-1536x829.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image31-50x27.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image31-74x40.jpg 74w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image31-696x376.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image31-560x302.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image31-548x296.jpg 548w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image31-840x453.jpg 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image31-80x43.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image31-48x26.jpg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image31.jpg 1999w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;It does something simple but effective: it gives immediate feedback on your answer.&lt;/p&gt;



&lt;p&gt;This isn’t a separate screen; it’s a quick reassurance: “You’re in good hands.” From there, the quiz delves deeper, distinguishing whether you struggle to fall asleep or stay asleep, before exploring potential causes of your sleep challenges.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;451&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image9-1024x451.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-50247&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image9-1024x451.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image9-300x132.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image9-768x338.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image9-1536x677.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image9-50x22.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image9-91x40.jpg 91w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image9-696x307.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image9-560x247.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image9-840x370.jpg 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image9-80x35.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image9-48x21.jpg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image9.jpg 1999w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;As a struggling insomniac, this felt great. There’s no judgment or irrelevant questioning, just a respectful interest in my challenges. I also like that you can select multiple options for both questions, rather than being forced to choose just one.&lt;/p&gt;



&lt;p&gt;Next, a relevant review appears from someone I can relate to. The imagery and name make it feel personal, though not knowing the source slightly undermines its credibility. That said, Calm’s brand is already well known in the space, so the funnel doesn’t need to lean heavily on social proof beyond a simple, relatable review.&lt;/p&gt;



&lt;p&gt;I also appreciate that Calm asks for context: Am I trying to sleep right now? &lt;strong&gt;Too often, we assume someone is using an app the moment they open it, when for many fitness and wellness apps, that may not be the case.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Interestingly, selecting either option doesn’t change the immediate next steps. But I can imagine it influences what comes later in the flow; for example, what Calm sends or shows you after signing up, like a general meditation versus a sleep story tailored to the moment.&lt;/p&gt;



&lt;p&gt;Next, they ask you to set your preferences for the type of content you’re interested in. My only issue is that you may not yet know what you want; you may simply be seeking recommendations or open to exploring. &lt;strong&gt;Calm could do a better job of highlighting their suggestions and explaining why they recommend these.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Before we move on to the final screens (which are the same for all flows), let’s take a look at what happens when you select one of the other options:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Reduce stress or anxiety&lt;/li&gt;



&lt;li&gt;Improve focus&lt;/li&gt;



&lt;li&gt;Self-improvement&lt;/li&gt;



&lt;li&gt;Something else&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-calm-s-alternative-quiz-flow&quot;&gt;Calm’s alternative quiz flow&lt;/h3&gt;



&lt;p&gt;I tested all four options and ended up with the same flow each time. It starts with a clarification question about how I’m feeling, accompanied by the same kind of reassuring feedback used in the sleep flow.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;474&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-49-1024x474.png&quot; alt=&quot;&quot; class=&quot;wp-image-50222&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-49-1024x474.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-49-300x139.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-49-768x356.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-49-1536x711.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-49-50x23.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-49-86x40.png 86w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-49-696x322.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-49-560x259.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-49-840x389.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-49-80x37.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-49-48x22.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-49.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Here, the flow first explores the cause — interestingly — and then loops back to dig deeper into understanding the problem.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;428&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-52-1024x428.png&quot; alt=&quot;&quot; class=&quot;wp-image-50228&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-52-1024x428.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-52-300x125.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-52-768x321.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-52-1536x642.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-52-50x21.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-52-96x40.png 96w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-52-696x291.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-52-560x234.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-52-840x351.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-52-80x33.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-52-48x20.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-52.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;We see a similar review slide again; this one is quite generic and doesn’t change across different responses. Given what I’ve shared so far, I would have expected a bit more personalization.&lt;/p&gt;



&lt;p&gt;I do like that Calm asks about my level of experience and provides reassurance based on that. As someone who has endlessly tried to meditate, having the basics repeated over and over isn’t helpful; it’s frustrating. This step also signals to the user that the app works for them, whether they’ve meditated before or not.&lt;/p&gt;



&lt;p&gt;The final part gives the user a sense of control:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;728&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-48-1024x728.png&quot; alt=&quot;&quot; class=&quot;wp-image-50220&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-48-1024x728.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-48-300x213.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-48-768x546.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-48-1536x1092.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-48-50x36.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-48-56x40.png 56w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-48-653x464.png 653w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-48-696x495.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-48-560x398.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-48-417x296.png 417w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-48-664x472.png 664w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-48-80x57.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-48-48x34.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-48.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Meditating can feel like just another task, so the app aims to strike a balance: not asking the user to do too much, nor too little, when they’re in a mindset of full dedication. It then attempts to understand the user’s current emotional state and when they plan to meditate, so the app can tailor push notifications and emails.&lt;/p&gt;



&lt;p&gt;While I appreciate the continued focus on emotional state and problem-solving, the order of the questions sometimes feels random.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-post-quiz-steps-all-flows&quot;&gt;Post quiz steps (all flows)&lt;/h3&gt;



&lt;p&gt;The final steps are the same for all flows. There’s an additional review that, while identical for everyone, focuses more on sleep before prompting the user to sign up for an account.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;976&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-57-1024x976.png&quot; alt=&quot;&quot; class=&quot;wp-image-50238&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-57-1024x976.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-57-300x286.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-57-768x732.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-57-50x48.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-57-42x40.png 42w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-57-487x464.png 487w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-57-696x664.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-57-560x534.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-57-310x296.png 310w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-57-495x472.png 495w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-57-80x76.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-57-48x46.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-57.png 1416w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;This pattern isn’t uncommon in web funnels, especially quizzes: by this point, the user has already provided substantial input, and &lt;strong&gt;Calm subtly leverages loss aversion by encouraging them to save their preferences.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;I find it interesting that Calm doesn’t provide any content feedback at the end of the quiz. While the quiz clearly aims to personalize the experience, that personalization only becomes visible &lt;em&gt;after&lt;/em&gt; account sign-up. Users can access recommended content for free, but at this stage, they don’t yet know that.&lt;/p&gt;



&lt;p&gt;This suggests the quiz is designed &lt;strong&gt;less for immediate conversion gratification and more for downstream personalization.&lt;/strong&gt; Rather than rewarding the user right away, Calm seems to optimize for what happens later inside the app, through recommendations, notifications, and lifecycle messaging. This approach also makes sense given the sensitivities around mental health, but it does leave the ‘look what you could get!’ factor on the table.&lt;/p&gt;



&lt;p&gt;By this point, the user has invested time, emotion, and data, making the trial feel like a natural next step rather than a hard sell.&lt;/p&gt;



&lt;p&gt;The payment page is deliberately simple: a single 7-day trial tied to an annual subscription, without overwhelming the user with choices. If you don’t sign up right away, Calm often follows up with an additional discount to encourage conversion.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-what-can-other-apps-learn-from-calm-s-web-to-app-funnel&quot;&gt;What can other apps learn from Calm’s web-to-app funnel?&lt;/h3&gt;



&lt;p&gt;Here are the lessons to learn from Calm:&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;1. Personalize where intent is highest&lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;Calm doesn’t try to personalize everything. Sleep gets a dedicated flow; other goals don’t. That’s a good reminder that effective personalization is about focus, not coverage.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;2. Emotional reassurance builds commitment&lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;The quiz works because it validates the user before requesting any information, such as an account or trial sign-up. By the time pricing appears, the user already feels understood.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;3. The real value of the quiz shows up later&lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;Calm collects a lot of input without immediately providing feedback. This suggests the quiz is designed more for later personalization and retention than for immediate conversion payoff.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;4. Simplicity still wins at the paywall&lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;After a long quiz (though not unusually long compared to other apps), Calm deliberately removes choice: one plan, one trial — no extra decisions.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;5. Brand trust can replace heavy social proof&lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;Some elements — such as generic reviews and limited sourcing — would disadvantage smaller apps. Calm can rely on its brand within the funnel, but other apps would need more social proof to build trust.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;6. Even strong funnels aren’t perfect&lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;The order sometimes feels random, and some personalization is underused. But this is actually reassuring. You don’t need perfection for your first (or even your hundredth) &lt;a href=&quot;https://www.revenuecat.com/blog/engineering/app-to-web-purchase-guidelines/&quot;&gt;web-to-app&lt;/a&gt; funnel to work well.&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-Z1nyPyK wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Create web-to-app funnels in RevenueCat&quot; text=&quot;&lt;p&gt;With RevenueCat Funnels, you can build no-code custom onboarding, surveys, and checkout flows that unlock seamless in-app access. &lt;a class=&amp;quot;notion-link-token notion-focusable-token notion-enable-hover&amp;quot; tabindex=&amp;quot;0&amp;quot; href=&amp;quot;https://www.revenuecat.com/feature/funnels/&amp;quot; rel=&amp;quot;noopener noreferrer&amp;quot; data-token-index=&amp;quot;1&amp;quot;&gt;&lt;span class=&amp;quot;link-annotation-unknown-block-id--717331513&amp;quot;&gt;Learn more&lt;/span&gt;&lt;/a&gt;&lt;span class=&amp;quot;link-annotation-unknown-block-id--717331513&amp;quot;&gt; ↗️&lt;/span&gt;&lt;!-- notionvc: 8ff03936-e607-4e73-895d-f9b30c634e17 --&gt;&lt;/p&gt;&quot; icon=&quot;bulb&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-2-blinkist-content-led-funnel&quot;&gt;2. Blinkist Content Led Funnel&lt;/h2&gt;



&lt;p&gt;&lt;strong&gt;Web funnel type: landing page → app install&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;The value of &lt;a href=&quot;https://www.blinkist.com/&quot;&gt;Blinkist&lt;/a&gt;, the learning and personal development app, is rooted in content, so it makes sense that content sits at the very front of their acquisition funnel. Rather than leading with app features or promises, Blinkist leads with ideas: you learn something first, then discover the product that enables you to experience more of it.&lt;/p&gt;



&lt;p&gt;Over time, Blinkist has built a strong content growth engine around short, insight-driven articles that summarize ideas. These articles are distributed both organically and through paid channels, helping build trust before asking users to download or subscribe. The same content formats are reused across paid ads, partnerships, and owned media, making this approach highly scalable.&lt;/p&gt;



&lt;p&gt;Marcus Burke noted that, at one point, approximately &lt;a href=&quot;https://www.revenuecat.com/blog/growth/web-to-app-paid-user-acquisition&quot;&gt;70% of Blinkist’s acquisitions came through web-to-app flows&lt;/a&gt;, proving just how central this content-led approach has been to their growth.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-what-does-the-typical-blinkist-web-to-app-journey-look-like&quot;&gt;What does the typical Blinkist web-to-app journey look like?&lt;/h3&gt;



&lt;p&gt;A typical Blinkist journey starts with an ad promoting a piece of content, rather than the app. The ad leads to an in-depth article exploring a concept, principle, or idea. Within that content, Blinkist positions itself as the tool that helps you go deeper or learn more efficiently.&lt;/p&gt;



&lt;p&gt;This is just one of many variations on the same pattern, but the overall structure remains consistent.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;656&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-56-1024x656.png&quot; alt=&quot;&quot; class=&quot;wp-image-50236&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-56-1024x656.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-56-300x192.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-56-768x492.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-56-50x32.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-56-62x40.png 62w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-56-696x446.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-56-560x359.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-56-462x296.png 462w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-56-737x472.png 737w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-56-80x51.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-56-48x31.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-56.png 1488w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Here are several other articles Blinkist is currently driving paid traffic to:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;557&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image43-1024x557.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-50249&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image43-1024x557.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image43-300x163.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image43-768x418.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image43-50x27.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image43-73x40.jpg 73w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image43-696x379.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image43-560x305.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image43-544x296.jpg 544w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image43-840x457.jpg 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image43-80x44.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image43-48x26.jpg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image43.jpg 1071w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Across their content, Blinkist relies heavily on social proof. Sometimes this appears as Apple features or App Store recognition. Other times, it comes from the authority of the author, thinker, or public figure behind the idea being explained. &lt;strong&gt;This approach transfers credibility from the content to the product, without feeling overly salesy.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;The calls to action are usually either “Start your free trial” or “Create an account”. Trial CTAs often lead into a web onboarding quiz similar to Calm, while account CTAs keep users on the web, letting them continue exploring content.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;926&quot; height=&quot;763&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-34.png&quot; alt=&quot;&quot; class=&quot;wp-image-50190&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-34.png 926w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-34-300x247.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-34-768x633.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-34-50x41.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-34-49x40.png 49w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-34-563x464.png 563w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-34-696x573.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-34-560x461.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-34-359x296.png 359w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-34-573x472.png 573w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-34-80x66.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-34-48x40.png 48w&quot; sizes=&quot;auto, (max-width: 926px) 100vw, 926px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-where-does-monetization-happen&quot;&gt;Where does monetization happen?&lt;/h3&gt;



&lt;p&gt;Once users create an account, they can browse a range of book summaries. Clicking any summary triggers a paywall prompting a web subscription. On mobile, Blinkist also nudges users to download the app, creating a true hybrid of web discovery and app-based consumption.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;491&quot; height=&quot;782&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image6.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-50251&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image6.jpg 491w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image6-188x300.jpg 188w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image6-31x50.jpg 31w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image6-25x40.jpg 25w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image6-291x464.jpg 291w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image6-352x560.jpg 352w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image6-186x296.jpg 186w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image6-296x472.jpg 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image6-50x80.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image6-30x48.jpg 30w&quot; sizes=&quot;auto, (max-width: 491px) 100vw, 491px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;What’s powerful about this approach is that Blinkist brings its &lt;em&gt;aha! &lt;/em&gt;moment forward. Users experience “I learned something useful” before ever creating an account or starting a trial. While the sign-up rate may be lower than on a direct, conversion-focused landing page, this strategy allows Blinkist to reach a much broader audience and build trust upfront. That trust likely translates into stronger intent and higher-quality conversions once users do decide to sign up.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-trade-offs-and-risks-to-be-aware-of&quot;&gt;Trade-offs and risks to be aware of&lt;/h3&gt;



&lt;p&gt;There are trade-offs to this strategy. Organic traffic to Blinkist’s website appears to have dropped significantly over the past two years, likely influenced by shifts in search behavior and AI-driven content discovery.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;136&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-23-1024x136.png&quot; alt=&quot;&quot; class=&quot;wp-image-50168&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-23-1024x136.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-23-300x40.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-23-768x102.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-23-50x7.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-23-125x17.png 125w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-23-696x93.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-23-560x75.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-23-840x112.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-23-80x11.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-23-48x6.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-23.png 1231w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;em&gt;&amp;nbsp;Source: SemRush — Worldwide Organic Traffic for &lt;/em&gt;&lt;a href=&quot;http://blinkist.com&quot;&gt;&lt;em&gt;Blinkist.com&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Meanwhile, what Semrush measures as paid traffic is more stable, but still smaller.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;122&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-24-1024x122.png&quot; alt=&quot;&quot; class=&quot;wp-image-50169&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-24-1024x122.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-24-300x36.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-24-768x91.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-24-50x6.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-24-125x15.png 125w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-24-696x83.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-24-560x67.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-24-840x100.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-24-80x10.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-24-48x6.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-24.png 1251w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;While this can be a powerful way to build trust online, especially with larger audiences, it’s important to be strategic about ensuring the content is seen and stays relevant.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-what-can-other-apps-learn-from-blinkist-s-web-to-app-funnel&quot;&gt;What can other apps learn from Blinkist’s web-to-app funnel?&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;1. Bring the &lt;/strong&gt;&lt;strong&gt;&lt;em&gt;aha!&lt;/em&gt;&lt;/strong&gt;&lt;strong&gt; moment forward&lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;Blinkist shows that demonstrating value before asking for a sign-up can drive stronger intent later. Users convert because they’ve already learned something, not because they were sold on features.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;2. Content can be the product preview&lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;For content-driven apps, the web funnel doesn’t need to explain the app. It can demonstrate value directly and make the app the natural next step.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;3. Web doesn’t need to convert immediately to be effective&lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;Many Blinkist flows use web to educate, qualify, and build trust. Conversion happens later, either through account creation, a quiz flow, or an in-app paywall.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;4. Social proof can come from ideas, not just reviews&lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;Blinkist relies less on generic testimonials and more on the authority of thinkers and concepts. This is especially effective for educational apps.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;5. Distribution matters as much as content quality&lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;A content-led funnel only works if the content continues to reach new audiences. Changes in search behavior or platform dynamics can quickly impact performance, so it’s crucial to consider how people search today and ensure your content ranks effectively for AI-driven search.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-3-plantin-landing-page-funnel&quot;&gt;3. PlantIn landing page funnel&lt;/h2&gt;



&lt;p&gt;&lt;strong&gt;Web funnel type: landing page → web purchase or app install&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://myplantin.com/&quot;&gt;PlantIn&lt;/a&gt;, an AI plant care app, uses a fairly classic web-to-app setup, but what stands out is how intentional it feels without being overly fancy. It blends content, app promotion, and a web-based subscription flow in a way that gives users plenty of opportunities to buy in before being asked to actually buy.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;900&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image32-1024x900.png&quot; alt=&quot;&quot; class=&quot;wp-image-50257&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image32-1024x900.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image32-300x264.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image32-768x675.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image32-1536x1350.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image32-50x44.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image32-46x40.png 46w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image32-528x464.png 528w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image32-696x612.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image32-560x492.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image32-337x296.png 337w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image32-537x472.png 537w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image32-80x70.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image32-48x42.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image32.png 1999w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;See the full flow &lt;a href=&quot;https://www.figma.com/design/trdPEQFNv7bfqCp0mO9GdQ/5-Web-to-App-Examples?node-id=0-1&amp;amp;t=8kXPXwjJluKwtQte-1&quot;&gt;here&lt;/a&gt;&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;The journey usually starts with content. Ads lead to a dynamic in-between page that introduces the app and its purpose. From there, the experience changes depending on the device: on mobile, users are nudged to download the app (even if they try to click away), while on desktop, they’re directed to the website instead. It’s a small detail, but a smart one, and shows PlantIn doesn’t force an app-first experience where it doesn’t make sense.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;a href=&quot;https://www.figma.com/design/trdPEQFNv7bfqCp0mO9GdQ/5-Web-to-App-Examples?node-id=0-1&amp;amp;t=8kXPXwjJluKwtQte-1&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1019&quot; height=&quot;838&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-37.png&quot; alt=&quot;&quot; class=&quot;wp-image-50198&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-37.png 1019w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-37-300x247.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-37-768x632.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-37-50x41.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-37-49x40.png 49w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-37-564x464.png 564w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-37-696x572.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-37-560x461.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-37-360x296.png 360w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-37-574x472.png 574w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-37-80x66.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-37-48x39.png 48w&quot; sizes=&quot;auto, (max-width: 1019px) 100vw, 1019px&quot;&gt;&lt;/a&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-plantin-s-landing-page&quot;&gt;PlantIn’s landing page&lt;/h3&gt;



&lt;p&gt;For some web-to-app landing pages, it isn’t always clear that they lead to an app. This can be tricky if you only offer web payments, since you don’t want users clicking through to the app store by mistake. For PlantIn, this isn’t an issue. They lead with a QR code for easy app download, include app store links, and show an in-app screenshot. The screenshot clearly highlights the value users can get from the app.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-style-default&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;448&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Plantin-Web2App-448x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-50265&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Plantin-Web2App-448x1024.png 448w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Plantin-Web2App-131x300.png 131w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Plantin-Web2App-768x1757.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Plantin-Web2App-895x2048.png 895w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Plantin-Web2App-22x50.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Plantin-Web2App-17x40.png 17w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Plantin-Web2App-203x464.png 203w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Plantin-Web2App-696x1592.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Plantin-Web2App-245x560.png 245w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Plantin-Web2App-129x296.png 129w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Plantin-Web2App-206x472.png 206w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Plantin-Web2App-35x80.png 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Plantin-Web2App-21x48.png 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Plantin-Web2App-scaled.png 1119w&quot; sizes=&quot;auto, (max-width: 448px) 100vw, 448px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The next section, “What is PlantIn?”, appears to explain what the app does, but it’s actually a statistical trust builder. It highlights six key stats designed to build credibility and confidence in PlantIn.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Before moving on to the app’s key benefits, each stat should be explained clearly so users understand how it works. &lt;/strong&gt;The section then wraps up with a brief social proof example and links to relevant articles — for example, the one on using coffee grounds for your plants (which I can personally recommend).&lt;/p&gt;



&lt;p&gt;What’s great about PlantIn is that it doesn’t rush users into conversion. Instead, it focuses on sign-ups and deeper content. It offers a wealth of in-depth pages, like showing plant types, plant diseases, and even mushrooms you can identify. This doesn’t take away from the core value of the app — the ability to identify plants with confidence — or distract from conversion, it shows value and builds trust.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;a href=&quot;https://www.figma.com/design/trdPEQFNv7bfqCp0mO9GdQ/5-Web-to-App-Examples?node-id=0-1&amp;amp;t=8kXPXwjJluKwtQte-1&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;577&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-58-577x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-50240&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-58-577x1024.png 577w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-58-169x300.png 169w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-58-28x50.png 28w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-58-23x40.png 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-58-262x464.png 262w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-58-316x560.png 316w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-58-167x296.png 167w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-58-266x472.png 266w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-58-45x80.png 45w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-58-27x48.png 27w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-58.png 649w&quot; sizes=&quot;auto, (max-width: 577px) 100vw, 577px&quot;&gt;&lt;/a&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-sign-up-first-then-subscribe&quot;&gt;Sign up first, then subscribe&lt;/h3&gt;



&lt;p&gt;It’s the same classic flow of signing up to purchase. This matters for apps because – without it – if buyers purchase without an account, it creates an awkward post-purchase flow to try and get them set up on the app. It also allows you to encourage them to sign up for emails so you can guide them further.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;720&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-39-1024x720.png&quot; alt=&quot;&quot; class=&quot;wp-image-50202&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-39-1024x720.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-39-300x211.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-39-768x540.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-39-50x35.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-39-57x40.png 57w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-39-660x464.png 660w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-39-696x490.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-39-560x394.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-39-421x296.png 421w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-39-671x472.png 671w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-39-80x56.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-39-48x34.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-39.png 1382w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;What I really like about PlantIn’s pricing step is that it clearly shows users how much they save by subscribing online. The app delivers &lt;a href=&quot;https://www.revenuecat.com/blog/growth/the-pros-and-cons-of-web-to-app-funnels/&quot;&gt;lower fees via the web and stronger retention to the end user&lt;/a&gt;.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;980&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-44-1024x980.png&quot; alt=&quot;&quot; class=&quot;wp-image-50212&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-44-1024x980.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-44-300x287.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-44-768x735.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-44-50x48.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-44-42x40.png 42w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-44-485x464.png 485w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-44-696x666.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-44-560x536.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-44-309x296.png 309w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-44-493x472.png 493w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-44-80x77.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-44-48x46.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-44.png 1227w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Free trials are less common on web due to fraud risk, so it’s notable that PlantIn offers one. They keep it short, likely to prevent abuse, and because users can see the app’s value relatively quickly.&lt;/p&gt;



&lt;p&gt;The checkout appears in a pop-up, making it clear what you’re paying for and what you’ll unlock. By this point, it feels less like a hard sell and more like the logical next step after everything you’ve already explored.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;734&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-45-734x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-50214&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-45-734x1024.png 734w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-45-215x300.png 215w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-45-768x1071.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-45-36x50.png 36w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-45-29x40.png 29w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-45-333x464.png 333w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-45-696x971.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-45-401x560.png 401w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-45-212x296.png 212w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-45-338x472.png 338w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-45-57x80.png 57w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-45-34x48.png 34w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-45.png 808w&quot; sizes=&quot;auto, (max-width: 734px) 100vw, 734px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;What stood out to me overall is how often PlantIn repeats its value proposition without it feeling aggressive. &lt;strong&gt;Each step adds a bit more context, rather than simply pushing the same message harder.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;That said, I do find the wording slightly misleading. The title says “subscribing on the web,” but all the plans use the term ‘access’. Only the small text — which oddly omits the dollar sign on the first charge — clarifies that it’s a recurring subscription. This risks unhappy customers who didn’t realize they subscribed. I would use the word subscription or ‘per X period’ clearly in the prices, to ensure it’s clear which options are subscriptions and which are not.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-what-can-other-apps-learn-from-plantin-s-web-to-app-funnel&quot;&gt;What can other apps learn from PlantIn’s web-to-app funnel?&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;1. Meet users where they are&lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;Routing mobile and desktop users differently avoids forcing an app download when it doesn’t make sense, rather than treating all users the same.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;2. Show the breadth of your app, not just the main feature&lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;PlantIn does a great job of making the subscription feel like access to an ecosystem, rather than just a single tool, while avoiding the trap of presenting itself as an ‘all-in-one’ solution.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;3. Use content to reduce anxiety&lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;Especially for users who feel like they’re ‘bad at plants’, the content reassures them before trying to sell.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;4. Keep the app visible throughout the journey&lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;Even when monetizing on the web, the app remains front and center.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;5. Don’t be afraid to communicate web-specific offerings&lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;The cheaper web subscription is presented as added value, not merely a way to avoid fees.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-4-ynab-workshop-funnel&quot;&gt;4. YNAB Workshop Funnel&lt;/h2&gt;



&lt;p&gt;&lt;strong&gt;Web funnel type:&lt;/strong&gt; &lt;strong&gt;workshop → web purchase or web onboarding → email → app install&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;http://ynab.com/&quot;&gt;YNAB&lt;/a&gt;… You Need a Budget, don’t we all? This subscription app, which unsurprisingly is a budget app, has an extensive web experience. Given the complexity of entering all the data needed to set up and track a budget, YNAB lets users complete the entire process on the web, with the app introduced much later in the customer journey than you might expect. So late, in fact, that I started doubting they even had an app — but they do!&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Workshops and webinars aren’t just effective for B2B apps; they can work really well for consumer apps too, especially when you want to build trust or stand out in a competitive market. I previously worked with a meditation and mindfulness app that offered weekly workshops. They ran multiple 3- and 7-day challenges you could join live, each centered around a theme like stress or gratitude.&lt;/p&gt;



&lt;p&gt;These free workshops helped users connect with the coach, and afterwards, they were encouraged to purchase the app. This approach not only drove short-term boosts but also often led to longer-term growth, as users realized they wanted more content from the coach.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-workshops-to-help-you-learn&quot;&gt;Workshops to help you learn&lt;/h3&gt;



&lt;p&gt;YNAB is built around its unique methodology and does a great job of supporting users and helping them learn.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;391&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-29-1024x391.png&quot; alt=&quot;&quot; class=&quot;wp-image-50180&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-29-1024x391.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-29-300x114.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-29-768x293.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-29-50x19.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-29-105x40.png 105w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-29-696x265.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-29-560x214.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-29-840x320.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-29-80x31.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-29-48x18.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-29.png 1455w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Signing up for a workshop is simple via Zoom, and you receive a confirmation email. At this stage, there’s no mention of the app, and so the approach is refreshingly un-salesy. The focus is purely on delivering value to both existing and new users.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1600&quot; height=&quot;936&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-43.png&quot; alt=&quot;&quot; class=&quot;wp-image-50210&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-43.png 1600w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-43-300x176.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-43-1024x599.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-43-768x449.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-43-1536x899.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-43-50x29.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-43-68x40.png 68w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-43-696x407.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-43-560x328.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-43-506x296.png 506w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-43-807x472.png 807w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-43-80x47.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-43-48x28.png 48w&quot; sizes=&quot;auto, (max-width: 1600px) 100vw, 1600px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;So what happens if you start the web flow? Get ready for a long web onboarding. This flow can be accessed via the website or after a webinar. Note that YNAB also runs ads to a 34-day free trial page, which is personalized to the user’s pain point and also leads into the same web onboarding.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1600&quot; height=&quot;650&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-38.png&quot; alt=&quot;&quot; class=&quot;wp-image-50200&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-38.png 1600w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-38-300x122.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-38-1024x416.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-38-768x312.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-38-1536x624.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-38-50x20.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-38-98x40.png 98w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-38-696x283.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-38-560x228.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-38-840x341.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-38-80x33.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-38-48x20.png 48w&quot; sizes=&quot;auto, (max-width: 1600px) 100vw, 1600px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-web-onboarding-process&quot;&gt;The web onboarding process&lt;/h3&gt;



&lt;p&gt;I found it fascinating how many steps you go through without any mention of the app or sales. The focus is really on creating a sense of investment, with enough ‘sunk costs’ that you’re naturally engaged. I also didn’t expect the setup to be so easy and enjoyable, despite the multitude of steps.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1000&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-33-1024x1000.png&quot; alt=&quot;&quot; class=&quot;wp-image-50188&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-33-1024x1000.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-33-300x293.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-33-768x750.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-33-1536x1500.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-33-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-33-41x40.png 41w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-33-475x464.png 475w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-33-696x680.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-33-560x547.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-33-303x296.png 303w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-33-483x472.png 483w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-33-80x78.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-33-48x48.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-33.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;812&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-40-1024x812.png&quot; alt=&quot;&quot; class=&quot;wp-image-50204&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-40-1024x812.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-40-300x238.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-40-768x609.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-40-1536x1218.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-40-50x40.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-40-585x464.png 585w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-40-696x552.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-40-560x444.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-40-373x296.png 373w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-40-595x472.png 595w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-40-80x63.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-40-48x38.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-40.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Talking about money can feel a bit &lt;em&gt;icky&lt;/em&gt;, and the questions can get personal. Still, I felt surprisingly comfortable sharing complete insight into my financial approach — bet you didn’t expect that in a web-to-app example article!&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;710&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-35-1024x710.png&quot; alt=&quot;&quot; class=&quot;wp-image-50193&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-35-1024x710.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-35-300x208.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-35-768x532.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-35-1536x1065.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-35-50x35.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-35-58x40.png 58w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-35-669x464.png 669w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-35-696x482.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-35-560x388.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-35-427x296.png 427w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-35-681x472.png 681w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-35-80x55.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-35-48x33.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-35.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;a href=&quot;https://www.figma.com/design/trdPEQFNv7bfqCp0mO9GdQ/5-Web-to-App-Examples?node-id=0-1&amp;amp;t=8kXPXwjJluKwtQte-1&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;984&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-36-1024x984.png&quot; alt=&quot;&quot; class=&quot;wp-image-50196&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-36-1024x984.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-36-300x288.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-36-768x738.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-36-1536x1476.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-36-50x48.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-36-42x40.png 42w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-36-483x464.png 483w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-36-696x669.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-36-560x538.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-36-308x296.png 308w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-36-491x472.png 491w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-36-80x77.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-36-48x46.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-36.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/a&gt;&lt;/figure&gt;



&lt;p&gt;I did find the setup a bit unusual: the content sits at the bottom of the screen, with the rest left blank throughout the onboarding process (shown in the screen one, but not in the following ones). Given the length of the flow, it sometimes felt incomplete.&lt;/p&gt;



&lt;p&gt;In essence, strong web quizzes often blur the line with onboarding, but for YNAB, there is no blurred line: this is pure onboarding. A few highlights are worth noting:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Customized reviews:&lt;/strong&gt; I got a completely different review depending on what I said my goal was&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Gradual build-up of the ‘thinking power’ required:&lt;/strong&gt; the questions started easy and get progressively more in-depth&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Personalization of relevant follow-up questions:&lt;/strong&gt; e.g. if I indicated I owned a house, there were later questions about home insurance etc.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Initial questions were easy to answer on the spot: &lt;/strong&gt;later, more in-depth questions arose that felt personal or needed calculation, e.g. how much you want or need to save per month, or your combined income&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Breaking up the questions&lt;/strong&gt;: it is a &lt;em&gt;lot&lt;/em&gt; of questions, but the pauses between for reviews, explanation, and feedback lighten the flow&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Even at the end of the quiz, there’s no mention of the app or YNAB’s costs. Since it’s a tool designed to help you save money, spending on it might feel odd until you’ve experienced the value, which is likely why they offer an extensive 34-day free trial. This period spans over a calendar month, allowing you to input data, start achieving your financial goals, and learn more about YNAB.&lt;/p&gt;



&lt;p&gt;There’s also a part two questionnaire for account setup and connecting to your bank account, followed by a more explanatory, passive onboarding phase.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;326&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-41-1024x326.png&quot; alt=&quot;&quot; class=&quot;wp-image-50206&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-41-1024x326.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-41-300x96.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-41-768x245.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-41-1536x490.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-41-50x16.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-41-125x40.png 125w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-41-696x222.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-41-560x179.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-41-840x268.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-41-80x26.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-41-48x15.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-41.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Two highlights stand out here. First, after completing part two of the setup, there’s a celebration moment. When the goal is long-term, celebrating progress like this is powerful; who doesn’t love a bit of colorful confetti? Budgeting has never felt so fun.&lt;/p&gt;



&lt;p&gt;Second, the flow is reassuring. I’m quite far along before they make a big, high-trust ask: connecting my bank details. They gently reassure me that it’s secure, which builds confidence before the action.&lt;/p&gt;



&lt;p&gt;Yet… still no mention of the app? Not even in the menu.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;435&quot; height=&quot;774&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-27.png&quot; alt=&quot;&quot; class=&quot;wp-image-50176&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-27.png 435w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-27-169x300.png 169w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-27-28x50.png 28w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-27-22x40.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-27-261x464.png 261w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-27-315x560.png 315w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-27-166x296.png 166w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-27-265x472.png 265w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-27-45x80.png 45w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-27-27x48.png 27w&quot; sizes=&quot;auto, (max-width: 435px) 100vw, 435px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The first time I saw the app was in a follow-up email sent the same day I signed up:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;465&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-42-465x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-50208&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-42-465x1024.png 465w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-42-136x300.png 136w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-42-23x50.png 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-42-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-42-211x464.png 211w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-42-135x296.png 135w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-42-215x472.png 215w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-42-36x80.png 36w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-42-22x48.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-42.png 525w&quot; sizes=&quot;auto, (max-width: 465px) 100vw, 465px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;This demonstrates that a strong flow doesn’t need to lead with your app. If your app is primarily a retention tool or requires significant setup and context, it can be more effective to provide an extensive, educational setup on the web first.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-what-can-other-apps-learn-from-ynab-s-web-to-app-funnel&quot;&gt;What can other apps learn from YNAB’s web-to-app funnel?&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;1. Web-to-app doesn’t have to lead with the app&lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;YNAB delays the app reveal almost to an uncomfortable degree, and that’s intentional. The app itself isn’t the core value proposition; the methodology is. The web experience does the heavy lifting by teaching, building trust, and getting users mentally invested before the app even enters the picture.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;2. Workshops work when education is the product&lt;/strong&gt;&lt;br&gt;The workshops aren’t a gimmick or a lead magnet tacked on for growth. They’re a natural extension of YNAB’s philosophy. If your product requires a mindset shift or the adoption of new behaviors, workshops can achieve what landing pages never will.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;3. Long onboarding can work if it feels earned&lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;This is a long flow, but it doesn’t feel that way. Questions start easy, gradually get more personal, and are regularly punctuated with reassurance, reviews, and explanations. In this case, pacing matters far more than the number of steps.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;4. Delay the ‘big ask’ until trust is established&lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;Connecting bank accounts is a major trust moment. YNAB waits until you’ve invested time, seen progress, and felt understood before asking for it. By then, it feels reasonable rather than risky.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;5. Celebrate progress, not outcomes&lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;Budgeting is a long-term game. YNAB celebrates setup milestones, not financial wins. That confetti moment after part two isn’t about money saved, it’s about momentum towards a goal.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;6. Free trials should match the job to be done&lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;The 34-day free trial isn’t arbitrary. It gives users enough time to complete a full monthly budgeting cycle and experience the benefits before being asked to pay. The trial length supports behavior change, not just conversion.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-5-photoroom-s-free-tool-funnel&quot;&gt;5: Photoroom’s free tool funnel&lt;/h2&gt;



&lt;p&gt;&lt;strong&gt;Web funnel type:&lt;/strong&gt; &lt;strong&gt;free tool → web onboarding → trial offer → app install&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.photoroom.com/&quot;&gt;Photoroom&lt;/a&gt;, the photo editing app, is one of my favorite examples of how a B2B-focused app can use web-to-app without feeling pushy. Instead of gating everything behind an account or trial, they let you do real work upfront. You can remove a background for free, directly on the web, with zero friction, and that alone delivers value.&lt;/p&gt;



&lt;p&gt;What’s interesting is that the web experience doesn’t feel like a stripped-down teaser; it feels like a useful product in its own right. Yet, at every step, it subtly nudges you toward deeper commitment.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;The moment you upload an image and see the result, you’ve already had the &lt;em&gt;aha!&lt;/em&gt; moment, and that’s when Photoroom starts layering in the next steps.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;a href=&quot;https://www.figma.com/design/trdPEQFNv7bfqCp0mO9GdQ/5-Web-to-App-Examples?node-id=0-1&amp;amp;t=8kXPXwjJluKwtQte-1&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;664&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-53-1024x664.png&quot; alt=&quot;&quot; class=&quot;wp-image-50230&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-53-1024x664.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-53-300x194.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-53-768x498.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-53-1536x996.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-53-50x32.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-53-62x40.png 62w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-53-696x451.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-53-560x363.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-53-457x296.png 457w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-53-728x472.png 728w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-53-80x52.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-53-48x31.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-53.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/a&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Reminder: you can zoom in on all the detail &lt;a href=&quot;https://www.figma.com/design/trdPEQFNv7bfqCp0mO9GdQ/5-Web-to-App-Examples?node-id=0-1&amp;amp;t=8kXPXwjJluKwtQte-1&quot;&gt;right here&lt;/a&gt;&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-give-value-first-then-ask-for-commitment&quot;&gt;&lt;strong&gt;Give value first, then ask for commitment&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Photoroom offers a range of tools that can be accessed and used directly online:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;426&quot; height=&quot;403&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-25.png&quot; alt=&quot;&quot; class=&quot;wp-image-50172&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-25.png 426w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-25-300x284.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-25-50x47.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-25-42x40.png 42w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-25-313x296.png 313w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-25-80x76.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-25-48x45.png 48w&quot; sizes=&quot;auto, (max-width: 426px) 100vw, 426px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;One of the smartest decisions Photoroom makes is not forcing account creation too early. You can complete your first action without signing up, which reduces initial friction, especially for people solving a one-off problem.&lt;/p&gt;



&lt;p&gt;But it doesn’t stop there. They use that first success to justify the next ask. If you want to continue editing, export in higher quality, or explore additional features, you’re encouraged to create an account. At that point, it feels reasonable. You’re not being asked to pay, or download anything. You’re not even signing up just to try it; you’re signing up to continue something you’ve already started.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;474&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-46-1024x474.png&quot; alt=&quot;&quot; class=&quot;wp-image-50216&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-46-1024x474.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-46-300x139.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-46-768x355.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-46-1536x710.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-46-50x23.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-46-86x40.png 86w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-46-696x322.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-46-560x259.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-46-840x389.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-46-80x37.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-46-48x22.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-46.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;This is a good reminder that web-to-app doesn’t always need a hard gate. Sometimes, letting people experience the core value first is the fastest path to building intent.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;920&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-51-1024x920.png&quot; alt=&quot;&quot; class=&quot;wp-image-50226&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-51-1024x920.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-51-300x269.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-51-768x690.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-51-1536x1380.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-51-50x45.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-51-45x40.png 45w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-51-517x464.png 517w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-51-696x625.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-51-560x503.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-51-330x296.png 330w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-51-526x472.png 526w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-51-80x72.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-51-48x43.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-51.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-self-employed-vs-business-two-very-different-journeys&quot;&gt;Self-employed vs. business: two very different journeys&lt;/h3&gt;



&lt;p&gt;Once you create an account, Photoroom quickly asks how you plan to use the product. This is where the funnel clearly becomes B2B-focused.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;706&quot; height=&quot;653&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-28.png&quot; alt=&quot;&quot; class=&quot;wp-image-50178&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-28.png 706w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-28-300x277.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-28-50x46.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-28-43x40.png 43w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-28-502x464.png 502w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-28-696x644.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-28-560x518.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-28-320x296.png 320w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-28-510x472.png 510w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-28-80x74.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-28-48x44.png 48w&quot; sizes=&quot;auto, (max-width: 706px) 100vw, 706px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;If you indicate that you’re using it for personal purposes, the flow stays relatively lightweight. Even then, it checks whether you have a brand to import:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;860&quot; height=&quot;528&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-26.png&quot; alt=&quot;&quot; class=&quot;wp-image-50174&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-26.png 860w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-26-300x184.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-26-768x472.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-26-50x31.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-26-65x40.png 65w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-26-696x427.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-26-560x344.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-26-482x296.png 482w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-26-769x472.png 769w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-26-80x49.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-26-48x29.png 48w&quot; sizes=&quot;auto, (max-width: 860px) 100vw, 860px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;But if you indicate you’re using Photoroom for a business, the experience changes. The onboarding goes much deeper: they ask about your company, your needs, and your expected volume. This doesn’t feel like unnecessary questioning; rather, it feels like qualification.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;860&quot; height=&quot;528&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image34.png&quot; alt=&quot;&quot; class=&quot;wp-image-50269&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image34.png 860w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image34-300x184.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image34-768x472.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image34-50x31.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image34-65x40.png 65w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image34-696x427.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image34-560x344.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image34-482x296.png 482w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image34-769x472.png 769w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image34-80x49.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image34-48x29.png 48w&quot; sizes=&quot;auto, (max-width: 860px) 100vw, 860px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Photoroom is clearly trying to understand what kind of customer you are and what pricing and setup will make sense for you. From a growth perspective, this achieves two things at once:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Improves relevance&lt;/strong&gt; by tailoring the experience&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Sets expectations early&lt;/strong&gt; for more advanced, higher-value plans&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;This is a strong example of using web onboarding not just to convert, but to properly segment users before the app experience even begins.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;710&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-35-1024x710.png&quot; alt=&quot;&quot; class=&quot;wp-image-50192&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-35-1024x710.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-35-300x208.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-35-768x532.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-35-1536x1065.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-35-50x35.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-35-58x40.png 58w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-35-669x464.png 669w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-35-696x482.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-35-560x388.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-35-427x296.png 427w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-35-681x472.png 681w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-35-80x55.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-35-48x33.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-35.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-team-setup-as-part-of-the-funnel&quot;&gt;Team setup as part of the funnel&lt;/h3&gt;



&lt;p&gt;One of my favorite parts of the Photoroom flow is how early they introduce team setup. For business users, inviting teammates isn’t treated as an advanced feature you’ll discover later; it’s positioned as a natural next step.&lt;/p&gt;



&lt;p&gt;The interface makes it easy to invite your team and set up a shared workspace. This does two important things:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Increases switching costs early&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Turns one user into multiple users&lt;/strong&gt; before monetization even happens&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;By the time pricing is introduced, you’re no longer thinking as an individual evaluating a tool; you’re thinking as a team adopting a workflow. That shift alone changes how pricing is perceived.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;917&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-54-1024x917.png&quot; alt=&quot;&quot; class=&quot;wp-image-50232&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-54-1024x917.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-54-300x269.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-54-768x688.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-54-1536x1376.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-54-50x45.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-54-45x40.png 45w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-54-518x464.png 518w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-54-696x623.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-54-560x502.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-54-330x296.png 330w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-54-527x472.png 527w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-54-80x72.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-54-48x43.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-54.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-repetition-without-feeling-repetitive&quot;&gt;Repetition without feeling repetitive&lt;/h3&gt;



&lt;p&gt;Photoroom does something subtle but highly-effective throughout the pricing flow: no matter which free tool you start with, you continue to see the same core features and value propositions repeated.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1013&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image7-1013x1024.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-50255&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image7-1013x1024.jpg 1013w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image7-297x300.jpg 297w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image7-768x776.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image7-50x50.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image7-40x40.jpg 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image7-459x464.jpg 459w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image7-696x703.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image7-554x560.jpg 554w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image7-293x296.jpg 293w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image7-467x472.jpg 467w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image7-80x80.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image7-48x48.jpg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image7.jpg 1342w&quot; sizes=&quot;auto, (max-width: 1013px) 100vw, 1013px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;At first glance, it might feel like they’re under-selling the breadth of the product. But I think this is intentional. Rather than overwhelming users with everything Photoroom can do, they focus on a small set of core capabilities and reinforce them consistently.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;864&quot; height=&quot;890&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-31.png&quot; alt=&quot;&quot; class=&quot;wp-image-50184&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-31.png 864w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-31-291x300.png 291w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-31-768x791.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-31-39x40.png 39w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-31-450x464.png 450w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-31-696x717.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-31-544x560.png 544w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-31-287x296.png 287w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-31-458x472.png 458w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-31-78x80.png 78w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-31-48x48.png 48w&quot; sizes=&quot;auto, (max-width: 864px) 100vw, 864px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;This repetition builds clarity. It’s a good reminder that focus often converts better than completeness.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-pricing-clarity-and-trial-positioning&quot;&gt;Pricing clarity and trial positioning&lt;/h3&gt;



&lt;p&gt;When Photoroom finally introduces the free trial, it doesn’t come out of nowhere. By this point, you’ve already:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Used the product&lt;/li&gt;



&lt;li&gt;Created an account&lt;/li&gt;



&lt;li&gt;Seen how it fits into your workflow&lt;/li&gt;



&lt;li&gt;Possibly invited your team&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The trial feels like a natural extension rather than an aggressive push. They’ve asked several questions and set you up with an account, which helps reduce the risk of failed online charges.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;911&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-55-911x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-50234&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-55-911x1024.png 911w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-55-267x300.png 267w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-55-768x863.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-55-1367x1536.png 1367w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-55-45x50.png 45w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-55-36x40.png 36w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-55-413x464.png 413w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-55-696x782.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-55-498x560.png 498w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-55-263x296.png 263w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-55-420x472.png 420w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-55-71x80.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-55-43x48.png 43w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-55.png 1424w&quot; sizes=&quot;auto, (max-width: 911px) 100vw, 911px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;I also appreciate how clearly Photoroom communicates pricing. You know exactly what you’re getting, what you’ll be charged, and when. There’s no sense of being tricked into a trial you might forget about. This transparency builds trust, which is especially important for business users.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-what-can-other-apps-learn-from-photoroom-s-web-to-app-funnel&quot;&gt;What can other apps learn from Photoroom’s web-to-app funnel?&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;1. Let users do real work for free&lt;/strong&gt;&lt;br&gt;Photoroom shows that giving away meaningful value upfront doesn’t cannibalize conversion. It creates it.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;2. Use web onboarding to qualify, not just convert&lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;Asking whether someone is a business user unlocks deeper segmentation and more relevant pricing later.&lt;br&gt;&lt;br&gt;&lt;strong&gt;3.&lt;/strong&gt; &lt;strong&gt;Design for teams early&lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;Introducing team setup before monetization increases commitment and expands account value.&lt;br&gt;&lt;br&gt;&lt;strong&gt;4. Subtle repetition builds clarity&lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;Focusing on a few core features across multiple entry points helps users understand (and remember!) what the product is really for.&lt;br&gt;&lt;br&gt;&lt;strong&gt;5. Trials work best when they feel earned&lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;By the time the free trial appears, it feels like the obvious next step rather than a risky decision.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-there-s-no-single-best-web-to-app-funnel&quot;&gt;There’s no single ‘best’ web-to-app funnel&lt;/h2&gt;



&lt;p&gt;Looking across all five examples, the biggest takeaway is that web-to-app isn’t a one-size-fits-all template. Calm, Blinkist, PlantIn, YNAB, and Photoroom all approach it differently because their products, audiences, and jobs to be done vary:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Some lead with &lt;strong&gt;emotion&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;Some lead with &lt;strong&gt;education&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;Some lead with &lt;strong&gt;utility&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;What they all have in common is intention and user value. None of these funnels treats the web as a thin acquisition layer whose only job is to push users into the app as fast as possible. Instead, the web is used to:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Build trust&lt;/li&gt;



&lt;li&gt;Create commitment&lt;/li&gt;



&lt;li&gt;Reduce uncertainty&lt;/li&gt;



&lt;li&gt;And, in some cases, even deliver the core value itself&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;If there’s one thing to take away, it’s this: &lt;strong&gt;your web funnel should do the hardest work before the app ever opens.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;That might mean helping users understand themselves better, like Calm. Or it might mean teaching them something useful, like Blinkist or YNAB. Maybe it’s letting them experience real value immediately, like Photoroom or PlantIn.&lt;/p&gt;



&lt;p&gt;The right approach depends on your subscription app, of course, but the opportunity is the same. Web-to-app works best when it’s not just a bridge, but a meaningful part of the product experience that drives high-quality users.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Building apps for an existing audience: why distribution is the new moat]]></title><description><![CDATA[The hardest part of building an app used to be… building the app. That's changed]]></description><link>https://www.revenuecat.com/blog/engineering/building-apps-existing-audience/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/building-apps-existing-audience/</guid><pubDate>Mon, 12 Jan 2026 11:46:34 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Building-apps-for-an-existing-audience-why-distribution-is-the-new-moat.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Remember when shipping an app meant months of coding, debugging, and praying your launch didn’t coincide with an iOS update that broke everything? Those days aren’t quite gone, but they’re fading fast. Thanks to AI-assisted development tools like Cursor, Bolt, Replit, and a growing army of ‘vibecoding’ platforms, the barrier to building has dropped dramatically. &lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://cloud.google.com/discover/what-is-vibe-coding&quot;&gt;Andrej Karpathy coined the term ‘vibe coding’ in early 2025&lt;/a&gt; to describe a workflow where you guide an AI tool to generate code through conversation, rather than writing it line by line. In its purest form, you can almost “forget that the code even exists”.&lt;/p&gt;



&lt;p&gt;This is genuinely exciting: more people can build. More ideas can ship. The app stores are about to get a lot more crowded.. &lt;/p&gt;



&lt;p&gt;But here’s the thing nobody’s talking about enough: if everyone can build, then building isn’t the competitive advantage anymore. The new moats are &lt;strong&gt;having a great idea&lt;/strong&gt; and &lt;strong&gt;getting it in front of people who want it&lt;/strong&gt;. And there’s a shortcut to both that smart developers (and smart creators) are starting to figure out.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-influencer-app-playbook-isn-t-new-but-it-s-never-been-more-relevant&quot;&gt;The influencer app playbook isn’t new, but it’s never been more relevant&lt;/h2&gt;



&lt;p&gt;Cast your mind back to 2014. Kim Kardashian partnered with Glu Mobile to launch &lt;em&gt;Kim Kardashian: Hollywood&lt;/em&gt;, a freemium game where players climb the celebrity ladder through fashion choices, relationships, and strategic selfies. The gaming press was skeptical. The app world shrugged. Then &lt;a href=&quot;https://www.forbes.com/sites/jeetendrsehdev/2024/01/08/game-changer-unveiling-the-kim-kardashian-hollywood-game-legacy/&quot;&gt;it made $1.6 million in its first five days&lt;/a&gt;. By the end of 2014, it had generated over $43 million in revenue. At its peak, &lt;a href=&quot;https://mobilegamer.biz/the-rise-and-fall-of-kim-kardashian-hollywood/&quot;&gt;the game was pulling in $700,000 per day&lt;/a&gt;.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;563&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/kim-kardashian-hollywood-game-1024x563.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-49953&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/kim-kardashian-hollywood-game-1024x563.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/kim-kardashian-hollywood-game-300x165.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/kim-kardashian-hollywood-game-768x422.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/kim-kardashian-hollywood-game-50x27.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/kim-kardashian-hollywood-game-73x40.jpg 73w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/kim-kardashian-hollywood-game-696x382.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/kim-kardashian-hollywood-game-560x308.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/kim-kardashian-hollywood-game-539x296.jpg 539w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/kim-kardashian-hollywood-game-840x461.jpg 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/kim-kardashian-hollywood-game-80x44.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/kim-kardashian-hollywood-game-48x26.jpg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/kim-kardashian-hollywood-game.jpg 1500w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The game wasn’t revolutionary from a mechanics standpoint. It was a narrative dress-up game with energy timers and premium currency. What made it work was that Kim Kardashian had 25 million Instagram followers at launch (she’s now north of 360 million), and her audience was exactly the demographic that would love a game about becoming famous. The distribution was built in. The idea was validated by the audience that already existed.&lt;/p&gt;



&lt;p&gt;That playbook has only gotten more sophisticated since then.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-from-hollywood-to-your-home-screen&quot;&gt;From Hollywood to your home screen&lt;/h2&gt;


&lt;div class=&quot;wp-block-image&quot;&gt;
&lt;figure class=&quot;alignright size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;473&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/centr-app-hemsworth-473x1024.jpeg&quot; alt=&quot;&quot; class=&quot;wp-image-49955&quot; style=&quot;aspect-ratio:0.46191498926127567;width:248px;height:auto&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/centr-app-hemsworth-473x1024.jpeg 473w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/centr-app-hemsworth-139x300.jpeg 139w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/centr-app-hemsworth-23x50.jpeg 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/centr-app-hemsworth-18x40.jpeg 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/centr-app-hemsworth-214x464.jpeg 214w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/centr-app-hemsworth-259x560.jpeg 259w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/centr-app-hemsworth-137x296.jpeg 137w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/centr-app-hemsworth-218x472.jpeg 218w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/centr-app-hemsworth-37x80.jpeg 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/centr-app-hemsworth-22x48.jpeg 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/centr-app-hemsworth.jpeg 480w&quot; sizes=&quot;auto, (max-width: 473px) 100vw, 473px&quot;&gt;&lt;/figure&gt;
&lt;/div&gt;


&lt;p&gt;Chris Hemsworth &lt;a href=&quot;https://www.forbes.com/sites/pamwindsor/2019/06/14/chris-hemsworth-worked-with-elite-team-of-trainers-to-create-centr-health--fitness-app/&quot;&gt;launched Centr in 2019&lt;/a&gt;, a premium wellness app featuring workouts, meal plans, and mindfulness content from a hand-picked team of elite trainers. It wasn’t just “Thor tells you to do pushups”. It was (is) a genuinely comprehensive fitness platform with cinematic production values. But the reason it could command premium subscription pricing from day one was that Chris Hemsworth’s 60+ million Instagram followers already trusted him on fitness. The app didn’t need to convince anyone that the guy who got jacked for Marvel movies knew something about working out.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://arnoldspumpclub.com/pages/the-pump-club-app&quot;&gt;Arnold Schwarzenegger took a similar approach with the Pump Club app&lt;/a&gt;, packaging 50+ years of fitness expertise into daily workouts, nutrition guidance, and habit-building tools. Conor McGregor’s FAST app sells the same conditioning protocols he uses in fight camps. &lt;/p&gt;



&lt;p&gt;The pattern is clear: take an existing audience that trusts you on a topic, then give them a product that serves that trust. But it’s not just A-list celebrities anymore.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-creator-economy-meets-the-app-economy&quot;&gt;The creator economy meets the app economy&lt;/h2&gt;



&lt;p&gt;The really interesting shift is happening with creators who aren’t household names, but have built dedicated audiences in specific niches.&lt;/p&gt;



&lt;p&gt;Kayla Itsines built her following on Instagram with ‘Bikini Body Guide’ workout programs. When she launched the Sweat app, she had a direct line to millions of people who had already done her workouts via PDF. The app &lt;a href=&quot;https://www.amraandelma.com/influencers-making-millions-from-mobile-apps/&quot;&gt;reportedly sold for around $400 million&lt;/a&gt; in 2021. That’s not celebrity money. That’s creator-to-app-founder money.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;384&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/sweat-app-kayla.png&quot; alt=&quot;&quot; class=&quot;wp-image-49957&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/sweat-app-kayla.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/sweat-app-kayla-300x113.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/sweat-app-kayla-768x288.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/sweat-app-kayla-50x19.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/sweat-app-kayla-107x40.png 107w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/sweat-app-kayla-696x261.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/sweat-app-kayla-560x210.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/sweat-app-kayla-840x315.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/sweat-app-kayla-80x30.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/sweat-app-kayla-48x18.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Likewise, Chloe Ting went viral on YouTube with free workout challenges that racked up hundreds of millions of views. Her app translates those viral programs into structured plans with calendars, timers, and progress tracking. Her 25+ million YouTube subscribers didn’t need to be convinced that her workouts were effective — they’d already sweated through them.&lt;/p&gt;



&lt;p&gt;And then there’s Hank Green.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-when-your-audience-is-your-product-insight&quot;&gt;When your audience IS your product insight&lt;/h2&gt;


&lt;div class=&quot;wp-block-image&quot;&gt;
&lt;figure class=&quot;alignright size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;572&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/focus-friend-app-572x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-49959&quot; style=&quot;aspect-ratio:0.558597538232003;width:321px;height:auto&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/focus-friend-app-572x1024.png 572w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/focus-friend-app-168x300.png 168w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/focus-friend-app-28x50.png 28w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/focus-friend-app-22x40.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/focus-friend-app-259x464.png 259w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/focus-friend-app-313x560.png 313w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/focus-friend-app-165x296.png 165w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/focus-friend-app-264x472.png 264w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/focus-friend-app-45x80.png 45w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/focus-friend-app-27x48.png 27w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/focus-friend-app.png 620w&quot; sizes=&quot;auto, (max-width: 572px) 100vw, 572px&quot;&gt;&lt;/figure&gt;
&lt;/div&gt;


&lt;p&gt;Hank Green (of VlogBrothers, Crash Course, and SciShow fame) launched Focus Friend in 2025: a cozy, gamified focus timer designed to help people with ADHD actually get things done. It features a ‘Bean Friend’ character that focuses when you focus, turning productivity into something closer to a Tamagotchi than a stern Pomodoro timer.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;ttps://www.youtube.com/watch?v=X3ARnEaEbhw&quot;&gt;The app hit #1 in the US App Store&lt;/a&gt;. Above ChatGPT. Above TikTok. Above Instagram.&lt;/p&gt;



&lt;p&gt;What makes Focus Friend interesting isn’t just that Hank Green has millions of followers (he does). It’s that he’s been openly discussing his own ADHD for years. His audience includes a massive number of people who relate to that experience. When he built an app to solve a problem he personally has, he was &lt;em&gt;also &lt;/em&gt;building for an audience that had self-selected around that exact problem.&lt;/p&gt;



&lt;p&gt;This is the real insight: creators don’t just bring distribution. They bring &lt;em&gt;validated demand&lt;/em&gt;. They’ve spent years learning what their audience struggles with; what they want — what they’ll pay for. That’s market research that most app developers would kill for, and creators have it for free.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-two-sided-opportunity&quot;&gt;The two-sided opportunity&lt;/h2&gt;



&lt;p&gt;So what does this mean for you?&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;If you’re a developer&lt;/strong&gt; who can build, but struggles with ideas or distribution, consider this: somewhere out there is a creator with an engaged audience and a problem worth solving, but no technical skills to build the solution. That’s a partnership waiting to happen. You bring the building. They bring the audience and the insight. You both bring the upside.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;If you’re a creator&lt;/strong&gt; sitting on an audience that trusts you, consider this: the technical barrier to building an app has never been lower. You don’t need to learn to code (though you can vibecode easily enough if you want to). You need to identify the problem your audience would pay to solve, then find a builder who can make it real. Or use the new AI tools to prototype something yourself and see if it resonates.&lt;/p&gt;



&lt;p&gt;The best apps in this model aren’t vanity projects or cash grabs. They’re genuine solutions to problems the creator understands deeply because they’ve been talking to (and often experiencing alongside) their audience for years.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-s-next&quot;&gt;What’s next&lt;/h2&gt;



&lt;p&gt;We’ve been thinking a lot about this intersection of creators, builders, and audiences at RevenueCat. The explosion of AI-assisted development tools means more apps will ship in 2026 than ever before. But the apps that break through — the ones that find real users and generate real revenue — will increasingly be the ones that start with distribution and work backward to the product.&lt;/p&gt;



&lt;p&gt;In the meantime, if you’re a developer looking for your next project, maybe spend less time on Product Hunt and more time in the comments of your favorite creators. And if you’re a creator wondering whether an app makes sense for your audience, the answer is probably yes — you just need the right building partner.&lt;/p&gt;



&lt;p&gt;The hard part isn’t building anymore. The hard part is finding something worth building, and people who want it. Turns out, some people have been solving that problem for years. They just didn’t know they were doing app market research the whole time.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-enter-the-shipyard&quot;&gt;Enter the Shipyard&lt;/h2&gt;



&lt;p&gt;Speaking of using creators to find proven audiences… we just might have something to help you in your next app adventure.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Shipyard: Creator Contest &lt;/strong&gt;is an app-building challenge where real influencers enlist you to build, launch, and monetize an MVP app for their audience. In four weeks or less. &lt;/p&gt;



&lt;p&gt;From &lt;strong&gt;January 15, 2026&lt;/strong&gt;, you can get involved in our new hackathon, Shipyard. There’s a $140k prize pool, briefs from influencers with huge follower counts, and the opportunity to build something for a ready-and-waiting audience. &lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.shipyard.fyi/&quot;&gt;Learn more here&lt;/a&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;538&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Teaser-link-preview-1024x538.png&quot; alt=&quot;&quot; class=&quot;wp-image-50049&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Teaser-link-preview-1024x538.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Teaser-link-preview-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Teaser-link-preview-768x403.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Teaser-link-preview-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Teaser-link-preview-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Teaser-link-preview-696x365.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Teaser-link-preview-560x294.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Teaser-link-preview-840x441.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Teaser-link-preview-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Teaser-link-preview-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Teaser-link-preview.png 1200w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;
</content:encoded></item><item><title><![CDATA[How to add subscriptions to a Bolt app]]></title><description><![CDATA[Learn how to monetize the app you created with Bolt using RevenueCat SDK and few lines of code.]]></description><link>https://www.revenuecat.com/blog/engineering/how-to-add-in-app-purchases-to-your-bolt-generated-expo-app/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/how-to-add-in-app-purchases-to-your-bolt-generated-expo-app/</guid><pubDate>Fri, 09 Jan 2026 11:42:34 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/Blog_05_Howto_Bolt.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;In this guide we’re going to look at how to add in-app purchases, meaning simple monthly and yearly subscriptions, into an app we have created with &lt;a href=&quot;https://bolt.new/&quot;&gt;Bolt&lt;/a&gt;. We’ll also add a paywall to monetize part of the content in the app, and implement logic for checking whether the user is eligible to access content.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;We are first going to create our project with Bolt, then you can start making your own changes to the apps. In this guide we’ll build an app that works on both iOS and Android, but you can of course choose to build for only one of those platforms if you prefer. Our example app is &lt;a href=&quot;https://github.com/plahteenlahti/Bolt-with-RevenueCat&quot;&gt;from this repository.&lt;/a&gt;&lt;/p&gt;


&lt;div class=&quot;lazyblock-dcadc5d83064-Za24rp wp-block-lazyblock-dcadc5d83064&quot;&gt;&lt;blogposthowtostep level=&quot;h2&quot; title=&quot;Step 1: Create your Bolt app with prompts&quot; summary=&quot;Creates a Bolt app with built-in UI and code for handling subscriptions using RevenueCat’s React Native SDK. The app runs in Expo Go, where in-app purchase functionality is mocked via Preview API Mode. &quot; image-url=&quot;&quot;&gt;
&lt;/blogposthowtostep&gt;&lt;/div&gt;


&lt;p&gt;As the first step let’s open &lt;a href=&quot;https://bolt.new/&quot;&gt;bolt.new&lt;/a&gt; and give the following prompt to get things started:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Up8aU wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;I&apos;m building a mobile app for browsing cat pictures. The app should have two tabs: Feed and Profile.\n\nIn the Feed tab:\n- Display a vertical scrollable list of 15 cat images.\n- Only the first 2 images should be fully visible. The remaining 13 images must have a semi-transparent overlay with the text:\n\&amp;quot;Subscribe to unlock\&amp;quot; centered over the image.\n- Tapping on a locked image should present a RevenueCat paywall screen, built using react-native-purchases-ui.\n- Install react-native-purchases using version 8.11.4 or higher, and also install react-native-purchases-ui using version 8.11.4\n- Use the Paywall component from react-native-purchases-ui to display and handle the subscription purchase.\n- The product shown must include 1_month_subscription_ios in the offering.\n- Do not create a custom purchase button or product card UI; rely on the RevenueCat-provided Paywall component entirely.\n\nHooks and Logic:\n- Create and export a custom hook called initializePurchases that configures the RevenueCat SDK using the actual Purchases.configure() method. Use this hook in _layout.tsx.\n- Create and export a hook called useSubscriptionStatus that checks the user&apos;s subscription status using Purchases.getCustomerInfo() and entitlements logic. Return a boolean isSubscribed value.\n- Do not mock the purchase or subscription logic; use the real RevenueCat methods.\n- Use the useSubscriptionStatus hook in both Feed and Profile tabs to show\/hide locked content and reflect subscription status.\n\nIn the Profile tab:\n- Show a simple message based on subscription state (e.g., \&amp;quot;You are subscribed\&amp;quot; \/ \&amp;quot;Not subscribed\&amp;quot;) using useSubscriptionStatus.\n\nAdditional Constraints:\n- Do not include installation instructions or unrelated boilerplate.\n- Avoid backend integration or persistent storage; rely on RevenueCat SDK only.\n- Keep code modular with well-named components for Feed, Profile, OverlayedImage.\n- Ensure the app runs in Expo Go, only use libraries that are compatible with it.\n- Do not implement any manual purchasing UI or fallback logic. The react-native-purchases-ui Paywall must handle the full purchase flow.&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-why-not-just-add-subscriptions-as-part-of-the-prompt&quot;&gt;Why not just add subscriptions as part of the prompt?&lt;/h3&gt;



&lt;p&gt;This prompt should provide you a working app that has all the UI parts and code necessary for handling subscriptions. If you navigate around the application, you’ll notice that everything appears functional, and even the subscription logic is already in place. However, when you press the ‘subscribe’ button, nothing happens. &lt;/p&gt;



&lt;p&gt;You might have noticed that the prompt includes the &lt;code&gt;react-native-purchases&lt;/code&gt; package. This is RevenueCat’s React Native SDK, required for enabling in-app purchases. The reason subscriptions still don’t work at this stage is because Bolt uses an app called &lt;a href=&quot;https://expo.dev/go&quot;&gt;Expo Go&lt;/a&gt; to preview your app. Expo Go is a prebuilt preview app that comes bundled with a fixed set of native modules. These allow for rich interactions with native code — like building advanced UIs or accessing the camera — but they don’t include the native modules required for in-app purchases.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-how-revenuecat-s-sdk-solves-this&quot;&gt;How RevenueCat’s SDK solves this&lt;/h3&gt;



&lt;p&gt;To address this limitation, &lt;code&gt;react-native-purchases&lt;/code&gt; automatically detects when it’s running in Expo Go. When Expo Go is detected, the SDK enters &lt;a href=&quot;https://www.revenuecat.com/docs/getting-started/installation/expo&quot;&gt;Preview API Mode&lt;/a&gt;. In this mode, all native calls are replaced with mock APIs. While this means subscriptions won’t actually function in the preview, the integration won’t break either. Instead, you can safely navigate your app and verify that your subscription-related logic is wired up correctly, without interrupting your development flow.&lt;/p&gt;



&lt;p&gt;At this point, you have a fully-functional app created with Bolt, including subscription logic and the RevenueCat SDK. All features should work as expected — except for actual subscription flows, which require native modules not available in Expo Go. You can continue using Bolt to build and enhance your app. Once you’re happy with the result, proceed to the next section to learn how to deploy your app using Expo Application Services (EAS), which will enable full subscription functionality.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-testing-with-test-store&quot;&gt;Testing with Test Store&lt;/h3&gt;



&lt;p&gt;RevenueCat also has a built-in testing environment that works immediately without platform setup, called &lt;a href=&quot;https://www.revenuecat.com/docs/test-and-launch/sandbox/test-store&quot;&gt;Test Store&lt;/a&gt;. Setting up Test Store does not need any additional configuration, the only requirement is using a Test Store API key. Test purchases made through Test Store behave like real purchases and subscriptions and allow you to build your app logic around subscriptions without having to configure App Store and Google Play subscriptions. Test Store also works on Expo Go.&lt;/p&gt;



&lt;p&gt;We won’t cover Test store in this blog post, but it’s worth considering if you’re still testing out your app idea, and don’t want to spend time on setting up different stores before your app and subscription logic is fully built. &lt;/p&gt;


&lt;div class=&quot;lazyblock-dcadc5d83064-Z1GsUJ3 wp-block-lazyblock-dcadc5d83064&quot;&gt;&lt;blogposthowtostep level=&quot;h2&quot; title=&quot;Step 2: Switch from Expo Go to EAS Build&quot; summary=&quot;Configures the app for native code by transitioning from Expo Go to EAS Build, enabling support for RevenueCat’s react-native-purchases SDK. Involves downloading the Bolt project, setting up dependencies, and following Expo’s official EAS integration steps. &quot; image-url=&quot;&quot;&gt;
&lt;/blogposthowtostep&gt;&lt;/div&gt;


&lt;p&gt;Now that our app has the basic UI for subscriptions in place, we can integrate the actual subscription logic using the &lt;a href=&quot;https://docs.revenuecat.com/docs/react-native&quot;&gt;react-native-purchases&lt;/a&gt; SDK from RevenueCat. Since the SDK includes native code, and our app uses Expo, we need to configure it to work with EAS Build, Expo’s custom build service.&lt;/p&gt;



&lt;p&gt;To get started, download the project you have created with Bolt to your computer and open it in your IDE of your choice (e.g. VS Code, Cursor). You will also need the command line, so open that and navigate to your project folder to run the following command:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-C1Qoq wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;npm install&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This will install the depencies of your app.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-prepare-expo-for-native-modules&quot;&gt;Prepare Expo for native modules&lt;/h3&gt;



&lt;p&gt;To enable native code in an Expo project, we need to switch from Expo Go to EAS Build. This is required for &lt;code&gt;react-native-purchases&lt;/code&gt; and any other library that depends on native modules.&lt;/p&gt;



&lt;p&gt;Follow the &lt;a href=&quot;https://support.bolt.new/integrations/expo&quot;&gt;official Bolt Expo integration guide&lt;/a&gt; to configure your app. The key steps are:&lt;/p&gt;



&lt;p&gt;1. Install eas-cli if you haven’t already: &amp;nbsp;&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1ubqFo wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;npm install -g eas-cli&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;2. Log in and configure the project:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-218HQV wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;eas login\neas build:configure&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;3. Once configured, use eas build instead of expo start to build your project for iOS or Android:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZzVQYE wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;eas build -platform android \n\/\/ or\neas build -platform ios&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This will create a production build of your application that you can then submit to the app stores. If you run into any errors or need additional support, check out &lt;a href=&quot;https://docs.expo.dev/tutorial/eas/android-production-build/&quot;&gt;Expo’s guide for creating production builds for Android&lt;/a&gt; and their &lt;a href=&quot;https://docs.expo.dev/tutorial/eas/ios-production-build/&quot;&gt;guide for creating production iOS builds&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;We now have a working production version of our app for Android and iOS that we can start adding subscriptions to. Before we do that we need to set up Google Play Console, App Store Connect, and RevenueCat, connect these three, then add products for our users to purchase.&lt;/p&gt;


&lt;div class=&quot;lazyblock-dcadc5d83064-ZfyXbX wp-block-lazyblock-dcadc5d83064&quot;&gt;&lt;blogposthowtostep level=&quot;h2&quot; title=&quot;Step 3: Set Up Products in apps stores and RevenueCat&quot; summary=&quot;Sets up in-app subscriptions by configuring products in Google Play Console and App Store Connect, and linking both platforms to RevenueCat. Guides through creating developer accounts, setting up service credentials, and importing products into RevenueCat. &quot; image-url=&quot;&quot;&gt;
&lt;/blogposthowtostep&gt;&lt;/div&gt;


&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;540&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/Screenshot-2026-01-07-at-12.00.03-1024x540.png&quot; alt=&quot;Screenshot of the different integrations RevenueCat offers: Google Play Store, App Store, Amazon Store.&quot; class=&quot;wp-image-49939&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/Screenshot-2026-01-07-at-12.00.03-1024x540.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/Screenshot-2026-01-07-at-12.00.03-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/Screenshot-2026-01-07-at-12.00.03-768x405.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/Screenshot-2026-01-07-at-12.00.03-1536x809.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/Screenshot-2026-01-07-at-12.00.03-2048x1079.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/Screenshot-2026-01-07-at-12.00.03-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/Screenshot-2026-01-07-at-12.00.03-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/Screenshot-2026-01-07-at-12.00.03-696x367.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/Screenshot-2026-01-07-at-12.00.03-560x296.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/Screenshot-2026-01-07-at-12.00.03-840x443.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/Screenshot-2026-01-07-at-12.00.03-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/Screenshot-2026-01-07-at-12.00.03-48x25.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Before we work on enabling subscriptions for our app, let’s set up RevenueCat and configure our products.&lt;/p&gt;



&lt;p&gt;Start by creating a new RevenueCat account at &lt;a href=&quot;http://revenuecat.com&quot;&gt;revenuecat.com&lt;/a&gt; for free.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-connect-revenuecat-to-google-play-store&quot;&gt;Connect RevenueCat to Google Play Store&lt;/h3&gt;



&lt;p&gt;Start by connecting your Google Play account to the RevenueCat dashboard, which will allow RevenueCat’s servers to communicate with Google Play Store on your behalf. To do this we need to provide RevenueCat with a set of service credentials. The process for configuring all of these is a bit complex, but this is all done to keep security high by only granting necessary access to RevenueCat.&lt;/p&gt;



&lt;p&gt;To get access to the Google Play console, where all your distributed apps will live, you need to sign up for a Google Play developer account, which currently costs a one time fee of $25. Learn more about setting up a Play Console developer account from &lt;a href=&quot;https://support.google.com/googleplay/android-developer/answer/6112435&quot;&gt;Google’s official documentation&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;Once you’ve set up your Play Console account, follow &lt;a href=&quot;https://www.revenuecat.com/docs/projects/connect-a-store&quot;&gt;RevenueCat’s guide to connect Google Play console and RevenueCat&lt;/a&gt;.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-configure-google-play-with-products&quot;&gt;Configure Google Play with Products&lt;/h3&gt;



&lt;p&gt;With our RevenueCat account connected to the Google Play Store, we’re now ready to configure in-app subscriptions for our app. First, log into &lt;a href=&quot;https://play.google.com/console&quot;&gt;Google Play Console&lt;/a&gt;, select your application, and navigate to Monetize &amp;gt; Products &amp;gt; Subscriptions in the sidebar.&lt;/p&gt;



&lt;p&gt;Click the &lt;strong&gt;Create subscription&lt;/strong&gt; button and configure your pricing and billing periods (e.g., monthly and yearly). Be sure to take note of the &lt;strong&gt;Product ID&lt;/strong&gt; for each subscription — you’ll need this when connecting your app to RevenueCat.&lt;/p&gt;



&lt;p&gt;For more detailed information follow our &lt;a href=&quot;https://www.revenuecat.com/docs/getting-started/entitlements/android-products&quot;&gt;Google Play product setup guide&lt;/a&gt;.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-connect-revenuecat-to-app-store-connect&quot;&gt;Connect RevenueCat to App Store Connect&lt;/h3&gt;



&lt;p&gt;To set up products for iOS, iPadOS, macOS, tvOS, and watchOS, start by logging into&amp;nbsp;&lt;a href=&quot;https://appstoreconnect.apple.com/&quot;&gt;App Store Connect&lt;/a&gt;. App Store Connect is Apple’s central hub for managing app releases, TestFlight, in-app purchases, and more.&amp;nbsp;To do this you need an Apple Developer account, which costs $99 a year.&lt;/p&gt;



&lt;p&gt;Once you’ve set up your App Store Connect account, follow &lt;a href=&quot;https://www.revenuecat.com/docs/projects/connect-a-store&quot;&gt;RevenueCat’s guide on connecting App Store Connect and RevenueCat&lt;/a&gt;.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-configure-app-store-connect-with-products&quot;&gt;Configure App Store Connect with Products&lt;/h3&gt;



&lt;p&gt;Navigate to your app and in the left navigation column under monetization select the &lt;em&gt;Subscriptions&lt;/em&gt; section. Here you can define your subscriptions for your app. You need to app a new subscription group, then create a new subscription and include the subscription in the previously created group.&lt;/p&gt;



&lt;p&gt;For more detailed information follow our &lt;a href=&quot;https://www.revenuecat.com/docs/getting-started/entitlements/ios-products&quot;&gt;iOS product setup guide&lt;/a&gt;.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-import-products-into-revenuecat&quot;&gt;&lt;strong&gt;Import Products into RevenueCat&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Now that your subscription products are live in both app stores, head back to the &lt;strong&gt;RevenueCat dashboard&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;Navigate to your project’s &lt;strong&gt;Products&lt;/strong&gt; tab and click &lt;strong&gt;+ New &amp;gt; Import Products&lt;/strong&gt;. RevenueCat will automatically fetch your available subscriptions from Google Play and App Store Connect. Select the ones you want to import and click &lt;strong&gt;Import&lt;/strong&gt;. Your subscriptions will now appear in your RevenueCat project, ready to use.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-create-an-offering&quot;&gt;&lt;strong&gt;Create an Offering&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Offerings in RevenueCat are how you define which products to show in your app. This makes it easy to test pricing, paywalls, and product combinations, all without needing to update your app.&lt;/p&gt;



&lt;p&gt;Go to the &lt;strong&gt;Offerings&lt;/strong&gt; tab and click &lt;strong&gt;+ New&lt;/strong&gt; to create your first offering. You’ll assign the products (like your monthly and yearly subscriptions) to this offering, which your app will reference when displaying a paywall.&lt;/p&gt;



&lt;p&gt;Follow the steps in &lt;a href=&quot;https://www.revenuecat.com/docs/offerings&quot;&gt;RevenueCat’s Offering documentation&lt;/a&gt; to complete setup.&lt;/p&gt;



&lt;p&gt;You should now have RevenueCat, Google Play Console, and App Store connect configured with subscriptions. Before continuing with the guide, navigate to the API keys section of RevenueCat dashboard and copy the Android and iOS SDK keys. We will need these in the next step to connect our app to RevenueCat.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-create-a-paywall&quot;&gt;Create a paywall&lt;/h3&gt;



&lt;p&gt;RevenueCat has paywall builder that allows you to remotely configure your entire paywall without any code changes or app updates. You can use paywalls to display different offerings and your app can multiple different types of paywalls. You can also test how paywalls perform with RevenueCat Experiments.&lt;/p&gt;



&lt;p&gt;We are going to add a simple paywall to show our possible subscription options. You can find the Paywalls RevenueCat dashboard in your project’s Monetization tools section. Pick from the pre-made paywall templates or make a fully custom one, and choose the offering you created in the previous sections. Once you are happy with the changes hit ‘publish’ to make the paywall available for your app. &lt;a href=&quot;https://www.youtube.com/watch?v=mPzCTxIlMXE&quot;&gt;Learn more about RevenueCat Paywalls in our overview video&lt;/a&gt;.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;485&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/Screenshot-2026-01-07-at-12.01.49-1024x485.png&quot; alt=&quot;Screenshot of RevenueCat Paywalls &quot; class=&quot;wp-image-49941&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/Screenshot-2026-01-07-at-12.01.49-1024x485.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/Screenshot-2026-01-07-at-12.01.49-300x142.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/Screenshot-2026-01-07-at-12.01.49-768x364.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/Screenshot-2026-01-07-at-12.01.49-1536x728.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/Screenshot-2026-01-07-at-12.01.49-2048x971.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/Screenshot-2026-01-07-at-12.01.49-50x24.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/Screenshot-2026-01-07-at-12.01.49-84x40.png 84w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/Screenshot-2026-01-07-at-12.01.49-696x330.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/Screenshot-2026-01-07-at-12.01.49-560x265.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/Screenshot-2026-01-07-at-12.01.49-840x398.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/Screenshot-2026-01-07-at-12.01.49-80x38.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/Screenshot-2026-01-07-at-12.01.49-48x23.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;


&lt;div class=&quot;lazyblock-dcadc5d83064-Z26TSRL wp-block-lazyblock-dcadc5d83064&quot;&gt;&lt;blogposthowtostep level=&quot;h2&quot; title=&quot;Step 4: Install and Configure RevenueCat&quot; summary=&quot;Verifies the installation of react-native-purchases and react-native-purchases-ui SDKs in the project, ensuring version 8.11.4 or higher. If needed, installs or updates the SDKs. Then initializes the RevenueCat SDK in the app, typically within _layout.tsx, using the API keys from the previous step to enable communication with RevenueCat’s backend &quot; image-url=&quot;&quot;&gt;
&lt;/blogposthowtostep&gt;&lt;/div&gt;


&lt;p&gt;The prompt from before should have installed both &lt;code&gt;react-native-purchases &lt;/code&gt;and&lt;code&gt; react-native-purchases-ui&lt;/code&gt; in both already. Verify this by checking that the &lt;code&gt;package.json&lt;/code&gt; file has the lines below:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-25xSoC wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;\&amp;quot;dependencies\&amp;quot;: {\n    ....other dependencies...\n    \&amp;quot;react-native-purchases\&amp;quot;: \&amp;quot;^8.11.4\&amp;quot;,\n    \&amp;quot;react-native-purchases-ui\&amp;quot;: \&amp;quot;^8.11.4\&amp;quot;,\n  },&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The versions should be 8.11.4 or higher. If either of these are missing or the version are lower than the mentioned, install the RevenueCat SDKs, by running:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-10gYVI wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;npx expo install react-native-purchases@8.11.4\nnpx expo install react-native-purchases-ui@8.11.4&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-initialize-the-revenuecat-sdk&quot;&gt;Initialize the RevenueCat SDK&lt;/h3&gt;



&lt;p&gt;You can now initialize RevenueCat in your app. This is typically done once when your app starts. Creating our app with Bolt created a commented section where to place the following code parts in our app. Most likely it is in a file called&lt;code&gt; _layout.tsx&lt;/code&gt;&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z24cNIL wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;export function initializePurchases() {\n  useEffect(() =&gt; {\n    const initRevenueCat = async () =&gt; {\n      try {\n        \/\/ Replace with your RevenueCat API key\n        const apiKey = Platform.select({\n          ios: &apos;your_ios_api_key_here&apos;,\n          android: &apos;your_android_api_key_here&apos;,\n          default: &apos;your_ios_api_key_here&apos;,\n        });\n\n        if (apiKey) {\n          await Purchases.configure({ apiKey });\n          console.log(&apos;RevenueCat initialized successfully&apos;);\n        }\n      } catch (error) {\n        console.error(&apos;Failed to initialize RevenueCat:&apos;, error);\n      }\n    };\n\n    initRevenueCat();\n  }, []);\n}\n\n\n\/\/ in _layout.tsx\n\nexport default function RootLayout() {\n  useFrameworkReady();\n  initializePurchases();\n\n  return (\n    &lt;&gt;\n      &lt;Stack screenOptions={{ headerShown: false }}&gt;\n        &lt;Stack.Screen name=\&amp;quot;(tabs)\&amp;quot; options={{ headerShown: false }} \/&gt;\n        &lt;Stack.Screen name=\&amp;quot;+not-found\&amp;quot; \/&gt;\n      &lt;\/Stack&gt;\n      &lt;StatusBar style=\&amp;quot;auto\&amp;quot; \/&gt;\n    &lt;\/&gt;\n  );\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Paste the API keys you copied in the previous section of this guide into the apiKey part. This enables your app to interact with RevenueCat’s servers.&lt;/p&gt;


&lt;div class=&quot;lazyblock-dcadc5d83064-Zms8fH wp-block-lazyblock-dcadc5d83064&quot;&gt;&lt;blogposthowtostep level=&quot;h2&quot; title=&quot;Step 5: Add purchase logic to the UI&quot; summary=&quot;Implements subscription-aware UI by checking active entitlements using getCustomerInfo() and reflecting subscription status in the Feed and Profile tabs. Enhances the paywall screen to display product offerings and handle purchase flows via RevenueCat. Updates the OverlayImage component to restrict content based on subscription status&quot; image-url=&quot;&quot;&gt;
&lt;/blogposthowtostep&gt;&lt;/div&gt;


&lt;p&gt;To check if the user has an active subscription, query getCustomerInfo() and look for an active entitlement:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-zt7KH wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;\nexport function useSubscriptionStatus() {\n  const [isSubscribed, setIsSubscribed] = useState(false);\n  const [isLoading, setIsLoading] = useState(true);\n\n  useEffect(() =&gt; {\n    const checkSubscriptionStatus = async () =&gt; {\n      try {\n        const customerInfo = await Purchases.getCustomerInfo();\n        const isActive = customerInfo.entitlements.active[&apos;premium&apos;] !== undefined;\n        setIsSubscribed(isActive);\n      } catch (error) {\n        console.error(&apos;Failed to check subscription status:&apos;, error);\n        setIsSubscribed(false);\n      } finally {\n        setIsLoading(false);\n      }\n    };\n\n    checkSubscriptionStatus();\n\n    \/\/ Set up listener for purchase updates\n    Purchases.addCustomerInfoUpdateListener(checkSubscriptionStatus);\n\n    return () =&gt; {\n      Purchases.removeCustomerInfoUpdateListener(checkSubscriptionStatus);\n    };\n  }, []);\n\n  return { isSubscribed, isLoading };\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Use this in both the Feed and Profile tabs to reflect the user’s subscription status.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-implement-the-paywall-logic&quot;&gt;Implement the paywall logic&lt;/h3&gt;



&lt;p&gt;Now we can update the paywall screen to show available offerings and handle purchases:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZEAlYI wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;\/\/... in index.tsx\n\nexport default function Feed() {\n  const { isSubscribed, isLoading } = useSubscriptionStatus();\n\n  if (isLoading) {\n    return (\n      &lt;SafeAreaView style={styles.container}&gt;\n        &lt;View style={styles.loadingContainer}&gt;\n          &lt;Text style={styles.loadingText}&gt;Loading...&lt;\/Text&gt;\n        &lt;\/View&gt;\n      &lt;\/SafeAreaView&gt;\n    );\n  }\n\n  return (\n    &lt;SafeAreaView style={styles.container}&gt;\n      &lt;View style={styles.header}&gt;\n        &lt;Text style={styles.headerTitle}&gt;Cats Feed&lt;\/Text&gt;\n        {isSubscribed &amp;amp;&amp;amp; (\n          &lt;Text style={styles.subscriptionBadge}&gt;Premium&lt;\/Text&gt;\n        )}\n      &lt;\/View&gt;\n      \n      &lt;ScrollView \n        style={styles.scrollView}\n        contentContainerStyle={styles.scrollContent}\n        showsVerticalScrollIndicator={false}\n      &gt;\n        {catImages.map((imageUrl, index) =&gt; {\n          const isLocked = !isSubscribed &amp;amp;&amp;amp; index &gt;= 2;\n          return (\n            &lt;OverlayedImage\n              key={index}\n              imageUrl={imageUrl}\n              isLocked={isLocked}\n              onPress={() =&gt; console.log(`Viewing cat image ${index + 1}`)}\n            \/&gt;\n          );\n        })}\n      &lt;\/ScrollView&gt;\n    &lt;\/SafeAreaView&gt;\n  );\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This fetches the product offerings from RevenueCat and initiates a purchase flow. After a successful purchase, the entitlement is checked and the paywall is dismissed if the subscription is active.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-update-the-overlayimage-component&quot;&gt;Update the OverlayImage component &lt;/h3&gt;



&lt;p&gt;Finally, use the isLocked value in your OverlayImage component to lock or unlock content:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZfsXFT wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;export default function OverlayedImage({ imageUrl, isLocked, onPress }: OverlayedImageProps) {\n\n  const handlePress = async () =&gt; {\n    if (isLocked) {\n      await RevenueCatUI.presentPaywall();\n    } else if (onPress) {\n      onPress();\n    }\n  };\n\n  return (\n    &lt;View style={styles.container}&gt;\n      &lt;TouchableOpacity onPress={handlePress} style={styles.imageContainer}&gt;\n        &lt;Image source={{ uri: imageUrl }} style={styles.image} \/&gt;\n        {isLocked &amp;amp;&amp;amp; (\n          &lt;View style={styles.overlay}&gt;\n            &lt;Text style={styles.overlayText}&gt;Subscribe to unlock&lt;\/Text&gt;\n          &lt;\/View&gt;\n        )}\n      &lt;\/TouchableOpacity&gt;\n    &lt;\/View&gt;\n  );\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This ensures that only subscribed users can access the full list of cat pictures.&lt;br&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-wrapping-up&quot;&gt;Wrapping up&lt;/h2&gt;



&lt;p&gt;With the RevenueCat and Google Play Console set up, the RevenueCat SDK integrated, and the necessary code changes made to the Bolt-created app, our app is now ready to accept and react to users subscribing. You’ll now want to create a new EAS build of your app; once the build finishes processing, test your app and the subscriptions. If you run into any problems, check that you have placed the code provided in the correct places. &lt;/p&gt;



&lt;p&gt;These guides can also help you:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://support.bolt.new/integrations/expo#deploying-android-app&quot;&gt;Using Bolt with Expo to create mobile apps&lt;/a&gt;, covers everything you need to deploy new versions of your app&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/getting-started/installation/expo&quot;&gt;RevenueCat’s updated guide to working with Expo&lt;/a&gt;, if you want to dive deeper into integrating your app with RevenueCat&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/engineering/the-ultimate-guide-to-android-subscription-testing/&quot;&gt;The ultimate guide to Android subscription testing&lt;/a&gt;, RevenueCat’s guide to testing Android subscriptions.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Building animated custom Paywalls in Jetpack Compose]]></title><description><![CDATA[In this article, you'll explore how to build sophisticated "Day & Night" animated paywalls in Jetpack Compose.]]></description><link>https://www.revenuecat.com/blog/engineering/custom-paywalls-compose/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/custom-paywalls-compose/</guid><pubDate>Fri, 09 Jan 2026 01:00:31 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/Blog_10_BuildingAnimatedPaywalls.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Paywalls are the critical touchpoint between your app and revenue. While pre-built templates can get you started quickly, there are compelling reasons to build custom paywalls that match your brand identity and create memorable user experiences. An animated paywall that responds to user context, like one that transitions between day and night themes, can create an emotional connection that static templates simply cannot achieve. The psychological impact of a well-crafted paywall extends beyond mere aesthetics; it signals to users that your app is polished, professional, and worth their investment.&lt;/p&gt;



&lt;p&gt;In this article, you’ll explore how to build sophisticated animated paywalls in Jetpack Compose. We’ll dive deep into a “Day &amp;amp; Night” paywall implementation, examining each animation technique step by step. You’ll also learn how to use Firebase for agile A/B testing of your custom paywall content, and discover when RevenueCat’s Paywall Builder might be the better choice. By the end, you’ll have a complete understanding of when and how to build custom paywalls that convert.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-building-custom-paywalls-day-amp-night-deep-dive&quot;&gt;&lt;strong&gt;Building custom paywalls: Day &amp;amp; Night deep dive&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Let’s examine a production-quality animated paywall that transitions between day and night themes on a 16-second cycle. This implementation demonstrates several advanced Compose animation techniques working together harmoniously. The paywall creates an immersive environment that changes dynamically, with the sun rising and setting, stars twinkling into view, clouds drifting across the sky, and UI elements adapting their colors to match the time of day. This continuous cycle captures attention and creates emotional engagement that static paywalls cannot achieve.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1561&quot; height=&quot;925&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/7.gif&quot; alt=&quot;&quot; class=&quot;wp-image-50037&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;architecture-overview&quot;&gt;&lt;strong&gt;Architecture overview&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The Day &amp;amp; Night paywall follows a layered architecture that separates concerns cleanly. At the foundation sits the &lt;code&gt;DayNightBackground&lt;/code&gt; composable, which handles all environmental animations including the sky gradient transitions, the procedurally generated star field with individual twinkling behaviors, the sun and moon following arc trajectories across the sky, a parallax cloud layer that drifts continuously, and a landscape gradient that grounds the scene.&lt;/p&gt;



&lt;p&gt;Above this animated background, the content overlay presents the actual paywall information: a greeting that crossfades between “GOOD MORNING” and “GOOD EVENING” based on the cycle, a feature list with animated checkmarks whose colors shift with the day/night state, price display with an animated accent color, and a call-to-action button that transitions between warm golden tones during the day and cool indigo at night.&lt;/p&gt;



&lt;p&gt;This layered architecture provides several benefits. The background animation logic remains isolated from the content presentation, making both easier to modify independently. The background can be reused in other contexts if needed, and the content layer can be updated without touching the complex animation code. This separation also improves performance by allowing Compose to optimize recomposition independently for each layer.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;setting-up-the-animation-cycle&quot;&gt;&lt;strong&gt;Setting up the animation cycle&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The entire paywall is driven by a single cycleProgress value that loops from 0 to 1 over 16 seconds. This duration was chosen carefully, long enough to appreciate the transitions without feeling rushed, but short enough that users experience the full cycle during a typical paywall viewing session:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z2rUj2P wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Composable\nfun DayNightPaywallScreen(onDismiss: () -&gt; Unit = {}) {\n    val paywallState = rememberPaywallState(onPurchaseSuccess = onDismiss)\n    val infiniteTransition = rememberInfiniteTransition(label = \&amp;quot;daynight\&amp;quot;)\n\n    val cycleProgress by infiniteTransition.animateFloat(\n        initialValue = 0f,\n        targetValue = 1f,\n        animationSpec = infiniteRepeatable(\n            animation = tween(16000, easing = LinearEasing),\n            repeatMode = RepeatMode.Restart,\n        ),\n        label = \&amp;quot;cycle\&amp;quot;,\n    )\n\n    val isDay = cycleProgress &lt; 0.5f\n    \/\/ ...\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This pattern is important for complex animations: &lt;strong&gt;use a single progress value as the source of truth, then derive all other animations from it&lt;/strong&gt;. This ensures perfect synchronization and makes the animation easy to reason about. When multiple animations need to coordinate, as they do in this paywall, having a single driver eliminates timing drift and makes the relationship between elements explicit.&lt;/p&gt;



&lt;p&gt;The &lt;code&gt;LinearEasing&lt;/code&gt; choice is deliberate. For a continuous cycle representing time passing, linear progression feels most natural. Non-linear easing would make certain parts of the day feel faster or slower than others, which would break the metaphor. The &lt;code&gt;RepeatMode.Restart&lt;/code&gt; ensures the cycle loops seamlessly from midnight back to sunrise.&lt;/p&gt;



&lt;p&gt;The cycle splits into two phases. The day phase spans from 0.0 to 0.5, during which the sun rises, crosses the sky, and sets. The night phase covers 0.5 to 1.0, when the moon performs the same journey. This symmetrical division creates a balanced experience where users spend equal time in day and night modes, maximizing exposure to both visual treatments.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;implementing-the-animated-background&quot;&gt;&lt;strong&gt;Implementing the animated background&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The &lt;code&gt;DayNightBackground&lt;/code&gt; composable handles all environmental animations. This is where the magic happens, transforming a simple progress value into a living, breathing scene. Let’s break down each layer and understand how they work together.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;procedural-star-generation&quot;&gt;&lt;strong&gt;Procedural star generation&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Stars are generated once and remembered, with randomized properties for natural variation. The procedural approach means every session produces a unique star field, adding subtle variety to the experience:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1r4i3u wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;data class NightStar(\n    val x: Float,\n    val y: Float,\n    val size: Float,\n    val twinklePhase: Float,\n    val twinkleSpeed: Float,\n)\n\n@Composable\nfun DayNightBackground(cycleProgress: Float, modifier: Modifier = Modifier) {\n    val stars = remember {\n        List(60) {\n            NightStar(\n                x = Random.nextFloat(),\n                y = Random.nextFloat() * 0.6f,  \/\/ Upper 60% of sky only\n                size = Random.nextFloat() * 2f + 1f,\n                twinklePhase = Random.nextFloat() * PI.toFloat() * 2f,\n                twinkleSpeed = Random.nextFloat() * 2f + 1f,\n            )\n        }\n    }\n    \/\/ ...\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Each star has its own twinkle phase and speed, ensuring they don’t twinkle in unison. This desynchronization is critical for realism, synchronized twinkling would look artificial and mechanical. The y coordinate is capped at 0.6 to keep stars in the upper portion of the sky where they belong, preventing stars from appearing in the landscape area at the bottom of the screen.&lt;/p&gt;



&lt;p&gt;The 60-star count balances visual density with performance. Fewer stars would make the night sky feel sparse, while significantly more could impact rendering performance on lower-end devices. The size range of 1 to 3 pixels (from &lt;code&gt;Random.nextFloat() * 2f + 1f&lt;/code&gt;) creates a sense of depth, with smaller stars appearing more distant.&lt;/p&gt;



&lt;p&gt;The &lt;code&gt;remember&lt;/code&gt; block ensures stars are generated only once per composition, maintaining consistency as the paywall cycles. Without this, stars would regenerate on every recomposition, creating a chaotic flickering effect.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;frame-accurate-delta-time&quot;&gt;&lt;strong&gt;Frame-accurate delta time&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;For smooth animations independent of frame rate, we track actual elapsed time. This technique is fundamental to professional-quality animation and ensures consistent behavior across devices with varying performance characteristics:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-iSQvm wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;var totalTime by remember { mutableFloatStateOf(0f) }\nvar lastFrameTimeNanos by remember { mutableLongStateOf(0L) }\n\nLaunchedEffect(Unit) {\n    while (true) {\n        withFrameNanos { frameTimeNanos -&gt;\n            val deltaTime = if (lastFrameTimeNanos == 0L) {\n                0.016f  \/\/ Assume 60fps for first frame\n            } else {\n                ((frameTimeNanos - lastFrameTimeNanos) \/ 1_000_000_000f)\n                    .coerceIn(0f, 0.1f)  \/\/ Cap to prevent jumps\n            }\n            lastFrameTimeNanos = frameTimeNanos\n            totalTime += deltaTime\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This approach has two benefits. First, animations remain smooth regardless of device performance, a device running at 30fps will show the same animation speed as one running at 120fps. Second, animation speed is consistent across devices, so users see the same experience whether they’re on budget hardware or flagship phones.&lt;/p&gt;



&lt;p&gt;The &lt;code&gt;coerceIn(0f, 0.1f)&lt;/code&gt; prevents animation jumps when the app returns from background. Without this cap, the delta time could be several seconds if the app was suspended, causing jarring jumps in continuous animations like cloud movement. By capping at 0.1 seconds (100ms), we ensure smooth recovery even after brief suspensions.&lt;/p&gt;



&lt;p&gt;The &lt;code&gt;withFrameNanos&lt;/code&gt; function is key here, it suspends until the next frame and provides the precise frame timestamp in nanoseconds. This is more accurate than alternatives like &lt;code&gt;delay()&lt;/code&gt; which can accumulate timing errors over long running animations.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;multi-phase-sky-gradients&quot;&gt;&lt;strong&gt;Multi-phase sky gradients&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The sky transitions through eight distinct color phases, creating a believable progression from dawn through day through dusk through night and back. Each phase uses a three-color gradient to add depth to the sky:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z2t8EN3 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;val sunriseColors = listOf(Color(0xFFFF8C42), Color(0xFFFFD700), Color(0xFFFFF4E0))\nval dayColors = listOf(Color(0xFF4A90D9), Color(0xFF87CEEB), Color(0xFFB8E0F0))\nval sunsetColors = listOf(Color(0xFFFF6B35), Color(0xFFFFAB5E), Color(0xFFFFD89E))\nval duskColors = listOf(Color(0xFF2C3E50), Color(0xFF34495E), Color(0xFF5D6D7E))\nval nightColors = listOf(Color(0xFF0D1B2A), Color(0xFF1B263B), Color(0xFF2C3E50))\nval dawnColors = listOf(Color(0xFF1A1A2E), Color(0xFF16213E), Color(0xFF1F4068))&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The color choices are intentional and based on observation of real skies. Sunrise features warm oranges and golds, transitioning through the top of the gradient to paler tones. Day uses familiar sky blues with lighter tones toward the horizon. Sunset intensifies the warm colors with deeper oranges and reds. Dusk introduces muted blue-grays as light fades. Night reaches deep navy and near-black at the top, while dawn adds hints of warm tones as the cycle prepares to restart.&lt;/p&gt;



&lt;p&gt;The phase calculation normalizes progress within each half-cycle, creating a local progress value that runs from 0 to 1 within either the day or night phase:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-23VBt2 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;val isDay = cycleProgress &lt; 0.5f\nval dayProgress = if (isDay) cycleProgress * 2f else (cycleProgress - 0.5f) * 2f&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This normalization simplifies the transition logic, each phase can work with a consistent 0-to-1 range regardless of where it falls in the overall cycle. The day phase occurs when &lt;code&gt;cycleProgress&lt;/code&gt; is below 0.5, while the night phase covers the upper half.&lt;/p&gt;



&lt;p&gt;Then each phase transitions smoothly using &lt;code&gt;lerp&lt;/code&gt; (linear interpolation), which blends between color values based on a progress parameter:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1OXmTt wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;val skyColors = if (isDay) {\n    when {\n        dayProgress &lt; 0.2f -&gt; {\n            val t = dayProgress \/ 0.2f  \/\/ Normalize to 0-1 within this phase\n            listOf(\n                lerp(sunriseColors[0], dayColors[0], t),\n                lerp(sunriseColors[1], dayColors[1], t),\n                lerp(sunriseColors[2], dayColors[2], t),\n            )\n        }\n        dayProgress &lt; 0.8f -&gt; dayColors  \/\/ Hold steady during midday\n        else -&gt; {\n            val t = (dayProgress - 0.8f) \/ 0.2f\n            listOf(\n                lerp(dayColors[0], sunsetColors[0], t),\n                lerp(dayColors[1], sunsetColors[1], t),\n                lerp(dayColors[2], sunsetColors[2], t),\n            )\n        }\n    }\n} else {\n    \/\/ Similar structure for night phases...\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This creates natural-feeling transitions with quick sunrise/sunset phases occupying 20% of each half-cycle and stable midday/midnight periods holding steady for the remaining 60%. This pacing mimics real daylight patterns where transitions happen relatively quickly at the horizon while the bulk of day and night are stable. The 20/60/20 split also ensures that users spending even brief time on the paywall will likely see some transition, keeping the experience dynamic.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;star-twinkling-with-fade-transitions&quot;&gt;&lt;strong&gt;Star twinkling with fade transitions&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Stars need to fade in and out at dawn and dusk, while also twinkling individually throughout the night. This dual-animation requirement demonstrates how to layer effects cleanly:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-176UwX wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;val starAlpha = if (isDay) {\n    when {\n        dayProgress &lt; 0.15f -&gt; 1f - dayProgress * 6f     \/\/ Fade out at dawn\n        dayProgress &gt; 0.85f -&gt; (dayProgress - 0.85f) * 6f \/\/ Fade in at dusk\n        else -&gt; 0f  \/\/ Invisible during day\n    }\n} else {\n    when {\n        dayProgress &lt; 0.15f -&gt; dayProgress * 6f           \/\/ Fade in after sunset\n        dayProgress &gt; 0.85f -&gt; 1f - (dayProgress - 0.85f) * 6f \/\/ Fade out before sunrise\n        else -&gt; 1f  \/\/ Fully visible at night\n    }\n}\n\nif (starAlpha &gt; 0f) {\n    for (star in stars) {\n        val twinkle = (sin(totalTime * star.twinkleSpeed + star.twinklePhase) + 1f) \/ 2f\n        val alpha = starAlpha * (0.4f + twinkle * 0.6f)  \/\/ Range: 40% to 100%\n        drawCircle(\n            color = Color.White.copy(alpha = alpha),\n            radius = star.size,\n            center = Offset(star.x * width, star.y * height),\n        )\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The fade timing uses 15% windows at the edges of each phase, creating smooth transitions. The multiplier of 6 (derived from 1/0.15) ensures the fade completes exactly within the window. During the day phase, stars are invisible (alpha 0) for 70% of the time, only appearing during the dawn and dusk transitions.&lt;/p&gt;



&lt;p&gt;The twinkle effect uses a sine wave offset by each star’s unique phase. The sine function naturally oscillates between -1 and 1, so (&lt;code&gt;sin(...) + 1f) / 2f &lt;/code&gt;normalizes this to 0-1. Multiplying by &lt;code&gt;starAlpha&lt;/code&gt; creates the overall fade effect, while the inner calculation &lt;code&gt;(0.4f + twinkle * 0.6f)&lt;/code&gt; ensures stars never fully disappear, they oscillate between 40% and 100% brightness, mimicking the atmospheric twinkling of real stars.&lt;/p&gt;



&lt;p&gt;The performance optimization &lt;code&gt;if (starAlpha &amp;gt; 0f)&lt;/code&gt; skips the star drawing loop entirely during the day, avoiding unnecessary computation when stars aren’t visible.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;sun-and-moon-arc-trajectories&quot;&gt;&lt;strong&gt;Sun and moon arc trajectories&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The sun and moon follow identical arc paths across the sky, creating a believable celestial motion. The trigonometry here creates a natural horizon-to-horizon path:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1mXPND wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;val sunMoonY = height * 0.35f  \/\/ Arc center Y position\nval arcRadius = width * 0.6f   \/\/ Arc radius\nval centerX = width \/ 2f\n\nif (isDay) {\n    val sunAngle = PI.toFloat() * (1f - dayProgress)  \/\/ PI to 0 as progress increases\n    val sunX = centerX + cos(sunAngle) * arcRadius\n    val sunY = sunMoonY - sin(sunAngle) * arcRadius * 0.5f + height * 0.1f\n\n    if (sunY &lt; height * 0.7f) {  \/\/ Only draw when above horizon\n        \/\/ Draw sun...\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The trigonometry creates a smooth arc through parametric calculation. At &lt;code&gt;dayProgress = 0&lt;/code&gt;, the angle is PI (180 degrees), so the sun is at the left side of the screen since &lt;code&gt;cos(PI) = -1.&lt;/code&gt; &lt;code&gt;At dayProgress = 0.5&lt;/code&gt;, the angle is PI/2 (90 degrees), placing the sun at the center top since &lt;code&gt;cos(PI/2) = 0&lt;/code&gt; and &lt;code&gt;sin(PI/2) = 1.&lt;/code&gt; At &lt;code&gt;dayProgress = 1&lt;/code&gt;, the angle is 0, positioning the sun at the right side since cos(0) = 1.&lt;/p&gt;



&lt;p&gt;The &lt;code&gt;0.5f&lt;/code&gt; multiplier on the Y component creates an elliptical arc rather than circular, giving a more natural horizon-to-horizon path that doesn’t extend too high into the sky. The &lt;code&gt;height * 0.1f&lt;/code&gt; offset shifts the entire arc downward so the sun and moon rise from and set to below the visible area, creating a proper horizon effect.&lt;/p&gt;



&lt;p&gt;The horizon check &lt;code&gt;if (sunY &amp;lt; height * 0.7f)&lt;/code&gt; prevents drawing the celestial body when it’s below the landscape area. This simple culling ensures clean transitions at sunrise and sunset, with the sun and moon appearing to rise from and sink below the horizon naturally.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;sun-rendering-with-animated-rays&quot;&gt;&lt;strong&gt;Sun rendering with animated rays&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The sun is composed of multiple layers for a luminous, living effect. Each layer serves a specific purpose in creating the overall impression of radiant warmth:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-NRjrR wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/\/ Outer glow\ndrawCircle(\n    brush = Brush.radialGradient(\n        colors = listOf(\n            Color(0xFFFFFFCC).copy(alpha = 0.4f),\n            Color(0xFFFFD700).copy(alpha = 0.2f),\n            Color.Transparent,\n        ),\n        center = Offset(sunX, sunY),\n        radius = 80f,\n    ),\n    radius = 80f,\n    center = Offset(sunX, sunY),\n)\n\n\/\/ Main sun body\ndrawCircle(\n    brush = Brush.radialGradient(\n        colors = listOf(\n            Color(0xFFFFFFE0),\n            Color(0xFFFFD700),\n            Color(0xFFFFA500),\n        ),\n        center = Offset(sunX - 8f, sunY - 8f),  \/\/ Offset for 3D effect\n        radius = 35f,\n    ),\n    radius = 35f,\n    center = Offset(sunX, sunY),\n)\n\n\/\/ Animated rays\nfor (i in 0 until 12) {\n    val rayAngle = (i * 30f + totalTime * 20f) * PI.toFloat() \/ 180f\n    val innerRadius = 40f\n    val outerRadius = 55f + sin(totalTime * 3f + i) * 5f  \/\/ Pulsing length\n    drawLine(\n        color = Color(0xFFFFD700).copy(alpha = 0.6f),\n        start = Offset(\n            sunX + cos(rayAngle) * innerRadius,\n            sunY + sin(rayAngle) * innerRadius,\n        ),\n        end = Offset(\n            sunX + cos(rayAngle) * outerRadius,\n            sunY + sin(rayAngle) * outerRadius,\n        ),\n        strokeWidth = 3f,\n        cap = StrokeCap.Round,\n    )\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The outer glow uses a radial gradient that fades to transparent, creating a soft halo effect around the sun. This atmospheric glow adds depth and prevents the sun from looking like a flat circle floating in space.&lt;/p&gt;



&lt;p&gt;The main sun body uses an offset gradient center (shifted 8 pixels up and left) to create a subtle 3D effect. This offset makes one edge appear brighter, as if the sun has volume and the light is coming from a consistent direction. The color progression from pale yellow at the center through gold to orange at the edge mimics the color gradation seen in photographs of the sun.&lt;/p&gt;



&lt;p&gt;The rays animate in two ways. First, &lt;code&gt;totalTime * 20f&lt;/code&gt; in the angle calculation makes them rotate slowly, creating a spinning effect. Second, &lt;code&gt;sin(totalTime * 3f + i) * 5f&lt;/code&gt; makes each ray’s length oscillate independently, with the phase offset + i ensuring different rays pulse at different times. This combination creates an organic, breathing quality that makes the sun feel alive.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;parallax-cloud-movement&quot;&gt;&lt;strong&gt;Parallax cloud movement&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Clouds create depth through independent movement speeds, a technique known as parallax that’s fundamental to creating perceived depth in 2D scenes:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1Dt6FC wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;data class Cloud(val xOffset: Float, val y: Float, val scale: Float, val speed: Float)\n\nval clouds = remember {\n    List(5) {\n        Cloud(\n            xOffset = Random.nextFloat(),\n            y = Random.nextFloat() * 0.3f + 0.1f,  \/\/ Upper portion of sky\n            scale = Random.nextFloat() * 0.5f + 0.8f,\n            speed = Random.nextFloat() * 0.02f + 0.01f,\n        )\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The five clouds have varying scales and speeds. Larger, slower clouds appear more distant, while smaller, faster clouds seem closer. This variation creates a sense of atmospheric depth, even in the flat 2D canvas. The Y positions are constrained to the upper third of the screen (0.1 to 0.4 of height), keeping clouds in the sky area where they belong.&lt;/p&gt;



&lt;p&gt;Each cloud is rendered as overlapping circles with wrapping horizontal movement:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1BCv9y wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;val cloudAlpha = if (isDay) 0.9f else 0.15f  \/\/ Dim at night\nval cloudColor = if (isDay) Color.White else Color(0xFF555555)\n\nfor (cloud in clouds) {\n    val cloudX = ((cloud.xOffset + totalTime * cloud.speed) % 1.4f - 0.2f) * width\n\n    drawCircle(\n        color = cloudColor.copy(alpha = cloudAlpha * 0.8f),\n        radius = 25f * cloud.scale,\n        center = Offset(cloudX, cloudY),\n    )\n    drawCircle(\n        color = cloudColor.copy(alpha = cloudAlpha),\n        radius = 35f * cloud.scale,\n        center = Offset(cloudX + 30f * cloud.scale, cloudY - 5f),\n    )\n    \/\/ Additional circles for cloud shape...\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The wrapping formula &lt;code&gt;% 1.4f - 0.2f&lt;/code&gt; ensures clouds exit on the right and re-enter from the left seamlessly. The 1.4 range (140% of screen width) combined with the -0.2 offset means clouds are generated slightly off the left edge of the screen, drift across the entire visible area, and continue slightly past the right edge before wrapping. This creates smooth, continuous motion without visible popping at the edges.&lt;/p&gt;



&lt;p&gt;The cloud color and alpha change between day and night. Daytime clouds are bright white at 90% opacity, clearly visible against the blue sky. Nighttime clouds become dark gray at only 15% opacity, creating subtle silhouettes that are visible but don’t dominate the starry sky.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;animating-ui-elements-with-the-cycle&quot;&gt;&lt;strong&gt;Animating UI elements with the cycle&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The UI layer animates in response to the day/night state using &lt;code&gt;animateColorAsState&lt;/code&gt;, which provides smooth interpolation between colors whenever the target changes:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1x5bRC wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;val buttonColor by animateColorAsState(\n    targetValue = if (isDay) Color(0xFFFFB800) else Color(0xFF6366F1),\n    animationSpec = tween(800),\n    label = \&amp;quot;buttonColor\&amp;quot;,\n)\n\nval buttonTextColor by animateColorAsState(\n    targetValue = if (isDay) Color.Black else Color.White,\n    animationSpec = tween(800),\n    label = \&amp;quot;buttonTextColor\&amp;quot;,\n)\n\nval accentColor by animateColorAsState(\n    targetValue = if (isDay) Color(0xFFFFD700) else Color(0xFF8B9DC3),\n    animationSpec = tween(800),\n    label = \&amp;quot;accentColor\&amp;quot;,\n)&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The 800ms duration creates smooth transitions that don’t feel rushed. This timing was chosen to match the overall pacing of the paywall, fast enough to feel responsive, but slow enough to be perceivable and pleasing. The color choices reinforce the day/night theme: warm golden tones during the day suggest sunshine and energy, while cool indigo and silver tones at night suggest calm and sophistication.&lt;/p&gt;



&lt;p&gt;The label parameters are important for debugging and tooling. When using Android Studio’s Animation Preview or Compose debugging tools, these labels help identify which animation is which in the visualization.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;greeting-crossfade-animation&quot;&gt;&lt;strong&gt;Greeting crossfade animation&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The greeting text switches between “GOOD MORNING” and “GOOD EVENING” using Crossfade, which automatically handles the enter and exit animations for content that changes:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZfXesK wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;Crossfade(\n    targetState = isDay,\n    animationSpec = tween(800),\n    label = \&amp;quot;greeting\&amp;quot;,\n) { day -&gt;\n    Text(\n        text = if (day) \&amp;quot;GOOD MORNING\&amp;quot; else \&amp;quot;GOOD EVENING\&amp;quot;,\n        style = TextStyle(\n            color = Color.White.copy(alpha = 0.8f),\n            fontSize = 12.sp,\n            fontWeight = FontWeight.Bold,\n            letterSpacing = 4.sp,\n        ),\n    )\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;Crossfade&lt;/code&gt; composable handles the transition automatically, fading out the old content while simultaneously fading in the new content. This creates a smooth handoff without any jump or flicker. The 800ms duration matches the other UI animations, creating a cohesive feel.&lt;/p&gt;



&lt;p&gt;The greeting text itself serves an important purpose beyond decoration, it creates a personal connection with the user. Time-appropriate greetings are a small touch that makes the app feel aware of and responsive to the user’s context. Combined with the animated environment, this creates the impression of a thoughtful, polished experience.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;custom-checkmark-drawing&quot;&gt;&lt;strong&gt;Custom checkmark drawing&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Feature list items include animated checkmarks drawn with Canvas, demonstrating how to create custom graphics that respond to animation:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZdtB74 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Composable\nfun TimeFeatureItem(title: String, checkColor: Color, modifier: Modifier = Modifier) {\n    Row(\n        modifier = modifier.fillMaxWidth().padding(vertical = 8.dp),\n        verticalAlignment = Alignment.CenterVertically,\n    ) {\n        Box(\n            modifier = Modifier\n                .size(24.dp)\n                .clip(CircleShape)\n                .background(checkColor),  \/\/ Animated color from parent\n            contentAlignment = Alignment.Center,\n        ) {\n            Canvas(modifier = Modifier.size(12.dp)) {\n                val path = Path().apply {\n                    moveTo(size.width * 0.2f, size.height * 0.5f)\n                    lineTo(size.width * 0.4f, size.height * 0.7f)\n                    lineTo(size.width * 0.8f, size.height * 0.3f)\n                }\n                drawPath(\n                    path = path,\n                    color = Color.White,\n                    style = Stroke(width = 2f, cap = StrokeCap.Round, join = StrokeJoin.Round),\n                )\n            }\n        }\n\n        Spacer(modifier = Modifier.width(14.dp))\n\n        Text(\n            text = title,\n            style = TextStyle(\n                color = Color.White,\n                fontSize = 15.sp,\n                fontWeight = FontWeight.Medium,\n            ),\n        )\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Drawing the checkmark with Canvas instead of an icon gives you precise control and eliminates asset dependencies. The checkmark path is defined using relative coordinates (percentages of the canvas size), making it scale correctly at any size. The &lt;code&gt;StrokeCap.Round&lt;/code&gt; and &lt;code&gt;StrokeJoin.Round&lt;/code&gt; create smooth, friendly-looking line endings and corners.&lt;/p&gt;



&lt;p&gt;The background color comes from the parent composable and animates with the day/night cycle. This means the checkmark circles smoothly transition from warm golden during the day to cool indigo at night, maintaining visual harmony with the rest of the paywall.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;integrating-revenuecat-for-purchases&quot;&gt;&lt;strong&gt;Integrating RevenueCat for purchases&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The paywall integrates RevenueCat through the &lt;code&gt;rememberPaywallState&lt;/code&gt; helper, which encapsulates all purchase logic and provides a clean interface for the UI layer:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1F1VWv wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Composable\nfun DayNightPaywallScreen(onDismiss: () -&gt; Unit = {}) {\n    val paywallState = rememberPaywallState(onPurchaseSuccess = onDismiss)\n\n    \/\/ ...\n\n    Button(\n        onClick = { paywallState.purchase(PackageType.ANNUAL) },\n        modifier = Modifier.fillMaxWidth().height(56.dp),\n        colors = ButtonDefaults.buttonColors(containerColor = buttonColor),\n        shape = RoundedCornerShape(14.dp),\n    ) {\n        Text(\n            text = \&amp;quot;Start Free Trial\&amp;quot;,\n            style = TextStyle(\n                color = buttonTextColor,\n                fontSize = 16.sp,\n                fontWeight = FontWeight.Bold,\n            ),\n        )\n    }\n\n    \/\/ ...\n\n    Text(\n        text = \&amp;quot;Restore Purchases\&amp;quot;,\n        modifier = Modifier.clickable { paywallState.restorePurchases() },\n        \/\/ ...\n    )\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;PaywallState&lt;/code&gt; class encapsulates all purchase logic, keeping the UI composable focused on presentation:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-24azdT wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;class PaywallState(\n    private val scope: CoroutineScope,\n    private val onPurchaseSuccess: () -&gt; Unit,\n    private val onPurchaseError: (String) -&gt; Unit,\n    private val onPurchaseCancelled: () -&gt; Unit,\n) {\n    var offering by mutableStateOf&lt;OfferingInfo?&gt;(null)\n    var isLoading by mutableStateOf(false)\n    var errorMessage by mutableStateOf&lt;String?&gt;(null)\n    var selectedPackage by mutableStateOf(PackageType.ANNUAL)\n\n    fun purchase(packageType: PackageType) {\n        scope.launch {\n            isLoading = true\n            when (val result = PurchaseHelper.purchase(packageType)) {\n                is PurchaseResult.Success -&gt; onPurchaseSuccess()\n                is PurchaseResult.Error -&gt; onPurchaseError(result.message)\n                is PurchaseResult.Cancelled -&gt; onPurchaseCancelled()\n            }\n            isLoading = false\n        }\n    }\n\n    fun restorePurchases() {\n        scope.launch {\n            isLoading = true\n            when (val result = PurchaseHelper.restorePurchases()) {\n                is PurchaseResult.Success -&gt; onPurchaseSuccess()\n                is PurchaseResult.Error -&gt; onPurchaseError(result.message)\n                is PurchaseResult.Cancelled -&gt; { \/* No-op *\/ }\n            }\n            isLoading = false\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This separation of concerns follows a clear architectural principle: UI components should be responsible only for presentation, while business logic belongs in separate classes. The &lt;code&gt;PaywallState&lt;/code&gt; manages all RevenueCat interactions, loading states, and error handling, exposing only the interface the UI needs. This makes the code easier to test, maintain, and modify—changes to purchase logic don’t require touching the UI code, and vice versa.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;firebase-for-agile-ab-testing&quot;&gt;&lt;strong&gt;Firebase for agile A/B testing&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Custom paywalls give you creative control, but testing different messaging and offers requires a mechanism for remote configuration. Firebase Real-Time Database or Firestore provides this capability, enabling you to iterate on paywall content without app updates.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;why-firebase-for-paywall-content&quot;&gt;&lt;strong&gt;Why Firebase for paywall content&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;RevenueCat excels at managing subscription products, pricing, and analytics. However, when you’ve built a custom paywall, you need remote control over the content layer, the headlines, subheadlines, feature lists, price display formats, and call-to-action text that influence conversion. These elements often benefit from experimentation, and waiting for app store review cycles to test changes dramatically slows iteration.&lt;/p&gt;



&lt;p&gt;Firebase lets you change these values without app updates, enabling rapid experimentation. You can launch a test in the morning, gather data throughout the day, and roll out the winner by evening, a pace impossible with traditional app updates. This agility is particularly valuable in the early stages of monetization when you’re still learning what resonates with your audience.&lt;/p&gt;



&lt;p&gt;The combination of custom UI (for brand expression and advanced animation) with remote content (for rapid iteration) gives you the best of both worlds. Your paywall looks and feels unique, but you can still optimize messaging as quickly as teams using templated solutions.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;setting-up-remote-config-for-paywall-content&quot;&gt;&lt;strong&gt;Setting up Remote Config for paywall content&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;First, define your paywall configuration structure in Firestore. This structure should capture all the text elements you might want to vary:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZXwfXV wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;data class PaywallConfig(\n    val headline: String = \&amp;quot;Always On\&amp;quot;,\n    val subheadline: String = \&amp;quot;Premium works day and night\&amp;quot;,\n    val features: List&lt;String&gt; = listOf(\n        \&amp;quot;24\/7 Access Anytime\&amp;quot;,\n        \&amp;quot;Sync Across All Devices\&amp;quot;,\n        \&amp;quot;Offline Mode Support\&amp;quot;,\n        \&amp;quot;Smart Scheduling\&amp;quot;,\n        \&amp;quot;Priority Notifications\&amp;quot;,\n    ),\n    val priceDisplay: String = \&amp;quot;$39.99\/year\&amp;quot;,\n    val priceSubtext: String = \&amp;quot;Less than $3.50\/month\&amp;quot;,\n    val ctaText: String = \&amp;quot;Start Free Trial\&amp;quot;,\n    val variant: String = \&amp;quot;control\&amp;quot;,\n)&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The default values serve two purposes. First, they provide a fallback if the network request fails, ensuring the paywall always displays something reasonable. Second, they document the expected content, making it clear what each field is for.&lt;/p&gt;



&lt;p&gt;The &lt;code&gt;variant&lt;/code&gt; field is important for analytics. By including the variant identifier in the configuration itself, you ensure that analytics events always include the correct attribution. This eliminates a common source of A/B testing bugs where the variant assignment and the displayed content become desynchronized.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Fetching configuration at paywall display&lt;/strong&gt;&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1yism0 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;class PaywallConfigRepository(\n    private val firestore: FirebaseFirestore\n) {\n    suspend fun getPaywallConfig(userId: String): PaywallConfig {\n        \/\/ Determine which variant this user should see\n        val variant = determineVariant(userId)\n\n        return firestore.collection(\&amp;quot;paywall_configs\&amp;quot;)\n            .document(variant)\n            .get()\n            .await()\n            .toObject&lt;PaywallConfig&gt;()\n            ?: PaywallConfig()  \/\/ Fallback to defaults\n    }\n\n    private fun determineVariant(userId: String): String {\n        \/\/ Simple hash-based assignment for consistent user experience\n        val hash = userId.hashCode().absoluteValue\n        return when (hash % 3) {\n            0 -&gt; \&amp;quot;control\&amp;quot;\n            1 -&gt; \&amp;quot;variant_a\&amp;quot;\n            else -&gt; \&amp;quot;variant_b\&amp;quot;\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The hash-based variant assignment ensures consistency, the same user always sees the same variant across sessions. This is critical for valid A/B testing; if users saw different variants on different visits, you couldn’t accurately measure the effect of any particular treatment.&lt;/p&gt;



&lt;p&gt;The fallback to default values (via the &lt;code&gt;?: PaywallConfig()&lt;/code&gt; null coalesce) ensures the paywall always works, even if Firestore is unavailable. This defensive approach prevents network issues from blocking purchases entirely.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;integrating-dynamic-content-into-the-paywall&quot;&gt;&lt;strong&gt;Integrating dynamic content into the paywall&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Modify the paywall to accept configuration:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZqEEjj wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Composable\nfun DayNightPaywallScreen(\n    config: PaywallConfig,\n    onDismiss: () -&gt; Unit = {},\n) {\n    \/\/ Use config values instead of hardcoded strings\n    Text(\n        text = config.headline,\n        style = TextStyle(\n            color = Color.White,\n            fontSize = 38.sp,\n            fontWeight = FontWeight.Bold,\n        ),\n    )\n\n    Text(\n        text = config.subheadline,\n        style = TextStyle(\n            color = Color.White.copy(alpha = 0.7f),\n            fontSize = 14.sp,\n        ),\n    )\n\n    \/\/ Dynamic feature list\n    Column(\n        modifier = Modifier\n            .fillMaxWidth()\n            .clip(RoundedCornerShape(16.dp))\n            .background(Color.Black.copy(alpha = 0.3f))\n            .padding(16.dp),\n    ) {\n        config.features.forEach { feature -&gt;\n            TimeFeatureItem(title = feature, checkColor = checkColor)\n        }\n    }\n\n    \/\/ Dynamic pricing\n    Text(text = config.priceDisplay, \/* ... *\/)\n    Text(text = config.priceSubtext, \/* ... *\/)\n\n    \/\/ Dynamic CTA\n    Button(onClick = { paywallState.purchase(PackageType.ANNUAL) }) {\n        Text(text = config.ctaText, \/* ... *\/)\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;By parameterizing the paywall with a config object, you’ve created a flexible system that supports unlimited variations. The animations and visual design remain constant (and distinctive), while the content can be tuned remotely. This separation reflects the insight that users respond to both form and content, the form (design) builds brand perception, while the content (messaging) drives conversion.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;tracking-conversion-events&quot;&gt;&lt;strong&gt;Tracking conversion events&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;To analyze A/B test results, log conversion events with the variant identifier:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-rsNck wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;class PaywallAnalytics(\n    private val analytics: FirebaseAnalytics\n) {\n    fun logPaywallViewed(variant: String) {\n        analytics.logEvent(\&amp;quot;paywall_viewed\&amp;quot;) {\n            param(\&amp;quot;variant\&amp;quot;, variant)\n            param(\&amp;quot;paywall_type\&amp;quot;, \&amp;quot;day_night\&amp;quot;)\n        }\n    }\n\n    fun logPurchaseStarted(variant: String, packageType: String) {\n        analytics.logEvent(\&amp;quot;purchase_started\&amp;quot;) {\n            param(\&amp;quot;variant\&amp;quot;, variant)\n            param(\&amp;quot;package_type\&amp;quot;, packageType)\n        }\n    }\n\n    fun logPurchaseCompleted(variant: String, packageType: String) {\n        analytics.logEvent(\&amp;quot;purchase_completed\&amp;quot;) {\n            param(\&amp;quot;variant\&amp;quot;, variant)\n            param(\&amp;quot;package_type\&amp;quot;, packageType)\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;These three events create a conversion funnel that lets you analyze where users drop off. By filtering each event by variant, you can compare performance across treatments. The &lt;code&gt;paywall_type&lt;/code&gt; parameter supports analysis across different paywall designs if you have multiple.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;analyzing-results-in-firebase&quot;&gt;&lt;strong&gt;Analyzing results in Firebase&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Create a funnel analysis in Firebase Analytics by examining the progression from &lt;code&gt;paywall_viewed&lt;/code&gt; to &lt;code&gt;purchase_started&lt;/code&gt; to &lt;code&gt;purchase_completed&lt;/code&gt;, filtering each step by variant. Compare conversion rates across variants to determine winners.&lt;/p&gt;



&lt;p&gt;When interpreting results, remember that statistical significance matters. Small differences in conversion rates may be noise rather than signal, especially with limited sample sizes. Firebase’s audience features can help you understand segment-specific effects, a variant that works well for new users might underperform for returning users, or vice versa.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;best-practices-for-paywall-ab-testing&quot;&gt;&lt;strong&gt;Best practices for paywall A/B testing&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Several principles help ensure your A/B tests yield actionable insights. First, test one variable at a time whenever possible. Changing the headline, feature list, and CTA simultaneously makes it impossible to know which change drove the result. If you must test multiple changes together, treat the entire bundle as a single variant and don’t draw conclusions about individual elements.&lt;/p&gt;



&lt;p&gt;Second, use consistent user assignment so the same user always sees the same variant. This prevents the noise that would come from users experiencing different treatments on different visits. Third, run tests long enough to achieve statistical significance, which typically requires 1000 or more conversions per variant depending on the effect size you’re trying to detect.&lt;/p&gt;



&lt;p&gt;Fourth, consider segment-specific testing. New users and returning users often respond differently to messaging, and testing within segments can reveal insights that aggregate analysis misses. Finally, document and archive your results. Over time, you’ll build organizational knowledge about what works for your audience, informing future experiments and reducing the need to retest ideas.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;revenuecat-paywall-builder-beyond-custom&quot;&gt;&lt;strong&gt;RevenueCat Paywall Builder: Beyond custom&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;While custom paywalls offer maximum flexibility, &lt;a href=&quot;https://www.revenuecat.com/docs/tools/paywalls/creating-paywalls#using-the-editor&quot;&gt;RevenueCat’s Paywall Builder&lt;/a&gt; provides compelling advantages for many scenarios. Understanding when each approach makes sense helps you allocate development resources effectively.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;735&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/2025-06-10-12.42.56-1024x735.gif&quot; alt=&quot;&quot; class=&quot;wp-image-50039&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/2025-06-10-12.42.56-1024x735.gif 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/2025-06-10-12.42.56-300x215.gif 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/2025-06-10-12.42.56-768x552.gif 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/2025-06-10-12.42.56-1536x1103.gif 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/2025-06-10-12.42.56-50x36.gif 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/2025-06-10-12.42.56-56x40.gif 56w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/2025-06-10-12.42.56-646x464.gif 646w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/2025-06-10-12.42.56-696x500.gif 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/2025-06-10-12.42.56-560x402.gif 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/2025-06-10-12.42.56-412x296.gif 412w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/2025-06-10-12.42.56-657x472.gif 657w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/2025-06-10-12.42.56-80x57.gif 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/2025-06-10-12.42.56-48x34.gif 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;what-paywall-builder-offers&quot;&gt;&lt;strong&gt;What Paywall Builder offers&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;RevenueCat’s Paywall Builder is a server-driven UI system that lets you design paywalls without code changes, using a visual editor in the RevenueCat dashboard. Once designed, paywalls can be updated remotely without app updates, you can change colors, fonts, layouts, images, and copy at any time. Built-in A/B testing lets you test different designs with statistical rigor, automatically allocating traffic and tracking results.&lt;/p&gt;



&lt;p&gt;Localization support manages translations in one place, with automatic serving based on user locale. Analytics integration provides automatic conversion tracking without additional instrumentation. And a template library gives you proven starting points that you can customize.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;server-driven-ui-advantages&quot;&gt;&lt;strong&gt;Server-driven UI advantages&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The key advantage of Paywall Builder is server-driven UI. Your app renders whatever configuration the server provides, decoupling the paywall appearance from the app release cycle:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-xkPKs wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Composable\nfun PaywallScreen(onDismiss: () -&gt; Unit) {\n    PaywallDialog(\n        PaywallDialogOptions.Builder()\n            .setDismissRequest(onDismiss)\n            .build()\n    )\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This single composable renders any paywall design you configure in the RevenueCat dashboard. No app update required to change colors, fonts, or layouts, swap images or icons, modify copy or pricing display, launch A/B tests, or roll out winning variants.&lt;/p&gt;



&lt;p&gt;The operational implications are significant. Your product team can iterate on paywalls independently of engineering, accelerating the experimentation cycle. Bugs in paywall content can be fixed immediately rather than waiting for app store review. Seasonal promotions can be created and removed on exact schedules without app update coordination.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;when-to-choose-paywall-builder&quot;&gt;&lt;strong&gt;When to choose Paywall Builder&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Paywall Builder is often the better choice when iteration speed matters most. If you’re optimizing for conversion and need to test many variations quickly, the visual editor and built-in A/B testing dramatically accelerate the feedback loop. The product team can create and launch tests without engineering involvement, freeing developers for other work.&lt;/p&gt;



&lt;p&gt;Engineering resource constraints also favor Paywall Builder. Custom paywalls require development time for initial implementation and ongoing maintenance. Paywall Builder shifts this work to product and design teams, who can work in the visual editor without writing code.&lt;/p&gt;



&lt;p&gt;If you don’t need advanced animations, Paywall Builder supports basic animations and transitions. If your paywall concept doesn’t require complex custom effects, the templates may be sufficient. Many successful apps use straightforward paywalls that focus on clear messaging rather than elaborate motion design.&lt;/p&gt;



&lt;p&gt;Cross-platform consistency is another consideration. Paywall Builder renders consistently across iOS, Android, and web. Custom implementations require separate development for each platform, multiplying the engineering investment.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;when-custom-paywalls-still-win&quot;&gt;&lt;strong&gt;When custom paywalls still win&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Custom paywalls remain the right choice when brand expression is paramount. If your paywall must match a distinctive visual identity with custom animations, templates can’t replicate that. The Day &amp;amp; Night paywall we examined could never be created in a templated system, the procedural star generation, trigonometric sun/moon paths, and synchronized multi-layer animation require custom code.&lt;/p&gt;



&lt;p&gt;You need unique interactions that templates don’t support. Gamified paywalls, AR previews, gesture-based navigation, or mini-demos of premium features require custom implementation. These interactive elements can significantly impact conversion by letting users experience value before committing.&lt;/p&gt;



&lt;p&gt;Sometimes the paywall is a product differentiator. If the paywall experience itself is a selling point, like a meditation app’s calming paywall that sets the tone for the premium experience, custom development is worthwhile. First impressions matter, and a distinctive paywall can signal the quality users should expect from the premium tier.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;hybrid-approach&quot;&gt;&lt;strong&gt;Hybrid approach&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Many successful apps use both approaches strategically. A custom implementation for the primary conversion flow provides the brand expression and distinctive experience that first-time subscribers see. &lt;a href=&quot;https://www.revenuecat.com/docs/tools/paywalls/creating-paywalls#using-the-editor&quot;&gt;Paywall Builder&lt;/a&gt; handles promotional paywalls for seasonal offers, win-back campaigns, or experiment variations where rapid iteration matters more than custom design. Secondary surfaces like settings screen upsells or feature-gated prompts also use Paywall Builder, since these are seen less frequently and benefit more from easy configurability than custom treatment.&lt;/p&gt;



&lt;p&gt;This hybrid approach maximizes both brand expression and iteration speed. The primary paywall creates the distinctive first impression, while Paywall Builder provides flexibility for ongoing optimization and promotional needs.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;conclusion&quot;&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Building animated custom paywalls in Jetpack Compose opens creative possibilities that templated solutions cannot match. The Day &amp;amp; Night paywall demonstrates how layered animations, sky gradients, twinkling stars, celestial body trajectories, parallax clouds, and synchronized UI elements, can create an immersive experience that engages users emotionally. These techniques transform the conversion moment from a transaction into an experience, potentially improving both conversion rates and brand perception.&lt;/p&gt;



&lt;p&gt;Firebase provides the remote configuration layer needed for agile A/B testing of paywall content. By externalizing headlines, features, pricing display, and CTA text, you can iterate on messaging without app updates while maintaining your custom animated experience. This combination, custom design with remote content, gives you both brand distinctiveness and operational agility.&lt;/p&gt;



&lt;p&gt;However, custom paywalls aren’t always the right choice. RevenueCat’s &lt;a href=&quot;https://www.revenuecat.com/docs/tools/paywalls/creating-paywalls#using-the-editor&quot;&gt;Paywall Builder&lt;/a&gt; offers server-driven UI, built-in A/B testing, and rapid iteration capabilities that often outweigh the benefits of custom development. Consider your team’s resources, iteration needs, and brand requirements when choosing between custom and templated approaches. Many successful apps use both, custom for the primary experience, templates for promotional and secondary surfaces.&lt;/p&gt;



&lt;p&gt;For complete documentation on RevenueCat’s SDK integration, refer to the &lt;a href=&quot;https://www.revenuecat.com/docs&quot;&gt;official RevenueCat documentation&lt;/a&gt;. For full source-code covered in this blog post, check out the &lt;a href=&quot;https://github.com/RevenueCat/compose-paywall-animations&quot;&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[How Jeff Morris drives growth and monetization in mobile]]></title><description><![CDATA[On the podcast, I talk with Jeff about Tinder's $50 million paywall win. Why now is such a great time to build apps, and how hard paywalls can mislead you about product-market fit.]]></description><link>https://www.revenuecat.com/blog/growth/how-jeff-morris-drives-growth-and-monetization-in-mobile/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/how-jeff-morris-drives-growth-and-monetization-in-mobile/</guid><pubDate>Wed, 07 Jan 2026 14:06:35 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/RC-Blog-Cover-Jeff-Morris-1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Jeff Morris, former VP of Product at Tinder and now a partner at Chapter One, brings years of experience in mobile growth and monetization strategies. In this episode, he shares actionable insights on building a scalable product, optimizing revenue streams, and staying agile in the fast-evolving app ecosystem.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;From Tinder to VC: Jeff Morris on Product-Market Fit, Monetization, and AI-Driven Growth&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/5qWhNLUR3MA?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;iframe loading=&quot;lazy&quot; width=&quot;100%&quot; height=&quot;180&quot; frameborder=&quot;no&quot; scrolling=&quot;no&quot; seamless=&quot;&quot; src=&quot;https://share.transistor.fm/e/5335178f?color=FFFFFF&amp;amp;background=30343C&quot;&gt;&lt;/iframe&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-product-market-fit-comes-first&quot;&gt;Product-market fit comes first&lt;/h2&gt;



&lt;p&gt;Before jumping into monetization, Jeff emphasizes the importance of ensuring product-market fit. Building a product that genuinely solves user problems and resonates with your audience is the key to long-term success. Monetization should follow naturally once you’ve built a loyal user base that values your product.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-test-and-adapt-monetization-strategies&quot;&gt;Test and adapt monetization strategies&lt;/h2&gt;



&lt;p&gt;The pressure to monetize early is rising, but Jeff advises against rushing into rigid strategies. Founders should test different models—such as subscriptions, paywalls, or in-app purchases—and adapt based on user responses. Flexibility and adaptation are critical in today’s competitive market, as the same monetization strategy doesn’t work for every app.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-experimentation-is-essential&quot;&gt;Experimentation is essential&lt;/h2&gt;



&lt;p&gt;Testing is not just necessary; it’s essential to growth. Jeff encourages founders to continually experiment with various aspects of their app, from creative assets to pricing strategies. Analyzing data and adjusting based on real-time results leads to smarter decisions that ultimately fuel growth and optimize revenue.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-quality-over-quantity-in-creative-testing&quot;&gt;Quality over quantity in creative testing&lt;/h2&gt;



&lt;p&gt;When it comes to creative testing, Jeff advocates for fewer, more meaningful experiments over testing hundreds of creatives without understanding why they work. Focus on strong hypotheses and ensure every test is geared towards discovering what truly resonates with your audience. Effective creative testing should be iterative and data-backed, not just about numbers.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-innovate-don-t-copy-competitors&quot;&gt;Innovate, don’t copy competitors&lt;/h2&gt;



&lt;p&gt;While learning from competitors is essential, Jeff warns against copying their playbooks without tailoring strategies to your app’s unique needs. Use competitor insights as inspiration, but adapt them based on your own data and user behavior to find what truly drives success for your app.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-accurate-data-is-key&quot;&gt;Accurate data is key&lt;/h2&gt;



&lt;p&gt;Data is at the core of Jeff’s approach to growth. He stresses the importance of accurate data instrumentation to make informed decisions. Whether it’s understanding user behavior, monitoring in-app analytics, or analyzing creative performance, having reliable data allows you to optimize your efforts and avoid costly mistakes.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-embrace-unconventional-approaches&quot;&gt;&lt;br&gt;Embrace unconventional approaches&lt;/h2&gt;



&lt;p&gt;Jeff encourages founders to think outside the box and not shy away from unconventional strategies. Small changes, such as how you map events or introduce new features, can significantly impact performance. Sometimes, doing the opposite of what’s considered conventional can open doors to new opportunities.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-conclusion&quot;&gt;Conclusion&lt;/h2&gt;



&lt;p&gt;Jeff’s experience shows that mobile growth and monetization aren’t about blindly following best practices—they’re about continuous testing, learning from data, and persistence in the face of challenges. By focusing on building a great product, testing frequently, and listening to user feedback, founders can find what works for their specific app and achieve sustainable, long-term growth.&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[How Peloton lost me after a price hike and what they could have done differently]]></title><description><![CDATA[9 practical retention lessons subscription apps can use during price increases]]></description><link>https://www.revenuecat.com/blog/growth/peloton-retention-takeaways/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/peloton-retention-takeaways/</guid><pubDate>Mon, 05 Jan 2026 13:40:24 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/How-Peloton-could-have-kept-me-subscribed-despite-a-price-hike.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Even before the &lt;a href=&quot;https://www.vanityfair.com/hollywood/2021/12/sex-and-the-city-peloton-big-and-just-like-that?srsltid=AfmBOoqJE6LJUN7Il8uy09YrgtYC95QBGPTrisiLD5k6HOXLYRGCNOYl&quot;&gt;big debacle&lt;/a&gt; in the pilot episode of &lt;em&gt;Sex and the City&lt;/em&gt;’s spin-off &lt;em&gt;And Just Like That&lt;/em&gt;, Peloton was all the hype, and I ran quickly away from it. I’ve never been great at following the crowd, and its cult-like following? Intimidating.&lt;/p&gt;



&lt;p&gt;Fast forward a few years: the craze had cooled, I had a slightly bigger space, and I got an irresistible offer. A friend was willing to give me his bike — barely used — for a third of the original price… if I could pick it up and haul it across London on a freezing February morning. Challenge accepted.&lt;/p&gt;



&lt;p&gt;Here’s my story: from falling in love with Peloton, to struggling with the monotony, surviving a price hike, and eventually canceling my subscription. Think of this as interval training: after the high-intensity bits of my painful memories, you’ll get a lighter, easy-breathe moment with the takeaways you can actually apply to your subscription app.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-interval-1-jumping-into-my-personalized-plan&quot;&gt;Interval 1: jumping into my personalized plan&lt;/h2&gt;



&lt;p&gt;My first hiccup came during account setup. Reading the fine print has never been my strong suit, and sure enough, I couldn’t use the bike to its full potential without the All-Access subscription at £39 a month.&lt;/p&gt;



&lt;p&gt;Whoops. But I was determined to give it a go. Plus, the subscription meant my partner could also use the bike, which seemed to excite him. Escaping the rain outside, I doubled down on bike rides.&lt;/p&gt;



&lt;p&gt;The real highlight? Peloton’s personalized plan feature:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;609&quot; height=&quot;913&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image.png&quot; alt=&quot;&quot; class=&quot;wp-image-49708&quot; style=&quot;width:400px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image.png 609w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-200x300.png 200w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-33x50.png 33w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-27x40.png 27w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-310x464.png 310w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-374x560.png 374w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-197x296.png 197w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-315x472.png 315w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-53x80.png 53w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-32x48.png 32w&quot; sizes=&quot;auto, (max-width: 609px) 100vw, 609px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;em&gt;Peloton email around personalising your plan&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;I’ve long struggled to fit into the box of a set plan that most apps offer. They usually focus on one type of exercise, while I thrive on variety. I’m the kind of person who never makes a recipe more than twice — yes, seriously.&lt;/p&gt;



&lt;p&gt;With Peloton, I quickly customized a routine that mixed biking, running, and strength training, and I was off.&lt;/p&gt;



&lt;p&gt;Here’s what their onboarding flow looks like:&lt;/p&gt;



&lt;figure class=&quot;wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-6 is-layout-flex wp-block-gallery-is-layout-flex&quot;&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;451&quot; height=&quot;1024&quot; data-id=&quot;49742&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-16-451x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-49742&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-16-451x1024.png 451w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-16-132x300.png 132w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-16-676x1536.png 676w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-16-22x50.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-16-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-16-204x464.png 204w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-16-696x1582.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-16-246x560.png 246w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-16-130x296.png 130w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-16-208x472.png 208w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-16-35x80.png 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-16-21x48.png 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-16.png 704w&quot; sizes=&quot;auto, (max-width: 451px) 100vw, 451px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;451&quot; height=&quot;1024&quot; data-id=&quot;49724&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-7-451x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-49724&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-7-451x1024.png 451w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-7-132x300.png 132w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-7-676x1536.png 676w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-7-22x50.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-7-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-7-204x464.png 204w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-7-696x1582.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-7-246x560.png 246w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-7-130x296.png 130w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-7-208x472.png 208w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-7-35x80.png 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-7-21x48.png 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-7.png 704w&quot; sizes=&quot;auto, (max-width: 451px) 100vw, 451px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;451&quot; height=&quot;1024&quot; data-id=&quot;49722&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-6-451x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-49722&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-6-451x1024.png 451w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-6-132x300.png 132w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-6-676x1536.png 676w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-6-22x50.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-6-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-6-204x464.png 204w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-6-696x1582.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-6-246x560.png 246w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-6-130x296.png 130w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-6-208x472.png 208w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-6-35x80.png 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-6-21x48.png 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-6.png 704w&quot; sizes=&quot;auto, (max-width: 451px) 100vw, 451px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;451&quot; height=&quot;1024&quot; data-id=&quot;49744&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-17-451x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-49744&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-17-451x1024.png 451w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-17-132x300.png 132w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-17-676x1536.png 676w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-17-22x50.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-17-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-17-204x464.png 204w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-17-696x1582.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-17-246x560.png 246w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-17-130x296.png 130w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-17-208x472.png 208w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-17-35x80.png 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-17-21x48.png 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-17.png 704w&quot; sizes=&quot;auto, (max-width: 451px) 100vw, 451px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;451&quot; height=&quot;1024&quot; data-id=&quot;49726&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-8-451x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-49726&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-8-451x1024.png 451w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-8-132x300.png 132w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-8-676x1536.png 676w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-8-22x50.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-8-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-8-204x464.png 204w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-8-696x1582.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-8-246x560.png 246w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-8-130x296.png 130w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-8-208x472.png 208w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-8-35x80.png 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-8-21x48.png 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-8.png 704w&quot; sizes=&quot;auto, (max-width: 451px) 100vw, 451px&quot;&gt;&lt;/figure&gt;
&lt;/figure&gt;



&lt;p&gt;&lt;em&gt;Peloton quiz&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;The onboarding is easy to navigate and never makes you feel stupid:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;If you’re unfamiliar with a workout type, like HIIT Cardio, they explain it clearly&lt;/li&gt;



&lt;li&gt;Visuals show exactly how to use the equipment&lt;/li&gt;



&lt;li&gt;Goals are asked about in simple, straightforward language&lt;/li&gt;
&lt;/ul&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;451&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-14-451x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-49738&quot; style=&quot;width:400px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-14-451x1024.png 451w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-14-132x300.png 132w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-14-676x1536.png 676w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-14-22x50.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-14-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-14-204x464.png 204w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-14-696x1582.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-14-246x560.png 246w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-14-130x296.png 130w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-14-208x472.png 208w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-14-35x80.png 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-14-21x48.png 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-14.png 704w&quot; sizes=&quot;auto, (max-width: 451px) 100vw, 451px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;em&gt;Clear explanations of exercises&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;I loved the variety of instructors and music, which perfectly complemented the high-energy workouts. My weekly streak grew quickly — just one workout a week was enough to keep it going — so no matter where I was in the world, I always did at least one session.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-takeaway-1-help-users-get-the-most-out-of-your-app-fast&quot;&gt;Takeaway 1: help users get the most out of your app, fast&lt;/h3&gt;



&lt;p&gt;Finding content with Peloton was effortless. A few simple questions helped the app understand me and offer workouts I actually enjoyed. ‘Fast’ doesn’t necessarily mean a short onboarding, &lt;strong&gt;but even if your onboarding is longer, it should give users a clear sense of value right away.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Peloton excels at this. They don’t just create a personalized routine; they also help you &lt;a href=&quot;https://www.onepeloton.com/en-GB/instructor-match&quot;&gt;find your favorite instructor&lt;/a&gt; with a separate, quick quiz. It’s like Tinder meets Strava, and it made me realize that matchmaking is exactly what had been missing from my workouts.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;664&quot; height=&quot;916&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-20.png&quot; alt=&quot;&quot; class=&quot;wp-image-49750&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-20.png 664w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-20-217x300.png 217w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-20-36x50.png 36w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-20-29x40.png 29w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-20-336x464.png 336w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-20-406x560.png 406w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-20-215x296.png 215w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-20-342x472.png 342w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-20-58x80.png 58w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-20-35x48.png 35w&quot; sizes=&quot;auto, (max-width: 664px) 100vw, 664px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;531&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-21-1024x531.png&quot; alt=&quot;&quot; class=&quot;wp-image-49752&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-21-1024x531.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-21-300x155.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-21-768x398.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-21-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-21-77x40.png 77w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-21-696x361.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-21-560x290.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-21-840x435.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-21-80x41.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-21-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-21.png 1339w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;em&gt;Instructor quiz on the Peloton website&lt;/em&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-interval-2-the-downward-hill-of-using-peloton&quot;&gt;Interval 2: the downward hill of using Peloton&lt;/h2&gt;



&lt;p&gt;You can’t stay in the honeymoon period forever, and ours ended over the summer. That’s when I noticed I was doing fewer and fewer workouts on Peloton. At first, I had a million excuses for the distance between me and Peloton; after all, I’d invested in the bike:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;I’d been injured, so I couldn’t run&lt;/li&gt;



&lt;li&gt;It was summer, and I was biking and swimming outside&lt;/li&gt;



&lt;li&gt;My sister was staying with me, and wanted guided strength workouts&amp;nbsp;&lt;/li&gt;



&lt;li&gt;I’d been traveling&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;But I persisted, trying to get back into it. I even reset my personalized plan to mix things up, but it felt like I was getting the same workouts on repeat.&lt;/p&gt;



&lt;p&gt;The plan offered a fixed week of classes, but there was no sense of progression or adjustment over time — just new versions of the same routines. It started to feel less like personalization and more like a static template that simply shuffled itself; making it harder to stay motivated when I was craving change.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Personalization without visible evolution can feel stagnant.&lt;/strong&gt; When users can’t see their progress, even the best content library starts to feel repetitive.&lt;/p&gt;



&lt;p&gt;I was already picking the most advanced workouts and experimenting with different instructors. I wasn’t a top performer (my power output on the bike could improve) but I didn’t know how to progress:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;More workouts?&lt;/li&gt;



&lt;li&gt;Different workouts?&lt;/li&gt;



&lt;li&gt;If it was personalized, where was the guidance?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;What was I even working toward? Slowly, the cracks started to show.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-takeaway-2-help-users-understand-how-recommendations-are-personalized-to-them&quot;&gt;Takeaway 2: help users understand how recommendations are personalized to them&lt;/h3&gt;



&lt;p&gt;Peloton’s personalized plan quiz was great for generating recommendations, but it missed a critical step: explaining &lt;em&gt;why&lt;/em&gt; those recommendations were made.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Users need to understand not just what to do, but why it’s tailored to them and what goal it serves. &lt;/strong&gt;Explaining the reasoning behind recommendations maintains trust and motivation. Sometimes products make the assumption users come to them because they don’t want to think, but that isn’t always true — we want the hard part done, but that doesn’t mean we don’t care about the ‘why’.&lt;/p&gt;



&lt;p&gt;If you’ve asked 10–20 questions during onboarding, don’t just hide behind a fake ‘thinking’ loader. Show users that their answers were heard. At a basic level, feed back their responses; at a more advanced level, demonstrate that you understand and confirm it with them. AI apps make this easier than ever.&lt;/p&gt;



&lt;p&gt;For example, Noom’s weightloss app has a lengthy onboarding process, but it breaks it up with little screens that reflect what it’s learned from your answers, making the personalization feel real:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;472&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-19-472x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-49748&quot; style=&quot;width:400px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-19-472x1024.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-19-138x300.png 138w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-19-708x1536.png 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-19-23x50.png 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-19-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-19-214x464.png 214w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-19-696x1509.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-19-258x560.png 258w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-19-137x296.png 137w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-19-218x472.png 218w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-19-37x80.png 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-19-22x48.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-19.png 738w&quot; sizes=&quot;auto, (max-width: 472px) 100vw, 472px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;em&gt;Noom’s personalization in the onboarding flow&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;It takes your answers to give you feedback on your profile and where you should focus, making you feel that Noom is truly personalized just from going through the onboarding process.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-takeaway-3-understand-what-drives-short-vs-long-term-retention&quot;&gt;Takeaway 3: understand what drives short vs. long-term retention&lt;/h3&gt;



&lt;p&gt;When you look at your monthly versus annual subscribers, you’ll often find that those canceling after a few months churn for very different reasons than those who leave after a year or two. &lt;strong&gt;Short-term and long-term retention are not the same game.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;There’s the initial activation phase, getting users to start using your app, which is easier for Peloton since many users have already made a big investment in the bike. That’s followed by the habit-building phase. But long-term retention requires something else entirely. Your user evolves, and your app has to evolve with them.&lt;/p&gt;



&lt;p&gt;This isn’t the first time I’ve outgrown an app. With ADHD, I quickly tire of repetition. I’ve had the same experience &lt;a href=&quot;https://www.revenuecat.com/blog/growth/subscription-app-churn-reasons-how-to-fix/#4-finding-a-better-app&quot;&gt;with mindfulness and recipe apps.&lt;/a&gt; Once you’ve mastered the basics and explored what an app has to offer, you start craving the next level.&lt;/p&gt;



&lt;p&gt;To sustain engagement,&lt;strong&gt; an app needs to grow and adapt alongside its users as their jobs-to-be-done evolve&lt;/strong&gt;. Peloton did allow you to retake your quiz to refresh recommendations, but it missed an opportunity to introduce clear levels, milestones, or a sense of progress, something to make users feel like they’re moving forward.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-interval-3-getting-the-email-all-users-dread-a-price-increase&quot;&gt;Interval 3: getting the email all users dread… a price increase&lt;/h2&gt;



&lt;p&gt;At this point, my two core personality traits were at war:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;The stubborn part of me that refused to give up on something I’d bought only nine months ago&lt;/li&gt;



&lt;li&gt;The restless part of me that craves newness&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;That’s when it landed in my inbox: the email every subscriber dreads. Subject line: “Changes coming to your Peloton Membership”. I knew exactly what the changes would be.&lt;/p&gt;



&lt;p&gt;Long before I’d finally joined the Peloton hype train, I’d actually used one of their previous price increase emails &lt;a href=&quot;https://www.revenuecat.com/blog/growth/how-to-raise-app-prices-effectively/&quot;&gt;as an example of great communication&lt;/a&gt;. It was clean, clear, and transparent, mapping out exactly what was changing and why. They had this great table showing just how much had changed between 2014 and 2022, from the number of workouts to the addition of programs.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;569&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-2-1024x569.png&quot; alt=&quot;&quot; class=&quot;wp-image-49712&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-2-1024x569.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-2-300x167.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-2-768x426.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-2-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-2-72x40.png 72w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-2-696x386.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-2-560x311.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-2-533x296.png 533w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-2-840x466.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-2-80x44.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-2-48x27.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-2.png 1149w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;em&gt;Peloton comparing the 2014 offering vs. the 2022 offering&amp;nbsp;&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;Of course, it’s always easier to admire a price hike email when you’re not the one paying for it.&lt;/p&gt;



&lt;p&gt;I still stand by it as a great email. I’m not a hater, and I can appreciate a good pricing update. So I opened this new one with an open mind, hoping for the same clarity. But instead of understanding, I was left confused. Here’s Peloton’s new price update email:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;842&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-13-1024x842.png&quot; alt=&quot;&quot; class=&quot;wp-image-49736&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-13-1024x842.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-13-300x247.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-13-768x632.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-13-50x41.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-13-49x40.png 49w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-13-564x464.png 564w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-13-696x573.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-13-560x461.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-13-360x296.png 360w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-13-574x472.png 574w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-13-80x66.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-13-48x39.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-13.png 1218w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;983&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-18-983x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-49746&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-18-983x1024.png 983w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-18-288x300.png 288w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-18-768x800.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-18-48x50.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-18-38x40.png 38w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-18-445x464.png 445w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-18-696x725.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-18-537x560.png 537w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-18-284x296.png 284w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-18-453x472.png 453w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-18-77x80.png 77w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-18-46x48.png 46w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-18.png 1232w&quot; sizes=&quot;auto, (max-width: 983px) 100vw, 983px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;em&gt;Email announcing price increase&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;I appreciated the clarity around when and how the change would happen. You’d be shocked at how often this is missed! As well as that, they gave me at least a month’s warning so that it wouldn’t come as a surprise.&lt;/p&gt;



&lt;p&gt;However, this time there was no clear table overview, just a list of changes — many of which I wasn’t personally interested in:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Number of classes: &lt;/strong&gt;“12,000 classes” does sound impressive, though at a certain point it borders on unnecessary — that’s 32 years’ worth of daily classes&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Club Peloton: &lt;/strong&gt;feels like something they use for engagement versus something I should pay more for&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Injury prevention: &lt;/strong&gt;whilst that in itself is interesting, the way it was phrased around Special Surgery meant I wasn’t sure if it was relevant for me&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Personalized Training with Peloton IQ: &lt;/strong&gt;felt a bit vague — I wasn’t sure what this was, I think it was a few stats I’d received whilst using the app which were helpful, but didn’t really change my training&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;But there was one line in the email really threw me off:&lt;/p&gt;



&lt;p&gt;“Breathwrk, now a part of Peloton — science-backed breathing exercises to help you reduce stress, recover faster, and stay focused.”&lt;/p&gt;



&lt;p&gt;What is Breathwrk?! I hadn’t seen any breathing content in the app, nor was it something I’d been looking for; I already used Calm for that. It feltThis would be like a hotel upgrading your room to include a karaoke machine — very cool, probably fun for someone, but completely irrelevant to why I booked the room — something you never asked for, and then charging you for it!&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-takeaway-4-communicate-major-new-offerings-in-app-before-the-price-increase&quot;&gt;Takeaway 4: Communicate major new offerings in-app before the price increase&lt;/h3&gt;



&lt;p&gt;Ironically, I only understood what &lt;a href=&quot;https://www.breathwrk.com/&quot;&gt;Breathwrk&lt;/a&gt; was after I canceled. It turned out to be a separate app Peloton had partnered with, but I never saw it mentioned anywhere inside the product.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-22-1024x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-49754&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-22-1024x1024.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-22-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-22-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-22-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-22-1536x1536.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-22-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-22-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-22-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-22-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-22-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-22-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-22-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-22-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-22-48x48.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-22.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;em&gt;Source: Breathwrk&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;I might have actually used it, or at least recognized it as added value, if it had been communicated before the price increase. A quick check of my inbox confirmed: they’d never emailed me about it either.&lt;/p&gt;



&lt;p&gt;While it’s fine to highlight new features in a price increase email, this felt like over-explaining. Like attempted justification. A better approach is to &lt;strong&gt;show the value first, let users experience it, then communicate the price change&lt;/strong&gt;. If you can’t ensure users have seen the updates, add more communication to build excitement before raising costs.&lt;/p&gt;



&lt;p&gt;This sounds like an excellent partnership for them, but a pricing email might not be the time to name-drop it without any context.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-interval-4-searching-for-another-membership-option&quot;&gt;Interval 4: searching for another membership option&lt;/h2&gt;



&lt;p&gt;Now, I’d be remiss not to acknowledge Peloton’s &lt;a href=&quot;https://www.revenuecat.com/blog/growth/2025-app-monetization-trends/&quot;&gt;hybrid monetization model&lt;/a&gt;. They combine an in-app subscription with a physical product, which is a powerful move. But, while it’s bold, it also leaves very little room for choice.&lt;/p&gt;



&lt;p&gt;I’d already realized I needed the top-tier subscription to unlock the bike’s full potential. Then, after a 15% price increase, I started hunting for alternatives that would let me keep using my bike: could I downgrade to a lower-tier subscription?&lt;/p&gt;



&lt;p&gt;The answer was a solid &lt;strong&gt;no.&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;726&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-10-1024x726.png&quot; alt=&quot;&quot; class=&quot;wp-image-49730&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-10-1024x726.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-10-300x213.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-10-768x545.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-10-50x35.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-10-56x40.png 56w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-10-654x464.png 654w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-10-696x494.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-10-560x397.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-10-417x296.png 417w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-10-665x472.png 665w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-10-80x57.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-10-48x34.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-10.png 1108w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;em&gt;Peloton subscription options&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;To give credit where it’s due, Peloton’s app subscriptions &lt;em&gt;do&lt;/em&gt; offer a sense of choice:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Monthly vs. annual subscriptions&lt;/li&gt;



&lt;li&gt;A ‘basics’ tier, or access to all workout types&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;These options give users flexibility, at least on paper, but when it comes to actually using the bike I already own, that flexibility disappears. Once you’ve committed to the top tier, there’s little room to adjust without losing access to features you’ve grown attached to.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;924&quot; height=&quot;919&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-1.png&quot; alt=&quot;&quot; class=&quot;wp-image-49710&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-1.png 924w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-1-300x298.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-1-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-1-768x764.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-1-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-1-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-1-467x464.png 467w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-1-696x692.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-1-560x557.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-1-298x296.png 298w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-1-475x472.png 475w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-1-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-1-48x48.png 48w&quot; sizes=&quot;auto, (max-width: 924px) 100vw, 924px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;em&gt;App One vs. App+ plan&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;I liked that Peloton offers options here, but I quickly realized that with my All Access subscription, the only choice was at £45/month. It almost felt like I was being punished for having the bike: some classes I could use on other equipment, but for the Peloton bike itself, access came at a premium.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-takeaway-5-reward-customers-who-invest-in-your-brand&quot;&gt;Takeaway 5: reward customers who invest in your brand&lt;/h3&gt;



&lt;p&gt;Rather than penalize someone for buying pricey equipment, reward them with better pricing to keep them loyal. Imagine if it were more expensive to use Peloton on other bikes?&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Suddenly, buying the bike, treadmill, or other equipment becomes an investment that pays off for sticking around. I’ve always hated how endless discounts are offered to new customers while existing users aren’t acknowledged for their loyalty.&lt;/p&gt;



&lt;p&gt;A simple way Peloton could have done this is by ensuring that it is cheaper to use the app with their equipment vs. other brands, or delaying the price increase for existing subscribers.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-takeaway-6-give-customers-a-sense-of-choice&quot;&gt;Takeaway 6: give customers a sense of choice&lt;/h3&gt;



&lt;p&gt;Have you ever told a kid to eat broccoli? Chances are, it didn’t go well, for you or for the broccoli. But I learned a valuable lesson from my cousins when dealing with little ones under five: make it seem like an option. “Do you want to eat the broccoli or the carrots?” Suddenly, vegetables are being consumed either way, and we can all breathe a sigh of relief.&lt;/p&gt;



&lt;p&gt;The takeaway? We all like to feel like we have a choice (even if it’s between two pre-selected options).&lt;/p&gt;



&lt;p&gt;Peloton does this well with their standard app subscriptions, but I missed it when it came to owning Peloton equipment: one subscription, one duration. There was no way to scale back usage (e.g. subscribe for 4x a month) or pay upfront for a year to save.&lt;/p&gt;



&lt;p&gt;From a psychological perspective, this matters. Research on &lt;a href=&quot;https://www.revenuecat.com/blog/growth/solve-app-problems-emotionally/&quot;&gt;self-determination theory&lt;/a&gt; shows that autonomy is a key driver of user satisfaction. When customers feel trapped by pricing or product limitations, perceived value drops fast, even if the product hasn’t changed. Monthly subscriptions may allow companies to charge more, but they also make it easier for users to say stop.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-interval-5-so-i-canceled-my-subscription&quot;&gt;Interval 5: so I canceled my subscription&lt;/h2&gt;



&lt;p&gt;I apologized to my bike and went to cancel, thinking a monthly plan would make it easy to restart if I missed it.&lt;/p&gt;



&lt;p&gt;That’s when things got a bit messy. I logged in on my phone… no subscription showing. Checked the website… still nothing. Confused, I contacted customer service.&lt;/p&gt;



&lt;p&gt;First impressions: they were super helpful. No fuss, no issues. My subscription was stopped just days before the renewal. I really want to celebrate Peloton for this, as I’ve known some brands that make canceling near-impossible. I won’t name names…this time.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-7 is-layout-flex wp-block-gallery-is-layout-flex&quot;&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;472&quot; height=&quot;1024&quot; data-id=&quot;49728&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-9-472x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-49728&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-9-472x1024.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-9-138x300.png 138w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-9-708x1536.png 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-9-23x50.png 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-9-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-9-214x464.png 214w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-9-696x1509.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-9-258x560.png 258w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-9-137x296.png 137w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-9-218x472.png 218w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-9-37x80.png 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-9-22x48.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-9.png 738w&quot; sizes=&quot;auto, (max-width: 472px) 100vw, 472px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;472&quot; height=&quot;1024&quot; data-id=&quot;49732&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-11-472x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-49732&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-11-472x1024.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-11-138x300.png 138w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-11-708x1536.png 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-11-23x50.png 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-11-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-11-214x464.png 214w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-11-696x1509.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-11-258x560.png 258w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-11-137x296.png 137w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-11-218x472.png 218w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-11-37x80.png 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-11-22x48.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-11.png 738w&quot; sizes=&quot;auto, (max-width: 472px) 100vw, 472px&quot;&gt;&lt;/figure&gt;
&lt;/figure&gt;



&lt;p&gt;&lt;em&gt;Chat conversation to cancel subscription&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;But then I waited for the questions… Why did I want to cancel my subscription? Did they want my feedback?&lt;/p&gt;



&lt;p&gt;They didn’t come. Maybe they’d include a survey in the confirmation email later.&lt;/p&gt;



&lt;p&gt;The confirmation email arrived… and still, no survey.&lt;/p&gt;



&lt;p&gt;It felt like dumping someone with a heartfelt speech, only to get a shrug. Like, don’t you want to know why I’m ending it? Don’t you feel desperate to find out if there’s someone else? (For the record: I &lt;em&gt;never&lt;/em&gt; cheated on Peloton.)&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;472&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-12-472x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-49734&quot; style=&quot;width:400px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-12-472x1024.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-12-138x300.png 138w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-12-708x1536.png 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-12-23x50.png 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-12-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-12-214x464.png 214w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-12-696x1509.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-12-258x560.png 258w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-12-137x296.png 137w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-12-218x472.png 218w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-12-37x80.png 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-12-22x48.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-12.png 738w&quot; sizes=&quot;auto, (max-width: 472px) 100vw, 472px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;em&gt;Confirmation of subscription cancelled&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;Overall, Peloton did a lot of things well:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Super clear confirmation that your account is cancelled — no fluff or noise&lt;/li&gt;



&lt;li&gt;No guilt-tripping; it showed understanding&lt;/li&gt;



&lt;li&gt;Clear timeline so you know when changes take effect&lt;/li&gt;



&lt;li&gt;Easy instructions for how to restart or change your subscription&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The missed opportunity? After a conversation and an email, I was never once asked to explain why. This is valuable feedback for a brand.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-takeaway-7-make-cancelling-an-enjoyable-experience&quot;&gt;Takeaway 7: make cancelling an enjoyable experience&lt;/h3&gt;



&lt;p&gt;Hiding cancellations or creating a complicated process never pays off. I don’t know why my membership didn’t show up on my account at first — probably a glitch across devices — but once I contacted support, everything was handled politely, and I was able to cancel in two minutes.&lt;/p&gt;



&lt;p&gt;Even if some people cancel directly through the app store, for web or &lt;a href=&quot;https://www.revenuecat.com/blog/company/introducing-customer-center/#:~:text=Go%20to%20the%20Projects%20in,like%20Cancellation%20and%20Refund%20Request.&quot;&gt;in-app subscriptions&lt;/a&gt;, a clear, simple cancellation flow is key.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-takeaway-8-ensure-you-have-a-clean-cancellation-email&quot;&gt;Takeaway 8: ensure you have a ‘clean’ cancellation email&lt;/h3&gt;



&lt;p&gt;A good cancellation email covers:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Confirmation that the subscription has been cancelled&lt;/li&gt;



&lt;li&gt;When the account stops&lt;/li&gt;



&lt;li&gt;A thank-you for being a subscriber&lt;/li&gt;



&lt;li&gt;A chance to provide feedback if they haven’t already&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Keep it short, concise, and skip the “DON’T ABANDON US” panic. Guilt tripping isn’t professional, and doesn’t work.&lt;/p&gt;



&lt;p&gt;So about that feedback…&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-interval-6-i-got-a-feedback-request&quot;&gt;Interval 6: I got a feedback request!&lt;/h2&gt;



&lt;p&gt;I did eventually get a survey, but I’m not 100% convinced it was because I cancelled. It was a Net Promoter Score (NPS) survey.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;472&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-5-472x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-49718&quot; style=&quot;width:400px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-5-472x1024.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-5-138x300.png 138w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-5-708x1536.png 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-5-23x50.png 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-5-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-5-214x464.png 214w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-5-696x1509.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-5-258x560.png 258w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-5-137x296.png 137w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-5-218x472.png 218w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-5-37x80.png 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-5-22x48.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-5.png 738w&quot; sizes=&quot;auto, (max-width: 472px) 100vw, 472px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;em&gt;NPS survey email&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;Interesting timing, right after cancelling? I rolled with it anyway.&lt;/p&gt;



&lt;p&gt;Answering the questions, it became clear the timing probably wasn’t intentional, as the survey didn’t seem to even know my subscription had been canceled:&lt;/p&gt;



&lt;figure class=&quot;wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-8 is-layout-flex wp-block-gallery-is-layout-flex&quot;&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;472&quot; height=&quot;1024&quot; data-id=&quot;49714&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-3-472x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-49714&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-3-472x1024.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-3-138x300.png 138w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-3-708x1536.png 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-3-23x50.png 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-3-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-3-214x464.png 214w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-3-696x1509.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-3-258x560.png 258w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-3-137x296.png 137w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-3-218x472.png 218w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-3-37x80.png 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-3-22x48.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-3.png 738w&quot; sizes=&quot;auto, (max-width: 472px) 100vw, 472px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;472&quot; height=&quot;1024&quot; data-id=&quot;49716&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-4-472x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-49716&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-4-472x1024.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-4-138x300.png 138w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-4-708x1536.png 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-4-23x50.png 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-4-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-4-214x464.png 214w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-4-696x1509.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-4-258x560.png 258w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-4-137x296.png 137w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-4-218x472.png 218w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-4-37x80.png 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-4-22x48.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-4.png 738w&quot; sizes=&quot;auto, (max-width: 472px) 100vw, 472px&quot;&gt;&lt;/figure&gt;
&lt;/figure&gt;



&lt;p&gt;&lt;em&gt;Questions in the feedback survey&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;I couldn’t select “I don’t have a membership” for the statement, “I’m happy with my Peloton membership”.&lt;/p&gt;



&lt;p&gt;For Peloton, I wasn’t a raging ex blocked on all social media; I was the ex you’re still friends with, where potential still exists. But even then, you don’t ask your ex:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Am I evolving to meet your needs?&lt;/li&gt;



&lt;li&gt;Do I value you as a friend/partner?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;It felt… weird. If I &lt;em&gt;had&lt;/em&gt; been the raging ex:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Let’s be honest, I probably wouldn’t have given feedback&lt;/li&gt;



&lt;li&gt;This would have annoyed me even more&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Still, I played the game, social niceties and all, trying to answer as best I could, even though I couldn’t indicate “I’ve cancelled!”&amp;nbsp;&lt;/p&gt;



&lt;p&gt;What Peloton did get right, though, was checking whether I’d seen their announcements.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;472&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-15-472x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-49740&quot; style=&quot;width:400px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-15-472x1024.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-15-138x300.png 138w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-15-708x1536.png 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-15-23x50.png 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-15-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-15-214x464.png 214w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-15-696x1509.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-15-258x560.png 258w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-15-137x296.png 137w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-15-218x472.png 218w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-15-37x80.png 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-15-22x48.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-15.png 738w&quot; sizes=&quot;auto, (max-width: 472px) 100vw, 472px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;em&gt;Asking about which features I’d seen&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;A bit of a random mention, but too often apps assume their users just know what they’re doing. The other day, I discovered a core feature in an app I’d been using daily for three weeks, oops.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-takeaway-9-have-a-specific-feedback-form-post-cancellation&quot;&gt;Takeaway 9: have a specific feedback form post cancellation&lt;/h3&gt;



&lt;p&gt;Keep it short, and ideally link it to the moment of cancellation to gather insights on why users are leaving. Here’s more on the &lt;a href=&quot;https://www.revenuecat.com/blog/growth/app-cancellation-flow-best-practices/&quot;&gt;best practices of a strong cancellation survey&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;To give Peloton some grace (told you I’m a nice ex), they did send a survey one day after I cancelled and noted that the system takes 72 hours to update. Maybe I just got unlucky with an NPS survey during that window. That said… I still haven’t received my actual cancellation survey.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-cooldown-life-after-peloton&quot;&gt;The cooldown: life after Peloton&lt;/h2&gt;



&lt;p&gt;What surprised me most was how emotional the experience felt. I’d built rituals around Peloton: the instructors, the playlists, the feeling of showing up for myself. That emotional connection kept me subscribed longer than any discount ever could. But once that connection faded, the price increase simply accelerated my exit.&lt;/p&gt;



&lt;p&gt;For other apps, this is a powerful reminder: retention isn’t just about utility, &lt;a href=&quot;https://www.revenuecat.com/blog/growth/solve-app-problems-emotionally/&quot;&gt;it’s about identity and belonging&lt;/a&gt;. Once users stop feeling seen or progressing, they stop showing up.&lt;/p&gt;



&lt;p&gt;It had nothing to do with working out; I’m still a fitness addict, training six days a week. Since cancelling, I’ve been testing a new app that I love: it challenges me, tracks my weights and reps, and shows me tangible progress.&lt;/p&gt;



&lt;p&gt;But it doesn’t include biking workouts. And my Peloton bike, still sitting in my workout space, quietly calls me as the nights get darker and the days rainier.&lt;/p&gt;



&lt;p&gt;I gave it a go without a subscription. Two short free classes brought back a wave of nostalgia. It was like running into my ex at the coffee shop we used to visit together.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;768&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-768x1024.jpeg&quot; alt=&quot;&quot; class=&quot;wp-image-49720&quot; style=&quot;width:400px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-768x1024.jpeg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-225x300.jpeg 225w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-1152x1536.jpeg 1152w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-38x50.jpeg 38w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-30x40.jpeg 30w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-348x464.jpeg 348w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-696x928.jpeg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-420x560.jpeg 420w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-222x296.jpeg 222w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-354x472.jpeg 354w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-60x80.jpeg 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image-36x48.jpeg 36w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2026/01/image.jpeg 1200w&quot; sizes=&quot;auto, (max-width: 768px) 100vw, 768px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;em&gt;The free tester class&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;Peloton’s story isn’t unique to fitness apps. Every subscription app faces the same challenge: evolving alongside its users. Whether you’re building a meditation, language-learning, or gaming app, these lessons are universal:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Help users get value fast&lt;/li&gt;



&lt;li&gt;Explain how personalization works&lt;/li&gt;



&lt;li&gt;Evolve with users as their goals change&lt;/li&gt;



&lt;li&gt;Communicate new value before raising prices&lt;/li&gt;



&lt;li&gt;Reward loyal customers, don’t penalize them&lt;/li&gt;



&lt;li&gt;Offer flexible, fair pricing options&lt;/li&gt;



&lt;li&gt;Make cancellation simple and respectful&lt;/li&gt;



&lt;li&gt;Send clear, thoughtful confirmation emails&lt;/li&gt;



&lt;li&gt;Collect timely, relevant feedback&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;When users feel both understood and in control, retention follows naturally.&lt;/p&gt;



&lt;p&gt;For now, it wasn’t enough to bring me back, but I’m not ready to sell the bike either. Maybe, in time, we’ll find a way to make this expensive relationship work again…&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Reduce support time with auto-attached app diagnostics]]></title><description><![CDATA[Add app diagnostics to support emails automatically and resolve issues faster with full context.]]></description><link>https://www.revenuecat.com/blog/company/customer-center-support-email-meta-data/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/company/customer-center-support-email-meta-data/</guid><pubDate>Wed, 31 Dec 2025 13:35:44 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Customer-Center-Support-Emails.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Most support emails start the same way:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“The app does not work!”&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;No device info. No OS version. No context. Your team wastes time asking follow-up questions and your customer waits for help.&lt;/p&gt;



&lt;p&gt;You can fix that in one afternoon. Add a small diagnostics block to support emails your app sends. It gives your team everything they need to solve problems fast and your customers get better support without back-and-forth.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-give-your-team-context-before-the-first-reply&quot;&gt;Give your team context before the first reply&lt;/h2&gt;



&lt;p&gt;Without context, support tickets turn into guesswork. Agents can’t see the customer’s setup or state. Maybe notifications are disabled, or large text pushed buttons off-screen.&lt;/p&gt;



&lt;p&gt;Adding metadata changes that. When every support email includes the customer’s environment, accessibility settings, and subscription state, agents can spot the issue immediately instead of asking for details.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-add-a-diagnostics-block-that-explains-the-problem-before-the-customer-does&quot;&gt;Add a diagnostics block that explains the problem before the customer does&lt;/h2&gt;



&lt;p&gt;Include a compact summary of the customer’s setup in each support email. Include the granted or denied permissions, important configuration options that might affect the user experience in the app. It might look something like this:&lt;/p&gt;



&lt;pre class=&quot;wp-block-code&quot;&gt;&lt;code&gt;App: 3.5.2 (302) • iOS 17.2 • iPhone 14
Notifications: allowed (alert/badge/sound)
Text size: XL (Accessibility Large)
Locale/TZ: en-US / PST
Network: reachable (Wi-Fi)
RC User ID: abcd1234 • entitlement=active
Last screen: Paywall • Last sync: 2025-10-14T09:32Z

&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;This one block replaces several messages of troubleshooting. Keep it short and human-readable. Five to seven lines is plenty.&lt;/p&gt;



&lt;p&gt;Include details that help the agent act fast: app version, OS, permissions, accessibility settings, locale, timezone, and key RevenueCat context like user ID and entitlement status. Avoid personal data or tokens, and mention in your help center that diagnostics are attached to support emails.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-build-it-yourself-in-a-few-lines-of-code&quot;&gt;Build it yourself in a few lines of code&lt;/h2&gt;



&lt;p&gt;You can add this now. On iOS or Android, pull data like notification settings, device info, locale, and entitlement status.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-track-how-much-faster-support-gets&quot;&gt;Track how much faster support gets&lt;/h3&gt;



&lt;p&gt;Once diagnostics are attached, measure the impact. Look at first-response time, time-to-resolution, and how often your support agents have to ask follow-up questions. You’ll see faster responses and fewer repetitive tickets.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-be-transparent-with-customers&quot;&gt;Be transparent with customers&lt;/h3&gt;



&lt;p&gt;Tell customers what’s included in the diagnostics and why. Keep it visible in your privacy notice or support screen. And if you want to go the extra mile, add a toggle so they can choose not to include it.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-handle-email-support-with-customer-center&quot;&gt;Handle email support with Customer Center&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;538&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Contact-Support-metadata-2-1024x538.png&quot; alt=&quot;&quot; class=&quot;wp-image-49662&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Contact-Support-metadata-2-1024x538.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Contact-Support-metadata-2-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Contact-Support-metadata-2-768x403.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Contact-Support-metadata-2-1536x806.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Contact-Support-metadata-2-2048x1075.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Contact-Support-metadata-2-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Contact-Support-metadata-2-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Contact-Support-metadata-2-696x365.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Contact-Support-metadata-2-560x294.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Contact-Support-metadata-2-840x441.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Contact-Support-metadata-2-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Contact-Support-metadata-2-48x25.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;If you don’t want to maintain your own diagnostic block, Customer Center does it for you.&lt;/p&gt;



&lt;p&gt;A new Support tab in Customer Center brings all your support email settings into one place. You can decide who sees the “Contact Support” action, set the address those messages go to, and connect tools like Intercom or Zendesk without touching code.&lt;/p&gt;



&lt;p&gt;The tab also adds a powerful improvement for debugging. You can turn on Support Metadata and Customer Center will attach a compact diagnostics block to every support email your customers send. It gives your team the context they need to resolve issues faster; app version, device details, permissions, subscription state, and other relevant signals.&lt;/p&gt;



&lt;p&gt;Everything runs server side. When a customer taps “Contact Support,” the email routes through RevenueCat, matches the message with backend data, and inserts the selected metadata into the footer before delivering it to your support inbox. You get accurate, up-to-date context without asking customers for screenshots or extra details, and your team cuts troubleshooting time dramatically.&lt;/p&gt;



&lt;p&gt;If you already rely on Zendesk or Intercom, the setup is automatic once you connect the integration. If you use a different tool, you can still forward emails normally and keep the metadata block intact. This update turns support emails into a reliable source of truth and makes Customer Center a complete home for managing support flows.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/tools/customer-center&quot;&gt;Add metadata to your support emails now.&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Craft, Seasonality, and the Long Game]]></title><description><![CDATA[On the podcast, I talk with Jordan about the power of seasonal business cycles, why refining your ad strategy can unlock growth, and how passion-driven apps can still find market fit without a huge marketing budget.]]></description><link>https://www.revenuecat.com/blog/growth/jordan-morgan-launched-podcast-2025/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/jordan-morgan-launched-podcast-2025/</guid><pubDate>Wed, 31 Dec 2025 13:29:17 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/LD-Blog-Cover-Jordan-Morgan-1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Jordan Morgan’s journey as an indie app developer is shaped by patience, experimentation, and a deep respect for craft. With years of experience building, selling, and even reacquiring apps, Jordan has navigated multiple phases of the indie landscape—from passion projects to sustainable businesses. Best known for apps like &lt;em&gt;Elite Hoops&lt;/em&gt; and &lt;em&gt;Alyx&lt;/em&gt;, Jordan’s work reflects a thoughtful balance between creativity and pragmatism.&lt;/p&gt;



&lt;p&gt;In this episode of &lt;em&gt;Launched&lt;/em&gt;, Jordan joins Charlie Chapman for an annual, reflective conversation on what it truly means to build apps that endure. Together, they explore seasonality, growth plateaus, paid acquisition, and the often-overlooked emotional side of long-term product building.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;The Balance Between Growth and Craft — Jordan Morgan, Elite Hoops&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/SpPlhaRH2Ck?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;iframe loading=&quot;lazy&quot; width=&quot;100%&quot; height=&quot;180&quot; frameborder=&quot;no&quot; scrolling=&quot;no&quot; seamless=&quot;&quot; src=&quot;https://share.transistor.fm/e/f8a7b4cf?color=FFFFFF&amp;amp;background=30343C&quot;&gt;&lt;/iframe&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-from-passion-project-to-sustainable-nbsp&quot;&gt;&lt;strong&gt;From Passion Project to Sustainable&amp;nbsp;&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;&lt;em&gt;Elite Hoops&lt;/em&gt;, Jordan’s flagship app for basketball coaches, began as a focused solution to a specific problem: helping coaches organize plays, drills, and practices more effectively. Over time, it evolved into a reliable, revenue-generating business—one defined not by explosive growth, but by consistency.&lt;/p&gt;



&lt;p&gt;Jordan explains that Elite Hoops is highly seasonal, with most revenue generated during the basketball season. Rather than fighting this reality, he embraced it. Each year, the app grows during peak months and stabilizes during the off-season, resulting in a steadily rising baseline. This predictable rhythm has enabled Jordan to reinvest with confidence, plan for the long term, and resist the pressure to chase constant growth.&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-learning-the-realities-of-acquisition-growth-vs-paid-nbsp&quot;&gt;&lt;strong&gt;Learning the Realities of Acquisition: Growth VS Paid&amp;nbsp;&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;A central theme of the conversation is Jordan’s evolving relationship with paid advertising. For years, he ran ads intuitively—without deep attribution or advanced tracking—relying instead on instinct and observation. While this approach worked early on, it eventually revealed its limits.&lt;/p&gt;



&lt;p&gt;By working with a professional marketing agency, Jordan began to understand where his growth was truly coming from. He discovered that seasonal demand and strong App Store search performance were driving much of &lt;em&gt;Elite Hoops’&lt;/em&gt; success, while some paid campaigns were offering little real impact. This realization marked a turning point: moving from indie intuition toward more disciplined, data-informed decision-making.&lt;/p&gt;



&lt;p&gt;The experience reinforced an important lesson—scaling sustainably often requires uncomfortable shifts, including better instrumentation, clearer attribution, and a willingness to admit what isn’t working.&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-reconnecting-with-craft-through-alyx&quot;&gt;&lt;strong&gt;Reconnecting with Craft Through Alyx&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Alongside the business-focused &lt;em&gt;Elite Hoops&lt;/em&gt;, Jordan built &lt;em&gt;Alyx&lt;/em&gt;, a caffeine-tracking app designed as a creative outlet. Unlike his sports apps, &lt;em&gt;Alyx&lt;/em&gt; was intentionally crafted as a playground for iOS features—integrating HealthKit, widgets, shortcuts, App Intents, and system-level APIs.&lt;/p&gt;



&lt;p&gt;&lt;em&gt;Alyx&lt;/em&gt; wasn’t built to maximize revenue. Instead, it served as a reminder of why Jordan started building apps in the first place: joy, curiosity, and craftsmanship. Shipping &lt;em&gt;Alyx&lt;/em&gt; alongside a new iOS release became a personal milestone, symbolizing a return to playful experimentation and platform-native design.&lt;/p&gt;



&lt;p&gt;This dual-track approach—one app focused on sustainability, the other on creative freedom—has allowed Jordan to balance business responsibility with creative fulfillment.&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-building-for-longevity-in-a-changing-indie-landscape&quot;&gt;&lt;strong&gt;Building for Longevity in a Changing Indie Landscape&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Jordan and Charlie also reflect on the broader indie ecosystem. They discuss how conversations around app development have shifted from craftsmanship toward growth metrics and monetization strategies, and how parts of the once-vibrant indie community have fragmented over time.&lt;/p&gt;



&lt;p&gt;Jordan’s perspective is grounded and optimistic. Rather than chasing trends, he believes longevity comes from solving real problems, respecting users, and staying aligned with personal values. Not every app needs to scale endlessly; some are meant to grow steadily, support their creators, and evolve thoughtfully over time.&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-conclusion&quot;&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Jordan Morgan’s story is not about overnight success or viral growth. It’s about building apps that last—through seasonality, plateaus, and changing platforms—while staying connected to the joy of making things well.&lt;/p&gt;



&lt;p&gt;Whether through a sustainable business like &lt;em&gt;Elite Hoops&lt;/em&gt; or a craft-driven passion project like &lt;em&gt;Alyx&lt;/em&gt;, Jordan’s journey offers a powerful reminder: meaningful products are built patiently, intentionally, and with a long-term mindset.&lt;/p&gt;



&lt;p&gt;For builders navigating the tension between craft and commerce, this episode is a thoughtful exploration of how to keep both alive—and why the long game is often the most rewarding one.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Paywalls now work on the web]]></title><description><![CDATA[Use the same paywalls on web and mobile, with one place to design, test, and update subscription flows.]]></description><link>https://www.revenuecat.com/blog/company/paywalls-on-the-web/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/company/paywalls-on-the-web/</guid><pubDate>Wed, 31 Dec 2025 13:12:59 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Web-Paywalls-1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;If you already use &lt;a href=&quot;https://www.revenuecat.com/feature/paywalls/&quot;&gt;RevenueCat Paywalls&lt;/a&gt; on mobile, you can now use those same paywalls in the browser.&lt;/p&gt;



&lt;p&gt;The paywalls you’ve designed for iOS and Android now render on the web, using the same layouts and components.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-one-paywall-across-mobile-and-web&quot;&gt;One paywall across mobile and web&lt;/h3&gt;



&lt;p&gt;Web paywalls aren’t a separate object or a new paywall type. They’re the web version of the paywalls you already create at the Offering level.&lt;/p&gt;



&lt;p&gt;An Offering can include mobile products, web products, or both. When it includes both, the same paywall layout serves mobile and web users.&lt;/p&gt;



&lt;p&gt;Your structure, copy, and experiments carry over automatically. You design a paywall once and use it across platforms.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-where-web-paywalls-show-up&quot;&gt;Where web paywalls show up&lt;/h3&gt;



&lt;p&gt;You can use web paywalls in two places, depending on how your product is set up.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Inside Web Purchase Links&lt;/strong&gt;&lt;br&gt;Web Purchase Links are RevenueCat-hosted checkout URLs. If a link uses the default package selection page, you can replace that step with your paywall.&lt;/p&gt;



&lt;p&gt;Users see your messaging, layout, and pricing context before checkout begins. You control the experience earlier in the flow, where it matters most.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Embedded in your web app with Purchases.js&lt;/strong&gt;&lt;br&gt;If you use Purchases.js, you can now render paywalls directly inside your web app. Call &lt;code&gt;presentPaywall&lt;/code&gt;, pass the HTML element where it should appear, and RevenueCat handles the rest.&lt;/p&gt;



&lt;p&gt;The paywall renders in place and continues into checkout without custom UI or hand-built flows.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-works-with-web-billing-and-paddle&quot;&gt;Works with Web Billing and Paddle&lt;/h3&gt;



&lt;p&gt;Web paywalls support both &lt;a href=&quot;https://www.revenuecat.com/billing/&quot;&gt;RevenueCat Web Billing&lt;/a&gt; and Paddle.&lt;/p&gt;



&lt;p&gt;Which products appear depends on the web config attached to the surface showing the paywall. A Web Purchase Link connected to a Paddle config shows Paddle products. Switch that same link to a Web Billing config and it shows Web Billing products instead.&lt;/p&gt;



&lt;p&gt;The paywall layout stays consistent while the product source changes based on configuration.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-change-paywalls-without-shipping-updates&quot;&gt;Change paywalls without shipping updates&lt;/h3&gt;



&lt;p&gt;Web paywalls are hosted and server driven.&lt;/p&gt;



&lt;p&gt;You can update copy, layouts, pricing blocks, and calls to action from the dashboard. When you publish, changes go live immediately.&lt;/p&gt;



&lt;p&gt;You can also target paywalls by country, platform, app version, or custom segments. Experiments work the same way they do on mobile, so you can test pricing, layout, or messaging on the web with the same tools.&lt;/p&gt;



&lt;p&gt;When something stops converting, you can respond the same day.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-run-subscriptions-from-one-place&quot;&gt;Run subscriptions from one place&lt;/h3&gt;



&lt;p&gt;You can embed web paywalls directly into your app or link to them through hosted URLs. Either way, you manage subscription flows for mobile and web from the same system, using the same paywalls and workflows.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/web/web-billing/paywalls&quot;&gt;Paywalls on the web are available now.&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[How Alper Taner Navigates the Evolving World of Mobile Growth]]></title><description><![CDATA[On the podcast I talk with Alper about the competitive advantage of ignoring (some) best practices, the risk of drawing false conclusions when researching competitor ads, and why poor metrics are just facts until proven problematic.]]></description><link>https://www.revenuecat.com/blog/growth/alper-taner-sub-club-podcast-2025/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/alper-taner-sub-club-podcast-2025/</guid><pubDate>Wed, 24 Dec 2025 14:48:37 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/RC-Blog-Cover-Alper-Taner-1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Alper Taner has spent over a decade in mobile growth, working across a wide range of verticals and managing large marketing budgets. In this episode, he shares his insights on what it takes to drive growth in today’s ever-changing app landscape.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;Challenging Best Practices in Mobile Growth – Alper Taner’s Secrets to Success&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/FF2GKgBi6ZI?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;iframe loading=&quot;lazy&quot; width=&quot;100%&quot; height=&quot;180&quot; frameborder=&quot;no&quot; scrolling=&quot;no&quot; seamless=&quot;&quot; src=&quot;https://share.transistor.fm/e/e845bea1?color=FFFFFF&amp;amp;background=30343C&quot;&gt;&lt;/iframe&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-focus-on-data-driven-decisions&quot;&gt;&lt;strong&gt;Focus on Data-Driven Decisions&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Alper emphasizes that while best practices can be helpful, they shouldn’t be followed blindly. The key is to prioritize what works for your specific app, based on your own data and current stage. Whether it’s testing creatives, bidding strategies, or incrementality, always ground your decisions in your app’s data, the same approach might not work for every account, so testing and adapting are crucial.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-don-t-rush-to-call-something-a-problem&quot;&gt;&lt;strong&gt;Don’t Rush to Call Something a Problem&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;One of Alper’s most critical insights is the importance of understanding the facts before reacting. For example, low trial conversions may seem problematic, but they may simply reflect the business model or user acquisition strategy. Test, iterate, and diagnose before labeling something as an issue. Often, low metrics are just the starting point for valuable insights.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-creative-testing-quality-over-quantity&quot;&gt;&lt;strong&gt;Creative Testing: Quality Over Quantity&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Alper challenges the standard approach of testing hundreds of creatives with little focus on why they work or don’t. He advocates for testing fewer creatives with strong hypotheses and focusing on what makes them successful. It’s not about the numbers—it’s about finding what resonates with your audience and optimizing accordingly. Vigorous creative testing should be both iterative and radical to uncover real winners.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-control-your-spend-guide-the-algorithm&quot;&gt;&lt;strong&gt;Control Your Spend, Guide the Algorithm&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;A major theme in Alper’s approach is taking control over your budget. He advises setting clear spend limits, adjusting bids based on performance, and using tools like budget caps to guide the algorithm. Don’t let platforms dictate your spend—use intelligent, strategic control to optimize your campaigns effectively.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-learn-from-competitors-but-don-t-copy&quot;&gt;&lt;strong&gt;Learn From Competitors, But Don’t Copy&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Alper cautions against blindly copying competitors. While it’s helpful to learn from what others are doing, the real value lies in customizing those insights for your app and audience. Competitor ads can inspire, but success comes from tailoring strategies to fit your unique goals and data.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-importance-of-accurate-data-and-instrumentation&quot;&gt;&lt;strong&gt;The Importance of Accurate Data and Instrumentation&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Accurate data is at the heart of Alper’s marketing approach. He stresses the importance of proper data instrumentation to ensure that you can make informed decisions. Whether it’s MMP, in-app analytics, or creative performance, interpreting data accurately is essential to guiding your marketing efforts and avoiding costly mistakes.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-a-holistic-approach-to-testing-and-learning&quot;&gt;&lt;strong&gt;A Holistic Approach to Testing and Learning&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Alper advocates for testing everything from bidding strategies to event mapping. He explains that small changes, like adjusting how events are mapped, can significantly impact performance. At the same time, always be open to radical testing—sometimes, doing the opposite of what’s commonly recommended can unlock new opportunities.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-conclusion&quot;&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Alper’s story is a reminder that in the world of mobile growth, success is about innovative experimentation, data-driven decisions, and constantly challenging what’s considered “best practice.” Be persistent, iterate based on results, and stay focused on long-term growth—it’s all about finding what truly works for your specific app and market.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Understanding Google Play’s subscription lifecycle: a complete guide]]></title><description><![CDATA[You will break down the complete Google Play subscription lifecycle in depth. ]]></description><link>https://www.revenuecat.com/blog/engineering/google-play-lifecycle/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/google-play-lifecycle/</guid><pubDate>Mon, 22 Dec 2025 00:05:47 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Understanding-Google-Plays-Subscription-Lifecycle_-A-Complete-Guide.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Managing subscription lifecycles on Android is one of the most complex aspects of in-app billing implementation. Subscriptions go through numerous states throughout their lifetime, from initial purchase to renewals, grace periods, account holds, pauses, cancellations, and eventual expiration. Each state transition requires specific handling in your app to ensure users receive the correct entitlements, while your backend maintains accurate subscription records. Understanding these lifecycle events is essential for building a robust subscription system that minimizes involuntary churn and provides a seamless user experience.&lt;/p&gt;



&lt;p&gt;To make it a little clearer, you will break down the complete Google Play subscription lifecycle in depth. We’ll cover every subscription state and the transitions between them, examine how Real-Time Developer Notifications (RTDN) inform your backend of changes, understand the differences between auto-renewing and prepaid subscriptions, and see how proper lifecycle handling can recover revenue from failed payments. Finally, we’ll look at how &lt;a href=&quot;https://www.revenuecat.com/&quot;&gt;RevenueCat&lt;/a&gt; simplifies this complexity by abstracting away much of the lifecycle management.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-subscription-lifecycle-at-a-glance&quot;&gt;&lt;strong&gt;The subscription lifecycle at a glance&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Before diving into the details, let’s establish a mental model of how subscriptions flow through different states. A subscription begins with a purchase, enters an active state, and eventually either renews successfully, encounters payment issues, gets canceled, or expires. The complexity arises from the numerous intermediate states and recovery mechanisms that Google Play provides.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;983&quot; height=&quot;531&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-22-at-9.39.57-AM.png&quot; alt=&quot;&quot; class=&quot;wp-image-49469&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-22-at-9.39.57-AM.png 983w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-22-at-9.39.57-AM-300x162.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-22-at-9.39.57-AM-768x415.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-22-at-9.39.57-AM-50x27.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-22-at-9.39.57-AM-74x40.png 74w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-22-at-9.39.57-AM-696x376.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-22-at-9.39.57-AM-560x303.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-22-at-9.39.57-AM-548x296.png 548w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-22-at-9.39.57-AM-840x454.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-22-at-9.39.57-AM-80x43.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-22-at-9.39.57-AM-48x26.png 48w&quot; sizes=&quot;auto, (max-width: 983px) 100vw, 983px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Each state has specific implications for user entitlements and requires different handling in your app and backend.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;new-subscription-purchases&quot;&gt;&lt;strong&gt;New subscription purchases&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;When a user purchases a subscription, your app receives a &lt;code&gt;SUBSCRIPTION_PURCHASED&lt;/code&gt; notification, and the subscription enters the &lt;code&gt;SUBSCRIPTION_STATE_ACTIVE&lt;/code&gt; state. This is the starting point of the lifecycle.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-critical-acknowledgment-requirement&quot;&gt;&lt;strong&gt;The critical acknowledgment requirement&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;One of the most important aspects of handling new purchases is &lt;strong&gt;acknowledgment&lt;/strong&gt;. Google Play requires you to acknowledge a subscription purchase within &lt;strong&gt;three days&lt;/strong&gt; of the transaction. If you fail to acknowledge within this window, the user automatically receives a refund, and the subscription is revoked.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-rRqxy wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;private fun processPurchase(purchase: Purchase) {\n    if (purchase.purchaseState == Purchase.PurchaseState.PURCHASED) {\n        \/\/ Verify the purchase with your backend first\n        verifyPurchaseWithBackend(purchase) { isValid -&gt;\n            if (isValid &amp;amp;&amp;amp; !purchase.isAcknowledged) {\n                val params = AcknowledgePurchaseParams.newBuilder()\n                    .setPurchaseToken(purchase.purchaseToken)\n                    .build()\n\n                billingClient.acknowledgePurchase(params) { result -&gt;\n                    if (result.responseCode == BillingClient.BillingResponseCode.OK) {\n                        grantEntitlement(purchase)\n                    }\n                }\n            }\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The acknowledgment serves as confirmation that you have granted the user access to their purchased content. It’s a safeguard that protects users from situations where a purchase succeeds on Google’s side but fails to register in your app.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;understanding-the-purchase-response&quot;&gt;&lt;strong&gt;Understanding the purchase response&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;When you query a new subscription purchase using the &lt;code&gt;purchases.subscriptionsv2.get&lt;/code&gt; API endpoint, you receive detailed information about the subscription state:&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Field&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Value for new purchase&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;subscriptionState&lt;/td&gt;&lt;td&gt;SUBSCRIPTION_STATE_ACTIVE&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;acknowledgementState&lt;/td&gt;&lt;td&gt;ACKNOWLEDGEMENT_STATE_PENDING&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;autoRenewEnabled&lt;/td&gt;&lt;td&gt;true&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;expiryTime&lt;/td&gt;&lt;td&gt;Next renewal date&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;The &lt;code&gt;expiryTime&lt;/code&gt; field indicates when the current billing period ends and renewal will be attempted. For a monthly subscription purchased on January 15, this would be February 15.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;linking-purchases-to-user-accounts&quot;&gt;&lt;strong&gt;Linking purchases to user accounts&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Google Play provides &lt;code&gt;ExternalAccountIdentifiers&lt;/code&gt; to help you associate purchases with user accounts in your system. When configuring the billing flow, you can pass your internal user ID:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z258UuL wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;val billingFlowParams = BillingFlowParams.newBuilder()\n    .setProductDetailsParamsList(productDetailsParamsList)\n    .setObfuscatedAccountId(userId.hashCode().toString())\n    .setObfuscatedProfileId(profileId.hashCode().toString())\n    .build()&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;These identifiers are returned in the purchase response and RTDN notifications, allowing your backend to correctly attribute purchases to user accounts even in edge cases like upgrades, downgrades, or resubscriptions.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;subscription-renewals&quot;&gt;&lt;strong&gt;Subscription renewals&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;For auto-renewing subscriptions, Google Play automatically attempts to charge the user’s payment method when the billing period ends. Successful renewals trigger a &lt;code&gt;SUBSCRIPTION_RENEWED&lt;/code&gt; notification.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;what-happens-on-successful-renewal&quot;&gt;&lt;strong&gt;What happens on successful renewal&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;When a subscription renews successfully, the subscription remains in &lt;code&gt;SUBSCRIPTION_STATE_ACTIVE&lt;/code&gt;, and the &lt;code&gt;expiryTime&lt;/code&gt; is updated to reflect the new billing period. Importantly, &lt;strong&gt;renewals do not require acknowledgment,&lt;/strong&gt; only the initial purchase does.&lt;/p&gt;



&lt;p&gt;Your backend should update the stored expiry time when receiving the renewal notification:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZTC5TJ wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;fun handleRenewalNotification(notification: SubscriptionNotification) {\n    val purchaseToken = notification.purchaseToken\n\n    \/\/ Query latest subscription state\n    val subscription = playDeveloperApi\n        .purchases()\n        .subscriptionsv2()\n        .get(packageName, purchaseToken)\n        .execute()\n\n    \/\/ Update stored expiry time\n    val newExpiryTime = subscription.lineItems[0].expiryTime\n    subscriptionRepository.updateExpiryTime(purchaseToken, newExpiryTime)\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;renewal-date-behavior&quot;&gt;&lt;strong&gt;Renewal date behavior&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Google Play follows specific rules for renewal dates that you should be aware of:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Subscriptions started on 29, 30, or 31 of a month will renew on day 28 (or 29 in leap years) when the following month has fewer days&lt;/li&gt;



&lt;li&gt;Once a renewal shifts to an earlier date (like 28), it stays on that date for subsequent months&lt;/li&gt;



&lt;li&gt;For example, a subscription starting March 31 renews April 30, then May 30, June 30, and so on&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;This behavior can affect analytics if you’re tracking renewal patterns, so keep it in mind when building reports.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;grace-periods-the-first-line-of-defense&quot;&gt;&lt;strong&gt;Grace periods: the first line of defense&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;When a renewal payment fails, Google Play doesn’t immediately suspend the subscription. Instead, it enters a &lt;strong&gt;grace period:&lt;/strong&gt; a recovery window during which the user retains full access while Google retries the payment.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;grace-period-configuration&quot;&gt;&lt;strong&gt;Grace period configuration&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Grace periods are enabled by default in the Play Console and can be configured per subscription:&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Billing period&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Available grace period options&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Weekly&lt;/td&gt;&lt;td&gt;3, 7 days&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Monthly&lt;/td&gt;&lt;td&gt;7, 14, 30 days&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Annual&lt;/td&gt;&lt;td&gt;7, 14, 30 days&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;During the grace period, the subscription state changes to &lt;code&gt;SUBSCRIPTION_STATE_IN_GRACE_PERIOD&lt;/code&gt;, but &lt;code&gt;autoRenewEnabled&lt;/code&gt; remains &lt;code&gt;true&lt;/code&gt; because the user hasn’t canceled; they just have a payment issue.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;handling-grace-period-in-your-app&quot;&gt;&lt;strong&gt;Handling grace period in your app&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;When you detect a user is in the grace period, you should encourage them to update their payment method. Google provides the In-App Messaging API to display a standardized payment update dialog:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1nGwYg wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;fun checkAndShowGracePeriodMessage(activity: Activity) {\n    val inAppMessageParams = InAppMessageParams.newBuilder()\n        .addInAppMessageCategoryToShow(InAppMessageParams.InAppMessageCategoryId.SUBSCRIPTION_GRACE_PERIOD)\n        .build()\n\n    billingClient.showInAppMessages(activity, inAppMessageParams) { result -&gt;\n        if (result.responseCode == InAppMessageResult.InAppMessageResponseCode.NO_ACTION_NEEDED) {\n            \/\/ No message was shown - user might have already fixed payment\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The key point is that &lt;strong&gt;users retain access during the grace period&lt;/strong&gt;. Your app should continue providing the subscribed features while simultaneously nudging users to fix their payment method.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;silent-grace-period&quot;&gt;&lt;strong&gt;Silent grace period&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Even if you configure a zero–day grace period in the Play Console, Google Play still provides a &lt;strong&gt;minimum one–day silent grace period&lt;/strong&gt; for payment processing retries. During this silent grace period, the subscription appears as &lt;code&gt;SUBSCRIPTION_STATE_ACTIVE&lt;/code&gt; (not &lt;code&gt;IN_GRACE_PERIOD&lt;/code&gt;).&lt;/p&gt;



&lt;p&gt;This is important to understand because you might receive a delayed notification about payment issues. After 24 hours, the subscription will transition to one of several states depending on the outcome:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;code&gt;SUBSCRIPTION_RENEWED&lt;/code&gt; if the retry succeeded&lt;/li&gt;



&lt;li&gt;&lt;code&gt;SUBSCRIPTION_ON_HOLD&lt;/code&gt; if account hold is enabled&lt;/li&gt;



&lt;li&gt;&lt;code&gt;SUBSCRIPTION_CANCELED&lt;/code&gt; if the user canceled during this time&lt;/li&gt;



&lt;li&gt;&lt;code&gt;SUBSCRIPTION_EXPIRED&lt;/code&gt; if no recovery mechanisms are enabled&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;account-hold-the-second-chance&quot;&gt;&lt;strong&gt;Account hold: the second chance&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;If the grace period expires without successful payment recovery, the subscription enters &lt;strong&gt;account hold&lt;/strong&gt;. This state represents a more serious payment failure where the user loses access to subscribed content.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;account-hold-duration&quot;&gt;&lt;strong&gt;Account hold duration&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Account hold is enabled by default with a duration of 60 days minus the grace period length. For example, if you have a seven–day grace period, account hold lasts 53 days. During this time:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;The subscription state is &lt;code&gt;SUBSCRIPTION_STATE_ON_HOLD&lt;/code&gt;&lt;/li&gt;



&lt;li&gt;The &lt;code&gt;expiryTime&lt;/code&gt; is set to a &lt;strong&gt;past timestamp&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;The subscription is &lt;strong&gt;not returned&lt;/strong&gt; by &lt;code&gt;queryPurchasesAsync()&lt;/code&gt;&lt;/li&gt;



&lt;li&gt;The user should lose access to premium features&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;user-experience-during-account-hold&quot;&gt;&lt;strong&gt;User experience during account hold&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Your app should detect when a user’s subscription is on hold and display appropriate messaging. Since subscriptions on hold are not returned by &lt;code&gt;queryPurchasesAsync()&lt;/code&gt;, you need to query your backend or the Google Play Developer API directly to check for this state:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z2rCwk4 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;class SubscriptionManager(\n    private val billingClient: BillingClient,\n    private val backendApi: BackendApi\n) {\n    suspend fun checkSubscriptionStatus(userId: String): SubscriptionState {\n        \/\/ First, check active purchases from Play Billing\n        val activePurchases = queryActivePurchases()\n\n        if (activePurchases.isNotEmpty()) {\n            return SubscriptionState.Active(activePurchases.first())\n        }\n\n        \/\/ No active purchases found - check backend for account hold\n        \/\/ Your backend should track subscription state from RTDN\n        val backendStatus = backendApi.getSubscriptionStatus(userId)\n\n        return when (backendStatus.state) {\n            \&amp;quot;SUBSCRIPTION_STATE_ON_HOLD\&amp;quot; -&gt; {\n                SubscriptionState.OnHold(\n                    purchaseToken = backendStatus.purchaseToken,\n                    holdStartTime = backendStatus.holdStartTime\n                )\n            }\n            \&amp;quot;SUBSCRIPTION_STATE_PAUSED\&amp;quot; -&gt; {\n                SubscriptionState.Paused(\n                    resumeTime = backendStatus.autoResumeTime\n                )\n            }\n            \&amp;quot;SUBSCRIPTION_STATE_CANCELED\&amp;quot; -&gt; {\n                SubscriptionState.Canceled(\n                    expiryTime = backendStatus.expiryTime\n                )\n            }\n            else -&gt; SubscriptionState.None\n        }\n    }\n\n    private suspend fun queryActivePurchases(): List&lt;Purchase&gt; {\n        return suspendCoroutine { continuation -&gt;\n            billingClient.queryPurchasesAsync(\n                QueryPurchasesParams.newBuilder()\n                    .setProductType(BillingClient.ProductType.SUBS)\n                    .build()\n            ) { billingResult, purchases -&gt;\n                if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {\n                    continuation.resume(purchases)\n                } else {\n                    continuation.resume(emptyList())\n                }\n            }\n        }\n    }\n}\n\n\/\/ In your Activity or ViewModel\nfun updateUIForSubscriptionState() {\n    lifecycleScope.launch {\n        when (val state = subscriptionManager.checkSubscriptionStatus(userId)) {\n            is SubscriptionState.Active -&gt; {\n                showPremiumContent()\n            }\n            is SubscriptionState.OnHold -&gt; {\n                \/\/ Show payment recovery UI with deep link to Play Store\n                showAccountHoldMessage()\n                showFixPaymentButton(state.purchaseToken)\n            }\n            is SubscriptionState.Paused -&gt; {\n                showPausedMessage(state.resumeTime)\n            }\n            is SubscriptionState.Canceled -&gt; {\n                \/\/ Still has access until expiry\n                showCanceledMessage(state.expiryTime)\n                showPremiumContent()\n            }\n            is SubscriptionState.None -&gt; {\n                showSubscriptionOffers()\n            }\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This implementation requires some infrastructure: your backend must receive and process RTDN notifications, store subscription state, and expose an API for your app to query. You also need to handle edge cases like network failures, state synchronization, and ensuring your backend state matches Google Play’s state.&lt;/p&gt;



&lt;p&gt;With RevenueCat SDK, this complexity is taken away entirely across platforms. RevenueCat processes RTDN notifications on your behalf and maintains subscription state that you can query with a single call:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1IvXS5 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;fun checkSubscriptionStatus() {\n    Purchases.sharedInstance.getCustomerInfoWith { customerInfo -&gt;\n        val entitlement = customerInfo.entitlements[\&amp;quot;premium\&amp;quot;]\n\n        when {\n            entitlement?.isActive == true -&gt; {\n                showPremiumContent()\n            }\n            entitlement?.billingIssueDetectedAt != null -&gt; {\n                \/\/ RevenueCat detected account hold or grace period\n                showPaymentRecoveryUI(customerInfo.managementURL)\n            }\n            entitlement != null -&gt; {\n                \/\/ Subscription exists but expired\n                showResubscribeOptions()\n            }\n            else -&gt; {\n                showSubscriptionOffers()\n            }\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;RevenueCat’s &lt;code&gt;CustomerInfo&lt;/code&gt; automatically reflects the current subscription state, including account hold status via the &lt;code&gt;billingIssueDetectedAt&lt;/code&gt; field. The &lt;code&gt;managementURL&lt;/code&gt; property provides a direct link to Google Play’s subscription management screen where users can fix their payment method.&lt;/p&gt;



&lt;p&gt;During account hold, users can still cancel, restore, or resubscribe. If they fix their payment method, you’ll receive a &lt;code&gt;SUBSCRIPTION_RECOVERED&lt;/code&gt; notification, and the subscription returns to &lt;code&gt;SUBSCRIPTION_STATE_ACTIVE&lt;/code&gt; with the &lt;strong&gt;same purchase token —&lt;/strong&gt; it’s a recovery, not a new purchase.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-billing-date-reset&quot;&gt;&lt;strong&gt;The billing date reset&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;An important detail: when a subscription recovers from account hold, the billing date resets to the recovery date. If a user’s subscription was originally set to renew on day 15 of each month, but they recover from account hold on day 22, their new renewal date becomes day 22.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;subscription-pausing&quot;&gt;&lt;strong&gt;Subscription pausing&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Google Play allows users to pause their subscriptions — a feature that can reduce cancellations by giving users a temporary break without losing their subscription entirely.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;pause-configuration-and-availability&quot;&gt;&lt;strong&gt;Pause configuration and availability&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Pause functionality is enabled by default in the Play Console but is only available for certain billing periods:&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Billing Period&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Available Pause Durations&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Weekly&lt;/td&gt;&lt;td&gt;1, 2, 3, 4 weeks&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Monthly&lt;/td&gt;&lt;td&gt;1, 2, 3 months&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Three-month&lt;/td&gt;&lt;td&gt;1, 2, 3 months&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Six-month&lt;/td&gt;&lt;td&gt;1, 2, 3 months&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Annual&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Not available&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;Annual subscriptions cannot be paused, this is a deliberate limitation because the pause period could potentially exceed the subscription duration.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-pause-lifecycle&quot;&gt;&lt;strong&gt;The pause lifecycle&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Pausing involves multiple notifications as the pause progresses through its stages:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;User initiates pause&lt;/strong&gt;: &lt;code&gt;SUBSCRIPTION_PAUSE_SCHEDULE_CHANGED&lt;/code&gt; notification
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;State remains &lt;code&gt;SUBSCRIPTION_STATE_ACTIVE&lt;/code&gt;&lt;/li&gt;



&lt;li&gt;User retains access until current billing period ends&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Pause takes effect&lt;/strong&gt;: &lt;code&gt;SUBSCRIPTION_PAUSED&lt;/code&gt; notification
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;State becomes &lt;code&gt;SUBSCRIPTION_STATE_PAUSED&lt;/code&gt;&lt;/li&gt;



&lt;li&gt;User loses access&lt;/li&gt;



&lt;li&gt;&lt;code&gt;PausedStateContext&lt;/code&gt; contains the expected resume date&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Subscription resumes&lt;/strong&gt;: &lt;code&gt;SUBSCRIPTION_RECOVERED&lt;/code&gt; notification
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Can be automatic (pause period ends) or manual (user resumes early)&lt;/li&gt;



&lt;li&gt;State returns to &lt;code&gt;SUBSCRIPTION_STATE_ACTIVE&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;If the user manually resumes their subscription before the pause period ends, their billing date changes to the date they resumed. This is similar to the billing date reset that occurs after account hold recovery.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;handling-pause-in-your-app&quot;&gt;&lt;strong&gt;Handling pause in your app&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Handling subscription pauses requires tracking multiple states and coordinating between your app and backend. The challenge is that paused subscriptions behave differently from other non-active states, a scheduled pause still grants access, while an active pause does not.&lt;/p&gt;



&lt;p&gt;Your backend needs to process RTDN notifications to track pause state changes:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z2ibnkE wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/\/ Backend notification handler\nclass SubscriptionNotificationHandler(\n    private val subscriptionRepository: SubscriptionRepository,\n    private val playDeveloperApi: AndroidPublisher\n) {\n    fun handleNotification(notification: DeveloperNotification) {\n        val purchaseToken = notification.subscriptionNotification.purchaseToken\n\n        when (notification.subscriptionNotification.notificationType) {\n            NotificationType.SUBSCRIPTION_PAUSE_SCHEDULE_CHANGED -&gt; {\n                \/\/ User scheduled a pause from Play Store subscription settings\n                val subscription = fetchSubscriptionDetails(purchaseToken)\n                val pauseInfo = subscription.lineItems[0].autoRenewingPlan?.pausedInfo\n\n                if (pauseInfo != null) {\n                    \/\/ Pause is scheduled - record when it will take effect\n                    subscriptionRepository.updatePauseSchedule(\n                        purchaseToken = purchaseToken,\n                        pauseScheduledAt = Instant.now(),\n                        pauseEffectiveAt = subscription.lineItems[0].expiryTime,\n                        autoResumeTime = pauseInfo.autoResumeTime\n                    )\n                } else {\n                    \/\/ User canceled the scheduled pause\n                    subscriptionRepository.clearPauseSchedule(purchaseToken)\n                }\n            }\n\n            NotificationType.SUBSCRIPTION_PAUSED -&gt; {\n                \/\/ Pause is now active - user loses access\n                val subscription = fetchSubscriptionDetails(purchaseToken)\n                val pausedContext = subscription.pausedStateContext\n\n                subscriptionRepository.updateSubscriptionState(\n                    purchaseToken = purchaseToken,\n                    state = SubscriptionState.PAUSED,\n                    autoResumeTime = pausedContext?.autoResumeTime\n                )\n            }\n\n            NotificationType.SUBSCRIPTION_RECOVERED -&gt; {\n                \/\/ Could be recovery from pause, account hold, or grace period\n                val subscription = fetchSubscriptionDetails(purchaseToken)\n\n                subscriptionRepository.updateSubscriptionState(\n                    purchaseToken = purchaseToken,\n                    state = SubscriptionState.ACTIVE,\n                    expiryTime = subscription.lineItems[0].expiryTime\n                )\n            }\n        }\n    }\n\n    private fun fetchSubscriptionDetails(purchaseToken: String): SubscriptionPurchaseV2 {\n        return playDeveloperApi\n            .purchases()\n            .subscriptionsv2()\n            .get(packageName, purchaseToken)\n            .execute()\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;On the client side, your app needs to query the backend to determine the current pause state and display appropriate UI:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-2fkmsO wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;class PauseStateManager(\n    private val backendApi: BackendApi,\n    private val billingClient: BillingClient\n) {\n    sealed class PauseState {\n        object NotPaused : PauseState()\n        data class PauseScheduled(\n            val currentPeriodEnd: Instant,\n            val autoResumeTime: Instant\n        ) : PauseState()\n        data class ActivelyPaused(\n            val autoResumeTime: Instant\n        ) : PauseState()\n    }\n\n    suspend fun checkPauseState(userId: String): PauseState {\n        val subscriptionStatus = backendApi.getSubscriptionStatus(userId)\n\n        return when (subscriptionStatus.state) {\n            \&amp;quot;SUBSCRIPTION_STATE_ACTIVE\&amp;quot; -&gt; {\n                \/\/ Check if pause is scheduled\n                if (subscriptionStatus.pauseScheduledAt != null) {\n                    PauseState.PauseScheduled(\n                        currentPeriodEnd = subscriptionStatus.expiryTime,\n                        autoResumeTime = subscriptionStatus.autoResumeTime!!\n                    )\n                } else {\n                    PauseState.NotPaused\n                }\n            }\n            \&amp;quot;SUBSCRIPTION_STATE_PAUSED\&amp;quot; -&gt; {\n                PauseState.ActivelyPaused(\n                    autoResumeTime = subscriptionStatus.autoResumeTime!!\n                )\n            }\n            else -&gt; PauseState.NotPaused\n        }\n    }\n}\n\n\/\/ In your Activity or ViewModel\nfun updatePauseUI() {\n    lifecycleScope.launch {\n        when (val pauseState = pauseStateManager.checkPauseState(userId)) {\n            is PauseState.NotPaused -&gt; {\n                \/\/ Normal subscription UI\n                showPremiumContent()\n            }\n            is PauseState.PauseScheduled -&gt; {\n                \/\/ User still has access, but pause is coming\n                showPremiumContent()\n                showPauseScheduledBanner(\n                    message = \&amp;quot;Your subscription will pause on ${formatDate(pauseState.currentPeriodEnd)}\&amp;quot;,\n                    resumeDate = pauseState.autoResumeTime\n                )\n            }\n            is PauseState.ActivelyPaused -&gt; {\n                \/\/ No access during pause\n                showPausedStateUI(\n                    message = \&amp;quot;Your subscription is paused\&amp;quot;,\n                    resumeDate = pauseState.autoResumeTime,\n                    onResumeEarlyClick = { openPlayStoreSubscriptionSettings() }\n                )\n            }\n        }\n    }\n}\n\nprivate fun openPlayStoreSubscriptionSettings() {\n    \/\/ Deep link to Play Store subscription management\n    val intent = Intent(Intent.ACTION_VIEW).apply {\n        data = Uri.parse(\n            \&amp;quot;&lt;https:\/\/play.google.com\/store\/account\/subscriptions?sku=$productId&amp;amp;package=$packageName&gt;\&amp;quot;\n        )\n        setPackage(\&amp;quot;com.android.vending\&amp;quot;)\n    }\n    startActivity(intent)\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The complexity here involves distinguishing between a scheduled pause (where users still have access) and an active pause (where access is revoked). You also need to handle the case where users cancel their scheduled pause, and provide a way for users to resume early if they choose.&lt;/p&gt;



&lt;p&gt;With RevenueCat, pause state management becomes straightforward:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1HobUm wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;fun checkPauseState() {\n    Purchases.sharedInstance.getCustomerInfoWith { customerInfo -&gt;\n        val entitlement = customerInfo.entitlements[\&amp;quot;premium\&amp;quot;]\n\n        when {\n            entitlement?.isActive == true -&gt; {\n                showPremiumContent()\n\n                \/\/ Check if pause is scheduled (will show in periodType)\n                entitlement.expirationDate?.let { expiration -&gt;\n                    if (entitlement.willRenew == false &amp;amp;&amp;amp; entitlement.unsubscribeDetectedAt == null) {\n                        \/\/ Subscription won&apos;t renew but wasn&apos;t canceled - likely paused\n                        showPauseScheduledBanner(expiration)\n                    }\n                }\n            }\n            entitlement != null &amp;amp;&amp;amp; !entitlement.isActive -&gt; {\n                \/\/ Could be paused, expired, or other non-active state\n                \/\/ RevenueCat&apos;s managementURL lets users manage their pause\n                showPausedOrExpiredUI(\n                    managementUrl = customerInfo.managementURL\n                )\n            }\n            else -&gt; {\n                showSubscriptionOffers()\n            }\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;RevenueCat automatically tracks pause state through its server-side RTDN processing. The &lt;code&gt;managementURL&lt;/code&gt; property provides a direct link to Google Play’s subscription settings where users can view their pause status, cancel a scheduled pause, or resume early. This eliminates the need to build custom deep links or track pause scheduling on your backend.&lt;/p&gt;



&lt;p&gt;Additionally, &lt;a href=&quot;https://www.revenuecat.com/docs/integrations/webhooks&quot;&gt;RevenueCat’s webhooks&lt;/a&gt; notify your server of pause events in a normalized format, making it easy to trigger pause-related communications like “We miss you!” emails or special offers to encourage early resumption.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;cancellations-and-expirations&quot;&gt;&lt;strong&gt;Cancellations and expirations&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;When a user decides to cancel their subscription, the lifecycle enters its terminal phase, but cancellation doesn’t mean immediate loss of access.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-cancellation-grace-period&quot;&gt;&lt;strong&gt;The cancellation grace period&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Upon cancellation, users retain access until the end of their current billing period. The subscription enters &lt;code&gt;SUBSCRIPTION_STATE_CANCELED&lt;/code&gt;, and the &lt;code&gt;expiryTime&lt;/code&gt; indicates when access will be revoked.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-tquoi wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;fun handleCancellation(notification: SubscriptionNotification) {\n    val subscription = getSubscriptionDetails(notification.purchaseToken)\n\n    val canceledContext = subscription.canceledStateContext\n    val userReason = canceledContext?.userInitiatedCancellation?.cancelSurveyResult\n\n    \/\/ Log cancellation reason for analytics\n    analytics.logCancellation(\n        reason = userReason,\n        remainingAccessTime = subscription.lineItems[0].expiryTime\n    )\n\n    \/\/ User still has access - don&apos;t revoke yet\n    \/\/ Just update UI to show cancellation status\n    showCancellationStatus(subscription.lineItems[0].expiryTime)\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;understanding-cancellation-reasons&quot;&gt;&lt;strong&gt;Understanding cancellation reasons&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The &lt;code&gt;canceledStateContext&lt;/code&gt; field provides valuable information about why the subscription was canceled:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;User voluntarily canceled (check &lt;code&gt;userInitiatedCancellation&lt;/code&gt; for the survey response)&lt;/li&gt;



&lt;li&gt;Developer canceled via API&lt;/li&gt;



&lt;li&gt;Subscription was replaced (upgrade/downgrade)&lt;/li&gt;



&lt;li&gt;Payment failed and all recovery mechanisms were exhausted&lt;/li&gt;



&lt;li&gt;Google canceled due to policy violations&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;This information is valuable for understanding churn patterns and improving retention strategies.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;expiration-end-of-the-line&quot;&gt;&lt;strong&gt;Expiration: end of the line&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;When the &lt;code&gt;expiryTime&lt;/code&gt; passes for a canceled subscription, or when account hold ends without recovery, the subscription expires. You receive a &lt;code&gt;SUBSCRIPTION_EXPIRED&lt;/code&gt; notification, and the state becomes &lt;code&gt;SUBSCRIPTION_STATE_EXPIRED&lt;/code&gt;.&lt;/p&gt;



&lt;p&gt;At this point, you should:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Revoke all entitlements associated with the subscription&lt;/li&gt;



&lt;li&gt;Mark the purchase token as invalid in your database&lt;/li&gt;



&lt;li&gt;Optionally, offer win-back promotions to the user&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;restore-and-resubscribe-bringing-users-back&quot;&gt;&lt;strong&gt;Restore and resubscribe: bringing users back&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Google Play provides two mechanisms for users to return to a subscription they previously had: &lt;strong&gt;restore&lt;/strong&gt; and &lt;strong&gt;resubscribe&lt;/strong&gt;.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;restore-before-expiration&quot;&gt;&lt;strong&gt;Restore: before expiration&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;If a user cancels but then changes their mind before the subscription expires, they can restore it. This uses the &lt;strong&gt;same purchase token&lt;/strong&gt; and continues the subscription as if it was never canceled.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZQ17LQ wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;fun handleRestore(notification: SubscriptionNotification) {\n    \/\/ SUBSCRIPTION_RESTARTED notification\n    \/\/ Same purchase token, cancellation fields cleared\n\n    val subscription = getSubscriptionDetails(notification.purchaseToken)\n\n    \/\/ Verify it&apos;s now active again\n    if (subscription.subscriptionState == \&amp;quot;SUBSCRIPTION_STATE_ACTIVE\&amp;quot;) {\n        \/\/ Update your database - subscription is back\n        subscriptionRepository.markRestored(notification.purchaseToken)\n\n        \/\/ No acknowledgment needed - same purchase\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Your app receives a &lt;code&gt;SUBSCRIPTION_RESTARTED&lt;/code&gt; notification, and the subscription returns to normal active status. Importantly, &lt;strong&gt;you don’t need to acknowledge restored subscriptions&lt;/strong&gt; because you already acknowledged the original purchase.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;resubscribe-after-expiration&quot;&gt;&lt;strong&gt;Resubscribe: after expiration&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;If the subscription has already expired, users can resubscribe, but this is treated as a &lt;strong&gt;new purchase&lt;/strong&gt; with a new purchase token. You’ll receive a &lt;code&gt;SUBSCRIPTION_PURCHASED&lt;/code&gt; notification and must acknowledge within three days.&lt;/p&gt;



&lt;p&gt;The resubscribe response includes helpful fields for linking the new subscription to the user’s existing account:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1dK5N2 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;fun handleResubscribe(notification: SubscriptionNotification) {\n    val subscription = getSubscriptionDetails(notification.purchaseToken)\n\n    \/\/ Check for previous subscription context\n    val previousContext = subscription.outOfAppPurchaseContext\n    val previousToken = previousContext?.expiredPurchaseToken\n    val previousAccountId = previousContext?.expiredExternalAccountIdentifiers\n\n    if (previousAccountId != null) {\n        \/\/ Link new subscription to existing user account\n        userRepository.linkSubscription(previousAccountId, notification.purchaseToken)\n    }\n\n    \/\/ Must acknowledge new purchase\n    acknowledgePurchase(notification.purchaseToken)\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;upgrades-downgrades-and-plan-changes&quot;&gt;&lt;strong&gt;Upgrades, downgrades, and plan changes&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;When users change their subscription plan, whether upgrading to a more expensive option or downgrading to save money, it creates a new subscription while invalidating the old one.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-linked-purchase-token&quot;&gt;&lt;strong&gt;The linked purchase token&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Plan changes generate a new purchase token, but the response includes a &lt;code&gt;linkedPurchaseToken&lt;/code&gt; field pointing to the previous subscription:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1N7psJ wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;fun handlePlanChange(notification: SubscriptionNotification) {\n    val newSubscription = getSubscriptionDetails(notification.purchaseToken)\n    val oldToken = newSubscription.linkedPurchaseToken\n\n    if (oldToken != null) {\n        \/\/ Find user by old purchase token\n        val user = userRepository.findByPurchaseToken(oldToken)\n\n        \/\/ Update to new purchase token\n        userRepository.updatePurchaseToken(user, notification.purchaseToken)\n\n        \/\/ Invalidate old token\n        subscriptionRepository.invalidate(oldToken)\n    }\n\n    \/\/ Must acknowledge new purchase\n    acknowledgePurchase(notification.purchaseToken)\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;proration-modes&quot;&gt;&lt;strong&gt;Proration modes&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;When implementing plan changes in your app, you can control how billing is handled using different proration modes:&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Mode&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Behavior&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;IMMEDIATE_WITH_TIME_PRORATION&lt;/td&gt;&lt;td&gt;User is credited/charged immediately, billing date unchanged&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;IMMEDIATE_AND_CHARGE_PRORATED_PRICE&lt;/td&gt;&lt;td&gt;User charged prorated amount immediately&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;IMMEDIATE_AND_CHARGE_FULL_PRICE&lt;/td&gt;&lt;td&gt;User charged full new plan price immediately&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;DEFERRED&lt;/td&gt;&lt;td&gt;Change takes effect at next renewal&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;The choice of proration mode affects user experience and revenue recognition, so consider your business requirements carefully.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;revocations-and-refunds&quot;&gt;&lt;strong&gt;Revocations and refunds&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Sometimes subscriptions end abruptly due to revocation or refund, bypassing the normal cancellation flow.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;when-revocation-occurs&quot;&gt;&lt;strong&gt;When revocation occurs&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;You receive a &lt;code&gt;SUBSCRIPTION_REVOKED&lt;/code&gt; notification when:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;You revoke the subscription via the Developer API&lt;/li&gt;



&lt;li&gt;A chargeback occurs&lt;/li&gt;



&lt;li&gt;Google revokes due to policy violations&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Revocations are immediate, the subscription jumps straight to &lt;code&gt;SUBSCRIPTION_STATE_EXPIRED&lt;/code&gt;, and you should revoke access immediately:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z2llm68 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;fun handleRevocation(notification: SubscriptionNotification) {\n    \/\/ Immediate access revocation\n    val purchaseToken = notification.purchaseToken\n\n    \/\/ Revoke entitlement immediately\n    entitlementRepository.revoke(purchaseToken)\n\n    \/\/ Mark subscription as revoked\n    subscriptionRepository.markRevoked(purchaseToken)\n\n    \/\/ Log for fraud detection if this is a chargeback\n    if (notification.notificationType == \&amp;quot;SUBSCRIPTION_REVOKED\&amp;quot;) {\n        fraudDetection.logChargeback(purchaseToken)\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;prepaid-subscriptions-a-different-lifecycle&quot;&gt;&lt;strong&gt;Prepaid subscriptions: a different lifecycle&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;While this article focuses primarily on auto-renewing subscriptions, it’s worth understanding how prepaid plans differ. Prepaid subscriptions don’t automatically renew; users explicitly purchase additional times.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;key-differences-for-prepaid-plans&quot;&gt;&lt;strong&gt;Key differences for prepaid plans&lt;/strong&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Aspect&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Auto-Renewing&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Prepaid&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Renewal&lt;/td&gt;&lt;td&gt;Automatic&lt;/td&gt;&lt;td&gt;User-initiated top-up&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Grace Period&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;td&gt;No&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Account Hold&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;td&gt;No&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Pausing&lt;/td&gt;&lt;td&gt;Yes (if enabled)&lt;/td&gt;&lt;td&gt;No&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;States&lt;/td&gt;&lt;td&gt;All states&lt;/td&gt;&lt;td&gt;Only Active, Pending, Expired&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;prepaid-acknowledgment-timing&quot;&gt;&lt;strong&gt;Prepaid acknowledgment timing&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Prepaid plans have stricter acknowledgment requirements:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Plans ≥ 1 week: acknowledge within three days&lt;/li&gt;



&lt;li&gt;Plans &amp;lt; 1 week: acknowledge within &lt;strong&gt;half the plan duration&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;For a three–day prepaid plan, you must acknowledge within one and a half days, or the user receives a refund.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;how-revenuecat-simplifies-lifecycle-management&quot;&gt;&lt;strong&gt;How RevenueCat simplifies lifecycle management&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Managing all these lifecycle states, notifications, and edge cases requires sophisticated backend infrastructure and careful implementation. This is where RevenueCat provides substantial value by handling most of this complexity automatically.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;automatic-state-management&quot;&gt;&lt;strong&gt;Automatic state management&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;RevenueCat maintains subscription state in real-time, processing Google Play’s RTDN notifications on your behalf. Instead of building infrastructure to receive, validate, and process notifications, you simply query RevenueCat for the current customer state:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z2cA4lz wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;fun checkAccess() {\n    Purchases.sharedInstance.getCustomerInfoWith { customerInfo -&gt;\n        \/\/ RevenueCat has already processed all lifecycle events\n        val isPremium = customerInfo.entitlements[\&amp;quot;premium\&amp;quot;]?.isActive == true\n\n        if (isPremium) {\n            enablePremiumFeatures()\n        } else {\n            showSubscriptionOptions()\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;CustomerInfo&lt;/code&gt; object reflects the current state of all subscriptions, including:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Active entitlements&lt;/li&gt;



&lt;li&gt;Expiration dates&lt;/li&gt;



&lt;li&gt;Whether the user is in a grace period&lt;/li&gt;



&lt;li&gt;Billing issues that need attention&lt;/li&gt;



&lt;li&gt;Management URL for subscription settings&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;handling-grace-periods-and-billing-issues&quot;&gt;&lt;strong&gt;Handling grace periods and billing issues&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;RevenueCat’s &lt;code&gt;CustomerInfo&lt;/code&gt; includes a &lt;code&gt;billingIssueDetectedAt&lt;/code&gt; timestamp when a subscription has payment problems. You can use this to show appropriate messaging:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-pK5gP wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;fun checkBillingStatus(customerInfo: CustomerInfo) {\n    val entitlement = customerInfo.entitlements[\&amp;quot;premium\&amp;quot;]\n\n    if (entitlement?.billingIssueDetectedAt != null) {\n        \/\/ User has a billing issue - show recovery UI\n        showBillingRecoveryMessage(\n            managementUrl = customerInfo.managementURL\n        )\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;RevenueCat also provides webhooks that notify your server of subscription events in a normalized format, making server-side integration much simpler than processing raw RTDN notifications.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;cross-platform-subscription-state&quot;&gt;&lt;strong&gt;Cross-platform subscription state&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;One of RevenueCat’s most convenient features is maintaining subscription state across platforms. If a user subscribes on Android and later opens your iOS app, their subscription status is automatically recognized. This is particularly valuable for lifecycle events, a subscription that enters grace period on Android will be reflected in the iOS app’s &lt;code&gt;CustomerInfo&lt;/code&gt; without any additional implementation.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;revenue-recovery&quot;&gt;&lt;strong&gt;Revenue recovery&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;RevenueCat’s Billing Alerts feature can automatically attempt to recover failed payments by:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Sending customizable email notifications to users with billing issues&lt;/li&gt;



&lt;li&gt;Prompting users to update payment methods at optimal times&lt;/li&gt;



&lt;li&gt;Tracking recovery rates and providing analytics&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;This automates much of the grace period and account hold handling that would otherwise require custom implementation.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;analytics-and-insights&quot;&gt;&lt;strong&gt;Analytics and insights&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Understanding your subscription lifecycle patterns is crucial for optimization. RevenueCat provides detailed analytics including:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Churn analysis by cancellation reason&lt;/li&gt;



&lt;li&gt;Grace period and account hold recovery rates&lt;/li&gt;



&lt;li&gt;Subscription duration and renewal patterns&lt;/li&gt;



&lt;li&gt;Revenue metrics across lifecycle stages&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;These insights help you identify where users are dropping off and opportunities to improve retention.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;best-practices-for-lifecycle-management&quot;&gt;&lt;strong&gt;Best practices for lifecycle management&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Based on the lifecycle stages we’ve covered, here are key practices to implement:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;always-verify-on-your-backend&quot;&gt;&lt;strong&gt;Always verify on your backend&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Never trust the client-side subscription state alone. Your backend should:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Process RTDN notifications (or use RevenueCat’s webhooks)&lt;/li&gt;



&lt;li&gt;Verify purchases using the Google Play Developer API&lt;/li&gt;



&lt;li&gt;Maintain authoritative subscription state&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;handle-grace-periods-proactively&quot;&gt;&lt;strong&gt;Handle grace periods proactively&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Users in grace periods are at high risk of churning. Implement multiple touchpoints:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;In-app messaging using Google’s API&lt;/li&gt;



&lt;li&gt;Push notifications reminding users to update payment&lt;/li&gt;



&lt;li&gt;Email campaigns for users not opening the app&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;make-cancellation-reversible&quot;&gt;&lt;strong&gt;Make cancellation reversible&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Since users retain access until their billing period ends, make it easy to restore:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Show clear ‘Resume subscription’ options&lt;/li&gt;



&lt;li&gt;Don’t punish users who explore cancellation&lt;/li&gt;



&lt;li&gt;Consider exit surveys but don’t make them mandatory&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;plan-for-edge-cases&quot;&gt;&lt;strong&gt;Plan for edge cases&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Real-world subscription management involves many edge cases:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Users switching devices mid-subscription&lt;/li&gt;



&lt;li&gt;Multiple purchases from the same user&lt;/li&gt;



&lt;li&gt;Refunds and chargebacks&lt;/li&gt;



&lt;li&gt;Subscription transfers between accounts&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Build your system to handle these gracefully, or use a service like RevenueCat that handles them automatically.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;summary&quot;&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Google Play’s subscription lifecycle is comprehensive but complex. From the initial purchase through renewals, grace periods, account holds, pauses, cancellations, and expirations, each state requires specific handling to ensure users receive correct entitlements while your business captures all possible revenue.&lt;/p&gt;



&lt;p&gt;The key states to understand are:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Active state&lt;/strong&gt; where users have full access&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Grace period&lt;/strong&gt; where users retain access while you attempt payment recovery&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Account hold&lt;/strong&gt; where access is suspended pending payment fix&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Paused state&lt;/strong&gt; where users voluntarily pause their subscription&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Canceled state&lt;/strong&gt; where users retain access until their paid period ends&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Expired state&lt;/strong&gt; where access should be revoked&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Whether you implement subscription lifecycle management directly or use RevenueCat, understanding these lifecycle stages is essential for building a robust subscription business on Android. The difference between losing a subscriber to involuntary churn and recovering them often comes down to how well you handle grace periods and account holds. The difference between a confusing user experience and a seamless one depends on how gracefully you handle pauses, cancellations, and restorations.&lt;/p&gt;



&lt;p&gt;For complete documentation on subscription lifecycle management, refer to the &lt;a href=&quot;https://developer.android.com/google/play/billing/lifecycle/subscriptions&quot;&gt;official Android Developer documentation&lt;/a&gt; and &lt;a href=&quot;https://www.revenuecat.com/docs/subscription-guidance/managing-subscriptions&quot;&gt;RevenueCat’s subscription guidance&lt;/a&gt;.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Monetize faster with RevenueCat Test Store by testing purchases without App Store or Play Console]]></title><description><![CDATA[Build and test real paywalls in minutes; no App Store Connect, no Play Console, no waiting. Test Store gives you realistic purchases with a single Test API key so you can ship monetization faster.]]></description><link>https://www.revenuecat.com/blog/company/revenuecat-test-store/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/company/revenuecat-test-store/</guid><pubDate>Fri, 19 Dec 2025 16:13:33 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Introducing-the-test-store.png" length="0" type="image/*"/><content:encoded>&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;Introducing the RevenueCat Test Store&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/MhPdyAmOfqI?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-a-hosted-test-store-that-behaves-like-a-real-store&quot;&gt;&lt;strong&gt;A hosted test store that behaves like a real store&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/test-and-launch/sandbox/test-store&quot;&gt;Test Store&lt;/a&gt; is a first-class store object inside RevenueCat; it stores products, serves offerings, accepts purchases, and records transactions for testing only. It is not a simulator or a local mock. When your app uses a Test API key, the SDK fetches Test Store products, runs the test purchase flow and returns &lt;code&gt;customerInfo&lt;/code&gt; and entitlements that match production shapes. Test activity is marked sandbox and kept separate from production.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-skip-store-setup-and-get-a-working-paywall-in-minutes&quot;&gt;&lt;strong&gt;Skip store setup and get a working paywall in minutes&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;You can skip the slow parts of early monetization. No need to configure App Store Connect and Play Console credentials. Test Store is provisioned automatically with every new project so you can design paywalls, test purchases, and iterate on subscriptions without waiting for platform setup.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-start-testing-paywalls-instantly-and-run-repeatable-subscription-tests&quot;&gt;&lt;strong&gt;Start testing paywalls instantly and run repeatable subscription tests&lt;/strong&gt;&lt;/h2&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Start immediately; a Test Store appears with every new project&lt;/li&gt;



&lt;li&gt;Validate paywalls end to end; receipts, entitlements, and customer objects match production&lt;/li&gt;



&lt;li&gt;Run subscription lifecycle tests quickly&lt;/li&gt;



&lt;li&gt;Test in Expo, web previews, simulators, and dev builds that lack native store APIs&lt;/li&gt;



&lt;li&gt;Rotate Test API keys for safety and keep test traffic out of revenue metrics&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-never-ship-an-app-with-a-test-store-api-key&quot;&gt;&lt;strong&gt;Never ship an app with a Test Store API key&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Enforce production keys at release. Test Store uses its own key so you control which store your app talks to during development, but production builds must switch to your platform-specific API keys. RevenueCat enforces this for a reason; if a release build initializes with a Test Store key, the SDK will show an alert and crash the app. That hard stop protects the security of your entitlements and prevents test purchases from leaking into production.&lt;/p&gt;



&lt;p&gt;To lock things down even more, use the &lt;a href=&quot;https://www.revenuecat.com/docs/projects/sandbox-access&quot;&gt;Sandbox Testing Access allowlist&lt;/a&gt;. You can restrict Test Store and other sandbox purchases so only approved App User IDs receive entitlements or virtual currency during testing. That way, non-production purchases stay in a safe, controlled lane while your real customers remain unaffected.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-create-a-project-and-run-your-first-test-purchase-in-minutes&quot;&gt;&lt;strong&gt;Create a project and run your first test purchase in minutes&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Create a new project in the RevenueCat dashboard and the Test Store is ready by default. Point your dev build at the Test API key, fetch offerings, and make a test purchase; you’ll see &lt;code&gt;customerInfo&lt;/code&gt; update and entitlements change just like production.&lt;/p&gt;



&lt;p&gt;Test Store removes the biggest speed bump in early monetization: no platform credentials, instant provisioning, and realistic test purchases so you can iterate faster and ship with confidence.&lt;/p&gt;



&lt;p&gt;To learn more, head over to the &lt;a href=&quot;https://www.revenuecat.com/docs/test-and-launch/sandbox/test-store&quot;&gt;Test Store docs&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[What app buyers really want: insights from 10 leading acquirers]]></title><description><![CDATA[Dealmaker Evelin Herrera interviewed leading app buyers about the acquisition landscape in 2026 — here’s what every founder needs to know before selling]]></description><link>https://www.revenuecat.com/blog/growth/guide-to-selling-apps/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/guide-to-selling-apps/</guid><pubDate>Thu, 18 Dec 2025 14:40:24 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/State-of-app-acquisitions.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Despite the fact many app developers dream of selling their app, the world of app buying is still rather uncharted territory. Much like job interviews or talking about personal finance, people seem to shy away from frank conversations.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Luckily, we don’t. And it seems about time someone demystified these questions.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Questions like:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;What’s my app worth?&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Do I need to stay after the acquisition?&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;em&gt;Can&lt;/em&gt; I stay after the acquisition?&lt;/li&gt;



&lt;li&gt;Do buyers prefer organic or paid traffic?&amp;nbsp;&lt;/li&gt;



&lt;li&gt;How good does my retention need to be?&lt;/li&gt;



&lt;li&gt;What’s a multiplier and how do I get it/do it/be it?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Answering those (and some others) is the goal of this article. Currently most app acquisition advice floating around the internet is either outdated, generic, or coming from people who’ve never actually &lt;em&gt;bought an app&lt;/em&gt;.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;For various reasons, many buyers keep their perspectives private; but just as job interviews are getting more transparent in what to prepare, we think founders deserve reliable acquisition guidance. So, we went straight to the source! &lt;/p&gt;



&lt;p&gt;This is &lt;strong&gt;the real state of industry acquisitions&lt;/strong&gt;, straight from the people shaping the vertical: buyers.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;If you’re a founder looking for an exit, or even just a newbie planning ahead, we promise you this is worth 10x the hours you’ll spend watching interviews, listening to podcasts, and in 1:1 conversations.&amp;nbsp;&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-featured-app-buyers&quot;&gt;&lt;strong&gt;Featured app buyers&lt;/strong&gt;&lt;/h4&gt;



&lt;p&gt;&lt;a href=&quot;https://www.linkedin.com/in/evelinherrera/&quot;&gt;Evelin Herrera&lt;/a&gt; is Founder of EHVM App Capital, the mobile app M&amp;amp;A firm working with high-growth app founders on exits and strategic acquisitions. Every day, Evelin is in the field working directly with founders and buyers, facilitating deals. So who better to get the real answers from buyers on what they’re looking for? &lt;/p&gt;



&lt;p&gt;After scouring her network, Evelin interviewed ten experienced, international buyers on everything from valuation to founder status post-acquisition. We’ve taken those interviews, and unpicked the answers to all those questions you haven’t had ticked off yet (or are too afraid to ask).&lt;/p&gt;



&lt;p&gt;Here’s who Evelin spoke to:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;🇺🇸 &lt;a href=&quot;https://www.linkedin.com/in/danielnovaes/&quot;&gt;Dan Novaes&lt;/a&gt;, Co-Founder &amp;amp; CEO at Mode Mobile&lt;/li&gt;



&lt;li&gt;🇫🇷 &lt;a href=&quot;https://www.linkedin.com/in/guillaume-larrieu-33623a16/&quot;&gt;Guillaume Larrieu&lt;/a&gt;, VP of Business Development at Quiet&lt;/li&gt;



&lt;li&gt;🇨🇦 &lt;a href=&quot;https://www.linkedin.com/in/jonwalshkodeon/&quot;&gt;Jon Walsh&lt;/a&gt;, Managing Partner at Kodeon and Partner at Push Capital&lt;/li&gt;



&lt;li&gt;🇸🇰 &lt;a href=&quot;https://www.linkedin.com/in/matejlancaric/&quot;&gt;Matej Lancaric&lt;/a&gt;, Independent User Acquisition &amp;amp; Marketing Consultant&lt;/li&gt;



&lt;li&gt;🇪🇸 &lt;a href=&quot;https://www.linkedin.com/in/michael-mcphee/&quot;&gt;Michael McPhee&lt;/a&gt;, Head of Business Development and M&amp;amp;A at Leadtech Group&lt;/li&gt;



&lt;li&gt;🇵🇱 &lt;a href=&quot;https://www.linkedin.com/in/pawelpochowski/&quot;&gt;Paweł Pochowski&lt;/a&gt;, Head of Business Development at Nova Sphere&lt;/li&gt;



&lt;li&gt;🇬🇧 &lt;a href=&quot;https://www.linkedin.com/in/ryanjthorpe/&quot;&gt;Ryan Thorpe&lt;/a&gt;, Director of Growth at Reflective Apps&lt;/li&gt;



&lt;li&gt;🇺🇸 &lt;a href=&quot;https://www.linkedin.com/in/kenneytom/&quot;&gt;Tom Kenney&lt;/a&gt;, CEO &amp;amp; Co-founder at LOYAL&lt;/li&gt;



&lt;li&gt;🇹🇷 &lt;a href=&quot;https://www.linkedin.com/in/yalcinozdemir/&quot;&gt;Yalçın Özdemir&lt;/a&gt;, Founder &amp;amp; CEO at AppNation&lt;/li&gt;



&lt;li&gt;🇺🇸 &lt;a href=&quot;https://www.linkedin.com/in/zachtobin/&quot;&gt;Zach Tobin&lt;/a&gt;, Founder of Product Growth LLC&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;These are the people acquiring, integrating, and scaling apps today, spanning app categories like gaming, health &amp;amp; fitness, productivity, utilities, and lifestyle. Read on for a peek into their world…&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-tl-dr-the-real-state-of-app-acquisitions-according-to-the-people-writing-the-checks&quot;&gt;&lt;strong&gt;TL;DR: the real state of app acquisitions (according to the people writing the checks)&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;If you’re just here for the quickfire facts, we’ve got you covered. From 10 hours of interviews, here are the highlights you &lt;em&gt;need &lt;/em&gt;to know if you’re interested in selling your app.&amp;nbsp;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;The majority of buyers prefer keeping original talent (including the founder) in place post-acquisition:&lt;/strong&gt; they benefit from product knowledge, quick iteration, and being able to scale without delays.&lt;/li&gt;



&lt;li&gt;The &lt;strong&gt;starting point for valuing your app is 3–5x EBITDA&lt;/strong&gt; (earnings before interest, taxes, depreciation, and amortization), provided your app is older than two years and has four plus months of subscriber retention.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Strategic acquisitions (not purely financially-motivated) &lt;/strong&gt;&lt;strong&gt;&lt;em&gt;do &lt;/em&gt;&lt;/strong&gt;&lt;strong&gt;happen&lt;/strong&gt;, but they’re rare and require a lot of matchmaking.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Most companies offer 100% upfront cash as standard&lt;/strong&gt;, but some offer variants like earnouts or equity. Consider these options carefully, as they can increase/decrease your overall valuation.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Different buyers favour more organic or more paid traffic&lt;/strong&gt;; organic builds reliable growth, but paid user acquisition (UA) drives scale. Try targeting a 50/50 mix to show strong metrics and reduce the risk of algorithmic reliance.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Why are buyers looking to acquire in the first place? &lt;/strong&gt;Buyers have seen double revenue in 12–18 months for &amp;lt;$500k acquisitions, so financial incentives are high. Many acquirers also prefer buying versus building from scratch to reduce risk, accelerate growth, and start with apps that benefit from proven &lt;a href=&quot;https://www.revenuecat.com/blog/growth/product-market-fit-subscription-apps/&quot;&gt;product-market fit&lt;/a&gt; (PMF).&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;The top green flags for acquisition are:&lt;/strong&gt; high retention, low running costs, organic compounding, domain authority, proven PMF and market momentum.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-actually-drives-app-valuation-and-the-truth-about-multipliers-nbsp&quot;&gt;&lt;strong&gt;What actually drives app valuation, and the truth about multipliers&amp;nbsp;&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;This is the first question developers always have: how much can I get for my app business? But valuation is tricky — you have to reflect potential future growth, stickiness &amp;gt; trends, technology moats (if any), and multiple other factors.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;The best way to answer the crux of this question is by hearing it from the folks who put the capital on the table. &lt;em&gt;But&lt;/em&gt;, before we dive in, let’s cover a couple of basics: &lt;strong&gt;acquisition types &lt;/strong&gt;and &lt;strong&gt;multipliers&lt;/strong&gt;.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-strategic-vs-financial-acquisitions&quot;&gt;&lt;strong&gt;Strategic vs. financial acquisitions&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Believe it or not, not all apps are bought just for financial gain. In fact, most are a mix of strategic moves, financial motivation, and passion projects. But broadly-speaking, there’s two types of acquisition: financial and strategic.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Financial acquisition&lt;/strong&gt; are valuations are solely based on the financial performance of the company:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“Financials are the priority, but if something lines up strategically with what we’re building, we’ll go there too.” — &lt;a href=&quot;https://www.linkedin.com/in/danielnovaes/&quot;&gt;Dan Novaes&lt;/a&gt;, Co-Founder &amp;amp; CEO at Mode Mobile&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;&lt;strong&gt;Strategic acquisitions &lt;/strong&gt;consider the strategic value (e.g. a gap in their &lt;a href=&quot;https://www.revenuecat.com/blog/growth/app-portfolio-vs-single-app/&quot;&gt;app portfolio&lt;/a&gt;, or particularly strong market value) an acquisition is bringing to the business — typically these come with a premium price:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“We’re always looking for acquisitions that help us advance our strategy of building a portfolio of high-quality life improvement-focused apps. We then base our valuation on a number of factors.” — &lt;a href=&quot;https://www.linkedin.com/in/jonwalshkodeon/&quot;&gt;Jon Walsh&lt;/a&gt;, Managing Partner at Kodeon and Partner at Push Capital&lt;/p&gt;
&lt;/blockquote&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;are-multipliers-the-defining-factor-in-an-acquisition&quot;&gt;&lt;strong&gt;Are multipliers the defining factor in an acquisition?&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;In the world of mobile app acquisitions, multipliers are tossed about left, right, and centre. Along with all the wonderful acronyms that come with them.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;In short, a multiplier is a simple way &lt;strong&gt;buyers estimate a business’ value, based on core financial metrics.&lt;/strong&gt; It’s about saying “we value your app at X times what it earns”, aka thinking about what it &lt;em&gt;could &lt;/em&gt;earn.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Most acquisitions use a core metric like &lt;a href=&quot;https://www.revenuecat.com/glossary/#monthly-recurring-revenue-mrr&quot;&gt;monthly recurring revenue (MRR)&lt;/a&gt;, annual recurring revenue (ARR), or EBITDA as the baseline. A multiple is the price per unit. So if an app makes $100k EBITDA, and buyers typically pay 3-5X EBITDA, then the app is worth $300-$500k. Buyers anchor value on these metrics because they’re disciplined, and it minimizes risk of overpaying.&amp;nbsp;&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“Valuations are always based on multiples. If you’re not disciplined, you’ll overpay which makes it that much more difficult to succeed. Valuations need to create a win/win for all parties, including the buyer.” — &lt;a href=&quot;https://www.linkedin.com/in/kenneytom/&quot;&gt;Tom Kenney&lt;/a&gt;, CEO &amp;amp; Co-founder at LOYAL&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Many founders obsess over multipliers and assume they’re the be-all and end-all for getting acquired. But the reality Evelin heard from every buyer was that multipliers are a starting point, not a golden rule. The real valuation moves up or down depending on a number of factors (which we’ll get into shortly) like &lt;a href=&quot;https://www.revenuecat.com/blog/growth/one-year-retention-rates-insights/&quot;&gt;retention&lt;/a&gt;, scalability, growth, team etc.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;For example, &lt;a href=&quot;https://www.linkedin.com/in/yalcinozdemir/&quot;&gt;Yalçın Özdemir,&lt;/a&gt; Founder &amp;amp; CEO at AppNation, explained how, for the right app, valuations can be flexible:&amp;nbsp;&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“When we identify opportunities where our strengths can quickly improve the revenue, we’re willing to stretch valuations. In these cases, we see the real value in the match between what the founder has built and what we can contribute.” — &lt;a href=&quot;https://www.linkedin.com/in/yalcinozdemir/&quot;&gt;Yalçın Özdemir&lt;/a&gt;, Founder &amp;amp; CEO at AppNation&lt;/p&gt;
&lt;/blockquote&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;when-multipliers-dont-tell-the-full-story&quot;&gt;&lt;strong&gt;When multipliers don’t tell the full story&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;As Yalçın says, multipliers aren’t the sole deciding factor in whether a buyer is interested. The big picture matters too, and certain industries, like gaming, can be less rigidly-reliant on multiples:&amp;nbsp;&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“Multipliers are a useful tool, but they’re not the only method we rely on — and certainly not always the most accurate. For example, games often experience revenue decline once user acquisition spend is reduced. In these cases, a valuation based solely on the past 12–24 months might not reflect the true potential.” — &lt;a href=&quot;https://www.linkedin.com/in/pawelpochowski/&quot;&gt;Paweł Pochowski&lt;/a&gt;, Head of Business Development at Nova Sphere&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Early-stage apps or products in emerging niches can also be poorly reflected by multiples alone. Paweł explained that these categories may not have had a chance to prove their value through performance metrics yet: “In these scenarios, we look beyond historical data and consider &lt;strong&gt;market trends&lt;/strong&gt;, &lt;strong&gt;strategic fit&lt;/strong&gt;, and &lt;strong&gt;growth potential&lt;/strong&gt;. If we see strong momentum or a unique positioning, we’re open to offering above-standard valuations.”&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“We start with financial performance, then dig deeper into the performance metrics, and build a comprehensive model that allows us to understand an app’s history, its current place in the market and value to current and past users.” — &lt;a href=&quot;https://www.linkedin.com/in/jonwalshkodeon/&quot;&gt;Jon Walsh&lt;/a&gt;, Managing Partner at Kodeon and Partner at Push Capital&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;&lt;a href=&quot;https://www.linkedin.com/in/jonwalshkodeon/&quot;&gt;Jon Walsh&lt;/a&gt;, Managing Partner at Kodeon and Partner at Push Capital, also says many buyers factor in their current app portfolio when valuing new apps: “We consider how complimentary it is to our overall portfolio and ultimately determine what price we are able to pay. We can, and do, pay higher multiples for assets that accelerate our overall plan, but within a range that is based on financial discipline.”&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;how-to-hack-the-high-multiple-tier&quot;&gt;&lt;strong&gt;How to hack the high-multiple tier&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;So what’s the secret to your app sitting in that magic high-multiple tier?&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Typically, valuations are a multiplier range e.g. 3–5x EBITDA. Different factors make apps lower or higher, and a handful of buyers will stretch beyond standard ranges when an app unlocks something bigger for their &lt;a href=&quot;https://www.revenuecat.com/blog/growth/app-portfolio-vs-single-app/&quot;&gt;app portfolio&lt;/a&gt;.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;These reasons could be:&amp;nbsp;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Cross-sell potential&lt;/li&gt;



&lt;li&gt;Category expertise&lt;/li&gt;



&lt;li&gt;Shared users&lt;/li&gt;



&lt;li&gt;Proven PMF in a target market&lt;/li&gt;



&lt;li&gt;A feature set they lack internally&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;This is why founders should talk to &lt;em&gt;multiple buyers&lt;/em&gt;. Your best valuation may come from the buyer who sees the most synergy between your app and their current portfolio, not the highest revenue multiple.&lt;/p&gt;



&lt;p&gt;Across every buyer Evelin spoke to, there was an unmistakable pattern. If you want the &lt;em&gt;upper&lt;/em&gt; end of the multiplier range, you need these three things:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Strong retention: &lt;/strong&gt;this signals undeniable product-market fit, and is the best predictor of long-term cash flow&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Low operational burden + clean architecture:&lt;/strong&gt; buyers want to scale quickly and easily — they can’t do that if there’s missing documentation, inconsistent analytics, or messy code&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Organic or compounding distribution: &lt;/strong&gt;this equals an efficient growth engine; think untapped markets, clear opportunities to expand features, early traction in a category etc.&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Not much to ask, right?&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;takeaway-valuation-multipliers&quot;&gt;&lt;strong&gt;Takeaway: valuation + multipliers&amp;nbsp;&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;While multipliers are simple to understand and have a quick potential for evaluating your app, it’s more important to find a buyer that’s the right fit. If your app helps a buyer advance faster towards their goal, offers a strategic or portfolio fit, or has growth momentum, you’re far more likely to get a much higher multiplier.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Likewise, if a buyer can clearly see where they’ll create value, the app becomes more attractive — and more expensive. Early trajectory and category dynamics also influence valuation almost as much as financials. But remember: financial responsibility still holds out. Most buyers put stock in EBITDA/MRR multiples, and won’t take a big financial risk.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;the-app-buyer-wishlist-what-founders-should-optimize-before-acquisition&quot;&gt;&lt;strong&gt;The app buyer wishlist: what founders should optimize before acquisition&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;While multipliers play a part in getting that offer, there’s a lot of factors that influence whether buyers move a deal forward. Evelin asked about the top three things buyers look for in an app, and do you know how many said the same top three factors?&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Yup, zilch. There’s no one-size-fits-all approach.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;But just like the signals influencing your multiplier, there were frequent recurring factors that all buyers put as priorities. Primarily, &lt;em&gt;everyone &lt;/em&gt;mentioned &lt;a href=&quot;https://www.revenuecat.com/glossary/#retention-rate&quot;&gt;retention&lt;/a&gt; and having ‘sticky’ users.&amp;nbsp;&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“Ultimately, the lower the price of the acquisition, the better. And the faster the return-on-investment, the better. But we look at so many factors and how they relate to each other.” — &lt;a href=&quot;https://www.linkedin.com/in/ryanjthorpe/&quot;&gt;Ryan Thorpe&lt;/a&gt;, Director of Growth at Reflective Apps&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Here’s what our buyers are looking for:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Retention&lt;/li&gt;



&lt;li&gt;Organic growth&lt;/li&gt;



&lt;li&gt;Monetization potential&lt;/li&gt;



&lt;li&gt;Valuation and ROI&lt;/li&gt;



&lt;li&gt;Technical infrastructure&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Product-market fit&lt;/li&gt;



&lt;li&gt;Familiarity with the vertical &lt;em&gt;and/or&lt;/em&gt; strategic/portfolio fit&lt;/li&gt;



&lt;li&gt;Market momentum&lt;/li&gt;
&lt;/ul&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;768&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/What-app-buyers-value-1.png&quot; alt=&quot;&quot; class=&quot;wp-image-49388&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/What-app-buyers-value-1.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/What-app-buyers-value-1-300x225.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/What-app-buyers-value-1-768x576.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/What-app-buyers-value-1-50x38.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/What-app-buyers-value-1-53x40.png 53w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/What-app-buyers-value-1-619x464.png 619w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/What-app-buyers-value-1-696x522.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/What-app-buyers-value-1-560x420.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/What-app-buyers-value-1-395x296.png 395w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/What-app-buyers-value-1-629x472.png 629w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/What-app-buyers-value-1-80x60.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/What-app-buyers-value-1-48x36.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Let’s break these down.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Priority&lt;/th&gt;&lt;th&gt;Why?&lt;/th&gt;&lt;th&gt;Relevant metrics&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Retention&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Retention is a key signal your user base isn’t going anywhere (and therefore has financial potential). Buyers see this as a quality signal and a sign you’ve got PMF. They want to see low churn and user ‘stickiness’; people keep coming back, even when the product doesn’t have new features, or has the odd bug.&amp;nbsp;&lt;br&gt;&lt;br&gt;Retention is the strongest signal of PMF, future cash flow, and downside protection. High retention reduces risk, even if growth slows.&amp;nbsp;&lt;/td&gt;&lt;td&gt;DAU/MAU&lt;br&gt;Cohort retention&lt;br&gt;Churn rate&lt;br&gt;&lt;a href=&quot;https://www.revenuecat.com/glossary/#trial-conversion-rate&quot;&gt;Conversion rate&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Organic growth&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Buyers are looking for growth, domain authority, and demand driven by organic channels. While not &lt;em&gt;all &lt;/em&gt;buyers care whether traffic is organic or paid (more on this later), everyone agreed that organic growth indicates positive brand association and compounding growth potential.&lt;/td&gt;&lt;td&gt;% of installs from organic&lt;br&gt;Keyword rankings (&lt;a href=&quot;https://www.revenuecat.com/glossary/#app-store-optimization-aso&quot;&gt;ASO&lt;/a&gt; + SEO) for core terms&lt;br&gt;Review volume + average rating&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Monetization potential&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;While it may feel counterintuitive, buyers see &lt;em&gt;under&lt;/em&gt;–&lt;a href=&quot;https://www.revenuecat.com/blog/growth/2025-app-monetization-trends/&quot;&gt;monetization&lt;/a&gt; as a plus, since it indicates the app can make more money than it currently is. They’re looking for proven monetization success, clear room for improvement, and revenue &lt;em&gt;quality&lt;/em&gt; as well as quantity.&amp;nbsp;&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://www.revenuecat.com/glossary/#arpu-average-revenue-per-user&quot;&gt;ARPU&lt;/a&gt;&lt;br&gt;Annual vs. monthly subscription mix&lt;br&gt;RPI&lt;br&gt;Subscription pricing and offer structure&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Valuation and ROI&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;This is our multiplier moment. Buyers mentioned that the deal needs to make financial sense for both parties. Some had specific cash offer ranges in mind, while others specified that payback periods factor into their decision. Several said they’d pay more if the app was a good ‘fit’.&amp;nbsp;&lt;/td&gt;&lt;td&gt;LTV/CAC&lt;br&gt;Payback period&lt;br&gt;Gross margin&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Technical&lt;/strong&gt; &lt;strong&gt;infrastructure&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Buyers are looking for apps that are easy to maintain. The infrastructure should be stable and scalable. Clean architecture, well-documented processes, and a reliable backend were all directly called out.&amp;nbsp;&lt;/td&gt;&lt;td&gt;App stability metrics&lt;br&gt;Infrastructure cost as % of revenue&lt;br&gt;Billing failure rate&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Product-market fit&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Across the board, buyers want to see evidence that the app truly solves a problem for a defined, existing audience. Without PMF, even the best-looking app is a no-go.&amp;nbsp;&lt;/td&gt;&lt;td&gt;Retention&lt;br&gt;Long-term subscribers&lt;br&gt;&lt;a href=&quot;https://www.revenuecat.com/glossary/#churn-rate&quot;&gt;Churn rate&lt;/a&gt;&lt;br&gt;Social proof&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Familiarity with the vertical and/or portfolio fit&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Buyers prefer markets they already understand, where existing analysis can be repurposed and userbases overlap. A number of buyers said they prioritize apps in familiar markets which fit within their portfolio.&amp;nbsp;&lt;br&gt;&lt;br&gt;However, some buyers were category-agnostic and instead looked for niche verticals with room for growth, even outside their expertise. Others said they look to plug gaps in their existing offering.&amp;nbsp;&lt;/td&gt;&lt;td&gt;Category benchmarks vs. peers (e.g. retention, ARPU)&lt;br&gt;Overlap with buyer’s existing portfolio&lt;br&gt;Pricing alignment with competitors&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Market&lt;/strong&gt; &lt;strong&gt;momentum&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Apps in growing or emerging spaces are popular. Category leaders and UA are used as a proxy for measuring momentum. Acquirers want to see a ‘booming niche’ or high-potential in a vertical.&amp;nbsp;&lt;/td&gt;&lt;td&gt;Install growth rate (MoM/YoY)&lt;br&gt;Revenue growth rate&lt;br&gt;Category growth indicators&amp;nbsp;&lt;br&gt;Category benchmarks&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Timing&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Two buyers explicitly mentioned timing and looking for signals that the app &lt;em&gt;can &lt;/em&gt;go further, but needs some help. Bottlenecks like bandwidth limits, founder fatigue, little knowledge of marketing, or hitting an execution ceiling were all mentioned.&amp;nbsp;&lt;/td&gt;&lt;td&gt;Qualitative signals&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;Almost no one values pure revenue alone. High multiples and desired apps come from alignment, across &lt;strong&gt;retention&lt;/strong&gt;, &lt;strong&gt;distribution&lt;/strong&gt;, &lt;strong&gt;monetization&lt;/strong&gt;, and personal &lt;strong&gt;buyer fit&lt;/strong&gt;.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Above all, everyone was looking to see an app that has found its place with strong audience and market fit. If it slots into a strategic or portfolio gap, even better. The recurring theme is &lt;em&gt;this app works, but we can make it work much better.&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;Okay, we know that multipliers don’t always tell the full story, and we know what buyers look for — let’s dig a little deeper into how you can illustrate these points when your app’s being assessed.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;retention-signals-that-tell-buyers-your-app-is-healthy&quot;&gt;&lt;strong&gt;Retention signals that tell buyers your app is ‘healthy’&amp;nbsp;&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Retention is a crucial point for many buyers — and it makes sense; if you’re paying years in advance of the business’ success, you want to retain paying users for a considerable time. Buyers consistently ranked retention as one of their top three valuation drivers, but how can founders prepare &lt;strong&gt;a retention story that clearly demonstrates stickiness, and reduces perceived risk?&lt;/strong&gt;&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Based on Evelin’s conversations, retention signals fall into three buckets:&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;1. Retention matches category benchmarks: &lt;/strong&gt;Buyers aren’t looking at universal stats, they’re evaluating retention relative to category norms, price point, subscription length, frequency of use etc.&amp;nbsp;&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“I look at who’s the biggest player in the category? How much revenue are they earning? What kind of UA channels do they run? This then serves as a benchmark for the app I’m considering. All this comes into my decision matrix.” — &lt;a href=&quot;https://www.linkedin.com/in/matejlancaric/&quot;&gt;Matej Lancaric&lt;/a&gt;, Independent User Acquisition &amp;amp; Marketing Consultant&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;The &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps-2025/&quot;&gt;&lt;em&gt;State of Subscription Apps report&lt;/em&gt;&lt;/a&gt; shows how drastically retention shifts between categories. Make sure you know your industry, what competitors are doing, and how you hold up.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;751&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-17-at-16.03.35-1024x751.png&quot; alt=&quot;&quot; class=&quot;wp-image-49328&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-17-at-16.03.35-1024x751.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-17-at-16.03.35-300x220.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-17-at-16.03.35-768x563.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-17-at-16.03.35-1536x1127.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-17-at-16.03.35-50x37.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-17-at-16.03.35-55x40.png 55w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-17-at-16.03.35-633x464.png 633w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-17-at-16.03.35-696x510.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-17-at-16.03.35-560x411.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-17-at-16.03.35-404x296.png 404w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-17-at-16.03.35-644x472.png 644w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-17-at-16.03.35-80x59.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-17-at-16.03.35-48x35.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-17-at-16.03.35.png 1808w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;strong&gt;2. Clear stories behind early churn: &lt;/strong&gt;With &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps-2025/&quot;&gt;30% of subscriptions cancelling in the first month&lt;/a&gt;, churn doesn’t mean an automatic ‘no’ from buyers. But you need to show that you understand &lt;em&gt;why &lt;/em&gt;the &lt;a href=&quot;https://www.revenuecat.com/blog/growth/robbie-kellman-baxter-how-a-membership-mindset-can-help-reduce-churn/&quot;&gt;churn&lt;/a&gt; happened, and have used it as a lesson to course-correct.&amp;nbsp; If you can explain churn, you can defend your valuation.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;3. Cohorts that stabilize over time: &lt;/strong&gt;Even if churn is high, you can still gather evidence that the most important long-term users &lt;em&gt;stick&lt;/em&gt;. Create a holistic view of your retention, across different subscription plans, user segments, and attribution sources.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Now, if you’re looking at your RevenueCat dashboard and panicking about your &lt;a href=&quot;https://www.revenuecat.com/glossary/#retention-rate&quot;&gt;retention rate&lt;/a&gt;, hold on a moment. The threshold considered ‘strong retention’ varies considerably between buyers:&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.linkedin.com/in/ryanjthorpe/&quot;&gt;Ryan Thorpe&lt;/a&gt;, Director of Growth at Reflective Apps, said “We have some apps as low at 25%, others as high at 60% on yearly subscriptions. It massively depends on what you class as ‘healthy’, and the kind of subscription model you’re running.”&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Meanwhile, &lt;a href=&quot;https://www.linkedin.com/in/jonwalshkodeon/&quot;&gt;Jon Walsh&lt;/a&gt;, Managing Partner at Kodeon and Partner at Push Capital, said: “Generally, I would say 60–70% is a decent range for annual subscription retention, depending on the app category and age. But there are a number of factors that can impact retention (like pricing strategy). It’s just one of many metrics we look at to determine whether an app is a fit for us and what its value is.”&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;takeaway-retention-signals&quot;&gt;&lt;strong&gt;Takeaway: retention signals&amp;nbsp;&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;This is a breath of fresh air for developers: it’s not &lt;em&gt;all&lt;/em&gt; about subscriber retention — all the other signals we outlined on the app buyer wishlist matter too. Consider payback periods, your pricing model, and &lt;a href=&quot;https://www.revenuecat.com/glossary/#ltv-cac-ratio&quot;&gt;LTV/CAC ratio&lt;/a&gt;; all of these add up to tell your &lt;a href=&quot;https://www.revenuecat.com/blog/growth/michael-ribero-conde-nast-sub-club-podcast-2025/&quot;&gt;retention story&lt;/a&gt;. And even then, ‘good’ retention can be anywhere between 25–70%, depending on who you’re asking.&lt;/p&gt;



&lt;p&gt;Make sure you understand your app’s metrics, know your category benchmarks, and can explain (or defend) any questions that may be thrown at you. Resources like the &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps-2025/&quot;&gt;&lt;em&gt;State of Subscription Apps report&lt;/em&gt;&lt;/a&gt; are a great place to start when comparing what ‘good’ looks like. You can also use tools like RevenueCat’s &lt;a href=&quot;https://www.revenuecat.com/healthscore/&quot;&gt;Subscription App Healthscore calculator&lt;/a&gt; to see how you measure up to competitors.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;paid-or-organic-buyer-preferences-on-traffic-and-ua&quot;&gt;&lt;strong&gt;Paid or organic? Buyer preferences on traffic and UA&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Another question Evelin gets all the time is whether &lt;a href=&quot;https://www.revenuecat.com/blog/growth/how-paid-campaigns-affect-your-apps-organic-traffic/&quot;&gt;organic traffic or scaling paid user acquisition&lt;/a&gt; (UA) matters more in valuations. This was one of the most polarizing questions in her interviews — some buyers want pure organic, others want pure paid. Most fall somewhere in between.&amp;nbsp;&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot;&gt;&lt;strong&gt;Buyers who strongly prefer organic growth&amp;nbsp;&lt;/strong&gt;&lt;/h4&gt;



&lt;p&gt;Organic traffic is seen as lower risk and higher value for money. &lt;a href=&quot;https://www.linkedin.com/in/zachtobin/&quot;&gt;Zach Tobin&lt;/a&gt;, Founder of Product Growth LLC, prefers organic: “It’s less effort to maintain, though it carries risk of algorithm changes. Ideally we want 100% organic, but I’ll invest in paid up until the breakeven point, which usually works out to an 80/20 split.”&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.linkedin.com/in/ryanjthorpe/&quot;&gt;Ryan Thorpe&lt;/a&gt;, Director of Growth at Reflective Apps, agreed: “Organic traffic is more reliable in distribution, predictable in its yearly returns, and has no additional high marketing costs.”&lt;/p&gt;



&lt;p&gt;These buyers value defensibility, and compounding growth. Organic growth is perceived as a sign of quality and secure product-market fit; making it an indicator for future reliability.&amp;nbsp;&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“The higher the organic traffic, the better. High organic traffic that is compounding is what we’re looking for: a predictable trend, where distribution is effectively free with product-market fit attained and momentum accelerating.” — &lt;a href=&quot;https://www.linkedin.com/in/ryanjthorpe/&quot;&gt;Ryan Thorpe&lt;/a&gt;, Director of Growth at Reflective Apps.&amp;nbsp;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;h4 class=&quot;wp-block-heading&quot;&gt;&lt;strong&gt;Buyers who prefer paid user acquisition&amp;nbsp;&lt;/strong&gt;&lt;/h4&gt;



&lt;p&gt;But for other buyers, &lt;a href=&quot;https://www.revenuecat.com/blog/growth/web-to-app-paid-user-acquisition/&quot;&gt;paid UA&lt;/a&gt; is seen as more predictable and thus scalable:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“Paid traffic is the backbone of our strategy… We’ve seen way too many examples of young apps rapidly showing growth through pure organic activities, but being unable to sustain that for the long run. Long-term profitability and scalability means paid UA.” — &lt;a href=&quot;https://www.linkedin.com/in/guillaume-larrieu-33623a16/&quot;&gt;Guillaume Larrieu&lt;/a&gt;, VP of Business Development at Quiet&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;&lt;a href=&quot;https://www.linkedin.com/in/kenneytom/&quot;&gt;Tom Kenney&lt;/a&gt;, CEO &amp;amp; Co-founder at LOYAL, explained that paid traffic can be a tactic to “break through the app store noise”, while other buyers preferred paid UA for its clearer insight into &lt;a href=&quot;https://www.revenuecat.com/glossary/#customer-acquisition-cost-cac&quot;&gt;CAC&lt;/a&gt;, ROAS, funnel performance, and channel trends — helping prevent costly future mistakes.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot;&gt;&lt;strong&gt;Buyers who want a balance of organic and paid traffic&lt;/strong&gt;&lt;/h4&gt;



&lt;p&gt;While some buyers said solely paid or organic traffic would turn them off an app, the majority of buyers said they wouldn’t be closed off to a split traffic mix, with many buyers actually preferring this for its balanced growth potential.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.linkedin.com/in/guillaume-larrieu-33623a16/&quot;&gt;Guillaume Larrieu&lt;/a&gt;, VP of Business Development at Quiet, said 75/25 paid/organic is a good mix for his acquisitions: “It’s even better if organic installs are driven by organic activities, like viral videos or social content, rather than ASO implementations.”&lt;/p&gt;



&lt;p&gt;Other buyers, like &lt;a href=&quot;https://www.linkedin.com/in/danielnovaes/&quot;&gt;Dan Novaes&lt;/a&gt;, Co-Founder &amp;amp; CEO at Mode Mobile, were happy with a more even split:&amp;nbsp;&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“I like paid traffic with a strong organic multiplier. Paid is predictable and scalable if you know what you’re doing. Algorithms change, so you can’t just rely on organic. A perfect world is 50/50 organic/paid.” — &lt;a href=&quot;https://www.linkedin.com/in/danielnovaes/&quot;&gt;Dan Novaes&lt;/a&gt;, Co-Founder &amp;amp; CEO at Mode Mobile&lt;/p&gt;
&lt;/blockquote&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;takeaway-organic-vs-paid-traffic&quot;&gt;&lt;strong&gt;Takeaway: organic vs. paid traffic&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Both types of traffic are relevant, but it’s clear that having paid UA is useful for buyers wanting to see metrics, profitability, or avoid old mistakes. While organic tells a story of pure growth, paid is seen as more predictable.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;You don’t need a perfect traffic mix before selling, but you need to be able to back your traffic split:&amp;nbsp;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;If organic is your strength, quantify defensibility&lt;/li&gt;



&lt;li&gt;If paid is your strength, present UA profitability + failed experiments + learnings&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Make sure you can offer buyers clarity on what channels work, what channels don’t work, why, and where you’ve built efficiency.&amp;nbsp;&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“We don’t have a preference for type of traffic, but if the app is doing paid acquisition then we really need to understand the UA metrics and what’s driving paid user performance, so we can determine how sustainable and scalable it is.” — &lt;a href=&quot;https://www.linkedin.com/in/jonwalshkodeon/&quot;&gt;Jon Walsh&lt;/a&gt;, Managing Partner at Kodeon and Partner at Push Capital&lt;/p&gt;
&lt;/blockquote&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;closing-the-deal-how-to-find-and-actually-talk-to-a-buyer&quot;&gt;&lt;strong&gt;Closing the deal: how to find (and actually talk to) a buyer&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;So you know what buyers are looking for, you’ve cleaned up your numbers, and coordinated the story of your app’s success. Now you just need to get in front of a buyer.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Sometimes a buyer may approach you, but if you’re ready to go right away, here’s how to get started.&amp;nbsp;&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Research different types of buyer: &lt;/strong&gt;individuals and businesses acquire apps for many reasons, and these different buyer types will look for different things. Spend some time familiarizing yourself with who buys apps, and where your app would fit best.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Find your buyers: &lt;/strong&gt;once you know the type of buyer you’re looking for, it’s time to network. There are websites and marketplaces where you can advertise your app, or you can speak to an M&amp;amp;A expert. Your best bet is typically networking in-person and LinkedIn. You’ll normally be looking for folks with business development, M&amp;amp;A, or partnership in their job title.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Build a target list&lt;/strong&gt;: after identifying your buyers, start tracking everyone in a spreadsheet. Record buyer info, typical deal size, recent acquisitions, and how to contact them. You can use this to document your outreach progress, too.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Reach out via channels that don’t waste time: &lt;/strong&gt;warm intros (founders, angels, lawyers, accountants, UA consultants) will &lt;em&gt;always &lt;/em&gt;outperform cold calling/emailing. If you can’t find a mutual connection, direct outreach can work through the proper channels. You can also check out founder or buyer forums or marketplace websites, where buyers may be discreetly lurking. And don’t forget in-person networking opportunities!&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Lead with a message, not your life story: &lt;/strong&gt;your first message &lt;em&gt;shouldn’t &lt;/em&gt;be a pitch. It’s a qualifier. Keep it simple, straightforward, and factual. Add top compelling metrics (think MRR, margin, growth), any relevant info (like similar apps they’re acquired, mutual connections etc.) and ask for a follow-up call.&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Once you get to the first call, your next moves will depend on who you’re talking to and what they’re looking for. Remember to lead with a combination of facts and storytelling, and keep momentum up in your conversations.&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-Z1PuL8H wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Quickfire who’s who of app buying:&quot; text=&quot;&lt;p&gt;&lt;span style=&amp;quot;font-weight: 400;&amp;quot;&gt;Apps can be bought by individuals &lt;/span&gt;&lt;i&gt;&lt;span style=&amp;quot;font-weight: 400;&amp;quot;&gt;and &lt;/span&gt;&lt;/i&gt;&lt;span style=&amp;quot;font-weight: 400;&amp;quot;&gt;businesses. Each tend to fall into one of three categories:&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li style=&amp;quot;font-weight: 400;&amp;quot; aria-level=&amp;quot;1&amp;quot;&gt;&lt;b&gt;Roll-ups and portfolio buyers&lt;/b&gt;&lt;span style=&amp;quot;font-weight: 400;&amp;quot;&gt; want predictable cash flow and clean operations&lt;/span&gt;&lt;/li&gt;
&lt;li style=&amp;quot;font-weight: 400;&amp;quot; aria-level=&amp;quot;1&amp;quot;&gt;&lt;b&gt;Growth studios &lt;/b&gt;&lt;span style=&amp;quot;font-weight: 400;&amp;quot;&gt;typically want scalable paid acquisition and clear &lt;/span&gt;&lt;a href=&amp;quot;https://www.revenuecat.com/blog/engineering/how-to-monetize-your-app-without-ads/&amp;quot;&gt;&lt;span style=&amp;quot;font-weight: 400;&amp;quot;&gt;monetization levers&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;Strategic buyers &lt;/b&gt;&lt;span style=&amp;quot;font-weight: 400;&amp;quot;&gt;are looking for category fit, cross-selling opportunities, or a missing feature &lt;/span&gt;&lt;/p&gt;&quot; icon=&quot;bulb&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;what-does-receiving-an-acquisition-offer-look-like&quot;&gt;&lt;strong&gt;What does receiving an acquisition offer look like?&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;You know how job ads frame ‘compensation packages’ versus individual salaries? Well, acquisition offers are similar. Typically, there’s three main structures to offers:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Cash: &lt;/strong&gt;fixed purchase price, paid upfront when the deal closes — this is the lowest risk for sellers, and most common kind of offer&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Equity&lt;/strong&gt;: part (or all) of the price is paid in shares of the buyer’s company; tying your payment to their growth&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Earnout distribution: &lt;/strong&gt;a portion of the price is paid only once hitting agreed revenue, profit, or growth targets post-acquisition&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Of the buyers Evelin spoke to, 66% do cash offers, with the remainders doing a mix of cash and equity or earnouts. While cash offers won’t necessarily pay out in one chunk (most buyers do 50% at a time, sometimes 6/12 months after the deal), they’re typically the best outcome for sellers, though equity can be valuable if being acquired by a successful company.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;768&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Most-common-offer-structure.png&quot; alt=&quot;&quot; class=&quot;wp-image-49390&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Most-common-offer-structure.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Most-common-offer-structure-300x225.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Most-common-offer-structure-768x576.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Most-common-offer-structure-50x38.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Most-common-offer-structure-53x40.png 53w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Most-common-offer-structure-619x464.png 619w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Most-common-offer-structure-696x522.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Most-common-offer-structure-560x420.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Most-common-offer-structure-395x296.png 395w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Most-common-offer-structure-629x472.png 629w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Most-common-offer-structure-80x60.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Most-common-offer-structure-48x36.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;what-makes-a-deal-close-fast&quot;&gt;&lt;strong&gt;What makes a deal close fast?&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;This section answers one of founders’ biggest questions: &lt;em&gt;What makes a buyer say ‘yes’ quickly?&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;Across interviews, buyers described what makes a deal feel ‘clean’ and easy, opposed to risky or slow. Here’s what speeds up decisions:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Clean, consistent financials: &lt;/strong&gt;speed requires all the numbers to be in order. No messy revenue classifications. No unexplained cliffs. No ‘miscellaneous’ line items. Anything but clear numbers will add a red flag and significantly slow down the process.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Clear handover documentation&lt;/strong&gt;: buyers moving quickly need to know they can pick up the new app and keep it ticking over without any trouble. This means getting access to: architecture overviews, data taxonomies, analytics events, roadmap history, experiment logs, growth playbooks, and anything else you have lurking in your Google Drive!&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;A transparent founder: &lt;/strong&gt;yes, fast-closing deals rely on a solid business, but they’re also impacted by &lt;em&gt;trust&lt;/em&gt;. Buyers who click with a founder and feel they’ve made a trusted connection will overlook imperfections and move faster.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;A believable growth story: &lt;/strong&gt;quite simply, buyers want to clearly be told &lt;em&gt;what happens after they buy the app. &lt;/em&gt;Help plot their success, and they’ll be eager to sign on the dotted line.&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-talent-taboo-do-app-buyers-want-founders-to-stay&quot;&gt;&lt;strong&gt;The talent taboo: Do app buyers want founders to stay?&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Most founders assume a buyer will want them gone immediately. But in reality, the answer is more nuanced — and varies depending on the buyer’s operating model.&lt;/p&gt;



&lt;p&gt;Across all interviews, we noticed three things:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Historical learnings can be very useful to support product scale&lt;/li&gt;



&lt;li&gt;Developers bring product and vision, then acquirers add marketing and &lt;a href=&quot;https://www.revenuecat.com/blog/growth/revenue-strategies-low-intent-users/&quot;&gt;monetization&lt;/a&gt; expertise&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Acquirers are interested in long term relationship-building&lt;/li&gt;
&lt;/ol&gt;



&lt;h4 class=&quot;wp-block-heading&quot;&gt;&lt;strong&gt;Buyers value product knowledge more than headcount&lt;/strong&gt;&lt;/h4&gt;



&lt;p&gt;Many acquirers prefer the original team to remain during the transition (or longer) for the undeniable reason that they deeply understand the product’s history, vision, and technical decisions.&amp;nbsp;&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“We like the teams to stick around as long as they’re still committed. The history of what they’ve tried is useful context, and we can build on that. Where they’re weaker, we plug in our expertise.” — &lt;a href=&quot;https://www.linkedin.com/in/danielnovaes/&quot;&gt;Dan Novaes&lt;/a&gt;, Co-Founder &amp;amp; CEO at Mode Mobile&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;&lt;a href=&quot;https://www.linkedin.com/in/michael-mcphee/&quot;&gt;Michael McPhee&lt;/a&gt;, Head of Business Development and M&amp;amp;A at Leadtech Group, said they ‘absolutely’ want founders to stay: “We always try to keep the team behind the app engaged after the acquisition. They know the product best, and their expertise is crucial for continued development and fast iterations.”&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.linkedin.com/in/pawelpochowski/&quot;&gt;Paweł Pochowski&lt;/a&gt;, Head of Business Development at Nova Sphere, agreed: “From a practical standpoint, having the original developer onboard ensures smoother maintenance and faster implementation of changes.”&amp;nbsp;&lt;/p&gt;



&lt;p&gt;For many buyers, acquisition is about combining skillsets of the founding team and the new owner. Michael explains: “At Leadtech, we focus on scaling marketing, monetization, and UA, while the original team focuses on product enhancements. This balance builds strong long-term partnerships and is one of the keys to our success.”&lt;/p&gt;



&lt;p&gt;Buyers don’t want to relearn the product from scratch. They want &lt;strong&gt;continuity&lt;/strong&gt;, and to &lt;strong&gt;capitalize on existing success&lt;/strong&gt;.&amp;nbsp;&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot;&gt;&lt;strong&gt;Founder involvement signals belief and influences valuation&lt;/strong&gt;&lt;/h4&gt;



&lt;p&gt;Some buyers also explicitly said that a founder wanting to stay post-acquisition can influence higher valuation. &lt;a href=&quot;https://www.linkedin.com/in/pawelpochowski/&quot;&gt;Paweł Pochowski&lt;/a&gt;, Head of Business Development at Nova Sphere, said the team prefers original creators to remain involved:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“Their continued commitment is a strong signal they believe in the product and are motivated to see it evolve.” — &lt;a href=&quot;https://www.linkedin.com/in/pawelpochowski/&quot;&gt;Paweł Pochowski&lt;/a&gt;, Head of Business Development at Nova Sphere&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Founders wanting to stay part of the team not only indicates belief in the product, but a level of passion and commitment that’s desirable of any &lt;a href=&quot;https://www.revenuecat.com/blog/growth/build-app-growth-team/&quot;&gt;team member&lt;/a&gt;. Rather than wanting to grab the cash and jump ship, founders who stay involved can support future growth, and enable smooth handovers when (or if) the time comes to part ways.&amp;nbsp;&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot;&gt;&lt;strong&gt;Some acquisitions are structured to absorb the product&amp;nbsp;&lt;/strong&gt;&lt;/h4&gt;



&lt;p&gt;Despite the benefits of creators remaining involved, large app studios or portfolio operators — particularly those with their own internal product, engineering, and UA teams — are less dependent on founders staying. However, this doesn’t mean they’re kicking you out of the door.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;As &lt;a href=&quot;https://www.linkedin.com/in/yalcinozdemir/&quot;&gt;Yalçın Özdemir&lt;/a&gt;, Founder &amp;amp; CEO at AppNation, puts it:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“We don’t expect founders to stay on after an acquisition. As a large app studio, our in-house teams, systems, and expertise allow us to integrate products efficiently and unlock value independently. That said, in rare cases where founders are deeply embedded in the product and critical to its continuity, we may ask them to remain for a transitional period of a few months.”&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;This is why it’s crucial to talk about your future as a founder with any potential buyers — wanting to leave or stay with the app won’t necessarily impact the sale, but it’s vital you’re all on the same page.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;takeaway-closing-the-deal&quot;&gt;&lt;strong&gt;Takeaway: closing the deal&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Once your numbers and story are tight, closing the deal is primarily about:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Finding the right buyer&lt;/li&gt;



&lt;li&gt;Making it easy for them to say yes&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Get to know your buyer types, build a focused list of targets and start networking. Deals move fastest when financials are clean, handover docs are ready, and founders are transparent. You don’t need to commit years of your life post-acquisition, but you &lt;em&gt;do&lt;/em&gt; need a clear transition plan. If you’re hoping to exit, consider how you can still convey confidence and historical product context to the new owners, be it through roadmaps, documentation, or a new advisory role.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;checklist-founder-prep-list-for-getting-acquired-in-2026&quot;&gt;&lt;strong&gt;Checklist: founder prep-list for getting acquired in 2026&amp;nbsp;&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;If you’re simply looking for a to-do list that answers “What do I need to do to get my app acquired?” then your wish is our command.&lt;/p&gt;



&lt;p&gt;Below is a foolproof checklist, distilled from Evelin’s app buyer interviews, ready for you to take the next steps towards acquisition. Think of this as ongoing prep for any founder looking to exit, be it today or five years from now.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;1-prepare-your-metrics&quot;&gt;&lt;strong&gt;1. Prepare your metrics&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Metrics are the evidence buyers need to decide whether your app is worth their time. Prioritize clarity and consistency — confusing or contradictory metrics slow deals more than ‘bad’ metrics.&lt;/p&gt;



&lt;p&gt;Top-level data points to prepare:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.revenuecat.com/glossary/#lifetime-value-ltv&quot;&gt;LTV&lt;/a&gt; by cohort and LTV/CAC ratio&lt;/li&gt;



&lt;li&gt;Retention curves (D7, D30, D90+ where possible)&lt;/li&gt;



&lt;li&gt;Churn reasons (voluntary vs. involuntary)&lt;/li&gt;



&lt;li&gt;Organic vs. paid traffic split&lt;/li&gt;



&lt;li&gt;UA profitability (by channel + key experiments)&lt;/li&gt;



&lt;li&gt;Revenue breakdown (subscription vs. &lt;a href=&quot;https://www.revenuecat.com/glossary/#in-app-purchase&quot;&gt;IAP&lt;/a&gt; vs. ads)&lt;/li&gt;



&lt;li&gt;% of users on annual plans (if applicable)&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;2-prepare-your-product&quot;&gt;&lt;strong&gt;2. Prepare your product&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Think of yourself as a salesperson: for the highest valuation, you need to make it as simple and appealing as possible for buyers to pick up the product and make money.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;Remember: &lt;/em&gt;&lt;/strong&gt;&lt;em&gt;Buyers aren’t looking for perfection, they’re looking for low friction.&lt;/em&gt;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Clean up any messy code paths or one-off hacks&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Reduce reliance on fragile third-party dependencies&lt;/li&gt;



&lt;li&gt;Improve onboarding clarity&lt;/li&gt;



&lt;li&gt;Tighten &lt;a href=&quot;https://www.revenuecat.com/glossary/#paywall&quot;&gt;paywalls&lt;/a&gt; and pricing logic as necessary&lt;/li&gt;



&lt;li&gt;Grow your organic traffic where possible (ASO, reviews, SEO)&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;3-prepare-your-financials&quot;&gt;&lt;strong&gt;3. Prepare your financials&amp;nbsp;&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Messy or unclear financials are one of the fastest ways to kill a deal. If a buyer has to infer what’s going on with your numbers, they’ll assume the worst. Make sure they don’t need to guess.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Before talking to buyers:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Review and cut non-essential costs (this will improve EBITDA and optics)&lt;/li&gt;



&lt;li&gt;Clean and reconcile your &lt;a href=&quot;https://docs.google.com/spreadsheets/d/1P9QafBw8OYuqJlznUr6eo7q6thwGmevR-mO2jQxvEhQ/edit?gid=1627863938#gid=1627863938&quot;&gt;profit and loss statement&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;Clearly document add-backs and one-off expenses&lt;/li&gt;



&lt;li&gt;Prepare MRR breakdowns (country, store, plan, platforms)&lt;/li&gt;



&lt;li&gt;Be ready to explain any revenue spikes, anomalies, or drop-offs&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;4-prepare-your-team&quot;&gt;&lt;strong&gt;4. Prepare your team&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Buyers care less about headcount, and more about continuity and protected knowledge. Make sure you have conversations with your team &lt;em&gt;before &lt;/em&gt;speaking to buyers.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;You need to decide:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Who’s staying post-acquisition, and for how long?&amp;nbsp;&lt;/li&gt;



&lt;li&gt;What knowledge or responsibilities need to be transferred?&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Whether you’re open to staying involved, and in what capacity&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Updated contracts, NDAs, and IP assignments&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;5-prepare-your-handover&quot;&gt;&lt;strong&gt;5. Prepare your handover&amp;nbsp;&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Deals move faster when buyers can clearly see how they’ll run the app &lt;em&gt;without &lt;/em&gt;you. Document things only you currently know, or product decisions and historic context that may be helpful for the team:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Current and historic product roadmaps&lt;/li&gt;



&lt;li&gt;Feature gating logic&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/paywalls-study-guide/&quot;&gt;Paywall logic&lt;/a&gt; and pricing history&lt;/li&gt;



&lt;li&gt;Onboarding flows and funnels&lt;/li&gt;



&lt;li&gt;Architecture overview (simple is fine)&lt;/li&gt;



&lt;li&gt;Brand assets and press kit&amp;nbsp;&lt;/li&gt;



&lt;li&gt;A master doc of tools, SDKs, dashboards, logins&lt;/li&gt;
&lt;/ul&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-Z1Cg82 wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Bonus tip&quot; text=&quot;&lt;p&gt;&lt;span style=&amp;quot;font-weight: 400;&amp;quot;&gt;Don’t forget to document experiments, distribution tests, and product learnings. It doesn’t have to be fancy, just section out information by channel or tactic and add bullet points. This will motivate the buyer knowing there’s learnings built, and documented, that they can benefit from. Evelin has created &lt;/span&gt;&lt;a href=&amp;quot;https://docs.google.com/document/d/1eUEbeo2eyPTl_4VEOEN00XT4kJifVS9X17cRRaj8jBw/edit?tab=t.0&amp;quot;&gt;&lt;span style=&amp;quot;font-weight: 400;&amp;quot;&gt;this template&lt;/span&gt;&lt;/a&gt; you can use&lt;span style=&amp;quot;font-weight: 400;&amp;quot;&gt;. &lt;/span&gt;&lt;/p&gt;&quot; icon=&quot;bulb&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;6-prepare-your-deal&quot;&gt;&lt;strong&gt;6. Prepare your deal&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Don’t wait until an offer appears to think about what you want, how you’ll approach acquisition conversations, and who else needs to know.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Here’s what you should think about:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Decide your minimum accepted offer and structure (cash vs. earnout vs. equity)&lt;/li&gt;



&lt;li&gt;Identify your ideal buyer type (studio, roll-up, strategic)&lt;/li&gt;



&lt;li&gt;Build a target buyer list&lt;/li&gt;



&lt;li&gt;Talk with at least five potential buyers before choosing&lt;/li&gt;



&lt;li&gt;Prep your first message and practice your pitch&lt;/li&gt;



&lt;li&gt;Be honest with yourself about timing, motivation, and trade-offs&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;You don’t need to tick off every item on this list at once, it’s a big job. But each checkmark is something prepared ahead of time, so when the right buyer shows up you can move forward quickly.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;final-thoughts-the-reality-of-selling-apps-in-2026&quot;&gt;&lt;strong&gt;Final thoughts: the reality of selling apps in 2026&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;After speaking to buyers, and having spoken to many founders over the years, Evelin says the biggest misconception founders have about acquisitions is that buyers are looking for perfection.&lt;/p&gt;



&lt;p&gt;They’re not.&lt;/p&gt;



&lt;p&gt;They’re looking for:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Predictable revenue&lt;/li&gt;



&lt;li&gt;A product with real PMF&lt;/li&gt;



&lt;li&gt;Retention that holds&lt;/li&gt;



&lt;li&gt;A growth story that makes sense&lt;/li&gt;



&lt;li&gt;A clean, transparent business&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Founders who can clearly communicate these signals, both in narrative form and in hard data, are going to consistently earn higher valuations and close deals faster. So if you’re wanting to sell in the next 12–24 months, start preparing now. You don’t need a perfect app or perfect pitch — you need a clear story, transparent figures, and the right buyer.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;related-tools-and-resources&quot;&gt;&lt;strong&gt;Related tools and resources&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Looking for more? Here are some related readings and tools to help you on your path to acquisition.&amp;nbsp;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Interview transcripts: &lt;a href=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Interviews-on-the-2026-app-buying-landscape.pdf&quot;&gt;read the full interview questions and answers&lt;/a&gt; &lt;/li&gt;



&lt;li&gt;RevenueCat’s &lt;a href=&quot;https://www.revenuecat.com/healthscore/&quot;&gt;subscription healthscore calculator&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;Report: &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps-2025/&quot;&gt;State of Subscription Apps&lt;/a&gt; (perfect for industry benchmarking!)&lt;/li&gt;



&lt;li&gt;Blog: &lt;a href=&quot;https://www.revenuecat.com/blog/growth/how-to-sell-an-app/&quot;&gt;How to sell an app, lessons from David Barnard&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;Podcast: &lt;a href=&quot;https://www.youtube.com/watch?v=T3YIc-clWo0&quot;&gt;What makes an app worth buying? Lessons from BlueThrone’s shift from volume to value&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;Podcast: &lt;a href=&quot;https://www.revenuecat.com/blog/growth/eric-duffet-spot-pattern-sub-club-podcast-2025/&quot;&gt;How real demand turned a hobby app into a business&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;Evelin’s template: &lt;a href=&quot;https://docs.google.com/document/d/1eUEbeo2eyPTl_4VEOEN00XT4kJifVS9X17cRRaj8jBw/edit?tab=t.0&quot;&gt;App learnings and experiments documentation&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;Evelin’s template: &lt;a href=&quot;https://docs.google.com/spreadsheets/d/1P9QafBw8OYuqJlznUr6eo7q6thwGmevR-mO2jQxvEhQ/edit?gid=1627863938#gid=1627863938&quot;&gt;Profit and loss statement&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title><![CDATA[The play-once game that sparked an indie dev career]]></title><description><![CDATA[On the podcast I talk with Taiwo about building games that are meant to be deleted, finding success by leaning into low retention instead of fighting it, and how a single unconventional idea led to Apple featuring his work and changing his career.]]></description><link>https://www.revenuecat.com/blog/growth/taiwo-omisore-word-tiles-launched-podcast-2025/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/taiwo-omisore-word-tiles-launched-podcast-2025/</guid><pubDate>Wed, 17 Dec 2025 09:47:26 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/LD-Blog-Cover-Taiwo-Omisore-1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;When Taiwo Omisore set out to make mobile games, he didn’t plan on building a business. He simply wanted to make something fun during his long commute. Over time, those experiments turned into a catalog of 15 quirky, joyful, and highly personal apps. One of them, a game designed to be played only once, changed his life.&lt;/p&gt;



&lt;p&gt;This week on Launched, we talk with Taiwo about how a side hobby became a full-time indie business powered by constraints, shareability, and unexpected virality.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;Building Differently: From Commute-Coding To 1 Chance And A 15-App Portfolio&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/CnQBqpWYnO0?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;iframe loading=&quot;lazy&quot; width=&quot;100%&quot; height=&quot;180&quot; frameborder=&quot;no&quot; scrolling=&quot;no&quot; seamless=&quot;&quot; src=&quot;https://share.transistor.fm/e/f16d11e9?color=FFFFFF&amp;amp;background=30343C&quot;&gt;&lt;/iframe&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-app-that-turned-everything-around&quot;&gt;&lt;strong&gt;The app that turned everything around&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;In 2020, Taiwo released One Chance, a game you can only play once. No retries. No replays. One Chance consisted of 14 quick mini-games, a leaderboard, and that’s it. He shared it quietly on TestFlight and Reddit. Then it started spreading—first in Germany, then globally. Soon, it was featured on the App Store.&lt;/p&gt;



&lt;p&gt;What surprised him most wasn’t the downloads but the behavior. People dug up extra devices just to try again. Friends and coworkers turned it into a competition. And the game’s single ad, shown only after gameplay, became a smart trade for attention.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-real-users-and-measurable-feedback&quot;&gt;&lt;strong&gt;Real users and measurable feedback&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Taiwo’s apps are playful, often strange, and always rooted in real-world input. Early on, he handed his phone to strangers on trains for feedback. Later, he’d bring folding tables to public spaces and host multiplayer games live with passersby.&lt;/p&gt;



&lt;p&gt;That same openness shaped everything from features to monetization. After One Chance took off, Taiwo experimented with subscriptions in apps like MultiWords and 10 Games. By focusing on simple mechanics, thoughtful UX, and low-friction monetization, he found a model that worked.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-building-with-care-sharing-with-joy&quot;&gt;&lt;strong&gt;Building with care, sharing with joy&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Many of Taiwo’s apps have no ads or in-app purchases. Some, like Who Am I?, even inspired physical art exhibitions. Others, like Of The Day, are updated daily with curated content and community submissions. He answers emails personally and celebrates being a one-person studio.&lt;/p&gt;



&lt;p&gt;Social media became a way to connect, not just promote. On TikTok, he shares coding sessions, street interviews, and app concepts. One clip even prompted a journal entry by Harry Styles.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-a-developer-first-approach&quot;&gt;&lt;strong&gt;A developer-first approach&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Today, Taiwo is a full-time indie. But his approach hasn’t changed. He builds fast, ships often, and keeps the focus on fun. His apps aren’t optimized for retention. In fact, some are designed to be deleted. And yet, they continue to find an audience, thanks to the care he puts in them and their contagious charm.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-conclusion&quot;&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;From single-play games to curated journals, this episode captures what’s possible when an indie dev leads with curiosity. Taiwo Omisore shows that with honesty, experimentation, and a little bit of joy, even the simplest ideas can turn into something lasting.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Monetize from Your IDE: AI assistant + RevenueCat MCP in the IntelliJ Plugin]]></title><description><![CDATA[Explore how the AI Assistant works in RevenueCat's IntelliJ plugin, what you can accomplish with it to boost your subscription revenue.]]></description><link>https://www.revenuecat.com/blog/engineering/ai-intellij-plug/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/ai-intellij-plug/</guid><pubDate>Wed, 17 Dec 2025 01:32:17 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/IMG_2737.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;We’ve &lt;a href=&quot;https://www.revenuecat.com/blog/engineering/revenuecat-intellij-plugin/&quot;&gt;announced the RevenueCat IntelliJ plugin&lt;/a&gt; and now it’s even got smarter. With the new AI Assistant feature, you can now query your subscription metrics, explore offerings, and get answers about your RevenueCat integration, all without leaving your IDE. Behind the scenes, this AI Assistant is integrated with the RevenueCat MCP Server, bringing the power of AI-assisted subscription management directly into your development workflow.&lt;/p&gt;



&lt;p&gt;In this article, you’ll explore how the AI Assistant works in RevenueCat’s IntelliJ plugin, what you can accomplish with it, and how this feature can help you make data-driven decisions that boost your subscription revenue.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;783&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/1-1-1024x783.png&quot; alt=&quot;&quot; class=&quot;wp-image-48858&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/1-1-1024x783.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/1-1-300x229.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/1-1-768x587.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/1-1-1536x1175.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/1-1-50x38.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/1-1-52x40.png 52w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/1-1-607x464.png 607w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/1-1-696x532.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/1-1-560x428.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/1-1-387x296.png 387w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/1-1-617x472.png 617w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/1-1-80x61.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/1-1-48x37.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/1-1.png 1552w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-is-the-revenuecat-mcp-server&quot;&gt;&lt;strong&gt;What is the RevenueCat MCP Server?&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Before diving into the AI Assistant, let’s understand the foundation it’s built on. The Model Context Protocol (MCP) is an open standard that allows AI assistants to interact with external tools and data sources. RevenueCat provides an &lt;a href=&quot;https://www.revenuecat.com/docs/tools/mcp&quot;&gt;official MCP Server&lt;/a&gt; that exposes subscription management capabilities to AI models.&lt;/p&gt;



&lt;p&gt;The MCP Server provides tools for fetching subscription metrics like MRR, active trials, and revenue. It can list and inspect offerings, packages, and products. It retrieves customer subscription information and provides documentation and resource links.&lt;/p&gt;



&lt;p&gt;The IntelliJ plugin’s AI Assistant uses the same underlying tool architecture as the MCP Server. This means you get consistent, reliable access to your RevenueCat data directly inside your IDE with our preferred AI model.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-setting-up-the-ai-assistant&quot;&gt;&lt;strong&gt;Setting up the AI Assistant&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Getting started with the AI Assistant takes just a few steps.&lt;/p&gt;



&lt;p&gt;First, open IntelliJ Settings and navigate to RevenueCat, then AI Settings. Enable the AI Assistant toggle to activate the feature.&lt;/p&gt;



&lt;p&gt;Next, choose your AI provider. The plugin supports OpenAI (GPT-4o, GPT-4o Mini), Anthropic (Claude 3.5 Sonnet, Claude 3 Haiku), and Google (Gemini 2.5 Flash, Gemini 2.5 Pro). Each provider has different strengths—GPT-4o and Claude Sonnet excel at complex reasoning, while GPT-4o Mini and Gemini Flash offer faster responses for simpler queries.&lt;/p&gt;



&lt;p&gt;Then enter your API key for your chosen provider. The key is stored securely in IntelliJ’s credential storage on your local computer.&lt;/p&gt;



&lt;p&gt;Finally, make sure your RevenueCat API credentials are configured in the main RevenueCat settings panel.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;553&quot; height=&quot;260&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/2-1.png&quot; alt=&quot;&quot; class=&quot;wp-image-48860&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/2-1.png 553w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/2-1-300x141.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/2-1-50x24.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/2-1-85x40.png 85w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/2-1-80x38.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/2-1-48x23.png 48w&quot; sizes=&quot;auto, (max-width: 553px) 100vw, 553px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Once configured, you’ll find the AI Assistant panel in the RevenueCat tool window. The interface is simple: a chat-style conversation where you can ask questions and receive responses.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;what-can-you-do-with-the-ai-assistant&quot;&gt;&lt;strong&gt;What can you do with the AI Assistant?&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The AI Assistant exposes four core capabilities through its tool set. Let’s explore each one with practical examples.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;fetching-subscription-metrics&quot;&gt;&lt;strong&gt;Fetching subscription metrics&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The most common use case is checking your subscription health without leaving the IDE.&lt;/p&gt;



&lt;p&gt;Ask the assistant “What are my current metrics?” or “Show me my MRR” and you’ll get a formatted response with your Monthly Recurring Revenue (MRR), active trials count, active subscriptions count, and total revenue. More than just querying, it’s your mini consultant. You can play with these metrics and get useful strategies to boost your revenue.&lt;/p&gt;



&lt;p&gt;This is invaluable during development. You can push a new paywall implementation, then immediately check if metrics are trending in the right direction. No dashboard tabs, no context switching.&lt;/p&gt;



&lt;p&gt;You can also ask follow-up questions like “How does my trial conversion look?” or “What’s my revenue growth?”, and “What can I do for boosting my revenue?” The AI will analyze your metrics and provide insights based on the data.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;exploring-offerings-and-packages&quot;&gt;&lt;strong&gt;Exploring offerings and packages&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;When implementing purchase flows, you need to know exactly what offerings and packages are available.&lt;/p&gt;



&lt;p&gt;Ask “What offerings do I have configured?” and the assistant will list all your offerings with their lookup keys, display names, and whether each is marked as the current offering. For each offering, you’ll see the packages it contains.&lt;/p&gt;



&lt;p&gt;This is particularly useful when you’re implementing a paywall and need to reference the exact package identifiers. Also, you can get directly the SDK API codes, by asking like “How should I fetch offerings on Android using Kotlin?”&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;815&quot; height=&quot;521&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/3-1.png&quot; alt=&quot;&quot; class=&quot;wp-image-48862&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/3-1.png 815w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/3-1-300x192.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/3-1-768x491.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/3-1-50x32.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/3-1-63x40.png 63w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/3-1-696x445.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/3-1-560x358.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/3-1-463x296.png 463w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/3-1-738x472.png 738w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/3-1-80x51.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/3-1-48x31.png 48w&quot; sizes=&quot;auto, (max-width: 815px) 100vw, 815px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;No more switching to the dashboard to double-check package names. Ask the assistant, get the answer, keep coding.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;checking-project-configuration&quot;&gt;&lt;strong&gt;Checking project configuration&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Before diving into implementation, verify your setup is correct.&lt;/p&gt;



&lt;p&gt;Ask “What’s my project status?” and the assistant will show whether your API key is configured, your project ID, whether the SDK API key is set up, and the status of notifications and webhooks.&lt;/p&gt;



&lt;p&gt;This quick health check catches configuration issues before they become runtime bugs. If something’s missing, the assistant will tell you exactly what needs to be configured.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;finding-documentation-and-resources&quot;&gt;&lt;strong&gt;Finding documentation and resources&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;When you need help with implementation, ask “Where can I find documentation for Android integration?” or “How do I set up webhooks?”&lt;/p&gt;



&lt;p&gt;The assistant provides curated links to relevant RevenueCat documentation, SDK guides for Android, iOS, Flutter, and Kotlin Multiplatform, community forums and GitHub issues, and the RevenueCat dashboard and API reference.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;choosing-the-right-ai-model&quot;&gt;&lt;strong&gt;Choosing the right AI model&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The plugin supports multiple AI providers and models. Here’s how to choose:&lt;/p&gt;



&lt;p&gt;For complex analysis and detailed explanations, use GPT-4o or Claude 3.5 Sonnet. These models excel at understanding nuanced questions and providing comprehensive answers. They’re ideal for questions like “Analyze my subscription trends and suggest improvements.”&lt;/p&gt;



&lt;p&gt;For quick queries and fast responses, use GPT-4o Mini, Claude 3 Haiku, or Gemini 2.5 Flash. These models respond faster and cost less per query. They’re perfect for simple lookups like “What’s my MRR?” or “List my offerings.”&lt;/p&gt;



&lt;p&gt;For balanced performance, Gemini 2.5 Pro offers strong reasoning capabilities with good response times.&lt;/p&gt;



&lt;p&gt;You can switch models at any time in settings. Try different models to find what works best for your workflow.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;boosting-revenue-with-ai-assisted-insights&quot;&gt;&lt;strong&gt;Boosting revenue with AI-assisted insights&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Beyond convenience, the AI Assistant can actively help you improve your subscription business.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;identify-optimization-opportunities&quot;&gt;&lt;strong&gt;Identify optimization opportunities&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Ask “What do my metrics tell me about my subscription health?” The AI will analyze your MRR, trial counts, and active subscriptions to identify patterns. Low trial conversion? The AI might suggest reviewing your onboarding flow. High churn? Consider implementing win-back campaigns.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;validate-ab-test-implementations&quot;&gt;&lt;strong&gt;Validate A/B test implementations&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;When implementing offering experiments, verify your setup is correct. Ask “Show me all my offerings and their packages” to ensure your test and control offerings are configured properly before running the experiment.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;debug-purchase-issues-faster&quot;&gt;&lt;strong&gt;Debug purchase issues faster&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;When a user reports a purchase problem, you can quickly check your configuration. “Is my project configured correctly?” gives you an instant health check. “What packages are in my default offering?” helps verify the user should see the right products.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;getting-help-and-exploring-more&quot;&gt;&lt;strong&gt;Getting help and exploring more&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The AI Assistant includes a help icon that links directly to the &lt;a href=&quot;https://www.revenuecat.com/docs/tools/mcp/usage-examples&quot;&gt;RevenueCat MCP usage examples documentation&lt;/a&gt;. This resource provides additional query examples and advanced usage patterns.&lt;/p&gt;



&lt;p&gt;You can also explore the RevenueCat IntelliJ plugin’s other features. The metrics dashboard, offerings explorer, SDK release notifications, and webhook listener all complement the AI Assistant to create a complete subscription development environment.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;conclusion&quot;&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The RevenueCat IntelliJ plugin’s AI Assistant brings subscription intelligence directly into your development workflow. By combining the power of modern AI models with RevenueCat’s comprehensive tooling, you can query metrics, explore offerings, check configuration, and find documentation—all without leaving your IDE.&lt;/p&gt;



&lt;p&gt;The result is less context switching, more flow state, and faster development cycles. Whether you’re building your first paywall or optimizing a mature subscription business, having AI-assisted access to your RevenueCat data makes the process smoother.&lt;/p&gt;



&lt;p&gt;The feature is available now in the RevenueCat IntelliJ plugin. Configure your AI provider, connect your RevenueCat credentials, and start asking questions. Your subscription metrics are just a chat message away.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[How to monetize your app without ads]]></title><description><![CDATA[The monetization paths that actually work — and why stay avoids ads for monetization]]></description><link>https://www.revenuecat.com/blog/engineering/how-to-monetize-your-app-without-ads/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/how-to-monetize-your-app-without-ads/</guid><pubDate>Tue, 16 Dec 2025 11:58:46 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-3.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Ads are a common way of monetizing apps&amp;nbsp;— providing a way to extract value from users without making them pay for the app directly. However, due to the scale they require most in-app ads never end up providing enough money to justify the downsides they bring. Additionally the negative effect on user experience and the dependency on ad networks to end up tilting the scale to the negative.&lt;/p&gt;



&lt;p&gt;At RevenueCat we aren’t against ads by default, but for most apps asking customers to pay for the app is a better way. This reasoning comes into effect especially when you’re monetizing a new app, where retention is more important than acquiring. That’s why we made this guide to monetizing your app without ads, going through all the other monetization methods you have at your disposal.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;This guide takes an indie developer friendly approach, suggesting methods you can adopt from already before you launch your app, and offering guidance on moving from one monetization method as you scale.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-indie-developers-should-not-choose-ads&quot;&gt;Why indie developers should not choose ads&lt;/h2&gt;



&lt;p&gt;When you’re an indie developer, ads are most likely the worst choice for monetizing your app. Hear me out. You most likely built your app because you yourself had use for it? Or perhaps you wanted to build something cool, or perhaps you just like building apps. Whatever the case is, what you’re predominantly not interested in is money in most cases, but building something people want to use.&lt;/p&gt;



&lt;p&gt;There is a certain thrill that you get when you see people using your app that is hard to beat. It can almost become a goal to get more users. At the same time, you wouldn’t mind getting a little bit of monetary recognition for your work. At that point you start to think “&lt;em&gt;I don’t want to restrict my app from anyone, I’ll just put ads&lt;/em&gt;”. But ads come with multiple downsides:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Massive downgrade to user experience and messy looking UIs&lt;/li&gt;



&lt;li&gt;Plenty of privacy concerns due to user data tracking&lt;/li&gt;



&lt;li&gt;Performance issues (draining more battery, more data usage)&lt;/li&gt;



&lt;li&gt;Your personal brand will take a hit&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;In general, it’s hard to position your app as a serious app with ads. There are plenty of ways to monetizing your app that have way fewer tradeoffs. Not to mention how little money ads usually bring you.&lt;/p&gt;



&lt;p&gt;To give an example let’s look at the &lt;a href=&quot;https://kk.org/thetechnium/1000-true-fans/&quot;&gt;1000 true fans hypothesis&lt;/a&gt;, an article by Kevin Kelly about how you can build a business or side hustle by just having 1000 true fans who all pay a little bit for the things you’re producing. 1000 people paying just a dollar a month is $12k a year. If you had 1000 users using your app with ads, you would only get a few dollars per month.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-core-non-ad-monetization-models&quot;&gt;The core non-ad monetization models&lt;/h2&gt;



&lt;p&gt;Whether you’re targeting iOS or Android, the ways you can monetize your app are the same. Let’s go through all the ways you can monetize your app beyond ads.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-pay-to-download&quot;&gt;Pay to download&lt;/h3&gt;



&lt;p&gt;Pay for the full version of the app used to be a common model back when software was still sold on CDs (ask your father). Back then developers could release a new every year and capture more revenue from users as they bought the new version of your app.&lt;/p&gt;



&lt;p&gt;App Store and Google Play Store still support putting a price on your app, but Apple for example considers this model outdated. As developing and supporting an app is a continuous process, the only time you should consider adopting pay to download is if you’re going to release your app once, and make only very limited changes to it in the future.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-in-app-purchases-iap&quot;&gt;In-app purchases (IAP)&lt;/h3&gt;



&lt;p&gt;Once the user has downloaded your app, whether that was for free or for a charge, you can actually ask users for more money. Both Play Store and App Store support payments inside apps for purchasing digital goods inside the app, hence the name in-app purchases. There are few different in-app purchase options: consumables, non-consumables, non-recurring subscriptions, and recurring subscriptions: the latter which we will talk about in its own section. Let’s first go through the other options.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-consumables&quot;&gt;&lt;strong&gt;Consumables&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Consumable in-app purchases are payments for things in the app that the user purchases and then consumes, such as extra lives in a game. They grant users the access to contents only until they are used in the app, so they work well for example in games where you can build custom economies based on them.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-non-consumables&quot;&gt;&lt;strong&gt;Non-consumables&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;These purchases never expire and the user is for example able to recover the purchases after uninstalling and reinstalling the app, as the purchase information is stored by Apple and Google. You can make non-consumable purchases unlock features in your app for permanent use. You could almost think of these as a way of moving the pay to download further into the actual app itself.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-non-recurring-subscriptions&quot;&gt;&lt;strong&gt;Non-recurring subscriptions&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;These purchases as the name suggests only grant the user access to features of the app for a certain period of time, for example one month, after which Apple and Google (TK check if google has this type actually) mark them expired. You can build for example limited time&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-subscriptions&quot;&gt;Subscriptions&lt;/h3&gt;



&lt;p&gt;Of all the mentioned in-app purchases options, only consumable in-app purchases (through repeated use) and recurring subscriptions (through periodic payments) bring you that much needed recurring revenue to continue building your app. Building your monetization around consumable purchases can be difficult, so recurring subscriptions is your best option for monetizing your app if you’re looking for recurring revenue.&lt;/p&gt;



&lt;p&gt;The fundamental concept behind subscription is simple: the user pays a periodic subscription fee and has access to all features of your app during the subscription period. If they do not cancel their subscription their access to the app continues, and they keep paying you.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Both App Store and Play Store provide extensive options for configuring subscriptions with different billing periods, prices, and offers such as free trials. Deciding on the pricing can get tricky, but benchmarking against your competitors is a good way to go. You can learn about these from our &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps-2025/&quot;&gt;State of subscription apps report&lt;/a&gt;.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-donations-and-tip-jars&quot;&gt;Donations and tip jars&lt;/h3&gt;



&lt;p&gt;Perhaps you don’t want to limit your users’ access to your app or its features, but if they feel like sponsoring you in any way, you wouldn’t say no to that? These types of payments, whether they are sponsorships, donations, or tipping also have to go through Apple’s and Google’s in-app purchase infrastructures.&lt;/p&gt;



&lt;p&gt;Donations and tipping and essentially just consumable purchases. If you’re interested in learning more about implementing these in your app, I suggest you take a look at this &lt;a href=&quot;https://www.revenuecat.com/blog/engineering/building-a-tip-jar-feature-with-revenuecat/&quot;&gt;blog post about building a tip jar in your app&lt;/a&gt;.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-virtual-currencies&quot;&gt;Virtual currencies&lt;/h3&gt;



&lt;p&gt;Virtual currencies are in-app currencies that allow your users to pay for using features and services of your app, without having to go through the in-app purchase infrastructure. This could be for example something like Duolingo Gems, which allow you to restore your broken streak. Another type of currency could be a second of video generation in an AI video creation app.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;The power of virtual currencies is that you can grant users with virtual currencies either through purchases or by completing certain actions. &lt;a href=&quot;https://www.revenuecat.com/docs/offerings/virtual-currency&quot;&gt;RevenueCat’s Virtual currencies&lt;/a&gt; feature allows you to grant them through both subscriptions as well as consumable purchases, meaning users could receive 500 gems every month for their subscription, but on top of that they can still purchase additional gem packs. Alternatively you could also grant a few gems for watching an ad (if you decide to keep those around).&lt;/p&gt;



&lt;p&gt;Games and gamified apps often use some form of virtual currencies, but as mentioned they can also be a flexible monetization method for AI powered tools, where the AI usage can be directly tied to usage. If you’re building an AI-powered app, take a look at this tutorial on &lt;a href=&quot;https://www.revenuecat.com/blog/engineering/how-to-monetize-your-ai-app-with-virtual-currencies/&quot;&gt;monetizing your AI app with virtual currencies&lt;/a&gt;.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-hybrid-models&quot;&gt;Hybrid models&lt;/h3&gt;



&lt;p&gt;Sometimes the best monetization strategy is one that combines multiple different models. Your app could offer both recurring options for monthly and yearly subscriptions, with an extra lifetime subscription that uses a non-consumable in-app purchase to do that. Hybrid models are becoming far more popular and effective than they were in the past. According to the 2025 State of Subscription Apps report, more than 35% of apps now combine subscriptions with consumables or lifetime purchases, and the fastest-growing categories (Gaming at 61.7% and Social &amp;amp; Lifestyle at 39.4%) are leading the shift.&lt;/p&gt;



&lt;p&gt;If your app currently has ads, one option is not to transition away from them completely, but instead make it so that the free version of the app has ads, which users can then remove by subscribing. You can learn more about this approach from our &lt;a href=&quot;https://www.revenuecat.com/blog/engineering/ad-free-subscriptions-in-react-native/&quot;&gt;building ad-free subscriptions with RevenueCat article&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;Virtual currencies is the most flexible option for hybrid models, as mentioned above, since it allows you to add two different recurring revenue models, subscriptions and consumable in-app purchases, without having to manage the complex in-app currencies yourself.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-to-find-the-best-model-for-your-app&quot;&gt;How to find the best model for your app&lt;/h2&gt;



&lt;p&gt;Since there are multiple ways to monetize your app, it might not be instantly evident what model suits your app the best. This is also something where RevenueCat can help you&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-use-state-of-subscription-apps-report-to-understand-your-competitors&quot;&gt;Use State of Subscription Apps report to understand your competitors&lt;/h3&gt;



&lt;p&gt;Every year RevenueCat publishes a report called the State of Subscription Apps, a preview into our insights on in-app subscription performance benchmarks, drawing from the world’s largest and most comprehensive subscription app data set.&lt;/p&gt;



&lt;p&gt;The report is a valuable tool for understanding how apps are performing under different monetization scenarios, across both the iOS and Android ecosystems. You can find the &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps-2025/&quot;&gt;latest report here&lt;/a&gt;.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-experimentation-is-the-key&quot;&gt;Experimentation is the key&lt;/h3&gt;



&lt;p&gt;Once you have a hunch on what kind of monetization method and pricing could work for your app it’s time to get to work by experimenting. RevenueCat allows you to build different paywalls, target specific types of users, build multiple pricing options with offers, and best of all extensively experiment and test which of these changes convert best to paying users. RevenueCat’s blog has articles around &lt;a href=&quot;https://www.revenuecat.com/blog/growth/10-price-test-ideas-for-your-mobile-app/&quot;&gt;price testing your app’s subscriptions&lt;/a&gt; and &lt;a href=&quot;https://www.revenuecat.com/blog/growth/paywalls-study-guide/&quot;&gt;a study guide for building paywalls&lt;/a&gt; that you should go through, should run into a wall.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-wrapping-up&quot;&gt;Wrapping up&lt;/h2&gt;



&lt;p&gt;Ads promise easy revenue, but for most indie developers they deliver the opposite: low earnings, lower retention, and a worse user experience. Sustainable growth comes from models that align your incentives with your users — and that almost always means asking people to pay for the value you’re building.&lt;/p&gt;



&lt;p&gt;Subscriptions remain the most reliable path to recurring revenue, but they’re not the only one. Consumables, virtual currencies, and hybrid approaches let you monetize different user segments without compromising the product experience. As the 2025 State of Subscription Apps shows, the top-performing apps increasingly mix models to boost LTV and give users more flexibility.&amp;nbsp; ￼&lt;/p&gt;



&lt;p&gt;Where you start matters less than how quickly you learn. Experiment with pricing, trials, paywalls, and offers. Use data to refine your approach. And lean on tools like RevenueCat to test, iterate, and scale your monetization without rebuilding infrastructure every time.&lt;/p&gt;



&lt;p&gt;Build something people love — then choose a monetization model that helps you keep building.&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[HDYHAU surveys as an attribution source: when they work (and what to do when they don’t)]]></title><description><![CDATA[When user recall aligns with social ads, and when it can skew channel performance]]></description><link>https://www.revenuecat.com/blog/growth/how-did-you-hear-about-us-surveys/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/how-did-you-hear-about-us-surveys/</guid><pubDate>Tue, 16 Dec 2025 10:50:07 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/The-impact-of-AI-apps-on-subscription-economics.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Uncovering where users first heard about your app and how they came to download it is an age-old problem for app businesses. Tracking attribution is key to tapping into your best user acquisition (UA) sources, but with advertising spread across multiple channels and things like word-of-mouth hard to track, teams are often left in the dark.&lt;/p&gt;



&lt;p&gt;‘How did you hear about us?’ (HDYHAU) questions seem to solve this problem, but are they really the solution?&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-use-hdyhau-nbsp&quot;&gt;&lt;strong&gt;Why use HDYHAU?&amp;nbsp;&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Many subscription apps face growing data discrepancies when it comes to tracking attribution. This is largely because iOS remains the primary source of revenue — but while these users typically have higher conversion rate (CVR) and stickiness, iOS offers limited attribution tracking. Structured frameworks for &lt;a href=&quot;https://www.revenuecat.com/blog/growth/ios-attribution-guide-skan-aem-probabilistic/&quot;&gt;modelling attribution on iOS&lt;/a&gt; can help, but that’s only part of the equation.&amp;nbsp;&amp;nbsp;&lt;/p&gt;



&lt;p&gt;To address these gaps, teams have opted for a simple way to measure the impact of ads: directly asking users “How did you hear about us?”. This question, commonly shown during onboarding or purchase flows, allows users to self-report their acquisition source. The answer options typically include:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Facebook&lt;/li&gt;



&lt;li&gt;Instagram&lt;/li&gt;



&lt;li&gt;TikTok&lt;/li&gt;



&lt;li&gt;YouTube&lt;/li&gt;



&lt;li&gt;Google&lt;/li&gt;



&lt;li&gt;Friend&lt;/li&gt;



&lt;li&gt;Other&lt;/li&gt;
&lt;/ul&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;569&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/HDYHAU-EXAMPLE-1024x569.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-48889&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/HDYHAU-EXAMPLE-1024x569.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/HDYHAU-EXAMPLE-300x167.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/HDYHAU-EXAMPLE-768x427.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/HDYHAU-EXAMPLE-50x28.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/HDYHAU-EXAMPLE-72x40.jpg 72w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/HDYHAU-EXAMPLE-696x387.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/HDYHAU-EXAMPLE-560x311.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/HDYHAU-EXAMPLE-533x296.jpg 533w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/HDYHAU-EXAMPLE-840x467.jpg 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/HDYHAU-EXAMPLE-80x44.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/HDYHAU-EXAMPLE-48x27.jpg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/HDYHAU-EXAMPLE.jpg 1260w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;(There are some apps that randomize the order of the options to ensure answers from users are intentional, but in my experience, this doesn’t tend to impact the distribution of the answers.)&lt;/p&gt;



&lt;p&gt;For early-stage teams running a small number of social channels (often Meta or TikTok) HDYHAU data has been a gamechanger; helping surface under-attribution in probabilistic systems and align performance with blended results. In these cases, self-reported data often appears more consistent than network or mobile measurement partner (MMP) reporting. However, as apps scale and expand into additional channels, HDYHAU responses become increasingly unreliable as an attribution source (more on this later).&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-using-hdyhau-for-social-ad-attribution&quot;&gt;&lt;strong&gt;Using HDYHAU for social ad attribution&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The HDYHAU question fixes a common issue that all advertisers have with iOS: it gives the possibility of comparing like-to-like in a landscape where every attribution methodology works in a different way. If you use tools like Amplitude or Mixpanel, you can have graphics like this:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;460&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-7-1024x460.png&quot; alt=&quot;&quot; class=&quot;wp-image-48886&quot; style=&quot;width:700px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-7-1024x460.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-7-300x135.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-7-768x345.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-7-50x22.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-7-89x40.png 89w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-7-696x313.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-7-560x251.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-7-840x377.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-7-80x36.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-7-48x22.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-7.png 1394w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;As you can see, this graphic is simply showing the answers for the HDYHAU question on a weekly basis, so if you take the campaign data, the MMP data, and compare them against this first-party data, you have a very simplistic way of seeing if your campaigns are underattributing or not.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;According to my experience, when you use probabilistic methodologies like ADC for TikTok or AEM for Meta, you will likely track &lt;em&gt;less&lt;/em&gt; conversions in your campaigns than have actually happened — leading you to make wrong &lt;a href=&quot;https://www.revenuecat.com/blog/growth/web-to-app-paid-user-acquisition/&quot;&gt;paid UA decisions&lt;/a&gt;.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;However, with HDYHAU, you quickly solve that problem by comparing both sources, so you can see if certain attribution channels are over- or under-attributed. That looks like this:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;762&quot; height=&quot;463&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-5.png&quot; alt=&quot;&quot; class=&quot;wp-image-48882&quot; style=&quot;width:700px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-5.png 762w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-5-300x182.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-5-50x30.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-5-66x40.png 66w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-5-696x423.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-5-560x340.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-5-487x296.png 487w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-5-80x49.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-5-48x29.png 48w&quot; sizes=&quot;auto, (max-width: 762px) 100vw, 762px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Since you (understandably) expect the user-reported data to be most accurate, &lt;a href=&quot;https://www.revenuecat.com/blog/growth/grow-your-app-with-revenuecat-an-intro-for-app-marketers/&quot;&gt;marketers&lt;/a&gt; using HDYHAU as an attribution source typically place more importance on this first-party data than the MMP or ad network data. In most cases, they see greater impact on the blended results when they enable campaigns (like in the screenshot above, from a current project of mine).&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-example-how-hdyhau-impacts-revenue&quot;&gt;&lt;strong&gt;Example: how HDYHAU impacts revenue&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;In my example above, the average difference between HDYHAU and the installs reported by Meta on a daily basis is 95. Assuming you have a 5% CVR, you’re roughly missing ~5 subscriptions per day (150/month) comparing the two attribution sources.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;em&gt;Note: You can also have direct subscription reports on Amplitude, if you group users by the answer they gave in the HDYHAU step, but for the sake of this example let’s keep it simple.&amp;nbsp;&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;Let’s consider two scenarios where we follow this first-party data:&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Scenario one:&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;On day 90, your app has a &lt;a href=&quot;https://www.revenuecat.com/glossary/#lifetime-value-ltv&quot;&gt;lifetime value (LTV)&lt;/a&gt; of $50; on day 60, it has an LTV of $30&lt;/li&gt;



&lt;li&gt;You &lt;em&gt;don’t&lt;/em&gt; have HDYHAU in place, so you’re relying on MMP and ad network data for attribution&lt;/li&gt;



&lt;li&gt;You spend $10k on paid campaigns during one month, then crosscheck Meta and MMP data, reporting &lt;strong&gt;200 purchases&lt;/strong&gt; — resulting in a &lt;strong&gt;$50 &lt;/strong&gt;&lt;a href=&quot;https://www.revenuecat.com/glossary/#customer-acquisition-cost-cac&quot;&gt;&lt;strong&gt;customer acquisition cost (CAC)&lt;/strong&gt;&lt;/a&gt;&amp;nbsp;&lt;/li&gt;



&lt;li&gt;In this scenario, your LTV would cover that CAC in 90 days, so from &lt;strong&gt;day 90&lt;/strong&gt; you would start to make profits&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;&lt;strong&gt;Scenario two:&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Imagine the same scenario, but you &lt;em&gt;do &lt;/em&gt;have HDYHAU in place:&lt;/li&gt;



&lt;li&gt;You see the same difference on conversions as in my example above (~150/month)&lt;/li&gt;



&lt;li&gt;With your first-party data in place and spending $10k on paid, you report &lt;strong&gt;350 subscriptions&lt;/strong&gt; in the same period of time, giving you a &lt;strong&gt;CAC of ~$29&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;In this scenario, you begin making profit from &lt;strong&gt;day 60&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;In a business model where cash flow is critical, this difference is &lt;em&gt;hugely&lt;/em&gt; impacting every decision on weekly optimization of paid campaigns, and how aggressively you can scale them.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;This is why first-party data has become a highly-valued data source for app teams relying on social ads. In a world shaped by ATT, SKAN, and privacy constraints, it’s one of few reliable ways of ensuring paid campaigns get the credit they deserve — because the answer is coming directly from users, rather than depending on probabilistic attribution methodologies that rely on fingerprinting.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;At a first glance, HDYHAU feels like the perfect solution to address all this attribution mess happening in iOS. No black boxes, no delayed postbacks, no large discrepancies. Just a direct answer from your user collected within your product.&lt;/p&gt;



&lt;p&gt;But there’s two significant flaws in this:&amp;nbsp;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;The easy-to-read attribution &lt;strong&gt;breaks down when you &lt;/strong&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/ad-channel-diversification/&quot;&gt;&lt;strong&gt;diversify paid ad channels&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;And what’s more, HDYHAU relies on users &lt;strong&gt;accurately recalling and recording where they first heard about you&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-when-hdyhau-fail-as-attribution-for-non-social-ads&quot;&gt;&lt;strong&gt;When HDYHAU fail as attribution for non-social ads&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Most companies begin with the classic ad networks (Google, Meta, TikTok) when they start paid UA, and using first-party data with this setup is smart — it’s likely more accurate than relying on probabilistic attribution. But when you have a large budget for these channels and run alternative ad channels (e.g. a demand-side platform (DSP)), HDYHAU begins losing accuracy.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;On a high level of spend, you have a large presence across social media due to paid ads and multiple channels — users will likely have come across an advert, logo, or app name long before they actually download the app. So when they click ‘Facebook’ or ‘TikTok’ as where they first heard about you, they’re actually selecting:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;What they &lt;em&gt;think &lt;/em&gt;influenced them&lt;/li&gt;



&lt;li&gt;What options &lt;em&gt;feel familiar &lt;/em&gt;to them&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;At this point, &lt;strong&gt;HDYHAU surveys aren’t capturing causal attribution; &lt;/strong&gt;they’re identifying &lt;strong&gt;perceived influence, brand familiarity, &lt;/strong&gt;and&lt;strong&gt; recall under pressure.&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-example-how-distribution-of-spend-impacts-hdyhau&quot;&gt;&lt;strong&gt;Example: how distribution of spend impacts HDYHAU&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;This fundamental flaw of HDYHAU at a large business level is also why the &lt;strong&gt;distribution of media mix and ad spend will likely affect the distribution of answers&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;For example, if your media mix is 60% Meta, 20% TikTok, 20% Google, you’ll likely have a HDYHAU attribution that reflects this, even after running campaigns in an alternative channel.&lt;strong&gt; &lt;/strong&gt;This interpretation becomes critical the moment you introduce these channels into your media mix.&lt;/p&gt;



&lt;p&gt;This screenshot is real data from a recent Applovin campaign I ran for a new client. They have a rough $50–60k spend, with 90% to Meta and the remainder to TikTok. We started Applovin for the first time in November and began monitoring the answers to ‘Other’ in the HDYHAU survey.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;463&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-6-1024x463.png&quot; alt=&quot;&quot; class=&quot;wp-image-48884&quot; style=&quot;width:700px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-6-1024x463.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-6-300x136.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-6-768x347.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-6-50x23.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-6-89x40.png 89w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-6-696x315.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-6-560x253.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-6-840x380.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-6-80x36.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-6-48x22.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-6.png 1436w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;As you can see, there’s no difference in the baseline after running the campaigns for more than 10 days and spending more than $10k (the minimum budgets in these platforms are much higher). The MMP reported +200 conversions to the campaigns based on last click, so we would have to see an uplift in this baseline.&lt;/p&gt;



&lt;p&gt;The reason behind this is simple — platforms like Applovin operate very differently from traditional social ads: they buy inventory across thousands of apps, and show ads beyond social media platforms e.g. playing a game, scrolling, or waiting for a reward. So later, when users reach the HDYHAU question, they just select the most familiar option.&lt;/p&gt;



&lt;p&gt;Meta, Google and TikTok benefit massively from this bias, since they’re culturally-dominant and top-of-mind. So even if users didn’t discover the app on these platforms, they’re a safe choice.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;The result? &lt;strong&gt;HDYHAU surveys over-attribute conversions to the most recognizable platforms&lt;/strong&gt; → you draw conclusions based on inaccurate data → you base budget allocation and channel optimization decisions on this.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-tl-dr-when-to-use-avoid-hdyhau-for-attribution&quot;&gt;&lt;strong&gt;TL;DR: when to use/avoid HDYHAU for attribution&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;When HDYHAU is treated as accurate attribution, demand-side platforms are set up to (look like they) fail. This doesn’t make HDYHAU surveys useless, but it &lt;em&gt;does &lt;/em&gt;limit their use to specific scenarios. Here’s a summary:&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;✅ When HDYHAU surveys can be reliable:&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;❌ When HDYHAU may be misleading:&lt;/strong&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;– Paid acquisition is limited to one–two major social platforms&lt;br&gt;– Spend is relatively concentrated (e.g. Meta or TikTok)&lt;br&gt;– The goal is detecting under-attribution in probabilistic systems&lt;br&gt;– Teams are early-stage and optimizing for speed over precision&lt;br&gt;– You want to get indicators of shifting channel familiarity and trends&lt;br&gt;– You need directional insights on brand awareness&lt;/td&gt;&lt;td&gt;– Multiple channels run simultaneously (social + DSPs + search)&lt;br&gt;– Brand presence is already high across platforms&lt;br&gt;– Users are exposed to ads outside recognizable environments&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-to-measure-attribution-with-dsps&quot;&gt;&lt;strong&gt;How to measure attribution with DSPs&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;If you read to this point you’re probably wondering what you &lt;em&gt;should&lt;/em&gt; rely on for attribution. HDYHAU surveys are still useful, but only on the small–medium level. Exploring how to measure attribution for larger ad budgets is another article in itself — but broadly-speaking, these are the most effective approaches to see if DSPs are really bringing impact:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Incrementality tests with GEO holdouts&lt;/li&gt;



&lt;li&gt;Incrementality tests with Ads ON/OFF&lt;/li&gt;



&lt;li&gt;Incrementality tests with budget ramps&lt;/li&gt;



&lt;li&gt;Blended performance analysis&lt;/li&gt;



&lt;li&gt;SKAN analysis (less effective because it tends to underattribute)&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;In my opinion, it’s valuable to run incrementality tests where you maintain the classic channels with a stable spend for a few days, and then you substantially increase the budget on the DSP. You can then measure how the baseline of conversions changed before and after starting the campaign in the DSP — and attribute the difference in the baseline to the MMP.&lt;/p&gt;



&lt;p&gt;With this approach, you don’t need to pause your main growth driver, since you normally start with DSPs when you’ve already reached a nice volume of spend on the classic channels.&lt;/p&gt;



&lt;p&gt;Yes, these methods are slower, less intuitive and harder to justify but they measure causality, &lt;strong&gt;not memory.&lt;/strong&gt;&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-value-of-hdyhau-is-how-you-use-them&quot;&gt;The value of &lt;strong&gt;HDYHAU is how you use them&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;In the current privacy landscape, first-party data feels like a safe fallback; but &lt;strong&gt;data being first-party doesn’t automatically make it correct&lt;/strong&gt;. The work of &lt;a href=&quot;https://www.revenuecat.com/blog/growth/build-app-growth-team/&quot;&gt;growth teams&lt;/a&gt; and marketers is to adapt your framework to track data to the current channel mix and then compare how it evolves when a new channel is introduced.&lt;/p&gt;



&lt;p&gt;If you want to understand whether your spend is working, you need measurement frameworks built for causality: incrementality tests, controlled experiments, and blended performance analysis. Surveys can still play a role, but only as qualitative context — not as evidence.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Announcing RevenueCat IntelliJ Plugin]]></title><description><![CDATA[We're announcing the RevenueCat IntelliJ plugin, which is a tool that integrates RevenueCat's core functionality directly into your IDE.]]></description><link>https://www.revenuecat.com/blog/engineering/revenuecat-intellij-plugin/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/revenuecat-intellij-plugin/</guid><pubDate>Mon, 15 Dec 2025 01:30:14 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Announcing-RevenueCat-IntelliJ-Plugin.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Building subscription-based apps involves constant context switching. You write code in your IDE, check metrics in the RevenueCat dashboard, monitor webhook events in a terminal, and browse documentation in a browser. Each context switch may break your flow and add friction to the development process. What if you could bring RevenueCat directly into your IDE?&lt;/p&gt;



&lt;p&gt;Today, we’re announcing the RevenueCat IntelliJ plugin, which is a tool that integrates RevenueCat’s core functionality directly into your IDE. You can track metrics, receive purchase notifications, integrate SDKs, set milestones, and stay updated with releases without leaving your development environment.&lt;/p&gt;



&lt;p&gt;The plugin works across the entire JetBrains IDE: IntelliJ IDEA, Android Studio, WebStorm, PyCharm, Fleet, and 10+ other IntelliJ-based IDEs. Whether you’re building Android apps in Android Studio, cross-platform apps in IntelliJ IDEA, or React Native apps in WebStorm, the plugin provides a consistent experience.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-getting-started&quot;&gt;&lt;strong&gt;Getting started&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The plugin is available on the JetBrains Marketplace. You can install it directly from your IDE:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Open &lt;strong&gt;Settings&lt;/strong&gt; → &lt;strong&gt;Plugins&lt;/strong&gt; → &lt;strong&gt;Marketplace&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;Search for “RevenueCat”&lt;/li&gt;



&lt;li&gt;Click &lt;strong&gt;Install&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;580&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-12-at-10.21.16-AM-1024x580.png&quot; alt=&quot;&quot; class=&quot;wp-image-48728&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-12-at-10.21.16-AM-1024x580.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-12-at-10.21.16-AM-300x170.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-12-at-10.21.16-AM-768x435.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-12-at-10.21.16-AM-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-12-at-10.21.16-AM-71x40.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-12-at-10.21.16-AM-696x395.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-12-at-10.21.16-AM-560x317.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-12-at-10.21.16-AM-522x296.png 522w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-12-at-10.21.16-AM-833x472.png 833w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-12-at-10.21.16-AM-80x45.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-12-at-10.21.16-AM-48x27.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-12-at-10.21.16-AM.png 1346w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;After installing the plugin, open the &lt;strong&gt;RevenueCat&lt;/strong&gt; tool window from the right sidebar. If you don’t see it there, you can enable it via &lt;strong&gt;View → Tool Windows → RevenueCat&lt;/strong&gt;. Then first, configure your API credentials in the settings panel, and you’ll see your metrics appear immediately. You can get all of these keys on your&lt;a href=&quot;https://app.revenuecat.com/&quot;&gt; RevenueCat dashboard&lt;/a&gt;.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;250&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/1-1024x250.png&quot; alt=&quot;&quot; class=&quot;wp-image-48585&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/1-1024x250.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/1-300x73.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/1-768x188.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/1-50x12.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/1-125x31.png 125w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/1-696x170.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/1-560x137.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/1-840x205.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/1-80x20.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/1-48x12.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/1.png 1202w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;track-key-metrics&quot;&gt;&lt;strong&gt;Track key metrics&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The plugin displays your RevenueCat dashboard metrics directly in your IDE. You can monitor MRR, active subscriptions, active trials, revenue, and other key metrics at a glance while you’re working on your app.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;771&quot; height=&quot;554&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/2.png&quot; alt=&quot;&quot; class=&quot;wp-image-48587&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/2.png 771w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/2-300x216.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/2-768x552.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/2-50x36.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/2-56x40.png 56w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/2-646x464.png 646w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/2-696x500.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/2-560x402.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/2-412x296.png 412w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/2-657x472.png 657w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/2-80x57.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/2-48x34.png 48w&quot; sizes=&quot;auto, (max-width: 771px) 100vw, 771px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The metrics panel shows your current subscription values without requiring you to open a browser. When you’re debugging a purchase flow or implementing a new subscription feature, having immediate visibility into your metrics helps you verify that changes are working as expected. The data refreshes by clicking the refresh button, or when you change any configurations.&lt;/p&gt;



&lt;p&gt;This is particularly valuable during feature development. When you’re implementing a new subscription tier or modifying your paywall, you can immediately see the impact on your metrics. You can start your morning by exploring the metrics on the IDE directly and focus on your code right away.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;receive-notifications-for-purchases-and-webhook-events&quot;&gt;&lt;strong&gt;Receive notifications for purchases and webhook events&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Want a little dopamine hit from new purchase notifications while you’re building? Stay informed about what’s happening with your app’s subscriptions in real-time. The plugin can receive&lt;a href=&quot;https://www.revenuecat.com/docs/integrations/webhooks&quot;&gt; RevenueCat’s webhook&lt;/a&gt; events and display notifications for new purchases, renewals, cancellations, billing issues, and other subscription lifecycle events directly in your IDE.&lt;/p&gt;



&lt;p&gt;You can set up a webhook for your IDE in the RevenueCat settings. This plugin includes a lightweight local server to listen for webhook events, so you’ll need to configure webhook integration on the RevenueCat dashboard and install &lt;strong&gt;ngrok&lt;/strong&gt; by following the plugin guide. Once it’s set up, the webhook listener will automatically start whenever you restart your IDE.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;382&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/3-1024x382.png&quot; alt=&quot;&quot; class=&quot;wp-image-48589&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/3-1024x382.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/3-300x112.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/3-768x287.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/3-50x19.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/3-107x40.png 107w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/3-696x260.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/3-560x209.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/3-840x314.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/3-80x30.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/3-48x18.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/3.png 1192w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Once you’ve finished the configuration, you can send a test event from the dashboard by going to &lt;strong&gt;Integrations (left menu) → Webhooks → Send test event&lt;/strong&gt;.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;481&quot; height=&quot;125&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/4.png&quot; alt=&quot;&quot; class=&quot;wp-image-48591&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/4.png 481w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/4-300x78.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/4-50x13.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/4-125x32.png 125w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/4-80x21.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/4-48x12.png 48w&quot; sizes=&quot;auto, (max-width: 481px) 100vw, 481px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The webhook integration works by running a local server managed by a plugin that receives events from RevenueCat server. When a purchase occurs, a renewal process, or a subscription cancels, you get an immediate notification in your IDE. This creates a tight feedback loop during development, you make a test purchase, and within seconds you see the confirmation appear in your IDE.&lt;/p&gt;



&lt;p&gt;This is particularly useful during development and testing. When you’re testing purchase flows with sandbox accounts, you can immediately see whether the transaction went through without checking the dashboard or digging through logs. The notification shows you the event type, the product involved, and relevant details, giving you instant feedback on your implementation.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;browse-and-manage-offerings&quot;&gt;&lt;strong&gt;Browse and manage offerings&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Your offerings define what subscription products are available to your users. The plugin displays your offerings directly in the IDE, showing each offering with its packages, current status, and paywall configuration.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;825&quot; height=&quot;623&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/5.png&quot; alt=&quot;&quot; class=&quot;wp-image-48593&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/5.png 825w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/5-300x227.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/5-768x580.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/5-50x38.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/5-53x40.png 53w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/5-614x464.png 614w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/5-696x526.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/5-560x423.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/5-392x296.png 392w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/5-625x472.png 625w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/5-80x60.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/5-48x36.png 48w&quot; sizes=&quot;auto, (max-width: 825px) 100vw, 825px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Each offering card shows the offering name, the number of packages it contains, and the individual packages with their display names and identifiers. You can quickly scan your product catalog without opening the dashboard. For offerings marked as current, a badge indicates which offering your app serves by default.&lt;/p&gt;



&lt;p&gt;The plugin provides a part of RevenueCat’s paywall functionality. If an offering has a paywall configured, you can click the Paywall button to open the paywall tab of your offering directly in your browser. If an offering doesn’t have a paywall yet, the Add Paywall button creates one for you and opens the paywall builder so you can start customizing immediately.&lt;/p&gt;



&lt;p&gt;The Manage button takes you directly to the offering’s configuration page in the RevenueCat dashboard. This provides quick access when you need to modify packages, update metadata, or configure advanced settings. Instead of navigating through the dashboard hierarchy, you jump straight to the offering you’re working with.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;integration-wizard-easy-sdk-and-paywall-setup&quot;&gt;&lt;strong&gt;Integration wizard: Easy SDK and Paywall setup&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Setting up RevenueCat in a new project involves multiple steps: adding dependencies, configuring the SDK, setting up entitlements, and integrating paywalls. Each platform has its own requirements, and getting the configuration right requires consulting documentation and copying code snippets. The integration wizard guides you through this entire process.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;823&quot; height=&quot;837&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/5-1.png&quot; alt=&quot;&quot; class=&quot;wp-image-48595&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/5-1.png 823w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/5-1-295x300.png 295w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/5-1-768x781.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/5-1-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/5-1-39x40.png 39w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/5-1-456x464.png 456w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/5-1-696x708.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/5-1-551x560.png 551w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/5-1-291x296.png 291w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/5-1-464x472.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/5-1-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/5-1-48x48.png 48w&quot; sizes=&quot;auto, (max-width: 823px) 100vw, 823px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The wizard supports Android, Kotlin Multiplatform, and Flutter projects. It detects your project type and generates the correct dependency configurations with the latest SDK version for your build system, whether that’s Gradle, or pub.yaml. Beyond dependencies, the wizard suggests initialization code tailored to your platform.&lt;/p&gt;



&lt;p&gt;You can choose between SDK-only integration or full paywall integration. The SDK-only option sets up the core RevenueCat functionality for fetching offerings and processing purchases. The paywall integration option adds RevenueCat’s UI components, generating the code to render the paywalls that you can customize in the RevenueCat dashboard.&lt;/p&gt;



&lt;p&gt;The wizard eliminates the friction of initial setup. Instead of spending time on boilerplate configuration, you can focus on building your subscription experience.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;set-milestones-and-monitor-progress&quot;&gt;&lt;strong&gt;Set milestones and monitor progress&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Building a subscription business is a long-term endeavor. Having concrete goals to work toward helps maintain momentum during development. The plugin lets you define revenue and subscriber milestones to track your app’s growth.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;832&quot; height=&quot;315&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/4-1.png&quot; alt=&quot;&quot; class=&quot;wp-image-48597&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/4-1.png 832w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/4-1-300x114.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/4-1-768x291.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/4-1-50x19.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/4-1-106x40.png 106w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/4-1-696x264.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/4-1-560x212.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/4-1-80x30.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/4-1-48x18.png 48w&quot; sizes=&quot;auto, (max-width: 832px) 100vw, 832px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;You can set targets for MRR, active subscriptions, active trials, new customers, or total revenue. The plugin monitors your progress against these milestones and displays your current standing. When you hit a milestone, the plugin celebrates with you, providing a moment of recognition for your progress.&lt;/p&gt;



&lt;p&gt;This feature transforms abstract business goals into tangible targets visible in your development environment. When you’re deep in implementation work, seeing that you’re 80% of the way to your next subscriber milestone provides motivation to push through. It connects the code you’re writing to the business outcomes you’re working toward.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;stay-up-to-date-with-sdk-releases&quot;&gt;&lt;strong&gt;Stay up to date with SDK releases&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;RevenueCat’s SDKs are actively developed, with regular releases that include bug fixes, new features, and performance improvements. Staying current with SDK versions ensures you have access to the latest capabilities and fixes, but manually checking GitHub for new releases is tedious.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;839&quot; height=&quot;603&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-10-at-10.54.36-AM.png&quot; alt=&quot;&quot; class=&quot;wp-image-48666&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-10-at-10.54.36-AM.png 839w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-10-at-10.54.36-AM-300x216.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-10-at-10.54.36-AM-768x552.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-10-at-10.54.36-AM-50x36.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-10-at-10.54.36-AM-56x40.png 56w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-10-at-10.54.36-AM-646x464.png 646w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-10-at-10.54.36-AM-696x500.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-10-at-10.54.36-AM-560x402.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-10-at-10.54.36-AM-412x296.png 412w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-10-at-10.54.36-AM-657x472.png 657w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-10-at-10.54.36-AM-80x57.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-10-at-10.54.36-AM-48x34.png 48w&quot; sizes=&quot;auto, (max-width: 839px) 100vw, 839px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The plugin fetches release notes from RevenueCat’s GitHub repositories and displays them in a dedicated dialog. You can view the latest releases for Android, iOS, Kotlin Multiplatform, Flutter, and React Native SDKs. Each release shows the version number, publication date, and full release notes, so you can quickly assess whether an update is relevant to your project.&lt;/p&gt;



&lt;p&gt;More importantly, you can enable notifications to get alerted when new SDK versions are released. When a new version drops, you’ll see a notification in your IDE with the version number and a link to the full release notes. This helps you stay current with bug fixes, new features, and breaking changes without manually checking GitHub or subscribing to release notifications.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;553&quot; height=&quot;161&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-05-at-11.10.58-AM.png&quot; alt=&quot;&quot; class=&quot;wp-image-48601&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-05-at-11.10.58-AM.png 553w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-05-at-11.10.58-AM-300x87.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-05-at-11.10.58-AM-50x15.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-05-at-11.10.58-AM-125x36.png 125w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-05-at-11.10.58-AM-80x23.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-05-at-11.10.58-AM-48x14.png 48w&quot; sizes=&quot;auto, (max-width: 553px) 100vw, 553px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The notification system is opt-in on a per-platform basis. If you’re only building Android apps, you can enable notifications just for the Android SDK. If you’re building cross-platform, you can enable notifications for multiple SDKs.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;browse-blog-posts-and-get-notified&quot;&gt;&lt;strong&gt;Browse blog posts and get notified&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The RevenueCat blog publishes articles about new features, engineering insights, best practices, and mobile subscription industry trends. Staying informed about these updates helps you make better decisions about your subscription implementation.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;784&quot; height=&quot;593&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-08-at-8.36.29-AM.png&quot; alt=&quot;&quot; class=&quot;wp-image-48603&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-08-at-8.36.29-AM.png 784w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-08-at-8.36.29-AM-300x227.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-08-at-8.36.29-AM-768x581.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-08-at-8.36.29-AM-50x38.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-08-at-8.36.29-AM-53x40.png 53w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-08-at-8.36.29-AM-613x464.png 613w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-08-at-8.36.29-AM-696x526.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-08-at-8.36.29-AM-560x424.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-08-at-8.36.29-AM-391x296.png 391w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-08-at-8.36.29-AM-624x472.png 624w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-08-at-8.36.29-AM-80x61.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-08-at-8.36.29-AM-48x36.png 48w&quot; sizes=&quot;auto, (max-width: 784px) 100vw, 784px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The plugin fetches recent articles from the RevenueCat blog and displays them in a browsable list. Each article shows the title, publication date, and a brief description. Clicking an article opens it in your browser, letting you read the full content when you’re ready.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;606&quot; height=&quot;175&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-10-at-10.48.32-AM.png&quot; alt=&quot;&quot; class=&quot;wp-image-48664&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-10-at-10.48.32-AM.png 606w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-10-at-10.48.32-AM-300x87.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-10-at-10.48.32-AM-50x14.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-10-at-10.48.32-AM-125x36.png 125w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-10-at-10.48.32-AM-560x162.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-10-at-10.48.32-AM-80x23.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Screenshot-2025-12-10-at-10.48.32-AM-48x14.png 48w&quot; sizes=&quot;auto, (max-width: 606px) 100vw, 606px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;You can enable notifications to get alerted when new articles are published. This keeps you informed about RevenueCat updates, new SDK features, and industry insights without manually checking the blog. When a new article is published, you’ll see a notification in your IDE with the title and a link to read more.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;conclusion&quot;&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The RevenueCat IntelliJ plugin brings subscription management more convenient directly into your IDE. Instead of context switching between your IDE, the RevenueCat dashboard, GitHub, and the blog, you can access everything from a single tool window. Track metrics while you code, receive instant notification on purchases, set up new projects with the integration wizard, monitor your progress toward business goals, stay current with SDK releases, and keep up with the latest articles.&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Web-to-app funnels: the complete 2026 guide]]></title><description><![CDATA[Benefits, pitfalls, and a blueprint to launch your first funnel]]></description><link>https://www.revenuecat.com/blog/growth/web-to-app-funnels/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/web-to-app-funnels/</guid><pubDate>Thu, 11 Dec 2025 14:00:00 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Complete-guide-to-web-to-app-funnels-1.png" length="0" type="image/*"/><content:encoded>&lt;div class=&quot;lazyblock-e525b3a3ae6c-Z1Bepg0 wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Build no-code web funnels in RevenueCat&quot; text=&quot;&lt;p&gt;Unlock the flexibility and profit of web-to-app with our new funnel builder: create custom onboarding, surveys, and checkout flows in an instant. Free and included in your regular plan. &lt;a href=&amp;quot;https://www.revenuecat.com/feature/funnels&amp;quot;&gt;Learn more&lt;/a&gt;.&lt;/p&gt;&quot; icon=&quot;star&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;p&gt;Web-to-app funnels are having a moment — but they’re a lot more complex than &lt;em&gt;send traffic to a landing page and profit&lt;/em&gt;. In this guide, we’ll break down when web-to-app actually makes sense, the benefits and disadvantages, how to design and test your first funnel, common questions, and what the future holds for web-to-app.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Personally, I love web-to-app because it blends the best of both worlds I work in: e-commerce and apps. You get the &lt;strong&gt;storytelling, experimentation, and control of a web funnel&lt;/strong&gt;, with the &lt;strong&gt;retention and lifetime value power of an app&lt;/strong&gt;. When it’s done right, it feels like the perfect growth setup. However, it does come with its challenges. I’m excited to guide you through it all.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-is-a-web-to-app-funnel&quot;&gt;What is a web-to-app funnel?&lt;/h2&gt;



&lt;p&gt;Web-to-app funnels (sometimes written as web2app) do exactly what they sound like: &lt;strong&gt;they start on the web and drive users into your app&lt;/strong&gt;. That might mean someone signs up or pays on the web before downloading the app (technically called web-to-web), or sometimes the payment happens after they install the app (web-to-app).&lt;/p&gt;



&lt;p&gt;In practice, most people just call it all “web-to-app”. And honestly, that’s fair, both approaches bridge the gap between web &amp;lt;&amp;gt; app. Here we’ll focus mainly on web-to-web funnels, as they differ most from in-app-only funnels.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;benefits-of-using-web-to-app&quot;&gt;Benefits of using web-to-app&lt;/h2&gt;



&lt;p&gt;Web funnels aren’t new — they’ve been popular for years, particularly in the health and fitness space — but their adoption has surged recently. Many believe funnels improve attribution and reduce costs, but of course there are &lt;a href=&quot;https://www.revenuecat.com/blog/growth/the-pros-and-cons-of-web-to-app-funnels/&quot;&gt;pros and cons to web-to-app funnels&lt;/a&gt;. Let’s look at both sides.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;1-cost-savings-debatable&quot;&gt;1. Cost savings (debatable)&lt;/h3&gt;



&lt;p&gt;The first reason people often consider web-to-app is cost savings. But like I said, it’s not that simple — &lt;a href=&quot;https://www.revenuecat.com/blog/growth/publishers-guide-app-store-fees-guidelines-compliance/&quot;&gt;Apple and Google take 15%–30% in fees&lt;/a&gt;; that’s a &lt;em&gt;big&lt;/em&gt; cut. By comparison, web payments usually cost far less (around 2%–3%, though when blended across all fees, more like 6%).&amp;nbsp;&lt;/p&gt;



&lt;p&gt;It’s natural to think web-to-app can save money, but it’s important to note that lower fees alone shouldn’t be the sole reason to switch.&lt;/p&gt;



&lt;p&gt;As &lt;a href=&quot;https://www.linkedin.com/in/thomasbcn/&quot;&gt;Thomas Petit&lt;/a&gt;, App Growth Consultant, explains on the &lt;a href=&quot;https://www.revenuecat.com/blog/growth/thomas-petit-sub-club-podcast-2024-web-to-app/&quot;&gt;&lt;em&gt;Sub Club&lt;/em&gt; podcast&lt;/a&gt;, “People are going web-to-app for the wrong reason.” Setting up a web-to-app funnel takes time and effort. Testing a completely new flow can reveal that what works in-app doesn’t always work on the web, and conversion rates may even be lower. This can increase your &lt;a href=&quot;https://www.revenuecat.com/glossary/#customer-acquisition-cost-cac&quot;&gt;customer acquisition cost (CAC)&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;The real benefit isn’t always reduced costs; it’s the &lt;em&gt;potential&lt;/em&gt; for higher &lt;a href=&quot;https://www.revenuecat.com/glossary/#lifetime-value-ltv&quot;&gt;lifetime value (LTV) &lt;/a&gt;per user. Even if your overall costs don’t drop, the value each user brings can increase.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;2-improved-retention-and-ltv&quot;&gt;2. Improved retention and LTV&lt;/h3&gt;



&lt;p&gt;Data shows that web subscribers tend to renew at higher rates than App Store or Google Play users, which generally leads to better retention and higher lifetime value. One reason is friction: on a phone, all subscriptions are in one place, making it easy for users to cancel multiple services at once, &lt;a href=&quot;https://www.revenuecat.com/blog/growth/how-to-tackle-new-year-subscription-churn/&quot;&gt;a trend we often see in January&lt;/a&gt;. Another factor is that web subscriptions often skew toward higher-end offerings.&lt;/p&gt;



&lt;p&gt;Web users may also be more accustomed to paying higher prices, making them comfortable spending more on your app as well.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;623&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-24-1024x623.png&quot; alt=&quot;&quot; class=&quot;wp-image-48458&quot; style=&quot;width:800px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-24-1024x623.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-24-300x183.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-24-768x467.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-24-1536x934.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-24-50x30.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-24-66x40.png 66w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-24-696x423.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-24-560x341.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-24-487x296.png 487w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-24-776x472.png 776w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-24-80x49.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-24-48x29.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-24.png 1578w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Source: &lt;/em&gt;&lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps-2025/&quot;&gt;&lt;em&gt;State of Subscription Apps&lt;/em&gt; report 2025&lt;/a&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;3-simplified-tracking-and-attribution&quot;&gt;3. Simplified tracking and attribution&lt;/h3&gt;



&lt;p&gt;In 2021, Apple introduced the App Tracking Transparency (ATT) policy, which also resulted in the app world rethinking web-to-app. On the web, tracking is simpler, giving campaigns more data and a better feedback loop.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;While web-to-app tracking isn’t perfect (for example, feeding purchase data to Meta seven days later can be tricky), it generally provides better insights into subscriber behavior, helping improve campaign performance, e.g. easily seeing how different acquisition sources impact retention and LTV.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;4-monetization-freedom&quot;&gt;4. Monetization freedom&lt;/h3&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/2025-app-monetization-trends/&quot;&gt;Money-back guarantees&lt;/a&gt;? Go for it. &lt;a href=&quot;https://www.revenuecat.com/blog/growth/lifetime-subscriptions/&quot;&gt;Lifetime subscription&lt;/a&gt; offers? Bundles? Upsells? Multiple pricing tests? Go absolutely &lt;em&gt;wild&lt;/em&gt;.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Over time, app stores have enforced stricter monetization rules and, as above, tracking. The web, however, is pretty much a free-for-all. You can experiment freely without worrying about app store constraints. Please note this is in no way an encouragement to follow &lt;a href=&quot;https://www.revenuecat.com/blog/growth/black-hat-aso-app-store-optimization/&quot;&gt;dark UX patterns&lt;/a&gt; or test a million things at once — regardless of the channel, you should follow best practices and respect &lt;a href=&quot;https://www.revenuecat.com/blog/growth/is-monetization-hurting-your-apps-user-experience/&quot;&gt;ethical monetization&lt;/a&gt; and UX. But this is one reason some folks favour web-to-app.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;5-quicker-testing-for-multiple-funnels&quot;&gt;5. Quicker testing for multiple funnels&lt;/h3&gt;



&lt;p&gt;The rise in popularity of web-to-app has also driven the growth of no-code web app builders, making it easy for non-developers to build funnels quickly. Maybe not quite as fast as a paywall can be built in RevenueCat (&lt;em&gt;fast&lt;/em&gt;, less than four minutes! See the &lt;a href=&quot;https://www.youtube.com/watch?v=bcnUYWLo-I4&quot;&gt;speed-building championship&lt;/a&gt;), but still speedy work.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Early-stage startups even use Typeform surveys or simple landing pages as their first web-to-app funnels.&lt;/p&gt;



&lt;p&gt;If you’re pre-launch, the joy of having the conversion on the web means you can use it to test &lt;a href=&quot;https://www.revenuecat.com/blog/growth/web-to-app-paid-user-acquisition/&quot;&gt;messaging, pricing, and positioning early on&lt;/a&gt;. As &lt;a href=&quot;https://www.linkedin.com/in/marcusburke/&quot;&gt;Marcus Burke&lt;/a&gt;, Meta Ads &amp;amp; App Growth Consultant, puts it: “You’re not moving to the web to save a 30% store fee. You’re moving to the web as it allows you to differentiate yourself, learn fast, and empower marketing, no matter what your product roadmap looks like.”&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;6-faster-cash-flow&quot;&gt;6. Faster cash flow&amp;nbsp;&lt;/h3&gt;



&lt;p&gt;In-app, when you get a new subscriber, great! Oh, wait, please hold up to &lt;a href=&quot;https://www.revenuecat.com/blog/growth/understanding-app-store-payments-and-revenue-reporting/&quot;&gt;68 days for the App Store to pay you&lt;/a&gt;. Thanks a lot, App Store, that’s a &lt;em&gt;long&lt;/em&gt; time for a &lt;a href=&quot;https://www.revenuecat.com/blog/growth/mobile-app-funding/&quot;&gt;cash-strapped startup&lt;/a&gt;.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;While there are solutions (for example, &lt;a href=&quot;https://www.youtube.com/watch?v=EVR7Crrm0_w&quot;&gt;RevenueCat is launching RC Capital&lt;/a&gt; to provide next-day payouts for App Store payout profits), web payments often result in immediate, or very quick, payouts by comparison to app stores.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;7-content-led-discovery&quot;&gt;7. Content-led discovery&lt;/h3&gt;



&lt;p&gt;As Thomas points out, web-to-app can also be a powerful tool for discovery: larger apps can use web-led content to attract new users. For example, Photoroom offers free web tools that drive awareness and funnel users into their app, creating a content-led growth strategy.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;698&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-25-1024x698.png&quot; alt=&quot;&quot; class=&quot;wp-image-48460&quot; style=&quot;width:800px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-25-1024x698.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-25-300x205.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-25-768x524.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-25-1536x1047.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-25-50x34.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-25-59x40.png 59w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-25-680x464.png 680w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-25-696x475.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-25-560x382.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-25-434x296.png 434w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-25-692x472.png 692w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-25-80x55.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-25-48x33.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-25.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;disadvantages-of-web-to-app&quot;&gt;Disadvantages of web-to-app&lt;/h2&gt;



&lt;p&gt;Before you start building your web-to-app funnel (and attempt to beat that paywall speed-building record), there are some important downsides to keep in mind.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Apps often underestimate how much they’ll need to change or set up for the web. We’ve touched on additional costs and time for testing, but there are a few other factors to consider:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;1-free-trials-dont-work-as-well-on-the-web&quot;&gt;1. Free trials don’t work as well on the web&lt;/h3&gt;



&lt;p&gt;If your main strategy relies on free trials or a freemium model, it may not translate smoothly online. Web users often enter card details for cards with no balance, so you may need an alternative setup, like a low-cost trial (e.g. $1) or a money-back guarantee.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;This can mean fewer free users entering your app, and makes comparing web versus app performance more complicated.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;2-impact-on-organic-rankings-and-traffic&quot;&gt;2. Impact on organic rankings and traffic&lt;/h3&gt;



&lt;p&gt;Many web-to-app funnels convert users directly on the web, which can reduce app installs, ratings, and reviews. In contrast, in-app campaigns drive traffic to app stores, even if users don’t convert immediately.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Fewer installs, ratings, and reviews may hurt your app store ranking and limit organic growth. &lt;a href=&quot;https://www.linkedin.com/in/nathan--hudson/&quot;&gt;Nathan Hudson&lt;/a&gt;, Founder of &lt;a href=&quot;https://www.perceptycs.com/&quot;&gt;Perceptycs&lt;/a&gt;, explains the &lt;a href=&quot;https://www.revenuecat.com/blog/growth/the-pros-and-cons-of-web-to-app-funnels/&quot;&gt;downsides&lt;/a&gt; of this as:&lt;/p&gt;



&lt;p&gt;“This can also hurt apps scaling paid acquisition who will need support from ASO to continue scaling with their target ROAS. Stronger rankings mean a higher volume of organic installs, which can drastically lower your blended acquisition cost.”&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;3-financial-and-legal-complexities&quot;&gt;3. Financial and legal complexities&lt;/h3&gt;



&lt;p&gt;We all cry about the greediness of the app stores charging such high fees, but the reality is they’re actually doing a lot of &lt;a href=&quot;https://www.revenuecat.com/blog/growth/understanding-app-store-payments-and-revenue-reporting/&quot;&gt;heavy lifting for us&lt;/a&gt;: handling different tax laws, chargebacks, and more.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;On the web, you’ll need to handle this yourself. If your app is international, this gets even more complex. While there are solutions for this, like using a Merchant of Records (e.g. &lt;a href=&quot;https://www.paddle.com/&quot;&gt;Paddle&lt;/a&gt;), it’s an additional cost and layer of complexity to the operation.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;4-messier-attribution&quot;&gt;4. Messier attribution&amp;nbsp;&lt;/h3&gt;



&lt;p&gt;Running multiple funnels across web &lt;em&gt;and &lt;/em&gt;app introduces complexity in tracking and attribution.&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;App campaigns&lt;/strong&gt; rely on SKAN or aggregated install data&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Web campaigns&lt;/strong&gt; use pixels and server-to-server tracking&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;If you’re testing both, it can get pretty messy. You risk having more users, which is great, but not being able to tell where they came from or assign them to the right funnel — making it harder to recreate success (or fix failure). You can improve this by ensuring you consistently tag users across web and app, as well as bringing together the data into a single source of truth.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;key-differences-between-web-to-app-and-in-app-purchases&quot;&gt;Key differences between web-to-app and in-app purchases&lt;/h2&gt;



&lt;p&gt;So it’s clear that web-to-app and in-app purchases operate very differently. While web-to-app offers significant benefits, it’s not something you can whip up to test quickly. Web funnels come with added complexities, as &lt;a href=&quot;https://www.linkedin.com/in/gessicabicego/&quot;&gt;Gessica Bicego&lt;/a&gt;, Marketing &amp;amp; Growth Consultant, &lt;a href=&quot;https://www.youtube.com/watch?v=xmEoGuUKnfo&quot;&gt;explained in her workshop&lt;/a&gt; at&lt;a href=&quot;https://www.revenuecat.com/blog/company/lessons-from-app-growth-annual-2025/&quot;&gt; App Growth Annual 2025&lt;/a&gt;:&lt;/p&gt;



&lt;p&gt;“Web funnels may look simple, but several technical layers add complexity.”&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;An MMP helps manage deep linking and accurate attribution&lt;/li&gt;



&lt;li&gt;A CRM tool is essential to capture and activate the emails you collect&lt;/li&gt;



&lt;li&gt;You’ll need a payment processor that handles global taxes&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Expect a high failed payment rate (around 50%), but tools and retries can significantly improve acceptance&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Here’s a roundup of everything you need to know the differences between web-to-app and in-app purchases.&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Area&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Web-to-app&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;In-app purchases&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Fees &amp;amp; margins&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Lower processor fees&lt;/strong&gt; (around 2–3% up to 6% including all costs) but higher build + maintenance effort. Savings aren’t guaranteed once conversion drop-offs are factored in.&lt;/td&gt;&lt;td&gt;&lt;strong&gt;15–30% store fee&lt;/strong&gt;, but stores handle tax, refunds, billing errors, fraud, and global payment methods.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Conversion rates&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Typically &lt;strong&gt;lower initial conversion&lt;/strong&gt; due to browser handoff friction. Free trials often underperform without tweaks (e.g. $1 trials, money-back).&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Smooth, trusted&lt;/strong&gt;, one-tap purchase results in the highest trial start and paid conversion rates.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Retention &amp;amp; LTV&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Users who push through friction tend to be &lt;strong&gt;stickier&lt;/strong&gt; and renew more (potentially higher LTV).&lt;/td&gt;&lt;td&gt;Large volume, but generally &lt;strong&gt;slightly lower&lt;/strong&gt; renewal rates.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Attribution &amp;amp; signal quality&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;More granular&lt;/strong&gt; tracking and faster feedback loops. Better for creative testing and channel optimization.&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Limited by ATT/SKAN&lt;/strong&gt;, delayed + aggregated signals, harder learning cycles.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Pricing &amp;amp; monetization freedom&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Full flexibility&lt;/strong&gt;: lifetime deals, bundles, upsells, guarantees, etc. Great for experimentation.&lt;/td&gt;&lt;td&gt;Must comply with App Store rules, &lt;strong&gt;less pricing and UX flexibility&lt;/strong&gt;.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Cash flow&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Fast payouts&lt;/strong&gt;, useful for cash-constrained teams scaling paid UA.&lt;/td&gt;&lt;td&gt;&lt;strong&gt;45–60 day payouts&lt;/strong&gt; (unless using financing products).&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;User acquisition&amp;nbsp;&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Mainly Meta&lt;/strong&gt;, but it also opens up new audiences and potential channels.&amp;nbsp;&amp;nbsp;&lt;/td&gt;&lt;td&gt;Additional campaign &lt;strong&gt;types/channels unavailable to web&lt;/strong&gt;, e.g. ASO, Apple Search Ads.&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Operational complexity&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;High&lt;/strong&gt;: own billing stack, compliance with tax laws, fraud management, supporting failed payments, CRM activation.&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Low&lt;/strong&gt;: app stores handle payments, taxes, and global compliance.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Impact on ASO &amp;amp; organic search&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Fewer users hit store pages, &lt;strong&gt;rankings can drop&lt;/strong&gt; if too much spend shifts to the web.&lt;/td&gt;&lt;td&gt;Drives &lt;strong&gt;ratings, reviews, and traffic&lt;/strong&gt; that boost discoverability.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Experimentation Speed&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Marketers can build/test funnels &lt;strong&gt;without waiting for app releases&lt;/strong&gt;.&lt;/td&gt;&lt;td&gt;&lt;strong&gt;More dev-dependent; &lt;/strong&gt;shipping updates slows testing velocity.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Attribution Across Channels&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Hybrid setups introduce attribution &lt;strong&gt;complexity&lt;/strong&gt; across multiple funnels.&lt;/td&gt;&lt;td&gt;Single source simplifies measurement, but SKAN / ATT still impacts measurement.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;who-should-test-web-to-app-funnels&quot;&gt;Who should test web-to-app funnels?&lt;/h2&gt;



&lt;p&gt;There isn’t one type of app that should test web-to-app; it’s relevant at different stages and for different apps, depending on their category and audience. If you’re wondering ‘should we give it a go?’, these are some of the main groups that should consider testing web-to-app:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;1-early-stage-startups&quot;&gt;1. Early-stage startups&lt;/h3&gt;



&lt;p&gt;For early-stage startups, web-to-app can be a great way to test your initial funnel and iterate quickly while experimenting with paid acquisition.&lt;/p&gt;



&lt;p&gt;That said, it’s best to avoid testing both in-app and web-to-app simultaneously — especially if you’re a small or bootstrapped team — as it can spread your focus too thin. Once you reach a later stage, running both can make sense.&lt;/p&gt;



&lt;p&gt;The exception is if you’ve already started with in-app but discover that web is a better fit; in that case, it’s smart to shift your full focus and energy to the web funnel.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;2-apps-looking-to-expand-their-paid-reach&quot;&gt;2. Apps looking to expand their paid reach&lt;/h3&gt;



&lt;p&gt;Paid optimization looks very different for app campaigns compared to web campaigns. By focusing on web, you can unlock an entirely new audience you may not have reached before.&lt;/p&gt;



&lt;p&gt;It’s often suggested that there’s only about &lt;a href=&quot;https://www.businessofapps.com/insights/winning-web-revenue-in-the-evolving-app-landscape/&quot;&gt;15% overlap between app and web audiences&lt;/a&gt; on Meta, meaning a web campaign can open the door to a whole new audience. Weirdly enough, despite the 100s of apps I download (it’s for work, I promise!) I rarely see an app campaign on Meta, so I’m definitely in that web audience bucket.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;3-apps-looking-to-improve-profitability&quot;&gt;3. Apps looking to improve profitability&lt;/h3&gt;



&lt;p&gt;While skipping app store fees can help, the real profitability boost from web-to-app usually comes from higher lifetime value and better retention. By building stronger relationships with web subscribers who tend to stick around longer, apps can meaningfully improve long-term profitability.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;4-apps-focusing-on-older-audiences&quot;&gt;4. Apps focusing on older audiences&lt;/h3&gt;



&lt;p&gt;Older audiences are generally more comfortable with web-based flows, while younger users (like Gen Z) tend to prefer native app experiences. That doesn’t mean web-to-app can’t work for younger audiences, it just tends to perform better with slightly older demographics who are used to purchasing and subscribing through the web.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;5-certain-categories-skew-more-to-web-to-app&quot;&gt;5. Certain categories skew more to web-to-app&lt;/h3&gt;



&lt;p&gt;Web-to-app first gained traction in health and fitness, as well as business apps, but the landscape is shifting. According to the &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps-2025/&quot;&gt;&lt;em&gt;State Of Subscription Apps&lt;/em&gt; report 2025&lt;/a&gt;, Health &amp;amp; Fitness is now one of the slower-growing web categories. Instead, we’re seeing strong growth across &lt;strong&gt;productivity&lt;/strong&gt;, &lt;strong&gt;utility&lt;/strong&gt;, and &lt;strong&gt;education&lt;/strong&gt; apps as more of these verticals adopt web-first funnels.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;771&quot; height=&quot;475&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image1-1.png&quot; alt=&quot;&quot; class=&quot;wp-image-48466&quot; style=&quot;width:800px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image1-1.png 771w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image1-1-300x185.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image1-1-768x473.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image1-1-50x31.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image1-1-65x40.png 65w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image1-1-696x429.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image1-1-560x345.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image1-1-480x296.png 480w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image1-1-766x472.png 766w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image1-1-80x49.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image1-1-48x30.png 48w&quot; sizes=&quot;auto, (max-width: 771px) 100vw, 771px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;We’re also seeing more Lifestyle, Entertainment, and Finance apps adopting web-to-app funnels. Ultimately, it’s less about the category itself and more about what you need to communicate to convince users to try your app.&lt;/p&gt;



&lt;p&gt;As Gessica highlights, apps that perform best with web funnels often share these traits:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Your product needs &lt;strong&gt;more explanation&lt;/strong&gt; (not easy to convey in a few lines or visuals)&lt;/li&gt;



&lt;li&gt;The experience relies on &lt;a href=&quot;https://www.revenuecat.com/blog/growth/solve-app-problems-emotionally/&quot;&gt;&lt;strong&gt;emotional triggers&lt;/strong&gt;&lt;/a&gt; that can be unlocked through questions or storytelling&lt;/li&gt;



&lt;li&gt;You can offer &lt;strong&gt;immediate value &lt;/strong&gt;during onboarding (e.g. quiz results, personalized plan, free tool)&lt;/li&gt;



&lt;li&gt;Web onboarding helps &lt;strong&gt;educate, engage,&lt;/strong&gt; and &lt;strong&gt;prequalify&lt;/strong&gt; users before driving them to purchase.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;So, category is the least important factor; it’s really about &lt;strong&gt;what your app needs to convey&lt;/strong&gt; to convert users effectively.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;6-b2b-brands-where-employers-pay&quot;&gt;6. B2B brands where employers pay&lt;/h3&gt;



&lt;p&gt;As someone who’s always been deep in B2C, I hadn’t initially considered this use case, but as Thomas explained on &lt;a href=&quot;https://www.youtube.com/@SubClubPodcast&quot;&gt;Sub Club&lt;/a&gt;, web-to-app can be especially valuable for B2B brands.&lt;/p&gt;



&lt;p&gt;App stores bill directly to an individual’s card, which isn’t ideal for company-paid subscriptions. The web, on the other hand, allows employers to easily manage team billing, set up company-wide subscriptions, and streamline payment processes, all of which make B2B purchases far smoother.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;testing-and-measuring-the-success-of-web-to-app-free-blueprint&quot;&gt;Testing and measuring the success of web-to-app: free blueprint&lt;/h2&gt;



&lt;p&gt;As we’ve covered, web-to-app funnels come with added complexity, so take your time and set them up correctly. A common recommendation is to start with a funnel that mirrors your existing in-app flow; this helps speed up setup and minimize differences when comparing results.&lt;/p&gt;



&lt;p&gt;That said, don’t just default to a quiz funnel. While quizzes are popular, they’re far from the only option.&lt;/p&gt;



&lt;p&gt;To give you a hand, here’s my &lt;strong&gt;blueprint to building your first web-to-app funnel.&lt;/strong&gt;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;1-determine-your-success-metrics-and-test-plan&quot;&gt;1. Determine your success metrics and test plan&lt;/h3&gt;



&lt;p&gt;When &lt;a href=&quot;https://www.revenuecat.com/blog/growth/iap-vs-web-purchases-conversion-test/&quot;&gt;testing web-to-app vs. in-app purchases&lt;/a&gt;, looking only at conversion rates or CACs can be misleading. It takes time to optimize web conversion rates and build a system that smoothly drives users from the web to the app.&lt;/p&gt;



&lt;p&gt;You may see higher &lt;a href=&quot;https://www.revenuecat.com/glossary/#trial-conversion-rate&quot;&gt;trial-to-paid conversions&lt;/a&gt;, but other metrics may initially drop. Instead of focusing on short-term numbers, analyze &lt;a href=&quot;https://www.revenuecat.com/glossary/#arpu-average-revenue-per-user&quot;&gt;average revenue per paying user (ARPU)&lt;/a&gt; and your &lt;a href=&quot;https://www.revenuecat.com/glossary/#ltv-cac-ratio&quot;&gt;LTV-to-CAC ratio&lt;/a&gt;, factoring in the extra costs of running a web funnel.&amp;nbsp;&lt;br&gt;For most apps, it’s not an either/or decision. The key question is &lt;strong&gt;whether web-to-app helps you reach a new audience profitably&lt;/strong&gt;. Define how long you’ll test (typically three–six months to get meaningful retention data) and what specific approaches you’ll try, to avoid never-ending tests.&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-2esXaf wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Remember&quot; text=&quot;&lt;p&gt;&lt;span style=&amp;quot;font-weight: 400;&amp;quot;&gt;Costs and performance benchmarks differ between web and app environments, making direct comparisons tricky.&lt;/span&gt;&lt;/p&gt;&quot; icon=&quot;bulb&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;2-work-out-your-web-to-app-setup&quot;&gt;2. Work out your web-to-app setup&lt;/h3&gt;



&lt;p&gt;Often, many people equate web-to-app with onboarding quiz funnels. While it’s a classic approach, it’s just one of many options — and &lt;a href=&quot;https://www.revenuecat.com/blog/growth/web-to-app-funnels-are-not-onboarding-quizzes/&quot;&gt;your web-to-app funnel shouldn’t be a replacement for onboarding&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;When testing, consider alternative flows such as:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Landing page → Checkout&lt;/li&gt;



&lt;li&gt;Landing page → Sign-up → Install&lt;/li&gt;



&lt;li&gt;Smart banners (AppsFlyer, Adjust, etc.)&lt;/li&gt;



&lt;li&gt;QR codes → App Install&lt;/li&gt;



&lt;li&gt;Email sequence → Web Paywall → Checkout&lt;/li&gt;



&lt;li&gt;Lead magnet → App install&lt;/li&gt;



&lt;li&gt;Blog post → Install&lt;/li&gt;



&lt;li&gt;Webinar funnel → Checkout&lt;/li&gt;



&lt;li&gt;Landing page → Web app demo → Checkout&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;That is not to hate on quizzes — they’re great for personalization, education, and more complex journeys, but they aren’t the only way. As Nathan puts it:&lt;/p&gt;



&lt;p&gt;“Don’t just copy what everyone else is doing — think through what makes sense for your product. What are your unique selling points? What are your customers’ pain points? How can you best highlight and address those on the web before they even download your app? It might not be a web onboarding quiz.”&lt;/p&gt;



&lt;p&gt;A simple starting point? Gessica shared that using a mini landing page can be an ideal first test to validate your web-to-app funnel before adding complexity.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;771&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-27-1024x771.png&quot; alt=&quot;&quot; class=&quot;wp-image-48464&quot; style=&quot;width:800px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-27-1024x771.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-27-300x226.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-27-768x578.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-27-50x38.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-27-53x40.png 53w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-27-616x464.png 616w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-27-696x524.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-27-560x422.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-27-393x296.png 393w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-27-627x472.png 627w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-27-80x60.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-27-48x36.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-27.png 1118w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;em&gt;Credit: Gessica Bicego&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;What’s great about Gessica’s example is that it mitigates some of the risks of a pure web funnel, particularly around payment setup, but it doesn’t unlock web campaigns on Meta, since payments still occur in the app.&lt;/p&gt;



&lt;p&gt;For building landing pages and web quizzes, there are plenty of no-code tools available to help get started: Unbounce, ConvertKit, Web2Wave, and more.&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-Z1nyPyK wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Create web-to-app funnels in RevenueCat&quot; text=&quot;&lt;p&gt;With RevenueCat Funnels, you can build no-code custom onboarding, surveys, and checkout flows that unlock seamless in-app access. &lt;a class=&amp;quot;notion-link-token notion-focusable-token notion-enable-hover&amp;quot; tabindex=&amp;quot;0&amp;quot; href=&amp;quot;https://www.revenuecat.com/feature/funnels/&amp;quot; rel=&amp;quot;noopener noreferrer&amp;quot; data-token-index=&amp;quot;1&amp;quot;&gt;&lt;span class=&amp;quot;link-annotation-unknown-block-id--717331513&amp;quot;&gt;Learn more&lt;/span&gt;&lt;/a&gt;&lt;span class=&amp;quot;link-annotation-unknown-block-id--717331513&amp;quot;&gt; ↗️&lt;/span&gt;&lt;!-- notionvc: 8ff03936-e607-4e73-895d-f9b30c634e17 --&gt;&lt;/p&gt;&quot; icon=&quot;bulb&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;3-determine-the-offer-structure&quot;&gt;3. Determine the offer structure&lt;/h3&gt;



&lt;p&gt;Most apps rely on hard paywalls, free trials, freemium, or some hybrid, but the offer structure often needs to change for web-to-app funnels. This is because:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Free trials convert worse on the web due to fraud and lower-intent users&lt;/li&gt;



&lt;li&gt;Web checkout friction means users expect a clear, immediate benefit&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Instead, we often see:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Paid trials (e.g. seven days for $1)&lt;/li&gt;



&lt;li&gt;Money-back guarantees (effective for content or service apps)&lt;/li&gt;



&lt;li&gt;Web-exclusive savings (passing fee savings on to users)&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;You can also simplify plan choices for web users:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Lead with a single annual plan for clarity and higher LTV&lt;/li&gt;



&lt;li&gt;Keep monthly pricing in-app to encourage the correct behavior&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;I really like the example of &lt;a href=&quot;https://myplantin.com/&quot;&gt;Plantin&lt;/a&gt;, a plant-identifying app. They highlight that the best deal is on web and offer a free trial (but keep it very short) which strikes the right balance between incentivizing users and reducing friction. That 30% off, because it is via the website, makes you feel like you’ve found a special deal.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;472&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-26-472x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-48462&quot; style=&quot;width:400px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-26-472x1024.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-26-138x300.png 138w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-26-708x1536.png 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-26-23x50.png 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-26-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-26-214x464.png 214w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-26-696x1509.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-26-258x560.png 258w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-26-137x296.png 137w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-26-218x472.png 218w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-26-37x80.png 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-26-22x48.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-26.png 738w&quot; sizes=&quot;auto, (max-width: 472px) 100vw, 472px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Over time, as you optimize, you’ll start to match offer structure to traffic intent and channel. For example, high-intent users may respond well to annual savings, while cold audiences may need a low-risk entry point or more explanation of how the money-back guarantee works.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;4-improve-your-initial-funnel&quot;&gt;4. Improve your initial funnel&lt;/h3&gt;



&lt;p&gt;In most cases, you’ll probably want to start by focusing on &lt;a href=&quot;https://www.revenuecat.com/blog/growth/subscription-app-creative-testing/&quot;&gt;optimizing your creatives&lt;/a&gt;. Especially if you’re running web campaigns for the first time, you’re reaching a new audience, and your creatives will impact the quality of users you attract.&lt;/p&gt;



&lt;p&gt;Trust is also a huge factor in web-to-app. In-app, you rely on the app store’s credibility and reviews; with web-to-app, &lt;strong&gt;you need to actively build and optimise trust&lt;/strong&gt;, such as highlighting features, showing social proof and ratings, or introducing &lt;a href=&quot;https://www.revenuecat.com/blog/growth/video-paywalls/&quot;&gt;video paywalls&lt;/a&gt; to serve as mini demos.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;From there, ensure you optimise your payment page. You don’t have the same restrictions as in-app on the &lt;a href=&quot;https://www.revenuecat.com/blog/growth/paywalls-study-guide/&quot;&gt;paywall&lt;/a&gt;, so work to ensure the value is clear, that there is a good incentive to choose web, and that it continues to build trust.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;A few general best practices to keep in mind:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Make checkout easy (e.g. Apple Pay)&lt;/li&gt;



&lt;li&gt;Ensure a seamless handoff to the app (deep link, auto-login)&lt;/li&gt;



&lt;li&gt;Maintain a mobile-first UX&lt;/li&gt;



&lt;li&gt;Limit plan choices to prevent overwhelm&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Once these bits of housekeeping are done, you can further improve your funnel, whether that’s testing and refining the landing page or optimizing your quiz questions (because yes, quizzes &lt;em&gt;can &lt;/em&gt;be really useful tools). Questions in a quiz format help to build trust, but irrelevant or vague questions that don’t feel personalized can hurt your conversion rate.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;5-optimize-the-individual-funnels-further&quot;&gt;5. Optimize the individual funnels further&lt;/h3&gt;



&lt;p&gt;The beauty of web-to-app is that you can customise your funnel for each audience. &lt;a href=&quot;https://www.linkedin.com/in/anastasia-karlova/&quot;&gt;Anastasiia Karlova&lt;/a&gt;, Head of Marketing at Plantin, shared &lt;a href=&quot;https://www.businessofapps.com/podcasts/maximizing-growth-with-web-to-app-funnels-with-anastasiia-karlova-head-of-marketing-at-plantin/&quot;&gt;an insightful example:&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;They tested an ‘identify mushrooms’ ad with a web funnel focused on helping users understand which mushrooms they encountered and whether they were edible. It performed well on the web, but once users reached the app, there was no mushroom-related content, and they churned.&lt;/p&gt;



&lt;p&gt;This shows that web funnels need to align with the app journey. Optimise each funnel for its channel, ensuring that the experience and content on the app matches what the user was promised on the web.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;whats-next-for-web-to-app&quot;&gt;What’s next for web-to-app?&lt;/h2&gt;



&lt;p&gt;The future is exciting for web-to-app. Here’s my predictions for what we’ll see:&amp;nbsp;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;A larger number of apps testing web funnels as scaling through in-app channels becomes more competitive&lt;/li&gt;



&lt;li&gt;More hybrid funnel models, with apps consciously deciding when to send users to the web versus pushing for &lt;a href=&quot;https://www.revenuecat.com/blog/growth/guide-to-mobile-paywalls-subscription-apps/&quot;&gt;in-app paywalls&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;After the&lt;a href=&quot;https://www.revenuecat.com/blog/growth/apple-anti-steering-ruling-monetization-strategy/&quot;&gt; Epic vs. Apple ruling&lt;/a&gt; (allowing &lt;a href=&quot;https://www.revenuecat.com/blog/growth/introducing-web-paywall-buttons/&quot;&gt;web payments via app&lt;/a&gt; in the US), we can also expect to see this expand to other countries and markets, creating new opportunities for web-to-app strategies&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;As it becomes simpler to build and personalize funnels, we’ll likely see more segmentation and tailored flows for different audiences — for example, wellness app &lt;a href=&quot;https://betterme.world/&quot;&gt;BetterMe&lt;/a&gt; already has at least 12 highly optimized funnels!&lt;/p&gt;



&lt;p&gt;Web-to-app won’t make you grow overnight, it requires a conscious decision based on your app and how the pros and cons apply. That said, it offers a huge opportunity to unlock a new audience and grow your app. The surge in web-to-app funnels is happening for a reason — while it isn’t for every app, every app &lt;em&gt;should&lt;/em&gt; consider whether strategically testing web-to-app could add value as an alternative or complement to their in-app funnel.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-frequently-asked-questions-about-web-to-app-funnels&quot;&gt;Frequently asked questions about web-to-app funnels&lt;/h2&gt;



&lt;div class=&quot;schema-faq wp-block-yoast-faq-block&quot;&gt;&lt;div class=&quot;schema-faq-section&quot; id=&quot;faq-question-1764338379654&quot;&gt;&lt;strong class=&quot;schema-faq-question&quot;&gt;&lt;strong&gt;What exactly is a web-to-app funnel?&lt;/strong&gt;&lt;/strong&gt; &lt;p class=&quot;schema-faq-answer&quot;&gt;It’s when a user starts their journey on the web — through a landing page, quiz, or another flow — and then converts to install or subscribe in the app. The purchase can happen on the web or in-app.&lt;/p&gt; &lt;/div&gt; &lt;div class=&quot;schema-faq-section&quot; id=&quot;faq-question-1764338403478&quot;&gt;&lt;strong class=&quot;schema-faq-question&quot;&gt;&lt;strong&gt;Why are apps moving to web-to-app now?&lt;/strong&gt;&lt;/strong&gt; &lt;p class=&quot;schema-faq-answer&quot;&gt;After Apple’s ATT changes in 2021, attribution became harder. Web funnels also offer cleaner tracking, faster iteration, more control over pricing and messaging, and potentially higher LTVs.&lt;/p&gt; &lt;/div&gt; &lt;div class=&quot;schema-faq-section&quot; id=&quot;faq-question-1764338415446&quot;&gt;&lt;strong class=&quot;schema-faq-question&quot;&gt;&lt;strong&gt;Does web-to-app always save money?&lt;/strong&gt;&lt;/strong&gt; &lt;p class=&quot;schema-faq-answer&quot;&gt;Not always. Web fees are lower (blended around 5–6% vs. 15–30% through the app stores), but conversion rates can be lower, and additional tools may be needed. The net financial gain varies depending on your setup.&lt;/p&gt; &lt;/div&gt; &lt;div class=&quot;schema-faq-section&quot; id=&quot;faq-question-1764338431802&quot;&gt;&lt;strong class=&quot;schema-faq-question&quot;&gt;&lt;strong&gt;Do I need developers to launch a web-to-app funnel?&lt;/strong&gt;&lt;/strong&gt; &lt;p class=&quot;schema-faq-answer&quot;&gt;Not necessarily. No-code web funnel and landing page builders make it possible to test a funnel with minimal engineering support. Developer help may be required to ensure shared logins or deep linking are set up to reroute users after download.&lt;/p&gt; &lt;/div&gt; &lt;div class=&quot;schema-faq-section&quot; id=&quot;faq-question-1764338443859&quot;&gt;&lt;strong class=&quot;schema-faq-question&quot;&gt;&lt;strong&gt;Are web-to-app funnels allowed by Apple?&lt;/strong&gt;&lt;/strong&gt; &lt;p class=&quot;schema-faq-answer&quot;&gt;Yes, web-to-app funnels have always been allowed. Since the 2025 Epic ruling, apps in the US can also link out to external purchase options.&lt;/p&gt; &lt;/div&gt; &lt;div class=&quot;schema-faq-section&quot; id=&quot;faq-question-1764338456441&quot;&gt;&lt;strong class=&quot;schema-faq-question&quot;&gt;&lt;strong&gt;What kind of apps benefit most from a web-to-app funnel?&lt;/strong&gt;&lt;/strong&gt; &lt;p class=&quot;schema-faq-answer&quot;&gt;Apps with users familiar with the web, higher price points, or more complex onboarding journeys, like health, education, or productivity apps, tend to see the strongest results.&lt;/p&gt; &lt;/div&gt; &lt;/div&gt;
</content:encoded></item><item><title><![CDATA[How Greg Cohn turned a failed app into a privacy powerhouse]]></title><description><![CDATA[On this episode of Sub Club, Greg shares the journey of how a failed product pivoted into Burner, a mobile privacy tool that has changed the way people manage multiple phone numbers. ]]></description><link>https://www.revenuecat.com/blog/growth/greg-cohn-burner-sub-club-podcast-2025/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/greg-cohn-burner-sub-club-podcast-2025/</guid><pubDate>Wed, 10 Dec 2025 13:40:30 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/RC-Blog-Cover-Greg-Cohn-1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Greg Cohn’s journey to creating Burner began with his first app, Wrangle. The app was designed to help people find others available for phone calls, but it didn’t gain traction. However, Wrangle introduced Greg to Twilio’s API, which would later play a crucial role in Burner’s development.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;More importantly, it sparked Greg’s realization of a growing problem in mobile communication: the lack of privacy. This insight led him to create Burner, an app that would redefine how people manage phone numbers and safeguard their personal information.&lt;/p&gt;



&lt;p&gt;On this episode of Sub Club, Greg shares the journey of how a failed product pivoted into Burner, a mobile privacy tool that has changed the way people manage multiple phone numbers.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;Pivots, Funding, and Building Apps That Last – Greg Cohn, Burner&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/PSu9ZrwKHLo?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;iframe loading=&quot;lazy&quot; width=&quot;100%&quot; height=&quot;180&quot; frameborder=&quot;no&quot; scrolling=&quot;no&quot; seamless=&quot;&quot; src=&quot;https://share.transistor.fm/e/61d83c05?color=FFFFFF&amp;amp;background=30343C&quot;&gt;&lt;/iframe&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-focus-on-real-needs&quot;&gt;&lt;strong&gt;Focus on real needs&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Unlike many early-stage products that aim to cater to every possible use case, Burner began with a specific purpose: offering a solution for people who need temporary phone numbers for privacy. Greg built the app to address his own frustration with constantly having to hand out his personal number. His approach wasn’t about simply creating a flashy app but solving a real problem that users could immediately relate to.&lt;/p&gt;



&lt;p&gt;The simplicity of the idea, combined with a focus on user needs over trends, led to Burner gaining traction quickly. Unlike other apps that try to capture attention through social media or viral loops, Burner grew because it offered something valuable: the ability to separate one’s personal and professional life seamlessly.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-iterate-and-build-trust-with-your-users&quot;&gt;&lt;strong&gt;Iterate and build trust with your users&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Greg didn’t rush to raise funds for Burner. Instead, he let the product speak for itself by offering a free, easy-to-use experience right from the start. As the app gained users, Greg stayed focused on iterating based on feedback and refining the experience. As he improved the app’s features, users began sharing positive experiences, which naturally led more people to download it.&lt;/p&gt;



&lt;p&gt;Rather than chase virality, Greg emphasized building trust through product updates and staying user-focused. By keeping core features free and offering premium options as thank-you bonuses, Greg built a loyal user base that valued the app for what it truly offered: privacy and simplicity.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-a-product-built-for-the-long-haul&quot;&gt;&lt;strong&gt;A product built for the long haul&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;As Burner continued to grow, Greg’s approach to scaling remained grounded. The app’s evolution from a paid download model to a subscription service was a natural step, but Greg didn’t focus on rapid scaling. Instead, he built a sustainable business model that prioritized user retention over short-term profits.&lt;/p&gt;



&lt;p&gt;In the face of competitors and an increasingly crowded market, Greg’s primary goal has always been to stay authentic and focused on privacy. As the app expanded, he explored additional features, such as a VPN, to further enhance user security and privacy, demonstrating the company’s unwavering commitment to its core mission.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-conclusion&quot;&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;From a failed app to a highly successful privacy solution, Greg’s story is a lesson in staying true to your vision and listening to your users. For anyone building a product that solves a real-world problem, this episode is a reminder that the key to success isn’t always chasing growth, but delivering consistent, meaningful value.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[App-to-web: navigating external purchases in iOS and Android apps]]></title><description><![CDATA[Everything you need to know about the rulings and regulations on app-to-web]]></description><link>https://www.revenuecat.com/blog/engineering/app-to-web-purchase-guidelines/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/app-to-web-purchase-guidelines/</guid><pubDate>Tue, 09 Dec 2025 14:39:39 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Blog_Cover_Introductory-Offer-for-Web-1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Over the past few years Apple and Google have opened the door for app-to-web, allowing developers to use external purchase flows for in-app subscriptions; making it possible to &lt;strong&gt;bypass app store fees&lt;/strong&gt; and have more flexibility with &lt;strong&gt;pricing, promotions, &lt;/strong&gt;and &lt;strong&gt;checkout experiments&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;This has largely come about from court rulings like &lt;a href=&quot;https://www.revenuecat.com/blog/growth/apple-anti-steering-ruling-monetization-strategy/&quot;&gt;Epic Games v. Apple in the US&lt;/a&gt; and the Digital Markets Act in the EU, ultimately forcing Apple and Google to loosen strict requirements around in-app purchases (IAP).&amp;nbsp;&lt;/p&gt;



&lt;p&gt;For app teams, this opens up a new realm of &lt;a href=&quot;https://www.revenuecat.com/app-to-web/&quot;&gt;app-to-web&lt;/a&gt; possibilities — but when it comes to the regulations surrounding app-to-web, it’s not quite so clear cut. New guidelines are constantly appearing and evolving, varying by country and app category, so it’s difficult to keep up with what’s allowed (or not).&lt;/p&gt;



&lt;p&gt;To help, we’ve broken down the latest options, eligibility requirements, and commissions/fees for external payments around the world, on both the Apple App Store and Google Play Store. Here’s everything you need to know.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-external-purchases-with-app-to-web-work&quot;&gt;&lt;strong&gt;How external purchases with app-to-web work&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Here’s a quick overview on how external purchases work, and the two primary ways to incorporate them in your app.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;em&gt;If you want to jump straight to Apple and Google’s purchase guidelines, click &lt;a href=&quot;https://www.revenuecat.com/blog/engineering/app-to-web-purchase-guidelines/#h-in-app-purchases-vs-external-purchases-guidelines-and-regulations-for-apple-and-google&quot;&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-external-web-link&quot;&gt;&lt;strong&gt;1. External web link&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Your app includes a link or button that sends the user to an external website (or opens a webview) where the user completes the purchase. The app then unlocks content/features based on that external purchase (usually by syncing with your backend).&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Apple refers to this as using an &lt;a href=&quot;https://developer.apple.com/documentation/storekit/externalpurchaselink&quot;&gt;&lt;strong&gt;External Purchase Link&lt;/strong&gt;&lt;/a&gt;. For instance, a streaming app might have a “Subscribe on our website” button that opens its web checkout. After payment, the user can log into the app with the new subscription.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-third-party-payment-in-app&quot;&gt;&lt;strong&gt;2. Third-party payment (in-app)&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Your app integrates a non-Apple/non-Google payment gateway directly in the app’s UI. The purchase happens within the app, but not via App Store/Google Play billing. This is sometimes called&lt;strong&gt; alternative in-app payment&lt;/strong&gt;.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;A common example is &lt;a href=&quot;https://www.revenuecat.com/blog/engineering/can-you-use-stripe-for-in-app-purchases/&quot;&gt;using Stripe for in-app purchases&lt;/a&gt;, or showing a country-specific credit card form at checkout in lieu of App Store purchase dialogs.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;While this used to be far trickier to implement, Apple v. Epic has meant third-party payments are much easier to use these days. However, Apple and Google have strict rules if you choose either of these paths:&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-implementing-third-party-payment-with-apple&quot;&gt;&lt;strong&gt;Implementing third-party payment with Apple&lt;/strong&gt;&lt;/h4&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;You’ll need to request Apple’s special entitlements before offering any kind of external purchase flow&lt;/li&gt;



&lt;li&gt;Depending on what you’re building, you’ll use either the External Purchase Link API (to send users to your web checkout) or the External Purchase Entitlement (to run a third-party payment flow inside the app)&lt;/li&gt;



&lt;li&gt;Before users leave the app or pay through a non-Apple method, Apple shows a built-in disclosure sheet letting them know the purchase isn’t handled by the App Store&lt;/li&gt;



&lt;li&gt;In some cases, if you use an external purchase entitlement, you cannot also offer Apple IAP in the same app in that region — it’s one or the other on a given storefront&lt;/li&gt;
&lt;/ul&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-implementing-third-party-payment-with-google&quot;&gt;&lt;strong&gt;Implementing third-party payment with Google&lt;/strong&gt;&lt;/h4&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Google’s User Choice Billing means the user is offered a choice between Google Play’s billing and an alternative billing method during checkout&lt;/li&gt;



&lt;li&gt;Developers must integrate Google’s alternative billing API to present this option&lt;/li&gt;



&lt;li&gt;For External Offers (EEA only), the app can directly link out to a purchase web page (and Google will display a ‘leaving Play’ prompt to users on tap)&lt;/li&gt;



&lt;li&gt;Like Apple, there are cases where you’re not allowed to mix standard Google Play Billing IAP with external offers&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-in-app-purchases-vs-external-purchases-guidelines-and-regulations-for-apple-and-google&quot;&gt;&lt;strong&gt;In-app purchases vs. external purchases: guidelines and regulations for Apple and Google&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Most apps on both the Apple App Store and Google Play Store use the platform’s built-in billing system for subscriptions and digital goods. By default, you’re not allowed to direct users to a different payment flow inside your app unless you qualify for (and opt into) one of the external-purchase programs covered below.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;For standard in-app purchases, each app store takes a cut. The standard commission for both Apple and Google Play is 30%, but both stores reduce this to 15% for developers making less than $1M/year from IAP. On Google Play, the 15% rate is also applied to recurring subscriptions after the first year.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;To avoid these fees, apps are allowed to offer external purchases, as long as they adhere to the following guidelines:&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-apple-app-store-external-purchases-guidelines&quot;&gt;&lt;strong&gt;Apple App Store external purchases guidelines&lt;/strong&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Region/program&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Eligible apps&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;What’s allowed for external payments&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Commissions/fees&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Notes and references&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;United States: External Purchase Links&amp;nbsp;&lt;/td&gt;&lt;td&gt;All app categories in the US App Store (including games)&lt;/td&gt;&lt;td&gt;Can include external payment links in-app to a web checkout&lt;/td&gt;&lt;td&gt;0%&amp;nbsp;&lt;br&gt;&lt;br&gt;Standard App Store commission (15–30%) still applies to any purchases made via IAP&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://developer.apple.com/app-store/review/guidelines/#link-to-other-purchase-methods&quot;&gt;&lt;em&gt;App Store Review Guidelines (United States)&lt;/em&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;EU/EEA: communication and promotion of offers&amp;nbsp;Alternative terms/StoreKit External Purchase Link&lt;/td&gt;&lt;td&gt;All apps on an EU or EEA storefront&lt;/td&gt;&lt;td&gt;External purchases or payments allowed via link-out or third-party processing&lt;/td&gt;&lt;td&gt;If using IAP:&amp;nbsp;&lt;br&gt;&lt;br&gt;10-17% commission+ 3% payment processing&lt;br&gt;&lt;br&gt;If using external purchases:&lt;br&gt;&lt;br&gt;2% Initial Acquisition fee&amp;nbsp;&lt;br&gt;&lt;br&gt;+ 5-13% (depending on optional store services)&lt;br&gt;&lt;br&gt;+ €0.50 Core Technology Fee per first annual install over 1M&lt;/td&gt;&lt;td&gt;Requires opt-in to the Alternative Terms Addendum for Apps in the EU and/or StoreKit External Purchase Link Entitlement for EU storefronts&lt;br&gt;&lt;br&gt;&lt;a href=&quot;https://developer.apple.com/support/communication-and-promotion-of-offers-on-the-app-store-in-the-eu/&quot;&gt;&lt;em&gt;Communication and promotion of offers on the App Store in the EU&lt;/em&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;EEA: music streaming services entitlement&lt;/td&gt;&lt;td&gt;Music streaming apps&lt;/td&gt;&lt;td&gt;External subscription link or button allowed to your website&lt;/td&gt;&lt;td&gt;Up to ~27% commission (roughly the normal 30% cut minus ~3% payment processing)&lt;br&gt;&lt;br&gt;If you instead opt into the EU Alternative Terms, external purchases are subject to the EU fee stack above (2% + 5–13% + 5% etc.) rather than a flat 27%&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://developer.apple.com/support/music-streaming-services-entitlement-eea/&quot;&gt;&lt;em&gt;Music streaming services entitlement (EEA)&lt;/em&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Netherlands: dating apps&lt;/td&gt;&lt;td&gt;Dating apps exclusive to the NL storefront&lt;/td&gt;&lt;td&gt;Alternate in-app payments and/or external link to web purchase are allowed alongside Apple IAP&lt;/td&gt;&lt;td&gt;Normal App Store commission minus 3% (e.g. 27% instead of 30%, 12% instead of 15% for small business/long‑running subs)&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://developer.apple.com/support/storekit-external-entitlement/&quot;&gt;&lt;em&gt;Distributing dating apps in the Netherlands&lt;/em&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;South Korea: StoreKit External Purchase Entitlement&lt;/td&gt;&lt;td&gt;All apps distributed solely on the South Korea App Store using a qualifying third‑party PSP&lt;/td&gt;&lt;td&gt;Alternate in-app payment providers allowed (no Apple IAP required)&lt;br&gt;&lt;br&gt;You cannot also offer IAP in the same SK app&lt;/td&gt;&lt;td&gt;26%&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://developer.apple.com/support/storekit-external-entitlement-kr&quot;&gt;&lt;em&gt;Distributing apps using a third‑party payment provider in South Korea&lt;/em&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Global: reader apps (External Link Account Entitlement)&lt;/td&gt;&lt;td&gt;‘Reader’ apps whose primary purpose is providing magazines, newspapers, books, audio, music, or video, and that let users sign in to access previously-purchased content&amp;nbsp;&lt;/td&gt;&lt;td&gt;Can include one link to your website for account creation and management&lt;br&gt;&lt;br&gt;The link must open in a browser&amp;nbsp;&lt;br&gt;&lt;br&gt;Cannot offer IAP in the same app&amp;nbsp;&lt;/td&gt;&lt;td&gt;0%&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://developer.apple.com/support/reader-apps/&quot;&gt;&lt;em&gt;Distributing reader apps with a link to your website&lt;/em&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Japan: Mobile Software Competition Act (MSCA)&lt;/td&gt;&lt;td&gt;All iOS apps on Japan App Store (all categories) with required entitlements&lt;/td&gt;&lt;td&gt;App-to-web purchases via Out-of-App Offers (external links to web checkout)&lt;br&gt;&lt;br&gt;Alternative in-app payments via Alternative Payment Processing (non-Apple PSPs)&lt;br&gt;&lt;br&gt;In-app display of prices and promotions for web purchases&lt;br&gt;&lt;br&gt;Apple IAP and external payment options must coexist and be shown side-by-side&lt;/td&gt;&lt;td&gt;Alternative Payment Processing: 21% (10% reduced cases)&lt;br&gt;&lt;br&gt;Out-of-App Offers (web): 15% (10% reduced cases; applies to renewals)&lt;br&gt;&lt;br&gt;Apple IAP: 21% + 5% payment processing (10% + 5% reduced)&lt;br&gt;&lt;br&gt;Alternative app marketplaces: 5% Core Technology Commission&lt;/td&gt;&lt;td&gt;External payments permitted under MSCA; Apple implements via entitlements, StoreKit APIs, disclosures, parity UI, default-browser links, and age restrictions&lt;br&gt;&lt;br&gt;&lt;a href=&quot;https://www.apple.com/newsroom/2025/12/apple-announces-changes-to-ios-in-japan&quot;&gt;Read Apple’s announcement here.&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-google-play-store-external-purchases-guidelines&quot;&gt;&lt;strong&gt;Google Play Store external purchases guidelines&lt;/strong&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Region/program&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Eligible apps&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;What’s allowed for external payments&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Commissions/fees&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Notes and references&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;User choice billing: Australia, Brazil, Indonesia, Japan, South Africa, United Kingdom, United States and EEA&lt;/td&gt;&lt;td&gt;&lt;em&gt;Non-game&lt;/em&gt; apps in Australia, Brazil, Indonesia, Japan, South Africa, United Kingdom, and United States&lt;br&gt;&lt;br&gt;&lt;em&gt;All&lt;/em&gt; apps in EEA, South Korea, India&lt;/td&gt;&lt;td&gt;‘User choice billing’ (UCB): apps can offer users a choice between Google Play’s billing and an alternative in-app billing method&lt;/td&gt;&lt;td&gt;If using IAP:&amp;nbsp;&lt;br&gt;&lt;br&gt;15% for the first $1M/year in revenue&lt;br&gt;&lt;br&gt;30% above $1M/year&amp;nbsp;&lt;br&gt;&lt;br&gt;If using external billing system:&amp;nbsp;&lt;br&gt;&lt;br&gt;Normal service fee minus 4% (e.g. 11% instead of 15%, 26% instead of 30%)&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://support.google.com/googleplay/android-developer/answer/13821247&quot;&gt;&lt;em&gt;User choice billing on Google Play&lt;/em&gt;&amp;nbsp;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;EEA: alternative billing only (no Google Play Billing in the app)&lt;/td&gt;&lt;td&gt;Apps targeting users in the EEA that want to remove Google Play Billing entirely and use only their own billing in‑app&lt;/td&gt;&lt;td&gt;You complete in‑app transactions through your own (or third‑party) billing system only&amp;nbsp;&lt;br&gt;&lt;br&gt;You are not allowed to offer Google Play Billing as an option in the same app&lt;/td&gt;&lt;td&gt;Standard Google Play service fee minus 3% (e.g. 12% instead of 15%, 27% instead of 30%)&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://support.google.com/googleplay/android-developer/answer/14659200?hl=en&quot;&gt;&lt;em&gt;EEA alternative‑billing program&lt;/em&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;EEA: external Offers Program (link‑out program)&lt;/td&gt;&lt;td&gt;Apps in the EEA that want to promote offers in‑app and send users outside the app (browser, other store, webview) for purchases/subscriptions&lt;/td&gt;&lt;td&gt;You can show in‑app promotional units and hyperlinks (‘linkouts’) that take users to your site or other destinations to purchase digital items or subscriptions&lt;/td&gt;&lt;td&gt;3% Initial Acquisition fee&amp;nbsp;&lt;br&gt;&lt;br&gt;+ 10% (required) Tier 1 service fee&lt;br&gt;&lt;br&gt;+ 3% / 10% (optional) Tier 2 fee (10% for IAP or +3% for subs)&amp;nbsp;&lt;br&gt;&lt;br&gt;+ Variable per-install fees depending on app category&lt;/td&gt;&lt;td&gt;Fees are additive, so a typical Tier‑1 setup is roughly 13% on external sales, while Tier 1+2 can reach the mid‑20% range for some offers&lt;br&gt;&lt;br&gt;&lt;a href=&quot;https://support.google.com/googleplay/android-developer/answer/16505463?hl=en&quot;&gt;&lt;em&gt;Changes to the external offers program for users in the EEA&lt;/em&gt;&lt;/a&gt;&amp;nbsp;(includes IA %, Tier 1/2 fees, per‑install fee tables)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Japan: Mobile Software Competition Act (MSCA)&lt;br&gt;&lt;/td&gt;&lt;td&gt;All apps distributed on Google Play in Japan (games and non-games), via program enrollment&lt;br&gt;&lt;/td&gt;&lt;td&gt;User Choice Billing (UCB): side-by-side alternative in-app billing expanded to all apps&lt;br&gt;&lt;br&gt;App-to-web purchases via new Google Play link-out program&lt;br&gt;&lt;br&gt;In-app display of prices and promotions for web purchases&lt;br&gt;&lt;br&gt;Google Play Billing and external options may coexist&lt;/td&gt;&lt;td&gt;Google Play Billing: 15% for first $1M/year, 30% above&lt;br&gt;&lt;br&gt;Alternative in-app billing (UCB): standard service fee minus ~4%&lt;br&gt;&lt;br&gt;App-to-web purchases: competitive fees via Google program (rates defined by Google)&lt;/td&gt;&lt;td&gt;MSCA compliance via expanded UCB and new app-to-web program; participation subject to APIs and safety/security requirements&lt;br&gt;&lt;br&gt;&lt;a href=&quot;https://blog.google/around-the-globe/google-asia/complying-with-mobile-software-competition-act/&quot;&gt;Read Google’s announcement here.&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;United States: External Content Links Program (ECLP)&lt;/td&gt;&lt;td&gt;All apps and games on Google Play serving users in the US (mobile and tablet)&lt;/td&gt;&lt;td&gt;Developers can link users to an external website for in-app digital purchases or app downloads. Can be offered alongside or instead of Google Play Billing. Info screen shown before redirect.&lt;/td&gt;&lt;td&gt;Currently 0% (not yet enforced). Proposed: 10% subs, 20% other digital purchases. First $1M/year at 10%. Downloads: $3.65/install (games), $2.85/install (apps).&lt;/td&gt;&lt;td&gt;Created under Epic v. Google injunction. Enrollment required by Jan 28, 2026. Fees pending settlement ruling. Requires Google’s external links APIs.&lt;br&gt;&lt;br&gt;&lt;a href=&quot;https://support.google.com/googleplay/android-developer/answer/16470497?hl=en&quot;&gt;&lt;em&gt;Enrolling in the external content links program for users in the US&lt;/em&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-adding-web-checkout-options-to-your-app&quot;&gt;&lt;strong&gt;Adding web checkout options to your app&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;If you’re reading this far, you’re probably already sold on app-to-web. The hard part isn’t &lt;em&gt;why&lt;/em&gt;; it’s &lt;em&gt;how&lt;/em&gt; to ship it quickly, stay compliant, and not turn your purchase flow into a science project.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/company/introducing-revenuecat-billing/&quot;&gt;RevenueCat Web&lt;/a&gt; is the simplest way to add a web checkout to a subscription app. Instead of stitching together a payment processor, entitlement sync, identity mapping, and analytics on your own, you get a full web billing stack that plugs into the RevenueCat setup you already use for mobile. Users can buy on the web and unlock access in iOS or Android right away, with one subscriber record and one source of truth.&lt;/p&gt;



&lt;p&gt;Here’s how the pieces fit together:&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/billing/&quot;&gt;&lt;strong&gt;Web Billing&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt; as your billing engine: &lt;/strong&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/company/introductory-offers-for-revenuecat-web-billing/&quot;&gt;Web Billing&lt;/a&gt; is RevenueCat’s native billing engine for web subscriptions. It manages the subscription lifecycle on the web and stays fully integrated with your RevenueCat products, customers, and entitlements. You don’t have to build or maintain separate web billing logic.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Web checkout surfaces that you can launch in minutes: &lt;/strong&gt;once Web Billing is on, you can direct users to web checkout in a few different ways:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.revenuecat.com/web-purchase-button/&quot;&gt;&lt;strong&gt;Web Purchase Button&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt; inside your in-app paywall:&lt;/strong&gt; add a button component to any RevenueCat Paywall; tapping it sends users to a web checkout&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Web Purchase Links&lt;/strong&gt;: RevenueCat-hosted checkout URLs you can drop anywhere, including behind the &lt;a href=&quot;https://www.revenuecat.com/blog/growth/introducing-web-paywall-buttons/&quot;&gt;Web Purchase Button&lt;/a&gt; — they work out of the box and support identified or anonymous flows&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/web/web-billing/paywalls#presenting-a-paywall-from-the-web-sdk&quot;&gt;&lt;strong&gt;Web Paywalls shown via the Web SDK&lt;/strong&gt;&lt;/a&gt;: if you have your own web app or landing pages, you can render a RevenueCat Paywall directly on your site through Purchases.js, then complete checkout there&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Everything stays connected. The &lt;a href=&quot;https://www.revenuecat.com/blog/company/web-overview-dashboard/&quot;&gt;Web overview dashboard&lt;/a&gt; shows you everything in one place, and your web and mobile offerings live in the same catalog, entitlements sync automatically, and events flow into the same analytics layer.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-how-to-keep-app-to-web-conversion-strong&quot;&gt;&lt;strong&gt;How to keep app-to-web conversion strong&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Teams usually worry that a web step will convert worse than native checkout. This can be easily avoided by sending users to a &lt;a href=&quot;https://www.revenuecat.com/docs/web/web-billing/paywalls#using-a-paywall-in-a-web-purchase-link&quot;&gt;web paywall&lt;/a&gt; that completes the purchase on the same page (aka, RevenueCat’s Express Purchase button).&amp;nbsp;&lt;/p&gt;



&lt;p&gt;If Apple Pay or Google Pay is available in the browser, a wallet button shows on the web paywall. The user taps once, confirms in their wallet, and the purchase completes. RevenueCat then syncs access back to the app automatically.&lt;/p&gt;



&lt;p&gt;This keeps the handoff short: paywall in app → paywall on web → wallet confirmation = access unlocked.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-examples-of-app-to-web&quot;&gt;&lt;strong&gt;Examples of app-to-web&lt;/strong&gt;&lt;/h3&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;In-app upgrade with a web option: &lt;/strong&gt;your in-app paywall includes a ‘Continue on web’ button. The web paywall opens with the same plan selected, and a wallet button appears when supported. Users who want a faster checkout finish in one tap.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Win-back discount: &lt;/strong&gt;a churned user sees a targeted in-app paywall with a comeback offer. The web button routes to a separate web offering with the discount already applied, so the user doesn’t need to hunt for the right plan.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Campaign traffic you can measure: &lt;/strong&gt;You share a Web Purchase Link in ads or email with UTM parameters intact. After purchase, a redemption step links the subscription to the user’s app account and unlocks access right away. You get clean attribution without custom glue code.&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-ready-to-experiment-with-app-to-web&quot;&gt;&lt;strong&gt;Ready to experiment with app-to-web?&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;As app-to-web guidelines continue to shift, your success depends on keeping checkouts flexible and compliant. We’ll keep this guide updated as Apple and Google refine their policies, so bookmark it and check back whenever you’re planning your next app-to-web iteration.&lt;/p&gt;



&lt;p&gt;Whether you experiment with custom checkout code or get RevenueCat Web to do the heavy lifting, app-to-web can be an efficient and flexible purchase flow. Good luck, and happy testing!&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[November product updates: A Paywalls special with faster builds, sharper promos, and new proof points]]></title><description><![CDATA[Figma-to-Paywalls export, faster editing, richer previews, countdown promos, and verified metrics sharing.]]></description><link>https://www.revenuecat.com/blog/company/november-product-updates-2025/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/company/november-product-updates-2025/</guid><pubDate>Mon, 08 Dec 2025 12:59:26 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Product-updates-November-2025.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;November was a Paywalls month through and through. If Paywalls are a key part of how you grow, you’ve probably felt the same tension we have: keep shipping experiments, keep design quality high, and don’t lose days to handoffs or tiny UI chores.&lt;/p&gt;



&lt;p&gt;This release set is about removing friction. You can move designs from Figma to live Paywalls without rebuilding, work faster in the editor, preview across more devices before you publish, and add real urgency to promotions with a Countdown component. We also shipped a new way to share verified performance metrics.&lt;/p&gt;



&lt;p&gt;Here’s what’s new.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-export-figma-designs-straight-into-paywalls&quot;&gt;Export Figma designs straight into Paywalls&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;576&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/figma-integration-1-1024x576.png&quot; alt=&quot;&quot; class=&quot;wp-image-48638&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/figma-integration-1-1024x576.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/figma-integration-1-300x169.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/figma-integration-1-768x432.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/figma-integration-1-1536x864.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/figma-integration-1-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/figma-integration-1-71x40.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/figma-integration-1-696x392.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/figma-integration-1-560x315.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/figma-integration-1-526x296.png 526w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/figma-integration-1.png 1920w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Design handoff shouldn’t mean starting over. Now it doesn’t.&lt;/p&gt;



&lt;p&gt;You can export Figma mockups directly into the Paywall editor. Your layout comes in as native Paywalls components, so you can immediately:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Edit copy without touching the structure.&lt;/li&gt;



&lt;li&gt;Swap products and packages.&lt;/li&gt;



&lt;li&gt;Localize text.&lt;/li&gt;



&lt;li&gt;Add experiments.&lt;/li&gt;



&lt;li&gt;Target specific audiences.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The practical win is speed. Designers stay in Figma, and the team shipping paywall tests can go from “final mock” to “live variant” without recreating the layout by hand.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://e.customeriomail.com/e/c/eyJlIjoxNzQzMDMsImVtYWlsX2lkIjoiZXhhbXBsZSIsImhyZWYiOiJodHRwczovL3d3dy5yZXZlbnVlY2F0LmNvbS9ibG9nL2VuZ2luZWVyaW5nL3JldmVudWVjYXQtZmlnbWEtcGx1Z2luLz91dG1fY2FtcGFpZ249Tm92ZW1iZXIrTmV3c2xldHRlclx1MDAyNnV0bV9jb250ZW50PU5vdmVtYmVyK05ld3NsZXR0ZXJcdTAwMjZ1dG1fbWVkaXVtPWVtYWlsX2FjdGlvblx1MDAyNnV0bV9zb3VyY2U9Y3VzdG9tZXIuaW8iLCJ0IjoxNzY0Njk3MDQ3fQ/b7d9d39cf861b68d6a988cd66fe5fd508b68ba0a2a9bb287d78acde049e07132&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Import a Figma &lt;/a&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/engineering/revenuecat-figma-plugin&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;design&lt;/a&gt;&lt;a href=&quot;https://e.customeriomail.com/e/c/eyJlIjoxNzQzMDMsImVtYWlsX2lkIjoiZXhhbXBsZSIsImhyZWYiOiJodHRwczovL3d3dy5yZXZlbnVlY2F0LmNvbS9ibG9nL2VuZ2luZWVyaW5nL3JldmVudWVjYXQtZmlnbWEtcGx1Z2luLz91dG1fY2FtcGFpZ249Tm92ZW1iZXIrTmV3c2xldHRlclx1MDAyNnV0bV9jb250ZW50PU5vdmVtYmVyK05ld3NsZXR0ZXJcdTAwMjZ1dG1fbWVkaXVtPWVtYWlsX2FjdGlvblx1MDAyNnV0bV9zb3VyY2U9Y3VzdG9tZXIuaW8iLCJ0IjoxNzY0Njk3MDQ3fQ/b7d9d39cf861b68d6a988cd66fe5fd508b68ba0a2a9bb287d78acde049e07132&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt; ↗&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-keyboard-shortcuts-in-the-paywalls-editor&quot;&gt;Keyboard shortcuts in the Paywalls editor&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;538&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Shortcuts-1024x538.png&quot; alt=&quot;&quot; class=&quot;wp-image-48626&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Shortcuts-1024x538.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Shortcuts-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Shortcuts-768x403.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Shortcuts-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Shortcuts-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Shortcuts-696x365.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Shortcuts-560x294.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Shortcuts-840x441.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Shortcuts-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Shortcuts-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Shortcuts.png 1200w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;When you’re iterating quickly, little clicks add up.&lt;/p&gt;



&lt;p&gt;The Paywalls editor now supports keyboard shortcuts for the actions you use most, including adding components, duplicating sections, undoing and redoing changes, and deleting blocks. It keeps you in flow and makes fast iteration feel genuinely fast.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/tools/paywalls/creating-paywalls&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;View all shortcuts ↗&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-preview-your-paywall-on-more-devices&quot;&gt;Preview your paywall on more devices&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;538&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Device-Preview-1024x538.png&quot; alt=&quot;&quot; class=&quot;wp-image-48628&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Device-Preview-1024x538.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Device-Preview-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Device-Preview-768x403.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Device-Preview-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Device-Preview-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Device-Preview-696x365.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Device-Preview-560x294.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Device-Preview-840x441.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Device-Preview-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Device-Preview-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Device-Preview.png 1200w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;A paywall can look perfect on one screen and awkward on another. That used to be something you discovered after publishing.&lt;/p&gt;



&lt;p&gt;Now you can preview Paywalls across a wider set of iOS and Android phones and tablets. The canvas updates to real screen sizes, so you can flip through devices in seconds to:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Catch spacing issues early.&lt;/li&gt;



&lt;li&gt;Confirm font sizes.&lt;/li&gt;



&lt;li&gt;Check crops and media positioning.&lt;/li&gt;



&lt;li&gt;Sanity-check scroll behavior.&lt;/li&gt;



&lt;li&gt;Make sure your CTA lands where you want it.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;It’s a simple change that prevents a lot of last-minute fixes.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-filter-paywall-templates&quot;&gt;Filter paywall templates&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;538&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywall-gallery-filters-1024x538.png&quot; alt=&quot;&quot; class=&quot;wp-image-48630&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywall-gallery-filters-1024x538.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywall-gallery-filters-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywall-gallery-filters-768x403.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywall-gallery-filters-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywall-gallery-filters-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywall-gallery-filters-696x365.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywall-gallery-filters-560x294.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywall-gallery-filters-840x441.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywall-gallery-filters-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywall-gallery-filters-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywall-gallery-filters.png 1200w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Templates are only helpful if you can find the right one quickly.&lt;/p&gt;



&lt;p&gt;The template gallery now includes filters by purchase method, tier, or package. It’s especially useful when you know the pattern you want up front, like a trial-first layout, a pricing grid, or a promo-ready design. You spend less time searching and more time shipping.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/tools/paywalls/creating-paywalls&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Start with a template ↗&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-countdown-component-for-your-paywall&quot;&gt;Countdown component for your paywall&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;538&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Countdown-Component-1-1024x538.png&quot; alt=&quot;&quot; class=&quot;wp-image-48632&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Countdown-Component-1-1024x538.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Countdown-Component-1-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Countdown-Component-1-768x403.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Countdown-Component-1-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Countdown-Component-1-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Countdown-Component-1-696x365.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Countdown-Component-1-560x294.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Countdown-Component-1-840x441.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Countdown-Component-1-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Countdown-Component-1-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Paywalls-Countdown-Component-1.png 1200w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Promos work best when urgency is clear and real.&lt;/p&gt;



&lt;p&gt;You can now add a Countdown timer to any Paywall. Set an end date once and the timer updates automatically. No extra code, no manual updates.&lt;/p&gt;



&lt;p&gt;This is built for campaigns like Black Friday, launch promos, limited-time discounts, or any offer where timing helps people decide.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/tools/paywalls/creating-paywalls/components#countdown&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Add a Countdown ↗&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-share-verified-performance-metrics&quot;&gt;Share verified performance metrics&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;538&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Verified-Metrics-1024x538.png&quot; alt=&quot;&quot; class=&quot;wp-image-48634&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Verified-Metrics-1024x538.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Verified-Metrics-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Verified-Metrics-768x403.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Verified-Metrics-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Verified-Metrics-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Verified-Metrics-696x365.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Verified-Metrics-560x294.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Verified-Metrics-840x441.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Verified-Metrics-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Verified-Metrics-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Verified-Metrics.png 1200w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;When you’re talking about growth, proof matters.&lt;/p&gt;



&lt;p&gt;You can now publicly share verified performance metrics from your RevenueCat project. You control what’s visible: publish with your project details, or anonymize the profile entirely.&lt;/p&gt;



&lt;p&gt;It’s a clean way to back up results for partners, investors, or your community with real numbers pulled directly from RevenueCat.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://x.com/RevenueCat/status/1989397530631921682&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Share your metrics ↗&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;If you want to try these updates, everything is live in the dashboard now. Start with the Figma export and device previews if your workflow includes a lot of Paywall design iteration. Add the Countdown component the next time you’re running a time-boxed promo. Each of these is aimed at the same thing: getting high-quality Paywalls live faster, with less friction along the way.&lt;br&gt;&lt;br&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Why more ad channels for your subscription app doesn’t always mean less risk]]></title><description><![CDATA[How to know when your team (and budget) are ready to diversify ad channels]]></description><link>https://www.revenuecat.com/blog/growth/ad-channel-diversification/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/ad-channel-diversification/</guid><pubDate>Fri, 05 Dec 2025 11:09:15 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Why-more-ad-channels-doesnt-always-mean-less-risk.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;This article is based on the assumption that most app teams diversify their ad spend because it feels safer. If Meta tanks your CPI overnight, or Google suddenly changes the optimal dimensions for creatives, it’s surely way safer to not be dependent on a single channel. Right?&lt;/p&gt;



&lt;p&gt;Well, read on for a breakdown of &lt;strong&gt;ad channel diversification&lt;/strong&gt;’s pros and cons, and what I’ve learnt scaling apps across Meta, TikTok, Google and more — like when channel diversification works (and when it doesn’t), how to make the most of your paid ad budget, and how to anticipate ad channel problems. Along the way, I’ll share real-life examples from my work with small, medium, and large apps.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-is-ad-channel-diversification&quot;&gt;&lt;strong&gt;What is ad channel diversification?&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Ad channel diversification is the practice of splitting your paid user acquisition budget across multiple advertising platforms instead of concentrating it on one or two channels.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;958&quot; height=&quot;824&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-2.png&quot; alt=&quot;&quot; class=&quot;wp-image-48574&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-2.png 958w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-2-300x258.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-2-768x661.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-2-50x43.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-2-47x40.png 47w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-2-539x464.png 539w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-2-696x599.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-2-560x482.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-2-344x296.png 344w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-2-549x472.png 549w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-2-80x69.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-2-48x41.png 48w&quot; sizes=&quot;auto, (max-width: 958px) 100vw, 958px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;In other words, it is the practice of not putting all your eggs in one basket. You’re protected from Apple’s latest privacy rule, or Meta’s fickle algorithm, because you have traffic coming from other places. Sounds logical, right?&lt;/p&gt;



&lt;p&gt;In reality, and my experience, following this advice can become a double-edged sword that kills your app’s growth and its chances of success.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Many subscription apps hurt ad performance by spreading budgets too thin. Ad channel diversification can be a huge win, but it can also dilute learning, slow optimization, and ad operational overhead. So when should you add new channels? This article aims to answer just that!&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;the-hidden-risks-of-ad-channel-diversification&quot;&gt;&lt;strong&gt;The hidden risks of ad channel diversification&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Diversification sounds strategic, but the operational drag is real. When you split a budget across multiple channels, you’re also splitting:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Learning-phase velocity&lt;/strong&gt;: each channel gets too little data to exit &lt;a href=&quot;https://www.revenuecat.com/blog/growth/meta-ads-cac-creative-testing/&quot;&gt;creative testing&lt;/a&gt; consistently&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Creative bandwidth&lt;/strong&gt;: your team now needs multiple formats, spec variations, and testing roadmaps&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Optimization focus&lt;/strong&gt;: time moves from ‘making what works work better’ to ‘keeping multiple sub-performing channels afloat’&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Years ago, I experienced the pain of diversifying ad channels firsthand.&lt;/p&gt;



&lt;p&gt;I worked with a subscription app, spending $80k/month exclusively on &lt;a href=&quot;https://www.revenuecat.com/blog/growth/meta-ads-in-2025-tips-for-apps/&quot;&gt;Meta&lt;/a&gt; with a blended &lt;a href=&quot;https://www.revenuecat.com/blog/growth/creative-fatigue-mobile-apps-roas/&quot;&gt;return-on-ad-spend (ROAS)&lt;/a&gt; of &lt;strong&gt;2.8x&lt;/strong&gt;. The founder decided to diversify ad channels&amp;nbsp; and split the budget: $40k for Meta, $25k for Google, and $15k for TikTok.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Three months later, the ROAS dropped to 1.9x across all channels. Why? None of the channels had enough budget to exit the &lt;a href=&quot;https://www.revenuecat.com/blog/growth/subscription-app-creative-testing/&quot;&gt;creative testing&lt;/a&gt; phase consistently.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/creative-volume-meta-ad/&quot;&gt;Creative volume&lt;/a&gt; couldn’t keep up with three different formats, and the &lt;a href=&quot;https://www.revenuecat.com/blog/growth/build-app-growth-team/&quot;&gt;growth team&lt;/a&gt; spent more time in meetings discussing ‘channel strategy’ than actually &lt;a href=&quot;https://www.youtube.com/watch?v=j2Drz5BRTbo&quot;&gt;optimizing ads and user acquisition&lt;/a&gt;.&amp;nbsp;&lt;br&gt;The uncomfortable truth is that diversification feels like risk management, but&lt;strong&gt; it’s often just dilution&lt;/strong&gt; — of resources, insights, and priorities. Without time to &lt;a href=&quot;https://www.revenuecat.com/blog/growth/overanalyze-creative-analysis-paid-ads/&quot;&gt;analyze creative success&lt;/a&gt; and put learnings into action, all we’d done was spread the ad budget too thin and have nothing to show for it.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;signals-youre-not-ready-to-diversify-ad-channels&quot;&gt;&lt;strong&gt;Signals you’re not ready to diversify ad channels&amp;nbsp;&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;This list is designed to help you decide whether diversifying your budget is worth it. Think of these as red flags to sense-check your decision, or show someone why more ad channels could be a risk.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;1-you-dont-have-enough-bandwidth&quot;&gt;&lt;strong&gt;1. You don’t have enough bandwidth&amp;nbsp;&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Ever heard the phrase “don’t bite off more than you can chew”?&lt;/p&gt;



&lt;p&gt;Understand and be conscious that the cost of losing focus is always higher than expected because it’s hard to measure. Teams frequently underestimate how much time disappears into creative resets, weekly channel reviews, and troubleshooting. And the consequences of not being able to say ‘no’ to more channels will only hit harder in the future.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;2-you-have-narrow-or-niche-audience-constraints&quot;&gt;&lt;strong&gt;2. You have narrow or niche audience constraints&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;I once advised an at-home services app that operated in just three cities (specific zip codes). Things started to work when we focused on keyword placements across &lt;a href=&quot;https://www.revenuecat.com/blog/growth/apple-search-ads-guide/&quot;&gt;Apple Ads&lt;/a&gt; and Google Ads (search-to-app), and stopped betting on broad targeting and algorithmic channels like &lt;a href=&quot;https://www.revenuecat.com/webinars/advanced-meta-ads-strategies-for-subscription-apps/&quot;&gt;Meta Ads&lt;/a&gt; and TikTokwith social content. In this case, the territory limitation and high CPM simply wasn’t worth the money.&lt;/p&gt;



&lt;p&gt;If you operate in just a few specific areas or target a niche persona, keyword channels may be your best bets. Sometimes your app’s audience is limited; not accounting for that constraint, just because you want to diversify, is a risky move.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;3-your-budget-cant-sustain-multiple-channels&quot;&gt;&lt;strong&gt;3. Your budget can’t sustain multiple channels&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Concentrating your budgets is an opportunity, not a restraint. Ignoring that opportunity is a red flag. Spreading your budget too thin means:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;More extended periods in the learning phase&lt;/li&gt;



&lt;li&gt;Less signals to ad networks to optimize performance&lt;/li&gt;



&lt;li&gt;Limited capacity to test ad creatives&lt;/li&gt;



&lt;li&gt;Reduced scalability when things start to gain traction&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;4-you-dont-have-capacity-for-ad-maintenance&quot;&gt;&lt;strong&gt;4. You don’t have capacity for ad maintenance&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Managing ads and keywords is one of the most tedious and time-consuming tasks for marketers. The minute you add more channels into the mix, you &lt;em&gt;double &lt;/em&gt;(or triple, quadruple etc.) the work. So diversification takes much longer than expected, and most of the time, the anticipated performance uplift doesn’t reflect that increase in work, or justify it.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Fewer quality ad channels that you can actually &lt;strong&gt;maintain&lt;/strong&gt; will almost always outperform lots of poorly-maintained channels.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;5-you-dont-want-to-tackle-roas-variance-across-channels&quot;&gt;&lt;strong&gt;5. You don’t want to tackle ROAS variance across channels&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Different channels generate different results (obviously), and juggling all these results, understanding, and predicting them — all simultaneously — is a lot.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Having a clear understanding of your ROAS can be hard to predict for just one channel. For example, users coming from social media may be assigned a different ROAS target than users coming from high-intent keyword searches. That’s all well and good, &lt;em&gt;if &lt;/em&gt;you can keep an eye on those differences in behavior, track them over time, and predict what’s coming next.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;6-your-reporting-and-attribution-stack-isnt-ready&quot;&gt;&lt;strong&gt;6. Your reporting and attribution stack isn’t ready&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;More data sources means more attribution confusion, more measurement problems, and more time spent debugging dashboards than driving results.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Which channels are telling the truth? Which channels are attracting the highest-quality users? Which channels should you prioritize?&lt;/p&gt;



&lt;p&gt;If you’re spending less than $100k/month on ads, these are questions you want to avoid. But if you have multiple channels, you’re going to need to answer them. Consider whether the money and potential results compensate for that work.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;when-does-it-make-sense-to-diversify-your-ad-channels&quot;&gt;&lt;strong&gt;When does it make sense to diversify your ad channels?&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The way I like to approach ad budget diversification is by asking a simple question.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Will new ad channels make me make more money — and can I prove it?&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;You’re ready to diversify when the answer to each of these follow-on questions is ‘yes’:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Do I have the human capital (time and expertise) needed to make it work?&lt;/li&gt;



&lt;li&gt;Do I have enough &lt;strong&gt;extra&lt;/strong&gt; money to allocate to this risky test, without affecting my current user acquisition efforts?&lt;/li&gt;



&lt;li&gt;Do I know how I will measure the potential uplift in performance attributed to this new ad channel?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Think about it in these criteria:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;You have the people&lt;/strong&gt;: someone owns experimentation, creative testing, and optimization for the new channel&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;You have the budget&lt;/strong&gt;: enough to reach stable delivery without harming your existing winners&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;You have the measurement&lt;/strong&gt;: a clear attribution plan for identifying incremental lift (not just last-click noise)&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;If these aren’t true, diversification usually becomes an expensive distraction rather than a growth lever.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-6-tips-for-diversifying-ad-channels&quot;&gt;&lt;strong&gt;6 Tips for diversifying ad channels&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Before we get into some firsthand examples of how to choose and diversify ad channels, here are my top tips for increasing your ad channels. Keep in mind that these come from my own personal experience, so use them as proxies for your decision-making, rather than global rules.&amp;nbsp;&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;If your budget is under $100k/month, focus on nailing one social platform — I suggest starting with &lt;a href=&quot;https://www.revenuecat.com/blog/growth/7-meta-ad-testing-frameworks-for-subscription-apps/&quot;&gt;Meta Ads&lt;/a&gt; or TikTok Ads&lt;/li&gt;



&lt;li&gt;Keyword-based channels like &lt;a href=&quot;https://www.revenuecat.com/blog/growth/measure-apple-search-ads-campaigns/&quot;&gt;Apple Ads&lt;/a&gt; or &lt;a href=&quot;https://www.revenuecat.com/blog/growth/a-practical-guide-to-google-app-campaigns/&quot;&gt;Google Ads&lt;/a&gt; can be operated in parallel with social media channels, &lt;strong&gt;but not at scale&lt;/strong&gt; (especially Apple Ads)&lt;/li&gt;



&lt;li&gt;For gaming apps, Applovin is one of the biggest ad channels to start with, but the big con is you need to pay for an MMP to run it&lt;/li&gt;



&lt;li&gt;Never use the excuse of channel saturation if you are spending less than $100/month; to be blunt, this is not the reason why your performance sucks&lt;/li&gt;



&lt;li&gt;If you’re an indie developer or lack the resources to produce high-quality video content at scale, start with Google Ads’ search-to-app campaigns (you can use tools like Appstack to make it happen quickly and easily)&lt;/li&gt;



&lt;li&gt;Diversifying into ad channels that are not Meta, TikTok, Google, Snapchat, X, or Apple may expose you to potential ad fraud at scale — keep your money safe and avoid non-self-attributed networks (non-SAN)&lt;/li&gt;
&lt;/ol&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;real-life-examples-of-diversified-ad-channels&quot;&gt;&lt;strong&gt;Real-life examples of diversified ad channels&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Let’s look at how this works in the real world. The following examples show the actual outcomes of diversifying (or not diversifying) ad spend across different apps and budgets:&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;1-bible-app&quot;&gt;&lt;strong&gt;1. Bible app&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;I’ve recently been advising a Christian app that was spending more $500k+/month on Meta Ads. They clearly had the economic resources to hire someone else or test new ad channels, but the main reason they were able to scale to that level was that they nailed Meta Ads &lt;em&gt;first.&lt;/em&gt;&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;The primary way they did this was by optimizing ad network signaling, and leveraging strong testing capacity &lt;a href=&quot;https://www.notion.so/How-to-do-ad-creative-testing-for-your-mobile-app-campaigns-2a0b0f4dbf3d8017b86aee0c70cf80b6?pvs=21&quot;&gt;using the SVS framework&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;They also have a strong mindset of focusing on one thing, but doing it better than anyone else. This is an example of the benefits of not diversifying, which saw a startup of 15 people scale to millions in ARR.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;2-fintech-app&quot;&gt;&lt;strong&gt;2. Fintech app&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;When working at a fintech company, we had a monthly budget of around $100k/month which then doubled to $200k/month after we saw success expanding into a new ad channel.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;The reason this worked for us came from maximizing our existing channel’s success: we deployed the best-performing video ads from Meta Ads into TikTok Ads, and it resulted in significant numbers (positive ROAS).&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Luckily, I had the resources to get enough time and allocation to test the new TikTok channel, so it wasn’t a huge risk. But this is one tactic for exploring a new channel without putting everything on the line. I call it a &lt;em&gt;soft diversification test&lt;/em&gt;, limiting time and scope to a duplication strategy of your best-performing content, simply added to a new channel. Of course typically the best-performing content will be unique to each channel, but it’s a good proof of concept.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;3-photo-and-video-app&quot;&gt;&lt;strong&gt;3. Photo and video app&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Finally, I’ve recently consulted one of the biggest photo and video apps in the world (sorry, I can’t share the name!), who spend more than $3m/month. They’re highly diversified in channel, meaning even the biggest ad channels like Meta Ads and Google Ads only use 30% of their ad spend.&lt;/p&gt;



&lt;p&gt;The reason it’s working for them is simple. &lt;strong&gt;Scale&lt;/strong&gt;. They have the budget to have specialized people in each channel, with almost unlimited funds to test and scale as needed. This is obviously not always the case, and it’s a prime example of how much resource you need to expand without risk.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;However, the flip side of this case is that the wider user acquisition function was pretty inefficient: ROAS was higher than reported, people weren’t working that hard, and they had serious measurement issues to determine what was actually moving the needle. Despite huge budgets, there were still issues under the surface.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;so-should-you-invest-in-new-ad-channels&quot;&gt;&lt;strong&gt;So, should you invest in new ad channels?&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The correct answer to your question: “Should I diversify my marketing budget allocation?” will always be simple: &lt;strong&gt;it depends.&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;I know, it’s annoying. But it’s true. And if someone tells you the opposite, doubt them.&lt;/p&gt;



&lt;p&gt;To move from ‘it depends’ to a straightforward yes/no, keep these takeaways in mind:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Depth beats width below $100k/month:&lt;/strong&gt; if you’re spending less than $100k/month, master one channel before adding another. Deep optimization on Meta or TikTok will outperform shallow testing across multiple platforms.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Use the three-question test:&lt;/strong&gt; before diversifying, ask: Do I have the people? Do I have the budget? Do I know how to measure it? Three ‘yes’ answers mean go. Anything else means wait.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Creative production is the hidden bottleneck:&lt;/strong&gt; three channels mean three different video specs, three sets of copy guidelines, and three times the creative refresh cycles. Most teams can’t keep up.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Attribution gets messy fast:&lt;/strong&gt; each new channel adds another layer of measurement complexity. If you can’t clearly answer “Which channel drove this subscriber?”, then you’re not ready to add another one.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Context-switching kills performance:&lt;/strong&gt; a growth marketer splitting time across four dashboards will always lose to one marketer entirely focused on a single platform. Optimization requires deep immersion, not surface-level monitoring.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Kill fast when channels don’t work:&lt;/strong&gt; after 90 days, if ROAS is below your primary channel or the team is burning 20+ hours/week for less than x% of revenue, pull the plug and reallocate.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Perceived saturation isn’t absolute saturation:&lt;/strong&gt; if you haven’t tested 100+ creatives/month (at least), exhausted all audience segments, and spent at least six months optimizing, you haven’t hit saturation; you’ve hit a skill ceiling.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;So, that’s my whirlwind guide to diversifying your ad channels. I hope it helped guide your decision, and if in doubt, ask yourself those three questions. It’s helped me stay on track more times than I can count.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Context wins: the hidden third dimension of paywall targeting]]></title><description><![CDATA[How paywall timing can reduce friction and drive conversion]]></description><link>https://www.revenuecat.com/blog/growth/contextual-paywall-targeting/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/contextual-paywall-targeting/</guid><pubDate>Thu, 04 Dec 2025 13:38:51 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Context-wins_-the-hidden-third-dimension-of-paywall-targeting.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;When setting up your paywall targeting, how do you segment your audience? Naturally, you probably think about &lt;em&gt;who &lt;/em&gt;the user is, and what they’re doing before they hit that paywall. But there’s another layer that influences whether they click ‘subscribe’: &lt;strong&gt;context.&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Demographics say who, behavior says what, but context decides &lt;em&gt;when&lt;/em&gt;. A user on the move vs. on the couch has radically different intent when faced with a &lt;a href=&quot;https://www.revenuecat.com/customers/runna/&quot;&gt;Runna&lt;/a&gt; paywall.&lt;/p&gt;



&lt;p&gt;Context is a combination of timing, motion and mentality. It’s about &lt;em&gt;when &lt;/em&gt;a user is ready to commit. That timing shapes intent dramatically; the same person can feel ‘not now’ in one moment and ‘I’m ready’ a minute later, all depending on the &lt;strong&gt;context&lt;/strong&gt;.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;In a world where attention is shifting constantly, and &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps-2025/?#:~:text=82%25%20of%20trial%20starts%20occur%20the%20same%20day%20a%20user%20installs%20an%20app&quot;&gt;82% of trials start on day zero,&lt;/a&gt; showing the right message at the wrong moment may be the &lt;a href=&quot;https://www.revenuecat.com/blog/growth/fix-onboarding-funnels/&quot;&gt;biggest leak in your funnel&lt;/a&gt;.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Learn how to trigger paywalls in those precious milliseconds when attention and intent peaks, and you can turn ‘not now’ into ‘subscribe’.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-cost-of-mistimed-paywalls-and-the-limitations-of-traditional-paywall-optimization&quot;&gt;&lt;strong&gt;The cost of mistimed paywalls and the limitations of traditional paywall optimization&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Every day, millions of users encounter paywalls at the wrong moment. They’re rushing to catch a train, trying to focus in a noisy environment or simply not in the right headspace to evaluate a subscription. The result? Frustration, negative reviews and lost revenue (that most apps never measure).&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;That friction pushes people out of the funnel.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;To iron out that friction, you probably look to &lt;a href=&quot;https://www.revenuecat.com/blog/growth/offering-customization-examples-targeting/&quot;&gt;paywall optimization&lt;/a&gt;. Typically, paywall optimization means demographic filters, simple behavioral triggers and lots of A/B tests. But this 2018 playbook isn’t working anymore — the &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps-2025/?#:~:text=Download%20to%20Paid&quot;&gt;State of Subscription Apps report 2025&lt;/a&gt; reveals some striking gaps between average apps and top performers:&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Metric&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Median apps&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Top-performing apps&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Download-to-paid within 35 days&lt;/td&gt;&lt;td&gt;1.9%&lt;/td&gt;&lt;td&gt;4.6%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Trial-to-paid conversion rate&lt;/td&gt;&lt;td&gt;34.8%&lt;/td&gt;&lt;td&gt;51.5%&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;Much of that gap comes down to &lt;em&gt;when&lt;/em&gt; the paywall appears. Traditional optimization treats all day zero users identically; whether they’re commuting to work, lying in bed or sitting in a coffee shop. It’s ignoring the &lt;em&gt;when&lt;/em&gt;.&lt;/p&gt;



&lt;p&gt;So how do you serve users paywalls at the right time? &lt;strong&gt;Contextual targeting.&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;While &lt;a href=&quot;https://www.revenuecat.com/feature/targeting/&quot;&gt;paywall targeting&lt;/a&gt; allows you to customize your paywall and offerings to specific segments, adding &lt;em&gt;context &lt;/em&gt;lets you also customize to the users’ circumstance, surroundings, and behavior.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-a-third-dimension-for-targeting-the-user-s-context&quot;&gt;&lt;strong&gt;A third dimension for targeting: the user’s context&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Traditional paywall optimization relies on roughly five-10 data points, like time-since-install, features accessed, demographic info and basic usage patterns. This data barely scratches the surface of who your user is, what their life is like and how they interact with your app. You need &lt;strong&gt;context.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Your smartphone generates &lt;strong&gt;over 300 contextual signals&lt;/strong&gt; every second: motion data, how the user holds their phone, battery level, ambient light, connectivity status and dozens more.&lt;/p&gt;



&lt;p&gt;While human analysts can meaningfully process maybe three–four variables simultaneously when making targeting decisions, machine learning models can analyze all 300+ signals in real-time to identify the optimal moment for paywall display. Of course, context-aware machine learning doesn’t replace human intuition — it simply amplifies it, with real-time data that humans can’t process at the same scale.&lt;/p&gt;



&lt;p&gt;These additional context signals don’t replace demographic and behavioral targeting; they add a third dimension that can significantly enhance targeting effectiveness. A 25-year-old professional might be your ideal customer demographic, but their conversion likelihood varies dramatically based on whether they’re walking to a meeting whilst on a business call and 5% battery, or relaxing on the couch scrolling TikTok with their phone plugged in.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;576&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-1024x576.png&quot; alt=&quot;&quot; class=&quot;wp-image-48548&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-1024x576.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-300x169.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-768x432.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-1536x864.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-71x40.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-696x392.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-560x315.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-526x296.png 526w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-840x472.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-80x45.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-48x27.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Mobile gaming makes the impact of contextual targeting visible: immersion is fragile, time is valuable, and heavy-handed offers break flow. But by timing prompts to natural pauses, you can harness users’ engagement and meet them in context. One example is indie puzzle game Blackbox, who recorded a &lt;a href=&quot;https://contextsdk.com/case-studies/case-study-blackbox?utm_source=revenuecat&amp;amp;utm_medium=blog&amp;amp;utm_campaign=context-timing-paywalls-2025&amp;amp;utm_content=blackbox-link&quot;&gt;50% revenue increase during peak periods&lt;/a&gt; and a sustained conversion lift over subsequent months — gains achieved by changing &lt;em&gt;when&lt;/em&gt; paywalls appeared, not what they said.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-9-strategic-moves-to-improve-paywall-targeting-by-role&quot;&gt;&lt;strong&gt;9 strategic moves to improve paywall targeting (by role)&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Timing of your paywall influences downstream metrics like refunds and early churn. The performance gap between top apps (4.6% download-to-paid) and the median (1.9%) is not only about pricing or features, it’s about whether the prompt arrives &lt;strong&gt;when a user is receptive. &lt;/strong&gt;Used carefully, contextual timing can improve conversion and user satisfaction — the intent is &lt;strong&gt;not to show more paywalls, but to show them at better moments.&lt;/strong&gt;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-contextual-targeting-strategies-for-growth-teams&quot;&gt;&lt;strong&gt;Contextual targeting strategies for growth teams&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/build-app-growth-team/&quot;&gt;Growth teams&lt;/a&gt; live in a world of competing priorities: hit this quarter’s numbers, optimize long-term &lt;a href=&quot;https://www.revenuecat.com/glossary/#lifetime-value-ltv&quot;&gt;LTV&lt;/a&gt;, reduce &lt;a href=&quot;https://www.revenuecat.com/glossary/#ltv-cac-ratio&quot;&gt;CAC&lt;/a&gt; payback period and still find time to run meaningful experiments. Context-aware timing helps by improving the efficiency of the monetization funnel.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-1-rethink-a-b-testing-make-timing-the-variable&quot;&gt;&lt;strong&gt;1. Rethink A/B testing: make timing the variable&lt;/strong&gt;&lt;/h4&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/engineering/mobile-app-a-b-price-testing-guide/&quot;&gt;A/B tests&lt;/a&gt; on paywall placement take weeks, and often miss the real driver of lift. Shift focus to &lt;em&gt;when&lt;/em&gt; the prompt appears. Run smaller, parallel experiments across moments and segments, keep a true control, and judge outcomes on cohort LTV, refunds and early churn, not just day zero conversion.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-2-choose-the-right-plan-for-the-moment&quot;&gt;&lt;strong&gt;2. Choose the right plan for the moment&lt;/strong&gt;&lt;/h4&gt;



&lt;p&gt;The &lt;em&gt;State of Subscription Apps &lt;/em&gt;report 2025 shows one-year retention differs by plan type (about 44.1% annual vs. 17.0% monthly vs. 3.4% weekly). Why not match which plan users are served to their context?&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;In high-consideration contexts such as stationary, longer evening sessions with deeper engagement, present annual plans or even &lt;a href=&quot;https://www.revenuecat.com/blog/growth/lifetime-subscriptions/&quot;&gt;lifetime subscriptions&lt;/a&gt;. In brief, in-motion sessions, surface shorter options like weekly or monthly. Validate the mix with retention and refund behavior rather than first conversion alone.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-3-hold-back-to-capture-more&quot;&gt;&lt;strong&gt;3. Hold back to capture more&lt;/strong&gt;&lt;/h4&gt;



&lt;p&gt;This might seem counterintuitive, but one of the most powerful moves a &lt;a href=&quot;https://www.revenuecat.com/blog/growth/first-growth-hire-subscription-app/&quot;&gt;growth team &lt;/a&gt;can make is holding back monetization prompts. For example, Dating app Wizz found that cutting prompt volume by roughly 50%, while timing offers to receptive contexts, ended with an &lt;a href=&quot;https://contextsdk.com/case-studies/case-study-wizz?utm_source=revenuecat&amp;amp;utm_medium=blog&amp;amp;utm_campaign=context-timing-paywalls-2025&amp;amp;utm_content=wizz-link&quot;&gt;81% lift on the primary offer flow&lt;/a&gt;.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;The lesson is simple: suppress in low-intent states and reallocate to moments instead of increasing total exposures. Users will feel less interrupted and more in control, and cohorts in the experiment above reflected it, with LTV up by roughly 20%.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-contextual-targeting-strategies-for-product-managers&quot;&gt;&lt;strong&gt;Contextual targeting strategies for product managers&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Product managers own the whole experience. Every monetization choice trades off exploration versus interruption. Treat timing as part of the product, not just a rule, so you can protect flow and still capture intent.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-4-make-timing-part-of-the-ux&quot;&gt;&lt;strong&gt;4. Make timing part of the UX&lt;/strong&gt;&lt;/h4&gt;



&lt;p&gt;The best product experiences feel like they’re reading your mind; surfacing exactly what you need, exactly when you need it.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Instead of a single gate, context-aware apps let access and prompts adapt to the moment. One example could be a fitness app recognizing the difference between someone lying in bed in the evening versus someone on a jog. In the stationary moment, show a full upgrade view with plan details. In motion, allow the workout with a light ‘upgrade to save x%’ nudge. Same feature, different timing, less friction.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;576&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-1-1024x576.png&quot; alt=&quot;&quot; class=&quot;wp-image-48550&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-1-1024x576.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-1-300x169.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-1-768x432.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-1-1536x864.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-1-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-1-71x40.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-1-696x392.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-1-560x315.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-1-526x296.png 526w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-1-840x472.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-1-80x45.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-1-48x27.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/image-1.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-5-progressive-disclosure-that-respects-context&quot;&gt;&lt;strong&gt;5. Progressive disclosure that respects context&lt;/strong&gt;&lt;/h4&gt;



&lt;p&gt;Surface decisions when users have the attention to make them. Hold back in obvious low-consideration states (in Apple’s driving focus, during phone calls, or while abroad etc.) and follow up when the session lengthens, motion drops, or engagement deepens. You’re not showing fewer opportunities; you’re placing them where they fit.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-6-design-for-it-gets-me-moments&quot;&gt;&lt;strong&gt;6. Design for ‘it gets me’ moments&lt;/strong&gt;&lt;/h4&gt;



&lt;p&gt;The holy grail of product experience is creating moments where users think “This app just &lt;em&gt;gets&lt;/em&gt; me”. These moments build loyalty, drive word-of-mouth, and increase &lt;a href=&quot;http://revenuecat.com/blog/growth/what-is-lifetime-value-ltv-apps/&quot;&gt;lifetime value&lt;/a&gt;. For example, a meditation app that offers a five minute session at 7am during their morning routine, and a sleep track at 10pm when the user lies in bed, feels tuned to the user’s life. Like it just &lt;em&gt;fits&lt;/em&gt;.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;But time is only one signal: combine session depth, motion, battery and connectivity to decide when to ask and what to ask for. Over time, these small, well-timed choices build trust and make upgrade prompts feel like part of the experience rather than interruptions.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-contextual-targeting-strategies-for-tech-leadership&quot;&gt;&lt;strong&gt;Contextual targeting strategies for tech leadership&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Engineering leaders don’t just ask “Does this work?”, they ask “Is it reliable, can it scale and can we maintain it?”.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Context-aware targeting adds real value, but remember to evaluate new capabilities through multiple lenses: implementation complexity, maintenance burden, scalability, privacy implications and strategic alignment.&amp;nbsp;&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-7-use-existing-device-signals-and-minimize-prompts&quot;&gt;&lt;strong&gt;7. Use existing device signals and minimize prompts&lt;/strong&gt;&lt;/h4&gt;



&lt;p&gt;Many useful signals are available via standard APIs without new permission prompts: time of day, battery level, device orientation, network type, screen state.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Where a platform does require consent for certain motion or fitness data, respect that boundary and degrade gracefully. You can get meaningful context without expanding your permissions surface.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-8-on-device-inference-for-latency-cost-and-reliability&quot;&gt;&lt;strong&gt;8. On-device inference for latency, cost and reliability&lt;/strong&gt;&lt;/h4&gt;



&lt;p&gt;Running models on-device with Core ML or ML Kit keeps decisions close to the user. Latency drops to milliseconds, so timing can adapt within a session. Server costs are lower because phones do the work rather than a central service. Reliability improves because decisions do not depend on a network round trip and continue to work on WiFi, cellular or offline.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-9-decouple-releases-from-experiments&quot;&gt;&lt;strong&gt;9. Decouple releases from experiments&lt;/strong&gt;&lt;/h4&gt;



&lt;p&gt;Shipping timing changes through app releases create a bottleneck: engineering implementation, QA, review, store approval and adoption can turn a simple test into weeks.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Use remote configuration or paywall management to ship timing rules and model updates over-the-air, with rollback if metrics dip. This way underperforming models can be detected and corrected within 24 hours, without an app update. The effect is practical: product teams keep building core features, while monetization experiments iterate safely in configuration.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-beyond-intuition-context-is-standard&quot;&gt;&lt;strong&gt;Beyond intuition: context is standard&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The traditional approach of manual paywall optimization has reached its performance ceiling. When even the best-performing apps convert less than 5% of downloads to paid users, there’s enormous room for improvement — contextual intelligence could be the solution.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps-2025/?#:~:text=35%25%2B-,Subscriptions%20aren%E2%80%99t%20enough%20anymore%20%E2%80%93%2035%25%20of%20apps%20now%20mix,-subscriptions%20with%20consumables&quot;&gt;35% of apps now mix subscriptions with consumables&lt;/a&gt; and lifetime purchases, and AI apps already outperform other categories. The future of apps is &lt;strong&gt;hyper-personalization&lt;/strong&gt;, and the trajectory for paywall targeting is clear:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;2020–2022&lt;/strong&gt;: Basic A/B testing of paywall copy and placement&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;2023–2025&lt;/strong&gt;: Behavioral and demographic targeting&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;2026+&lt;/strong&gt;: Real-time, contextual optimization via machine learning&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;As hyper-personalization becomes standard, the success of paywall optimization shifts from &lt;em&gt;what&lt;/em&gt; you show to &lt;em&gt;when&lt;/em&gt; you show it. In a crowded mobile environment where sessions are short and acquisition costs are high, timing your paywall to match user intent matters more than tweaking the design or copy.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Google Play’s subscription with Add-ons: guide to multi-line subscriptions]]></title><description><![CDATA[Read on to explore what multi-line subscriptions are, discuss practical strategies for using them effectively, walk through the implementation details using the Play Billing Library directly.]]></description><link>https://www.revenuecat.com/blog/engineering/subscription-add-ons/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/subscription-add-ons/</guid><pubDate>Thu, 04 Dec 2025 00:17:43 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/Google-Plays-subscription-with-Add-ons_-guide-to-multi-line-subscriptions.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Subscription monetization on Android has evolved significantly over the years. With the introduction of base plans and offers in 2022, Google gave developers more flexibility in structuring their subscription products. Now, Google has taken another major step forward with &lt;strong&gt;Subscription with Add-ons&lt;/strong&gt;, also known as multi-line subscriptions or multi-product checkout for subscriptions. This feature allows developers to bundle multiple subscription products together into a single purchase, creating a more streamlined experience for both users and developers.&lt;/p&gt;



&lt;p&gt;Read on to explore what multi-line subscriptions are, discuss practical strategies for using them effectively, walk through the implementation details using the Play Billing Library directly, and finally examine how &lt;a href=&quot;https://www.revenuecat.com/&quot;&gt;RevenueCat&lt;/a&gt; can simplify the entire process.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-are-multi-line-subscriptions&quot;&gt;&lt;strong&gt;What are multi-line subscriptions?&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;At its core, Subscription with Add-ons is a feature that lets you bundle multiple subscription products together so they can be purchased, billed, and managed as a unified subscription. Rather than requiring users to make separate purchases for a base subscription and additional premium features, you can now offer everything in a single checkout flow.&lt;/p&gt;



&lt;p&gt;Consider a music streaming application that offers a base ‘Premium’ subscription. Previously, if you wanted to offer additional features like ‘HiFi Audio’ or ‘Offline Downloads’ as separate paid add-ons, users would need to purchase and manage each subscription independently. This meant multiple transactions, multiple renewal dates, and multiple entries in their subscription management screen. With Subscription with Add-ons, users can select the base Premium plan along with any combination of add-ons and complete a single purchase. They see one combined price, go through one checkout flow, and have everything synchronized to a single renewal date.&lt;/p&gt;



&lt;p&gt;The terminology can be a bit confusing at first. Google uses ‘Subscription with Add-ons’ as the official feature name, but you might also see it referred to as ‘multi-line subscriptions’ (referring to the multiple line items in a single purchase) or ‘multi-product checkout’ (emphasizing the checkout experience). These all refer to the same capability.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;how-the-bundle-works&quot;&gt;&lt;strong&gt;How the bundle works&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;When a user purchases a Subscription with Add-ons, the first item in the product list becomes the &lt;strong&gt;base item&lt;/strong&gt;, and all subsequent items are treated as &lt;strong&gt;add-ons&lt;/strong&gt;. This distinction is important because the base item determines certain behaviors for the entire bundle. For example, when the base subscription is canceled, all associated add-ons are automatically canceled as well. The add-ons cannot exist independently of the base subscription.&lt;/p&gt;



&lt;p&gt;Google Play handles the complexity of aligning billing cycles automatically. When a user adds a new add-on to an existing subscription, Google Play calculates a prorated charge to align the add-on’s renewal date with the base item. This means that after the initial prorated period, all items in the bundle renew together on the same date. Similarly, if a user removes an add-on, it continues to provide access until the end of its current billing period but will not renew.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;key-constraints-to-understand&quot;&gt;&lt;strong&gt;Key constraints to understand&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Before diving into implementation, there are several important constraints that shape how you can use this feature.&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;All items in a Subscription with Add-ons must have the same billing period. You &lt;strong&gt;cannot&lt;/strong&gt; combine an annual base subscription with monthly add-ons, or vice versa. If your base plan bills monthly, all add-ons must also bill monthly. This constraint exists because Google Play needs to synchronize renewal dates across all items.&lt;/li&gt;



&lt;li&gt;This feature is only available for auto-renewing subscriptions. Prepaid subscriptions, which have a fixed duration and do not automatically renew, cannot be used as the base item or as add-ons.&lt;/li&gt;



&lt;li&gt;There’s a maximum limit of 50 items in a single Subscription with Add-ons purchase. While most applications will never approach this limit, it is worth knowing if you are building a highly modular subscription system.&lt;/li&gt;



&lt;li&gt;This feature isn’t available in all regions. As of the current documentation, India and South Korea don’t support Subscription with Add-ons. You will need to provide alternative purchase flows for users in these regions.&lt;/li&gt;



&lt;li&gt;Finally, pausing and resuming subscriptions is not supported for subscriptions that have add-ons. If your application relies heavily on the pause feature, you will need to consider whether the benefits of add-ons outweigh this limitation.&lt;/li&gt;
&lt;/ol&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;strategies-for-using-multi-line-subscriptions&quot;&gt;&lt;strong&gt;Strategies for using multi-line subscriptions&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Understanding the mechanics is one thing, but knowing how to apply this feature effectively requires thinking through your monetization strategy. Let me share several approaches that can help you maximize the value of Subscription with Add-ons.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-modular-feature-strategy&quot;&gt;&lt;strong&gt;The modular feature strategy&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;One of the most straightforward applications is offering a modular subscription where users can customize their plan by selecting only the features they need. Instead of creating multiple pre-defined tiers (Basic, Standard, Premium), you create a base subscription and a menu of add-ons that users can mix and match.&lt;/p&gt;



&lt;p&gt;For example, a productivity application might offer a base subscription that includes core features like task management and basic collaboration. Add-ons could include advanced reporting, team management features, third-party integrations, or increased storage. Users who only need advanced reporting can add just that feature, while power users can add multiple add-ons. This approach can increase conversion rates because users feel they are paying only for what they actually need.&lt;/p&gt;



&lt;p&gt;The key to making this strategy work is ensuring your base subscription provides genuine value on its own. If the base feels stripped down or incomplete, users may perceive the add-ons as nickel-and-diming rather than genuine flexibility.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-premium-upgrade-strategy&quot;&gt;&lt;strong&gt;The premium upgrade strategy&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Another approach uses add-ons as a path to gradually upgrade users over time. You start users on a base subscription and then offer add-ons as upsells based on their usage patterns or at strategic moments in their journey.&lt;/p&gt;



&lt;p&gt;Consider a photo editing application where the base subscription includes standard editing tools. As users become more engaged, you can offer add-ons like professional presets, advanced retouching tools, or cloud storage for their edited photos. The advantage of using add-ons rather than a traditional tier upgrade is that users keep their existing features and simply add new capabilities. There is no perception of ‘losing’ their current plan.&lt;/p&gt;



&lt;p&gt;This strategy works particularly well when combined with personalized recommendations. By analyzing user behavior, you can surface relevant add-ons at moments when users are most likely to see value in them.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-bundle-and-save-strategy&quot;&gt;&lt;strong&gt;The bundle and save strategy&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;While Subscription with Add-ons allows individual selection of features, you can also use it to create attractive bundles. By setting prices strategically, you can make bundles of add-ons more appealing than purchasing items individually.&lt;/p&gt;



&lt;p&gt;For instance, if your base subscription is $9.99/month and you have three add-ons each priced at $4.99/month, you might offer all three add-ons as a bundle for $11.99/month instead of $14.97/month if purchased separately. Users who want multiple features get a better deal, and you increase your average revenue per user. The bundled price still provides more revenue than users who might only purchase one add-on.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;managing-complexity&quot;&gt;&lt;strong&gt;Managing complexity&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;One risk with add-ons is creating too much complexity. If users face a bewildering array of options, they may experience decision paralysis and abandon the purchase entirely. Consider limiting the number of add-ons to a manageable set, typically three to five options. Provide clear descriptions of what each add-on includes and who it is best suited for. You might also consider offering recommended bundles or a ‘select all’ option for users who want the complete experience.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;implementing-subscription-with-add-ons-without-revenuecat&quot;&gt;&lt;strong&gt;Implementing Subscription with Add-ons without RevenueCat&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Let us walk through how to implement Subscription with Add-ons using the Google Play Billing Library directly. This implementation requires Play Billing Library v5 or higher, though you should use the latest version (currently v8) to ensure access to all features and security updates.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;setting-up-your-products-in-google-play-console&quot;&gt;&lt;strong&gt;Setting up your products in Google Play Console&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Before writing any code, you need to configure your subscription products in the Google Play Console. The good news is that existing subscription products can be offered as add-ons without any special configuration. You do not need to create separate ‘add-on’ type products. Any auto-renewing subscription can serve as either a base item or an add-on.&lt;/p&gt;



&lt;p&gt;When creating your products, remember that all items you plan to bundle together must have matching billing periods. If you want to offer both monthly and annual options, you will need to create separate base plans for each billing period.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;querying-product-details&quot;&gt;&lt;strong&gt;Querying product details&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The first step in your implementation is querying the available products from Google Play. You use the &lt;code&gt;queryProductDetailsAsync&lt;/code&gt; method to fetch details for all the subscription products you want to offer.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZxG9e6 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;class BillingManager(private val context: Context) {\n    private lateinit var billingClient: BillingClient\n\n    private val productIds = listOf(\n        \&amp;quot;premium_base_monthly\&amp;quot;,\n        \&amp;quot;hifi_addon_monthly\&amp;quot;,\n        \&amp;quot;offline_addon_monthly\&amp;quot;,\n        \&amp;quot;family_addon_monthly\&amp;quot;\n    )\n\n    fun initialize() {\n        billingClient = BillingClient.newBuilder(context)\n            .setListener { billingResult, purchases -&gt;\n                handlePurchasesUpdated(billingResult, purchases)\n            }\n            .enablePendingPurchases()\n            .build()\n\n        billingClient.startConnection(object : BillingClientStateListener {\n            override fun onBillingSetupFinished(billingResult: BillingResult) {\n                if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {\n                    querySubscriptionProducts()\n                }\n            }\n\n            override fun onBillingServiceDisconnected() {\n\/\/ Implement retry logic here\n            }\n        })\n    }\n\n    private fun querySubscriptionProducts() {\n        val productList = productIds.map { productId -&gt;\n            QueryProductDetailsParams.Product.newBuilder()\n                .setProductId(productId)\n                .setProductType(BillingClient.ProductType.SUBS)\n                .build()\n        }\n\n        val params = QueryProductDetailsParams.newBuilder()\n            .setProductList(productList)\n            .build()\n\n        billingClient.queryProductDetailsAsync(params) { billingResult, productDetailsList -&gt;\n            if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {\n\/\/ Store product details for later use when launching purchase flow\n                handleProductDetails(productDetailsList)\n            }\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The query returns &lt;code&gt;ProductDetails&lt;/code&gt; objects for each subscription product. These objects contain all the information you need to display pricing to users and to launch the purchase flow, including the available base plans, offers, and their associated offer tokens.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;launching-the-purchase-flow-with-multiple-items&quot;&gt;&lt;strong&gt;Launching the purchase flow with multiple items&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;When a user selects their desired subscription configuration (base plus selected add-ons), you launch the billing flow with multiple &lt;code&gt;ProductDetailsParams&lt;/code&gt; objects. The critical detail here is that the first item in the list becomes the base item, so you must ensure your base subscription is added first.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1BLAJH wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;fun launchSubscriptionWithAddons(\n    activity: Activity,\n    baseProductDetails: ProductDetails,\n    baseOfferToken: String,\n    addonProductDetailsList: List&lt;Pair&lt;ProductDetails, String&gt;&gt;\n) {\n    val productDetailsParamsList = mutableListOf&lt;BillingFlowParams.ProductDetailsParams&gt;()\n\n\/\/ Add the base subscription first - this is crucialval baseParams = BillingFlowParams.ProductDetailsParams.newBuilder()\n        .setProductDetails(baseProductDetails)\n        .setOfferToken(baseOfferToken)\n        .build()\n    productDetailsParamsList.add(baseParams)\n\n\/\/ Add each selected add-onfor ((addonDetails, offerToken) in addonProductDetailsList) {\n        val addonParams = BillingFlowParams.ProductDetailsParams.newBuilder()\n            .setProductDetails(addonDetails)\n            .setOfferToken(offerToken)\n            .build()\n        productDetailsParamsList.add(addonParams)\n    }\n\n    val billingFlowParams = BillingFlowParams.newBuilder()\n        .setProductDetailsParamsList(productDetailsParamsList)\n        .build()\n\n    val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)\n\n    if (billingResult.responseCode != BillingClient.BillingResponseCode.OK) {\n\/\/ Handle error - perhaps show a message to the user\n        handleBillingError(billingResult)\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Each item in the list must be unique. You cannot include two &lt;code&gt;ProductDetailsParams&lt;/code&gt; objects with the same product ID. The offer token specifies which base plan or offer to use for that item, and you must provide a valid offer token obtained from the &lt;code&gt;ProductDetails.subscriptionOfferDetails()&lt;/code&gt; method.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;processing-the-purchase&quot;&gt;&lt;strong&gt;Processing the purchase&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;After the user completes the purchase flow, your &lt;code&gt;PurchasesUpdatedListener&lt;/code&gt; receives the result. Processing a Subscription with Add-ons is similar to processing a single subscription, with one key difference: the purchase grants entitlements for multiple items.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZonU0C wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;private fun handlePurchasesUpdated(\n    billingResult: BillingResult,\n    purchases: List&lt;Purchase&gt;?\n) {\n    when (billingResult.responseCode) {\n        BillingClient.BillingResponseCode.OK -&gt; {\n            purchases?.forEach { purchase -&gt;\n                processPurchase(purchase)\n            }\n        }\n        BillingClient.BillingResponseCode.USER_CANCELED -&gt; {\n\/\/ User canceled the purchase flow\n        }\n        else -&gt; {\n\/\/ Handle other error codes\n        }\n    }\n}\n\nprivate fun processPurchase(purchase: Purchase) {\n\/\/ For Subscription with Add-ons, getProducts() returns all product IDsval purchasedProductIds = purchase.products\n\n\/\/ Verify the purchase with your backend server\n    verifyPurchaseWithBackend(purchase) { isValid -&gt;\n        if (isValid) {\n\/\/ Grant entitlements for all purchased productsfor (productId in purchasedProductIds) {\n                grantEntitlement(productId)\n            }\n\n\/\/ Acknowledge the purchase if not already acknowledgedif (!purchase.isAcknowledged) {\n                acknowledgePurchase(purchase)\n            }\n        }\n    }\n}\n\nprivate fun acknowledgePurchase(purchase: Purchase) {\n    val params = AcknowledgePurchaseParams.newBuilder()\n        .setPurchaseToken(purchase.purchaseToken)\n        .build()\n\n    billingClient.acknowledgePurchase(params) { billingResult -&gt;\n        if (billingResult.responseCode != BillingClient.BillingResponseCode.OK) {\n\/\/ Handle acknowledgment failure\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;purchase.products&lt;/code&gt; property returns a list of all product IDs included in the purchase. You should grant entitlements for each product and verify the purchase with your backend server before doing so.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;modifying-an-existing-subscription-with-add-ons&quot;&gt;&lt;strong&gt;Modifying an existing Subscription with Add-ons&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Users may want to add more add-ons to their existing subscription or remove some they no longer need. When modifying an existing Subscription with Add-ons, you need to include the current purchase token and specify a replacement mode.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1ytq3j wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;fun modifySubscriptionAddons(\n    activity: Activity,\n    currentPurchaseToken: String,\n    baseProductDetails: ProductDetails,\n    baseOfferToken: String,\n    newAddonsList: List&lt;Pair&lt;ProductDetails, String&gt;&gt;\n) {\n    val productDetailsParamsList = mutableListOf&lt;BillingFlowParams.ProductDetailsParams&gt;()\n\n\/\/ Include the base subscription\n    productDetailsParamsList.add(\n        BillingFlowParams.ProductDetailsParams.newBuilder()\n            .setProductDetails(baseProductDetails)\n            .setOfferToken(baseOfferToken)\n            .build()\n    )\n\n\/\/ Include all add-ons (both existing ones to keep and new ones to add)for ((addonDetails, offerToken) in newAddonsList) {\n        productDetailsParamsList.add(\n            BillingFlowParams.ProductDetailsParams.newBuilder()\n                .setProductDetails(addonDetails)\n                .setOfferToken(offerToken)\n                .build()\n        )\n    }\n\n\/\/ Configure the subscription updateval subscriptionUpdateParams = BillingFlowParams.SubscriptionUpdateParams.newBuilder()\n        .setOldPurchaseToken(currentPurchaseToken)\n        .setSubscriptionReplacementMode(\n            BillingFlowParams.SubscriptionUpdateParams.ReplacementMode.CHARGE_PRORATED_PRICE\n        )\n        .build()\n\n    val billingFlowParams = BillingFlowParams.newBuilder()\n        .setProductDetailsParamsList(productDetailsParamsList)\n        .setSubscriptionUpdateParams(subscriptionUpdateParams)\n        .build()\n\n    billingClient.launchBillingFlow(activity, billingFlowParams)\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;When modifying a subscription, you must include all items that should remain active after the modification. If you want to keep the base subscription and an existing add-on while adding a new add-on, all three must be in the product list. If you omit an existing add-on from the list, it will be removed.&lt;/p&gt;



&lt;p&gt;The replacement mode determines how Google Play handles the billing transition. &lt;code&gt;CHARGE_PRORATED_PRICE&lt;/code&gt; calculates a prorated charge for new items to align their renewal with the base subscription. Other modes like &lt;code&gt;CHARGE_FULL_PRICE&lt;/code&gt; or &lt;code&gt;WITHOUT_PRORATION&lt;/code&gt; are available depending on your use case.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;server-side-verification-and-real-time-notifications&quot;&gt;&lt;strong&gt;Server-side verification and real-time notifications&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;For production applications, you must verify purchases on your backend server and handle Real-Time Developer Notifications (RTDN) to keep your entitlement records synchronized with Google Play.&lt;/p&gt;



&lt;p&gt;One important detail for Subscription with Add-ons: the &lt;code&gt;subscriptionId&lt;/code&gt; field is not provided in RTDN messages for multi-item purchases because there are multiple subscriptions involved. Instead, you should use the &lt;code&gt;purchaseToken&lt;/code&gt; from the notification to query the Google Play Developer API and retrieve the full list of entitled items.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z2m82o3 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/\/ This is for your backend serverfun handleRealTimeNotification(notification: DeveloperNotification) {\n    val purchaseToken = notification.subscriptionNotification.purchaseToken\n\n\/\/ Query the Google Play Developer API for full purchase detailsval subscriptionPurchase = playDeveloperApi\n        .purchases()\n        .subscriptionsv2()\n        .get(packageName, purchaseToken)\n        .execute()\n\n\/\/ The lineItems field contains all items in the subscriptionval lineItems = subscriptionPurchase.lineItems\n\n    for (item in lineItems) {\n        val productId = item.productId\n        val expiryTime = item.expiryTime\n        val autoRenewingPlan = item.autoRenewingPlan\n\n\/\/ Update your entitlement database based on each item&apos;s status\n        updateEntitlement(purchaseToken, productId, expiryTime, autoRenewingPlan)\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;lineItems&lt;/code&gt; list in the API response contains details for each subscription item, including its product ID, expiration time, and renewal status. This allows you to track entitlements for each component of the subscription bundle independently.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;handling-edge-cases&quot;&gt;&lt;strong&gt;Handling edge cases&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Several edge cases require special attention when implementing Subscription with Add-ons.&lt;/p&gt;



&lt;p&gt;Grace periods and account holds apply to the entire subscription bundle. If a renewal payment fails, all items enter the recovery period together, regardless of which specific items were involved in the failed renewal. The grace period duration is determined by the item with the minimum grace period setting among all active items.&lt;/p&gt;



&lt;p&gt;Refunds and revocation, interestingly, can be handled at the item level. Using the Google Play Developer API, you can revoke individual items without affecting the entire subscription. This is useful if a user requests a refund for a specific add-on while wanting to keep their base subscription.&lt;/p&gt;



&lt;p&gt;Price changes follow similar rules as single-item subscriptions, but with additional complexity when multiple items have pending price increases. All outstanding opt-in price increases must result in the same renewal time with the new price. If an item has a pending opt-in price increase that the user has not confirmed, new price increases for other items in the bundle may be ignored unless they align.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;simplifying-implementation-with-revenuecat&quot;&gt;&lt;strong&gt;Simplifying Implementation with RevenueCat&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;While implementing Subscription with Add-ons directly with the Play Billing Library gives you complete control, it also requires managing significant complexity, and time resources (this is a thing) as well. You need to handle billing client lifecycle, query caching, purchase verification, entitlement management, real-time notifications, and all the edge cases we discussed. This is where RevenueCat provides substantial value.&lt;/p&gt;



&lt;p&gt;RevenueCat abstracts away the complexities of the Play Billing Library and provides a unified API for managing subscriptions across platforms. For Subscription with Add-ons specifically, RevenueCat handles the intricacies of multi-item purchases, entitlement tracking, and server-side verification automatically.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;configuring-products-in-revenuecat&quot;&gt;&lt;strong&gt;Configuring Products in RevenueCat&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;In RevenueCat, you configure your subscription products in the dashboard by creating &lt;strong&gt;Products&lt;/strong&gt; and organizing them into &lt;a href=&quot;https://www.revenuecat.com/docs/offerings/overview&quot;&gt;Offerings&lt;/a&gt;. Each Google Play subscription product ID maps to a RevenueCat Product, and you can group related products into Offerings that represent your subscription tiers or bundles.&lt;/p&gt;



&lt;p&gt;For Subscription with Add-ons, you would create separate products for your base subscription and each add-on. RevenueCat’s entitlement system then allows you to map these products to specific features in your app. When a user makes a purchase, RevenueCat automatically tracks which entitlements they have based on their active subscriptions.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;simplified-purchase-flow&quot;&gt;&lt;strong&gt;Simplified Purchase Flow&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;With RevenueCat, launching a purchase and handling the result is significantly simpler. The SDK manages the billing client connection, purchase verification, and entitlement updates.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZKli43 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;class SubscriptionManager(private val context: Context) {\n\n    fun initialize() {\n        Purchases.configure(\n            PurchasesConfiguration.Builder(context, \&amp;quot;your_revenuecat_api_key\&amp;quot;)\n                .build()\n        )\n    }\n\n    suspend fun getAvailableOfferings(): Offerings {\n        return Purchases.sharedInstance.awaitOfferings()\n    }\n\n    suspend fun purchaseSubscriptionWithAddons(\n        activity: Activity,\n        basePackage: Package,\n        addonPackages: List&lt;Package&gt;\n    ) {\n\/\/ RevenueCat handles the complexity of bundling these into a single purchaseval purchaseParams = PurchaseParams.Builder(activity, basePackage)\n            .build()\n\n        try {\n            val (transaction, customerInfo) = Purchases.sharedInstance\n                .awaitPurchase(purchaseParams)\n\n\/\/ CustomerInfo automatically reflects all active entitlements\n            updateUIWithEntitlements(customerInfo)\n        } catch (e: PurchasesException) {\n            handlePurchaseError(e)\n        }\n    }\n\n    fun checkEntitlements() {\n        Purchases.sharedInstance.getCustomerInfoWith { customerInfo -&gt;\n\/\/ Check which entitlements are activeval hasPremium = customerInfo.entitlements[\&amp;quot;premium\&amp;quot;]?.isActive == true\n            val hasHiFi = customerInfo.entitlements[\&amp;quot;hifi\&amp;quot;]?.isActive == true\n            val hasOffline = customerInfo.entitlements[\&amp;quot;offline\&amp;quot;]?.isActive == true\n\n            updateFeatureAccess(hasPremium, hasHiFi, hasOffline)\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;That’s all! Sounds easy? RevenueCat’s &lt;code&gt;CustomerInfo&lt;/code&gt; object provides a real-time view of the user’s active entitlements across all their purchases. You do not need to manually track which products map to which features or handle the complexity of multi-item purchases. The SDK and RevenueCat’s backend handle purchase verification, receipt validation, and entitlement calculation automatically.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;cross-platform-consistency&quot;&gt;&lt;strong&gt;Cross-platform consistency&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;One of RevenueCat’s strongest advantages is providing a consistent API across Android, iOS, and other platforms. If your application is available on multiple platforms, RevenueCat ensures that users have a unified subscription experience. A user who subscribes on Android and later switches to iOS will have their entitlements recognized automatically.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;analytics-and-insights&quot;&gt;&lt;strong&gt;Analytics and Insights&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;RevenueCat’s dashboard provides detailed analytics about your subscription performance, including metrics specific to subscription bundles. You can track which add-on combinations are most popular, monitor conversion rates for different offerings, and identify opportunities to optimize your pricing strategy.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;webhooks-and-server-integration&quot;&gt;&lt;strong&gt;Webhooks and server integration&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;For applications that need server-side awareness of subscription status, RevenueCat provides webhooks that notify your server of subscription events. These webhooks are simpler to work with than Google Play’s RTDN because RevenueCat normalizes the data and handles the complexity of multi-item purchases.For detailed implementation guidance, refer to the &lt;a href=&quot;https://www.revenuecat.com/docs/getting-started/entitlements/android-products&quot;&gt;RevenueCat documentation for Google Play products&lt;/a&gt; and the &lt;a href=&quot;https://www.revenuecat.com/docs/subscription-guidance/managing-subscriptions&quot;&gt;subscription management guide&lt;/a&gt;.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;wrapping-up&quot;&gt;&lt;strong&gt;Wrapping up&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Subscription with add-ons gives us values in how Android developers can structure their subscription offerings. By enabling multi-item purchases with synchronized billing, Google has opened new possibilities for flexible, user-friendly monetization strategies. Whether you choose to offer modular subscriptions where users customize their plan, use add-ons as an upgrade path for engaged users, or create attractive bundles that increase average revenue per user, this feature provides the tools to implement your vision.&lt;/p&gt;



&lt;p&gt;Implementing this feature directly with the Play Billing Library requires careful attention to product configuration, purchase flow management, and edge case handling. The code examples in this article provide a foundation, but production implementations will need additional error handling, retry logic, and thorough testing.&lt;/p&gt;



&lt;p&gt;For teams that want to move faster or need cross-platform support, RevenueCat offers a compelling alternative that abstracts away much of this complexity while providing additional benefits like unified analytics and simplified server integration.&lt;/p&gt;



&lt;p&gt;As you plan your implementation, start by clearly defining your monetization strategy. Understand which features should be in your base subscription versus add-ons, ensure your billing periods align, and consider how you will communicate the value of each option to users. With thoughtful planning and solid implementation, Subscription with Add-ons can help you create a subscription experience that serves both your users and your business goals.For the complete official documentation on this feature, visit the &lt;a href=&quot;https://developer.android.com/google/play/billing/subscription-with-addons&quot;&gt;Android Developers guide for Subscription with Add-ons&lt;/a&gt;, and &lt;a href=&quot;https://www.revenuecat.com/docs/offerings/overview&quot;&gt;RevenueCat Offerings&lt;/a&gt;.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[How Shotsy became the go-to app for GLP-1 tracking]]></title><description><![CDATA[Aja Beckett created Shotsy, the go-to mobile app for GLP-1 medication tracking. She turned her personal health journey into a product loved by thousands, focusing on authenticity, user-first design, and a mission to empower people on similar paths.]]></description><link>https://www.revenuecat.com/blog/growth/aja-beckett-shotsy-launched-podcast-2025/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/aja-beckett-shotsy-launched-podcast-2025/</guid><pubDate>Wed, 03 Dec 2025 14:05:28 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/RC-Launched-Blog-Cover-Aja-Beckett-1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Before building one of the most trusted tools for people on GLP-1 medications, Aja Beckett was navigating a string of indie app experiments. Each had promise, but none found traction until she started building for herself. As she began taking GLP-1s, the need for a better tracking tool became impossible to ignore.&lt;/p&gt;



&lt;p&gt;On this episode of &lt;em&gt;Launched&lt;/em&gt;, Aja shares how a personal need sparked a product that quickly became a movement within one of the fastest-growing health categories on the App Store.&lt;/p&gt;



&lt;iframe loading=&quot;lazy&quot; width=&quot;100%&quot; height=&quot;180&quot; frameborder=&quot;no&quot; scrolling=&quot;no&quot; seamless=&quot;&quot; src=&quot;https://share.transistor.fm/e/b0352f31?color=FFFFFF&amp;amp;background=30343C&quot;&gt;&lt;/iframe&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;The Smart Business Model Behind this GLP‑1 Tracking App — Aja Beckett, Shotsy&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/553qajdB_HU?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-authenticity-before-anything-else&quot;&gt;&lt;strong&gt;Authenticity before anything else&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Unlike past projects, Shotsy didn’t chase trends or solve a generic need. Aja built the app as a direct response to her own health experience, which meant she understood what mattered. Tracking doses, navigating side effects, and making better decisions with her doctor were non-negotiables. &lt;em&gt;“All the important stuff is free,”&lt;/em&gt; she says, reflecting a values-first approach that still drives the roadmap.&lt;/p&gt;



&lt;p&gt;The result was a product that users shared, screenshotted, and asked for by name. And so, there was an apparent demand.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-start-small-stay-smart&quot;&gt;&lt;strong&gt;Start small, stay smart&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Even before launch, traction showed up in the form of spreadsheet threads, subreddit buzz, and beta testers who filled up in minutes. Instead of raising money right away or launching everywhere at once, Aja focused on building what people needed most. That included refining her ASO strategy, staying focused on App Store search, and delivering value from day one.&lt;/p&gt;



&lt;p&gt;Her seventh app, Shotsy, became the one that stuck, not because it was the flashiest but because it met people exactly where they were. Users weren’t looking for a “weight loss app.”&amp;nbsp;&lt;/p&gt;



&lt;p&gt;They were seeking support for a profoundly personal journey.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-building-trust-not-virality&quot;&gt;&lt;strong&gt;Building trust, not virality&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Aja didn’t set out to build a social loop, but her users made one anyway. Screenshots of Shotsy’s colorful charts began showing up across communities, sparking word-of-mouth growth. She hasn’t spent a dollar on ads. Instead, she’s reinvested in features that help users feel supported and stay consistent.&lt;em&gt; “You can use it for free forever,”&lt;/em&gt; she explains, with premium features designed more as thank-you bonuses than locked essentials.&lt;/p&gt;



&lt;p&gt;Later, Aja raised a small pre-seed round to protect what she’d already built. As competitors emerged, her goal was to keep the most trusted app in the hands of those who needed it most.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-conclusion&quot;&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;From a solo side project to a breakout health product, Shotsy’s story is a masterclass in building with empathy. If you’re working on something personal, this episode is a reminder of what can happen when you listen closely, stay real, and let your users lead the way.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[UGC ads aren’t dead, they just evolved (and your app’s LTV depends on it)]]></title><description><![CDATA[The rise of feed-native, value-first ad creatives]]></description><link>https://www.revenuecat.com/blog/growth/ugc-ads-apps/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/ugc-ads-apps/</guid><pubDate>Tue, 02 Dec 2025 14:34:09 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/12/User-generated-content.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Old-school user-generated content (UGC) just isn’t hitting like it used to. Those scripted testimonials, faux-enthusiasm demos and influencer ads that used to do wonders for referrals? Users now see right through them. But what’s replacing them isn’t some glossy brand campaign; it’s a new wave of performance creative that actually &lt;em&gt;feels &lt;/em&gt;authentic.&lt;/p&gt;



&lt;p&gt;I’m talking UGC-style performance creative: content that actually fits into people’s feeds, entertains or teaches &lt;em&gt;first&lt;/em&gt;,&lt;em&gt; &lt;/em&gt;and builds real trust.&lt;/p&gt;



&lt;p&gt;Apps that nail this UGC-style approach aren’t just getting clicks, they’re building a trusting community that compounds results: lower acquisition costs, better subscribers, and way longer retention.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-when-authentic-ugc-stopped-working&quot;&gt;&lt;strong&gt;When ‘authentic’ UGC stopped working&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;In the last year, many subscription apps saw their ‘authentic’ testimonials tank. Those ring-light videos with polished lines that used to crush? We watched as cost-per-trial skyrocketed, and &lt;a href=&quot;https://www.revenuecat.com/glossary/#trial-conversion-rate&quot;&gt;trial-to-paid conversions&lt;/a&gt; fell off a cliff. Formats that absolutely killed it in 2020–2021 were now destroying unit economics. &lt;strong&gt;So what’s changed?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;When UGC first blew up around 2019, it worked because it felt different: shaky iPhone footage, unscripted testimonials, real experiences. It was raw and caught you off guard. But success breeds copycats. Pretty soon, the testimonial format became a formula:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Ring-light testimonials: &lt;em&gt;“I literally can’t live without this app”&lt;/em&gt;&lt;/li&gt;



&lt;li&gt;Robotic feature walkthroughs with forced enthusiasm&lt;/li&gt;



&lt;li&gt;Influencers clearly reading off a script&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The data tells the story:&lt;a href=&quot;https://www.appsflyer.com/resources/reports/creative-optimization-report/&quot;&gt; AppsFlyer’s 2025 Creative Optimization Report&lt;/a&gt; analyzed 1.1 million creative variations across $2.4B in ad spend, and found a massive gap between what gets funded and what actually performs. &lt;/p&gt;



&lt;p&gt;For example, when advertising for social media apps, creatives like tutorials and app reviews generate 45% higher IPM (installs per thousand impressions) and 17% better day seven retention compared to testimonials, yet testimonials still capture the majority of budgets.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Why the disconnect?&lt;/strong&gt; Because most teams are still funding yesterday’s playbook. Testimonials are familiar, easy to produce, and historically worked. But user behavior has shifted, and &lt;a href=&quot;https://www.revenuecat.com/blog/growth/creative-fatigue-mobile-apps-roas/&quot;&gt;creative fatigue&lt;/a&gt; is real. Today, they see right through those testimonials.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;People learned to scroll right past, conversions dropped, churn spiked, and the impact on our metrics was brutal. This version of UGC wasn’t just ineffective, it was actively killing our unit economics.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-shift-from-fake-ugc-to-authenticity&quot;&gt;&lt;strong&gt;The shift from ‘fake UGC’ to authenticity&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The smartest growth teams didn’t ditch UGC altogether. They asked a better question:&lt;/p&gt;



&lt;p&gt;&lt;em&gt;What if the problem isn’t user-generated content itself, but content that FEELS generated (staged, formulaic, lifeless) instead of genuinely useful?&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;That’s what led us to focus on UGC-style performance creative. This approach prioritizes value for users first, and selling second. It’s simple: if users feel like they’re being sold to, they scroll. If they see genuinely useful or interesting content that features an app, they click. Our UGC-style creative doesn’t announce itself as an ad. It blends into the feed, entertains, educates, or surprises, while naturally showing what the product does.&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Old UGC = interruption marketing disguised as authenticity&lt;/li&gt;



&lt;li&gt;Our approach = value-first content that earns attention&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Think of it like the difference between a jingle you skip and a Netflix scene you actually want to rewatch.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-why-this-economic-model-compounds&quot;&gt;&lt;strong&gt;Why this economic model compounds&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Old UGC optimized for one metric: the click. This new approach optimizes for the entire journey, creating two compounding loops:&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-1-the-paid-performance-loop-how-views-convert-to-ltv&quot;&gt;&lt;strong&gt;1. The paid performance loop (how views convert to LTV)&lt;/strong&gt;&lt;/h4&gt;



&lt;p&gt;This starts by earning the view. An ad that feels authentic and adds value isn’t skipped. This builds trust &lt;em&gt;before&lt;/em&gt; the click, leading to a higher-quality click and better install conversion on the App Store.&lt;/p&gt;



&lt;p&gt;This immediately lowers the cost-per-trial/&lt;a href=&quot;https://www.revenuecat.com/glossary/#customer-acquisition-cost-cac&quot;&gt;customer acquisition cost (CAC)&lt;/a&gt;. And because the ad set clear expectations, the user sticks around, leading directly to higher trial-to-paid conversion and longer-term retention and &lt;a href=&quot;https://www.revenuecat.com/glossary/#lifetime-value-ltv&quot;&gt;lifetime value (LTV)&lt;/a&gt;.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-2-the-organic-trust-loop-non-paid-value&quot;&gt;&lt;strong&gt;2. The organic trust loop (‘non-paid’ value)&lt;/strong&gt;&lt;/h4&gt;



&lt;p&gt;When the content is genuinely good (by being entertaining or educational), it also gets organic shares, saves, and comments. This builds social proof and brand trust at no extra cost. This organic loop then feeds back into the paid loop, making &lt;em&gt;all&lt;/em&gt; our ads perform better and &lt;a href=&quot;https://www.revenuecat.com/blog/growth/meta-ads-cac-creative-testing/&quot;&gt;lowering our blended CAC&lt;/a&gt; even further.&lt;/p&gt;



&lt;p&gt;In short, the economics improve &lt;em&gt;across the entire funnel&lt;/em&gt;, not just at the top.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-when-old-aka-formulaic-ugc-still-works&quot;&gt;&lt;strong&gt;When old (aka formulaic) UGC still works&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Traditional testimonial-style UGC isn’t completely dead. Users don’t have creator fatigue, they have &lt;em&gt;format&lt;/em&gt; fatigue. The perfectly-filmed, polished editing, scripted-with-keywords format can still work when that format is what conveys most value to the user.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;This format can still work for:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Utility apps with instant value (parking, weather)&lt;/li&gt;



&lt;li&gt;Emerging categories where education isn’t needed yet&lt;/li&gt;



&lt;li&gt;Viral features that genuinely surprise users&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;But honestly? These cases are getting rare. For most subscription apps, this new, authentic approach is now table stakes.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-four-performance-formats-that-actually-move-metrics&quot;&gt;&lt;strong&gt;Four performance formats that actually move metrics&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;So, we know outdated UGC isn’t converting. But what does this new UGC-style performance creative actually &lt;em&gt;look &lt;/em&gt;like?&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Well, from thousands of &lt;a href=&quot;https://www.revenuecat.com/blog/growth/overanalyze-creative-analysis-paid-ads/&quot;&gt;creatives tested&lt;/a&gt; across subscription apps in 2023–2025, these are the formats we’ve found that consistently outperform traditional testimonials. What do they have in common? They educate, entertain, or build curiosity first, rather than just saying “trust me, this app is great”.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-expert-commentary-the-podcast-clip&quot;&gt;&lt;strong&gt;1: Expert commentary: the ‘podcast clip’&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;For apps that require trust or behavior change, this format mimics a ‘hot take’ from a podcast. It feels like high-value advice, not a sales pitch.&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Example: &lt;/strong&gt;&amp;nbsp;Jumpspeak, a language learning app&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Creative:&lt;/strong&gt; Visually, it looks exactly like a clip from a high-production podcast (mics, studio lighting, multiple angles). An authoritative ‘expert’ guest argues that popular language learning apps are just ‘passive learning’ that make you feel productive but fail in real life situations.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;The pitch:&lt;/strong&gt; The ‘expert’ anchors the value of Jumpspeak against a $60/hour private tutor, and positions it as a scientifically-backed alternative, stating: “Immersion activates 85% more neural pathways”.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Why it works:&lt;/strong&gt; It appeals to logic and authority. By citing the National Training Labs and using specific stats, it bypasses the user’s ‘sales filter’ and builds trust.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;



&lt;figure class=&quot;wp-block-embed is-type-wp-embed is-provider-wistia-inc wp-block-embed-wistia-inc&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; class=&quot;wp-embedded-content&quot; sandbox=&quot;allow-scripts&quot; security=&quot;restricted&quot; title=&quot;UGC example: Jumpspeak Video&quot; src=&quot;https://fast.wistia.net/embed/iframe/c33esylicn?dnt=1#?secret=CfZVg0vCyj&quot; data-secret=&quot;CfZVg0vCyj&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; width=&quot;422&quot; height=&quot;750&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;&lt;em&gt;Source: &lt;a href=&quot;https://www.facebook.com/ads/library/?active_status=active&amp;amp;ad_type=all&amp;amp;country=GB&amp;amp;id=711511728238667&amp;amp;is_targeted_country=false&amp;amp;media_type=all&amp;amp;search_type=page&amp;amp;view_all_page_id=103581851453799&quot;&gt;Jumpspeak Meta Ads Library&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-scenario-based-skits-sell-problems-not-features&quot;&gt;&lt;strong&gt;2: Scenario-based skits: sell problems, not features&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Instead of stiff testimonials, skits dramatize relatable struggles and show the app as the natural solution.&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Example:&lt;/strong&gt; Mojo, a video editing app&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;The creative:&lt;/strong&gt; It dramatizes the frustration of slow, manual editing software, then uses a second character to mock this old way before revealing the app’s ‘Auto Edit’ feature as the magical solution.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Why it works:&lt;/strong&gt; People don’t buy features. They buy scenarios they recognize themselves in and the &lt;a href=&quot;https://www.revenuecat.com/blog/growth/solve-app-problems-emotionally/&quot;&gt;emotion that comes with a solved problem&lt;/a&gt;.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;



&lt;figure class=&quot;wp-block-embed is-type-wp-embed is-provider-wistia-inc wp-block-embed-wistia-inc&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; class=&quot;wp-embedded-content&quot; sandbox=&quot;allow-scripts&quot; security=&quot;restricted&quot; title=&quot;UGC example: Mojo Video&quot; src=&quot;https://fast.wistia.net/embed/iframe/y88ox01ac5?dnt=1#?secret=ijtaC5QffF&quot; data-secret=&quot;ijtaC5QffF&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; width=&quot;422&quot; height=&quot;750&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-viral-surprise-the-pattern-interrupt-nbsp&quot;&gt;&lt;strong&gt;3: Viral surprise: the ‘pattern interrupt’&amp;nbsp;&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;This format relies on a plot twist. It starts as a piece of viral entertainment (a fight, a public moment, a POV) and surprises the viewer by pivoting into the product.&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Example:&lt;/strong&gt; Muzz, a Muslim dating app&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;The creative:&lt;/strong&gt; A POV-style video with subtitles: ‘POV: A hijabi hit your car’. It opens with high tension: a man getting out of his car after an accident to confront another driver (the POV), before starting to flirt with her, attempting to turn the car crash into a meet-cute. She shuts him down, but…&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;The twist:&lt;/strong&gt; The person recording breaks the tension by saying, “Listen, if you want to get married so bad, just download Muzz”, then dropping social proof: “more than 600k couples met on Muzz”.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Why it works:&lt;/strong&gt; It captures attention and catches the viewer off guard. They watch because they want to see the outcome of the car crash (the drama), then the brand message arrives as a plot twist rather than a sales pitch.&lt;/li&gt;
&lt;/ul&gt;



&lt;figure class=&quot;wp-block-embed is-type-wp-embed is-provider-wistia-inc wp-block-embed-wistia-inc&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; class=&quot;wp-embedded-content&quot; sandbox=&quot;allow-scripts&quot; security=&quot;restricted&quot; title=&quot;UGC content example: Muzz Video&quot; src=&quot;https://fast.wistia.net/embed/iframe/d7tb7xshk0?dnt=1#?secret=mjsHTSrwCL&quot; data-secret=&quot;mjsHTSrwCL&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; width=&quot;422&quot; height=&quot;750&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;&lt;em&gt;Source: &lt;a href=&quot;https://www.facebook.com/ads/library/?active_status=active&amp;amp;ad_type=all&amp;amp;country=GB&amp;amp;id=24632372939798404&amp;amp;is_targeted_country=false&amp;amp;media_type=all&amp;amp;search_type=page&amp;amp;view_all_page_id=104459332127204&quot;&gt;Muzz Meta Ads Library&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-4-street-interview-the-credibility-hook&quot;&gt;&lt;strong&gt;4: Street interview: the credibility hook&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;This format isn’t just about ‘asking strangers questions’, it’s about confrontation. It creates a micro-moment of truth where the participant (and the viewer) admits to a struggle, creating the perfect opening for the product.&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Example:&lt;/strong&gt; Gronda, a cooking app&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;The creative:&lt;/strong&gt; The interviewer approaches strangers with a simple challenge: “Rate your cooking level from 1 to 10”. Interviewees admit the truth, one girl says “3”, another admits he’s a “toast chef”. This builds instant relatability.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;The pitch: &lt;/strong&gt;The interviewer doesn’t just talk about the app; he shows the phone screen with Gronda’s masterclass in plating. We see the interviewees go from self-doubting to impressed: “Wait, that makes it look so easy”.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Why it works:&lt;/strong&gt; It capitalizes on relatability, social proof, and anchors the viewer in their current state (bad cook) then uses the app to bridge the gap to their desired state (pro chef). It validates the viewer’s insecurity and immediately solves it.&lt;/li&gt;
&lt;/ul&gt;



&lt;figure class=&quot;wp-block-embed is-type-wp-embed is-provider-wistia-inc wp-block-embed-wistia-inc&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; class=&quot;wp-embedded-content&quot; sandbox=&quot;allow-scripts&quot; security=&quot;restricted&quot; title=&quot;UGC example: Gronda Video&quot; src=&quot;https://fast.wistia.net/embed/iframe/2n24va55es?dnt=1#?secret=dnOfteEei8&quot; data-secret=&quot;dnOfteEei8&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; width=&quot;422&quot; height=&quot;750&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-which-creative-format-should-you-use-for-each-platform&quot;&gt;&lt;strong&gt;Which creative format should you use for each platform?&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Which format you go for depends on the social channel you’re using. &lt;a href=&quot;https://www.appsflyer.com/resources/reports/creative-optimization-report/&quot;&gt;AppsFlyer’s report&lt;/a&gt; emphasizes the need to diversify creatives per media type, as the same creative concept can deliver completely different results depending on the media type.&lt;/p&gt;



&lt;p&gt;My rule of thumb is that the more your content feels like it belongs, the better it performs. Look at what content does well on the platform you want to target, and go for that. If in doubt, these are my general suggestions:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;TikTok and Instagram Reels:&lt;/strong&gt; skits dominate – hook in three seconds or less, and use humor and relatability to win&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;YouTube Shorts:&lt;/strong&gt; expert commentary performs best – longer clips, higher intent&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Facebook and Instagram feed:&lt;/strong&gt; focus on discovery and post captions; carousels showing processes also work well&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;LinkedIn:&lt;/strong&gt; process documentation thrives, posts about productivity hacks feel natural in this space&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;This also means that trying to re-use the same creative across different platforms is a recipe for failure. Each platform demands its own native format. Pick one platform, invest in &lt;a href=&quot;https://www.revenuecat.com/blog/growth/subscription-app-creative-testing/&quot;&gt;creative testing&lt;/a&gt;, and focus on nailing that channel before you expand.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-6-point-checklist-for-authentic-performance&quot;&gt;&lt;strong&gt;6-Point checklist for authentic performance&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;It’s all too easy to get ahead of yourself and click ‘publish’, but bad UGC can do more harm than no UGC. Before you launch, test every creative against this checklist:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;App-channel fit:&lt;/strong&gt; does your app’s core purpose (e.g. a wedding app) naturally fit the platform’s audience (e.g. Pinterest)?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Platform-native format:&lt;/strong&gt; does the &lt;em&gt;video itself&lt;/em&gt; feel native to the platform, or does it feel like an ad?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Authentic voice:&lt;/strong&gt; does the creator sound believable?&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Trust building:&lt;/strong&gt; does it educate and build credibility, not just hype?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Creating intention&lt;/strong&gt;: does it inspire actually trying the app?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Expectation setting:&lt;/strong&gt; will users feel the app matches what they were told? Do they know what success looks like?&lt;/li&gt;
&lt;/ol&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-common-pitfalls-with-ugc-nbsp&quot;&gt;&lt;strong&gt;Common pitfalls with UGC&amp;nbsp;&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Even solid ideas can tank. Here’s what to watch out for:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Pivot problem: &lt;/strong&gt;your video has a great start, followed by an awkward, scripted sales pitch&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Perfect life trap:&lt;/strong&gt; unrealistic instant results – think before and after clips, perfectly-arranged backgrounds, and model-looking actors&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Feature laundry list:&lt;/strong&gt; avoid overwhelming people with many benefits crammed in; keep it anchored on the core &lt;a href=&quot;https://www.revenuecat.com/blog/growth/what-drives-users-to-pay-jobs-to-be-done/&quot;&gt;job-to-be-done (JTBD)&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Platform mismatch:&lt;/strong&gt; there’s nothing that screams ad&lt;em&gt; &lt;/em&gt;more than a TikTok-style video dumped on LinkedIn&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;The one-shot myth:&lt;/strong&gt; don’t expect your first creative to boom, performance is a numbers game; you have to test many concepts to find a winner&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;To solve most of these problems, the solution is simple: keep performances natural, keep the creators and information credible, and make sure the video doesn’t feel out of place.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-three-creative-experiments-for-2026&quot;&gt;&lt;strong&gt;Three creative experiments for 2026&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;To move beyond stale UGC and capitalize on the shift to authentic performance, here’s three quick experiments you plan today and share tomorrow:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-skits-vs-testimonials-problem-first-vs-product-first&quot;&gt;&lt;strong&gt;1. Skits vs. testimonials (problem-first vs. product-first)&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Take your current best-performing testimonial and turn it into a scenario-based skit:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Same core promise, but framed as a real-life situation instead of a monologue&lt;/li&gt;



&lt;li&gt;Run a clean A/B test on testimonial vs. skit: same audience, same budget&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;strong&gt;What to look at:&lt;/strong&gt; CTR, IPM, cost-per-trial, and trial-to-paid&lt;/p&gt;



&lt;p&gt;If your experience matches what we’ve seen across subscription apps, the skit will attract fewer curious clicks, but more qualified ones, improving down-funnel metrics.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-method-first-vs-product-first-hook&quot;&gt;&lt;strong&gt;2. Method-first vs. product-first hook&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;For one of your hero features, create two versions of the same ad:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Version A (product-first):&lt;/strong&gt; introduce the app in the first three seconds&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Version B (method-first):&lt;/strong&gt; spend 15–20 seconds selling the method (the ‘how’ and ‘why’) before ever naming the app, like the Jumpspeak example&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;strong&gt;What to look at:&lt;/strong&gt; trial-start rate, trial-to-paid, and early retention (day one–seven)&lt;/p&gt;



&lt;p&gt;In most cases, method-first creatives generate slightly lower CTR, but much higher intent and LTV.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-one-concept-three-native-variants-platform-fit&quot;&gt;&lt;strong&gt;3. One concept, three native variants (platform fit)&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Pick a single creative concept (e.g. frustration with the current solution) and adapt it natively for three platforms:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;TikTok and Instagram Reels&lt;/strong&gt;: fast skit, jump cuts, creator-led&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;YouTube Shorts&lt;/strong&gt;: more structured explanation and/or commentary&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Instagram feed&lt;/strong&gt;: shortened cut + supporting carousel or strong caption&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Keep the core narrative identical, but adapt the format, pacing, and framing to each platform.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;What to look at:&lt;/strong&gt; IPM, cost-per-trial, and view time per platform&lt;/p&gt;



&lt;p&gt;This will show you where your narrative travels well as-is, and where you need a truly platform-native editorial approach.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-evolution-not-revolution&quot;&gt;&lt;strong&gt;Evolution, not revolution&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The core insight of UGC was always right: people trust people more than brands. But execution matters.&lt;/p&gt;



&lt;p&gt;‘Authentic’ doesn’t need to mean amateur, and ‘user-generated’ shouldn’t mean without strategy. The best performance creative keeps what made UGC powerful (relatability and a human voice) while moving past what made it ineffective (the stale, inauthentic formulas). Apps stuck on testimonials will keep burning budgets, while apps embracing this authentic performance model will build durable growth, stronger retention, and compounding LTV.&lt;/p&gt;



&lt;p&gt;As we head into 2026, authenticity isn’t a style; it’s its own UGC strategy.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Android SDK lifecycle management with Hilt dependency injection]]></title><description><![CDATA[In this article, you'll dive deep into SDK lifecycle management with Hilt, dependency injection library.]]></description><link>https://www.revenuecat.com/blog/engineering/hilt-sdk-lifecycle/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/hilt-sdk-lifecycle/</guid><pubDate>Wed, 26 Nov 2025 23:20:08 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Android-SDK-lifecycle-management-with-Hilt-Dependency-Injection.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Android applications integrate numerous third-party SDKs for payment processing, analytics, and subscription services, each with its own initialization requirements and clean up procedures. Managing these lifecycles manually leads to memory leaks, resource exhaustion, and subtle bugs when SDKs outlive their usefulness. Hilt’s component scoping and lifecycle hooks provide a solution, but understanding how to properly leverage them requires knowledge of the internal mechanisms that make lifecycle management possible.&lt;/p&gt;



&lt;p&gt;Let’s dive into SDK lifecycle management with Hilt, including:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Exploring the modern dependency injection library&lt;/li&gt;



&lt;li&gt;How Hilt’s component hierarchy maps to Android lifecycles&lt;/li&gt;



&lt;li&gt;How lifecycle callbacks enable automatic clean-up&lt;/li&gt;



&lt;li&gt;How scoping determines SDK lifetime&lt;/li&gt;



&lt;li&gt;Why proper lifecycle management prevents resource leaks.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Using &lt;a href=&quot;https://github.com/RevenueCat/purchases-android&quot;&gt;RevenueCat’s Purchases SDK&lt;/a&gt; as an example, you’ll see how different scoping strategies affect SDK initialization and disposal, when clean-up is necessary versus premature, and the performance implications of each approach. This isn’t a guide on integrating SDKs. It’s an exploration of the lifecycle machinery that makes proper resource management possible.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-fundamental-problem-sdk-lifecycle-mismatches&quot;&gt;&lt;strong&gt;The fundamental problem: SDK lifecycle mismatches&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Third-party SDKs often have explicit lifecycle requirements:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-TzBgN wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/\/ RevenueCat initialization\nPurchases.configure(\n    PurchasesConfiguration.Builder(context, apiKey).build()\n)\n\n\/\/ Later, when done\nPurchases.sharedInstance.close()&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The challenge: when is “later”? If you initialize in &lt;code&gt;Application.onCreate()&lt;/code&gt; and never call &lt;code&gt;close()&lt;/code&gt;, the SDK holds resources (connections, caches, listeners) for the entire app lifetime. If you initialize in &lt;code&gt;Activity.onCreate()&lt;/code&gt; and call &lt;code&gt;close()&lt;/code&gt; in &lt;code&gt;onDestroy()&lt;/code&gt;, you might prematurely dispose of resources during configuration changes.&lt;/p&gt;



&lt;p&gt;The naive approach is manual lifecycle tracking:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1fhhJE wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;class SubscriptionActivity : AppCompatActivity() {\n  private lateinit var purchases: Purchases\n\n  override fun onCreate(savedInstanceState: Bundle?) {\n    super.onCreate(savedInstanceState)\n    purchases = Purchases.configure(\n        PurchasesConfiguration.Builder(this, apiKey).build()\n    )\n  }\n\n  override fun onDestroy() {\n    super.onDestroy()\n    if (isFinishing) {  \/\/ Only close if truly finishing\n      purchases.close()\n    }\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This works but is brittle. You must remember to call close() in every activity that uses the SDK, and you must correctly distinguish configuration changes from true destruction. Hilt’s scoping and lifecycle mechanisms automate this pattern.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;hilts-component-hierarchy-mapping-to-android-lifecycles&quot;&gt;&lt;strong&gt;Hilt’s component hierarchy: Mapping to Android lifecycles&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Hilt provides a predefined component tree that aligns with Android’s lifecycle:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZaWNE2 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;SingletonComponent (application lifetime)\n    \u2514\u2500\u2500 ActivityRetainedComponent (survives configuration changes)\n        \u251c\u2500\u2500 ActivityComponent (activity lifetime)\n        \u2502   \u251c\u2500\u2500 FragmentComponent (fragment lifetime)\n        \u2502   \u2514\u2500\u2500 ViewComponent (view lifetime)\n        \u2514\u2500\u2500 ViewModelComponent (ViewModel lifetime)&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Each component has an associated scope annotation and lifecycle:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;The &lt;code&gt;SingletonComponent&lt;/code&gt; with &lt;code&gt;@Singleton&lt;/code&gt; scope lives from application creation to application destruction&lt;/li&gt;



&lt;li&gt;The &lt;code&gt;ActivityRetainedComponent&lt;/code&gt; with &lt;code&gt;@ActivityRetainedScoped&lt;/code&gt; scope lives from activity creation to activity finish, surviving rotation&lt;/li&gt;



&lt;li&gt;The &lt;code&gt;ActivityComponent&lt;/code&gt; with &lt;code&gt;@ActivityScoped&lt;/code&gt; scope lives from activity creation to activity destruction, getting destroyed on rotation&lt;/li&gt;



&lt;li&gt;The &lt;code&gt;ViewModelComponent&lt;/code&gt; with &lt;code&gt;@ViewModelScoped&lt;/code&gt; scope lives from ViewModel creation to ViewModel cleared&lt;/li&gt;



&lt;li&gt;The &lt;code&gt;FragmentComponent&lt;/code&gt; with &lt;code&gt;@FragmentScoped&lt;/code&gt; scope lives from fragment creation to fragment destruction&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Understanding this hierarchy is critical for SDK lifecycle management. The component you choose determines when initialization and clean-up occur.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;the-lifecycle-callback-mechanism-retainedlifecycle-internals&quot;&gt;&lt;strong&gt;The lifecycle callback mechanism: RetainedLifecycle internals&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Hilt provides lifecycle hooks through the RetainedLifecycle interface:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1LQxhY wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;public interface RetainedLifecycle {\n  @MainThread\n  void addOnClearedListener(@NonNull OnClearedListener listener);\n\n  @MainThread\n  void removeOnClearedListener(@NonNull OnClearedListener listener);\n\n  interface OnClearedListener {\n    void onCleared();\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This interface is implemented by &lt;code&gt;ActivityRetainedLifecycle&lt;/code&gt; and &lt;code&gt;ViewModelLifecycle&lt;/code&gt;, providing clean-up callbacks for retained components.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;retainedlifecycleimpl-the-implementation&quot;&gt;&lt;strong&gt;RetainedLifecycleImpl: the implementation&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The internal implementation reveals important constraints:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1FrJGs wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;public final class RetainedLifecycleImpl\n    implements ActivityRetainedLifecycle, ViewModelLifecycle {\n\n  private final Set&lt;RetainedLifecycle.OnClearedListener&gt; listeners = new HashSet&lt;&gt;();\n  private boolean onClearedDispatched = false;\n\n  @Override\n  public void addOnClearedListener(@NonNull RetainedLifecycle.OnClearedListener listener) {\n    ThreadUtil.ensureMainThread();\n    throwIfOnClearedDispatched();\n    listeners.add(listener);\n  }\n\n  @Override\n  public void removeOnClearedListener(@NonNull RetainedLifecycle.OnClearedListener listener) {\n    ThreadUtil.ensureMainThread();\n    throwIfOnClearedDispatched();\n    listeners.remove(listener);\n  }\n\n  public void dispatchOnCleared() {\n    ThreadUtil.ensureMainThread();\n    onClearedDispatched = true;\n    for (RetainedLifecycle.OnClearedListener listener : listeners) {\n      listener.onCleared();\n    }\n  }\n\n  private void throwIfOnClearedDispatched() {\n    if (onClearedDispatched) {\n      throw new IllegalStateException(\n          \&amp;quot;There was a race between the call to add\/remove an OnClearedListener and onCleared(). \&amp;quot;\n          + \&amp;quot;This can happen when posting to the Main thread from a background thread, \&amp;quot;\n          + \&amp;quot;which is not supported.\&amp;quot;);\n    }\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;All lifecycle operations must happen on the main thread. This is enforced via &lt;code&gt;ThreadUtil.ensureMainThread()&lt;/code&gt;, preventing concurrent access issues. Listeners are stored in a &lt;code&gt;HashSet&lt;/code&gt;, not a thread-safe collection. The main thread requirement eliminates the need for synchronization overhead.&lt;/p&gt;



&lt;p&gt;The &lt;code&gt;onClearedDispatched&lt;/code&gt; flag ensures clean-up happens exactly once. Attempting to add listeners after clean-up throws an exception. The exception message explicitly describes the race condition scenario, making debugging easier.&lt;/p&gt;



&lt;p&gt;This implementation prioritizes simplicity and performance over flexibility. Lifecycle callbacks are strictly single-threaded and one-way.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-viewmodel-bridge-how-clean-up-is-triggered&quot;&gt;&lt;strong&gt;The ViewModel bridge: how clean-up is triggered&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The lifecycle callback is triggered through Android’s &lt;code&gt;ViewModel.onCleared()&lt;/code&gt;:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z26jX8T wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;static final class ActivityRetainedComponentViewModel extends ViewModel {\n  private final ActivityRetainedComponent component;\n  private final SavedStateHandleHolder savedStateHandleHolder;\n\n  ActivityRetainedComponentViewModel(\n      ActivityRetainedComponent component,\n      SavedStateHandleHolder savedStateHandleHolder) {\n    this.component = component;\n    this.savedStateHandleHolder = savedStateHandleHolder;\n  }\n\n  @Override\n  protected void onCleared() {\n    super.onCleared();\n    ActivityRetainedLifecycle lifecycle =\n        EntryPoints.get(component, ActivityRetainedLifecycleEntryPoint.class)\n            .getActivityRetainedLifecycle();\n    ((RetainedLifecycleImpl) lifecycle).dispatchOnCleared();\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This is elegant. Hilt doesn’t reimplement lifecycle tracking. Instead, it piggybacks on Android’s existing &lt;code&gt;ViewModel&lt;/code&gt; retention mechanism. The &lt;code&gt;ActivityRetainedComponent&lt;/code&gt; is stored inside &lt;code&gt;ActivityRetainedComponentViewModel&lt;/code&gt;. Android’s &lt;code&gt;ViewModelStore&lt;/code&gt; retains the ViewModel across configuration changes, and when the Activity finishes (not just rotates), &lt;code&gt;ViewModelStore&lt;/code&gt; clears the ViewModel. Then &lt;code&gt;ViewModel.onCleared()&lt;/code&gt; is called, which dispatches Hilt’s lifecycle callbacks.This design means Hilt’s lifecycle hooks have the same semantics as &lt;code&gt;ViewModel.onCleared()&lt;/code&gt;. They fire when the Activity is finishing, not during configuration changes.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;sdk-lifecycle-patterns-three-scoping-strategies&quot;&gt;&lt;strong&gt;SDK lifecycle patterns: three scoping strategies&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Let’s examine three different approaches to managing RevenueCat’s Purchases SDK, each with different lifecycle implications.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;pattern-1-singleton-scope-application-lifetime&quot;&gt;&lt;strong&gt;Pattern 1: Singleton scope (application lifetime)&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The simplest approach is application-scoped initialization:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZnkSDr wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Module\n@InstallIn(SingletonComponent::class)\nobject PurchasesModule {\n\n  @Provides\n  @Singleton\n  fun providePurchases(\n      @ApplicationContext context: Context\n  ): Purchases {\n    return Purchases.configure(\n        PurchasesConfiguration.Builder(context, BuildConfig.REVENUECAT_API_KEY)\n            .appUserId(null)  \/\/ Anonymous user\n            .build()\n    )\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The SDK initializes on first injection, typically during Application creation. It never gets disposed of. The SDK lives for the entire app lifetime.&lt;/p&gt;



&lt;p&gt;The Google Play Billing connection is maintained throughout app lifetime with approximately a few KB overhead. The subscription cache stays in memory, typically less than 100 KB for most apps. Network listeners remain active for the app lifetime.&lt;/p&gt;



&lt;p&gt;This approach makes sense when subscription features are core to the app, like subscription-based apps where user subscription status is checked frequently across many screens. The overhead is acceptable given usage patterns.&lt;/p&gt;



&lt;p&gt;This approach should be avoided when subscription features are rarely used, like a one-time &lt;a href=&quot;https://www.revenuecat.com/blog/engineering/building-a-tip-jar-feature-with-revenuecat/&quot;&gt;tip jar&lt;/a&gt; in settings. It’s also not ideal when the app is resource-constrained and runs on low-end devices, or when the Billing SDK conflicts with other payment integrations.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;pattern-2-activityretainedscoped-survives-configuration-changes&quot;&gt;&lt;strong&gt;Pattern 2: ActivityRetainedScoped (survives configuration changes)&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;For feature-scoped usage, tie the SDK to a specific section:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1cnjCY wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Module\n@InstallIn(ActivityRetainedComponent::class)\nobject FeatureScopedPurchasesModule {\n\n  @Provides\n  @ActivityRetainedScoped\n  fun providePurchases(\n      @ApplicationContext context: Context,\n      lifecycle: ActivityRetainedLifecycle\n  ): Purchases {\n    val purchases = Purchases.configure(\n        PurchasesConfiguration.Builder(context, BuildConfig.REVENUECAT_API_KEY)\n            .build()\n    )\n\n    \/\/ Register clean-up callback\n    lifecycle.addOnClearedListener {\n      purchases.close()\n    }\n\n    return purchases\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The SDK initializes on first injection within the Activity’s component graph. It gets disposed of when the Activity finishes, after &lt;code&gt;isFinishing&lt;/code&gt; becomes true.&lt;/p&gt;



&lt;p&gt;When the screen rotates, the SDK instance is retained with no reinitialization. The same &lt;code&gt;ActivityRetainedComponent&lt;/code&gt; is reused during activity recreation. When the activity finishes, &lt;code&gt;lifecycle.onCleared()&lt;/code&gt; fires and &lt;code&gt;purchases.close()&lt;/code&gt; is called.&lt;/p&gt;



&lt;p&gt;Let’s trace the complete lifecycle:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1imcqk wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;User navigates to SubscriptionActivity\n    \u2192 ActivityRetainedComponentManager.generatedComponent() called\n    \u2192 ActivityRetainedComponentViewModel created (if first time)\n    \u2192 ActivityRetainedComponent built\n    \u2192 providePurchases() called\n    \u2192 Purchases.configure() initializes SDK\n    \u2192 OnClearedListener registered\n\nUser rotates device\n    \u2192 Activity destroyed\n    \u2192 New Activity created\n    \u2192 Same ActivityRetainedComponentViewModel retrieved from ViewModelStore\n    \u2192 Same ActivityRetainedComponent reused\n    \u2192 Same Purchases instance injected (no reinitialization)\n\nUser navigates away (finishes Activity)\n    \u2192 Activity.onDestroy() with isFinishing=true\n    \u2192 ViewModelStore cleared\n    \u2192 ActivityRetainedComponentViewModel.onCleared() called\n    \u2192 RetainedLifecycleImpl.dispatchOnCleared() called\n    \u2192 OnClearedListener.onCleared() invoked\n    \u2192 purchases.close() executes&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This is the sweet spot for feature-scoped SDKs. You get configuration change resilience without app-wide overhead.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;pattern-3-viewmodelscoped-per-viewmodel-instances&quot;&gt;&lt;strong&gt;Pattern 3: ViewModelScoped (per-ViewModel instances)&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;For ViewModel-specific SDK instances:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-fCedD wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Module\n@InstallIn(ViewModelComponent::class)\nobject ViewModelScopedPurchasesModule {\n\n  @Provides\n  @ViewModelScoped\n  fun providePurchases(\n      @ApplicationContext context: Context,\n      lifecycle: ViewModelLifecycle\n  ): Purchases {\n    val purchases = Purchases.configure(\n        PurchasesConfiguration.Builder(context, BuildConfig.REVENUECAT_API_KEY)\n            .build()\n    )\n\n    lifecycle.addOnClearedListener {\n      purchases.close()\n    }\n\n    return purchases\n  }\n}\n\n@HiltViewModel\nclass SubscriptionViewModel @Inject constructor(\n    private val purchases: Purchases\n) : ViewModel() {\n  fun loadOfferings() {\n    purchases.getOfferingsWith { offerings -&gt;\n      \/\/ Handle offerings\n    }\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The SDK initializes when the ViewModel is created. It gets disposed of when the ViewModel is cleared, which happens when the Activity or Fragment is destroyed. Each ViewModel gets its own SDK instance, providing complete isolation.&lt;/p&gt;



&lt;p&gt;This pattern works well when you have multiple independent purchase flows with separate state, when testing requires isolated SDK instances, or when different ViewModels need different SDK configurations.&lt;/p&gt;



&lt;p&gt;Creating multiple SDK instances means multiple Google Play Billing connections. A SubscriptionViewModel instance creates Purchases instance #1 with Google Play Billing connection #1. An UpgradeViewModel instance creates Purchases instance #2 with Google Play Billing connection #2. Each connection has overhead of approximately 200 to 500ms initialization time and a few KB memory. For most apps, a single shared instance is more efficient.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-configure-debug-amp-release-sdk-initialization&quot;&gt;Configure &lt;strong&gt;debug &amp;amp; release SDK initialization&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;For example when developing with RevenueCat, you can set different SDK configurations for debug builds to enable testing without real purchases. Since RevenueCat’s &lt;a href=&quot;https://www.revenuecat.com/blog/engineering/testing-test-store/&quot;&gt;StoreKit Testing (Test Store)&lt;/a&gt; allows you to simplify subscription testing flows without connecting to real App Store servers. For release mode, you can set the real private key, and allow your users to purchases the products.&lt;/p&gt;



&lt;p&gt;Different build variants need different SDK configurations:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZMwEBQ wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Module\n@InstallIn(SingletonComponent::class)\nobject PurchasesModule {\n\n  @Provides\n  @Singleton\n  fun providePurchases(\n      @ApplicationContext context: Context\n  ): Purchases {\n    return \n\tif (BuildConfig.DEBUG) {\n Purchases.configure(\n        PurchasesConfiguration.Builder(\n            context,\n            BuildConfig.REVENUECAT_DEBUG_API_KEY\n        )\n            .dangerousSettings(\n                DangerousSettings(\n                    autoSyncPurchases = false  \/\/ Manual sync for testing\n                )\n            )\n            .build()\n    ).apply {\n      \/\/ Enable Test Store mode for local testing\n      Purchases.logLevel = LogLevel.DEBUG\n    }\n  }\n } else {\n   Purchases.configure(\n        PurchasesConfiguration.Builder(\n            context,\n            BuildConfig.REVENUECAT_API_KEY\n        )\n            .build()\n    )\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Hilt processes each variant separately, so debug and release modules don’t conflict. The debug module configures the SDK with verbose logging and manual sync control, making it easier to test subscription flows with Test Store. The release module uses production configuration with automatic sync enabled.&lt;/p&gt;



&lt;p&gt;The Test Store integration allows you to test subscription scenarios locally without making real purchases. You can verify that your SDK lifecycle management works correctly across different subscription states, test upgrade and downgrade flows, and validate that clean-up happens properly when users cancel subscriptions. This is particularly valuable when testing ActivityRetainedScoped SDKs because you can simulate the complete lifecycle from subscription purchase through activity rotation to final clean-up.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;revenuecats-singleton-protection-a-special-case&quot;&gt;&lt;strong&gt;RevenueCat’s singleton protection: a special case&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Before diving into why clean-up matters, it’s important to understand that RevenueCat’s Purchases SDK has built-in singleton protection that prevents accidental instance duplication. Look at the implementation:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1ClurK wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;fun configure(configuration: PurchasesConfiguration): Purchases {\n    if (isConfigured) {\n        if (backingFieldSharedInstance?.purchasesOrchestrator?.currentConfiguration == configuration) {\n            infoLog { ConfigureStrings.INSTANCE_ALREADY_EXISTS_WITH_SAME_CONFIG }\n            return sharedInstance\n        } else {\n            infoLog { ConfigureStrings.INSTANCE_ALREADY_EXISTS }\n        }\n    }\n    return PurchasesFactory().createPurchases(configuration).also {\n        sharedInstance = it\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;When you call &lt;code&gt;Purchases.configure()&lt;/code&gt; with the same configuration multiple times, RevenueCat returns the existing singleton instance instead of creating a new one. This means the ActivityRetainedScoped and ViewModelScoped patterns described earlier won’t actually create multiple SDK instances if you’re using the same API key and configuration.&lt;/p&gt;



&lt;p&gt;However, if you call &lt;code&gt;configure()&lt;/code&gt; with different configurations (different API keys, different user IDs, different settings), RevenueCat will create a new instance and replace the singleton. The old instance still exists in memory until you explicitly call &lt;code&gt;close()&lt;/code&gt; on it.&lt;/p&gt;



&lt;p&gt;This singleton protection is specific to RevenueCat. Many other SDKs don’t have this safeguard and will happily create multiple instances if you call their initialization methods repeatedly. Examples include Firebase Analytics, Amplitude, Mixpanel, and many payment SDKs. For these SDKs, the resource leak scenarios described below are real concerns.&lt;/p&gt;



&lt;p&gt;The key takeaway: even though RevenueCat protects against duplicate instances with the same configuration, the lifecycle management patterns with Hilt still matter because they ensure proper clean-up when you’re done with the SDK, handle configuration changes correctly, and establish patterns that work across all SDKs, not just RevenueCat.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;why-clean-up-matters-resource-leak-analysis&quot;&gt;&lt;strong&gt;Why clean-up matters: Resource leak analysis&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Let’s analyze what happens without proper clean-up, both for RevenueCat and for SDKs without singleton protection.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;memory-leak-scenario-singleton-without-scoping&quot;&gt;&lt;strong&gt;Memory leak scenario: Singleton without scoping&lt;/strong&gt;&lt;/h3&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1f1zW8 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;class Application : Application() {\n  override fun onCreate() {\n    super.onCreate()\n    Purchases.configure(...)  \/\/ Initialized once\n    \/\/ Never closed\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The Google Play Billing Service connection is maintained indefinitely. Service binding holds Context reference and prevents garbage collection of associated objects. The subscription state cache grows over time with cached offerings, products, and purchase history. There’s no eviction policy without &lt;code&gt;close()&lt;/code&gt;. Network listeners stay active throughout app lifetime, including webhook listeners for subscription changes and background sync operations.&lt;/p&gt;



&lt;p&gt;For a singleton SDK in a subscription app, this is acceptable. The resources are used throughout the app lifetime. The ‘leak’ is intentional.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;resource-exhaustion-scenario-activity-scope-without-clean-up&quot;&gt;&lt;strong&gt;Resource exhaustion scenario: Activity scope without clean-up&lt;/strong&gt;&lt;/h3&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZsPIEO wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;class SubscriptionActivity : AppCompatActivity() {\n  private lateinit var purchases: Purchases\n\n  override fun onCreate(savedInstanceState: Bundle?) {\n    super.onCreate(savedInstanceState)\n    purchases = Purchases.configure(...)\n    \/\/ Never closed, even when Activity finishes\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;For RevenueCat specifically, thanks to the singleton protection, calling &lt;code&gt;configure()&lt;/code&gt; with the same configuration repeatedly just returns the existing instance. You won’t create 10 separate instances. However, you still have a problem: you’re holding references to the singleton in multiple Activity instances, and you never call &lt;code&gt;close()&lt;/code&gt; to clean up when you’re truly done with subscriptions.&lt;/p&gt;



&lt;p&gt;More importantly, this pattern becomes a real problem with SDKs that don’t have singleton protection. Consider an analytics SDK without this safeguard:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Yct0R wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;class AnalyticsActivity : AppCompatActivity() {\n  private lateinit var analytics: AnalyticsSDK\n\n  override fun onCreate(savedInstanceState: Bundle?) {\n    super.onCreate(savedInstanceState)\n    analytics = AnalyticsSDK.initialize(context, apiKey)\n    \/\/ Never closed, even when Activity finishes\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;When the user visits &lt;code&gt;AnalyticsActivity&lt;/code&gt; for the first time, &lt;code&gt;AnalyticsSDK&lt;/code&gt; instance #1 is created with its own event buffer and network queue. When the user navigates away and returns, &lt;code&gt;AnalyticsActivity&lt;/code&gt; instance #2 is created, AnalyticsSDK instance #2 is created with another event buffer and network queue. But &lt;code&gt;AnalyticsSDK&lt;/code&gt; instance #1 still exists because it was never cleaned up. After 10 visits, you have 10 &lt;code&gt;AnalyticsSDK&lt;/code&gt; instances, 10 event buffers, 10 network queues, and a cumulative memory leak.&lt;/p&gt;



&lt;p&gt;Eventually, the app will hit resource limits through either memory exhaustion or connection limits.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-isfinishing-pitfall-configuration-changes-vs-destruction&quot;&gt;&lt;strong&gt;The isFinishing() pitfall: configuration changes vs. destruction&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Manual clean-up often looks like this:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-9LUEO wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;override fun onDestroy() {\n  super.onDestroy()\n  if (isFinishing) {\n    purchases.close()\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This works but is fragile. Every Activity using the SDK must implement this pattern, which is easy to forget. Unit tests must mock &lt;code&gt;isFinishing&lt;/code&gt; correctly, adding testing complexity. Edge cases emerge, like when &lt;code&gt;finish()&lt;/code&gt; is called from &lt;code&gt;onCreate()&lt;/code&gt; or during programmatic recreation.Hilt’s &lt;code&gt;ActivityRetainedLifecycle&lt;/code&gt; eliminates these concerns. The callback fires exactly when the Activity is finishing, with no manual checks needed.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;advanced-pattern-conditional-sdk-initialization&quot;&gt;&lt;strong&gt;Advanced pattern: Conditional SDK initialization&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Sometimes SDKs should only be initialized under certain conditions:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1EEzF1 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Module\n@InstallIn(SingletonComponent::class)\nobject ConditionalPurchasesModule {\n\n  @Provides\n  @Singleton\n  fun providePurchases(\n      @ApplicationContext context: Context,\n      userRepository: UserRepository\n  ): Purchases? {\n    return if (userRepository.currentUser?.canMakePurchases == true) {\n      Purchases.configure(\n          PurchasesConfiguration.Builder(context, BuildConfig.REVENUECAT_API_KEY)\n              .build()\n      )\n    } else {\n      null  \/\/ No SDK for users without purchase capability\n    }\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Nullable injection handles the conditional initialization:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1UkDAY wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@HiltViewModel\nclass SubscriptionViewModel @Inject constructor(\n    private val purchases: Purchases?  \/\/ Nullable\n) : ViewModel() {\n\n  fun loadOfferings() {\n    purchases?.getOfferingsWith { offerings -&gt;\n      \/\/ Handle offerings\n    } ?: run {\n      \/\/ User can&apos;t make purchases, show alternative UI\n    }\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This pattern prevents unnecessary SDK initialization for users who can’t use it.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;performance-profiling-measuring-sdk-lifecycle-impact&quot;&gt;&lt;strong&gt;Performance profiling: measuring SDK lifecycle impact&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;To understand the performance implications, let’s measure RevenueCat initialization and disposal.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;initialization-cost&quot;&gt;&lt;strong&gt;Initialization cost&lt;/strong&gt;&lt;/h3&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-tdOVy wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Provides\n@Singleton\nfun providePurchases(\n    @ApplicationContext context: Context\n): Purchases {\n  val startTime = SystemClock.elapsedRealtime()\n\n  val purchases = Purchases.configure(\n      PurchasesConfiguration.Builder(context, apiKey).build()\n  )\n\n  val duration = SystemClock.elapsedRealtime() - startTime\n  Log.d(\&amp;quot;PurchasesModule\&amp;quot;, \&amp;quot;Initialization took ${duration}ms\&amp;quot;)\n\n  return purchases\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Cold start typically takes 50 to 100ms (depending on your machines), which includes Google Play Billing connection. Warm start typically takes 10 to 20ms when the Billing Service is already bound. Configuration blocks the calling thread, creating main thread impact.&lt;/p&gt;



&lt;p&gt;You can optimize by initializing on a background thread:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z4weth wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Provides\n@Singleton\nfun providePurchases(\n    @ApplicationContext context: Context,\n    @IODispatcher dispatcher: CoroutineDispatcher\n): Lazy&lt;Purchases&gt; = lazy {\n  runBlocking(dispatcher) {\n    Purchases.configure(\n        PurchasesConfiguration.Builder(context, apiKey).build()\n    )\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Using &lt;code&gt;Lazy&lt;/code&gt; defers initialization until first access. If that access is from a co-routine on a background dispatcher, initialization happens off the main thread.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;clean-up-cost&quot;&gt;&lt;strong&gt;Clean-up cost&lt;/strong&gt;&lt;/h3&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-2vgUmq wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;lifecycle.addOnClearedListener {\n  val startTime = SystemClock.elapsedRealtime()\n  purchases.close()\n  val duration = SystemClock.elapsedRealtime() - startTime\n  Log.d(\&amp;quot;PurchasesModule\&amp;quot;, \&amp;quot;clean-up took ${duration}ms\&amp;quot;)\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Clean-up duration typically takes 10 to 50ms. Operations include disconnecting from Billing Service, canceling pending queries, and clearing caches.&lt;/p&gt;



&lt;p&gt;Clean-up happens in &lt;code&gt;ViewModel.onCleared()&lt;/code&gt;, which is synchronous. Long clean-up blocks the main thread during Activity finish.&lt;/p&gt;



&lt;p&gt;You can optimize expensive clean-up by moving to a background thread:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-17WvjM wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;lifecycle.addOnClearedListener {\n  CoroutineScope(Dispatchers.IO).launch {\n    purchases.close()\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;However, be cautious. If clean-up must happen before the process terminates, background clean-up might not complete.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;memory-profiling-comparing-scoping-strategies&quot;&gt;&lt;strong&gt;Memory profiling: comparing scoping strategies&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Using Android Studio’s Memory Profiler, we can measure SDK memory overhead. With singleton scope, initial allocation is approximately 500 KB. After visiting 10 screens, memory usage remains at approximately 500 KB because the same instance is reused. Memory growth is zero.&lt;/p&gt;



&lt;p&gt;With &lt;code&gt;ActivityRetainedScoped&lt;/code&gt; while visiting 10 different screens, screen 1 adds 500 KB during initialization. When screen 1 finishes, 500 KB is freed during clean-up. Screen 2 adds 500 KB during initialization. When screen 2 finishes, 500 KB is freed. This pattern continues, maintaining a steady state of approximately 500 KB with one instance at a time.&lt;/p&gt;



&lt;p&gt;Without clean-up while visiting 10 screens, screen 1 adds 500 KB, screen 2 adds another 500 KB, screen 3 adds another 500 KB, continuing until screen 10 adds another 500 KB. The total accumulates to approximately 5 MB from 10 instances leaked.&lt;/p&gt;



&lt;p&gt;The measurements show that proper clean-up is critical for activity-scoped SDKs.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;testing-sdk-lifecycle-management&quot;&gt;&lt;strong&gt;Testing SDK lifecycle management&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Hilt’s lifecycle integration requires special consideration in tests.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;unit-testing-mocking-lifecycle-callbacks&quot;&gt;&lt;strong&gt;Unit testing: mocking lifecycle callbacks&lt;/strong&gt;&lt;/h3&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-vUGDk wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@HiltAndroidTest\nclass SubscriptionViewModelTest {\n\n  @get:Rule\n  var hiltRule = HiltAndroidRule(this)\n\n  @Inject\n  lateinit var purchases: Purchases\n\n  @Inject\n  lateinit var lifecycle: ActivityRetainedLifecycle\n\n  @Before\n  fun setup() {\n    hiltRule.inject()\n  }\n\n  @Test\n  fun testcleanup() {\n    \/\/ Verify clean-up callback is registered\n    val callbackCaptor = argumentCaptor&lt;ActivityRetainedLifecycle.OnClearedListener&gt;()\n    verify(lifecycle).addOnClearedListener(callbackCaptor.capture())\n\n    \/\/ Simulate lifecycle cleared\n    callbackCaptor.firstValue.onCleared()\n\n    \/\/ Verify SDK clean-up\n    verify(purchases).close()\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This test verifies that the module registers a clean-up callback and that the callback calls &lt;code&gt;close()&lt;/code&gt;.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;integration-testing-verifying-clean-up-happens&quot;&gt;&lt;strong&gt;Integration testing: verifying clean-up happens&lt;/strong&gt;&lt;/h3&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z2dDEcU wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@HiltAndroidTest\n@HiltAndroidRule(ComponentActivity::class)\nclass SDKLifecycleTest {\n\n  @get:Rule\n  var hiltRule = HiltAndroidRule(this)\n\n  @Test\n  fun testActivityFinishTriggersclean-up() {\n    val scenario = launchActivity&lt;SubscriptionActivity&gt;()\n\n    \/\/ Inject to trigger SDK initialization\n    scenario.onActivity { activity -&gt;\n      \/\/ Trigger injection\n      val viewModel: SubscriptionViewModel by activity.viewModels()\n      viewModel.loadOfferings()\n    }\n\n    \/\/ Verify SDK is initialized\n    val purchases = Purchases.sharedInstance\n    assertNotNull(purchases)\n\n    \/\/ Finish activity\n    scenario.close()\n\n    \/\/ Verify clean-up (this requires SDK instrumentation)\n    \/\/ In practice, you&apos;d verify through memory leaks or state checks\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This test verifies the full lifecycle from initialization on activity creation to clean-up on activity finish.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;replacing-sdks-in-tests&quot;&gt;&lt;strong&gt;Replacing SDKs in tests&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;For tests that don’t need the real SDK:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1wi6LU wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Module\n@InstallIn(SingletonComponent::class)\n@TestInstallIn(\n    components = [SingletonComponent::class],\n    replaces = [PurchasesModule::class]\n)\nobject FakePurchasesModule {\n\n  @Provides\n  @Singleton\n  fun provideFakePurchases(): Purchases {\n    return mockk&lt;Purchases&gt;(relaxed = true)\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;@TestInstallIn&lt;/code&gt; annotation replaces the production module with a fake, avoiding real SDK initialization in tests.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;real-world-case-study-multi-sdk-coordination&quot;&gt;&lt;strong&gt;Real-world case study: multi-SDK coordination&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Many apps integrate multiple SDKs with interdependent lifecycles:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-veo6d wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Module\n@InstallIn(ActivityRetainedComponent::class)\nobject AnalyticsModule {\n\n  @Provides\n  @ActivityRetainedScoped\n  fun provideAnalytics(\n      @ApplicationContext context: Context,\n      purchases: Purchases,  \/\/ Depends on Purchases SDK\n      lifecycle: ActivityRetainedLifecycle\n  ): Analytics {\n    val analytics = Analytics.initialize(context)\n\n    \/\/ Set user properties from subscription status\n    purchases.getCustomerInfoWith { customerInfo -&gt;\n      analytics.setUserProperty(\&amp;quot;subscription_status\&amp;quot;, customerInfo.entitlements.active)\n    }\n\n    lifecycle.addOnClearedListener {\n      analytics.flush()  \/\/ Ensure events are sent before clean-up\n      analytics.close()\n    }\n\n    return analytics\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Dagger’s dependency graph ensures &lt;code&gt;Purchases&lt;/code&gt; is initialized before &lt;code&gt;Analytics&lt;/code&gt; because &lt;code&gt;Analytics&lt;/code&gt; depends on it. This initialization order is automatic based on the dependency graph.&lt;/p&gt;



&lt;p&gt;Clean-up callbacks fire in registration order. If you need specific ordering, you can register multiple callbacks, but relying on callback order is fragile. A better approach is to handle dependencies explicitly:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-jYR8e wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;data class SDKCoordinator @Inject constructor(\n    private val purchases: Purchases,\n    private val analytics: Analytics,\n    private val lifecycle: ActivityRetainedLifecycle\n) {\n  init {\n    lifecycle.addOnClearedListener {\n      clean-upAll()\n    }\n  }\n\n  private fun clean-upAll() {\n    \/\/ Explicit clean-up order\n    analytics.close()\n    purchases.close()\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This coordinator pattern makes clean-up order explicit and testable.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;recap&quot;&gt;&lt;strong&gt;Recap&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;SDK lifecycle management with Hilt leverages the framework’s component hierarchy and lifecycle callback mechanisms to automate initialization and clean-up. The component scoping determines SDK lifetime. Use &lt;code&gt;@Singleton&lt;/code&gt; for application-wide SDKs, &lt;code&gt;@ActivityRetainedScoped&lt;/code&gt; for feature-scoped SDKs that survive configuration changes, and &lt;code&gt;@ViewModelScoped&lt;/code&gt; for ViewModel-specific instances. The &lt;code&gt;RetainedLifecycle&lt;/code&gt; interface provides clean-up hooks that fire when components are destroyed, implemented through Android’s &lt;code&gt;ViewModel.onCleared()&lt;/code&gt; mechanism.&lt;/p&gt;



&lt;p&gt;The internal implementation reveals important constraints. Lifecycle callbacks are strictly main-thread operations enforced through &lt;code&gt;ThreadUtil.ensureMainThread()&lt;/code&gt;. Clean-up is one-time-only with explicit race condition detection. The ViewModel bridge ensures clean-up happens when Activities finish rather than during configuration changes. Performance profiling shows that proper clean-up prevents memory leaks by avoiding cumulative SDK instances while scoping determines initialization cost, balancing application-wide overhead against feature-scoped deferred initialization.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;ready-to-tidy-up-your-sdk&quot;&gt;&lt;strong&gt;Ready to tidy up your SDK?&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Understanding these internals helps you make better architectural decisions:&amp;nbsp;&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Choose appropriate scoping based on SDK usage patterns&lt;/li&gt;



&lt;li&gt;Register clean-up callbacks to prevent resource leaks&lt;/li&gt;



&lt;li&gt;Measure initialization and clean-up costs to optimize performance&lt;/li&gt;



&lt;li&gt;Coordinate multiple interdependent SDKs through explicit dependency management&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;While RevenueCat’s Purchases SDK has built-in singleton protection that prevents duplicate instances with the same configuration, many other SDKs lack this safeguard. The lifecycle management patterns demonstrated here work universally across all SDKs, ensuring proper resource management regardless of the SDK’s internal implementation.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Whether you’re integrating subscription services like RevenueCat, analytics platforms, or payment processors, Hilt’s lifecycle mechanisms provide a declarative, type-safe solution to the SDK lifecycle problem.&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Start here: Black Friday, holiday sales, and promotional offers]]></title><description><![CDATA[Everything you need to set up a promotional offer for your subscription app]]></description><link>https://www.revenuecat.com/blog/growth/promotional-offers-sales-app/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/promotional-offers-sales-app/</guid><pubDate>Wed, 26 Nov 2025 16:28:18 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Holiday-sales-promotional-offers.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Seasonal offers and holiday sales can boost conversion, retention, and long-term revenue — but only when paired with the right strategy. This study guide brings together everything you need to &lt;strong&gt;plan, build and launch&lt;/strong&gt; effective promotional campaigns across iOS, Android, and the web.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Whether you’re running your first Black Friday sale or optimizing a multi-region holiday strategy, start here.&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-Z1QXveO wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Need to get a sale live ASAP?&quot; text=&quot;&lt;p&gt;&lt;span style=&amp;quot;font-weight: 400;&amp;quot;&gt;&lt;a href=&amp;quot;https://www.revenuecat.com/blog/growth/promotional-offers-sales-app/#h-running-seasonal-campaigns-across-channels-revenuecat-tutorials&amp;quot;&gt;Jump ahead&lt;/a&gt; to the step-by-step for setting up sales and promotional offers in RevenueCat.&lt;/span&gt;&lt;/p&gt;&quot; icon=&quot;warning&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-promotional-offers-essential-reading&quot;&gt;&lt;strong&gt;Promotional offers: essential reading&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Starting off with the fundamentals of why seasonal offers work, how pricing affects behavior, and what to test before you launch.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Link&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Format&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Includes&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=ypW5OG0MzJQ&quot;&gt;Maximizing subscription app revenue with holiday discounts and promotions&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Webinar&lt;/td&gt;&lt;td&gt;How to plan, run, and evaluate seasonal promotions, ft. examples of effective discount structures and campaign timing&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://subclub.com/episode/how-to-re-engage-churned-users-caroline-walthall-quizlet&quot;&gt;How to re-engage churned users — Caroline Walthall, Quizlet&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Podcast episode&lt;/td&gt;&lt;td&gt;Real-world insights on how social proof, flexible plans, and targeted discounts can help re-activate churned users&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/smart-discounting-strategies/&quot;&gt;Smart discounting strategies: When, why, and how to offer deals&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Blog&lt;/td&gt;&lt;td&gt;Techniques for building discount logic and choosing offer types to maximize conversion, while protecting long-term revenue&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-choosing-the-right-promotional-offer&quot;&gt;&lt;strong&gt;Choosing the right promotional offer&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Use these resources to decide which type of promotional offer will create the most lift for your app, from introductory discounts to win-backs and targeted plans.&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Link&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Format&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Includes&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/paywalls-introductory-offers/&quot;&gt;Unlocking growth: How to supercharge your paywalls with offers&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Blog&lt;/td&gt;&lt;td&gt;Guidance on layering offers into paywalls, increasing paywall relevance, and using incentives to improve view-to-trial conversion&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/introductory-offers-apps/&quot;&gt;Introductory offers: a key lever for growth&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Blog&lt;/td&gt;&lt;td&gt;How introductory offers influence behavior, and when to deploy them for maximum impact&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/lifetime-subscriptions/&quot;&gt;A guide to lifetime subscriptions: are they right for your app?&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Blog&lt;/td&gt;&lt;td&gt;The pros and cons of discounted lifetime subscriptions, and when to use them&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/company/introductory-offers-for-revenuecat-web-billing/&quot;&gt;Introductory offers for RevenueCat Web Billing: convert more users with the right first price&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Blog&lt;/td&gt;&lt;td&gt;Instructions to set up web-based introductory offers in RevenueCat&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/guide-to-apple-win-back-offers/&quot;&gt;The beginner’s guide to Apple win-back offers&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Blog&lt;/td&gt;&lt;td&gt;How-to for Apple’s win-back offers, and how to use them to re-engage churned iOS subscribers&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/when-is-the-best-time-to-send-a-win-back-offer/&quot;&gt;When is the best time to send a win-back offer?&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Blog&lt;/td&gt;&lt;td&gt;Understanding churn patterns and when to launch win-back offers, based on user behaviour and subscription lifecycle&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=T92KL7Kw620&quot;&gt;How to win back lost customers: Proven strategies for re-engagement&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Webinar&lt;/td&gt;&lt;td&gt;Real app examples for designing win-back campaigns, including offer types and targeted segmentation&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-running-seasonal-campaigns-across-channels-revenuecat-tutorials&quot;&gt;&lt;strong&gt;Running seasonal campaigns across channels (+ RevenueCat tutorials)&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Whether you’re building on iOS, Android, or web, these resources walk through the exact steps to implement promo pricing, offer codes, and signed subscription offers.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Link&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Format&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Includes&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Platform&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/holiday-sales-for-subscription-apps-in-app-store-connect/&quot;&gt;How to run a holiday sale in App Store Connect for iOS subscription apps&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Blog + video tutorial&lt;/td&gt;&lt;td&gt;Steps to configure discounted pricing and schedule holiday campaigns in the App Store&amp;nbsp;&lt;/td&gt;&lt;td&gt;iOS&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/holiday-sale-google-play-console/&quot;&gt;How to run a holiday sale in Play Console for Android subscription apps&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Blog&lt;/td&gt;&lt;td&gt;Instructions for setting up price changes, configuring promotional pricing, and scheduling discounted periods in Google Play&lt;/td&gt;&lt;td&gt;Android&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/black-friday-web-campaign-for-apps/&quot;&gt;How to run a Black Friday campaign for your app on the web&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Blog&lt;/td&gt;&lt;td&gt;Best practices for web-based promotions, including landing page setup, messaging, and syncing web offers to in-app pricing&lt;/td&gt;&lt;td&gt;Web&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/tools/customer-center/customer-center-promo-offers-apple&quot;&gt;Configuring Apple Promotional Offers for Customer Center&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Developer documentation&lt;/td&gt;&lt;td&gt;How to setup and manage Apple promotional offers directly inside Customer Center&lt;/td&gt;&lt;td&gt;iOS&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/engineering/create-and-track-offer-codes-ios-app/&quot;&gt;Create and track offer codes for your iOS app&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Blog&lt;/td&gt;&lt;td&gt;How to generate, distribute, and monitor promotional codes in RevenueCat for iOS&lt;/td&gt;&lt;td&gt;iOS&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/subscription-guidance/subscription-offers/ios-subscription-offers&quot;&gt;Implementing iOS Subscription Offers with Purchases SDK&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Developer documentation&lt;/td&gt;&lt;td&gt;Technical guidance for setting up and managing subscription offers, including handling eligibility and redeeming promotions&lt;/td&gt;&lt;td&gt;iOS&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/engineering/signing-ios-subscription-offers/&quot;&gt;Signing iOS Subscription Offers&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Blog&lt;/td&gt;&lt;td&gt;How to use RevenueCat to show a retention subscription offer to a recently-cancelled user&lt;/td&gt;&lt;td&gt;iOS&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/subscription-guidance/subscription-offers/google-play-offers&quot;&gt;Setting up your offers in Google Play Console&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Developer documentation&lt;/td&gt;&lt;td&gt;Setup and management for subscription offers in Google Play Console, and how to link them to your RevenueCat configuration&lt;/td&gt;&lt;td&gt;Android&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/tools/customer-center/customer-center-promo-offers-google&quot;&gt;Configuring Google Play promo offers in Customer Center&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Developer documentation&lt;/td&gt;&lt;td&gt;How to display and manage Google Play promo offers via Customer Center in RevenueCat&lt;/td&gt;&lt;td&gt;Android&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/tools/paywalls/creating-paywalls/supporting-offers&quot;&gt;Supporting Offers in RevenueCat Paywalls&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Developer documentation&lt;/td&gt;&lt;td&gt;How to surface seasonal promotions directly inside RevenueCat Paywalls with targeting and A/B testing&lt;/td&gt;&lt;td&gt;iOS, Android, Web&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;Seasonal campaigns work best when supported by strong paywalls, clear pricing, and continuous testing. Whether you’re preparing for a recurring seasonal sale or running a one-off regional promotion, start with one improvement, measure its impact, and iterate.&lt;/p&gt;



&lt;p&gt;Your next steps:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Pick one promotional lever to test&lt;/strong&gt;: a new intro offer, an annual-plan discount, or a targeted win-back&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Benchmark your numbers&lt;/strong&gt; with the &lt;a href=&quot;https://www.revenuecat.com/healthscore/&quot;&gt;RevenueCat App Health Score&lt;/a&gt; to understand where offers can improve performance&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Keep experimenting&lt;/strong&gt; — offers are most effective when they evolve with your audience&lt;/li&gt;
&lt;/ol&gt;
</content:encoded></item><item><title><![CDATA[When pricing becomes product strategy]]></title><description><![CDATA[On the podcast we talk with Ravi about subscriptions as a force multiplier for consumables, why narratives matter more than metrics in goal-setting, and why you might want to try a longer onboarding, or a shorter one.]]></description><link>https://www.revenuecat.com/blog/growth/ravi-mehta-tinder-sub-club-podcast-2025/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/ravi-mehta-tinder-sub-club-podcast-2025/</guid><pubDate>Wed, 26 Nov 2025 14:02:21 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/RC-Blog-Cover-Ravi-Mehta-1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;&lt;a href=&quot;https://www.linkedin.com/in/ravimehta/&quot;&gt;Ravi Mehta&lt;/a&gt; knows the consumer monetization business better than most. During his time as Chief Product Officer at &lt;a href=&quot;https://www.lifeattinder.com/&quot;&gt;Tinder&lt;/a&gt;, he helped shape the multi-tier subscription system that redefined how consumer apps grow and earn. Now he works with startups as a hands-on advisor, helping them fine-tune pricing, onboarding, and product strategy.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;This week on the Sub Club podcast, we talked with Ravi about why subscriptions and consumables work better together, how to design pricing that meets users where they are, and why your onboarding might need to get longer (or shorter).&lt;/p&gt;



&lt;iframe loading=&quot;lazy&quot; width=&quot;100%&quot; height=&quot;180&quot; frameborder=&quot;no&quot; scrolling=&quot;no&quot; seamless=&quot;&quot; src=&quot;https://share.transistor.fm/e/a3da6cf0?color=FFFFFF&amp;amp;background=30343C&quot;&gt;&lt;/iframe&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;How Tinder Captures More Value With Tiered Pricing and Consumables — Ravi Mehta&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/AWI3rofh0BA?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-filling-the-demand-curve&quot;&gt;Filling the demand curve&lt;/h2&gt;



&lt;p&gt;Ravi’s “famous chart” from his time at Tinder has become a benchmark for understanding consumer willingness to pay. By layering multiple subscription tiers with à la carte purchases, Tinder found ways to serve users across the full demand curve, from casual free users to high-value “whales.” The lesson: there’s money left on both sides of a single-tier subscription.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;693&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/c2ab5b25-b7bb-4b69-858c-c69a68f34789_1600x1083-1024x693.webp&quot; alt=&quot;Chat showing willingness to pay vs. number of paying users&quot; class=&quot;wp-image-48435&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/c2ab5b25-b7bb-4b69-858c-c69a68f34789_1600x1083-1024x693.webp 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/c2ab5b25-b7bb-4b69-858c-c69a68f34789_1600x1083-300x203.webp 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/c2ab5b25-b7bb-4b69-858c-c69a68f34789_1600x1083-768x520.webp 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/c2ab5b25-b7bb-4b69-858c-c69a68f34789_1600x1083-50x34.webp 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/c2ab5b25-b7bb-4b69-858c-c69a68f34789_1600x1083-59x40.webp 59w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/c2ab5b25-b7bb-4b69-858c-c69a68f34789_1600x1083-685x464.webp 685w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/c2ab5b25-b7bb-4b69-858c-c69a68f34789_1600x1083-696x471.webp 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/c2ab5b25-b7bb-4b69-858c-c69a68f34789_1600x1083-560x379.webp 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/c2ab5b25-b7bb-4b69-858c-c69a68f34789_1600x1083-437x296.webp 437w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/c2ab5b25-b7bb-4b69-858c-c69a68f34789_1600x1083-697x472.webp 697w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/c2ab5b25-b7bb-4b69-858c-c69a68f34789_1600x1083-80x54.webp 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/c2ab5b25-b7bb-4b69-858c-c69a68f34789_1600x1083-48x33.webp 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/c2ab5b25-b7bb-4b69-858c-c69a68f34789_1600x1083.webp 1456w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-free-to-play-not-free-to-fail&quot;&gt;Free to play, not free to fail&lt;/h2&gt;



&lt;p&gt;Tinder’s biggest breakthrough was the decision to go free. Opening access built the network effects that make the product work, while consumables and premium tiers monetized the subset of users who wanted more. As Ravi explains, “subscription tiers are force multipliers for microtransactions.”&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-long-or-short-onboarding&quot;&gt;Long or short onboarding?&lt;/h2&gt;



&lt;p&gt;Working with healthcare startup &lt;a href=&quot;https://sesamecare.com/&quot;&gt;Sesame Care&lt;/a&gt;, Ravi found that expanding a three-step signup to twenty-five steps increased conversion by 40%. But the same rule doesn’t apply everywhere. Tinder’s success came from stripping onboarding down to seconds. The key is knowing when friction builds confidence and when it kills it.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-narratives-over-numbers&quot;&gt;Narratives over numbers&lt;/h2&gt;



&lt;p&gt;Ravi also shared his framework for goal setting, NCTs (Narratives, Commitments, and Tasks), a simple alternative to OKRs that keeps teams focused on the why, what, and how of their work. And when it comes to growth, his advice is clear: don’t chase vanity metrics; build systems that create lasting value and predictable revenue.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-conclusion&quot;&gt;Conclusion&lt;/h2&gt;



&lt;p&gt;These are just a few of the topics we covered in our conversation with Ravi. To hear more on monetization strategy, onboarding psychology, and how to build products users love to pay for, check out this week’s episode of the Sub Club podcast.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[The definitive guide to video paywalls]]></title><description><![CDATA[How you can leverage video to explain value, build trust, and boost paywall conversion rate]]></description><link>https://www.revenuecat.com/blog/growth/video-paywalls/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/video-paywalls/</guid><pubDate>Tue, 25 Nov 2025 12:20:18 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Using-video-paywalls-to-boost-conversion.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Back in the day, ‘video paywalls’ simply meant a video locked behind a paywall, like a content creator selling access to their course. These days, the term has evolved into something more exciting: embedding video on your paywall. Say goodbye to boring, static paywalls and hello to interactive experiences that capture attention and communicate value in seconds.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Videos are a powerful way to boost paywall performance and convey your value clearly. &lt;/strong&gt;While there’s limited data on testing videos specifically on paywalls, we know video as a medium works: it communicates quickly and enhances emotional recall. For example, &lt;a href=&quot;https://www.fitnessai.com/&quot;&gt;Fitness AI&lt;/a&gt; shared at an App Promotion Summit that adding a video to their paywall resulted in roughly an 80% revenue increase, and they still use a video on their paywall today.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-wp-embed is-provider-wistia-inc wp-block-embed-wistia-inc&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; class=&quot;wp-embedded-content&quot; sandbox=&quot;allow-scripts&quot; security=&quot;restricted&quot; title=&quot;Fitness AI - Video on paywall&quot; src=&quot;https://fast.wistia.net/embed/iframe/tm8pnvnyih?dnt=1#?secret=GkPBbt90GA&quot; data-secret=&quot;GkPBbt90GA&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; width=&quot;346&quot; height=&quot;750&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;If you’ve read my article on &lt;a href=&quot;https://www.revenuecat.com/blog/growth/weird-paywalls-drive-subscription-growth/&quot;&gt;weird paywalls&lt;/a&gt;, you’ll know I have a soft spot for quirky, offbeat designs. One of my favorite examples is &lt;strong&gt;Water Llama&lt;/strong&gt;, a water-tracking app that uses a playful feature video to bring its paywall to life by showing the adorable llama water tracker filling up right on the screen.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-wp-embed is-provider-wistia-inc wp-block-embed-wistia-inc&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; class=&quot;wp-embedded-content&quot; sandbox=&quot;allow-scripts&quot; security=&quot;restricted&quot; title=&quot;WaterLlama - Animated Carousel Video&quot; src=&quot;https://fast.wistia.net/embed/iframe/6s6h4jcyw5?dnt=1#?secret=9sZM6TA5W9&quot; data-secret=&quot;9sZM6TA5W9&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; width=&quot;346&quot; height=&quot;750&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;While adding a llama to your paywall might be a step too far, adding a video is a move worth considering, whether on your paywall or during onboarding.&lt;/p&gt;



&lt;p&gt;So, read on for who should (and shouldn’t) consider a video paywall, as well as how to test and implement one effectively to set yourself up for success.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-quickfire-pros-and-cons-of-adding-video-to-your-paywall&quot;&gt;Quickfire: Pros and cons of adding video to your paywall&lt;/h2&gt;



&lt;p&gt;While videos are more common for certain app categories and audiences, that shouldn’t stop you from considering them. Ultimately, video paywalls can help you achieve four key goals — these should be the drivers of whether you use videos on your paywalls, rather than the app’s category. But, there are a few drawbacks to consider as well.&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Convey emotion: &lt;/strong&gt;videos can do this far more effectively than static images or text&lt;br&gt;&lt;br&gt;&lt;strong&gt;Visually explain your app: &lt;/strong&gt;perfect for photo, video, health, and wellness apps, or any app where showing functionality beyond the paywall helps users understand value&lt;br&gt;&lt;br&gt;&lt;strong&gt;Build trust and show transformation: &lt;/strong&gt;demonstrate the impact of using your app and reassure users that it will deliver results&lt;br&gt;&lt;br&gt;&lt;strong&gt;Capture attention: &lt;/strong&gt;slow the user down to capture their focus and convey your message&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Increased load time&lt;/strong&gt; can hurt performance&lt;br&gt;&lt;br&gt;&lt;strong&gt;Potential distraction or overwhelm&lt;/strong&gt;, especially if users expect a quick, functional experience&lt;br&gt;&lt;br&gt;&lt;strong&gt;High-quality asset requirements&lt;/strong&gt; demand extra time, skill, and budget&lt;br&gt;&lt;br&gt;&lt;strong&gt;Testing complexity&lt;/strong&gt;, with so many variables at play, can make it difficult to pinpoint why a video isn’t improving conversions&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;At the end of the day, whether a video paywall is right for your app depends on your audience, category, and goals, but it’s always worth testing before making a final call. Read on to dive deeper into whether video paywalls are right for your app.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-when-should-you-add-video-to-your-paywall&quot;&gt;When should you add video to your paywall?&lt;/h2&gt;



&lt;p&gt;My own experience has shown testing videos in your onboarding and paywall can improve not only the number of trials started, but also the &lt;a href=&quot;https://www.revenuecat.com/glossary/#trial-conversion-rate&quot;&gt;trial-to-paid conversion rate&lt;/a&gt; — especially with how-to videos that help your audience understand the real value of your app.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;A great video can elevate your paywall and improve conversion, but the wrong one can slow it down or muddy the message. Here’s how to tell when your app may benefit from a video-first paywall.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-when-emotion-drives-conversion&quot;&gt;1. When emotion drives conversion&lt;/h3&gt;



&lt;p&gt;Apps in the fitness, wellness, or habit space often &lt;a href=&quot;https://www.revenuecat.com/blog/growth/solve-app-problems-emotionally/&quot;&gt;sell a &lt;em&gt;feeling&lt;/em&gt;&lt;/a&gt;, and video is perfect for capturing that. Take &lt;a href=&quot;https://apps.apple.com/us/app/cardi-mate-heart-rate-monitor/id1570842053&quot;&gt;Cardi Mate&lt;/a&gt;, a heart-tracking app, for example. Their paywall uses a full-screen background video showing the app in action while clearly conveying both the app’s value and the feeling of calm and control over your heart health.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-wp-embed is-provider-wistia-inc wp-block-embed-wistia-inc&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; class=&quot;wp-embedded-content&quot; sandbox=&quot;allow-scripts&quot; security=&quot;restricted&quot; title=&quot;Cardi Mate - Background video&quot; src=&quot;https://fast.wistia.net/embed/iframe/kode2c9ft7?dnt=1#?secret=ifLwrlvOXS&quot; data-secret=&quot;ifLwrlvOXS&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; width=&quot;346&quot; height=&quot;750&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;It’s layered with minimum copy and a subtle overlay at the bottom that conveys:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Social proof (number of subscribers)&lt;/li&gt;



&lt;li&gt;Trial/payment setup&lt;/li&gt;



&lt;li&gt;A brief description of the app&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;This combination helps users feel the value of the app immediately, boosting their likelihood to convert. Clicking ‘Continue’ takes you straight to payment with no extra screens and no friction.Another great example is &lt;a href=&quot;https://loona.app/&quot;&gt;Loóna&lt;/a&gt;, a sleep app. The onboarding features relaxing music, instantly fostering a sense of zen. The video on the paywall is simple but soothing, perfectly capturing the state that Loóna helps users achieve (though their &lt;a href=&quot;https://www.revenuecat.com/blog/growth/is-monetization-hurting-your-apps-user-experience/&quot;&gt;dark UX&lt;/a&gt; way of reporting pricing definitely isn’t as chill).&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-wp-embed is-provider-wistia-inc wp-block-embed-wistia-inc&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; class=&quot;wp-embedded-content&quot; sandbox=&quot;allow-scripts&quot; security=&quot;restricted&quot; title=&quot;Loona - video top of paywall&quot; src=&quot;https://fast.wistia.net/embed/iframe/b35kvtaecz?dnt=1#?secret=SPSColhjyK&quot; data-secret=&quot;SPSColhjyK&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; width=&quot;346&quot; height=&quot;750&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;2-when-visuals-explain-the-value-faster-than-words&quot;&gt;2. When visuals explain the value faster than words&lt;/h3&gt;



&lt;p&gt;If a picture’s worth a thousand words, a video’s worth more than Jeff Bezos’s portfolio. Let’s get the obvious out of the way: photo and video apps. &lt;strong&gt;Any app that relies heavily on visual content naturally benefits from a more visual way of showcasing its features.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Take &lt;a href=&quot;https://www.capcut.com/tools/desktop-video-editor?download_channel=capcutpc_pmax&amp;amp;utm_medium=pmax&amp;amp;utm_source=googleadwords_int&amp;amp;pid=359289&amp;amp;af_c_id=22895025581&amp;amp;adset_id=&amp;amp;ad_id=&amp;amp;keyword_name=&amp;amp;matchtype=&amp;amp;placement=&amp;amp;targetid=&amp;amp;channel=x&amp;amp;gad_source=1&amp;amp;gad_campaignid=22895028443&amp;amp;gbraid=0AAAAACROvhnoPmjhISKTtp4AA3fAT4Cn7&amp;amp;gclid=CjwKCAjwx-zHBhBhEiwA7Kjq6_w7bYzWQMXM3yVsrN97Fi438RYqwY0TU_QXEmvbyoXJS7Sq5GzJFxoC8dUQAvD_BwE&quot;&gt;CapCut&lt;/a&gt;, an AI-powered video and image editor owned by ByteDance (TikTok’s parent company). Like Water Llama, CapCut uses video on its paywall to highlight key features, automatically displaying them one by one with short clips that show exactly how each feature works.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-wp-embed is-provider-wistia-inc wp-block-embed-wistia-inc&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; class=&quot;wp-embedded-content&quot; sandbox=&quot;allow-scripts&quot; security=&quot;restricted&quot; title=&quot;CapCut - Animated Header Video&quot; src=&quot;https://fast.wistia.net/embed/iframe/kdac8t528q?dnt=1#?secret=Q0bzJjqZAs&quot; data-secret=&quot;Q0bzJjqZAs&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; width=&quot;346&quot; height=&quot;750&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;Videos are invaluable when used to demonstrate how an app works, or to walk users through key features right after download.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;3-when-transformation-or-trust-needs-to-be-proven&quot;&gt;3. When transformation or trust needs to be proven&lt;/h3&gt;



&lt;p&gt;Now, for a more &lt;em&gt;unusual&lt;/em&gt; example from my exploration of video paywalls. I downloaded 50+ apps to test their paywalls — partly because it’s hard to confirm whether an app shows a video upfront, and partly because my memory isn’t perfect. (Shockingly, I don’t remember &lt;em&gt;every&lt;/em&gt; paywall I’ve ever seen.)&lt;/p&gt;



&lt;p&gt;One app I tested out, which I came across through &lt;a href=&quot;https://www.retention.blog/p/creative-paywall-inspiration-vo&quot;&gt;Jacob Rushfinn’s newsletter&lt;/a&gt;, is &lt;a href=&quot;https://apps.apple.com/gb/app/dr-kegel-for-mens-health/id1470065487&quot;&gt;Dr Kegal&lt;/a&gt;. At first, I thought nothing of it and was simply excited to try out the app he recommended. But this app did something unexpected: it forced users to watch a 30+ second video before even showing the paywall. A major faux pas in the video world.&lt;/p&gt;



&lt;p&gt;Here’s the kicker: I now have an app on my phone, as a woman, that helps with erection duration… It’s a topic that many users might feel uncomfortable discussing, or unsure whether exercises will actually help. The paywall video shows multiple men who have benefited from the app, establishing trust and credibility. Once it finishes, the video remains at the top of the paywall, reinforcing the social proof and value before users decide to subscribe.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;472&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Dr-Kegal-Screenshot-Video-top-472x1024.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-48401&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Dr-Kegal-Screenshot-Video-top-472x1024.jpg 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Dr-Kegal-Screenshot-Video-top-138x300.jpg 138w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Dr-Kegal-Screenshot-Video-top-768x1665.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Dr-Kegal-Screenshot-Video-top-709x1536.jpg 709w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Dr-Kegal-Screenshot-Video-top-945x2048.jpg 945w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Dr-Kegal-Screenshot-Video-top-23x50.jpg 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Dr-Kegal-Screenshot-Video-top-18x40.jpg 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Dr-Kegal-Screenshot-Video-top-214x464.jpg 214w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Dr-Kegal-Screenshot-Video-top-696x1509.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Dr-Kegal-Screenshot-Video-top-258x560.jpg 258w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Dr-Kegal-Screenshot-Video-top-137x296.jpg 137w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Dr-Kegal-Screenshot-Video-top-218x472.jpg 218w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Dr-Kegal-Screenshot-Video-top-37x80.jpg 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Dr-Kegal-Screenshot-Video-top-22x48.jpg 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Dr-Kegal-Screenshot-Video-top.jpg 1179w&quot; sizes=&quot;auto, (max-width: 472px) 100vw, 472px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;A secondary video on the scrollable paywall then dives into the science behind the app and explains more about how it works.&lt;/p&gt;



&lt;p&gt;In situations where users may be skeptical of an app — or uneasy about its topic — a video on the &lt;a href=&quot;https://www.revenuecat.com/blog/growth/paywalls-unexpected-uses/&quot;&gt;paywall can help build trust&lt;/a&gt; at that critical moment. Another excellent use case is in a competitive market; by building trust that you offer something different.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;4-when-attention-is-scarce-and-video-helps-capture-it&quot;&gt;4. When attention is scarce (and video helps capture it)&lt;/h3&gt;



&lt;p&gt;Your audience type can influence whether you prioritize video. &lt;a href=&quot;https://www.askattest.com/blog/research/gen-z-media-consumption&quot;&gt;Data suggests that younger audiences&lt;/a&gt; prefer video explanations over text, making video paywalls worth testing for these groups. With older &lt;a href=&quot;https://civicscience.com/3-key-social-media-trends-among-gen-z-and-millennials&quot;&gt;generations spending less time on social media&lt;/a&gt;, we’re seeing apps mimic social platforms more and more — not just with short-form video, but also with Instagram-style story swipes and bite-sized content. Let’s be honest: most of us don’t read thoroughly anymore.&lt;/p&gt;



&lt;p&gt;While this guide focuses on using video on the paywall, you can also use it in onboarding or even create a two-step paywall (video → paywall with trial/payment info) to capture attention and understanding before the payment screen.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.linkedin.com/in/sylvaingauchet/&quot;&gt;Sylvain Gauchet&lt;/a&gt;, Growth Consultant and author of the &lt;a href=&quot;https://growthgems.substack.com/&quot;&gt;&lt;em&gt;Growth Gems&lt;/em&gt;&lt;/a&gt; newsletter, recently highlighted the &lt;a href=&quot;https://subclub.com/episode/how-to-build-more-successful-paywalls-sylvain-gauchet&quot;&gt;growing trend of paywall-onboarding blurring&lt;/a&gt;:&amp;nbsp;&lt;/p&gt;



&lt;p&gt;“I’ve been seeing multiscreen paywalls more and more, especially for free trials, where instead of showing the bleakest timeline, they actually break it down in multiple screens…it blurs the line between what’s onboarding and what’s a paywall. It’s like if you have a screen before the paywall, is that part of the onboarding? Is that part of the paywall? But, it gives you that possibility to show benefits, explain better the actual transactional aspect, and a last-minute pitch or recap to push people over the edge.”&lt;/p&gt;



&lt;p&gt;I’m currently testing this approach for a Gen Z app. We’re swapping the four rapid-fire feature screens (image + text) with video + text feature screens, leading into the paywall to ensure users fully understand the app before being asked to pay.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;when-should-apps-avoid-using-a-video-on-their-paywall&quot;&gt;When should apps avoid using a video on their paywall?&lt;/h2&gt;



&lt;p&gt;It’s important to note that video requires more effort than other types of paywall — specifically, it’s more effort to test and validate. My recommendation is to only introduce video (and test it) after you’ve &lt;strong&gt;validated your messaging&lt;/strong&gt; and &lt;strong&gt;identified which features drive users to pay&lt;/strong&gt;. You can then test your paywall, and know it’s specifically the &lt;em&gt;video&lt;/em&gt; driving any changes. If you skip straight to adding a video it often results in slower, less effective testing and lower success rates than if you optimize your copy and core features first.&lt;/p&gt;



&lt;p&gt;So if you’re yet to find &lt;a href=&quot;https://www.revenuecat.com/blog/growth/product-market-fit-subscription-apps/&quot;&gt;product-market fit&lt;/a&gt;, or identify &lt;a href=&quot;https://www.revenuecat.com/blog/growth/customer-validation-subscription-app/&quot;&gt;whether users are really willing to pay&lt;/a&gt;, you may want to hold off before adding videos. There are a few other cases where video may be less relevant:&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;1-if-your-audience-has-lower-bandwidth-or-limited-data&quot;&gt;1. If your audience has lower bandwidth or limited data&amp;nbsp;&lt;/h3&gt;



&lt;p&gt;Even if you optimize video size for faster loading (&lt;a href=&quot;https://www.revenuecat.com/feature/paywalls/&quot;&gt;RevenueCat’s Paywall Builder&lt;/a&gt; does this automatically), videos still impact load time. If your users have slower internet speeds, limited data, or unreliable wifi, a video paywall could create friction.&lt;/p&gt;



&lt;p&gt;You may be thinking “But Daphne, how do I know what my users’ internet speed is?”, but that’s not quite what I mean. Consider what your app does and when it’s most-used. Apps users look to when hiking or camping, for example, need to function with minimal service. If you know your audience is older, then perhaps their internet won’t be as fast as if you’re targeting Gen Z gamers who rely on lightning fibre connections. Likewise, if the markets you’re selling to are in more rural areas, or countries whose internet infrastructure is slower — these are all elements to consider.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;2-if-your-apps-usp-is-being-simple-and-functional&quot;&gt;2. If your app’s USP is being simple and functional&lt;/h3&gt;



&lt;p&gt;For straightforward utility apps, a video paywall can actually get in the way. If speed is the user’s priority, a video may distract them from their end goal. For example, if someone just wants to quickly scan and upload a passport copy, the last thing they want is to sit through a video first; it could just frustrate them. You need to weigh up whether a video will actually help your user convert — or if you just think it will. This is also where testing comes in (stay tuned for that)…&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;3-if-you-dont-have-or-cant-get-high-quality-videos&quot;&gt;3. If you don’t have (or can’t get) high-quality videos&lt;/h3&gt;



&lt;p&gt;While AI has made video production easier, creating effective videos still requires time and investment. Whether animated or live-action, you can’t cut corners on quality. A low-quality video on your paywall can do more harm than good.&lt;/p&gt;



&lt;p&gt;You’ll also need to test different formats to find what resonates with your audience, so be mindful of the time and resources required before committing.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;testing-and-implementing-a-video-paywall&quot;&gt;Testing and implementing a video paywall&lt;/h2&gt;



&lt;p&gt;Okay, you’ve got your messaging airtight, you know users want the product, and video seems the right fit for your paywall. How do you go about testing and launching a video paywall?&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;1-define-your-goal-for-testing-video&quot;&gt;1. Define your goal for testing video&lt;/h3&gt;



&lt;p&gt;We’ve covered the main reasons why apps might use video on their paywall:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Convey emotion&lt;/li&gt;



&lt;li&gt;Visually explain features&lt;/li&gt;



&lt;li&gt;Communicate transformation and build trust&lt;/li&gt;



&lt;li&gt;Capture attention&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Clarifying your goal will help determine what format and setup you should test, e.g. if you’re focused on explaining your app better, you probably want to test a feature carousel or a full video background.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;2-decide-on-the-video-format&quot;&gt;2. Decide on the video format&lt;/h3&gt;



&lt;p&gt;Next, identify which format best supports your goal. As you’ve seen from the examples, there are several effective ways to integrate video into your paywall:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;At the top of the paywall: &lt;/strong&gt;showcase your app in action and immediately engage users&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;As a background: &lt;/strong&gt;add motion and depth to make your paywall feel more dynamic&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;A block within a longer landing page: &lt;/strong&gt;ideal for premium apps that need to explain features or value propositions in more detail, keeping users engaged across a scrollable paywall&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;In a carousel: &lt;/strong&gt;demonstrate multiple features in short, digestible clips&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;First screen of your paywall: &lt;/strong&gt;capture attention and understanding before moving into pricing or trial details&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;You can also combine formats, as seen with Dr. Kegal, which blends multiple videos across its paywall. Another great example is &lt;a href=&quot;https://reface.ai/&quot;&gt;Reface&lt;/a&gt;, the AI-powered face swap app, which uses a carousel that doubles as a looping background video, creating a lively, interactive experience.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-wp-embed is-provider-wistia-inc wp-block-embed-wistia-inc&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; class=&quot;wp-embedded-content&quot; sandbox=&quot;allow-scripts&quot; security=&quot;restricted&quot; title=&quot;Reface - Background + Carousel Video&quot; src=&quot;https://fast.wistia.net/embed/iframe/9l6xnbmqmu?dnt=1#?secret=wROGjMCwZl&quot; data-secret=&quot;wROGjMCwZl&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; width=&quot;346&quot; height=&quot;750&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;For apps that want to showcase an animation, a video can also be used, especially if you are using a paywall builder that doesn’t support animation. &lt;a href=&quot;https://www.revenuecat.com/blog/growth/paywall-conversion-boosters/&quot;&gt;Animations are a great way to boost engagement&lt;/a&gt;. For example, &lt;a href=&quot;https://www.duolingo.com/&quot;&gt;Duolingo&lt;/a&gt;, the language learning app, uses a little animation of Duo, their owl, on their paywall.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-wp-embed is-provider-wistia-inc wp-block-embed-wistia-inc&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; class=&quot;wp-embedded-content&quot; sandbox=&quot;allow-scripts&quot; security=&quot;restricted&quot; title=&quot;Duolingo - Paywall animation Video&quot; src=&quot;https://fast.wistia.net/embed/iframe/2v9x66di81?dnt=1#?secret=WcCH5fDzsW&quot; data-secret=&quot;WcCH5fDzsW&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; width=&quot;346&quot; height=&quot;750&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;While apps like Reface likely use code to implement this, a quick way to test a similar effect — especially if your paywall builder doesn’t support animation — is by using a short, looped video or GIF. That said, it’s worth noting that animations implemented directly with code will generally load faster than videos.&lt;/p&gt;



&lt;p&gt;Your goal and chosen format will also help determine where to test the video. Some apps, like CapCut, use the same video across all paywalls because the features showcased remain universally relevant. But if your goal is to help new users understand the app’s value, you might choose to test it only on the initial paywall.&lt;/p&gt;



&lt;p&gt;For example: &lt;a href=&quot;https://fitonapp.com/&quot;&gt;FitOn&lt;/a&gt;, a fitness app with an intense paywall video, features upbeat music, flashing visuals, and full-screen energy. It’s highly effective for new users, giving instant context and excitement about what the app offers. But forcing returning users to watch that same video every time could be more irritating than inspiring.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-wp-embed is-provider-wistia-inc wp-block-embed-wistia-inc&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; class=&quot;wp-embedded-content&quot; sandbox=&quot;allow-scripts&quot; security=&quot;restricted&quot; title=&quot;FitOn - Video paywall&quot; src=&quot;https://fast.wistia.net/embed/iframe/a06jhejdtg?dnt=1#?secret=WOqnRC1ckG&quot; data-secret=&quot;WOqnRC1ckG&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; width=&quot;346&quot; height=&quot;750&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;When I returned to their app, the paywall I saw after that was a simpler feature carousel instead:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;472&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-23-472x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-48397&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-23-472x1024.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-23-138x300.png 138w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-23-708x1536.png 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-23-23x50.png 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-23-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-23-214x464.png 214w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-23-696x1509.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-23-258x560.png 258w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-23-137x296.png 137w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-23-218x472.png 218w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-23-37x80.png 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-23-22x48.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-23.png 738w&quot; sizes=&quot;auto, (max-width: 472px) 100vw, 472px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;3-what-content-to-include-in-the-video-and-the-rest-of-your-paywall&quot;&gt;3. What content to include in the video (and the rest of your paywall)&lt;/h3&gt;



&lt;p&gt;When it comes to your video content, keep these best practices in mind:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Keep the video short:&lt;/strong&gt; in most cases, no more than 15–30 seconds&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Ensure it works without sound:&lt;/strong&gt; most users won’t have sound on — all of the examples we’ve discussed work silently; only Dr. Kegal uses a voiceover (and even then, they include subtitles)&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Start with a strong visual hook:&lt;/strong&gt; at the start of the video, especially if the video is used to communicate the value of the app&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Keep in mind, cognitive load can quickly become overwhelming when combining video, copy, and calls to action. Simplicity almost always wins. You’ll notice in the examples that the more detailed or dynamic the video, the simpler and more minimal the supporting copy tends to be.&lt;/p&gt;



&lt;p&gt;If you’re unsure what kind of video to test, a great starting point is a simple walkthrough that highlights how your app works, showcasing the key benefits and features in a clear, engaging way.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;4-setting-up-the-video&quot;&gt;4. Setting up the video&lt;/h3&gt;



&lt;p&gt;When setting up your video paywall, there are a few key considerations:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Loop vs. play once: &lt;/strong&gt;most paywall videos tend to loop – users may read the text first or miss the beginning, especially if they’re multitasking (or, like me, have ADHD).&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Autoplay vs. click-to-play: &lt;/strong&gt;should your video play automatically, or only when tapped? Autoplay is the standard, as it immediately captures attention. But click-to-play can work well for optional content, like user testimonials or deeper feature explanations, keeping the paywall cleaner and less distracting.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Mute vs. sound on: &lt;/strong&gt;as mentioned above, many users will have sound off when using an app, and may even get frustrated if the sound suddenly goes on (or off) or they can’t understand what is going on in the video. My advice: Keep it muted by default. If there is dialogue in your video, I beg you to use captions. It will &lt;a href=&quot;https://www.3playmedia.com/blog/studies-find-captions-improve-engagement/&quot;&gt;improve engagement&lt;/a&gt;, accessibility, and the user experience.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Of course, there are exceptions. Let’s return to the example of FitOn. Their high-energy, full-screen video doesn’t loop or auto-mute because it’s designed to immerse users completely. As the video ends, it fades out smoothly to direct attention toward the ‘Subscribe’ button, creating a natural flow rather than a jarring stop. Since the video is longer and highly dynamic, muting it wouldn’t make sense in this context, and looping it would be overwhelming.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-wp-embed is-provider-wistia-inc wp-block-embed-wistia-inc&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; class=&quot;wp-embedded-content&quot; sandbox=&quot;allow-scripts&quot; security=&quot;restricted&quot; title=&quot;FitOn - Video paywall&quot; src=&quot;https://fast.wistia.net/embed/iframe/a06jhejdtg?dnt=1#?secret=WOqnRC1ckG&quot; data-secret=&quot;WOqnRC1ckG&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; width=&quot;346&quot; height=&quot;750&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;Additionally, make sure to optimize your video for load time. While load time matters less in an app than on web, it still impacts performance and user experience.&lt;/p&gt;



&lt;p&gt;If you’re using RevenueCat’s paywall builder, the good news is that it &lt;a href=&quot;https://www.revenuecat.com/docs/tools/paywalls/creating-paywalls/components#video-component&quot;&gt;automatically optimizes the video&lt;/a&gt; following the best practices:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Initial load: &lt;/strong&gt;the video thumbnail appears immediately&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Progressive load:&lt;/strong&gt; a lower-resolution version plays first for speed, then transitions to high quality&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Local caching:&lt;/strong&gt; the video is stored locally for faster playback on subsequent views&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Bandwidth optimization: &lt;/strong&gt;data usage is minimized for a smoother experience&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;If you’re implementing this on a native paywall, that’s the moment to smile sweetly at your developer and beg for help… it’s their time to shine.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;your-testing-roadmap&quot;&gt;Your testing roadmap&lt;/h3&gt;



&lt;p&gt;You’re testing a video for a good reason (I hope). So please don’t test one video, and if it flops, swear off video forever. Then two years later, when a bright-eyed new Product Manager suggests, “Hey, maybe we could try a video on the paywall…,” you immediately cut them off: “No, we tested that two years ago. Video doesn’t work for us.”&amp;nbsp;&lt;/p&gt;



&lt;p&gt;One test doesn’t prove that video paywalls don’t work, it just means &lt;em&gt;that version&lt;/em&gt; didn’t.&lt;/p&gt;



&lt;p&gt;Based on your goal, focus your testing on three main elements:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Content: &lt;/strong&gt;what the video covers, how it starts, and how long it is&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Placement: &lt;/strong&gt;where the video sits on your paywall (and if you have a multi-step paywall, on which screen)&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Setup: &lt;/strong&gt;the various technical and behavioral setup options we discussed earlier&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;That’s also the order I recommend testing in. For most apps, especially single-screen paywalls, content will have the biggest impact.&lt;/p&gt;



&lt;p&gt;Here’s what your high-level testing plan might look like:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Baseline: &lt;/strong&gt;start with your current static paywall and record conversion and engagement metrics&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Experiment 1: &lt;/strong&gt;swap the hero image for a short looping video (keeping copy the same). Measure the lift&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Experiment 2: &lt;/strong&gt;test different video types, e.g. a feature demo vs. an emotional story, to see which drives better conversions&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Experiment 3–X: &lt;/strong&gt;combine your top-performing video with tweaks to hooks, placement, or length for further optimization&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;does-video-deserve-a-spot-on-your-paywall&quot;&gt;Does video deserve a spot on your paywall?&lt;/h2&gt;



&lt;p&gt;Your paywall is your make-or-break moment. In that split second, users decide whether your app feels worth it. A video gives you another dimension to make that decision easier, to help users feel the outcome, see the transformation, and stay just a little longer.&lt;/p&gt;



&lt;p&gt;Not every app needs a video, but many should at least test it, especially with tools like &lt;a href=&quot;https://www.revenuecat.com/blog/growth/announcing-revenuecat-paywalls-v2/&quot;&gt;RevenueCat Paywalls&lt;/a&gt;, which make it easier than ever to level up your paywall experience.&lt;/p&gt;



&lt;p&gt;When done well, video can boost conversions, strengthen your brand, and make your paywall stand out in a sea of sameness.&lt;/p&gt;



&lt;p&gt;So whether it’s an animation of a llama getting hydrated or a user unlocking their fitness potential, don’t be afraid to bring your paywall to life with a video that adds real value.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[October product updates: Paywall videos, smarter support, and a big step onto the web]]></title><description><![CDATA[New web paywalls, richer Paywall design, Unity support, and smarter Zendesk and Intercom workflows.]]></description><link>https://www.revenuecat.com/blog/company/october-2025-product-updates-paywalls-web-videos-support-integrations/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/company/october-2025-product-updates-paywalls-web-videos-support-integrations/</guid><pubDate>Tue, 25 Nov 2025 11:50:33 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Product-updates-October-2025.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;If your growth playbook includes “iterate faster” and “meet customers where they are,” this release is for you. RevenueCat’s October product releases focus on exactly that.&lt;/p&gt;



&lt;p&gt;You can now take Paywalls beyond the app and into the browser, make them richer with video and new layout tools, and give support teams instant subscription context right where they work. Plus a handful of quieter upgrades that make daily life smoother.&lt;/p&gt;



&lt;p&gt;Here’s what’s new.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-meet-the-revenuecat-changelog&quot;&gt;Meet the RevenueCat changelog&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;511&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Changelog-4-1024x511.png&quot; alt=&quot;&quot; class=&quot;wp-image-48377&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Changelog-4-1024x511.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Changelog-4-300x150.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Changelog-4-768x383.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Changelog-4-1536x766.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Changelog-4-50x25.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Changelog-4-80x40.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Changelog-4-696x347.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Changelog-4-560x279.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Changelog-4-840x419.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Changelog-4-48x24.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Changelog-4.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Now you can track every release in one place. The changelog lists new features, improvements, and fixes so you always know what’s been shipped. It’s the easiest way to stay current and share updates across your team.&lt;/p&gt;



&lt;p&gt;If you want to keep an eye on what’s landing week to week, start there. &lt;a href=&quot;https://www.revenuecat.com/changelog&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;View the changelog ↗&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-introducing-paywalls-on-the-web&quot;&gt;Introducing Paywalls on the web&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;512&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Web-Paywalls-1024x512.png&quot; alt=&quot;&quot; class=&quot;wp-image-48379&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Web-Paywalls-1024x512.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Web-Paywalls-300x150.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Web-Paywalls-768x384.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Web-Paywalls-1536x768.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Web-Paywalls-50x25.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Web-Paywalls-80x40.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Web-Paywalls-696x348.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Web-Paywalls-560x280.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Web-Paywalls-840x420.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Web-Paywalls-48x24.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Web-Paywalls.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;RevenueCat Paywalls now work in the browser, not just inside iOS, Android or other mobile apps.&lt;/p&gt;



&lt;p&gt;That means you can:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Design the same high-performing paywalls you already use on mobile.&lt;/li&gt;



&lt;li&gt;Drop them into landing pages, ads, newsletters, or any link-based flow with web purchase links or the Web SDK.&lt;/li&gt;



&lt;li&gt;Update instantly without shipping new code or waiting for an app release.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Web paywalls give you a clean path from “someone clicked a link” to “someone subscribed,” while keeping all your testing and targeting in one place.&lt;/p&gt;



&lt;p&gt;Web Purchase Links already give you a fast path to sell on the web; Paywalls on the web make those pages customizable, testable, and far easier to optimize.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://e.customeriomail.com/e/c/eyJlbWFpbF9pZCI6ImRnVGYwUW9EQUs3dEY2M3RGd0dhV2R2SkhWR082ZHhIZFZ1OUl3MD0iLCJocmVmIjoiaHR0cHM6Ly93d3cucmV2ZW51ZWNhdC5jb20vZG9jcy93ZWIvd2ViLWJpbGxpbmcvcGF5d2FsbHM_dXRtX2NhbXBhaWduPU9jdG9iZXIrTmV3c2xldHRlclx1MDAyNnV0bV9jb250ZW50PU9jdG9iZXIrTmV3c2xldHRlclx1MDAyNnV0bV9tZWRpdW09ZW1haWxfYWN0aW9uXHUwMDI2dXRtX3NvdXJjZT1jdXN0b21lci5pbyIsImludGVybmFsIjoiZGZkMTBhMGRiZDA2YWVlZDE3IiwibGlua19pZCI6OTM2MH0/https://www.revenuecat.com/docs/web/web-billing/paywalls&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Check out the docs ↗&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-paywalls-get-videos-plan-sheets-and-text-gradients&quot;&gt;Paywalls get videos, plan sheets, and text gradients&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;538&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Paywalls-Videos-1024x538.png&quot; alt=&quot;&quot; class=&quot;wp-image-48381&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Paywalls-Videos-1024x538.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Paywalls-Videos-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Paywalls-Videos-768x403.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Paywalls-Videos-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Paywalls-Videos-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Paywalls-Videos-696x365.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Paywalls-Videos-560x294.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Paywalls-Videos-840x441.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Paywalls-Videos-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Paywalls-Videos-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Paywalls-Videos.png 1200w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Once Paywalls moved to the web, we wanted them to feel even more like your product and less like a template. Three new tools help with that:&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Videos on Paywalls&lt;/strong&gt;&lt;br&gt;Add a product demo, a quick walkthrough, or a customer testimonial right in the paywall. It’s a simple way to answer “what do I get?” without adding clutter.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;“View all plans” sheets&lt;/strong&gt;&lt;br&gt;You can now tuck extra pricing options behind a button that opens a plan sheet. Keep the main paywall focused, while still giving power users the full menu.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Gradient text&lt;/strong&gt;&lt;br&gt;For headlines that need a little punch, gradient text lets you highlight key value props without redesigning the whole page.&lt;/p&gt;



&lt;p&gt;Together, these updates help you build paywalls that look custom and convert better, with zero extra engineering.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://e.customeriomail.com/e/c/eyJlbWFpbF9pZCI6ImRnVGYwUW9EQUs3dEY2M3RGd0dhV2R2SkhWR082ZHhIZFZ1OUl3MD0iLCJocmVmIjoiaHR0cHM6Ly93d3cucmV2ZW51ZWNhdC5jb20vZG9jcy90b29scy9wYXl3YWxscy9jcmVhdGluZy1wYXl3YWxscy9jb21wb25lbnRzP3V0bV9jYW1wYWlnbj1PY3RvYmVyK05ld3NsZXR0ZXJcdTAwMjZ1dG1fY29udGVudD1PY3RvYmVyK05ld3NsZXR0ZXJcdTAwMjZ1dG1fbWVkaXVtPWVtYWlsX2FjdGlvblx1MDAyNnV0bV9zb3VyY2U9Y3VzdG9tZXIuaW8jdmlkZW8tY29tcG9uZW50IiwiaW50ZXJuYWwiOiJkZmQxMGEwZGJkMDZhZWVkMTciLCJsaW5rX2lkIjo5MzYxfQ/https://www.revenuecat.com/docs/tools/paywalls/creating-paywalls/components#video-component&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Check out the docs ↗&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-unity-support-for-paywalls-and-customer-center&quot;&gt;Unity support for Paywalls and Customer Center&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;538&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/RC-x-Unity-1024x538.png&quot; alt=&quot;&quot; class=&quot;wp-image-48383&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/RC-x-Unity-1024x538.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/RC-x-Unity-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/RC-x-Unity-768x403.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/RC-x-Unity-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/RC-x-Unity-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/RC-x-Unity-696x365.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/RC-x-Unity-560x294.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/RC-x-Unity-840x441.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/RC-x-Unity-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/RC-x-Unity-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/RC-x-Unity.png 1200w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;If you ship in Unity, monetization and subscription management should feel just as native as they do on iOS and Android.&lt;/p&gt;



&lt;p&gt;With the latest SDK, Paywalls and Customer Center now work in Unity apps. You can present native paywalls, let users manage subscriptions in-app, and control offers and entitlements from the same RevenueCat dashboard you already use elsewhere.&lt;/p&gt;



&lt;p&gt;So Unity teams get the full RevenueCat experience, end to end. &lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://e.customeriomail.com/e/c/eyJlbWFpbF9pZCI6ImRnVGYwUW9EQUs3dEY2M3RGd0dhV2R2SkhWR082ZHhIZFZ1OUl3MD0iLCJocmVmIjoiaHR0cHM6Ly9naXRodWIuY29tL1JldmVudWVDYXQvcHVyY2hhc2VzLXVuaXR5L3JlbGVhc2VzL3RhZy84LjQuMD91dG1fY2FtcGFpZ249T2N0b2JlcitOZXdzbGV0dGVyXHUwMDI2dXRtX2NvbnRlbnQ9T2N0b2JlcitOZXdzbGV0dGVyXHUwMDI2dXRtX21lZGl1bT1lbWFpbF9hY3Rpb25cdTAwMjZ1dG1fc291cmNlPWN1c3RvbWVyLmlvIiwiaW50ZXJuYWwiOiJkZmQxMGEwZGJkMDZhZWVkMTciLCJsaW5rX2lkIjo5MzYyfQ/https://github.com/RevenueCat/purchases-unity/releases/tag/8.4.0&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Check out the release notes ↗&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-support-gets-smarter-with-zendesk-and-intercom-integrations&quot;&gt;Support gets smarter with Zendesk and Intercom integrations&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;538&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Customer-Center-Integrations-3-1-1024x538.png&quot; alt=&quot;&quot; class=&quot;wp-image-48385&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Customer-Center-Integrations-3-1-1024x538.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Customer-Center-Integrations-3-1-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Customer-Center-Integrations-3-1-768x403.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Customer-Center-Integrations-3-1-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Customer-Center-Integrations-3-1-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Customer-Center-Integrations-3-1-696x365.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Customer-Center-Integrations-3-1-560x294.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Customer-Center-Integrations-3-1-840x441.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Customer-Center-Integrations-3-1-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Customer-Center-Integrations-3-1-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Customer-Center-Integrations-3-1.png 1200w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Support teams don’t want to chase billing breadcrumbs. They want to solve the problem in front of them.&lt;/p&gt;



&lt;p&gt;The new Zendesk and Intercom integrations bring subscription data straight into your support sidebar, including:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Customer history&lt;/li&gt;



&lt;li&gt;Revenue contribution&lt;/li&gt;



&lt;li&gt;Active entitlements&lt;/li&gt;



&lt;li&gt;Subscription status&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Agents can auto-match customers when possible, or search manually when they need to. Either way, they get the full picture without switching tools. Support is quicker and easier.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.intercom.com/app-store/?app_package_code=revenuecat-customer-profiles-2oan&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Intercom integration ↗&lt;/a&gt; &lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.zendesk.com/marketplace/apps/support/1138597/revenuecat-customer-profiles/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Zendesk integration ↗&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-a-new-home-for-web-monetization&quot;&gt;A new home for web monetization&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;538&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Web-Home-1-1024x538.png&quot; alt=&quot;&quot; class=&quot;wp-image-48387&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Web-Home-1-1024x538.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Web-Home-1-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Web-Home-1-768x403.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Web-Home-1-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Web-Home-1-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Web-Home-1-696x365.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Web-Home-1-560x294.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Web-Home-1-840x441.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Web-Home-1-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Web-Home-1-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Web-Home-1.png 1200w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;We also rolled out a dedicated RevenueCat Web hub. Think of it as mission control for anything web-based:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Web Billing&lt;/li&gt;



&lt;li&gt;Purchase links&lt;/li&gt;



&lt;li&gt;Paywall performance insights&lt;/li&gt;



&lt;li&gt;Real-time revenue tracking&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The goal is simple: you should be able to go from setup to optimization without bouncing between pages or hunting for the right dashboard.&lt;/p&gt;



&lt;p&gt;If web revenue is becoming a bigger piece of your mix, this is where you’ll want to live.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/company/web-overview-dashboard/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Learn more ↗&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-more-improvements-worth-knowing-about&quot;&gt;More improvements worth knowing about&lt;/h2&gt;



&lt;p&gt;A few smaller upgrades that still matter:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;AppsFlyer integration with Paddle support&lt;/strong&gt;&lt;br&gt;You can now track Paddle transaction events in AppsFlyer, so attribution stays unified across web and mobile purchases.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Preview Customer Center colors&lt;/strong&gt;&lt;br&gt;See color changes instantly before publishing on iOS, which makes design tweaks faster and less guess-and-check.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;If you want to take any of these for a spin, everything is live in the dashboard now. Start with Paywalls on the web if you’re already using Purchase Links; the upgrade is immediate, and it opens up a lot more room for testing and iteration. And as always, keep the feedback coming. The fastest way we improve the product is by hearing what you’re trying to build next.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Why are React Native apps monetizing better?]]></title><description><![CDATA[Why React Native beats Flutter and Native in revenue]]></description><link>https://www.revenuecat.com/blog/engineering/why-react-native-apps-make-more-money/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/why-react-native-apps-make-more-money/</guid><pubDate>Mon, 24 Nov 2025 11:48:03 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Blog-44_Why-react-native-apps-make-more-money.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;If you look at the cross-platform charts at the end of 2026 State of subscription apps (SOSA) you will notice a peculiarity: React Native apps seem to be making more money in almost every possible way.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Since RevenueCat has access to all the subscription related information; e.g. how much was the subscription price, did it have free trial, was this a returning customer, and what technology the app is built with (ease to determine by just checking which RevenueCat SDK is sending the aforementioned data); our data set is possibly the most comprehensive when it comes to in-app purchases. Well if Apple and Google are not counted, but that data is not, and most likely will never be public.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;So React Native apps make more money, but why, and how? In this article I’m going to look at what SOSA tells us about monetization on cross-platform frameworks, and explore what characteristics of these frameworks could explain the data we are seeing.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-where-does-this-data-come-from&quot;&gt;Where does this data come from&lt;/h3&gt;



&lt;p&gt;Data collected by RevenueCat comes from the SDK installed on apps by developers themselves. RevenueCat only measures in-app purchase revenue, some types of monetization (paid apps, web-only subscriptions, physical goods, or custom billing systems) fall outside this dataset. Despite that limitation, the sample is broad: it spans solo developers, venture-funded companies, and apps across every major category on iOS and Android.&lt;/p&gt;



&lt;p&gt;Evan Bacon’s &lt;a href=&quot;https://bacon.expo.app/blog/expo-apps&quot;&gt;Who’s using Expo in 2025&lt;/a&gt; adds important context to the amount of React Native apps, showing 2,200 apps in the App Store using Expo SDK or React Navigation, both very often used with React Native, in production. Since the list is collected from trending and top downloaded charts, it provides a look at apps that people are actually using, and many of those happen to be React Native apps.&amp;nbsp;&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Despite all of this, the data collected by RevenueCat is extensive as it includes all major platforms, all major development frameworks, and apps made by both solo developers and large VC funded companies.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-understanding-the-data-and-visualizations&quot;&gt;Understanding the data and visualizations&lt;/h3&gt;



&lt;p&gt;Before diving into what the numbers tell us about React Native, Flutter, and native apps, it’s important to understand the structure of the SOSA dataset and how its visualizations work. The report uses box-and-whisker (candlestick) charts throughout.&lt;/p&gt;



&lt;p&gt;Each chart breaks the distribution into four key points:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Bottom quartile (Q1 / lower whisker) – The lowest-performing 25% of apps&lt;/li&gt;



&lt;li&gt;Median (Q2 / lower edge of the box) – The “middle” app in the dataset&lt;/li&gt;



&lt;li&gt;Upper quartile (Q3 / upper edge of the box) – The top 25% of apps&lt;/li&gt;



&lt;li&gt;P90 (upper whisker) – The threshold the top 10% of apps exceed&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;This structure gives a more realistic picture of how apps perform in the real world. The “box” shows where most apps cluster, while the whiskers show the spread between weaker and exceptional performers. When we talk about React Native outperforming other frameworks, we’re referring to these distribution points — not isolated outliers.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;500&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-40-1024x500.png&quot; alt=&quot;&quot; class=&quot;wp-image-48360&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-40-1024x500.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-40-300x146.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-40-768x375.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-40-1536x750.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-40-50x24.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-40-82x40.png 82w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-40-696x340.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-40-560x273.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-40-840x410.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-40-80x39.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-40-48x23.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-40.png 2040w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-react-native-converts-better-than-flutter-and-native&quot;&gt;React Native converts better than Flutter and native&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps-2025/#h-download-to-paid-by-framework&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;655&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-41-1024x655.png&quot; alt=&quot;&quot; class=&quot;wp-image-48362&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-41-1024x655.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-41-300x192.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-41-768x492.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-41-1536x983.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-41-50x32.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-41-62x40.png 62w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-41-696x445.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-41-560x358.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-41-462x296.png 462w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-41-737x472.png 737w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-41-80x51.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-41-48x31.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-41.png 1578w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/a&gt;&lt;/figure&gt;



&lt;p&gt;When we look at download-to-paid performance in the SOSA dataset, one pattern stands out immediately: &lt;strong&gt;React Native apps convert a higher share of their users into paying subscribers&lt;/strong&gt; than apps built with Flutter or fully native technologies such as Swift and Kotlin.&lt;/p&gt;



&lt;p&gt;The box-plot above shows React Native’s median conversion rate at 2.2%, compared to 1.8% in Flutter and 1.9% in native apps. But where React Native really pulls away is at the high end: the 90th percentile hits 11.2%, while Flutter reaches 8.8%, and native apps peak at 7.7%. In practise, this means that when comparing two apps with similar audiences, similar categories, and similar subscription models:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;The average React Native app turns more of its downloaders into paying customers.&lt;/li&gt;



&lt;li&gt;The best React Native apps outperform the best apps built natively.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Put another way: if you took two teams of equal skill and resources, one building an app in Swift/Kotlin, the other building it in React Native, the React Native team is more likely to produce an app that successfully converts users. React Native apps are more likely to reach the conversion rates that turn a good idea into a sustainable business.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-first-key-learning-deliver-as-fast-as-possible&quot;&gt;First key learning: deliver as fast as possible&lt;/h3&gt;



&lt;p&gt;One of the main benefits of React Native is that you can share much of the code between multiple platforms, most commonly those being Android and iOS. A capable developer, or a team of developers, can realize a complex React Native app in 3-6 months (with exceptions, but higher than that and you lose the benefits), and release it to both app stores around the same time.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Shopify went all-in on React Native in 2002,&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;Shopify went all-in on React Native five years ago. Just this week, the company reflected on how it went, &lt;a href=&quot;https://shopify.engineering/five-years-of-react-native-at-shopify?q=v&quot;&gt;sharing&lt;/a&gt;:&lt;/p&gt;



&lt;p&gt;– More productivity: thanks to one codebase powering iOS and Android, and working across both apps&lt;/p&gt;



&lt;p&gt;– Performance and reliability: all pages have sub-500ms loads and crash-free rates are above 99.9%. Both are impressive numbers!&lt;/p&gt;



&lt;p&gt;– TypeScript for the win: using TypeScript makes it easy for devs to transfer between React and React Native.&lt;/p&gt;



&lt;p&gt;– There are downsides: debugging is worse than for native apps, and updating to new React Native versions can be painful.&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;



&lt;p&gt;In mobile apps the market is divided between iOS and Android. Any serious app business will eventually have to target both. React Native allows you to technically do that from day one. This gives competitive advantage by allowing developers to experiment with pricing and monetization methods earlier on both platforms. This is particularly important on Android where users are more price sensitive, due to having cheaper devices and lower standards of living.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-don-t-flutter-apps-have-a-smaller-time-to-market-as-well&quot;&gt;Don’t Flutter apps have a smaller time to market as well?&lt;/h3&gt;



&lt;p&gt;The multi-platform aspect is being solved by other technologies as well. Kotlin multiplatform is trying to get Android developers to ship their apps to iOS, and there are some solutions for Swift to do the opposite. What comes closest to React Native is Flutter, which also targets multiple platforms. It’s loved by developers due to the comfortable syntax of Dart, but businesses show less love towards Flutter, mainly because Dart as a language is not as common, as is mainly just used in Flutter apps. React Native instead makes use of JavaScript, a language that most businesses already hire because of the existing web app based products as well.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-react-native-apps-generate-more-revenue-per-install&quot;&gt;React Native apps generate more revenue per install&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps-2025/#h-download-to-paid-by-framework:~:text=Paid%2C%20By%20Framework-,Revenue%20per%20Install%2C%20By%20Framework,-Revenue%20per%20Install&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;671&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-42-1024x671.png&quot; alt=&quot;&quot; class=&quot;wp-image-48364&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-42-1024x671.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-42-300x197.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-42-768x503.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-42-1536x1006.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-42-50x33.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-42-61x40.png 61w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-42-696x456.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-42-560x367.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-42-452x296.png 452w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-42-721x472.png 721w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-42-80x52.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-42-48x31.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-42.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/a&gt;&lt;/figure&gt;



&lt;p&gt;In the revenue per install (RPI) chart in native and Flutter apps look similar at the median (around $0.18–$0.19), with Flutter pulling slightly ahead at the top end ($1.55 vs. $1.11 for native).&lt;/p&gt;



&lt;p&gt;Once again React Native seems to be operating on a different curve entirely:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Median RPI: $0.30 (roughly 50% higher than native/Flutter)&lt;/li&gt;



&lt;li&gt;90th percentile: $2.48 (more than double native’s top performers)&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;In plain words, the best React Native apps seem to generate significantly more money per install. Coming back to the example of two equally skilled teams, if each acquired 100,000 users, the strong React Native app could earn $248k, versus $111k for a strong native app.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-feedback-loop-of-faster-time-to-market&quot;&gt;Feedback loop of faster time to market&lt;/h3&gt;



&lt;p&gt;Building great products is all about getting the products in the hands of your customers as fast as possible. The main reason for aiming for this is to learn from the customers: what they want, what features they are willing to pay for, and how much they are willing to pay for them, etc. The faster you’re at the market doing this, the more likely you are to beat your competition by having the things customers want.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;The pattern matches what we see in conversion data: React Native teams tend to optimize harder and iterate faster&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-react-native-pulls-further-ahead-by-day-60&quot;&gt;React Native pulls further ahead by day 60&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;643&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-43-1024x643.png&quot; alt=&quot;&quot; class=&quot;wp-image-48366&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-43-1024x643.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-43-300x188.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-43-768x482.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-43-1536x964.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-43-50x31.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-43-64x40.png 64w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-43-696x437.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-43-560x351.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-43-472x296.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-43-752x472.png 752w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-43-80x50.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-43-48x30.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-43.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps-2025/#h-revenue-per-install-by-framework-1&quot;&gt;Link&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;By Day 60, the revenue patterns sharpen: React Native not only starts ahead — it keeps widening the gap. This chart isn’t just about how much money apps make early; it shows how well they monetize over time.&lt;/p&gt;



&lt;p&gt;Here’s what the data really tells us:&lt;/p&gt;



&lt;p&gt;React Native apps keep compounding revenue better than any other framework&lt;/p&gt;



&lt;p&gt;A median RPI of $0.44 and a 90th percentile of $3.54 means RN apps don’t just convert early — they continue generating value from users weeks after install. Whatever advantages RN teams have (iteration speed, better testing velocity, product-focus), they keep paying off long after launch.&lt;/p&gt;



&lt;p&gt;Flutter apps outperform native at the high end&lt;/p&gt;



&lt;p&gt;The median is similar ($0.26 vs $0.27), but Flutter’s 90th percentile ($2.29) and upper quartile both exceed native. This suggests that while the average Flutter app behaves like a native app, the best Flutter teams drive significantly higher long-term revenue.&lt;/p&gt;



&lt;p&gt;Native apps stay steady but fall behind&lt;/p&gt;



&lt;p&gt;Native tops out at $1.53 for the 90th percentile — solid, but noticeably behind both Flutter and React Native. At D60, this makes native apps look like the “safe baseline”: consistent median performance, but fewer breakout successes.&lt;/p&gt;



&lt;p&gt;Other frameworks are extremely uneven&lt;/p&gt;



&lt;p&gt;The median ($0.29) is low, but the 90th percentile hits $2.94, nearly matching Flutter. This means some “Other” apps (Unity, Cordova, etc.) can monetize extremely well — but the outcomes are far more unpredictable.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-what-day-60-really-means&quot;&gt;What Day 60 Really Means&lt;/h3&gt;



&lt;p&gt;D60 revenue is a proxy for retention, pricing power, upsell behavior, and the maturity of the monetization model. The fact that React Native continues to outperform tells us:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Users acquired by RN apps stick around longer&lt;/li&gt;



&lt;li&gt;Those users keep buying (renewals, upgrades, add-ons)&lt;/li&gt;



&lt;li&gt;RN teams iterate faster, pushing improvements before revenue decay sets in&lt;/li&gt;



&lt;li&gt;RN apps likely adopt monetization best practices more aggressively&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-year-1-retention-by-plan-type-shows-only-modest-differences-across-frameworks&quot;&gt;Year-1 Retention by Plan Type Shows Only Modest Differences Across Frameworks&lt;/h2&gt;



&lt;p&gt;Here’s the real story of this chart:&lt;/p&gt;



&lt;p&gt;Retention at one year barely differs between Native, Flutter, React Native, or any other framework.&lt;/p&gt;



&lt;p&gt;That means React Native’s massive lead in conversion and revenue cannot be explained by better long-term retention. Users don’t stay subscribed longer in RN apps. They stay about the same.&lt;/p&gt;



&lt;p&gt;And that is the interesting part — because it tells us exactly where the advantage must be coming from:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;React Native apps convert more users earlier&lt;/li&gt;



&lt;li&gt;React Native apps extract more revenue per install&lt;/li&gt;



&lt;li&gt;But when it comes to keeping customers for a year, all frameworks perform similarly&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;In other words: React Native wins by front-loading value, not by keeping users longer.&lt;/p&gt;



&lt;p&gt;Now the quick breakdown by plan type (supporting, not leading):&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Weekly plans:&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;All frameworks are nearly identical (median ~2–4%). No technology advantage.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Monthly plans:&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Native and “Other” frameworks retain a few percentage points higher at the median (≈9–10% vs. ≈7–8% for Flutter/RN).&lt;/p&gt;



&lt;p&gt;The gap is small — not enough to matter strategically.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Annual plans:&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;All frameworks cluster tightly in the high 20s to low 30s at the median.&lt;/p&gt;



&lt;p&gt;Even the top performers are scattered evenly across frameworks.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-native-feel-dilemma&quot;&gt;The native feel dilemma&lt;/h3&gt;



&lt;p&gt;One of the early arguments against React Native, that still persists today, is that it is not “native enough”. Non-native feel has meant:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Slower apps, with RN apps both taking longer to start up, but also navigating and other interactions having more jank than native apps&lt;/li&gt;



&lt;li&gt;Wrong feeling animations, with noticeable framerate drops, wrong easings&lt;/li&gt;



&lt;li&gt;UI not following the platform specifications&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Every year since its launch, React Native has been working towards making this statement less and less true. To understand those efforts&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-what-year-1-retention-really-means&quot;&gt;What Year-1 Retention Really Means&lt;/h3&gt;



&lt;p&gt;Retention is a downstream outcome of value — if an app reliably solves a recurring problem, users stay subscribed. In that sense, this chart reinforces an important point:&lt;/p&gt;



&lt;p&gt;React Native’s monetization advantage does not come from retaining customers better, but from converting more customers and monetizing them more effectively.&lt;/p&gt;



&lt;p&gt;Retention stabilizes across frameworks&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-react-native-delivers-the-highest-ltv-per-paying-user-by-a-wide-margin&quot;&gt;React Native delivers the highest LTV per paying user — by a wide margin&lt;/h2&gt;



&lt;p&gt;Link&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;658&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-44-1024x658.png&quot; alt=&quot;&quot; class=&quot;wp-image-48368&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-44-1024x658.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-44-300x193.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-44-768x494.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-44-1536x987.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-44-50x32.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-44-62x40.png 62w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-44-696x447.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-44-560x360.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-44-461x296.png 461w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-44-735x472.png 735w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-44-80x51.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-44-48x31.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-44.png 1746w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;If you want to know which apps make the most money from each paying subscriber over their first year, this chart answers it clearly: React Native is in its own tier.&lt;/p&gt;



&lt;p&gt;React Native apps show:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Median LTV: $22.80 (higher than all other frameworks)&lt;/li&gt;



&lt;li&gt;P90 LTV: $85.26 (dramatically higher than native, Flutter, or “Other”)&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;That means React Native apps don’t just convert better and earn more per install — their paying users are also worth more over time. The framework draws a straight line through the whole monetization funnel.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Flutter vs. Native&lt;/strong&gt;&lt;br&gt;Flutter sits below native at the median ($13.81 vs. $16.15), but once you move into the upper quartile and top performers, Flutter pulls ahead.&lt;/p&gt;



&lt;p&gt;This suggests Flutter has a longer tail of “misses,” but when a Flutter app hits, it hits hard.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;“Other” frameworks&lt;/strong&gt;&lt;br&gt;While inconsistent at the median ($16.38), the 90th percentile reaches $70.90, meaning some apps built with alternative stacks monetize extremely well — but the distribution is much more volatile.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-conclusion&quot;&gt;Conclusion&lt;/h2&gt;



&lt;p&gt;Product is the key, not the technology&lt;/p&gt;



&lt;p&gt;React Native doesn’t just produce more payers — it produces payers who stick around and spend more.&lt;/p&gt;



&lt;p&gt;This is the final reinforcement of the monetization pattern visible across every chart:&lt;/p&gt;



&lt;p&gt;React Native teams iterate faster, test pricing more aggressively, ship more improvements, and ultimately capture more lifetime value from their best users.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Convert Figma designs to paywalls instantly with the new RevenueCat Figma plugin]]></title><description><![CDATA[Create, export, and iterate on paywall variations at record speed.]]></description><link>https://www.revenuecat.com/blog/engineering/revenuecat-figma-plugin/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/revenuecat-figma-plugin/</guid><pubDate>Thu, 20 Nov 2025 17:27:17 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/figma-plugin-blog-header.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Designing high-converting paywalls usually starts in Figma, where your design team already lives, experiments, and iterates. Our Paywalls Editor is built to make rebuilding those Figma designs fast and easy, but why not skip that step entirely?&lt;/p&gt;



&lt;p&gt;Today, we’re making that happen.&lt;/p&gt;



&lt;p&gt;You can now access the &lt;strong&gt;&lt;a href=&quot;https://www.figma.com/community/plugin/1571207414894772119&quot;&gt;RevenueCat Figma plugin&lt;/a&gt;&lt;/strong&gt;, a new way to go from design to live paywall instantly. With a single export, the plugin converts your Auto Layout–based Figma frames directly into fully editable paywalls in RevenueCat.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-from-figma-frame-to-revenuecat-paywall&quot;&gt;From Figma frame to RevenueCat Paywall&lt;/h2&gt;



&lt;p&gt;Once installed, the plugin lets you:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Export one or multiple paywalls from a single Figma file&lt;/strong&gt;: perfect for rapid iteration or preparing a batch of A/B test variations&lt;/li&gt;
&lt;/ul&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Preserve your exact layout and styling&lt;/strong&gt;: text becomes text, images become images, frames become stacks – all mapped automatically&lt;/li&gt;
&lt;/ul&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Automatically detect key components&lt;/strong&gt;: layer names like &lt;em&gt;Button&lt;/em&gt;, &lt;em&gt;Purchase Button&lt;/em&gt;, or &lt;em&gt;Package&lt;/em&gt; are translated into their corresponding RevenueCat Paywall components&lt;/li&gt;
&lt;/ul&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Send designs straight into the Paywall Editor&lt;/strong&gt;: your growth or CX team can then tweak copy, swap products, localize text, or spin up experiments – all without needing more design or engineering support&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;This workflow empowers designers to craft rich, on-brand paywalls that feel native to the app, while giving product teams the flexibility to iterate quickly inside RevenueCat.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-this-matters&quot;&gt;Why this matters&lt;/h2&gt;



&lt;p&gt;For most teams, paywalls start in Figma. Designers define layout, visual hierarchy, branding, and conversion-driven variations long before engineering or growth gets involved. But historically, getting those designs into a live paywall required manually recreating them in the Paywall Editor.&lt;/p&gt;



&lt;p&gt;The new plugin eliminates that step entirely.&lt;/p&gt;



&lt;p&gt;Now designers can build paywalls exactly where they prefer to work, and every variation, from small copy tweaks to full redesigns, can be exported in seconds. Meanwhile, PMs and growth teams can immediately turn those designs into experiments, compare performance, and publish updates without needing new design files.&lt;/p&gt;



&lt;p&gt;It’s a faster, cleaner, more collaborative approach to paywall iteration.&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-1bQwLV wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Find inspiration with real paywall examples on Paywalls.com&quot; text=&quot;&lt;p&gt;Browse real examples at &lt;a href=&amp;quot;https://www.paywalls.com/&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noopener&amp;quot;&gt;Paywalls.com&lt;/a&gt;: filter paywall screens by different UI elements, app category, and trending and top-growth paywalls.&lt;/p&gt;&quot; icon=&quot;sparks&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-watch-the-full-tutorial-and-read-the-docs&quot;&gt;Watch the full tutorial and read the docs&lt;/h2&gt;



&lt;p&gt;If you want to see the full flow end-to-end, we’ve put together a complete walkthrough:&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Full Video Tutorial&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;Import designs from Figma into RevenueCat Paywalls&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/dhUADHmZMjg?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;&lt;strong&gt;Documentation&lt;/strong&gt;&lt;br&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/tools/paywalls/creating-paywalls#importing-from-figma&quot;&gt;https://www.revenuecat.com/docs/tools/paywalls/creating-paywalls#importing-from-figma&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Get the Figma Plugin&lt;/strong&gt;&lt;br&gt;&lt;a href=&quot;https://www.figma.com/community/plugin/1571207414894772119&quot;&gt;https://www.figma.com/community/plugin/1571207414894772119&lt;/a&gt;&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;p&gt;The fastest way to build high-quality, on-brand paywalls is now the one your designers were already using. Try the plugin, experiment with multiple variations, and start shipping paywalls faster than ever.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Grow ARPU by adding value for existing subscribers: tactics + real app examples]]></title><description><![CDATA[How expanding product value can unlock untapped revenue and attract new users]]></description><link>https://www.revenuecat.com/blog/growth/subscription-app-expand-value/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/subscription-app-expand-value/</guid><pubDate>Thu, 20 Nov 2025 16:20:13 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Growing-ARPU-through-existing-subscribers.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Growth often slows for more established subscription apps from acquisition channels mature and conversion funnels are optimized. So how do you continue to scale?&amp;nbsp;&lt;/p&gt;



&lt;p&gt;The next stage of growth doesn’t come from finding more users, it comes from &lt;strong&gt;creating more value for the users you already have&lt;/strong&gt; (and monetizing that value, of course).&lt;/p&gt;



&lt;p&gt;Expanding product value helps in two key ways:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Retention:&lt;/strong&gt; by solving more problems and staying relevant in your user’s daily life, you reduce churn and increase &lt;a href=&quot;http://revenuecat.com/blog/growth/what-is-lifetime-value-ltv-apps/&quot;&gt;subscriber lifetime value&lt;/a&gt; (LTV)&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;ARPU:&lt;/strong&gt; once new value is proven and desired, it can be tiered, bundled, or monetized — increasing &lt;a href=&quot;https://www.revenuecat.com/glossary/#arpu-average-revenue-per-user&quot;&gt;average revenue per users&lt;/a&gt; (ARPU)&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;In practice, the line between retention and ARPU is thin. Value expansion often starts as a retention initiative, then evolves into a revenue driver once engagement and perceived value grow.&lt;/p&gt;



&lt;p&gt;Before we dive into identifying opportunities to expand value for your existing subscribers, let’s take a look at examples from five leading &lt;a href=&quot;https://www.revenuecat.com/blog/growth/okrs-kpis-subscription-apps/&quot;&gt;subscription apps&lt;/a&gt; whose added value paid off.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-5-app-examples-for-expanding-core-product-value-nbsp&quot;&gt;&lt;strong&gt;5 app examples for expanding core product value&amp;nbsp;&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;These mini case studies show how mature brands have extended their core product to unlock both &lt;a href=&quot;https://www.revenuecat.com/glossary/#retention-rate&quot;&gt;retention&lt;/a&gt; and revenue growth, primarily through:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Capitalizing on adjacent use cases and jobs-to-be-done&lt;/li&gt;



&lt;li&gt;Finding new audiences through new use cases&lt;/li&gt;



&lt;li&gt;Expanding frequency of relevance in users’ daily lives&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Adding new core value that can be monetized as premium&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Read on for more detail, and some inspiration!&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-headspace-from-meditation-to-whole-person-wellbeing&quot;&gt;&lt;strong&gt;1. Headspace: from meditation to whole-person wellbeing&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Headspace began as a meditation app but gradually broadened its focus to include sleepcasts, focus music, workouts, and therapy content. This shift positioned the brand as an entire, holistic wellbeing platform rather than a single-purpose meditation tool.&lt;/p&gt;



&lt;p&gt;The expansion worked by &lt;strong&gt;extending Headspace’s relevance&lt;/strong&gt; (and potentially deepened engagement) &lt;strong&gt;across more daily moments&lt;/strong&gt;: sleep, exercise, focus, and stress management.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Over time, the company also introduced &lt;a href=&quot;https://sbigrowth.com/insights/headspace-calm-pricing?&quot;&gt;higher-priced tiers&lt;/a&gt; and enterprise partnerships, reflecting how a &lt;strong&gt;wider value proposition can support stronger monetization&lt;/strong&gt;. For example, Headspace’s blog and press releases indicate that by 2023-24 the company was offering enterprise clients a &lt;a href=&quot;https://organizations.headspace.com/blog/headspace-launches-all-in-one-mental-health-offering-and-expands-eap-replacement-solution?&quot;&gt;single app&lt;/a&gt; integrating mindfulness, coaching, therapy and psychiatry, as well as launching direct-to-consumer &lt;a href=&quot;https://www.headspace.com/articles/headspace-launches-direct-to-consumer-mental-health-service?&quot;&gt;mental health coaching.&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Lesson: &lt;/strong&gt;expanding into enterprise and higher-value, direct-to-consumer tiers is a clear route to widen value proposition, and can create the justification for stronger monetization.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;724&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image2-1024x724.png&quot; alt=&quot;&quot; class=&quot;wp-image-48314&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image2-1024x724.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image2-300x212.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image2-768x543.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image2-1536x1086.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image2-50x35.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image2-57x40.png 57w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image2-656x464.png 656w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image2-696x492.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image2-560x396.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image2-419x296.png 419w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image2-668x472.png 668w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image2-80x57.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image2-48x34.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image2.png 1999w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Headspace’s App Store page emphasizes the breadth of features and life areas it can help users with&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-classpass-from-fitness-access-to-lifestyle-membership&quot;&gt;&lt;strong&gt;2. ClassPass: from fitness access to lifestyle membership&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;ClassPass initially grew its subscriber base with access to boutique fitness-studios and classes. Today, the platform has shifted into selling far more than workouts; offering a broader lifestyle subscription covering wellness and self-care.&lt;/p&gt;



&lt;p&gt;On its website, ClassPass now &lt;a href=&quot;https://classpass.com/?utm_source=google&amp;amp;utm_medium=brand&amp;amp;utm_campaign=21295235716&amp;amp;utm_term=178332892776_classpass%7Cp&amp;amp;gad_source=1&amp;amp;gad_campaignid=21295235716&amp;amp;gbraid=0AAAAADjDAprcTUMLtTftwi5sG8FNhRTvc&amp;amp;gclid=Cj0KCQiAiebIBhDmARIsAE8PGNLl8twoif8UjgILAqF46zUUV-R6iXkpQoP2u4w-gybDpW5o7udM-6gaAq2EEALw_wcB&quot;&gt;describes itself&lt;/a&gt; as “one app for all things fitness, wellness &amp;amp; beauty” and states that credits can be used for bookings at gyms, studios, salons and spas.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;A 2018 article &lt;a href=&quot;https://hauteliving.com/2018/02/classpass-beauty-wellness-experiences/651900/?&quot;&gt;noted the addition&lt;/a&gt; of “an assortment of new wellness experiences including massages, facials, cryotherapy, float spas, infrared saunas”. Since then, wellness and beauty bookings reportedly became a major part of the business — at one point in 2021,&lt;a href=&quot;https://www.modernretail.co/retailers/as-gyms-falter-classpass-is-rapidly-expanding-beyond-fitness/&quot;&gt; non-fitness venues made up 55% of all listings in New York&lt;/a&gt; for ClassPass; massages in particular “became the most popular wellness activity”.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;ClassPass is a great example of how a subscription service can&lt;strong&gt; expand into adjacent motivations to reach a new audience&lt;/strong&gt; (e.g. from solely gym-goers to also self-care and beauty lovers) and increase usage frequency. By widening the scope of what can be booked with credits, ClassPass not only found new users, but increased the relevance of its membership across more parts of existing users’ weekly life.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Lesson: &lt;/strong&gt;supporting higher engagement (more usage occasions) and deeper value for members will ultimately result in stronger retention, LTV, and new monetization paths (through premium plans, more credits, higher-value bookings).&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;735&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image1-1024x735.png&quot; alt=&quot;&quot; class=&quot;wp-image-48317&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image1-1024x735.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image1-300x215.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image1-768x551.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image1-1536x1103.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image1-50x36.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image1-56x40.png 56w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image1-646x464.png 646w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image1-696x500.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image1-560x402.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image1-412x296.png 412w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image1-658x472.png 658w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image1-80x57.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image1-48x34.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image1.png 1999w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;ClassPass quickly demonstrates its wide relevance, from the app name and subtitle to app preview images&amp;nbsp;&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-airbnb-from-budget-stays-to-curated-experiences&quot;&gt;&lt;strong&gt;3. Airbnb: from budget stays to curated experiences&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Airbnb rose to success as a peer-to-peer marketplace for spare rooms. Since its launch in 2008, &amp;nbsp; &lt;a href=&quot;https://www.stayclassyhomes.com/pages/airbnb-history?&quot;&gt;the platform has expanded&lt;/a&gt; beyond accommodation into categories such as curated online ‘Experiences’, luxury home rentals, and &lt;a href=&quot;https://www.airbnb.co.uk/resources/hosting-homes/a/introducing-airbnb-services-741&quot;&gt;bespoke services&lt;/a&gt; allowing users to book chefs, trainers, massage therapists and more at their rentals.&lt;/p&gt;



&lt;p&gt;In 2025 Airbnb&lt;a href=&quot;https://techcrunch.com/2025/05/13/airbnb-lauches-services-and-experinces-as-it-thinks-about-connecting-travelers/?&quot;&gt; announced a relaunch&lt;/a&gt; of its Experiences and introduced Airbnb ‘Services’. The evolution suggests the company is not simply scaling by adding more listings or new types of accommodation, but broadening what a “trip with Airbnb” can mean, &lt;strong&gt;making the brand relevant to more moments&lt;/strong&gt;, more identities of traveller, and ultimately &lt;strong&gt;enabling higher-value bookings&lt;/strong&gt; over time.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Lesson: &lt;/strong&gt;broaden your offering around related use-cases to not only deepen engagement and relevance, but also open the door to increasing transaction size and revenue potential.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;738&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image3-1024x738.png&quot; alt=&quot;&quot; class=&quot;wp-image-48319&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image3-1024x738.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image3-300x216.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image3-768x554.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image3-1536x1107.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image3-50x36.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image3-55x40.png 55w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image3-644x464.png 644w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image3-696x502.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image3-560x404.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image3-411x296.png 411w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image3-655x472.png 655w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image3-80x58.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image3-48x35.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image3.png 1984w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Airbnb’s subtitle and app previews directly call out each use case for the app’s expanded value&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-4-duolingo-from-language-learning-to-the-learning-habit&quot;&gt;&lt;strong&gt;4. Duolingo: from language learning to the learning habit&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Duolingo built its reputation on gamified, bite-sized lessons designed for language learning. Over time, however, the company broadened its scope: it &lt;a href=&quot;https://blog.duolingo.com/new-subjects/&quot;&gt;introduced longer courses&lt;/a&gt; in subjects like maths and music, and more recently launched a chess course that uses puzzles and interactive matches.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;This expansion appears to have been aimed at turning a language-learning habit into a more generalised learning habit. Rather than simply charging more up front, Duolingo has focused on &lt;strong&gt;increasing daily engagement and habit strength&lt;/strong&gt; across multiple subjects first, then positioned itself to &lt;strong&gt;monetise this broader surface area&lt;/strong&gt; of learning via upgraded subscription tiers and premium features.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;The broader curriculum appears consistent with the strong financial momentum the company is &lt;a href=&quot;https://investors.duolingo.com/news-releases/news-release-details/duolingo-reports-41-revenue-growth-46-subscription-revenue&quot;&gt;reporting&lt;/a&gt;: 41% revenue growth, and rising paid subscriptions in 2025. Analyst commentary further &lt;a href=&quot;https://simplywall.st/stocks/us/consumer-services/nasdaq-duol/duolingo/news/duolingo-duol-evaluating-valuation-after-strategic-shift-ove?&quot;&gt;suggests&lt;/a&gt; this adjacent-subject expansion is a key lever for driving higher ARPU.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Lesson: &lt;/strong&gt;expand your habit loop into adjacent domains (from languages to maths, music, and chess) to boost retention first, then create the platform for increased ARPU once the concept is proven.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;729&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image4-1024x729.png&quot; alt=&quot;&quot; class=&quot;wp-image-48321&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image4-1024x729.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image4-300x214.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image4-768x547.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image4-1536x1093.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image4-50x36.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image4-56x40.png 56w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image4-652x464.png 652w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image4-696x495.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image4-560x399.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image4-416x296.png 416w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image4-663x472.png 663w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image4-80x57.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image4-48x34.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image4.png 1999w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;While Duolingo’s App Store name still indicates language-learning as its primary use case, the subtitle and screenshots quickly showcase the variety of topics users can learn&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-5-openai-from-chat-to-a-daily-co-pilot-across-work-and-life&quot;&gt;&lt;strong&gt;5. OpenAI: from chat to a daily co-pilot across work and life&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;ChatGPT launched in late 2022 as a conversational AI that people used for questions, ideas and simple creative tasks. With rapid expansion, the platform has broadened into a much wider set of everyday and professional use cases. ChatGPT is now being used across writing, coding, studying, analysis and business workflows.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;OpenAI’s own product announcements reflect this widening scope. For example, ChatGPT can now generate and analyse files, troubleshoot code, create images, support team collaboration, and&lt;a href=&quot;https://openai.com/index/introducing-gpts/&quot;&gt; run custom agents built by users&lt;/a&gt;.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;ChatGPT’s use now spans&lt;a href=&quot;https://openai.com/index/more-ways-to-work-with-your-team/?&quot;&gt; students, marketers, engineers, SMBs and enterprise teams&lt;/a&gt;. In many cases under the same Plus or Team subscription.&lt;/p&gt;



&lt;p&gt;By expanding into more real-world contexts, ChatGPT appears to have &lt;strong&gt;evolved from a curiosity into a utility product&lt;/strong&gt;, which helps support premium plans. Reporting shows that ChatGPT Plus &lt;a href=&quot;https://www.reuters.com/technology/openai-seeks-tens-billions-new-investment-wsj-reports-2024-02-02&quot;&gt;reached around two million subscribers &lt;/a&gt;by early 2024 as use cases broadened.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Lesson: &lt;/strong&gt;when a product expands into more daily use cases, occasional usage can turn into habit — and habitual use creates the foundation for stronger retention and pricing power.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;727&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image5-1024x727.png&quot; alt=&quot;&quot; class=&quot;wp-image-48323&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image5-1024x727.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image5-300x213.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image5-768x546.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image5-1536x1091.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image5-50x36.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image5-56x40.png 56w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image5-653x464.png 653w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image5-696x494.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image5-560x398.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image5-417x296.png 417w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image5-664x472.png 664w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image5-80x57.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image5-48x34.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image5.png 1999w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;ChatGPT differs from the other examples’ App Store listings, not calling out use cases in the name or subtitle, and focusing on aspirational motivations rather than feature callouts&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-identifying-your-subscription-app-s-value-expansion-opportunities&quot;&gt;&lt;strong&gt;Identifying your subscription app’s value expansion opportunities&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Once a product reaches maturity, the question shifts from “how do we get more subscribers?” to “how do we create more reasons for existing subscribers to stay and pay more?”. The answer is pretty simple: make your app worth more. Give subscribers new features, new use cases, and new motivations to use the app.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Value expansion isn’t guesswork; the most successful companies, like the examples above, follow a recognisable pattern. Here’s four steps to identify your app’s next shift:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-start-by-mapping-core-and-adjacent-jobs-to-be-done&quot;&gt;&lt;strong&gt;Start by mapping core and adjacent jobs-to-be-done&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Every subscription product solves a primary job for users, but most users have several related needs surrounding that core job. For example, Headspace began by helping users target anxiety and relaxation — the next natural step was tackling sleep.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;You can start by observing what people try to accomplish before, during, and after they use your product to reveal natural places to expand. These adjacent jobs usually become the clearest starting points for broadening value.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Alternately, look to competitors and the rest of the market. Duolingo was already the market leader for language-learning, but the ‘Education’ category of the App Store still showed other general learning apps. So it made sense for them to expand to other subjects beyond language.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-validate-with-behavioural-and-survey-data&quot;&gt;&lt;strong&gt;Validate with behavioural and survey data&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Not every adjacent idea is worth pursuing. The strongest signals come from your most retained users: what else do they repeatedly do, search for, or pair with your product?&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Behavioral analysis often uncovers complementary apps, repeat patterns, or clusters of similar feature requests. &lt;a href=&quot;https://www.revenuecat.com/blog/growth/review-mining-for-subscription-apps/&quot;&gt;Review mining&lt;/a&gt; can also be a valuable technique to identify new areas for expansion that you already know users are interested in. Surveys and interviews help confirm whether those patterns represent real unmet needs rather than edge cases.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-test-expansion-ideas-through-lightweight-prototypes&quot;&gt;&lt;strong&gt;Test expansion ideas through lightweight prototypes&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Value expansion rarely begins with a full feature build. Many companies start with small, reversible bets: content pilots, limited betas, basic integrations or partnerships. These early experiments reveal whether users recognise the added value and whether it increases engagement.&lt;/p&gt;



&lt;p&gt;&amp;nbsp;If the signal is strong, the surface area can be expanded with more confidence, and you can consider putting &lt;a href=&quot;https://www.revenuecat.com/blog/growth/ad-monetization-subscription-apps/&quot;&gt;monetization strategies&lt;/a&gt; in place (see below!).&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-monetize-only-once-the-value-is-established&quot;&gt;&lt;strong&gt;Monetize only once the value is established&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Most companies introduce expanded value as a retention lever &lt;em&gt;before&lt;/em&gt; treating it as a revenue lever. While it’s tempting to put new features or use cases behind a &lt;a href=&quot;https://www.revenuecat.com/blog/growth/paywalls-study-guide/&quot;&gt;paywall&lt;/a&gt;, hold off until users consistently engage with the new behaviour or app areas. Proven value supports pricing power; unproven value does not.&lt;/p&gt;



&lt;p&gt;Once you have this proof, higher-tier plans, add-ons, or bundles feel far more natural to users, and far less risky to your retention..&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-ready-to-expand-your-app-s-value&quot;&gt;&lt;strong&gt;Ready to expand your app’s value?&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;For established apps, expanding value is a natural next step once the core product and funnel have matured. It’s a retention lever first and an ARPU lever second.&lt;/p&gt;



&lt;p&gt;There’s many ways to expand the value of your app and drive increased revenue per user; the examples and guidance in this article are just a handful of options at your disposal. But there is a general consistency among the apps that expand &lt;em&gt;successfully:&lt;/em&gt; thoughtful expansion into adjacent use cases and audiences, backed by user research or interest, rather than a rapid reach in a new direction.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;The longer users stay and the more needs you meet, the easier it becomes to justify premium pricing or new product lines later on.&lt;/p&gt;



&lt;p&gt;In short: earn engagement, then monetize it. That’s how established subscription businesses turn retention improvements into sustainable ARPU growth.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[How to run a Black Friday campaign for your app on the web]]></title><description><![CDATA[It’s not too late! Spin up a Black Friday campaign in hours.]]></description><link>https://www.revenuecat.com/blog/growth/black-friday-web-campaign-for-apps/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/black-friday-web-campaign-for-apps/</guid><pubDate>Wed, 19 Nov 2025 14:39:27 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Run-a-Black-Friday-campaign-on-the-web-scaled.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Black Friday is a perfect moment to sell on the web. Your audience finds you through newsletters, ads, podcasts, and social links; you bring them to a checkout you control, shorten the subscription flow and keep more of the revenue.&lt;/p&gt;



&lt;p&gt;If you’re panicking that it’s too late to cash in on Black Friday sales, relax 😎&lt;/p&gt;



&lt;p&gt;RevenueCat Web Billing lets you launch fast, convert easily, and measure end-to-end. Read on for how to build a simple, effective campaign in hours.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-the-web-for-black-friday&quot;&gt;Why the web for Black Friday&lt;/h2&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Better acquisition&lt;/strong&gt;: the web is where top‑of‑funnel happens; email, paid social, search, influencers, and affiliates all link out to web, so one click takes people straight to your offer&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Quicker to build &amp;amp; easier to optimize&lt;/strong&gt;: update copy, pricing, or creative in minutes, no review cycles, just test and learn while traffic is hot&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Lower costs&lt;/strong&gt;: keep the margin you’d lose to app store fees, seasonal discounts pay off more when you keep the upside&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-example-justin-guitar-s-quick-and-easy-black-friday-campaign&quot;&gt;Example: Justin Guitar’s quick and easy Black Friday campaign&lt;/h2&gt;



&lt;p&gt;To see Black Friday sales via Web Billing in action, here’s how &lt;a href=&quot;https://justinguitarapp.com/&quot;&gt;&lt;strong&gt;Justin Guitar&lt;/strong&gt;&lt;/a&gt; set up their Black Friday campaign on the web.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;639&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/CleanShot-2025-11-12-at-11.50.34@2x-1024x639.png&quot; alt=&quot;&quot; class=&quot;wp-image-48218&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/CleanShot-2025-11-12-at-11.50.34@2x-1024x639.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/CleanShot-2025-11-12-at-11.50.34@2x-300x187.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/CleanShot-2025-11-12-at-11.50.34@2x-768x480.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/CleanShot-2025-11-12-at-11.50.34@2x-1536x959.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/CleanShot-2025-11-12-at-11.50.34@2x-2048x1279.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/CleanShot-2025-11-12-at-11.50.34@2x-50x31.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/CleanShot-2025-11-12-at-11.50.34@2x-64x40.png 64w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/CleanShot-2025-11-12-at-11.50.34@2x-696x435.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/CleanShot-2025-11-12-at-11.50.34@2x-560x350.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/CleanShot-2025-11-12-at-11.50.34@2x-474x296.png 474w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/CleanShot-2025-11-12-at-11.50.34@2x-756x472.png 756w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/CleanShot-2025-11-12-at-11.50.34@2x-80x50.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/CleanShot-2025-11-12-at-11.50.34@2x-48x30.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Justin Guitar added a simple banner to the homepage promoting &lt;strong&gt;40% off the first year&lt;/strong&gt; of their annual plan. The banner linked directly to a RevenueCat &lt;a href=&quot;https://www.revenuecat.com/docs/web/web-billing/web-purchase-links&quot;&gt;&lt;strong&gt;Web Purchase Link&lt;/strong&gt;&lt;/a&gt;, a hosted checkout page connected to their existing products. No extra code or web app changes needed.&lt;/p&gt;



&lt;p&gt;They also used a &lt;a href=&quot;https://www.revenuecat.com/docs/web/web-billing/redemption-links&quot;&gt;&lt;strong&gt;Redemption Link&lt;/strong&gt;&lt;/a&gt; so buyers could unlock new in‑app features right after paying, without creating or logging into an account first.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-why-this-works&quot;&gt;Why this works&lt;/h3&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Low friction&lt;/strong&gt;: visitors go from homepage to checkout in one click&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;High intent&lt;/strong&gt;: the audience is already familiar with the brand through email and social channels&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Better economics&lt;/strong&gt;: by selling on the web, they keep the revenue share that would’ve gone to the app stores&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;You can build this same setup in an hour, add your offer, link it to checkout, drop the banner or email link, and start tracking results.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-to-build-a-black-friday-web-campaign-in-revenuecat&quot;&gt;How to build a Black Friday web campaign in RevenueCat:&lt;/h2&gt;



&lt;p&gt;Now you know what a solid web campaign looks like, here’s what you need to build yours:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;A promo landing page that matches your offer and brand&lt;/li&gt;



&lt;li&gt;A hosted checkout that works anywhere a link fits&lt;/li&gt;



&lt;li&gt;A redemption step that connects the purchase to your app without a login&lt;/li&gt;



&lt;li&gt;Clear tracking from the first click to in‑app activation&lt;a href=&quot;&quot;&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;&lt;strong&gt;The flow at a glance looks like this:&lt;/strong&gt; Ad or email → web paywall or promo page → hosted checkout → success page → redeem in app&lt;/p&gt;



&lt;p&gt;You can run this with no code if you want speed. Use Web Purchase Links for checkout and Redemption Links to connect the purchase to a user. If you have time for more control, add a &lt;a href=&quot;https://www.revenuecat.com/feature/paywalls/&quot;&gt;Paywall&lt;/a&gt; to design a richer pitch and test variants.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-what-you-need-before-you-start&quot;&gt;What you need before you start&lt;/h3&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;A RevenueCat project with a mobile app, products and prices set up&lt;/li&gt;



&lt;li&gt;An offer to promote, including any intro discount and renewal details&lt;/li&gt;



&lt;li&gt;Redemption Links set up in RevenueCat (or enough time to go through app review)&lt;/li&gt;



&lt;li&gt;A place to link from: email, landing page, homepage banner, or all three&lt;/li&gt;



&lt;li&gt;Optional: a simple visual for your campaign flow, and a branded hero image&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;With the basics ready, it’s time to build the offer and connect the purchase flow.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-1-create-your-black-friday-product-offering-and-intro-offer&quot;&gt;Step 1: Create your Black Friday product, offering and intro offer&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;538&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Product-1-1-1024x538.png&quot; alt=&quot;&quot; class=&quot;wp-image-48249&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Product-1-1-1024x538.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Product-1-1-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Product-1-1-768x403.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Product-1-1-1536x806.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Product-1-1-2048x1075.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Product-1-1-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Product-1-1-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Product-1-1-696x365.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Product-1-1-560x294.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Product-1-1-840x441.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Product-1-1-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Product-1-1-48x25.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Start by creating a new product for your Black Friday deal — this keeps the discount separate from your regular plans and gives you clean reporting when the campaign ends.&lt;/p&gt;



&lt;p&gt;Set up the product with the exact duration and price you want for the promotion. Then create an entitlement that grants the same premium access your standard plans unlock. Linking the new product to this entitlement ensures buyers get the full experience in your app without changing anything in your existing setup. This structure also lets you pair the product with a dedicated offering so your intro offer, checkout link, and paywall all pull from the same source.&lt;/p&gt;



&lt;p&gt;Now use &lt;a href=&quot;https://www.revenuecat.com/docs/web/web-billing/product-setup#introductory-period&quot;&gt;&lt;strong&gt;Intro Offers&lt;/strong&gt;&lt;/a&gt; in RevenueCat to set up a limited-time discount. This is perfect for Black Friday: offer X% off the first year, or a short discounted trial that rolls into a full plan later. You can also define custom renewal cycles or durations, which gives you more flexibility than App Store or Play Store billing.&lt;/p&gt;



&lt;p&gt;Black Friday brings a surge of high-intent traffic, so think about how you want that traffic to behave. A free trial captures more people during those peak days, while an intro offer gives you healthier LTV because buyers commit with an upfront payment.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-2-set-up-your-checkout-link&quot;&gt;Step 2: Set up your checkout link&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;538&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/WPL-1-1-1024x538.png&quot; alt=&quot;&quot; class=&quot;wp-image-48251&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/WPL-1-1-1024x538.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/WPL-1-1-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/WPL-1-1-768x403.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/WPL-1-1-1536x806.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/WPL-1-1-2048x1075.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/WPL-1-1-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/WPL-1-1-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/WPL-1-1-696x365.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/WPL-1-1-560x294.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/WPL-1-1-840x441.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/WPL-1-1-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/WPL-1-1-48x25.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Next, create a &lt;a href=&quot;https://www.revenuecat.com/docs/web/web-billing/web-purchase-links&quot;&gt;&lt;strong&gt;Web Purchase Link&lt;/strong&gt;&lt;/a&gt;. It’s a hosted checkout page, no code needed. You can share it in emails, ads, or your homepage banner. It automatically displays your available packages and handles payment securely.&lt;/p&gt;



&lt;p&gt;If you only have one offer, skip the package selection and link straight to checkout. That removes friction and boosts conversion.&lt;/p&gt;



&lt;p&gt;To create your link:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Go to your RevenueCat project dashboard&lt;/li&gt;



&lt;li&gt;Open the &lt;strong&gt;Web section&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;Create a &lt;strong&gt;Purchase Link&lt;/strong&gt; for your Black Friday product or package&lt;/li&gt;



&lt;li&gt;Customize the branding and copy of your &lt;strong&gt;Purchase Link&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;Copy the URL to use in your campaign&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;When you create the offer:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Pick a clear, time-bound promotion (for example, “X% off your first month/year”)&lt;/li&gt;



&lt;li&gt;Add urgency in your marketing copy (“Ends Cyber Monday”)&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-3-set-up-purchase-redemption&quot;&gt;Step 3: Set up purchase redemption&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;538&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Redemption-2-1-1024x538.png&quot; alt=&quot;&quot; class=&quot;wp-image-48253&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Redemption-2-1-1024x538.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Redemption-2-1-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Redemption-2-1-768x403.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Redemption-2-1-1536x806.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Redemption-2-1-2048x1075.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Redemption-2-1-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Redemption-2-1-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Redemption-2-1-696x365.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Redemption-2-1-560x294.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Redemption-2-1-840x441.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Redemption-2-1-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Redemption-2-1-48x25.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;After purchase, use a &lt;a href=&quot;https://www.revenuecat.com/docs/web/web-billing/redemption-links&quot;&gt;&lt;strong&gt;Redemption Link&lt;/strong&gt;&lt;/a&gt; so buyers can unlock access in your app without logging in first. It’s a simple way to bridge web-to-app purchases while keeping conversion high. When a user redeems, RevenueCat connects that transaction to their user ID automatically.&lt;/p&gt;



&lt;p&gt;You need redemption links set up in RevenueCat before this step works. That includes adding redemption support in your mobile SDK configuration and shipping an app update with that change. Once the updated app is live, buyers can redeem their purchase in one tap and RevenueCat will connect the transaction to their user ID automatically. If you haven’t set this up yet, follow the &lt;a href=&quot;https://www.revenuecat.com/docs/web/web-billing/redemption-links&quot;&gt;Redemption Links Docs guide&lt;/a&gt; for the SDK steps and project settings you need to enable.&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-Z1zBCsj wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Good to know&quot; text=&quot;&lt;p&gt;If you can’t use redemption links, add a signup step before checkout so every buyer has a user ID. Pass that user ID in the purchase link URL, and RevenueCat will attach the transaction to the right account. Docs will walk through the exact parameters and SDK steps to make this work.&lt;/p&gt;&quot; icon=&quot;bulb&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;p&gt;Here’s how to add Redemption Links to your purchase experience:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Open your Web Purchase Link in the RevenueCat dashboard and go to its settings&lt;/li&gt;



&lt;li&gt;Check the option to show download and redemption instructions&lt;/li&gt;



&lt;li&gt;Add your App Store and Play Store URLs so the link can display the correct download buttons&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;It will add the redemption step:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;On a success page that thanks them for the purchase&lt;/li&gt;



&lt;li&gt;In your post-purchase email&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-4-preview-and-test-the-flow&quot;&gt;Step 4: Preview and test the flow&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;538&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Redemption-1-1024x538.png&quot; alt=&quot;&quot; class=&quot;wp-image-48229&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Redemption-1-1024x538.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Redemption-1-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Redemption-1-768x403.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Redemption-1-1536x806.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Redemption-1-2048x1075.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Redemption-1-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Redemption-1-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Redemption-1-696x365.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Redemption-1-560x294.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Redemption-1-840x441.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Redemption-1-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Redemption-1-48x25.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Use the sandbox URL to test the full purchase flow before you go live. Open the sandbox version of your Web Purchase Link, run through a checkout with a test credit card, and make sure the pricing and copy look right. After the purchase succeeds, test redemption in your mobile app with the SDK configured so you can confirm that the transaction attaches to the correct user and unlocks the entitlement instantly.&lt;/p&gt;



&lt;p&gt;Click through your full campaign once from start to finish:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Does the ad or email link open the right paywall or checkout?&lt;/li&gt;



&lt;li&gt;Is the pricing and copy correct?&lt;/li&gt;



&lt;li&gt;Does the redemption link work cleanly from desktop and mobile?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Once it’s smooth, you’re ready to go live.&lt;/p&gt;



&lt;p&gt;And that’s it! &lt;strong&gt;You’ve got a working Black Friday campaign with a production URL you can use in any email, ad or social media post.&lt;/strong&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-adding-branded-paywalls-to-your-black-friday-campaign&quot;&gt;Adding branded Paywalls to your Black Friday campaign&lt;/h2&gt;



&lt;p&gt;Now, if you’ve got a little more time, you can increase engagement and bring your campaign to life with a branded Paywall. Branding your paywall takes slightly longer, but will lead to significantly higher conversion.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-1-build-your-paywall&quot;&gt;Step 1: Build your paywall&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;538&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Editor-1024x538.png&quot; alt=&quot;&quot; class=&quot;wp-image-48231&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Editor-1024x538.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Editor-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Editor-768x403.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Editor-1536x806.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Editor-2048x1075.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Editor-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Editor-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Editor-696x365.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Editor-560x294.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Editor-840x441.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Editor-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Editor-48x25.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Open the &lt;a href=&quot;https://www.revenuecat.com/docs/web/web-billing/paywalls&quot;&gt;&lt;strong&gt;Paywalls&lt;/strong&gt;&lt;/a&gt; editor in RevenueCat. When you create a new paywall, make sure to use the same offering you previously created for your Black Friday campaign.&lt;/p&gt;



&lt;p&gt;Start from a template or a blank layout, then add the pieces that sell your offer, headline, subhead, image or carousel, and product list. Keep the copy short and visual. Focus on the value of your deal, not the discount math.&lt;/p&gt;



&lt;p&gt;Good paywalls:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Lead with one clear message (for example, “Get X% off your first month/year of premium”)&lt;/li&gt;



&lt;li&gt;Use social proof if you have it, testimonials or logos add trust fast&lt;/li&gt;



&lt;li&gt;Add urgency (for example, “Offer ends Cyber Monday”)&lt;/li&gt;



&lt;li&gt;Match your brand colors and fonts to make the promo feel native&lt;/li&gt;
&lt;/ul&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-Z2lKN70 wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Good to know&quot; text=&quot;&lt;p&gt;Check out our &lt;a href=&amp;quot;https://www.revenuecat.com/blog/growth/paywalls-study-guide/&amp;quot;&gt;paywalls study guide&lt;/a&gt; for inspiration best practices to maximize conversion&lt;/p&gt;&quot; icon=&quot;bulb&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;p&gt;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-2-connect-the-flow&quot;&gt;Step 2: Connect the flow&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;538&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Custom-paywall-1-1-1024x538.png&quot; alt=&quot;&quot; class=&quot;wp-image-48255&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Custom-paywall-1-1-1024x538.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Custom-paywall-1-1-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Custom-paywall-1-1-768x403.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Custom-paywall-1-1-1536x806.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Custom-paywall-1-1-2048x1075.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Custom-paywall-1-1-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Custom-paywall-1-1-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Custom-paywall-1-1-696x365.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Custom-paywall-1-1-560x294.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Custom-paywall-1-1-840x441.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Custom-paywall-1-1-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Custom-paywall-1-1-48x25.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Once your paywall looks right, replace the paywall of your &lt;strong&gt;Web Purchase Link&lt;/strong&gt;. Go to your purchase link settings and change the radio button to the custom paywall setting. Double-check that the path flows cleanly:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Promo email or ad → paywall&lt;/li&gt;



&lt;li&gt;Paywall → checkout&lt;/li&gt;



&lt;li&gt;Checkout → redemption&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Everything should feel fast and friction-free.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-3-publish-and-monitor&quot;&gt;Step 3: Publish and monitor&lt;/h3&gt;



&lt;p&gt;Go live and keep an eye on the numbers. Adjust copy, layout, or pricing mid-campaign if you need to. The benefit of web is that you can ship changes instantly.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-time-to-get-started&quot;&gt;Time to get started!&lt;/h2&gt;



&lt;p&gt;Running a Black Friday campaign on the web is simple when you use the right tools. You control the offer, the checkout, and the customer data, all without app store limits. The web lets you move fast, test ideas, and keep more of your revenue.&lt;/p&gt;



&lt;p&gt;Here’s a quick recap:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Use &lt;a href=&quot;https://www.revenuecat.com/docs/web/web-billing/product-setup#introductory-period&quot;&gt;&lt;strong&gt;Intro Offers&lt;/strong&gt;&lt;/a&gt; to set up flexible discounts&lt;/li&gt;



&lt;li&gt;Create a &lt;a href=&quot;https://www.revenuecat.com/docs/web/web-billing/web-purchase-links&quot;&gt;&lt;strong&gt;Web Purchase Link&lt;/strong&gt;&lt;/a&gt; for a no-code checkout&lt;/li&gt;



&lt;li&gt;Add a &lt;a href=&quot;https://www.revenuecat.com/docs/web/web-billing/redemption-links&quot;&gt;&lt;strong&gt;Redemption Link&lt;/strong&gt;&lt;/a&gt; to connect the purchase to your app&lt;/li&gt;



&lt;li&gt;Build a &lt;strong&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/web/web-billing/paywalls&quot;&gt;Paywall&lt;/a&gt;&lt;/strong&gt; if you want full control of branding and testing&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Together, these pieces make it easy to launch a polished, high-converting campaign in a day. Your audience is already on the web. Bring them to a checkout that’s yours.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[How Flighty grows by obsessing over product, not ad campaigns]]></title><description><![CDATA[Flighty's Ryan Jones talks about the power of product-driven growth, why traditional marketing strategies often fall short, and the challenges of acquiring users while staying focused on building great products. ]]></description><link>https://www.revenuecat.com/blog/growth/ryan-jones-flighty-launched-podcast-2025/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/ryan-jones-flighty-launched-podcast-2025/</guid><pubDate>Wed, 19 Nov 2025 13:27:39 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/RC-Launched-Blog-Cover-Ryan-Jones-1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;When most teams think about growing a top-ranked app, the instinct is to reach for paid acquisition. But for Ryan Jones and the team behind Flighty – the meticulously crafted flight-tracking app – growth has come from a different place. Instead of ramping up ad campaigns, they’ve leaned into product, shareability, and craft.&lt;/p&gt;



&lt;p&gt;This week on &lt;em&gt;Launched&lt;/em&gt;, we sat down with Ryan to unpack how Flighty became one of the most beloved travel apps in the world by focusing almost entirely on the product experience.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;How Flighty Grew by Obsessing Over Product, Not Ad Campaigns — Ryan Jones&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/ulKpAAv5GJ4?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;iframe loading=&quot;lazy&quot; width=&quot;100%&quot; height=&quot;180&quot; frameborder=&quot;no&quot; scrolling=&quot;no&quot; seamless=&quot;&quot; src=&quot;https://share.transistor.fm/e/4c633044?color=FFFFFF&amp;amp;background=30343C&quot;&gt;&lt;/iframe&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-product-is-the-growth-engine&quot;&gt;&lt;strong&gt;Product is the growth engine&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Flighty’s philosophy is clear: build great features, and growth follows. Whenever the team has experimented with more conventional tactics, the trade-offs were obvious. As Ryan recalls, &lt;em&gt;“Every time we focused on product, we would’ve gotten basically more growth or free growth.”&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;The opposite was equally true: &lt;em&gt;“Every time we chased marketing tactics, we stalled.”&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;Over the years, Flighty has tried three separate attempts to spin up performance marketing. Each time, it diverted the team’s attention and delivered little in return. As Ryan puts it, &lt;em&gt;“It takes a significant amount of our attention away from building product… and at the end of the day… it kind of breaks even.”&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;That pattern reinforced a simple operating principle: &lt;em&gt;“We just need to stay at the stuff that we’re great at.”&lt;/em&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-focus-on-shareability-not-scale&quot;&gt;&lt;strong&gt;Focus on shareability, not scale&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Some of Flighty’s strongest growth has come from features that weren’t even designed for growth. The digital passport – an automatically updated, beautifully rendered flight log – quickly became one of the app’s biggest organic drivers. According to Ryan, &lt;em&gt;“The passport itself… if it’s not our number one growth driver, it’s top three.”&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;The team spent months refining small touches, including a now-iconic black-light effect. &lt;em&gt;“One of the things that we haven’t mentioned yet… on the original one, a black light button… that was a huge part of it.”&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;Not every experiment landed. Their first attempt at a “year in review” flopped: &lt;em&gt;“For some reason it just didn’t really catch on.”&lt;/em&gt; But revisiting the idea through the lens of craft, storytelling, and visual delight produced a completely different outcome: &lt;em&gt;“It took us a while, but we figured out that… it’s gone crazy.”&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;Other features quietly fuel the same organic loops. Flighty’s live flight-sharing links, for instance, solve a familiar problem for travelers and introduce new users in the process. Ryan summed up the intention: &lt;em&gt;“We’re looking for things that we can do in Flighty that help the user… and help someone else come into the ecosystem.”&lt;/em&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-a-deliberate-approach-to-acquisition&quot;&gt;&lt;strong&gt;A deliberate approach to acquisition&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Flighty doesn’t run Facebook ads, TikTok campaigns, or performance UA. The only paid channel it invests in is Apple Search Ads (ASA).&lt;/p&gt;



&lt;p&gt;&lt;em&gt;“The one thing we do do is App Store Optimization or ASA,”&lt;/em&gt; Ryan explains. And it matters: &lt;em&gt;“That’s probably 20 or 30% of our new users… come through ASA.”&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;But even here, the team is cautious. Running ASA without expertise is a quick way to burn money. As Ryan puts it plainly: &lt;em&gt;“If you’re doing the basic version of ASA, you’re probably losing money.”&lt;/em&gt; The solution, he says, is simple: &lt;em&gt;“You have to have… a specialist.”&lt;/em&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-growth-from-delight&quot;&gt;&lt;strong&gt;Growth from delight&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Flighty’s reputation has also benefited from embracing new iOS capabilities like Live Activities and Dynamic Island on day one. These moments led to App Store features and Apple mentions, but the real value came from how seamlessly they improved the experience for travelers.&lt;/p&gt;



&lt;p&gt;Above everything else, the team relies on a simple north star: would we want this ourselves? That consistent focus on usefulness, clarity, and delight has helped Flighty grow on its own terms – without chasing the typical tactics.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-conclusion&quot;&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;From the viral passport to disciplined ASO, this episode offers a clear blueprint for product-led growth. Whether you’re building a travel app or scaling without traditional ad campaigns, Ryan Jones shows how far a team can go by focusing deeply on what they do best and letting users spread the word.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[How to run a holiday sale in Play Console for Android subscription apps]]></title><description><![CDATA[A practical guide to planning, configuring, and promoting seasonal subscription offers on Google Play.]]></description><link>https://www.revenuecat.com/blog/growth/holiday-sale-google-play-console/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/holiday-sale-google-play-console/</guid><pubDate>Wed, 19 Nov 2025 09:27:43 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/cover.jpg" length="0" type="image/*"/><content:encoded>&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;How to run a holiday sale in Google Play Console for Android subscription apps&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/naQnmPvDCjo?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;Holiday season is one of the most powerful times of year to attract new subscribers, re-engage lapsed customers, and strengthen the relationship with your existing audience. Between Black Friday, Cyber Monday, Christmas shopping and New Year Sales, consumers are on the hunt for deals. If you’re an Android developer with a subscription-based app, you can &lt;strong&gt;use Google Play’s offer tools to create a compelling holiday promotion&lt;/strong&gt; that boosts conversions and &lt;a href=&quot;https://www.revenuecat.com/glossary/#lifetime-value-ltv&quot;&gt;lifetime value (LTV)&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;This guide walks you through every step of creating, launching, and analyzing a holiday subscription offer using the Google Play Console and RevenueCat.&amp;nbsp;&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-Z2cbl4t wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Note&quot; text=&quot;&lt;p&gt;This guide follows the same logic as &lt;a href=&amp;quot;https://www.revenuecat.com/docs/subscription-guidance/subscription-offers/google-play-offers&amp;quot;&gt;RevenueCat&apos;s subscription offers documentation&lt;/a&gt; but is designed specifically for seasonal campaigns.&lt;/p&gt;&quot; icon=&quot;circle-info&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-overview-of-google-play-subscriptions&quot;&gt;Overview of Google Play subscriptions&lt;/h2&gt;



&lt;p&gt;Let’s first refresh our minds on how subscriptions work in Google Play Store.&lt;/p&gt;



&lt;p&gt;In Google Play Store, every subscription can have multiple &lt;strong&gt;base plans&lt;/strong&gt;, which in turn can have multiple &lt;strong&gt;offers&lt;/strong&gt;. Base plans define the subscription billing period (monthly, yearly), renewal type (auto-renewing, prepaid), and the price. Offers define the discount available to users matching the eligibility criteria. Offers can only be configured for auto-renewing offers.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Each subscription in Google Play Store can create a combined total of 250 base plans and offers, with a maximum of 50 being active at the same time.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;576&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-19-1024x576.png&quot; alt=&quot;Different subscription object types from https://support.google.com/googleplay/android-developer/answer/12154973?hl=en&quot; class=&quot;wp-image-48184&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-19-1024x576.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-19-300x169.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-19-768x432.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-19-1536x864.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-19-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-19-71x40.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-19-696x392.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-19-560x315.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-19-526x296.png 526w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-19-840x472.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-19-80x45.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-19-48x27.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-19.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-two-ways-to-run-a-sale-on-google-play&quot;&gt;Two ways to run a sale on Google Play&lt;/h2&gt;



&lt;p&gt;Before diving deeper, it’s important to understand that Google Play provides &lt;strong&gt;two primary mechanisms&lt;/strong&gt; for running discounted subscription promotions:&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-1-offer-phases&quot;&gt;1. Offer phases&lt;/h2&gt;



&lt;p&gt;Use the standard offer system inside Google Play subscriptions. Each offer can include up to two phases (free trial, introductory pricing, discounted billing cycles). These are best for broad, paywall-visible sales where your goal is to drive conversions directly through the subscription product configuration.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-2-promo-codes&quot;&gt;2. Promo codes&lt;/h2&gt;



&lt;p&gt;Codes that unlock a free trial or access to a subscription. Promo codes are redeemed manually by the user. They’re best for &lt;strong&gt;targeted&lt;/strong&gt;, &lt;strong&gt;limited-quantity&lt;/strong&gt;, &lt;strong&gt;partner-driven&lt;/strong&gt;, or &lt;strong&gt;community-driven&lt;/strong&gt; campaigns where you want tight control over who can redeem the offer.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-planning-your-holiday-offer&quot;&gt;Planning your holiday offer&lt;/h2&gt;



&lt;p&gt;A strong campaign begins with clear goals and a defined audience. Before you touch Google Play Console, decide what success looks like for your app.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-defining-your-goals&quot;&gt;Defining your goals&lt;/h3&gt;



&lt;p&gt;Ask yourself what you’re trying to accomplish. Do you want to acquire new users? Reactivate past subscribers? Reward loyal customers? Each goal requires a different setup. For example, acquisition offers target users who have not subscribed before, while developer-determined offers can re-engage lapsed ones.&lt;/p&gt;



&lt;p&gt;Holiday timing also matters. Some apps see their biggest lift during Black Friday weekend, while others benefit from the post-Christmas days when people are setting up new devices. Map out a timeline and plan your offers around it, whether that’s &lt;a href=&quot;https://www.revenuecat.com/glossary/#trial-conversion-rate&quot;&gt;install-to-trial conversion&lt;/a&gt;, first &lt;a href=&quot;https://www.revenuecat.com/glossary/#renewal-rate&quot;&gt;renewal rate&lt;/a&gt;, or total recurring revenue.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-choosing-between-offer-phases-and-promo-codes-based-on-your-goal&quot;&gt;Choosing between Offer Phases and Promo Codes based on your goal&lt;/h3&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;If your goal is &lt;strong&gt;maximum conversion from new users&lt;/strong&gt; during a big holiday event (e.g., Black Friday), then use &lt;strong&gt;Offer phases&lt;/strong&gt;. These appear directly on your paywall and require no code entry. They scale well for large-volume campaigns.&lt;/li&gt;



&lt;li&gt;If your goal is &lt;strong&gt;targeted reactivation&lt;/strong&gt;, &lt;strong&gt;gifting&lt;/strong&gt;, &lt;strong&gt;influencer partnerships&lt;/strong&gt;, or &lt;strong&gt;limited-edition holiday bonuses&lt;/strong&gt;, then &lt;strong&gt;Promo codes&lt;/strong&gt; may be the better tool. They give you full control over distribution, but require more user effort and don’t automatically appear on the paywall.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Promo codes and offer phases can coexist in the same campaign, but most apps will rely on offer phases as the default mechanism for holiday sales.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-segmenting-your-audience-using-eligibility-criteria&quot;&gt;Segmenting your audience using eligibility criteria&lt;/h3&gt;



&lt;p&gt;Eligibility rules apply specifically to subscription offers created using Offer Phases. They determine which users will see a given offer inside the subscription options returned by Play Billing and RevenueCat. Promo codes bypass eligibility checks because the user explicitly redeems them.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;256&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.26.36-1024x256.png&quot; alt=&quot;&quot; class=&quot;wp-image-48202&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.26.36-1024x256.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.26.36-300x75.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.26.36-768x192.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.26.36-1536x384.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.26.36-50x13.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.26.36-125x31.png 125w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.26.36-696x174.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.26.36-560x140.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.26.36-840x210.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.26.36-80x20.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.26.36-48x12.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.26.36.png 2032w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;br&gt;&lt;strong&gt;New customer acquisition:&lt;/strong&gt; With this eligibility criterion, Google Play determines if a customer is eligible to receive the offer. You can configure this to check for customers who have never had &lt;strong&gt;this particular subscription&lt;/strong&gt; to your app, or customers who have never had &lt;strong&gt;any subscription&lt;/strong&gt; to your app. If Google Play determines a customer is not eligible, the offer will &lt;strong&gt;not&lt;/strong&gt; show up in the subscriptionOptions of the StoreProduct in the SDK at all.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Upgrade:&lt;/strong&gt; This eligibility criterion is the inverse of the previous one. Customers are only eligible if they &lt;strong&gt;currently have another subscription&lt;/strong&gt; of your product, and you can configure in detail what products this offer applies to. Again, if Google Play determines a customer is not eligible, the offer will &lt;strong&gt;not&lt;/strong&gt; show up in the subscriptionOptions of the StoreProduct in the SDK at all.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Developer determined:&lt;/strong&gt; Offers with this eligibility criterion will &lt;strong&gt;always&lt;/strong&gt; show up in the subscriptionOptions of the StoreProduct in the SDK, and &lt;strong&gt;you are responsible&lt;/strong&gt; for determining whether or not to apply the offer to a customer. If you are relying on the RevenueCat SDK automatically applying free trials and introductory periods and you &lt;strong&gt;do not&lt;/strong&gt; want a developer determined offer to be automatically selected, apply the tag &lt;code&gt;rc-ignore-offer&lt;/code&gt; to the offer.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;185&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-18-1024x185.png&quot; alt=&quot;&quot; class=&quot;wp-image-48182&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-18-1024x185.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-18-300x54.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-18-768x139.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-18-50x9.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-18-125x23.png 125w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-18-696x126.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-18-560x101.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-18-840x152.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-18-80x14.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-18-48x9.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-18.png 1370w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-offer-phases&quot;&gt;Offer phases&lt;/h3&gt;



&lt;p&gt;Offer phases are one of the two main tools for running a Google Play sale. They let you create up to two sequential discounted billing periods, such as a free trial followed by introductory pricing before the subscription resumes its normal base plan price. Offer phases are ideal for large seasonal sales because they appear automatically on your paywall and scale effortlessly to all eligible users.&lt;/p&gt;



&lt;p&gt;Decide whether your holiday deal will be a short-term discount or a longer phased pricing plan. A big one month discount can drive conversions, but a phased offer plan may improve retention.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-promo-codes&quot;&gt;Promo codes&lt;/h3&gt;



&lt;p&gt;Play console also allows developers to create codes that are redeemable for one-time products or as trials to subscriptions. There are two types of promo codes.&amp;nbsp;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;One-time codes&lt;/strong&gt; are unique, auto-generated by the Google Play console, and limited to a single-use&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Custom codes&lt;/strong&gt; are codes created by the developer which are redeemable as many times as the developer allows&lt;/li&gt;
&lt;/ul&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-Z1WYxke wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Good to know&quot; text=&quot;&lt;p&gt;This guide will not cover creating promo codes, but our documentation on that is a good source for doing these correctly. Read more about &lt;a href=&amp;quot;https://www.revenuecat.com/docs/subscription-guidance/subscription-offers/google-play-offers#redeeming-promo-codes&amp;quot;&gt;redeeming promo codes here&lt;/a&gt;.&lt;/p&gt;&quot; icon=&quot;bulb&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;833&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.25.38-1024x833.png&quot; alt=&quot;&quot; class=&quot;wp-image-48200&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.25.38-1024x833.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.25.38-300x244.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.25.38-768x625.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.25.38-1536x1250.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.25.38-2048x1667.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.25.38-50x41.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.25.38-49x40.png 49w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.25.38-570x464.png 570w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.25.38-696x566.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.25.38-560x456.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.25.38-364x296.png 364w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.25.38-580x472.png 580w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.25.38-80x65.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.25.38-48x39.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-setting-up-a-holiday-offer-in-google-play-console&quot;&gt;Setting up a holiday offer in Google Play Console&lt;/h2&gt;



&lt;p&gt;Once your goals and audience are clear, the next step is to create the offer in Google Play Console. The entire configuration happens there, and once you are familiar with the workflow, each new offer only takes a few minutes to create.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-1-configure-your-base-plan&quot;&gt;Step 1: Configure your base plan&lt;/h3&gt;



&lt;p&gt;Every subscription offer must belong to a base plan. A base plan defines the underlying product ID, billing period, and standard pricing that your offer will temporarily override.&lt;/p&gt;



&lt;p&gt;In Play Console, open Monetization → Subscriptions, choose your subscription product, and verify that your base plan is active in all regions where you intend to run the holiday promotion.&lt;/p&gt;



&lt;p&gt;If you want to isolate campaign results, consider creating a separate base plan named something like &lt;code&gt;premium-holiday2025&lt;/code&gt;. This lets you switch back to your standard base plan later without affecting other configurations.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;686&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.23.05-1024x686.png&quot; alt=&quot;&quot; class=&quot;wp-image-48198&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.23.05-1024x686.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.23.05-300x201.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.23.05-768x514.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.23.05-1536x1029.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.23.05-2048x1371.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.23.05-50x33.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.23.05-60x40.png 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.23.05-693x464.png 693w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.23.05-696x466.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.23.05-560x375.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.23.05-442x296.png 442w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.23.05-705x472.png 705w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.23.05-80x54.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.23.05-48x32.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-2-create-a-new-offer&quot;&gt;Step 2: Create a new offer&lt;/h3&gt;



&lt;p&gt;Under your chosen base plan, click Add offer. Give the offer a descriptive and human-readable ID such as &lt;code&gt;holiday-2025-blackfriday &lt;/code&gt;or &lt;code&gt;holiday-2025-reactivation&lt;/code&gt;. Clear naming matters because you will see this ID in RevenueCat dashboards, cohort exports, and logs.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;404&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-20-1024x404.png&quot; alt=&quot;&quot; class=&quot;wp-image-48185&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-20-1024x404.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-20-300x119.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-20-768x303.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-20-1536x607.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-20-50x20.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-20-101x40.png 101w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-20-696x275.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-20-560x221.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-20-840x332.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-20-80x32.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-20-48x19.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-20.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Once created, the offer lives under that base plan and can be toggled on or off without deleting it, allowing easy reuse for future events.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-3-define-eligibility&quot;&gt;Step 3: Define eligibility&lt;/h3&gt;



&lt;p&gt;As mentioned in the planning section, Google Play provides three core eligibility rules, which control who can redeem your offer:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;New customer acquisition:&lt;/strong&gt; only users who have never subscribed to this product can redeem it — perfect for first-time installs during your holiday user-acquisition blitz&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Upgrade:&lt;/strong&gt; for customers moving from a lower tier or a legacy subscription to a higher-value plan&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Developer determined:&lt;/strong&gt; you decide in-app who qualifies — this is ideal for re-engaging churned subscribers or rewarding loyal users&lt;/li&gt;
&lt;/ol&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;285&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.21.42-1024x285.png&quot; alt=&quot;&quot; class=&quot;wp-image-48196&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.21.42-1024x285.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.21.42-300x84.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.21.42-768x214.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.21.42-1536x428.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.21.42-2048x571.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.21.42-50x14.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.21.42-125x35.png 125w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.21.42-696x194.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.21.42-560x156.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.21.42-840x234.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.21.42-80x22.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.21.42-48x13.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;For holiday campaigns, ‘New customer acquisition’ often performs best for growth, while ‘Developer determined’ gives maximum flexibility for reactivation deals. To enforce developer-determined eligibility, your app checks conditions through the Play Billing Library before showing the discounted SKU. E.g., if a user canceled more than 60 days ago, you can programmatically make them eligible for the &lt;code&gt;holiday-2025-reactivate&lt;/code&gt; offer.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-4-set-pricing-phases&quot;&gt;Step 4: Set pricing phases&lt;/h3&gt;



&lt;p&gt;A single offer can include up to two pricing phases, letting you script how the price changes over time. For example:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Phase one might be a one month free trial&lt;/li&gt;



&lt;li&gt;Phase two can ease the user back toward the standard price, e.g. 50% off for January, before auto-transitioning to the base plan price in February&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;These phases make it possible to reward early adopters without locking in low pricing permanently.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;214&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.18.42-1024x214.png&quot; alt=&quot;&quot; class=&quot;wp-image-48194&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.18.42-1024x214.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.18.42-300x63.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.18.42-768x161.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.18.42-1536x322.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.18.42-2048x429.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.18.42-50x10.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.18.42-125x26.png 125w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.18.42-696x146.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.18.42-560x117.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.18.42-840x176.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.18.42-80x17.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.18.42-48x10.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;When editing a phase, specify both the price and duration (in billing cycles). Remember that each phase must be at least one billing period long. Preview the total charge sequence in the summary view before publishing.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-5-add-tags-and-metadata&quot;&gt;Step 5: Add tags and metadata&lt;/h3&gt;



&lt;p&gt;Tags are optional but highly recommended. They allow you to track performance later in RevenueCat and the Play Console reports. Use concise, consistent tags like &lt;code&gt;holiday-sale&lt;/code&gt;, &lt;code&gt;black-friday&lt;/code&gt;, or &lt;code&gt;q4-2025&lt;/code&gt;.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;190&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.18.21-1024x190.png&quot; alt=&quot;&quot; class=&quot;wp-image-48192&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.18.21-1024x190.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.18.21-300x56.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.18.21-768x143.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.18.21-1536x285.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.18.21-2048x380.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.18.21-50x9.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.18.21-125x23.png 125w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.18.21-696x129.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.18.21-560x104.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.18.21-840x156.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.18.21-80x15.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-10.18.21-48x9.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Within RevenueCat, you will see these tags alongside each transaction, making it easy to filter cohorts or compare, e.g. &lt;code&gt;black-friday&lt;/code&gt; versus &lt;code&gt;standard-offer&lt;/code&gt; revenue.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-7-integrate-and-test-with-revenuecat&quot;&gt;Step 7: Integrate and test with RevenueCat&lt;/h3&gt;



&lt;p&gt;Finally, ensure your app recognizes the new offer. In your RevenueCat setup, reference it through the SDK’s subscriptionOptions so that the correct price and offer period appear on the paywall.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z2m3Bo3 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;val basePlan = storeProduct.subscriptionOptions?.basePlan\nval freeTrialOffer = storeProduct.subscriptionOptions?.freeTrial\nval introductoryOffer = storeProduct.subscriptionOptions?.introOffer\nval offerForLapsedCustomers = storeProduct.subscriptionOptions?.withTag(\&amp;quot;lapsed-customers\&amp;quot;).first()\n\n\/\/ For example, to purchase the offer for lapsed customers directly, you would then use the following code\nPurchases.sharedInstance.purchaseWith(\n  PurchaseParams.Builder(requireActivity(), offerForLapsedCustomers).build(), \n  onError = { error, userCancelled -&gt;\n    ...\n  },\n  onSuccess = { storeTransaction, customerInfo -&gt;\n    ...\n  }\n)&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Use test accounts in the Play Console’s license testing section to confirm eligibility logic, pricing-phase transitions, and analytics tagging before launch.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/engineering/testing-test-store/&quot;&gt;RevenueCat’s sandbox environment&lt;/a&gt; mirrors the offer structure, so you can verify that events like “Initial Purchase” and “Renewal – Offer Phase 2” appear as expected.&lt;/p&gt;



&lt;p&gt;Once everything checks out, publish the offer and sync your paywall assets so users see the new holiday pricing immediately.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-marketing-your-introductory-offer&quot;&gt;Marketing your introductory offer&lt;/h2&gt;



&lt;p&gt;Once you have your offers set up, users will begin seeing your discounted price or free trial at the scheduled time, but they won’t have any indication there’s a sale. You can, of course, run external marketing campaigns to message out the discounted price, but your best bet is to message about the sale in the app using a custom paywall.&lt;/p&gt;



&lt;p&gt;If you use &lt;a href=&quot;https://www.revenuecat.com/feature/paywalls/&quot;&gt;RevenueCat Paywalls&lt;/a&gt;, you can easily build a custom paywall for your sale and switch the default offering to the offering with your custom paywall to immediately start showing it within the app. If you were already using RevenueCat Paywalls for your presale offerings then setting up this sale requires no code changes at all.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;When using RevenueCat’s SDK with a custom paywall, Offering Metadata is the perfect solution for you. Simply add a field to your metadata JSON to specify which paywall you want to be shown, and then in your app check that metadata property to decide which paywall to render. To start and stop your sale paywall, you simply need to change this one JSON property in your Offering Metadata.&amp;nbsp;&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;734&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-9.28.39-1024x734.png&quot; alt=&quot;&quot; class=&quot;wp-image-48190&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-9.28.39-1024x734.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-9.28.39-300x215.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-9.28.39-768x551.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-9.28.39-1536x1101.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-9.28.39-2048x1468.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-9.28.39-50x36.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-9.28.39-56x40.png 56w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-9.28.39-647x464.png 647w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-9.28.39-696x499.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-9.28.39-560x401.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-9.28.39-413x296.png 413w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-9.28.39-658x472.png 658w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-9.28.39-80x57.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Screenshot-2025-11-19-at-9.28.39-48x34.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-wrapping-up&quot;&gt;Wrapping up 🎁&lt;/h2&gt;



&lt;p&gt;Holiday promotions on Google Play are one of the easiest and most effective ways to grow subscription revenue when consumer attention is at its peak. Planning early, defining clear goals, and using Google Play’s offer tools together with RevenueCat’s analytics, you can turn a seasonal discount into long-term subscribers. Make the offer simple to understand, run it during a defined window, and track every result.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;When done well, a holiday campaign not only boosts year-end numbers but also sets a foundation for stronger retention and smarter promotions all year round.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Stop chasing growth hacks — fix your funnel first]]></title><description><![CDATA[Why the first two minutes of onboarding are your biggest growth lever]]></description><link>https://www.revenuecat.com/blog/growth/fix-onboarding-funnels/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/fix-onboarding-funnels/</guid><pubDate>Mon, 17 Nov 2025 15:52:08 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Stop-chasing-growth-hacks-—-fix-your-funnel-first.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;There are some stories I keep coming back to, because they surprise people every single time.&lt;/p&gt;



&lt;p&gt;They don’t start with a viral campaign or a million-dollar experiment.&lt;/p&gt;



&lt;p&gt;They start with something quieter — a spreadsheet, a late-night analysis, and one stubborn data point that rewired the way I thought about growth forever.&lt;/p&gt;



&lt;p&gt;This story begins (improbably enough) with onboarding.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-spreadsheet-that-changed-everything&quot;&gt;&lt;strong&gt;The spreadsheet that changed everything&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Back in 2018, I was sitting at my desk, convinced I already understood how users behave, until the numbers quietly dismantled everything I thought I knew.&lt;/p&gt;



&lt;p&gt;I was mapping conversion windows for an app, tracking the exact moment people decided to pay.&lt;/p&gt;



&lt;p&gt;It was slow, manual work: scribbling timestamps on paper, transferring data cell by cell, building the story line by line. The kind of task that feels like punishment when you start, but is so satisfying when you finish because you’ve built something solid with your own hands.&lt;/p&gt;



&lt;p&gt;I expected the numbers to confirm a story I’d told myself for years: users arrive, explore, find their &lt;em&gt;aha!&lt;/em&gt; moment, and only then decide to subscribe.&lt;/p&gt;



&lt;p&gt;The truth? They didn’t.&lt;/p&gt;



&lt;p&gt;Over 80% of all subscriptions happened within two minutes of download. Not day two. Not three hours in. Two minutes.&lt;/p&gt;



&lt;p&gt;That’s before they’d even experienced the product. Before any of the features we obsessed over had the chance to matter.&lt;/p&gt;



&lt;p&gt;They downloaded, flowed through onboarding, hit the paywall, and made a decision. No feature use. No deep exploration. Just a feeling, a pitch, and a choice.&lt;/p&gt;



&lt;p&gt;And it turns out, this wasn’t an anomaly.&lt;/p&gt;



&lt;p&gt;Fast-forward to 2025: &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps-2025/&quot;&gt;RevenueCat’s State of Subscription Apps&lt;/a&gt; report shows the same pattern at scale: across all categories, 82% of subscription app trial starts still happen on day zero.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps-2025/&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;757&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-1024x757.jpeg&quot; alt=&quot;&quot; class=&quot;wp-image-48146&quot; style=&quot;object-fit:cover&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-1024x757.jpeg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-300x222.jpeg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-768x568.jpeg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-50x37.jpeg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-54x40.jpeg 54w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-628x464.jpeg 628w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-696x515.jpeg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-560x414.jpeg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-400x296.jpeg 400w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-638x472.jpeg 638w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-80x59.jpeg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-48x35.jpeg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image.jpeg 1170w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/a&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;Download to trial, by access&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;In other words, for most subscription products, &lt;strong&gt;your window to convert someone has never been smaller&lt;/strong&gt;.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-illusion-of-the-aha-moment-in-app-marketing&quot;&gt;&lt;strong&gt;The illusion of the &lt;/strong&gt;&lt;strong&gt;&lt;em&gt;aha!&lt;/em&gt;&lt;/strong&gt;&lt;strong&gt; moment in app marketing&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Realising that those first two minutes decide the fate of almost every subscription app, I couldn’t stop thinking about what that really meant.&lt;/p&gt;



&lt;p&gt;If people were committing before they’d even experienced the product, what did that say about everything we’d built to be discovered later?&lt;/p&gt;



&lt;p&gt;The gradual build-up. The elegant flow toward the &lt;em&gt;aha!&lt;/em&gt; moment. The free-will discovery we imagined users would stumble into somewhere in the middle of the journey.&lt;/p&gt;



&lt;p&gt;What if that moment wasn’t waiting in the middle at all, but right there at the start?&lt;br&gt;&lt;br&gt;Masterminds of audience engagement love the grand story arc, what many refer to as the Hero’s Journey: curiosity, exploration, enlightenment, decision. App marketers often borrow this structure for user funnels — the gradual build-up, the carefully sequenced onboarding, the climactic &lt;em&gt;aha! &lt;/em&gt;moment that supposedly arrives once the user has explored enough.&lt;/p&gt;



&lt;p&gt;But unfortunately, human behavior doesn’t always follow that script.&lt;/p&gt;



&lt;p&gt;In reality, it’s shorter, sharper, and far more primal. People don’t wait to fall in love with your app; they make up their minds almost instantly.&lt;/p&gt;



&lt;p&gt;We often treat onboarding as if it were the trailer before the movie. But for most users, onboarding is the movie. The opening scene IS the decision.&lt;/p&gt;



&lt;p&gt;If you haven’t earned their hearts within the first few screens, you’ve already lost them.&lt;/p&gt;



&lt;p&gt;There’s also what psychologists call the &lt;a href=&quot;https://medium.com/@fghidan/time-perception-when-perception-lags-behind-reality-d32ff30bae92&quot;&gt;perception–experience lag&lt;/a&gt;: users don’t judge what the product is; they judge what it feels like it will be. That lag lasts only a few seconds, but in that brief window, your brand equity is either born or it dies.&lt;/p&gt;



&lt;p&gt;A beautifully coded feature that solves a real pain point means nothing if the promise of that value doesn’t land first.&lt;/p&gt;



&lt;p&gt;Humans are story-driven, not spec-driven.&lt;/p&gt;



&lt;p&gt;They buy the narrative of progress long before they ever touch the proof. Once you truly understand what happens in those first two minutes, you stop treating onboarding as maintenance and start treating it as one of your most powerful growth levers.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-funnel-work-beats-retention-work&quot;&gt;&lt;strong&gt;Why funnel work beats retention work&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Shifting from seeing onboarding as a supporting act to treating it as the stage itself changes everything. It reframes how you think about growth entirely; and where leverage truly lives.&lt;/p&gt;



&lt;p&gt;In every growth meeting I’ve ever sat through, someone eventually says:&lt;/p&gt;



&lt;p&gt;“If we can just improve 30-day retention by 5%…”&lt;/p&gt;



&lt;p&gt;Yes, retention compounds, and that matters. But as we’ve already seen, about 80% of conversions still happen in the first session, regardless of your overall rate. The concentration doesn’t move; only the size of the pool does. That means the better your funnel performs, the more that 80% pays off.&lt;br&gt;&lt;br&gt;A five-point improvement in onboarding can therefore create a far greater impact than the same lift in retention, because funnel gains apply to every new user you attract, while retention gains only benefit the ones you’ve already won.&lt;/p&gt;



&lt;p&gt;This is the math most teams overlook.&lt;/p&gt;



&lt;p&gt;They chase loyalty before they’ve earned belief. They optimise for longevity before they’ve secured commitment.&lt;/p&gt;



&lt;p&gt;When you shift focus to the first touchpoint, the moment where intent crystallises or evaporates, you’re no longer just fixing drop-off. You’re compounding every dollar of acquisition that follows.&lt;/p&gt;



&lt;p&gt;So when teams ask, &lt;em&gt;“Where can we do the most impactful work?”&lt;/em&gt;, the answer is almost always the same: look at the very first touchpoint.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-example-flo-s-use-of-commitment-psychology&quot;&gt;Example: Flo’s use of commitment psychology&lt;/h2&gt;



&lt;p&gt;If the first touchpoint is where growth truly lives, few companies embody that truth better than &lt;a href=&quot;https://flo.health&quot;&gt;&lt;strong&gt;Flo&lt;/strong&gt;&lt;/a&gt;, the period-tracking app. Without overstating it, it’s safe to say Flo turned its first two minutes of use into one of the most profitable pieces of real estate in the subscription economy. Here’s how…&lt;br&gt;&lt;br&gt;Flo launched in 2015 as a simple period-tracking app and has since evolved into a full-scale health platform. Today, it reaches over 420 million users worldwide, and what’s most impressive isn’t the scale but &lt;em&gt;how&lt;/em&gt; that scale was built.&lt;br&gt;&lt;br&gt;When I interviewed &lt;a href=&quot;https://subclub.com/episode/how-to-maximize-revenue-with-regional-pricing-dmitry-gurski-flo&quot;&gt;Dmitry Gurski, co-founder of Flo&lt;/a&gt;, at an Aperture Sessions event in London, I asked him about experimentation at Flo. He explained that Flo doesn’t leave first impressions to chance. At the time, they were running more than 15,000 tests a year, not focused on adding shiny new features but on refining how people feel in those first two minutes.&lt;/p&gt;



&lt;p&gt;Dmitry told me that when Flo first launched, monetisation wasn’t a focus. For years, they grew without it through millions of installs and steady chart positions driven almost entirely by word of mouth and the gravitational pull of late-2010s App Store feature spots (remember those days?).&lt;/p&gt;



&lt;p&gt;By the time they decided to switch on monetisation, their data team modelled what ‘good’ might look like for a subscription app. The target was ambitious yet achievable.&lt;br&gt;And then they blew past it by multiples.&lt;/p&gt;



&lt;p&gt;Flo now monetises around &lt;strong&gt;25% of its US audience&lt;/strong&gt;. Read that again: roughly one-in-four American users chooses to pay. That’s wild.&lt;/p&gt;



&lt;p&gt;One of the subtle levers that helped get them there, which sits quietly inside the onboarding flow, was the &lt;strong&gt;commitment screen&lt;/strong&gt;.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;438&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Flo-commitment-screen-1024x438.png&quot; alt=&quot;&quot; class=&quot;wp-image-48152&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Flo-commitment-screen-1024x438.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Flo-commitment-screen-300x128.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Flo-commitment-screen-768x328.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Flo-commitment-screen-1536x657.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Flo-commitment-screen-50x21.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Flo-commitment-screen-94x40.png 94w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Flo-commitment-screen-696x298.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Flo-commitment-screen-560x239.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Flo-commitment-screen-840x359.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Flo-commitment-screen-80x34.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Flo-commitment-screen-48x21.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Flo-commitment-screen.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;Flo’s commitment prompt just before the paywall&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;I’ve loved this tactic for years, and Flo’s execution is almost textbook. Before users see the paywall, they’re asked to affirm intent: a soft, psychologically-charged moment that converts self-reflection into micro-commitment.&lt;/p&gt;



&lt;p&gt;They’re not alone. &lt;a href=&quot;https://makeheadway.com/onboarding/self-growth/landing?utm_source=google&amp;amp;utm_campaign=WO_Search_ENG_HW_Brand_TIER1&amp;amp;utm_adset=WO_Search_ENG_HW_Brand_TIER1&amp;amp;utm_term=headway&amp;amp;utm_campaignid=22963472116&amp;amp;utm_adgroupid=184314789309&amp;amp;gad_source=1&amp;amp;gad_campaignid=22963472116&amp;amp;gbraid=0AAAAApRlofIkjGvNponbAczRtHe33iOth&amp;amp;gclid=Cj0KCQiA5abIBhCaARIsAM3-zFUUzFtdcl4wbUJ8IFJEBwJ5F93f2WEeWQUHZh_N4j7i6p8E4BkG0QcaAqmdEALw_wcB&quot;&gt;&lt;strong&gt;Headway&lt;/strong&gt;&lt;/a&gt; uses it. &lt;a href=&quot;https://www.duolingo.com&quot;&gt;&lt;strong&gt;Duolingo&lt;/strong&gt;&lt;/a&gt; uses it. Many others follow the pattern.&lt;br&gt;The interface differs: &lt;em&gt;Hold down your thumb. I’m committing. Sign your name. Answer a pledge question.&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;The design changes, but the psychology doesn’t.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;438&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-14-1024x438.png&quot; alt=&quot;&quot; class=&quot;wp-image-48150&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-14-1024x438.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-14-300x128.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-14-768x328.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-14-1536x657.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-14-50x21.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-14-94x40.png 94w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-14-696x298.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-14-560x239.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-14-840x359.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-14-80x34.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-14-48x21.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-14.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;Here’s how Headway and Duolingo do this, just before their paywall&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;Even something as trivial as tapping a button can trigger that deep, almost irrational human need to stay consistent with what we’ve already declared.&lt;/p&gt;



&lt;p&gt;As Robert Cialdini explains in his classic book &lt;em&gt;Influence&lt;/em&gt;, the psychology of commitment is one of the most reliable forces in human behavior: once people take even a small stand, they feel compelled to stay consistent with it.&lt;/p&gt;



&lt;p&gt;Before you ever see Flo’s paywall, you’ve already said to yourself: &lt;em&gt;I’m ready. &lt;/em&gt;The decision shifts from ‘should I buy this?’ to ‘should I stop what I’ve already committed to?’&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;I’ve seen the same pattern play out firsthand in smaller products too&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;A couple of years ago, I worked with a sustainability app that struggled with the same problem Flo solved on a much larger stage: high installs, low follow-through.&lt;br&gt;Users loved the idea but weren’t sticking around long enough to turn good intentions into habits.&lt;/p&gt;



&lt;p&gt;So we tried something simple. We added a single commitment request screen during onboarding that asked users to confirm: “I’m committing to reducing my carbon footprint this month.”&lt;/p&gt;



&lt;p&gt;One tap. No feature redesign. No new UX patterns. Just a moment of micro-ownership.&lt;/p&gt;



&lt;p&gt;The result? &lt;strong&gt;Day-30 retention doubled.&lt;/strong&gt; Not because of design, because of psychology.&lt;/p&gt;



&lt;p&gt;Flo has a big team running 15,000 tests a year. This little sustainability app had a humble-sized team of five people.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Different scale, same instinct: action creates identity.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;4-psychological-levers-behind-the-commitment-tactics&quot;&gt;&lt;strong&gt;4 psychological levers behind the commitment tactics&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;What makes Flo’s onboarding powerful is the psychology behind it. The tap, the pledge, the quiet ‘I’m ready’ moment that reaches deeper than the interface. They capture the instant when interest turns into intent.&lt;br&gt;&lt;br&gt;Across the best onboarding flows, Flo’s thumbprint pledge, Headway’s commitment pact, Duolingo’s playful badge, the same idea appears. Each uses subtle cues that guide people from curiosity to commitment.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;1. Self-identification: this is who I am.&lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;People don’t just use products; they use them to express something about themselves. Every small action, from pressing ‘yes’ to choosing a path or setting a goal, comes from a sense of self-identifying, and a quiet declaration of belonging.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;2. Goal priming: this is what I want.&lt;/strong&gt;&lt;br&gt;Good onboarding creates direction. It helps users look ahead and imagine who they’ll become by engaging, making progress feel personal rather than transactional.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;3. Effort justification: I’ve already started, I can’t stop now.&lt;/strong&gt;&lt;br&gt;Each tap or choice builds invisible momentum. The more people invest, the more they value the journey itself. Curiosity turns into ownership.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;4. Consistency bias: I want to follow through.&lt;/strong&gt;&lt;br&gt;As Robert Cialdini explains in &lt;em&gt;Influence&lt;/em&gt;, once people take a stand, they feel an inner pull to stay true to it. A single decision can quietly evolve into a pattern of loyalty.&lt;/p&gt;



&lt;p&gt;Beneath all of this lies a deeper mechanism called the &lt;strong&gt;self-perception theory.&lt;/strong&gt; Psychologist Daryl Bem proposed that people infer who they are by observing what they do. Behaviour comes first, then identity follows.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;866&quot; height=&quot;1000&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-13.png&quot; alt=&quot;&quot; class=&quot;wp-image-48148&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-13.png 866w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-13-260x300.png 260w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-13-768x887.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-13-43x50.png 43w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-13-35x40.png 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-13-402x464.png 402w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-13-696x804.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-13-485x560.png 485w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-13-256x296.png 256w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-13-409x472.png 409w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-13-69x80.png 69w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-13-42x48.png 42w&quot; sizes=&quot;auto, (max-width: 866px) 100vw, 866px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;An illustration of the loop connecting your thoughts, emotions, and actions (Source: &lt;a href=&quot;http://becomingbetter.org&quot;&gt;becomingbetter.org&lt;/a&gt;)&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;When someone taps ‘I’m committed’, they’re not just acknowledging intent but rewriting their self-story: I’m the kind of person who follows through.&lt;/p&gt;



&lt;p&gt;That’s why the sustainability app’s simple button worked and why Flo’s ‘I’m ready’ screen converts at scale. Both turn small actions into identity shifts. No one thinks, ‘I’m forming a contract with myself’&lt;em&gt;,&lt;/em&gt; but that’s exactly what happens. It’s the same instinct that drives New Year’s resolutions, gym sign-ups, or finishing a half-read book: once we start, we want to follow through.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;The best onboarding teams understand this and design moments that make users &lt;em&gt;choose&lt;/em&gt; commitment, without feeling pushed into it.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-when-the-funnel-leak-is-at-the-start&quot;&gt;&lt;strong&gt;When the funnel leak is at the start&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;For every app that masters the first two minutes, countless others never get around to fixing them. Not because they don’t see the leak, but because they underestimate where, and what, is dripping away.&lt;/p&gt;



&lt;p&gt;I’ve seen this pattern again and again… brilliant products, talented teams, the right mission, all pointing in the right direction. And yet the growth never comes.&lt;/p&gt;



&lt;p&gt;Earlier this year, we worked with one of those teams. We loved their product. We believed in their vision. We did what any disciplined growth partner would do: tightened targeting, ran creative tests, and found new efficiencies. We cut CPIs by over 80%. It’s the kind of result that usually unlocks the next phase of scale.&lt;/p&gt;



&lt;p&gt;But it didn’t.&lt;/p&gt;



&lt;p&gt;Because the app simply wouldn’t convert.&lt;/p&gt;



&lt;p&gt;A year earlier, we’d already run an audit of their onboarding flow. We’d identified friction, mapped better sequencing, and outlined the fixes. The playbook was sitting there, ready. But new features, deadlines, competing priorities took over, and the everyday gravity that pulls teams toward what’s visible instead of what’s vital took hold.&lt;/p&gt;



&lt;p&gt;In the end, all that cheaper traffic just flowed in instead — and flowed straight back out.&lt;/p&gt;



&lt;p&gt;Better targeting couldn’t fix it. Better creatives couldn’t fix it. Better acquisition efficiency couldn’t fix it.&lt;/p&gt;



&lt;p&gt;When the pipe leaks at the source, no amount of volume or pressure will ever fill the system. It will only waste more water. This is why app teams &lt;em&gt;must &lt;/em&gt;fix their funnel and start from the first user moment then work forward.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;why-teams-still-ignore-the-obvious&quot;&gt;&lt;strong&gt;Why teams still ignore the obvious&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Stories like that stay with you. Once you’ve seen a great product leak at the start, you start spotting the same pattern everywhere.&lt;/p&gt;



&lt;p&gt;From the outside, it’s baffling. You can literally see the cliff on the chart — the sharp drop-off right after signup. You can run the math and know exactly what a five-point lift in activation would mean for revenue, retention, even runway.&lt;/p&gt;



&lt;p&gt;And still, most teams don’t move.&lt;/p&gt;



&lt;p&gt;It’s not that they don’t care. It’s that the system rewards the wrong kind of motion.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Firstly, retention has better PR. &lt;/strong&gt;It sounds noble; loyalty, community, long-term love. It photographs well in strategy decks.&lt;/p&gt;



&lt;p&gt;Activation, on the other hand, doesn’t have the same reputation. The industry has turned it into a greedy checklist of forms, buttons, and paywalls. It’s seen as a process to complete rather than a moment to inspire.&lt;/p&gt;



&lt;p&gt;So the story that sounds inspiring gets funded, while the one that could actually change an app’s fate gets ignored.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Then comes the &lt;em&gt;aha! &lt;/em&gt;myth. &lt;/strong&gt;I’m not saying this doesn’t exist at all in some form, but the way we think about &lt;em&gt;aha! moments &lt;/em&gt;isn’t accurate. It’s an illusion: the idea that users will fall in love once they’ve seen enough. This magic moment doesn’t happen, because most never make it that far.&lt;/p&gt;



&lt;p&gt;As &lt;a href=&quot;https://youtu.be/qp0HIF3SfI4?t=128&quot;&gt;Simon Sinek reminds us&lt;/a&gt;: people don’t buy what you do; they buy why you do it.&lt;em&gt; &lt;/em&gt;That’s the core truth behind activation. You don’t sell the proof; you sell the promise. You don’t sell products; you sell stories. And if the story fails to land early, the proof never gets its chance.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;And finally, bias builds that sends app teams the wrong signals.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Shipping something new feels like momentum. It wins applause. Iterating on something old feels like housekeeping. It doesn’t make headlines, even when it moves the needle more than a new feature ever will.&lt;/p&gt;



&lt;p&gt;But every single customer you’ve ever won (and every one you’ve lost) has passed through that same onboarding flow.&lt;/p&gt;



&lt;p&gt;So why wouldn’t you perfect the one experience &lt;em&gt;everyone&lt;/em&gt; shares?&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;the-revenue-math-most-teams-never-do&quot;&gt;&lt;strong&gt;The revenue math most teams never do&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Let’s make it tangible.&lt;/p&gt;



&lt;p&gt;Say you bring in 100,000 installs each month. Around 10% of them start a trial. Of those, about 25% convert to paying users. That gives you roughly 2,500 paying users.&lt;/p&gt;



&lt;p&gt;Now increase trial starts by just five points, from 10 to 15%. That small list adds 5,000 more trials. At the same 25% conversion rate, that’s 1,250 additional paying users — without increasing ad spend or changing the app itself.&lt;/p&gt;



&lt;p&gt;This is the math most teams never do: the quiet compounding effect of &lt;strong&gt;fixing the front door instead of buying more visitors to walk through it.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;On paper, everyone agrees this early conversion matters, but in practice, no one truly owns it. Product teams see it as a marketing problem. Marketing teams assume it’s a product issue. UX calls it ‘flow’ and moves on to the next sprint.&lt;/p&gt;



&lt;p&gt;And while the org chart debates semantics, revenue quietly leaks away through the very first experience every customer has.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;what-great-onboarding-actually-does&quot;&gt;&lt;strong&gt;What great onboarding &lt;/strong&gt;&lt;strong&gt;&lt;em&gt;actually &lt;/em&gt;&lt;/strong&gt;&lt;strong&gt;does&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Once you’ve seen how much growth quietly leaks through the first two minutes, one question inevitably follows: what does great onboarding do that the rest doesn’t?&lt;/p&gt;



&lt;p&gt;For a talk I gave last year, I asked ChatGPT a simple question: &lt;strong&gt;What makes a great first date?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;It answered:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Clear communication:&lt;/strong&gt; be open about intentions&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Learn about each other:&lt;/strong&gt; share, ask, listen&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Tailor the experience:&lt;/strong&gt; make it feel personal&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Create reliability: &lt;/strong&gt;be honest and consistent&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Keep it interesting:&lt;/strong&gt; maintain spark and momentum&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;It was, surprisingly, a perfect description of great onboarding.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;573&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/ChatGPT-first-date-advice-1024x573.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-48166&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/ChatGPT-first-date-advice-1024x573.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/ChatGPT-first-date-advice-300x168.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/ChatGPT-first-date-advice-768x430.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/ChatGPT-first-date-advice-1536x859.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/ChatGPT-first-date-advice-50x28.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/ChatGPT-first-date-advice-72x40.jpg 72w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/ChatGPT-first-date-advice-696x389.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/ChatGPT-first-date-advice-560x313.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/ChatGPT-first-date-advice-529x296.jpg 529w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/ChatGPT-first-date-advice-840x470.jpg 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/ChatGPT-first-date-advice-80x45.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/ChatGPT-first-date-advice-48x27.jpg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/ChatGPT-first-date-advice.jpg 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The best onboarding flows don’t just explain features. Instead, they &lt;strong&gt;sell the future while building trust in the present&lt;/strong&gt;. They distil the entire value proposition into a few moments that feel natural and earned.&lt;/p&gt;



&lt;p&gt;Like a great first date, you’re not listing achievements but sharing a laugh, a small truth, a hint of what’s ahead. When it works, it feels effortless: the conversation flows, trust builds, and commitment starts to feel inevitable.&lt;/p&gt;



&lt;p&gt;Did you catch it? There it is again — the same pattern of voluntary commitment I mentioned earlier, playing out once more.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;The same quiet force behind Flo’s ‘I’m ready’ screen also drives &lt;a href=&quot;https://quittrapp.com&quot;&gt;QUITTR&lt;/a&gt;, a habit-breaking app created by Alex Slater, who scaled it to over $3m ARR within its first year.&lt;/p&gt;



&lt;p&gt;That’s the genius of great onboarding. It doesn’t push people to commit, but makes them &lt;em&gt;want &lt;/em&gt;to commit. Instead of overwhelming users with information, it sets the emotional tone, building a sense of safety and excitement that pulls them in naturally.&lt;/p&gt;



&lt;p&gt;Apps like Flo, Duolingo, Headway, and Calm all understand this rhythm:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Flo makes you feel understood&lt;/li&gt;



&lt;li&gt;Duolingo makes you laugh&lt;/li&gt;



&lt;li&gt;Headway makes you feel productive&lt;/li&gt;



&lt;li&gt;Calm makes you exhale&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Each of them builds what’s called &lt;a href=&quot;https://www.forbes.com/sites/renaegregoire/2025/04/17/anticipatory-selling-how-to-shape-buyer-perceptions-and-create-demand/&quot;&gt;anticipatory trust &lt;/a&gt;— the feeling that this product really understands you. And that feeling, more than any feature or design trick, is what makes people pay and stay.&lt;/p&gt;



&lt;p&gt;When I spoke with Alex Slater about QUITTR’s growth, he explained the same principle from another angle:&lt;/p&gt;



&lt;p&gt;“The longer users spend during onboarding,” he said, “the higher the likelihood they are to convert. People want something back for the time they invest. It’s like the gamblers’ philosophy. They want a return for the time they spent losing.”&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;438&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-16-1024x438.png&quot; alt=&quot;&quot; class=&quot;wp-image-48156&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-16-1024x438.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-16-300x128.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-16-768x328.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-16-1536x657.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-16-50x21.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-16-94x40.png 94w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-16-696x298.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-16-560x239.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-16-840x359.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-16-80x34.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-16-48x21.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-16.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;QUITTR’s onboarding screen examples&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;That insight shaped some of QUITTR’s best-performing flows. Rather than focusing on features, they invited users to see onboarding as an investment in themselves. One screen even asked people to sign their name as a personal promise — a simple gesture that taps into our instinct to stay true to what we’ve already chosen.&lt;/p&gt;



&lt;p&gt;Every great product I’ve studied strikes the same balance: expectation, emotion, trust, a bit of friction, and momentum. When one is missing, the experience breaks. When they align, the first two minutes build belief.&lt;/p&gt;



&lt;p&gt;Great teams&lt;strong&gt; treat onboarding as an ongoing habit rather than a finished project&lt;/strong&gt;. They keep it on the roadmap, continuously testing sharper messages, subtle variations, and stronger emotional cues.&lt;/p&gt;



&lt;p&gt;They know every user passes through this flow, making it the most powerful place to improve. When onboarding becomes a living system instead of a one-time launch, conversion grows and learning compounds.&lt;/p&gt;



&lt;p&gt;That’s what separates an app that’s merely tested from one that’s truly trusted. Great onboarding defines the relationship with the user and keeps it growing.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;what-great-onboarding-doesnt-do-4-mistakes-to-watch-for&quot;&gt;&lt;strong&gt;What great onboarding &lt;/strong&gt;&lt;strong&gt;&lt;em&gt;doesn’t&lt;/em&gt;&lt;/strong&gt;&lt;strong&gt; do&lt;/strong&gt;&lt;strong&gt;: 4 mistakes to watch for&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;When onboarding falls flat, it’s rarely from neglect. More often, teams try too hard in the wrong places and lose commitment little by little.&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Burying the paywall:&lt;/strong&gt; Hiding your core value behind too many steps drains energy. If users have to search for what matters, momentum is already gone&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Information overload:&lt;/strong&gt; Too often, teams rush to show features when users are really searching for outcomes. They fall in love with what it does for them, not with what a product does&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Overuse of brand language: &lt;/strong&gt;Teams sometimes rely too heavily on branded terms or feature names that mean little to new users. What feels distinctive internally can rather sound confusing or hollow to someone encountering the app for the first time.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Skipping the emotion:&lt;/strong&gt; Onboarding is a pitch. It should stir a sense of urgency, aspiration, or even the faint fear of missing out. Without that spark, it’s just another set of screens to swipe through.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Earlier this year, Aperture partnered with &lt;a href=&quot;https://www.mob.co.uk/premium/app&quot;&gt;&lt;strong&gt;Mob&lt;/strong&gt;&lt;/a&gt;, the UK App Store’s leading Food &amp;amp; Drink app, on a series of creatives, ads, and onboarding projects that all shared the same goal: making every interaction feel personal and human.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;438&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Mob-onboarding-1024x438.png&quot; alt=&quot;&quot; class=&quot;wp-image-48160&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Mob-onboarding-1024x438.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Mob-onboarding-300x128.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Mob-onboarding-768x328.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Mob-onboarding-1536x657.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Mob-onboarding-50x21.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Mob-onboarding-94x40.png 94w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Mob-onboarding-696x298.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Mob-onboarding-560x239.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Mob-onboarding-840x359.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Mob-onboarding-80x34.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Mob-onboarding-48x21.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Mob-onboarding.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;Some of Mob’s onboarding screens&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;Rather than overwhelming new users with features, the onboarding was redesigned to show &lt;em&gt;why&lt;/em&gt; Mob matters before showing &lt;em&gt;what&lt;/em&gt; it does. A series of questions was introduced, turning onboarding into a dialogue to get to know the users. This meant that by the time users reached the paywall, they already felt a connection.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;798&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-15-798x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-48154&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-15-798x1024.png 798w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-15-234x300.png 234w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-15-768x985.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-15-1197x1536.png 1197w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-15-39x50.png 39w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-15-31x40.png 31w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-15-362x464.png 362w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-15-696x893.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-15-436x560.png 436w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-15-231x296.png 231w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-15-368x472.png 368w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-15-62x80.png 62w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-15-37x48.png 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-15.png 1247w&quot; sizes=&quot;auto, (max-width: 798px) 100vw, 798px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;Mob ranked #1 in the UK food &amp;amp; Drink Category (August 2025)&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;The results spoke for themselves: Mob became the #1 Food &amp;amp; Drink app in the UK, reached #3 overall in Australia, and saw trial opt-ins surge.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-want-to-start-fixing-your-funnel-start-here&quot;&gt;&lt;strong&gt;Want to start fixing your funnel? Start here&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;If you only do three things, start here:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Audit your onboarding flow: &lt;/strong&gt;Look at it with fresh eyes. Better yet, watch new users go through it in real time. Notice where they hesitate, where they drop off, and where they light up. The answers are usually right in front of you.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Test one change a month: &lt;/strong&gt;It doesn’t have to be huge. Reorder the steps. Rewrite the headline on the paywall. Try adding a commitment device. One controlled improvement every month is enough to build steady momentum.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Measure aggressively: &lt;/strong&gt;Track install-to-trial and trial-to-paid rates separately, and break them down by platform. Make your success metric the number of new paying users, not just percentage lifts that look good in slides but hide real performance.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Attention is expensive. Privacy shifts, higher CPIs, ad fatigue, and shorter patience make the first two minutes the most valuable space you own. You won’t outspend a leaky entry point or out-retain a weak first impression; &lt;strong&gt;your real advantage is how well you learn from that opening moment.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Most teams overlook where that learning lives: the small window between install and intent.&lt;/p&gt;



&lt;p&gt;When I think back to those 2018 spreadsheets, I remember what they taught me — a great onboarding isn’t a trick or a tactic; it’s seeing what actually moves people forward.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;We can ship all the features we want, but if most users never reach them, those features never do their job. The fastest progress comes from making the first two minutes impossible to abandon.&lt;/p&gt;



&lt;p&gt;Fix the front door, and everything else you build finally starts to matter.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Apple’s App Store Mini Apps Partner Program: what app teams need to know]]></title><description><![CDATA[Apple introduces a 15% IAP rate for apps that host third-party mini apps, with strict rules and new APIs attached.]]></description><link>https://www.revenuecat.com/blog/engineering/apple-mini-apps-partner-program/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/apple-mini-apps-partner-program/</guid><pubDate>Mon, 17 Nov 2025 11:17:27 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Mini-Apps-program.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Apple doesn’t drop many surprises these days, but this one genuinely caught us off guard. With the new Mini Apps Partner Program, &lt;a href=&quot;https://developer.apple.com/news/?id=xcz1s7cz&quot;&gt;Apple is officially opening&lt;/a&gt; the door for apps that host third-party mini apps to access a reduced 15% fee on qualifying in-app purchases.&lt;/p&gt;



&lt;p&gt;It’s a niche change, but an important one. If you’re building anything that resembles a platform, marketplace, or ecosystem, this is Apple giving you a clearer rulebook — and a financial incentive — to do it on their terms.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-apple-means-by-a-mini-app&quot;&gt;What Apple means by a “mini app”&lt;/h2&gt;



&lt;p&gt;Apple defines a mini app as a self-contained HTML5/JavaScript experience that’s downloaded after install and runs inside a native host app. The key requirement: it must be developed by a separate third party, not a feature your team built and wrapped in a webview.&lt;/p&gt;



&lt;p&gt;That definition narrows the field dramatically. Apple isn’t trying to reclassify everyday app features. They’re targeting the types of HTML-based micro experiences popularized in ecosystems like WeChat and Alipay.&lt;/p&gt;



&lt;p&gt;For those products, Apple is now offering a structured, compliant way to operate on iOS.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-15-headline-when-it-applies&quot;&gt;The 15% headline: when it applies&lt;/h2&gt;



&lt;p&gt;If your app qualifies and you implement the required APIs, you keep &lt;strong&gt;85%&lt;/strong&gt; of eligible purchases made inside a mini app, including:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;consumables&lt;/li&gt;



&lt;li&gt;non-consumables&lt;/li&gt;



&lt;li&gt;auto-renewing subscriptions&lt;/li&gt;



&lt;li&gt;non-renewing subscriptions&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;But purchases must:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;occur inside a qualifying mini app, and&lt;/li&gt;



&lt;li&gt;use the &lt;a href=&quot;https://www.revenuecat.com/blog/growth/what-you-need-to-know-apples-advanced-commerce-api/&quot;&gt;Advanced Commerce API&lt;/a&gt; — Apple does not allow classic App Store Connect products for these flows.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;There are guardrails too. For example, consumables must be scoped to the mini app that sold them, not shared across multiple experiences.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-joining-the-program-requires&quot;&gt;What joining the program requires&lt;/h2&gt;



&lt;p&gt;Apple ties the lower fee to a set of newer App Store technologies. To participate, host apps must support:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Advanced Commerce API&lt;/strong&gt; for configuring products and handling purchases&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Declared Age Range API&lt;/strong&gt; to ensure content is served appropriately&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;StoreKit IAP&lt;/strong&gt; as the payment system&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Refund consumption reporting&lt;/strong&gt; via the App Store Server API&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Mini-app manifests&lt;/strong&gt; with detailed metadata for each hosted mini app&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;This is Apple formalizing a model that previously sat in a grey zone. Now there are rules, APIs, and predictable review expectations, but with more work required from the host.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-platform-style-apps-should-pay-attention&quot;&gt;Why platform-style apps should pay attention&lt;/h2&gt;



&lt;p&gt;If your product already resembles a platform, this update is meaningful.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-mini-apps-become-first-class-economic-units&quot;&gt;Mini apps become first-class economic units&lt;/h3&gt;



&lt;p&gt;Each mini app has its own SKUs, entitlements, and refund logic. This lets platforms handle commerce cleanly without forcing everything through a single global product catalog.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-better-economics&quot;&gt;Better economics&lt;/h3&gt;



&lt;p&gt;A 15% fee makes the model more attractive for hosts and for third-party developers building mini experiences inside your app.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-clearer-compliance&quot;&gt;Clearer compliance&lt;/h3&gt;



&lt;p&gt;&lt;a href=&quot;https://developer.apple.com/app-store/review/guidelines/#third-party-software&quot;&gt;Guideline 4.7&lt;/a&gt; has been shaping this space for years. The Mini Apps Partner Program adds structure and removes some of the ambiguity around what Apple allows.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-if-you-re-not-a-platform-this-likely-isn-t-for-you&quot;&gt;If you’re not a platform, this likely isn’t for you&lt;/h2&gt;



&lt;p&gt;If your app doesn’t host external developers, creators, or partners — and you don’t plan to — this program won’t affect your roadmap. Apple isn’t creating a shortcut to lower fees; it’s creating a compliant framework for a specific app pattern.&lt;/p&gt;



&lt;p&gt;That said, it’s still worth watching. Apple is making space for “apps inside apps” in a more formal way, and that has long-term implications for how mobile software might evolve.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-early-signals-from-the-announcement&quot;&gt;Early signals from the announcement&lt;/h2&gt;



&lt;p&gt;A few themes stood out as we dug into the details:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Apple is cleaning up a longstanding grey zone.&lt;/strong&gt; Mini-app ecosystems have been allowed but messy. This adds rules, structure, and expectations.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;This aligns with global super-app patterns.&lt;/strong&gt; Markets with strong mini-app cultures now have a clearer path on iOS.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Advanced Commerce API is now central.&lt;/strong&gt; The lower fee is directly tied to adopting Apple’s modern commerce stack — a sign of where future features may go.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;This could open the door for JS-based app-building tools.&lt;/strong&gt; There’s early interest from “vibecoding” platforms: the tools that let users or creators build lightweight, JS-powered mini experiences inside a host app. If they can align with Apple’s definition of a mini app (third-party, HTML/JS, downloaded after install), this program could become a natural fit for their emerging marketplace models.&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-to-decide-if-this-matters-for-your-team&quot;&gt;How to decide if this matters for your team&lt;/h2&gt;



&lt;p&gt;A simple litmus test:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Do you host (or want to host) third-party micro-apps or tools?&lt;/li&gt;



&lt;li&gt;Are those experiences built with HTML5/JS, or could they be?&lt;/li&gt;



&lt;li&gt;Does your product strategy lean toward a platform or marketplace model?&lt;/li&gt;



&lt;li&gt;Are you prepared to integrate Advanced Commerce, Declared Age Range, and structured mini-app metadata?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;If the answer isn’t a confident “yes,” you can safely treat this as strategic context rather than something you need to act on.&lt;/p&gt;



&lt;p&gt;But if you are building toward a platform, this is one of the clearest signals Apple has ever sent — lower fees, more structure, and a defined path to hosting mini apps at scale.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Flex + RevenueCat: Accept HSA/FSA payments for in-app subscriptions]]></title><description><![CDATA[Health and wellness apps can now accept pre-tax payments directly in-app — powered by Flex, managed through RevenueCat.]]></description><link>https://www.revenuecat.com/blog/company/flex-integration-announcement/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/company/flex-integration-announcement/</guid><pubDate>Fri, 14 Nov 2025 10:03:12 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/flex-intgeration-cover.jpg" length="0" type="image/*"/><content:encoded>&lt;p&gt;We’re excited to announce a new integration with &lt;strong&gt;&lt;a href=&quot;https://www.withflex.com/&quot;&gt;Flex&lt;/a&gt;&lt;/strong&gt;, enabling developers to accept HSA (health spending account) and FSA (flexible spending account) payments for in-app subscriptions for the very first time.&lt;/p&gt;



&lt;p&gt;This update lets health and wellness apps offer compliant, tax-advantaged payment options, managed through RevenueCat and powered by Flex’s HSA/FSA technology.&lt;/p&gt;



&lt;p&gt;Together, we’re unlocking a new, compliant revenue stream for developers and a smoother checkout experience for users eager to use their pre-tax dollars on eligible digital health products.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-4-3 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;Flex + RevenueCat Integration&quot; width=&quot;500&quot; height=&quot;375&quot; src=&quot;https://www.youtube.com/embed/SD5QBFrlHuE?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-this-matters&quot;&gt;Why this matters&lt;/h2&gt;



&lt;p&gt;Until recently, Apple’s in-app purchase (IAP) requirements limited developers to billing systems that didn’t support HSA or FSA cards.&lt;/p&gt;



&lt;p&gt;For digital health apps, that created friction on both sides:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Users couldn’t apply their pre-tax benefits to eligible subscriptions.&lt;/li&gt;



&lt;li&gt;Developers lost conversions or forced users into manual reimbursement flows.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Now, with Apple supporting external billing in the US, developers using RevenueCat + Flex can securely accept HSA/FSA payments while maintaining all the benefits of RevenueCat’s cross-platform subscription management, analytics, and entitlements.&lt;/p&gt;



&lt;p&gt;The result: more compliant payment flexibility, better user experience, and higher conversion from a previously untapped payment channel.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-it-works&quot;&gt;How it works&lt;/h2&gt;



&lt;p&gt;The integration connects Flex’s HSA/FSA payment processing with RevenueCat’s subscription infrastructure.&lt;/p&gt;



&lt;p&gt;Developers can activate it in just two steps inside the RevenueCat dashboard — no major engineering lift required.&lt;/p&gt;



&lt;p&gt;Once enabled:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Flex&lt;/strong&gt; ensures every transaction meets IRS and plan requirements.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;RevenueCat&lt;/strong&gt; handles subscription renewals, trials, analytics, and entitlements across all platforms.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;That means developers can launch new payment options fast — while keeping everything in sync with their existing billing systems (like Stripe or IAP).&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-developers-are-seeing&quot;&gt;What developers are seeing&lt;/h2&gt;



&lt;p&gt;Early adopters like &lt;strong&gt;Ladder&lt;/strong&gt;, the strength training app, have already seen measurable impact:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“The Flex integration through RevenueCat made it simple for Ladder to offer subscriptions via HSA and FSA cards — a major unlock for our users and an effective new growth lever.&lt;/p&gt;



&lt;p&gt;We launched an email campaign educating potential customers about HSA/FSA eligibility using Flex’s marketing guide, and within a few weeks saw over 500 annual subscribers check out using their benefits.&lt;/p&gt;



&lt;p&gt;From a technical standpoint, Flex’s seamless, native integration with RevenueCat functions just like our Stripe and IAP integrations — keeping our data and entitlements consistent while enabling a smooth experience across all of our purchase channels.” — &lt;strong&gt;Ryan Mott, VP of Data Product at Ladder&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;For developers, this opens access to &lt;strong&gt;over $100 billion in annual U.S. HSA/FSA spending&lt;/strong&gt; — and makes it possible to capture that demand directly from their apps.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-available-now&quot;&gt;Available now&lt;/h2&gt;



&lt;p&gt;The &lt;strong&gt;Flex + RevenueCat&lt;/strong&gt; integration is available today for all Flex and RevenueCat customers.&lt;/p&gt;



&lt;p&gt;👉 &lt;a href=&quot;https://docs.withflex.com/developer-guides/integration/revenuecat&quot;&gt;Get started here&lt;/a&gt; and start accepting HSA/FSA payments in-app in minutes.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[A guide to lifetime subscriptions: are they right for your app?]]></title><description><![CDATA[How to decide if a lifetime offer is right for your app]]></description><link>https://www.revenuecat.com/blog/growth/lifetime-subscriptions/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/lifetime-subscriptions/</guid><pubDate>Wed, 12 Nov 2025 14:56:31 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Ultimate-guide-to-lifetime-subscriptions-1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;I bought a lifetime of Calm.&lt;/p&gt;



&lt;p&gt;The app, not the feeling, although I’d definitely pay a lot for actual calmness in my life.&lt;/p&gt;



&lt;p&gt;After a few years of bouncing between Calm and Headspace, meditating off and on, I saw an offer that felt impossible to refuse: lifelong access to Calm. No monthly payments, no annual renewal, just one payment, &lt;em&gt;forever&lt;/em&gt;.&lt;/p&gt;



&lt;p&gt;It sounded perfect. Wouldn’t I meditate more if I knew I’d already invested? Wouldn’t it feel amazing to never have to think about my subscription again? One less thing on the mental load. So, after some deliberation, I did it. My first-ever lifetime subscription. My second one came earlier this year when I married my now-husband.&lt;/p&gt;



&lt;p&gt;Years later, Calm is still on my phone. Still updated, still upgraded, still going strong. But that raises a bigger question: if a giant like Calm is offering lifetime subscriptions at scale… should your app?&lt;/p&gt;



&lt;p&gt;Like with my other deep dives into subscription models (from the &lt;a href=&quot;https://www.revenuecat.com/blog/growth/annual-subscriptions-apps-pros-cons/&quot;&gt;pros and cons of annual subscriptions&lt;/a&gt; to whether &lt;a href=&quot;https://www.revenuecat.com/blog/growth/weekly-subscriptions/&quot;&gt;weekly subscriptions make sense&lt;/a&gt;), you’ll know it’s never as simple as yes or no“yes, do it” or “no, don’t touch it.” There are advantages and disadvantages for both your customer and your brand. And it doesn’t suit every industry.&lt;/p&gt;



&lt;p&gt;So today, we’re diving into lifetime subscriptions. We’ll consider:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;How common lifetime offers actually are across industries&lt;/li&gt;



&lt;li&gt;The benefits (and risks) for both your customers and your business&lt;/li&gt;



&lt;li&gt;Who should consider lifetime subscriptions, and who shouldn’t&lt;/li&gt;



&lt;li&gt;How to structure a lifetime offer for success&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;While you’re probably reading this from a business perspective, I always start with the customers, too. You need to understand their perception and hesitation if you want to test lifetime subscriptions. A lifetime subscription almost always favors either the customer or the brand — rarely both. I can feel like I got an unbeatable deal with Calm, or Calm can feel like they maximized my value. But not both at the same time.&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-1v2D5H wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Quick note&quot; text=&quot;&lt;p&gt;When I refer to lifetime subscriptions here, I mean the one-time, non-consumable in-app purchase that grants ongoing access, not an actual App Store subscription.&lt;/p&gt;&quot; icon=&quot;bulb&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;p&gt;Are many apps really offering lifetime subscriptions?&amp;nbsp;&lt;/p&gt;



&lt;p&gt;I turn to my trusty data source, my favorite nerdy nighttime read: the &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps-2025/&quot;&gt;&lt;em&gt;State of Subscription Apps 2025 Report&lt;/em&gt;&lt;/a&gt;. (Yes, all 262 pages of it, and yes, it delivers every time.)&amp;nbsp;&lt;/p&gt;



&lt;p&gt;For most app categories, offering a combination of subscription and lifetime subscription is the second most popular form of monetization. On top of that, a small share of apps also layer in consumables:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;526&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-6-1024x526.png&quot; alt=&quot;&quot; class=&quot;wp-image-48099&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-6-1024x526.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-6-300x154.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-6-768x395.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-6-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-6-78x40.png 78w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-6-696x358.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-6-560x288.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-6-840x432.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-6-80x41.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-6-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-6.png 1304w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Where are lifetime subscriptions most common? &lt;strong&gt;Photo &amp;amp; Video apps lead the way&lt;/strong&gt;, where the model is often framed less as ‘forever access’ and more as a one-off upgrade. They’re also popular in &lt;strong&gt;Education&lt;/strong&gt; and &lt;strong&gt;Travel&lt;/strong&gt;, where users see clear long-term value.&lt;/p&gt;



&lt;p&gt;For most other categories, adoption hovers around &lt;strong&gt;18–24% of apps&lt;/strong&gt; offering both subscription and lifetime options, with consumables sprinkled in.&lt;/p&gt;



&lt;p&gt;The big outlier? &lt;strong&gt;Business apps.&lt;/strong&gt; Here, lifetime access makes far less sense — ongoing per-user costs are high, and products evolve too quickly. Especially in the B2B space, lifetime subscriptions rarely align with reality.&lt;/p&gt;



&lt;h1 class=&quot;wp-block-heading&quot; id=&quot;h-the-benefits-of-lifetime-subscriptions&quot;&gt;The benefits of lifetime subscriptions&lt;/h1&gt;



&lt;p&gt;So why would you consider moving from a monthly or annual subscription model to lifetime one-off? Let’s look at both sides.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-from-the-customer-side&quot;&gt;From the customer side&lt;/h2&gt;



&lt;p&gt;People are tired of subscriptions. Everything from TV to toothbrushes now wants a monthly fee. It’s hard to keep track of them, and everything feels like a subscription these days. Heck, there are literally apps to track your subscription apps. If that’s not subscription fatigue, I don’t know what is.&lt;/p&gt;



&lt;p&gt;That’s where lifetime subscriptions come in. They’re appealing:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;No more subscription creep:&lt;/strong&gt; instead of adding one more bill to the pile, users can pay once and forget about it&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;A way to take a bet:&lt;/strong&gt; lifetime offers let people back a new app they like, even if it’s still early — many startups price lifetime deals more attractively than their annual plan to encourage this “I’m in for the ride” mindset&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;The long-game win:&lt;/strong&gt; stick with the app beyond the breakeven point, and it feels like you’ve unlocked an amazing deal&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-from-the-brand-and-business-side&quot;&gt;From the brand and business side&lt;/h2&gt;



&lt;p&gt;There’s several main business benefits to offering lifetime subscriptions:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Upfront revenue&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Boosted retention&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Early cashflow&amp;nbsp;&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Attracting committed users&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Referral benefits&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Stand out against competitors&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Lifetime subscriptions give you at least five years’ worth of revenue upfront — sometimes more. And if a customer would have churned earlier? Even better. You’ve locked in value you might have lost down the line.&lt;/p&gt;



&lt;p&gt;Offering it early, when your app is just getting started, can also boost retention. Those initial lifetime subscribers give you more data to refine your retention strategy, while providing an early revenue boost.&lt;/p&gt;



&lt;p&gt;This upfront cash is particularly helpful for content-heavy brands. Think Calm: new meditations, celebrity narrators, music, partnerships — all require continuous investment. A surge of lifetime subscription revenue can fund growth, or even help &lt;a href=&quot;https://www.revenuecat.com/blog/growth/mobile-app-funding/&quot;&gt;bootstrapped apps expand without raising capital&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;Lifetime subscriptions can also be timed strategically, such as during specific periods where people expect an offer, like &lt;a href=&quot;https://www.revenuecat.com/webinars/holiday-discounts-and-promotions-for-your-app/&quot;&gt;holiday discounts and seasonal promotions&lt;/a&gt;. In my experience, discount-driven users tend to engage less and churn faster — and &lt;a href=&quot;https://www.digitalcommerce360.com/2024/04/17/study-black-friday-app-installs-airship/&quot;&gt;Airship’s research on Black Friday subscribers&lt;/a&gt; confirms this. But a lifetime deal lets you attract committed users while discouraging bargain hunters.&lt;/p&gt;



&lt;p&gt;There’s also a more niche benefit: referrals. Take &lt;a href=&quot;https://useorigin.com/&quot;&gt;Origin&lt;/a&gt;, a finance app, which rewards lifetime access to users who refer three friends. They cleverly frame it: “Refer two friends to cover one year of Origin, refer one more friend and earn a lifetime membership.” The offer is far more compelling than a free month or year, turning referrals into a powerful growth engine.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;451&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-10-451x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-48107&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-10-451x1024.png 451w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-10-132x300.png 132w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-10-677x1536.png 677w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-10-22x50.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-10-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-10-204x464.png 204w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-10-696x1580.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-10-247x560.png 247w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-10-130x296.png 130w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-10-208x472.png 208w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-10-35x80.png 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-10-21x48.png 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-10.png 705w&quot; sizes=&quot;auto, (max-width: 451px) 100vw, 451px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Finally, in a competitive industry, lifetime subscriptions can be a smart way to stand out against the giants, most of whom don’t offer them (Calm being the rare exception). Take &lt;a href=&quot;https://www.jumpspeak.com/&quot;&gt;Jumpspeak&lt;/a&gt;, a language app trying to compete with Duolingo: in my experience, they push lifetime subscriptions heavily to differentiate themselves and attract committed users.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;870&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-11-1024x870.png&quot; alt=&quot;&quot; class=&quot;wp-image-48109&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-11-1024x870.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-11-300x255.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-11-768x653.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-11-1536x1306.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-11-50x43.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-11-47x40.png 47w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-11-546x464.png 546w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-11-696x592.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-11-560x476.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-11-348x296.png 348w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-11-555x472.png 555w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-11-80x68.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-11-48x41.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-11.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;When I tried Jumpspeak, it wasn’t quite right for me, but I could see how someone really enjoying the app might opt for the lifetime subscription. That locks them into Jumpspeak for life (hopefully), rather than just testing it and returning to Duolingo. Compared to Calm, where the lifetime offer is roughly 5x the annual price, Jumpspeak prices it at just 3.6x annual, making it a notably aggressive strategy.&lt;/p&gt;



&lt;h1 class=&quot;wp-block-heading&quot; id=&quot;h-the-downsides-of-lifetime-subscriptions&quot;&gt;The downsides of lifetime subscriptions&lt;/h1&gt;



&lt;p&gt;Okay, now what’s the catch?&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-for-the-customer&quot;&gt;For the customer&lt;/h2&gt;



&lt;p&gt;When I bought Calm lifetime, I didn’t read the fine print as carefully as I should have (the cost was about a third of what they charge now). Some lifetime subscriptions are limited to certain features, and ‘lifetime’ usually means the lifetime of the product, aka as long as the company stays in business. That’s a gamble, especially with new apps.&lt;/p&gt;



&lt;p&gt;If you buy a lifetime from a small startup and they fold a year later, your ‘lifetime’ ends far sooner than expected. With Calm, I didn’t worry as they were already established, but with a newer app like Jumpspeak, which I hadn’t tested extensively, I was more hesitant. Was it worth it?&lt;/p&gt;



&lt;p&gt;Another consideration: trials are harder to offer. Since lifetime subscriptions aren’t technically subscriptions under App Store rules, you can’t provide an app trial. This might force users to pay for a few months or a year first before upgrading to lifetime, which can limit adoption.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-for-the-brand-and-business&quot;&gt;For the brand and business&lt;/h2&gt;



&lt;p&gt;Here’s where it gets tricky. Lifetime subscriptions are often priced at 5–12x the annual subscription, designed to sit just above your expected &lt;a href=&quot;https://www.revenuecat.com/glossary/#lifetime-value-ltv&quot;&gt;lifetime value (LTV)&lt;/a&gt;. But averages can be misleading, and lifetime subscriptions don’t take into account price increases.&lt;/p&gt;



&lt;p&gt;Take me, for example: I’d already been subscribing to Calm for a few years and likely would have continued for many more. In that case, they probably earned less from me by offering lifetime access. That’s why pricing lifetime subscriptions is always a bit of a tug-of-war.&lt;/p&gt;



&lt;p&gt;For reference, I got my Calm lifetime subscription for £119.99.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;960&quot; height=&quot;850&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-7.png&quot; alt=&quot;&quot; class=&quot;wp-image-48101&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-7.png 960w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-7-300x266.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-7-768x680.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-7-50x44.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-7-45x40.png 45w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-7-524x464.png 524w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-7-696x616.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-7-560x496.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-7-334x296.png 334w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-7-533x472.png 533w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-7-80x71.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-7-48x43.png 48w&quot; sizes=&quot;auto, (max-width: 960px) 100vw, 960px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Back then, Calm was much cheaper — my faulty memory says around $29.99 per year — but now they charge $399 for a lifetime subscription (and $79.99 for an annual subscription). So they could have made significantly more from me as a recurring annual subscriber, especially after the price increase.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;You can’t predict inflation, market changes and competitor pricing shifts, or future features which hike up the cost of running the app (e.g. &lt;a href=&quot;http://revenuecat.com/blog/growth/ai-subscription-app-pricing/&quot;&gt;AI features&lt;/a&gt;). Meaning your lifetime subscription cost could go from being a safe financial bet one year, to significantly undervaluing your app a couple of years later.&lt;/p&gt;



&lt;p&gt;Another downside: upsells.&lt;strong&gt; It’s much harder to upsell someone who’s already on lifetime. &lt;/strong&gt;Sure, you can highlight new premium tiers that aren’t included, but it’s messy. Moving a customer from lifetime to a subscription later is basically impossible. If tier upgrades are central to your monetization strategy, lifetime subscriptions may not be the right fit.&lt;/p&gt;



&lt;p&gt;There’s also the mechanics to consider. Switching from a subscription to a lifetime plan usually requires customers to cancel their existing subscription manually before purchasing the lifetime plan. This can be confusing, sometimes leading to accidental double payments, refund requests, support headaches, and unhappy loyal customers.&lt;/p&gt;



&lt;p&gt;There’s also the aforementioned important technical detail: in the app stores, lifetime isn’t technically a subscription. It’s classified as &lt;strong&gt;a non-consumable in-app purchase&lt;/strong&gt;, which comes with a few implications:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;No subscription features:&lt;/strong&gt; you can’t offer free trials or the usual subscription upgrade paths.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Manual migration required:&lt;/strong&gt; customers can’t simply tap ‘upgrade’ from monthly to lifetime, they must cancel first then repurchase. Some apps handle this for the user, others explain it clearly. Miscommunication here is often what leads to double charges, refunds, and support challenges.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;There are also future product headaches to consider. Pushing lifetime subscribers to a new premium version can require maintaining an extra product version, and makes it hard to get them to pay again. &lt;a href=&quot;https://subclub.com/episode/how-to-not-screw-up-switching-your-app-to-subscriptions-matt-ronge-astropad&quot;&gt;Matt Ronge, CEO of Astropad, learned this the hard way&lt;/a&gt;: ongoing costs were high, making it difficult to support lifetime users while building new features.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;He shared on Sub Club that if he could go back, he’d have been even more generous to early customers. His advice: don’t rely on the stick; build something so good that customers want to upgrade voluntarily.&lt;/p&gt;



&lt;p&gt;From an investor perspective, lifetime revenue is a one-off hit, whereas subscriptions are predictable and recurring. Predictable revenue compounds over time and increases company valuation. Leaning too heavily on lifetime offers can drag down valuation, which is why you rarely see lifetime subscriptions in B2B SaaS, where running costs are high and recurring revenue multipliers drive growth.&lt;/p&gt;



&lt;h1 class=&quot;wp-block-heading&quot; id=&quot;h-lifetime-subscriptions-at-a-glance&quot;&gt;Lifetime subscriptions at a glance&lt;/h1&gt;



&lt;p&gt;We’ve covered a lot, so before diving deeper, let’s summarize the key benefits and downsides of lifetime subscriptions:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-lifetime-subscriptions-at-a-glance-0&quot;&gt;&lt;strong&gt;Lifetime subscriptions at a glance&lt;/strong&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Perspective&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Benefits&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Downsides&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Customer&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;No ongoing subscription fatigueOne-and-done paymentCan back a new app earlyA great deal if used long-term&lt;/td&gt;&lt;td&gt;Risk if the company folds‘Lifetime’ = lifetime of the productNo trials possible (App Store treats it as non-consumable)Feature exclusions in the fine print&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Brand&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Upfront cashLocks in value from would-be churnersFunds content or runway (esp. bootstrapped)Works well as promo (Black Friday, New Year)Can be used for referrals / tackling big competitors&lt;/td&gt;&lt;td&gt;Can cannibalize loyal high-LTV customersHarder to upsell or tier laterMessy mechanics (manual cancel + rebuy)Support headaches (double charges, refunds)Ongoing costs may outpace lifetime revenueLess attractive to investors (MRR &amp;gt; upfront cash)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-should-you-offer-lifetime-subscriptions&quot;&gt;Should you offer lifetime subscriptions?&lt;/h2&gt;



&lt;p&gt;To make this easy, I’ve created a simple quiz. The more ‘yes’ answers, the stronger the case for lifetime subscriptions. The more ‘no’ answers, the more carefully you should evaluate before testing a lifetime offer.&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Are your ongoing costs per user low? &lt;/strong&gt;High ongoing costs (e.g., many AI apps) make lifetime subscriptions less attractive.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Is valuation a lower priority right now?&lt;/strong&gt; If you’re not gearing up for investors or an exit, lifetime can be a smart move. If valuation is key, investors tend to value recurring revenue over front-loaded cash.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Do you need the upfront cash to fund future improvements or improve your runway? &lt;/strong&gt;Lifetime subscriptions can provide a significant cash boost to fund development or growth.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Is retention weak or uncertain?&lt;/strong&gt; If customers churn early, lifetime offers can lock in value upfront while you work on improving retention, and give you a larger user base to learn from.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Do you have a segment asking for lifetime subscriptions?&lt;/strong&gt; If users continue to request a lifetime option (especially older or potentially subscription-fatigued cohorts), that’s a sign it could be worth testing.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Are lifetime subscriptions common in your industry or sector? &lt;/strong&gt;Not saying you should copy others, but if it’s rare, there may be a good reason why.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Are upsells and higher tiers &lt;/strong&gt;&lt;strong&gt;&lt;em&gt;not&lt;/em&gt;&lt;/strong&gt;&lt;strong&gt; a big part of your model? &lt;/strong&gt;Lifetime subscriptions can block future growth, as users are less likely to upgrade or pay extra after buying lifetime access.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Don’t dash off just yet! If you decide to move forward with lifetime subscriptions, there are still a few important considerations to plan for.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-considerations-when-planning-lifetime-subscriptions-nbsp&quot;&gt;Considerations when planning lifetime subscriptions&amp;nbsp;&lt;/h2&gt;



&lt;p&gt;Even if you answered ‘yes’ to all the quiz questions, it’s still important to carefully consider a few key factors before rolling out lifetime subscriptions:&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-1-how-to-price-your-lifetime-subscriptions&quot;&gt;1. How to price your lifetime subscriptions&lt;/h2&gt;



&lt;p&gt;Pricing is crucial: set it too low, and you risk eroding your MRR; set it too high, and you may scare off potential customers. Lifetime subscription pricing varies widely across apps, from 2x annual pricing to nearly 12x annual pricing, depending on the product and market.&lt;/p&gt;



&lt;p&gt;Just look at how different apps approach it (note: prices regularly change and vary by country; these examples are based on current pricing in one market):&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;App name&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Annual price&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Lifetime price&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Lifetime price x annual&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Calm&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;$79&lt;/td&gt;&lt;td&gt;$399&lt;/td&gt;&lt;td&gt;5.0x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Jumpspeak&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;$69&lt;/td&gt;&lt;td&gt;$249&lt;/td&gt;&lt;td&gt;3.6x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Moonly&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;$28.98&lt;/td&gt;&lt;td&gt;$59.98&lt;/td&gt;&lt;td&gt;2.1x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Fiit&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;£119.99&lt;/td&gt;&lt;td&gt;£375 (£299 on offer)&lt;/td&gt;&lt;td&gt;3.1x (2.5x on offer)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Placify&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;$14.99&lt;/td&gt;&lt;td&gt;$49.99&lt;/td&gt;&lt;td&gt;3.3x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Waking Up&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;$129.99&lt;/td&gt;&lt;td&gt;$1500&lt;/td&gt;&lt;td&gt;11.5x&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;To determine where your lifetime subscription should sit within that range, consider:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Annual pricing&lt;/li&gt;



&lt;li&gt;Annual churn&lt;/li&gt;



&lt;li&gt;Gross margin&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Your category and retention patterns&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Strong retention and low margins generally allow for higher pricing. It’s also worth examining your LTV by cohort, not just the average:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;How are recent customers retaining?&lt;/li&gt;



&lt;li&gt;How do the most active customers retain, and what is their LTV?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;This approach helps ensure you don’t cannibalize your own revenue by pricing too low.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;If in doubt, I’d always recommend going higher rather than lower, like &lt;a href=&quot;https://www.wakingup.com/&quot;&gt;Waking Up&lt;/a&gt;, the meditation app, does. I struggled to find their lifetime subscription offer (more on why that is a good thing later), but the &lt;a href=&quot;https://www.wsj.com/tech/personal-tech/what-are-lifetime-subscriptions-deal-savings-c3c5757b&quot;&gt;Wall Street Journal reported that they charged $1,500&lt;/a&gt; for their Lifetime Subscription — more than 11x their annual price. This ensures it only convinces the most loyal of customers. and is worth it for Waking Up.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-2-which-audience-to-target-and-where-you-ll-promote-it&quot;&gt;2. Which audience to target and where you’ll promote it&lt;/h2&gt;



&lt;p&gt;Your target audience is closely tied to pricing strategy. My hypothesis: Waking Up aims to convert its most loyal customers, while Calm uses lifetime subscriptions more as a churn-reduction or holiday offer, pricing it lower at about 5x their annual subscription.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Knowing your target also helps determine where to promote the offer. &lt;/strong&gt;Most lifetime offers aren’t prominently featured on the app’s paywall. Instead, they are often sent via email or promoted as a one-off opportunity.&lt;/p&gt;



&lt;p&gt;In some cases, apps consciously offer lifetime subscriptions to all users as part of their strategy. This is common for utility-style apps, like &lt;a href=&quot;https://placify.co.uk/&quot;&gt;Placify&lt;/a&gt;, a personal mapping app:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;451&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-9-451x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-48105&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-9-451x1024.png 451w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-9-132x300.png 132w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-9-677x1536.png 677w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-9-22x50.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-9-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-9-204x464.png 204w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-9-696x1580.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-9-247x560.png 247w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-9-130x296.png 130w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-9-208x472.png 208w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-9-35x80.png 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-9-21x48.png 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-9.png 705w&quot; sizes=&quot;auto, (max-width: 451px) 100vw, 451px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;And &lt;a href=&quot;https://moonly.app/&quot;&gt;Moonly&lt;/a&gt;, a moon phases and calendar app. For apps where pricing is relatively low or usage fluctuates month-to-month, lifetime subscriptions can be a standard part of the offering, rather than a limited-time promotion.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;451&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-12-451x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-48111&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-12-451x1024.png 451w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-12-132x300.png 132w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-12-677x1536.png 677w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-12-22x50.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-12-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-12-204x464.png 204w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-12-696x1580.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-12-247x560.png 247w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-12-130x296.png 130w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-12-208x472.png 208w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-12-35x80.png 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-12-21x48.png 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-12.png 705w&quot; sizes=&quot;auto, (max-width: 451px) 100vw, 451px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;br&gt;In reality, the most Lifetime Offers I’ve seen and received have been through email, like &lt;a href=&quot;https://fiit.tv/&quot;&gt;Fiit&lt;/a&gt;, the fitness app:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;350&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-8-350x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-48103&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-8-350x1024.png 350w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-8-17x50.png 17w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-8-14x40.png 14w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-8-191x560.png 191w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-8-101x296.png 101w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-8-161x472.png 161w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-8-27x80.png 27w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-8-16x48.png 16w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-8.png 397w&quot; sizes=&quot;auto, (max-width: 350px) 100vw, 350px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;In this case, it felt like a win-back attempt, as I had just canceled my subscription. Overall, I’d recommend testing your lifetime offer first via owned channels — email, push, or in-app notifications — before promoting it more broadly. Of course, the approach will depend on which audience you plan to target.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-3-your-terms-and-conditions&quot;&gt;3. Your terms and conditions&lt;/h2&gt;



&lt;p&gt;Not the most exciting part, but absolutely critical to prevent lifetime subscriptions from backfiring. (&lt;strong&gt;Quick disclaimer: this is not legal advice!&lt;/strong&gt; This is where you get legal involved.)&lt;/p&gt;



&lt;p&gt;It’s important to think through considerations like:&amp;nbsp;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Which plan do they receive (if you have multiple tiers)&lt;/li&gt;



&lt;li&gt;Whether it can be combined with other discounts (I’d advise against it)&amp;nbsp;&lt;/li&gt;



&lt;li&gt;How major future changes to the app are handled&lt;/li&gt;



&lt;li&gt;How does the transition work from subscription to lifetime&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The second point is especially important. For example, if you offer family plans on lifetime subscriptions, users could end up getting far more value than you intended, cutting into your revenue.&lt;/p&gt;



&lt;p&gt;4. Determine your test strategy&amp;nbsp;&lt;/p&gt;



&lt;p&gt;By now, you should have a good sense of your initial lifetime subscription test strategy:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;How to price it: &lt;/strong&gt;don’t be afraid to&lt;strong&gt; &lt;/strong&gt;A/B test different multipliers (5x vs. 8x vs. 12x annual) and track not just conversions, but who converts&lt;/li&gt;
&lt;/ul&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Who sees it:&lt;/strong&gt; start by targeting lapsed users or segments with low retention rates&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;When to show it: &lt;/strong&gt;test seasonal promotions (Black Friday, New Year’s Day etc.) before deciding whether to make it evergreen&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;However, there is still one key final part to work out: &lt;strong&gt;how can you measure its success?&lt;/strong&gt;&amp;nbsp;&lt;/p&gt;



&lt;p&gt;It’s nearly impossible to know what those customers would have spent otherwise, and you’re likely working off a predicted LTV for the cohorts you’re comparing it to.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Instead, you want to be looking at:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Conversion rate: &lt;/strong&gt;how does it convert compared to other offers, and which segments are converting?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;ARPU vs similar cohorts: &lt;/strong&gt;are you earning more or less than you would have with traditional subscriptions?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;It’s also worth monitoring:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Engagement of lifetime subscribers: &lt;/strong&gt;paid users who don’t engage are less likely to advocate for your app&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Refunds and customer support load: &lt;/strong&gt;watch for double payment issues and keep an eye on refund requests and support volume&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Mix of revenue: &lt;/strong&gt;track the percentage of revenue from lifetime vs. subscription — too high a share of lifetime revenue could compromise compounding MRR in exchange for short-term cash&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Finally, start testing through your owned channels and keep it smaller or temporary. This allows you to fine-tune, learn from early data, and optimize before a full rollout.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-so-was-my-calm-lifetime-subscription-worth-it&quot;&gt;So, was my Calm lifetime subscription worth it?&lt;/h2&gt;



&lt;p&gt;For me, yes. Buying Calm for life removed the mental load of one more subscription, and even years later, I still feel like I got a bargain. But that’s the key: lifetime subscriptions usually feel like a win for the customer, not necessarily the brand.&lt;/p&gt;



&lt;p&gt;If Calm had kept me on an annual plan, they’d likely have earned significantly more from me by now. Instead, they traded long-term revenue for upfront cash, which may have made sense at the time to fund new features, celebrity narrators, and all the content they’ve since built.&lt;/p&gt;



&lt;p&gt;That’s the trade-off every app faces. &lt;strong&gt;Lifetime subscriptions can unlock cash when you need it, build loyalty, or help smaller apps stand out against bigger players.&lt;/strong&gt; But they can also cannibalize your most valuable customers, limit upsell opportunities, and create operational headaches that last for years.&lt;/p&gt;



&lt;p&gt;If you’re considering lifetime subscriptions, run the numbers, test carefully, and know who you’re really building it for. Because when your customer is thinking, “What a deal!”, you need to be absolutely sure you’re thinking the same on your side.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[The future of subscription apps: advice from an app-focused investment banker]]></title><description><![CDATA[GP Bullhound's Eric Crowley talks about the future of consumer subscriptions, how AI is reshaping growth, and why the best apps are built for love, not acquisition.]]></description><link>https://www.revenuecat.com/blog/growth/eric-crowley-gp-bullhound-sub-club-podcast-2025/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/eric-crowley-gp-bullhound-sub-club-podcast-2025/</guid><pubDate>Wed, 12 Nov 2025 14:35:45 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/RC-Blog-Cover-Eric-Crowley-1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;The consumer subscription software industry might not seem like an investment banker’s domain, but few people know it better than &lt;a href=&quot;http://linkedin.com/in/crowleyeric&quot;&gt;Eric Crowley&lt;/a&gt;. As a partner at &lt;a href=&quot;https://www.gpbullhound.com/&quot;&gt;GP Bullhound&lt;/a&gt;, Eric has spent the past six years advising top consumer app companies and publishing one of the industry’s most respected reports.&lt;/p&gt;



&lt;p&gt;This week on the Sub Club podcast, we sat down with Eric to discuss the findings from his latest Consumer Subscription Software Report. We talked about the future of consumer subscriptions, how AI is reshaping growth, and why the best apps are built for love, not acquisition.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
https://www.youtube.com/watch?v=IGxuXkPXEco
&lt;/div&gt;&lt;/figure&gt;



&lt;iframe loading=&quot;lazy&quot; width=&quot;100%&quot; height=&quot;180&quot; frameborder=&quot;no&quot; scrolling=&quot;no&quot; seamless=&quot;&quot; src=&quot;https://share.transistor.fm/e/69dd4ed5?color=FFFFFF&amp;amp;background=30343C&quot;&gt;&lt;/iframe&gt;



&lt;p&gt;&lt;strong&gt;The myth of subscription fatigue&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Subscription fatigue makes headlines, but Eric says it’s largely misunderstood. Consumers are more willing than ever to pay for products that genuinely add value. Tools for managing subscriptions have made billing more transparent, and AI-powered apps are creating entirely new categories of utility and entertainment.&lt;/p&gt;



&lt;p&gt;As Eric explains, people might cancel the services they don’t use, but they’ll keep paying for the ones they can’t live without. The opportunity for developers is to focus less on quantity and more on building the few apps users truly value.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Runna, Strava, and building for acquisition&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Eric also shared lessons from advising &lt;a href=&quot;https://www.runna.com/&quot;&gt;Runna&lt;/a&gt;&lt;strong&gt; &lt;/strong&gt;on its acquisition by &lt;a href=&quot;https://www.strava.com/&quot;&gt;Strava&lt;/a&gt;. The deal, he says, worked because both companies created strong standalone products with loyal audiences before coming together. Rather than building with a single buyer in mind, founders should aim to make something consumers love because great products naturally attract acquisition offers.&lt;/p&gt;



&lt;p&gt;For Strava, the Runna acquisition expanded its total market by serving runners who didn’t yet identify as “athletes.” For founders, it’s a reminder that integrations and bundles can open the door to new users and new revenue tiers.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;AI, app stores, and the next wave&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;AI is changing everything from app discovery to product development. Search traffic patterns are shifting as users turn to chatbots for recommendations, forcing marketers to rethink SEO and attribution. But the same technology is also helping teams test faster, generate content, and improve retention.&lt;/p&gt;



&lt;p&gt;Eric sees another significant tailwind: app stores are finally opening up. With Google and Apple relaxing restrictions on external payments, developers could see 15-20% of margin returned to their bottom line. Add in new opportunities in categories like pet wellness and screen time management, and it’s clear there’s still plenty of room to grow.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Wrap-up&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;These are just a few of the topics we covered in our conversation with Eric. To hear more on AI, acquisitions, and the future of consumer subscriptions, check out &lt;a href=&quot;https://www.youtube.com/watch?v=IGxuXkPXEco&quot;&gt;this week’s episode of the Sub Club podcast on YouTube&lt;/a&gt; or wherever you find your podcasts.&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[RevenueCat and Neon Apps join forces to support Türkiye’s growing app community]]></title><description><![CDATA[Expert local support + best-in-class monetization infrastructure now available for Turkish developers ]]></description><link>https://www.revenuecat.com/blog/company/revenuecat-turkiye-partnership/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/company/revenuecat-turkiye-partnership/</guid><pubDate>Wed, 12 Nov 2025 12:37:05 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Neon-Apps-x-RC.jpg" length="0" type="image/*"/><content:encoded>&lt;p&gt;Türkiye’s mobile app scene has exploded in recent years. New studios are building for global audiences, but many still face complex challenges around monetization, subscription infrastructure, and international growth.&lt;/p&gt;



&lt;p&gt;To help bridge that gap, &lt;strong&gt;RevenueCat&lt;/strong&gt; has partnered with &lt;strong&gt;&lt;a href=&quot;https://www.neonapps.co/&quot;&gt;Neon Apps&lt;/a&gt;&lt;/strong&gt;, a leading Istanbul-based software and growth agency. The partnership will make it easier than ever for Turkish app developers to get local support, expert guidance, and access to world-class tools for managing and optimizing in-app subscriptions.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-a-local-partner-for-global-growth-nbsp&quot;&gt;&lt;strong&gt;A local partner for global growth&amp;nbsp;&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;As RevenueCat’s official partner in Türkiye, &lt;strong&gt;Neon Apps&lt;/strong&gt; will provide dedicated support to local developers across every stage of app growth. Even better, it’s completely free — if you’re a RevenueCat customer, you can work with Neon Apps at zero extra cost.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;So if you’re a developer in Türkiye, this means that you’ll have access to hands-on, local-language support with all aspects of your RevenueCat project, including:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Technical implementation across iOS, Android and the Web&lt;/li&gt;



&lt;li&gt;Migrations to RevenueCat from alternative providers or your own system&lt;/li&gt;



&lt;li&gt;Understanding, analyzing and benchmarking your performance data&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Implementing RevenueCat’s suite of growth tools including our paywall builder, multi-variant testing and experiments features&lt;/li&gt;



&lt;li&gt;Access to a growing local community of peers building and scaling subscription apps&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;With this step, RevenueCat is continuing to expand its global partner network — empowering developers everywhere to monetize smarter, scale faster, and focus on building apps users love.&lt;/p&gt;



&lt;p&gt;This collaboration reflects a shared mission: helping developers make more money, &lt;em&gt;wherever &lt;/em&gt;they’re building.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-strengthening-turkiye-s-global-developer-footprint&quot;&gt;&lt;strong&gt;Strengthening Türkiye’s global developer footprint&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;In October 2025, we were excited to welcome founders from Türkiye’s top mobile studios to App Growth Annual in New York. Developers and founders from VL Media, Stoikk, PlusMinusOne, AppNation, Pixery Labs, Madduck, Byterise, Seven Apps, Popcorns, and Mobile Ocean joined the delegation — representing a new generation of globally-minded Turkish studios.&lt;/p&gt;



&lt;figure class=&quot;wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex&quot;&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;681&quot; data-id=&quot;48087&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01243-1024x681.jpeg&quot; alt=&quot;&quot; class=&quot;wp-image-48087&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01243-1024x681.jpeg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01243-300x199.jpeg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01243-768x511.jpeg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01243-1536x1021.jpeg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01243-2048x1362.jpeg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01243-50x33.jpeg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01243-60x40.jpeg 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01243-696x463.jpeg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01243-560x372.jpeg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01243-445x296.jpeg 445w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01243-710x472.jpeg 710w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01243-80x53.jpeg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01243-48x32.jpeg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;681&quot; data-id=&quot;48073&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01208-1024x681.jpeg&quot; alt=&quot;&quot; class=&quot;wp-image-48073&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01208-1024x681.jpeg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01208-300x199.jpeg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01208-768x511.jpeg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01208-1536x1021.jpeg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01208-2048x1362.jpeg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01208-50x33.jpeg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01208-60x40.jpeg 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01208-696x463.jpeg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01208-560x372.jpeg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01208-445x296.jpeg 445w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01208-710x472.jpeg 710w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01208-80x53.jpeg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01208-48x32.jpeg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;681&quot; data-id=&quot;48081&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01317-1024x681.jpeg&quot; alt=&quot;&quot; class=&quot;wp-image-48081&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01317-1024x681.jpeg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01317-300x199.jpeg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01317-768x511.jpeg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01317-1536x1021.jpeg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01317-2048x1362.jpeg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01317-50x33.jpeg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01317-60x40.jpeg 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01317-696x463.jpeg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01317-560x372.jpeg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01317-445x296.jpeg 445w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01317-710x472.jpeg 710w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01317-80x53.jpeg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01317-48x32.jpeg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;681&quot; data-id=&quot;48075&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01397-1024x681.jpeg&quot; alt=&quot;&quot; class=&quot;wp-image-48075&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01397-1024x681.jpeg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01397-300x199.jpeg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01397-768x511.jpeg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01397-1536x1021.jpeg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01397-2048x1362.jpeg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01397-50x33.jpeg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01397-60x40.jpeg 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01397-696x463.jpeg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01397-560x372.jpeg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01397-445x296.jpeg 445w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01397-710x472.jpeg 710w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01397-80x53.jpeg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01397-48x32.jpeg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;681&quot; data-id=&quot;48085&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01271-1024x681.jpeg&quot; alt=&quot;&quot; class=&quot;wp-image-48085&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01271-1024x681.jpeg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01271-300x199.jpeg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01271-768x511.jpeg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01271-1536x1021.jpeg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01271-2048x1362.jpeg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01271-50x33.jpeg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01271-60x40.jpeg 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01271-696x463.jpeg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01271-560x372.jpeg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01271-445x296.jpeg 445w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01271-710x472.jpeg 710w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01271-80x53.jpeg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01271-48x32.jpeg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;681&quot; data-id=&quot;48093&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01153-2-1024x681.jpeg&quot; alt=&quot;&quot; class=&quot;wp-image-48093&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01153-2-1024x681.jpeg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01153-2-300x199.jpeg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01153-2-768x511.jpeg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01153-2-1536x1021.jpeg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01153-2-2048x1362.jpeg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01153-2-50x33.jpeg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01153-2-60x40.jpeg 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01153-2-696x463.jpeg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01153-2-560x372.jpeg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01153-2-445x296.jpeg 445w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01153-2-710x472.jpeg 710w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01153-2-80x53.jpeg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/DSC01153-2-48x32.jpeg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;
&lt;/figure&gt;



&lt;p&gt;The same week, the two teams co-hosted the Turkish Tech Companies Meetup, gathering over 100 entrepreneurs and investors to celebrate the country’s growing influence in the global app economy.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-wp-embed is-provider-wistia-inc wp-block-embed-wistia-inc&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; class=&quot;wp-embedded-content&quot; sandbox=&quot;allow-scripts&quot; security=&quot;restricted&quot; title=&quot;RC x Neon Apps NYC Video&quot; src=&quot;https://fast.wistia.net/embed/iframe/p7dlw6trf1?dnt=1#?secret=OtEY9pk2oW&quot; data-secret=&quot;OtEY9pk2oW&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; width=&quot;500&quot; height=&quot;281&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-s-next&quot;&gt;&lt;strong&gt;What’s next?&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Our partnership with Neon Apps’ is just the beginning of our mission to help app developers worldwide make more money. If you’re a Türkiye-based app builder, &lt;strong&gt;&lt;a href=&quot;https://www.revenuecat.com/talk-to-sales/&quot;&gt;get in touch with RevenueCat&lt;/a&gt; and we’ll introduce you to Neon Apps&lt;/strong&gt; to see how they can support your growth journey.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;You can also check out our expansive &lt;a href=&quot;https://www.revenuecat.com/docs&quot;&gt;Docs&lt;/a&gt; for detailed information on getting started and growing with RevenueCat.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Simplify in-app purchase unit testing with RevenueCat’s Test Store]]></title><description><![CDATA[You'll deep dive into building reliable, automated unit tests for your in-app purchases logic, especially based on Android and Kotlin]]></description><link>https://www.revenuecat.com/blog/engineering/testing-test-store/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/testing-test-store/</guid><pubDate>Wed, 12 Nov 2025 01:04:36 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Simplify-in-app-purchases-unit-testing-with-RevenueCat-Test-Store.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;In-app purchase testing has long been a pain point in Android development. Setting up Google Play sandbox environments, managing test accounts, waiting for purchase verification, dealing with cached state… the friction is real. Luckily, RevenueCat’s &lt;a href=&quot;https://www.revenuecat.com/docs/getting-started/configuring-sdk#testing-with-test-store&quot;&gt;Test Store&lt;/a&gt; is a solution to this problem — offering &lt;strong&gt;instant testing without the complexity of real billing systems&lt;/strong&gt;. But the real benefit of Test Store isn’t just its simplified setup, it’s how it enables true unit testing of purchase flows, with minimal infrastructure.&lt;/p&gt;



&lt;p&gt;Read on to explore how to write unit tests for in-app purchases using RevenueCat’s Test Store, examining real test implementations that verify offering fetching, purchase flows, entitlement granting, and error handling. We’ll also deep dive into building reliable, fast unit tests for your monetization code, especially based on Android, but the overall approach will not be much different across platforms. You can see a complete implementation of these tests in &lt;a href=&quot;https://github.com/RevenueCat/cat-paywall-compose/pull/19&quot;&gt;this pull request&lt;/a&gt;.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-understanding-the-core-abstraction-what-makes-test-store-special&quot;&gt;&lt;strong&gt;Understanding the core abstraction: What makes Test Store special&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Test Store is a mock billing backend that behaves exactly like production RevenueCat, but without requiring real payment processing from Google Play Billing or StoreKit. What distinguishes Test Store from Google Play’s sandbox is its adherence to two fundamental properties: &lt;strong&gt;instant availability&lt;/strong&gt; and &lt;strong&gt;complete control&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;There’s not much setup required beyond enabling your Test Store and getting your Test Store API key from the dashboard. You don’t need to configure test accounts, wait for Google Play sandbox propagation, or deal with payment method requirements.&lt;/p&gt;



&lt;p&gt;Complete control means you decide the outcome of every purchase. When the Test Store shows its dialog, you choose: &lt;em&gt;successful purchase&lt;/em&gt;,&lt;em&gt; failed purchase&lt;/em&gt;, or &lt;em&gt;cancellation&lt;/em&gt;. This determinism is what makes unit testing possible — you can reliably test both happy paths and error conditions without flaky network dependencies.&lt;/p&gt;



&lt;p&gt;These properties aren’t just conveniences, they’re architectural constraints that enable fast, reliable unit tests. You can run hundreds of purchase flow tests in minutes because there’s no real billing service, no network latency, and no external state to manage.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;how-to-create-the-test-store-and-test-products&quot;&gt;&lt;strong&gt;How to create the Test Store and test products&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;To enable Test Store, go to the&lt;a href=&quot;https://app.revenuecat.com/&quot;&gt; RevenueCat dashboard&lt;/a&gt;, and click the &lt;strong&gt;Apps &amp;amp; providers&lt;/strong&gt; menu on the sidebar, then you can create your Test Store like the image below:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;911&quot; height=&quot;267&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/1.png&quot; alt=&quot;&quot; class=&quot;wp-image-48056&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/1.png 911w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/1-300x88.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/1-768x225.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/1-50x15.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/1-125x37.png 125w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/1-696x204.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/1-560x164.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/1-840x246.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/1-80x23.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/1-48x14.png 48w&quot; sizes=&quot;auto, (max-width: 911px) 100vw, 911px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Once you click &lt;strong&gt;Create Test Store&lt;/strong&gt;, you’ll receive a &lt;strong&gt;Test Store API key&lt;/strong&gt;. You can use this key just like a regular secret API key when running in a &lt;strong&gt;test environment&lt;/strong&gt;, allowing you to perform in-app purchases through the &lt;strong&gt;Test Store&lt;/strong&gt; instead of the real app stores.&lt;/p&gt;



&lt;p&gt;Next, navigate to &lt;strong&gt;Product Catalog → Products&lt;/strong&gt;, and create &lt;strong&gt;Test Products&lt;/strong&gt; under the &lt;strong&gt;Test Store&lt;/strong&gt; section just as you’d create regular products. You can also attach entitlements and configure the test products as needed.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;675&quot; height=&quot;196&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/2.png&quot; alt=&quot;&quot; class=&quot;wp-image-48058&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/2.png 675w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/2-300x87.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/2-50x15.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/2-125x36.png 125w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/2-560x163.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/2-80x23.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/2-48x14.png 48w&quot; sizes=&quot;auto, (max-width: 675px) 100vw, 675px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Finally, make sure to add your test product to the offering, within a package. This links it to your Test Store, so you can switch between test and live stores just by changing the API key.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;751&quot; height=&quot;428&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/3.png&quot; alt=&quot;&quot; class=&quot;wp-image-48060&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/3.png 751w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/3-300x171.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/3-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/3-70x40.png 70w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/3-696x397.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/3-560x319.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/3-519x296.png 519w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/3-80x46.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/3-48x27.png 48w&quot; sizes=&quot;auto, (max-width: 751px) 100vw, 751px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;And that’s it! With your &lt;strong&gt;Test Store API key&lt;/strong&gt;, you’ve basically got your own mini app store, like Google Play or the App Store, where you can freely test and run unit tests for in-app purchase flows without any limitations.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;the-test-architecture-unit-tests-vs-instrumented-tests&quot;&gt;&lt;strong&gt;The test architecture: Unit tests vs. instrumented tests&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;When structuring tests for in-app purchases, you’ll need to decide between unit tests and instrumented tests. For Test Store, instrumented tests are required because in-app purchases depend on Android-specific APIs, such as Activity.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;understanding-source-sets&quot;&gt;&lt;strong&gt;Understanding source sets&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Android projects typically have two test source sets:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-2cBnr7 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;src\/test\/kotlin\/             # Unit tests (JVM) - Fast, no Android framework\nsrc\/androidTest\/kotlin\/      # Instrumented tests - Run on device\/emulator&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Unit tests:&lt;/strong&gt; Run on the JVM without the Android framework — they’re fast (milliseconds) but can’t access Android APIs like Context, Activity, or hardware sensors.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Instrumented tests:&lt;/strong&gt; Run on an actual Android device or emulator — they have full access to the Android framework but are slower to execute.&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-instrumented-test-requirement&quot;&gt;&lt;strong&gt;The instrumented test requirement&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;RevenueCat’s SDK requires an Android context for initialization:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1L2Qop wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;Purchases.configure(\n  PurchasesConfiguration.Builder(context, BuildConfig.REVENUECAT_TEST_API_KEY)\n    .purchasesAreCompletedBy(PurchasesAreCompletedBy.REVENUECAT)\n    .diagnosticsEnabled(true)\n    .build()\n)\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This means you can’t test purchase flows in pure JVM unit tests. You need either:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Instrumented tests:&lt;/strong&gt; Run on a device/emulator with real Android framework&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Robolectric tests:&lt;/strong&gt; Simulate Android framework on the JVM (not covered here)&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Instrumented tests provide the most accurate representation of production behavior. The tests run on an actual Android environment, using the real RevenueCat SDK with Test Store backend. This gives you confidence that the integration works correctly, not just that your ‘mocks’ behave as expected.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-test-setup-configuration-and-api-key-management&quot;&gt;&lt;strong&gt;The test setup: configuration and API key management&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Before diving into test implementations, let’s examine the setup required. Every test class needs to configure the RevenueCat SDK before running tests. This happens in a &lt;code&gt;@Before&lt;/code&gt; method that runs before each test.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;step-1-getting-the-android-context&quot;&gt;&lt;strong&gt;Step 1: Getting the Android context&lt;/strong&gt;&lt;/h3&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-QBV0W wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Before\nfun setup() {\n  val context = InstrumentationRegistry.getInstrumentation().targetContext&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;InstrumentationRegistry provides access to the test environment. The targetContext is the application context of the app being tested, this is what RevenueCat needs for initialization.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;step-2-initializing-the-sdk&quot;&gt;&lt;strong&gt;Step 2: Initializing the SDK&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Next, you should initialize RevenueCat SDK inside the setup function like the below:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1TzDDl wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/\/ Configure Purchases SDK with Test Store API key\n  Purchases.logLevel = LogLevel.DEBUG\n  Purchases.configure(\n    PurchasesConfiguration.Builder(context, BuildConfig.REVENUECAT_TEST_API_KEY)\n      .purchasesAreCompletedBy(PurchasesAreCompletedBy.REVENUECAT)\n      .build()\n  )&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Breaking down each configuration option:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;LogLevel.DEBUG&lt;/strong&gt;: Enables detailed SDK logging; in production you’d use LogLevel.WARN or LogLevel.ERROR, but for testing, verbose logs help trace issues&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;purchasesAreCompletedBy(PurchasesAreCompletedBy.REVENUECAT)&lt;/strong&gt;: Tells the SDK that RevenueCat’s backend handles purchase acknowledgment — this is the recommended approach, and what Test Store expects&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;step-3-managing-the-test-store-api-key&quot;&gt;&lt;strong&gt;Step 3: Managing the Test Store API key&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The Test Store API key is loaded from BuildConfig, which reads from local.properties:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-104bd4 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;# local.properties\nrevenuecat.test.api.key=test_YOUR_KEY_HERE&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This keeps secrets out of version control. The Gradle build script injects it as a build config field:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1NJKwF wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;android {\n  defaultConfig {\n    buildConfigField(\&amp;quot;String\&amp;quot;, \&amp;quot;REVENUECAT_TEST_API_KEY\&amp;quot;, \&amp;quot;\\\\\&amp;quot;${properties[&apos;revenuecat.test.api.key&apos;] ?: &apos;&apos;}\\\\\&amp;quot;\&amp;quot;)\n  }\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;For CI environments, you’d set this via environment variables instead.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;test-implementation-verifying-sdk-connection-and-offerings&quot;&gt;&lt;strong&gt;Test implementation: verifying SDK connection and offerings&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Let’s start with the most basic test: verifying that the SDK can connect to the Test Store and fetch customer info. This test validates that your setup is correct before attempting more complex purchase flows.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-connection-test-structure&quot;&gt;&lt;strong&gt;The connection test structure&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The test uses runTest from&lt;a href=&quot;https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-test/&quot;&gt; kotlinx-coroutines-test&lt;/a&gt;:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1UdIv4 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Test\nfun testSDKConnection() = runTest {\n  ..\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;&lt;code&gt;runTest&lt;/code&gt; provides a controlled coroutine environment for testing suspend functions. It automatically waits for all launched coroutines to complete and fails the test if any throw exceptions.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;fetching-customer-info&quot;&gt;&lt;strong&gt;Fetching customer info&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The core operation is fetching customer info:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-2pw3z8 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;  val customerInfo = Purchases.sharedInstance.awaitCustomerInfo()&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;&lt;code&gt;awaitCustomerInfo()&lt;/code&gt; is a suspend function that returns CustomerInfo, RevenueCat’s representation of a user’s subscription state. This single call does several things:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Connects to RevenueCat’s servers&lt;/li&gt;



&lt;li&gt;Authenticates with your Test Store API key&lt;/li&gt;



&lt;li&gt;Creates or retrieves an anonymous user&lt;/li&gt;



&lt;li&gt;Returns subscription and entitlement data&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;If this call succeeds, it means your Test Store configuration is correct.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;validating-the-response&quot;&gt;&lt;strong&gt;Validating the response&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The test validates specific fields that should always be present:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-25zhlt wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;  assertNotNull(\&amp;quot;CustomerInfo should not be null\&amp;quot;, customerInfo)\n  assertNotNull(\&amp;quot;User ID should not be null\&amp;quot;, customerInfo.originalAppUserId)\n  assertFalse(\&amp;quot;User ID should not be empty\&amp;quot;, customerInfo.originalAppUserId.isEmpty())\n  assertNotNull(\&amp;quot;First seen date should not be null\&amp;quot;, customerInfo.firstSeen)\n  assertNotNull(\&amp;quot;Entitlements map should not be null\&amp;quot;, customerInfo.entitlements)&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Breaking down what each assertion catches:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;originalAppUserId&lt;/strong&gt;: The anonymous user ID generated by RevenueCat — if this is null or empty, user tracking won’t work correctly&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;firstSeen&lt;/strong&gt;: Timestamp of when this user was first seen — this should never be null for a valid customer&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;entitlements&lt;/strong&gt;: Map of all entitlements (may be empty for new users, but the map itself should exist)&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;fetching-offerings-testing-product-configuration&quot;&gt;&lt;strong&gt;Fetching offerings: testing product configuration&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The next test verifies that offerings can be fetched from the Test Store.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z2a7y3B wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Test\nfun testFetchOfferings() = runTest {\n  val offerings = Purchases.sharedInstance.awaitOfferings()\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;&lt;code&gt;awaitOfferings()&lt;/code&gt; returns an &lt;code&gt;Offerings&lt;/code&gt; object containing all configured offerings. The &lt;code&gt;all&lt;/code&gt; property is a map of offering ID to &lt;code&gt;Offering&lt;/code&gt; object. Now, you have offerings, you can verify each offering has a valid identifier.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZFRnMN wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;  offerings.all.forEach { (id, offering) -&gt;\n\/\/ Verify offering has required fields\n    assertNotNull(\&amp;quot;Offering identifier should not be null\&amp;quot;, offering.identifier)\n    assertEquals(\&amp;quot;Offering map key should match identifier\&amp;quot;, id, offering.identifier)\n    assertNotNull(\&amp;quot;Available packages should not be null\&amp;quot;, offering.availablePackages)&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;These assertions verify the data structure integrity:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Identifier consistency:&lt;/strong&gt; The map key must match the offering’s identifier — this ensures lookups work correctly&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Packages exist:&lt;/strong&gt; Every offering must have packages — an offering without packages can’t be purchased&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;validating-package-and-product-details&quot;&gt;&lt;strong&gt;Validating package and product details&lt;/strong&gt;&lt;/h3&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z25sAuB wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;    offering.availablePackages.forEach { pkg -&gt;\n      assertNotNull(\&amp;quot;Package identifier should not be null\&amp;quot;, pkg.identifier)\n      assertFalse(\&amp;quot;Package identifier should not be empty\&amp;quot;, pkg.identifier.isEmpty())\n      assertNotNull(\&amp;quot;Product should not be null\&amp;quot;, pkg.product)\n      assertNotNull(\&amp;quot;Product ID should not be null\&amp;quot;, pkg.product.id)\n      assertNotNull(\&amp;quot;Product price should not be null\&amp;quot;, pkg.product.price)\n    }&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This validates that each product has the fields your UI needs. If pkg.product.price were null, displaying it would crash. This test catches that during development, not in production.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;verifying-the-current-offering&quot;&gt;&lt;strong&gt;Verifying the current offering&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Most apps display a ‘current offering’ to users, aka the primary monetization option. Testing this requires graceful handling when it’s not configured:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1MFtKH wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Test\nfun testCurrentOffering() = runTest {\n  val offerings = Purchases.sharedInstance.awaitOfferings()\n  val currentOffering = offerings.current\n\n  assertTrue(\n    \&amp;quot;Current offering should have at least one package\&amp;quot;,\n    currentOffering.availablePackages.isNotEmpty()\n  )\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;testing-the-purchase-flow-espresso-ui-interaction&quot;&gt;&lt;strong&gt;Testing the purchase flow: Espresso UI interaction&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The most important tests involve full purchase flows. These tests use Espresso to interact with Test Store’s dialog, simulating user actions like clicking ‘Test valid Purchase’ or ‘Cancel’.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;why-purchase-tests-need-an-activity&quot;&gt;&lt;strong&gt;Why purchase tests need an Activity&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;RevenueCat’s purchase API requires an &lt;code&gt;Activity&lt;/code&gt; context:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1Hy04q wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;suspend fun awaitPurchase(purchaseParams: PurchaseParams): PurchaseResult&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The Activity is needed because:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Google Play Billing shows UI (though Test Store doesn’t use real billing)&lt;/li&gt;



&lt;li&gt;The billing flow needs a lifecycle to attach to&lt;/li&gt;



&lt;li&gt;RevenueCat validates that the Activity is active before starting purchases&lt;/li&gt;
&lt;/ol&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;creating-a-test-activity&quot;&gt;&lt;strong&gt;Creating a test Activity&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;For testing, you need a minimal Activity that launches purchases:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1OqU9O wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;class TestPurchaseActivity : Activity() {\n  private val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())\n\n  override fun onDestroy() {\n    super.onDestroy()\n    scope.cancel()\n  }\n\n  fun launchPurchase(\n    packageToPurchase: Package,\n    callback: (PurchaseResult?, Throwable?) -&gt; Unit\n  ) {\n    scope.launch {\n      try {\n        val purchaseParams = PurchaseParams.Builder(this@TestPurchaseActivity, packageToPurchase).build()\n        val result = Purchases.sharedInstance.awaitPurchase(purchaseParams)\n        callback(result, null)\n      } catch (e: Exception) {\n        callback(null, e)\n      }\n    }\n  }\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Breaking down the implementation:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Coroutine scope:&lt;/strong&gt; Tied to &lt;code&gt;Dispatchers.Main&lt;/code&gt; because purchase UI must show on the main thread. Using &lt;code&gt;SupervisorJob()&lt;/code&gt; ensures one failed purchase doesn’t cancel other operations&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Proper cleanup:&lt;/strong&gt; The scope is cancelled in &lt;code&gt;onDestroy()&lt;/code&gt; to prevent coroutine leaks when the Activity finishes.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Callback-based API:&lt;/strong&gt; Tests need to wait for purchase completion. A callback signals when the purchase finishes (successfully or with error), allowing the test thread to synchronize with the purchase operation.&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;testing-successful-purchases-with-espresso&quot;&gt;&lt;strong&gt;Testing successful purchases with Espresso&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;A successful purchase test involves several steps: fetching offerings, launching an Activity, initiating a purchase, interacting with Test Store’s dialog, and verifying the results. Let’s break it down step by step.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;step-1-preparing-the-purchase&quot;&gt;&lt;strong&gt;Step 1: Preparing the purchase&lt;/strong&gt;&lt;/h3&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-2lOBXA wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Test\nfun testSuccessfulPurchaseFlow() = runBlocking {\n\/\/ Fetch offeringsval offerings = Purchases.sharedInstance.awaitOfferings()\n  val testOffering = offerings.all[\&amp;quot;test-offering\&amp;quot;]\n  assertNotNull(\&amp;quot;test-offering should exist\&amp;quot;, testOffering)\n\n  val packageToPurchase = testOffering!!.availablePackages.first()\n\n\/\/ Get initial customer info to compare laterval initialCustomerInfo = Purchases.sharedInstance.awaitCustomerInfo()\n  val initialActiveEntitlements = initialCustomerInfo.entitlements.active.size&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The test uses &lt;code&gt;runBlocking&lt;/code&gt; instead of &lt;code&gt;runTest&lt;/code&gt; because it needs to interact with UI (Espresso) while waiting for async operations. We fetch the offering we’ll purchase and capture the initial entitlement state to verify changes later.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;step-2-launching-the-activity-and-initiating-purchase&quot;&gt;&lt;strong&gt;Step 2: Launching the Activity and initiating purchase&lt;/strong&gt;&lt;/h3&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1tS6ap wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;  activityScenario = ActivityScenario.launch(TestPurchaseActivity::class.java)\n\n  var purchaseResult: PurchaseResult? = null\n  var purchaseError: Throwable? = null\n\n  activityScenario.onActivity { activity -&gt;\n    activity.launchPurchase(packageToPurchase) { result, error -&gt;\n      purchaseResult = result\n      purchaseError = error\n    }\n  }&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;&lt;code&gt;ActivityScenario.launch()&lt;/code&gt; starts the test Activity. The &lt;code&gt;onActivity&lt;/code&gt; block executes on the main thread with access to the Activity instance. We call &lt;code&gt;launchPurchase()&lt;/code&gt;, which triggers &lt;code&gt;awaitPurchase()&lt;/code&gt; in a coroutine. The callback will fire when the purchase completes.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;step-3-interacting-with-test-stores-dialog&quot;&gt;&lt;strong&gt;Step 3: Interacting with Test Store’s dialog&lt;/strong&gt;&lt;/h3&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-2dDot1 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;  delay(2000)\/\/ Give dialog time to appear\n\n  onView(withText(\&amp;quot;Test valid Purchase\&amp;quot;)).perform(click())&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;After initiating the purchase, Test Store shows a dialog with three options. Espresso’s &lt;code&gt;onView()&lt;/code&gt; finds the button by text and &lt;code&gt;perform(click())&lt;/code&gt; simulates a user tap.&lt;/p&gt;



&lt;p&gt;The &lt;code&gt;delay(2000)&lt;/code&gt; gives the dialog time to appear. This is a pragmatic approach, in production tests you’d use Espresso’s idling resources for more reliable synchronization, but for Test Store the delay is sufficient.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;step-4-waiting-for-purchase-completion&quot;&gt;&lt;strong&gt;Step 4: Waiting for purchase completion&lt;/strong&gt;&lt;/h3&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1so2S wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;  withTimeout(30.seconds) {\n    while (purchaseResult == null &amp;amp;&amp;amp; purchaseError == null) {\n      delay(500)\n    }\n  }&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This polling loop waits for the callback to fire. The purchase happens asynchronously in the Activity’s coroutine, while the test thread polls the result variables. &lt;code&gt;withTimeout&lt;/code&gt; ensures the test fails if the purchase hangs rather than blocking forever.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Step 5: Verifying the results&lt;/strong&gt;&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-2bQV70 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;  assertNotNull(\&amp;quot;Purchase should complete without error\&amp;quot;, purchaseResult)\n\n  val result = purchaseResult!!\n\n\/\/ Verify entitlements were granted\n  assertTrue(\n    \&amp;quot;Should have active entitlements after purchase\&amp;quot;,\n    result.customerInfo.entitlements.active.isNotEmpty()\n  )\n\n\/\/ Verify transaction details\n  assertTrue(\n    \&amp;quot;Transaction should contain purchased product\&amp;quot;,\n    result.storeTransaction.productIds.contains(packageToPurchase.product.id)\n  )\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The test verifies three things:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Purchase completed without error (no exception)&lt;/li&gt;



&lt;li&gt;Entitlements were granted (active entitlements exist)&lt;/li&gt;



&lt;li&gt;Transaction contains the correct product ID&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;This catches subtle bugs where purchase succeeds but entitlements aren’t granted correctly. Your app relies on entitlements to unlock features — if they’re not granted, premium features won’t work.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;testing-purchase-cancellation&quot;&gt;&lt;strong&gt;Testing purchase cancellation&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Cancellation testing verifies that your app handles user-initiated cancellations correctly:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-UdCk5 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Test\nfun testPurchaseCancellation() = runBlocking {\n  val offerings = Purchases.sharedInstance.awaitOfferings()\n  val packageToPurchase = offerings.all[\&amp;quot;test-offering\&amp;quot;]!!.availablePackages.first()\n\n  activityScenario = ActivityScenario.launch(TestPurchaseActivity::class.java)\n\n  var purchaseError: Throwable? = null\n  activityScenario.onActivity { activity -&gt;\n    activity.launchPurchase(packageToPurchase) { _, error -&gt;\n      purchaseError = error\n    }\n  }\n\n  delay(2000)\n  onView(withText(\&amp;quot;Cancel\&amp;quot;)).perform(click())\n\n  withTimeout(15.seconds) {\n    while (purchaseError == null) delay(500)\n  }\n\n  assertNotNull(\&amp;quot;Should have error after cancellation\&amp;quot;, purchaseError)\n  assertTrue(\n    \&amp;quot;Error should indicate cancellation\&amp;quot;,\n    purchaseError?.message?.contains(\&amp;quot;cancel\&amp;quot;, ignoreCase = true) == true\n  )\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The assertion checks that the error message contains ‘cancel’. This is important; your app needs to distinguish between user cancellation (don’t show error UI) and actual errors (show error message). When a user taps ‘Cancel’, it’s not an error condition, it’s expected behavior that shouldn’t trigger error alerts.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;testing-failed-purchases&quot;&gt;&lt;strong&gt;Testing failed purchases&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Failed purchase testing verifies that billing errors don’t grant entitlements:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z2sIhfd wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Test\nfun testFailedPurchase() = runBlocking {\n  val offerings = Purchases.sharedInstance.awaitOfferings()\n  val packageToPurchase = offerings.all[\&amp;quot;test-offering\&amp;quot;]!!.availablePackages.first()\n\n\/\/ Capture initial stateval initialCustomerInfo = Purchases.sharedInstance.awaitCustomerInfo()\n  val initialEntitlements = initialCustomerInfo.entitlements.active.size\n\n  activityScenario = ActivityScenario.launch(TestPurchaseActivity::class.java)\n\n  var purchaseError: Throwable? = null\n  activityScenario.onActivity { activity -&gt;\n    activity.launchPurchase(packageToPurchase) { _, error -&gt;\n      purchaseError = error\n    }\n  }\n\n  delay(2000)\n  onView(withText(\&amp;quot;Test failed Purchase\&amp;quot;)).perform(click())\n\n  withTimeout(15.seconds) {\n    while (purchaseError == null) delay(500)\n  }\n\n  assertNotNull(\&amp;quot;Should have error after failed purchase\&amp;quot;, purchaseError)\n\n\/\/ Verify entitlements unchangedval finalCustomerInfo = Purchases.sharedInstance.awaitCustomerInfo()\n  val finalEntitlements = finalCustomerInfo.entitlements.active.size\n\n  assertFalse(\n    \&amp;quot;Failed purchase should not grant entitlements\&amp;quot;,\n    finalEntitlements &gt; initialEntitlements\n  )\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The critical assertion is that entitlements don’t increase after a failed purchase. This catches bugs where error handling is incomplete and entitlements are granted even when purchase fails. Your app must handle this correctly, failed purchases shouldn’t unlock premium features.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;running-the-tests-gradle-commands-and-ci-integration&quot;&gt;&lt;strong&gt;Running the tests: Gradle commands and CI integration&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;To run these tests locally, use Gradle’s connected test tasks:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1QbAPY wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;# Run all instrumented tests in the data module\n.\/gradlew :core:data:connectedAndroidTest\n\n# Run only Test Store tests\n.\/gradlew :core:data:connectedAndroidTest --tests \&amp;quot;*RevenueCatTestStoreTest\&amp;quot;\n.\/gradlew :core:data:connectedAndroidTest --tests \&amp;quot;*TestStorePurchaseFlowTest\&amp;quot;\n\n# Run with verbose output\n.\/gradlew :core:data:connectedAndroidTest --info&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;connectedAndroidTest&lt;/code&gt; task requires a connected device or running emulator. For CI, you’d typically use an emulator:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1V1sB3 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;# GitHub Actions example- name: Start emulator\n  uses: reactivecircus\/android-emulator-runner@v2\n  with:\n    api-level: 30\n    target: google_apis\n    arch: x86_64\n    script: .\/gradlew :core:data:connectedAndroidTest\n\n- name: Upload test results\n  uses: actions\/upload-artifact@v3\n  if: always()\n  with:\n    name: test-results\n    path: &apos;**\/build\/reports\/androidTests\/&apos;&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Now, you can even verify the entire in-app purchases testing flows within your CI machine, which is entirely automated.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;wrapping-up&quot;&gt;&lt;strong&gt;Wrapping up&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;So, we’ve explored how to write comprehensive unit tests for in-app purchases using RevenueCat’s Test Store, automating real test implementations that verify offerings, purchase flows, entitlements, and error handling without requiring real payment processing or Google Play infrastructure. Now, it’s time for you to get testing!&lt;/p&gt;



&lt;p&gt;By having unit tests for in-app purchase flows, you’ll have confidence in your monetization code. Whether you’re building a new subscription feature, refactoring purchase flows, or debugging entitlement issues, these tests provide a foundation for reliable, fast verification of your in-app purchase implementation. The key is leveraging Test Store’s deterministic behavior, letting you control success, failure, and cancellation, making it possible to test error paths that are difficult or impossible to test withing real billing systems.&lt;/p&gt;



&lt;p&gt;As always, happy coding!&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Inside the sales org at RevenueCat: helping over selling]]></title><description><![CDATA[A peek under the hood of our sales motion (we’re hiring!)]]></description><link>https://www.revenuecat.com/blog/company/inside-sales/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/company/inside-sales/</guid><pubDate>Tue, 11 Nov 2025 09:01:14 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/IMG_1971.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;‘Sales’ in quotes because we’ve never done the hard-selling many folks picture when they hear that word. In fact, while RevenueCat powers a significant share of all the world’s in-app revenue, right now our entire sales org is three and a half people (counting myself as the half)&lt;/p&gt;



&lt;p&gt;When a prospect or customer fills out a form to talk to us or signs up for RevenueCat, we focus on helping them evaluate, and if it makes sense, buy RevenueCat. We’re not particularly bothered how you want to evaluate (poke around the product, do a live demo, build a business case for your company), and we don’t really mind how you want to buy (self-serve, via a contract). We primarily handle ‘inbound’ interest (people fill out a form or sign up)&lt;/p&gt;



&lt;p&gt;Why inbound? We’ve historically offered the entire RevenueCat platform as a whole, which isn’t something you can easily pitch in a cold call. “Hey, want to rip out all the subscription tech in your multi-million dollar app and use ours instead?” isn’t exactly a winning opener. Instead, we focus on being consultative product and market experts who ensure that when an app developer or company shows interest, we add value. We make it easy to implement our product, understand our value, buy from us, and work with us&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-does-the-sales-motion-look-like-today&quot;&gt;What does the sales motion look like today?&lt;/h2&gt;



&lt;p&gt;It’s heavily inbound and aligned with &lt;a href=&quot;https://www.revenuecat.com/blog/company/why-were-customer-obsessed-and-you-should-be-too/&quot;&gt;our customer-centric ethos&lt;/a&gt;. When a prospect (often a developer, product manager, or founder) reaches out, our team jumps in to help them learn what we do, how we do it, and how it’ll help them make more money (&lt;a href=&quot;https://www.revenuecat.com/blog/company/values/&quot;&gt;the company mission we live by&lt;/a&gt;). We answer questions, dive into their technical setup, and even provide some revenue growth tips and tricks where we can. The app space is small, so it helps to help even if it doesn’t result in winning a new customer today&lt;/p&gt;



&lt;p&gt;Our goal isn’t to push a deal at all costs; it’s to ensure every potential customer deeply understands how we can solve their problems. This also means being honest if we’re &lt;em&gt;not&lt;/em&gt; the right fit, or not the right fit &lt;em&gt;right now&lt;/em&gt;. In many cases, the ‘Sales’ team is actually just helping people self-serve: use the free tier, play with the SDK, read our docs, ping us with questions, etc&lt;/p&gt;



&lt;p&gt;A successful sales motion for us is not about ringing the sales gong, but helping our customers extract the most value from RevenueCat. Some of the biggest RevenueCat-powered apps in the app stores today got their start on our self-serve plan. We only step in when specifically asked to do so, or when we suspect folks will need some help (e.g. bigger teams often have a harder time evaluating across multiple stakeholders)&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-our-approach-is-different-and-why-we-like-it&quot;&gt;How our approach is different (and why we like it)&lt;/h2&gt;



&lt;p&gt;Thanks to our product-led growth (PLG) engine, our sales approach is a bit different. Here’s a few ways we stand out&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-sales-engineering-heavy&quot;&gt;Sales-Engineering heavy&lt;/h3&gt;



&lt;p&gt;We’ve developed a predominantly sales engineering-led motion. Our technical experts (sales engineers) often handle customer conversations end to end (from evaluation to buying), and – as a result – have to be very well rounded. They can speak the developer’s language, demonstrate the SDK, and troubleshoot on the fly, but they also know what a great paywall looks like and can suggest a simple reactivation campaign for churned users. Even in this sales-engineering heavy environment, the Account Executive is an important part of the puzzle: They’re not only great at navigating complex companies and buying preferences, but also know how to quantify &lt;em&gt;and&lt;/em&gt; communicate the costs and benefits of RevenueCat&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-helping-over-closing&quot;&gt;Helping over ‘closing’&lt;/h3&gt;



&lt;p&gt;Every SaaS out there loves to say they’re consultative, but at RevenueCat we truly live it. Our philosophy is that if we take care of our customers’ needs, the sales will take care of itself. Concretely, this means the team spends a lot of time educating prospects. From in-app monetization best practices, implementation details, analytics and reporting tips, we get into the weeds before the topic of pricing even comes up. We’re not here to convince you that you &lt;em&gt;need&lt;/em&gt; RenueCat; we’re here to show you how we could help, and let you decide if it’s right. This approach builds trust and long-term partnerships, which in turn means that we’ve been talking on and off to some prospects about app growth and trends for years before they move over&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;222&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-5-1024x222.png&quot; alt=&quot;&quot; class=&quot;wp-image-48052&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-5-1024x222.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-5-300x65.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-5-768x167.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-5-50x11.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-5-125x27.png 125w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-5-696x151.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-5-560x121.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-5-840x182.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-5-80x17.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-5-48x10.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-5.png 1162w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Real quote pulled from a recent Gong transcript for a call with one of the top 200 biggest apps in the world&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-an-inbound-machine&quot;&gt;An inbound machine&lt;/h3&gt;



&lt;p&gt;Thanks to our vocal customer base, some pretty sophisticated account based marketing efforts, and the success of our product, we have a strong inbound engine. Over 60% of our target strategic accounts (the top xxx apps in the world) engage with our website, content, and community on a monthly basis. That’s a dream scenario for most sales orgs. It means a lot of potential customers out there already know us, trust our brand, and are curious to learn more. Our job in Sales is often to simply respond to that interest quickly and helpfully. We use a bunch of tools to make sure no interested developer falls through the cracks: From intent data platforms (shoutout to 6Sense) to Clay-powered enrichment flows that automatically flag signups that are likely to need a bit of proactive support. The bottom line is, we’re not typically cold-calling strangers; we’re talking to people who &lt;em&gt;want&lt;/em&gt; to talk to us. It makes the whole experience more pleasant for everyone involved. Oh, and if you are in the mobile space, perhaps you’ve &lt;a href=&quot;https://www.linkedin.com/posts/susannahbanks_if-youre-at-mau-today-swing-by-and-say-activity-7331295439817777153-y7zl/&quot;&gt;seen us at a conference or two&lt;/a&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;RevenueCat Annual Conference 2025 at Pier 60 NYC | Event Videography by Atèpá Media&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/axaqWPW7628?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;A video recap of the recent App Growth Annual conference we hosted&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-product-led-and-usage-based-nbsp&quot;&gt;Product-led and usage-based&amp;nbsp;&lt;/h3&gt;



&lt;p&gt;We’re a proud product-led growth company. The vast majority of customers adopt RevenueCat without ever talking to sales at all. And even bigger customers often start with a self-serve integration, or stick to our regular Pro plan as long as it serves their needs. Because our pricing is usage-based and we don’t have arbitrary feature gates, we don’t have to step in with heavy-handed upselling. We’ve built a product to ensure the customer is successful, and their expansion happens naturally (with some light advice and guidance from our Success org). This means the Sales team can often act as advisors, rather than negotiators. We do work out custom contracts and pricing for (very) large partners, but even those discussions are rooted in usage data and mutual value, not arm-twisting or hidden levers&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-cross-team-everything-nbsp&quot;&gt;Cross-team everything&amp;nbsp;&lt;/h3&gt;



&lt;p&gt;Our Sales team works &lt;em&gt;very&lt;/em&gt; closely with Marketing, Success, and Product. We have a bi-weekly GTM standup, a 30-person meeting that probably warrants its own blogpost, which – against all odds – seems to work at keeping us aligned. Product often hops into calls with prospects to hear firsthand their needs and challenges, explain what we are building, log the feedback for our product roadmap, and build an ongoing relationship. We partner with Success to ensure a smooth handoff after a deal closes. Marketing keeps feeding us warm, relevant pipeline with industry staples such as the&lt;a href=&quot;https://subclub.com/&quot;&gt; Sub Club&lt;/a&gt; podcast, &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps-2025/&quot;&gt;State of Subscription Apps&lt;/a&gt; report, and App Growth Annual conference. Joining our Sales team means joining a tightly integrated go-to-market squad. We love folks who are team players and realize that revenue is a team sport here&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;TikTok as a Growth Loop for Ladder: How the Fitness App Pivoted from Instagram to TikTok&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/6dYQ3AHhOiM?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Greg, the CEO of Ladder spilling the beans on their user acquisition strategy&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-state-of-sales-at-revenuecat-transparency-time&quot;&gt;The state of sales at RevenueCat (&lt;em&gt;transparency time&lt;/em&gt;)&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;400&quot; height=&quot;167&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/f88cbef4-2d00-4ece-8962-3c79ab9a6525_text.gif&quot; alt=&quot;&quot; class=&quot;wp-image-48049&quot; style=&quot;width:446px;height:auto&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Everything is awesome! Well, not everything. In the spirit of transparency, let me share exactly what we’re building, and where we’re still lagging behind a little. We’re not a fully-oiled machine, and at this stage, that’s by design. We’re still figuring some things out, and we’re okay admitting that! Here’s the candid scoop&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-a-small-growing-team&quot;&gt;A small, growing team&lt;/h3&gt;



&lt;p&gt;As of now (late 2025), you can count the dedicated Sales team on one hand with a couple fingers to spare:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;A grand total of two Sales Engineers, responsible for all inbound requests, so our customers talk to a technical resource first&lt;/li&gt;



&lt;li&gt;A single Strategic Account Manager who manages big customer commercial relationships, both through the sales process &lt;em&gt;and&lt;/em&gt; after the deal closes (+ renewals)&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;So if you’ve ever wanted to join a startup early in the go-to-market buildup, but are a little too risk-averse to join a fresh YC graduate, this is your shot. We very clearly have ‘product market fit’ (we power in-app purchases for tens of thousands of apps, including the likes of ChatGPT), but there’s virtually no legacy process to worry about or big org chart to navigate. On the flip side, this means we’re building a lot of things from scratch: playbooks, reporting cadence, enablement materials, you name it. It’s greenfield territory with a ton of intent and market recognition already in place&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-heavy-inbound-light-outbound-for-now&quot;&gt;Heavy inbound, light outbound (for now)&lt;/h3&gt;



&lt;p&gt;We currently get more form fills and high-potential signups than we have capacity to handle to the level of service we’d like. That’s why we’re hiring! Our rare outbound efforts are very targeted, and based on deep account understanding: RevenueCat as a platform doesn’t really fit an outbound approach, unless we’re very confident that somebody is experiencing a ‘&lt;a href=&quot;https://meddicc.com/resources/the-necessity-of-a-compelling-event&quot;&gt;compelling event&lt;/a&gt;’ (the “Why now?” for adopting RevenueCat)&lt;/p&gt;



&lt;p&gt;We expect some change in that regard starting next year, as we have very exciting products in the pipeline that don’t require prospects to adopt &lt;em&gt;all&lt;/em&gt; of RevenueCat. Maybe that’ll involve a personalized note highlighting a specific insight, engaging via our community events, or something totally new and unique that you come up with. What it &lt;em&gt;won’t&lt;/em&gt; be is a spammy cold pitch. The ethos remains the same: &lt;strong&gt;thoughtful, helpful, and value-driven in every interaction&lt;/strong&gt;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-still-optimizing-our-process&quot;&gt;Still optimizing our process&lt;/h3&gt;



&lt;p&gt;Since our sales motion has always been relatively light, we’re still refining it. We know there are some inefficiencies in how leads flow through, and how we transition customers from interested to implemented&lt;/p&gt;



&lt;p&gt;We have areas to work on, and we expect anyone joining the team to uncover some more. For example, one challenge is ensuring we engage the right stakeholders (including the business decision-makers) when a highly-technical team trials our product, &lt;em&gt;without&lt;/em&gt; slowing down their technical evaluation. We’re experimenting with ways to do this better and we expect new team members to have a say in shaping those solutions.&lt;/p&gt;



&lt;p&gt;Another area we’re formalizing is our sales playbook: Mapping out common customer scenarios and the best practices to guide them. If you love creating structure and repeatable processes, you’ll have plenty of opportunity to flex that muscle here! And if you prefer a bit of chaos and learning as you go, well… you’ll feel right at home too. We certainly have some ‘build the plane while flying it’ moments!&lt;/p&gt;



&lt;p&gt;In short, our state is ‘early-stage sales org finding its groove’, supported by a product with massive traction, new feature with massive potential, and a company-wide determination to get this right&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-what-s-next&quot;&gt;What’s next&lt;/h3&gt;



&lt;p&gt;We’ve been doing a few things to level up our sales motion:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;We’ve invested in great tooling (Gong for call and account insights, Clay for enrichment and automation, Scratchpad to easily understand pipeline and progress)&lt;/li&gt;



&lt;li&gt;We’re working on tightening the feedback loop with Product, as (especially with some new launches on the horizon) our joint success will depend on systematically funneling the learnings from sales calls into product decisions and vice versa&lt;/li&gt;



&lt;li&gt;We’re also defining clearer interfaces between Sales Engineering, Account Execs, Success, and Technical Account Managers (who handle implementations and post-sales tech support), so everyone knows who does what at each stage of the customer journey (and our customers don’t feel bounced around)&lt;/li&gt;



&lt;li&gt;At the same time, we’re very deliberately not copy-pasting some standard SaaS enterprise playbook. We want to grow in a way that stays true to our values and unique model. That means no aggressive quarter-end fireworks, no rush to close contracts by a certain date, no ‘whatever it takes’ mis-selling. We’d rather miss a target than push a bad fit. It also means keeping our empathy for developers front and center&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;If that resonates with you, here are the opportunities:&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-meet-the-roles-hiring-for-the-next-phase-of-revenuecat-sales&quot;&gt;Meet the roles: hiring for the next phase of RevenueCat Sales&lt;/h2&gt;



&lt;p&gt;To support and accelerate everything I described above, we’re growing our Sales team. Specifically, we’re hiring for two key roles right now, and expect to further double the team in the first half of 2026.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Those roles (all remote!):&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-senior-sales-engineer&quot;&gt;Senior Sales Engineer&lt;/h3&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“I never imagined I’d be working in sales, but that’s because I didn’t know sales orgs like what we’re building at RevenueCat existed. We really are different. I get to help some of the biggest and best apps every day, and without doing anything even remotely sales-ey.” — Chris Free, Sales Engineering Manager&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;You’ll be the technical backbone of our sales motion: part problem-solver, part teacher, part developer whisperer, joining &lt;a href=&quot;https://www.linkedin.com/in/andres-solleiro/&quot;&gt;Andrés&lt;/a&gt; (Sales Engineer) and &lt;a href=&quot;https://www.linkedin.com/in/chrisfree/&quot;&gt;Chris&lt;/a&gt; (Sales Engineering Manager). Many of our customers are engineers in product teams at some of the world’s biggest apps, and your job is to help them understand exactly how RevenueCat fits into their stack. You’ll demo, prototype, debug, and advise, sometimes all in one call. It’s perfect for someone who has a decent amount of sales or solutions engineering experience, has built mobile apps before, loves talking shop, and wants to spend their day helping other developers ship faster and make more money&lt;br&gt;&lt;br&gt;👉&lt;a href=&quot;https://jobs.ashbyhq.com/revenuecat/5cf6fa15-bae4-4fb4-aaf1-e2a82f888afb&quot;&gt; See the full role&lt;/a&gt;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-strategic-account-executive&quot;&gt;Strategic Account Executive&lt;/h3&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“&lt;/em&gt;A win for RevenueCat doesn’t have to be closing a 6 figure contract. It can also be sharing insight beyond our product capabilities or even telling a developer we are not a good fit. It is unique to work with a team that values authenticity over dollars.“ — Amanda Madaras, Strategic Account Executive&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;This isn’t your typical outbound grind. &lt;a href=&quot;https://www.linkedin.com/in/amadaras/&quot;&gt;Amanda&lt;/a&gt;, who manages Strategic Accounts for us, works with some of the world’s top apps, often ones already exploring RevenueCat, and guides them through complex evaluations and deals. You’ll join her team and collaborate closely with Sales Engineers, Marketing, and Success to turn curiosity into long-term partnerships. We’re looking for someone who can navigate both technical and commercial conversations, loves working with smart teams, and isn’t afraid to help build the playbook as we go&lt;br&gt;&lt;br&gt;👉&lt;a href=&quot;https://jobs.ashbyhq.com/revenuecat/f097b175-d40a-434f-94e1-c3771c4511ff&quot;&gt; See the full role&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Both roles are foundational: together with the Sales &lt;em&gt;teamlet&lt;/em&gt; we have today, these hires will help define how we sell, how we collaborate, and how we continue to grow without losing the developer-first DNA that got us here. If you’re excited by the idea of joining early, building the motion alongside us, and having an outsized impact, now’s the time&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Product-market fit for subscription apps is a moving target]]></title><description><![CDATA[How to find PMF at every stage of growth]]></description><link>https://www.revenuecat.com/blog/growth/product-market-fit-subscription-apps/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/product-market-fit-subscription-apps/</guid><pubDate>Thu, 06 Nov 2025 18:09:09 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Finding-your-product-market-fit_-A-guide-for-subscription-apps-1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Every startup dreams of one thing: &lt;strong&gt;product-market fit&lt;/strong&gt;. Sure, they probably have a few ‘teeth falling out’ anxiety dreams along the way (especially when a product is launching) but ultimately we’re all chasing customers who love the product. And when you nail product-market fit? The feeling is electric. Customers stick around, they tell others about your app, and growth, while not effortless, is certainly easier.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;There’s a certain buzz to product-market fit (PMF), the kind you see in apps that have clearly nailed it: Strava, Calm, TikTok.&lt;/p&gt;



&lt;p&gt;But what &lt;em&gt;is&lt;/em&gt; product-market fit? And how do you go from a vague, dreamy concept to actually knowing whether you the right ‘fit’ or not?&lt;/p&gt;



&lt;p&gt;That’s exactly what we’re diving into today. Consider this your one-stop guide to everything product-market fit for subscription apps:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;What is product-market fit, and why do you need it?&lt;/li&gt;



&lt;li&gt;Where does it fit into an app’s growth lifecycle? (Hint: not just at the start)&lt;/li&gt;



&lt;li&gt;How do you measure and validate whether you have product-market fit?&lt;/li&gt;



&lt;li&gt;How do you achieve product-market fit?&lt;/li&gt;



&lt;li&gt;What comes after finding it?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Without PMF, efforts in marketing, user acquisition, and other &lt;a href=&quot;https://www.revenuecat.com/blog/growth/grow-your-app-with-revenuecat-an-intro-for-app-marketers/&quot;&gt;growth strategies&lt;/a&gt; are far less effective — and can even lead to unsustainable scaling. We’ll wrap up by exploring how to balance growth with product-market fit, so you’re focusing on the right priorities at the right time.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-is-product-market-fit&quot;&gt;What is product-market fit?&lt;/h2&gt;



&lt;p&gt;The less romanticized definition of product-market fit is simple: it’s when &lt;strong&gt;your app’s value proposition aligns with the needs or desires of a well-defined target market&lt;/strong&gt;, creating a product that satisfies strong demand&lt;strong&gt;.&lt;/strong&gt; In other words, you’ve found your gap in the market, and subscribers not only buy in, but they stick around.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;532&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-3-1024x532.png&quot; alt=&quot;&quot; class=&quot;wp-image-48022&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-3-1024x532.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-3-300x156.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-3-768x399.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-3-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-3-77x40.png 77w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-3-696x361.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-3-560x291.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-3-840x436.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-3-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-3-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-3.png 1306w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-why-should-i-care-about-product-market-fit&quot;&gt;Why should I care about product-market fit?&lt;/h3&gt;



&lt;p&gt;I’d go so far as to say that every major profitable subscription app either has or has had product-market fit. It’s crucial for growth, especially in crowded markets where standing out is harder than ever. PMF is often the &lt;strong&gt;first real indicator of long-term potential&lt;/strong&gt;, validating that people actually need, or want, what you’re building.&lt;/p&gt;



&lt;p&gt;Still skeptical? Consider this: if you’re looking to &lt;a href=&quot;https://www.revenuecat.com/blog/growth/mobile-app-funding/&quot;&gt;fundraise rather than bootstrap&lt;/a&gt;, investors are more likely to back a startup with clear PMF. It shows you can retain users — and in a subscription model, that signals strong growth potential.&lt;/p&gt;



&lt;p&gt;Even if raising capital — which is increasingly difficult — isn’t your goal, you want to ensure you’re onto something before sinking all your hard-earned money into an app. A PMF-focused approach forces you to &lt;strong&gt;understand your audience from day one&lt;/strong&gt; and build something they genuinely can’t live without.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://subclub.com/episode/turning-a-side-project-into-a-six-figure-subscription-business-eric-duffett-shot-pattern&quot;&gt;Eric Duffet&lt;/a&gt;, a school teacher turned app developer, illustrates the risks of skipping PMF. His first app, essentially “meditation for golf”, took five years of development, content creation, and outreach to over 300 instructors. Yet he discovered (too late) that golfers simply didn’t want it. His second app, &lt;a href=&quot;https://shotpattern.app/&quot;&gt;Shot Pattern&lt;/a&gt;, took a different approach: he shared the concept online, discussed it on Twitter, and watched trialists — and even professional golfers — interact in real time. Those interactions were his signal: he was on the right track.&lt;/p&gt;



&lt;p&gt;Too often, apps try to skip this phase, chasing growth too early. Eric’s story is a warning: without product-market fit, there’s no meaningful or sustainable growth.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-where-does-pmf-fit-into-an-app-s-growth-lifecycle&quot;&gt;Where does PMF fit into an app’s growth lifecycle?&lt;/h2&gt;



&lt;p&gt;You should always be thinking about product-market fit on some level, but it’s most important on specific occasions:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;In early stages of app development&lt;/li&gt;



&lt;li&gt;When market shifts occur&lt;/li&gt;



&lt;li&gt;When consumer needs change, or you need to expand audience&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-in-early-stages-of-app-development&quot;&gt;In early stages of app development&lt;/h3&gt;



&lt;p&gt;For early-stage apps, your first growth goal should be finding product-market fit. That’s your priority before getting caught up in optimizing user acquisition, pricing, A/B tests, or other ‘growth hacks’. Those tactics might give small boosts, but they won’t truly move the needle if you haven’t nailed PMF.&lt;/p&gt;



&lt;p&gt;It’s important to clarify: focusing on PMF doesn’t mean piling on features. &lt;a href=&quot;https://www.linkedin.com/in/rosie-hoggmascall/&quot;&gt;Rosie Hoggmascall&lt;/a&gt; put it perfectly in one of her &lt;a href=&quot;https://growthdives.com/&quot;&gt;Growth Dives&lt;/a&gt; newsletters: &lt;strong&gt;the best products do one thing extremely well&lt;/strong&gt;. Early-stage startups need to figure out what that one thing is and double down on it.&lt;/p&gt;



&lt;p&gt;Take &lt;a href=&quot;https://www.revenuecat.com/customers/ladder-revenuecat-case-study/&quot;&gt;Ladder&lt;/a&gt;, the workout app. Their focus is simple: help busy people work out efficiently and track progress, without the hassle of planning. They continually refine that core experience, instead of endlessly adding features.&lt;/p&gt;



&lt;p&gt;Another example is &lt;a href=&quot;https://talkingparents.com/&quot;&gt;TalkingParents&lt;/a&gt;. While now a multi-feature app, it &lt;a href=&quot;https://subclub.com/episode/from-consultancy-to-10m-in-arr-vince-mayfield-talking-parents&quot;&gt;started with a single goal&lt;/a&gt;: helping divorced parents coordinate and care for their children without conflict. Expansion only came later, once the core problem (and feature) was optimal.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;What matters less is polish or design perfection. In an &lt;a href=&quot;https://subclub.com/episode/from-consultancy-to-10m-in-arr-vince-mayfield-talking-parents&quot;&gt;interview with Vince Mayfield, CEO of TalkingParents&lt;/a&gt;, Jacob Eiting, RevenueCat CEO, highlighted that product-market fit is demonstrated when your product grows despite problems like technical debt or lack of monetization.&lt;/p&gt;



&lt;p&gt;TL;DR: early on, double down on PMF by focusing on what makes your app different. Prioritize value over perfection, and resist the temptation to chase features.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-when-market-shifts-occur&quot;&gt;When market shifts occur&lt;/h3&gt;



&lt;p&gt;Later-stage apps might think they’re in the clear, with product-market fit achieved and growth mode engaged. But PMF is fickle.&lt;strong&gt; It can shift as competitors emerge or external factors change.&lt;/strong&gt; &lt;a href=&quot;https://subclub.com/episode/how-to-not-screw-up-switching-your-app-to-subscriptions-matt-ronge-astropad&quot;&gt;Matt Ronge, CEO of Astropad&lt;/a&gt;, experienced this firsthand: when Apple launched Sidecar — a built-in Mac-to-iPad display — Astropad’s original PMF (helping users connect their Mac and iPad as a second screen to draw) vanished &lt;em&gt;overnight&lt;/em&gt;. They had to pivot from basic mirroring to offering a pro workflow for power users, something Apple didn’t provide, essentially creating a niche for themselves.&lt;/p&gt;



&lt;p&gt;At the time of writing, many apps face a similar challenge, but the competitor culprit is AI. &lt;a href=&quot;https://www.revenuecat.com/blog/company/the-state-of-subscription-apps-2025-launch/&quot;&gt;AI has fueled a surge of new competitors&lt;/a&gt; and made users rely on LLMs for tasks like personalized workout plans, recipe recommendations, or, in my case, analyzing photos of my garden to learn how to prune plants.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=fDJ5qzjSZXI&quot;&gt;Duolingo&lt;/a&gt; provides another example. As more people turn to AI to create language-learning plans and practice, AI-powered language apps have exploded. In response, Duolingo is continuously testing and exploring ways to integrate AI into their platform, adjusting their offerings to stay competitive.&lt;/p&gt;



&lt;p&gt;Just like Astropad, apps now need to go back to the drawing board to identify what AI can’t solve. For example, I’d pay for an app that helps me map my garden, schedule tasks based on weather, or links to a backyard camera to monitor plant health. But simply identifying a plant and telling me how to prune it? That’s no longer enough.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-when-consumer-needs-change-or-you-need-to-expand-your-audience&quot;&gt;When consumer needs change, or you need to expand your audience&lt;/h3&gt;



&lt;p&gt;Even if it’s not due to a competitor, customers’ wants and needs evolve over time. When that happens, it’s time to go back to basics and ask:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;How can you ensure your product still adds value for your current audience?&lt;/li&gt;



&lt;li&gt;Do you need to shift focus to a different audience?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Even if your product-market fit is strong, you’ll likely want to expand to new audiences, whether to reach broader demographics or explore alternative niches. Expanding to new geographies also requires re-evaluating PMF, since each market has slightly different needs.&lt;/p&gt;



&lt;p&gt;Take &lt;a href=&quot;https://www.joinladder.com/&quot;&gt;Ladder&lt;/a&gt; — their initial audience came through &lt;a href=&quot;https://subclub.com/episode/how-ladder-cracked-tiktok-and-grew-500-greg-stewart-ladder&quot;&gt;their first fitness coaches&lt;/a&gt; who joined the app. Users were deeply connected to them, willing to pay more for one-on-one guidance and the chance to meet their heroes. Ladder quickly reached $1 million ARR, but then struggled to scale further.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;After talking to countless users, both active and churned, and conducting pricing research using &lt;a href=&quot;https://www.revenuecat.com/blog/growth/guide-to-app-pricing-research-methods/&quot;&gt;the Van Westendorp model&lt;/a&gt;, they realized that offering a lower price without the expensive one-on-one coaching could help them reach the next growth stage. They needed to widen their audience to regular fitness enthusiasts — who weren’t drawn in by specific coaches, and thus weren’t willing to pay $60/month.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;This is a classic example of &lt;a href=&quot;https://mobiledevmemo.com/the-growth-trap/&quot;&gt;avoiding the growth trap&lt;/a&gt;: being willing to expand beyond your niche, even if it means removing beloved features or revisiting pricing, to reach a broader audience.&lt;/p&gt;



&lt;p&gt;So, my advice? Initially, &lt;strong&gt;focus on finding PMF with your niche&lt;/strong&gt;, then look at how to expand that audience to continue scaling, while staying specific enough in how you solve a problem that you maintain unique PMF.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-do-you-measure-and-validate-whether-you-have-product-market-fit&quot;&gt;How do you measure and validate whether you have product-market fit?&lt;/h2&gt;



&lt;p&gt;Brutal truth: &lt;strong&gt;if you’re asking, “Do we have product-market fit?” then you probably don’t.&lt;/strong&gt; That doesn’t mean you aren’t on your way; it just means you need to figure out how far off you are.&lt;/p&gt;



&lt;p&gt;It’s also not a binary state: you don’t just ‘have’ it or not.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;In early-stage startups, it’s common to see some level of PMF, but with too broad an audience. The users who join love the product, yet the company struggles to explain its value clearly up front.&lt;/p&gt;



&lt;p&gt;So how do you measure it more concretely?&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-the-classic-pmf-test&quot;&gt;1. The classic PMF test&lt;/h3&gt;



&lt;p&gt;The &lt;a href=&quot;https://pmfsurvey.com/&quot;&gt;classic PMF test, developed by Sean Ellis&lt;/a&gt;, is to ask your customers:&lt;/p&gt;



&lt;p&gt;How disappointed would you be if you could no longer use the product/service?&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Very disappointed&lt;/li&gt;



&lt;li&gt;Somewhat disappointed&lt;/li&gt;



&lt;li&gt;Not disappointed&lt;/li&gt;



&lt;li&gt;I no longer use the app&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The rule of thumb is that &lt;strong&gt;if 40% of your customers answer ‘very disappointed,’ you have PMF&lt;/strong&gt;. You follow up that question with “Could you explain your answer?”&lt;/p&gt;



&lt;p&gt;Now, who do you ask: trialists? Downloads? Existing subscribers?&lt;/p&gt;



&lt;p&gt;I always recommend starting with your users’ main &lt;em&gt;aha!&lt;/em&gt; moment and using that as your cut-off point. For example, if it usually takes seven days for someone to really understand and love your app, focus on users from day seven onward.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;It’s a delicate balance: if you only ask users who’ve been on your app for two months, you might be fooling yourself into thinking you have product-market fit. Ask too early, like before the &lt;em&gt;aha!&lt;/em&gt; moment, and you risk painting a negative picture.&lt;/p&gt;



&lt;p&gt;My number one tip: ask additional questions or combine survey findings with other data, like onboarding metrics. With enough responses (you’ll need at least a few hundred), you can narrow down where PMF exists — e.g. maybe it’s only with older users, or users who use your app for a very specific reason.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-net-promoter-score-nps-and-word-of-mouth&quot;&gt;2. Net Promoter Score (NPS) and word-of-mouth&lt;/h3&gt;



&lt;p&gt;There are several signals to gauge how close (or far) you are from product-market fit. One key indicator is a &lt;a href=&quot;https://www.revenuecat.com/blog/growth/net-promoter-score-nps-for-subscription-apps/&quot;&gt;Net Promoter Score (NPS) survey&lt;/a&gt;. Asking users whether they would recommend your app can reveal a lot about whether you’ve found your fit.&lt;/p&gt;



&lt;p&gt;Ladder found that when they combined the classic PMF question with NPS, subscribers who said they’d be “somewhat disappointed” if they lost the app had much lower NPS than those who said they’d be “very disappointed.” The two metrics correlated strongly. Ladder then used insights from the “very disappointed” group to guide focus, while learning from the “somewhat disappointed” group where there was room for improvement.&lt;/p&gt;



&lt;p&gt;With NPS, you can also segment responses to understand why users do or don’t promote your app. Tracking word-of-mouth acquisition is another powerful PMF signal: if 15%+ of your new users come through referrals, that’s a strong indicator that your app resonates with its audience.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-review-rate-and-overall-rating&quot;&gt;3. Review rate and overall rating&lt;/h3&gt;



&lt;p&gt;I find review rate (how quickly your app is reviewed by users after download or prompting a review) and overall ratings to be a good indicator of how close you are to finding PMF. You can initially &lt;a href=&quot;https://www.revenuecat.com/blog/engineering/how-to-hack-your-app-store-ratings/#h-hacking-app-store-ratings&quot;&gt;boost your review rate by timing it close to your &lt;em&gt;aha! &lt;/em&gt;moment&lt;/a&gt; or prompting users to leave a review after interacting with key features&lt;/p&gt;



&lt;p&gt;However, if, after all that optimization, you’re still seeing a much slower ratings-to-downloads ratio compared to competitors — commonly referred to as &lt;a href=&quot;https://appfigures.com/support/kb/737/what-is-dpr-and-why-its-important-for-app-store-optimization&quot;&gt;DPR&lt;/a&gt;, which measures the number of downloads needed to get one new rating — it may indicate lower PMF, especially when coupled with a low average rating.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-4-engagement-and-retention-metrics&quot;&gt;4. Engagement and retention metrics&lt;/h3&gt;



&lt;p&gt;Finally, engagement and &lt;a href=&quot;https://www.revenuecat.com/blog/growth/monthly-renewal-rate-in-app-subscriptions/&quot;&gt;retention data&lt;/a&gt; are another helpful indicator of PMF:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Are subscribers using your app frequently?&lt;/li&gt;



&lt;li&gt;Are they renewing?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;I recommend benchmarking performance against your category with &lt;a href=&quot;https://www.revenuecat.com/blog/growth/subscription-metrics-mobile-apps/&quot;&gt;subscription metrics&lt;/a&gt; like month-one renewals and annual renewal rates. For engagement, it’s important to consider your specific use case. I’ve spoken to apps that found their best subscribers — those who loved the app and used it for years — didn’t necessarily use it as frequently as other users. This highlights the need to &lt;strong&gt;understand the use case you solve best&lt;/strong&gt;, then ensure you measure the right frequency of use.&lt;/p&gt;



&lt;p&gt;In &lt;a href=&quot;https://subclub.com/episode/vc-funding-vs-bootstrapping-for-subscription-apps-martin-siniawski-podcast-app&quot;&gt;Martin Siniawski’s &lt;em&gt;Sub Club&lt;/em&gt; episode&lt;/a&gt;, he notes that focusing initially on monthly subscribers rather than optimizing for annual subscriptions can help you learn faster and force you to demonstrate real, repeatable value. It also allows you to interview churned customers earlier, uncovering why they didn’t retain and what caused them to churn.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-5-willingness-to-pay&quot;&gt;5. Willingness to pay&lt;/h3&gt;



&lt;p&gt;Technically, willingness to pay is separate from product–market fit, however some apps intentionally start with a hard paywall to &lt;strong&gt;validate whether users are willing to pay&lt;/strong&gt; and to attract higher-quality subscribers. Think of it as testing product-market fit in a very bold way!&lt;/p&gt;



&lt;p&gt;A low willingness to pay may suggest you haven’t yet nailed your value proposition — we’ve seen this with the Ladder example, where its pricing wasn’t initially right for a broader audience, and identifying the optimal price point was key to scaling. But keep in mind there are many ways to &lt;a href=&quot;https://www.revenuecat.com/blog/growth/customer-validation-subscription-app/&quot;&gt;validate willingness to pay before building your app&lt;/a&gt;.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-signals-you-ve-found-product-market-fit-nbsp&quot;&gt;Signals you’ve found product-market fit&amp;nbsp;&lt;/h2&gt;



&lt;p&gt;Although PMF has several tangible metrics, it’s rarely black and white.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Identifying product-market fit means looking at a combination of signals that suggest you’re on the right track:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Users come back on their own, not just when prompted&lt;/li&gt;



&lt;li&gt;People stick around month after month, even if there are bugs&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Users tell others about your app&lt;/li&gt;



&lt;li&gt;They’re eager to share feedback and input&lt;/li&gt;



&lt;li&gt;People are willing to pay, not just use it for free or heavily discounted&lt;/li&gt;



&lt;li&gt;Your retention curve flattens relatively quickly (e.g. after 4–8 weeks)&lt;/li&gt;



&lt;li&gt;Users reach their &lt;em&gt;aha!&lt;/em&gt; moment without excessive guidance&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-do-you-achieve-product-market-fit&quot;&gt;How do you achieve product-market fit?&lt;/h2&gt;



&lt;p&gt;Often the very metrics you track to identify PMF will reveal what’s driving product-market fit, so if you’ve done NPS surveys or looked at reviews, you’re already halfway there.&lt;/p&gt;



&lt;p&gt;Developing a deep understanding of why those signals matter helps you better define the problem you’re solving and connect every improvement you make to your app and user experience back to that core insight.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://andres.barre.to/2020/11/08/how-to-get-to-product-market-fit/&quot;&gt;Andres Barreto recommends the following framework&lt;/a&gt; for improving product-market fit:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Discover pain through user research&lt;/li&gt;



&lt;li&gt;Create experiments to observe customer behavior&lt;/li&gt;



&lt;li&gt;Kill ideas or experiments that don’t work&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;&lt;a href=&quot;https://open.spotify.com/episode/0Jns928ranD8aynlZU0jwr?si=66a1846dcc4d4a6e&amp;amp;nd=1&amp;amp;dlsi=2742c27bd2824fd3&quot;&gt;Early validation is so important&lt;/a&gt; in getting to product-market fit, and Andres’s framework helps you do this by focusing on really understanding and testing your assumptions in the beginning. Let’s break it down.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-discovering-pain-through-user-research&quot;&gt;1. Discovering pain through user research&lt;/h3&gt;



&lt;p&gt;Product-market fit starts with &lt;strong&gt;finding problem-solution fit&lt;/strong&gt;. You need to identify the &lt;em&gt;problem&lt;/em&gt; you can solve better than anyone else.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;854&quot; height=&quot;522&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-2.png&quot; alt=&quot;&quot; class=&quot;wp-image-48020&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-2.png 854w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-2-300x183.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-2-768x469.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-2-50x31.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-2-65x40.png 65w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-2-696x425.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-2-560x342.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-2-484x296.png 484w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-2-772x472.png 772w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-2-80x49.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-2-48x29.png 48w&quot; sizes=&quot;auto, (max-width: 854px) 100vw, 854px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Take &lt;a href=&quot;https://subclub.com/episode/finding-product-market-fit-by-unbundling-photoshop-matthieu-rouif-photoroom&quot;&gt;Photoroom as an example.&lt;/a&gt; When they first started, they hyper-focused on one pain point — a single &lt;a href=&quot;https://www.revenuecat.com/blog/growth/what-drives-users-to-pay-jobs-to-be-done/&quot;&gt;job-to-be-done&lt;/a&gt;: removing backgrounds from photos, and doing that better than any other solution out there. What didn’t they do? Try to be easier than Photoshop at everything. That would’ve been &lt;strong&gt;focusing on a solution, not a problem&lt;/strong&gt; (aka, a big mistake).&lt;/p&gt;



&lt;p&gt;From there, they identified patterns in their users’ challenges and expanded thoughtfully by building a suite of tools for easy, on-the-go photo editing.&lt;/p&gt;



&lt;p&gt;With this, there are two essential considerations:&amp;nbsp;&lt;/p&gt;



&lt;p&gt;The first is how big the problem is. We’re looking for &lt;a href=&quot;https://www.revenuecat.com/blog/growth/how-subscription-apps-can-become-painkillers/&quot;&gt;must-solve, major pain points&lt;/a&gt;, not nice-to-haves. The second is how big the audience is. The basic maths works as follows:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Size of target audience (TAM — total addressable market)&lt;/strong&gt;: don’t confuse everyone who has the problem with your potential market; only the &lt;em&gt;desperate-to-solve&lt;/em&gt; segment counts as your true audience&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;% you think you can obtain (SAM — serviceable available market):&lt;/strong&gt; this depends on how competitive your market is, but you can start by modeling scenarios between 2% and 15%&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.revenuecat.com/glossary/#arpu-average-revenue-per-user&quot;&gt;&lt;strong&gt;Average revenue per subscriber (ARPU)&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; Estimate what you expect to earn per paying user&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;This is a useful way to estimate your potential early on and gauge how quickly you’ll need to expand your market focus. For example, I worked with a niche app in a smaller country that wasn’t charging much. A quick calculation showed that while they still had room to grow locally, they would eventually need to adjust pricing for sustainability and plan to expand internationally.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-create-experiments-to-observe-your-customers-behavior&quot;&gt;3. Create experiments to observe your customers’ behavior&lt;/h3&gt;



&lt;p&gt;Once you’ve identified the problem, the next step is to experiment, learning both how to solve it best and how to communicate your solution so it truly resonates. The goal is to learn fast and fail fast, &lt;a href=&quot;https://www.revenuecat.com/blog/growth/customer-validation-subscription-app/&quot;&gt;validating as much as possible without building&lt;/a&gt; full features.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;I once spoke with an app that had spent two years building and still wasn’t sure if their main, expensive feature was something people would actually pay for. Tools like prototypes and painted door tests can help reduce this risk and accelerate learning.&lt;/p&gt;



&lt;p&gt;This also explains why it’s hard to say how long the PMF phase will last. It depends how quickly you can develop a &lt;strong&gt;deep understanding of the right problem and audience&lt;/strong&gt;, and how many misses it takes before finding the solution and approach that truly works.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-kill-ideas-or-experiments-that-did-not-work-nbsp&quot;&gt;3. Kill ideas or experiments that did not work&amp;nbsp;&lt;/h3&gt;



&lt;p&gt;In this phase, it’s crucial not to be afraid to ‘kill your darlings’. Some ideas and solutions simply won’t work or resonate, and there’s always a lot of pivoting early on.&lt;/p&gt;



&lt;p&gt;This approach is particularly effective when you’re still building your product. But sometimes your app is already live, with a wide audience and some subscribers retaining, while others aren’t. In that case, you may not need to change the product itself; rather, &lt;strong&gt;you need to better understand who your audience is.&lt;/strong&gt; Remember, product-market fit requires a match from both sides.&lt;/p&gt;



&lt;p&gt;During this challenging phase, it’s easy to get distracted. One major distraction is fundraising and the belief that more capital will solve PMF. But raises come with pressure, which can lead to endless feature building or heavy investment in paid acquisition, only to see high churn.&lt;/p&gt;



&lt;p&gt;Another distraction is chasing short-term growth hacks. These may produce temporary spikes, but they won’t fix fundamental product issues.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Next, we’ll dive into how to balance growth with achieving true product-market fit.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-can-early-stage-apps-balance-product-market-fit-with-growth&quot;&gt;How can early-stage apps balance product-market fit with growth?&lt;/h2&gt;



&lt;p&gt;The most common risk when seeking PMF is &lt;strong&gt;focusing on growth too early&lt;/strong&gt;.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;This often comes from investor pressure or a few early wins that get you overly excited (we’ve all been there). You rush into paid ads, burn through your run rate, and watch users churn, then panic to acquire more. &lt;a href=&quot;https://www.revenuecat.com/blog/growth/eric-seufert-sub-club-podcast-2025/&quot;&gt;Eric Seufert&lt;/a&gt; refers to this as the&lt;em&gt; growth trap&lt;/em&gt;. Growth becomes like running on a treadmill with the speed constantly increasing: you might keep up at first, but eventually, you fall flat as you lose more customers than you gain.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Before scaling, you need a basic level of retention and product-market fit&lt;/strong&gt;. Even if it’s just with a niche audience or a minimum viable product, this ensures that as you grow, you can learn, optimize, and improve your product.&lt;/p&gt;



&lt;p&gt;Once you’ve established that foundation, growth isn’t your sole focus. Instead, you can follow Seufert’s solution to the growth trap: the &lt;a href=&quot;https://mobiledevmemo.com/the-growth-trap/&quot;&gt;growth sandwich&lt;/a&gt; (sounds way more fun than falling off a treadmill). The growth sandwich layers paid marketing and product optimization to balance expanding your audience beyond your initial niche, while refining the product for them.&lt;/p&gt;



&lt;p&gt;The flip side is the ‘one more feature’ trap. It’s like planning a treadmill workout but spending 30 minutes fetching your water bottle, headphones, and changing outfit — your intentions are there, but you never actually start. If you get stuck endlessly optimizing for a tiny niche, you miss growth. You need a sufficiently large cohort to truly learn what works and what doesn’t.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-comes-after-product-market-fit&quot;&gt;What comes after product-market fit?&lt;/h2&gt;



&lt;p&gt;So you’ve nailed product-market fit. What happens then?&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-product-model-fit&quot;&gt;Product-model fit&lt;/h3&gt;



&lt;p&gt;The funny thing is, having product-market fit doesn’t automatically mean people will pay for your product. So the next step is to build a monetization model around your product that matches usage and that audience.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;662&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-4-1024x662.png&quot; alt=&quot;&quot; class=&quot;wp-image-48024&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-4-1024x662.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-4-300x194.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-4-768x497.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-4-1536x994.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-4-50x32.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-4-62x40.png 62w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-4-696x450.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-4-560x362.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-4-458x296.png 458w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-4-730x472.png 730w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-4-80x52.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-4-48x31.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-4.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;This is also known as &lt;strong&gt;product-model fit&lt;/strong&gt;, and it’s more than just your pricing strategy. It is about improving your business model. It includes your packaging, your funnel (web-to-app vs. in-app), trial vs. no-trial, &lt;a href=&quot;https://www.revenuecat.com/blog/growth/should-your-app-stop-offering-free-trials/&quot;&gt;freemium vs. premium&lt;/a&gt; only. The process typically starts with product-market fit and retention, then moves into product-model fit.&lt;/p&gt;



&lt;p&gt;Pricing, packaging, and funnel decisions are hard to finalize before PMF. For example, Ladder initially had a high proportion of monthly subscribers. Once they achieved a second phase of product-market fit with a broader audience, they optimized their model and converted more customers to annual subscriptions.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-product-market-channel-fit&quot;&gt;Product/market-channel fit&lt;/h3&gt;



&lt;p&gt;Once your retention metrics are strong and you’ve optimized monetization, the next focus is product/market-channel fit. By this point, you’ve likely tested several channels but struggled to find one with a good enough payback period to scale.&lt;/p&gt;



&lt;p&gt;Optimizing for PMF and monetization helps by &lt;a href=&quot;https://www.revenuecat.com/blog/growth/what-is-lifetime-value-ltv-apps/&quot;&gt;increasing the LTV of your subscribers&lt;/a&gt;, but you still need to &lt;strong&gt;identify which channels can drive profitable growth&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;As &lt;a href=&quot;https://www.linkedin.com/in/gessicabicego/&quot;&gt;Gessica Bicego&lt;/a&gt; (CMO of Paired and former Head of Growth at Blinkist) &lt;a href=&quot;https://subclub.com/episode/brand-marketing-product-market-fit-app-growth-gessica-bicego-paired&quot;&gt;has seen firsthand&lt;/a&gt;, channel fit is real and highly app-specific. For Paired, a relationship app, social media became the ideal growth engine, driving rapid scale. For Blinkist, a learning app with a different audience and use case, TikTok never became a repeatable growth channel. After months of testing, Taboola and Outbrain emerged as key acquisition drivers.&lt;/p&gt;



&lt;p&gt;Her advice: carefully weigh time-to-impact, resource requirements, and creative demands when deciding which channels to test.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-product-market-fit-the-ongoing-journey&quot;&gt;Product-market fit: the ongoing journey&lt;/h2&gt;



&lt;p&gt;Product-market fit isn’t just something you find at the start of your journey — you need to continually revisit it as your market, competitors, and audience evolve. It’s what makes all your other growth efforts effective, and helps you avoid scaling a leaky bucket or falling into the growth trap.&lt;/p&gt;



&lt;p&gt;For early-stage apps, this means focusing on &lt;strong&gt;deeply understanding your audience&lt;/strong&gt;, &lt;strong&gt;solving one problem exceptionally well&lt;/strong&gt;, and &lt;strong&gt;validating that people truly value and retain your product&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;For later-stage apps, it means &lt;strong&gt;staying alert to market shifts &lt;/strong&gt;— whether from new competitors, AI changing user behavior, or expansion into new audiences — and &lt;strong&gt;being willing to return to the fundamentals&lt;/strong&gt; when needed.&lt;/p&gt;



&lt;p&gt;Once you’ve achieved product-market fit, you can layer on product-model fit and product/market-channel fit, building growth and monetization on a solid foundation. Without PMF, every feature, ad, and experiment is just noise. Focus on creating something people can’t imagine losing, and the growth will follow.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Turn support into growth by integrating RevenueCat with Intercom or Zendesk]]></title><description><![CDATA[Meet the new Intercom and Zendesk integrations]]></description><link>https://www.revenuecat.com/blog/company/integrating-revenuecat-with-intercom-or-zendesk/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/company/integrating-revenuecat-with-intercom-or-zendesk/</guid><pubDate>Wed, 05 Nov 2025 16:23:34 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Customer-Center-Integrations-4-scaled.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Support teams handle critical customer moments every day. When a user runs into a billing issue or can’t access a feature they paid for, the clock starts ticking.&lt;/p&gt;



&lt;p&gt;Without subscription context, every ticket looks the same. Agents don’t know who’s trialing, who’s canceled, or who’s been paying for months. That means more guesswork, longer replies, and frustrated customers.&lt;/p&gt;



&lt;p&gt;RevenueCat’s new integrations for &lt;a href=&quot;https://www.intercom.com/app-store/?app_package_code=revenuecat-customer-profiles-2oan&quot;&gt;&lt;strong&gt;Intercom&lt;/strong&gt;&lt;/a&gt; and &lt;a href=&quot;https://www.zendesk.com/marketplace/apps/support/1138597/revenuecat-customer-profiles/&quot;&gt;&lt;strong&gt;Zendesk&lt;/strong&gt;&lt;/a&gt; change that. They bring the full subscription story, including plan, renewal status, and purchase history, directly into your support tools.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-support-without-context-is-expensive&quot;&gt;&lt;strong&gt;Support without context is expensive&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;When you can’t see a customer’s history, providing the best support possible gets tricky.&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;A canceled subscriber and a free user both say “the app stopped working.”&lt;/li&gt;



&lt;li&gt;A user mid-trial and one past renewal both ask “why was I charged?”&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Without visibility, you have to waste time digging for data or give the wrong answer. That’s how you lose customers.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-access-subscription-data-where-you-work&quot;&gt;&lt;strong&gt;Access subscription data where you work&lt;/strong&gt;&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;640&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-0-1-1024x640.png&quot; alt=&quot;&quot; class=&quot;wp-image-47648&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-0-1-1024x640.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-0-1-300x188.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-0-1-768x480.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-0-1-1536x960.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-0-1-50x31.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-0-1-64x40.png 64w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-0-1-696x435.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-0-1-560x350.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-0-1-474x296.png 474w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-0-1-755x472.png 755w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-0-1-80x50.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-0-1-48x30.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-0-1.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The new RevenueCat Customer Profiles apps for Intercom and Zendesk pull live subscription data into every support conversation.&lt;/p&gt;



&lt;p&gt;When a ticket or chat opens, the customer’s RevenueCat profile appears in the sidebar. You can instantly see:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Subscription status (active, expired, or in trial)&lt;/li&gt;



&lt;li&gt;Purchase history and renewal details&lt;/li&gt;



&lt;li&gt;Account identifiers like email and app user ID&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;There’s no need to switch tabs or dig through dashboards. Everything loads automatically and securely in real time. Nothing is stored in Intercom or Zendesk. The data comes directly from your RevenueCat project every time a ticket loads.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;640&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-1-1-1024x640.png&quot; alt=&quot;&quot; class=&quot;wp-image-47650&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-1-1-1024x640.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-1-1-300x188.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-1-1-768x480.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-1-1-1536x960.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-1-1-50x31.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-1-1-64x40.png 64w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-1-1-696x435.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-1-1-560x350.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-1-1-474x296.png 474w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-1-1-755x472.png 755w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-1-1-80x50.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-1-1-48x30.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-1-1.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;643&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-2-1-1024x643.png&quot; alt=&quot;&quot; class=&quot;wp-image-47652&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-2-1-1024x643.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-2-1-300x188.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-2-1-768x482.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-2-1-1536x964.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-2-1-50x31.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-2-1-64x40.png 64w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-2-1-696x437.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-2-1-560x351.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-2-1-472x296.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-2-1-752x472.png 752w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-2-1-80x50.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-2-1-48x30.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/screenshot-2-1.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-work-faster-with-customer-data-at-your-fingertips&quot;&gt;&lt;strong&gt;Work faster with customer data at your fingertips&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;When support teams have full context, every conversation improves. Agents can see if an issue stems from an expired subscription or a payment error before responding. They can reassure paying users faster and guide trial users toward upgrading.&lt;/p&gt;



&lt;p&gt;Support leads can prioritize tickets from high-value customers or those at risk of churn. What used to take minutes of cross-checking now happens in seconds.&lt;/p&gt;



&lt;p&gt;This visibility makes support both efficient and empathetic. Your team knows who they’re helping and what matters to that customer.&lt;/p&gt;



&lt;p&gt;Getting started takes only a few steps.&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;In Intercom or Zendesk, open the RevenueCat Customer Profiles app&lt;/li&gt;



&lt;li&gt;Add your RevenueCat project ID and API key in the settings&lt;/li&gt;



&lt;li&gt;Open any conversation, and the customer’s RevenueCat data appears instantly in the sidebar&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;These integrations were built with the same care and security standards that RevenueCat applies across its platform.&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;All data is transmitted with TLS encryption&lt;/li&gt;



&lt;li&gt;No customer data is stored in Intercom or Zendesk&lt;/li&gt;



&lt;li&gt;Fully compliant with GDPR requirements, including data access, correction, and deletion&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Customer data is always fetched directly from your RevenueCat project and never cached elsewhere.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-support-that-drives-retention&quot;&gt;&lt;strong&gt;Support that drives retention&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;When you have revenue context at your fingertips, you can respond faster, personalize every reply, and solve problems before customers churn.&lt;/p&gt;



&lt;p&gt;That’s what it means to turn support into a growth engine. Every interaction strengthens trust and protects your recurring revenue.&lt;/p&gt;



&lt;p&gt;Connect RevenueCat with &lt;a href=&quot;https://www.intercom.com/app-store/?app_package_code=revenuecat-customer-profiles-2oan&quot;&gt;&lt;strong&gt;Intercom&lt;/strong&gt;&lt;/a&gt; or &lt;a href=&quot;https://www.zendesk.com/marketplace/apps/support/1138597/revenuecat-customer-profiles/&quot;&gt;&lt;strong&gt;Zendesk&lt;/strong&gt;&lt;/a&gt; and start resolving with revenue context.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Understanding Apple’s Retention Messaging API (and how RevenueCat can help you with it)]]></title><description><![CDATA[Apple’s new retention capability × enterprise-grade reliability (and no backend work required on your side) = 💛]]></description><link>https://www.revenuecat.com/blog/engineering/apple-retention-messaging-api/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/apple-retention-messaging-api/</guid><pubDate>Tue, 04 Nov 2025 13:37:22 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/How-RevenueCat-makes-Apples-Retention-Messaging-API-easy-2.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Apple’s new Retention Messaging API lets apps reach subscribers at the exact moment they choose to cancel, showing a message, incentive, or discount directly within the iOS subscription settings screen. This creates a new opportunity to re-engage users who might otherwise leave.&lt;/p&gt;



&lt;p&gt;Depending on your setup, your message can take one of three forms: a simple message (optionally with an image), an alternative product such as a lower-priced tier, or a promotional offer like a discount or extended trial.&lt;/p&gt;



&lt;figure class=&quot;wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-2 is-layout-flex wp-block-gallery-is-layout-flex&quot;&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;472&quot; height=&quot;1024&quot; data-id=&quot;47621&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Apple-retention-messaging-preview-2-472x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-47621&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Apple-retention-messaging-preview-2-472x1024.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Apple-retention-messaging-preview-2-138x300.png 138w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Apple-retention-messaging-preview-2-23x50.png 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Apple-retention-messaging-preview-2-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Apple-retention-messaging-preview-2-214x464.png 214w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Apple-retention-messaging-preview-2-258x560.png 258w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Apple-retention-messaging-preview-2-137x296.png 137w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Apple-retention-messaging-preview-2-218x472.png 218w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Apple-retention-messaging-preview-2-37x80.png 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Apple-retention-messaging-preview-2-22x48.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Apple-retention-messaging-preview-2.png 536w&quot; sizes=&quot;auto, (max-width: 472px) 100vw, 472px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;472&quot; height=&quot;1024&quot; data-id=&quot;47623&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Apple-retention-messaging-preview-1-472x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-47623&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Apple-retention-messaging-preview-1-472x1024.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Apple-retention-messaging-preview-1-138x300.png 138w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Apple-retention-messaging-preview-1-23x50.png 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Apple-retention-messaging-preview-1-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Apple-retention-messaging-preview-1-214x464.png 214w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Apple-retention-messaging-preview-1-258x560.png 258w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Apple-retention-messaging-preview-1-137x296.png 137w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Apple-retention-messaging-preview-1-218x472.png 218w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Apple-retention-messaging-preview-1-37x80.png 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Apple-retention-messaging-preview-1-22x48.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Apple-retention-messaging-preview-1.png 536w&quot; sizes=&quot;auto, (max-width: 472px) 100vw, 472px&quot;&gt;&lt;/figure&gt;
&lt;/figure&gt;



&lt;p&gt;If you’ve ever wanted to reach customers before they walk out the door, this API finally makes that possible. However, it also comes with tight performance limits, tricky setup requirements, and a fair amount of backend plumbing.&lt;/p&gt;



&lt;p&gt;Read on for why retention messaging matters, how it works, and how RevenueCat can take care of the painful parts for you.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-apple-s-retention-messaging-api-works&quot;&gt;&lt;strong&gt;How Apple’s Retention Messaging API works&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;When a user enters the iOS subscription management screen and taps Cancel, Apple checks whether you’ve configured a default retention message for that specific product and locale. If you have, Apple calls your backend with the subscriber’s transaction information and waits for your response. If a default message is configured for that product and locale, &lt;strong&gt;Apple gives your server under 700ms to return the message&lt;/strong&gt;, alternate product, or promotional offer.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;RevenueCat handles this entire real-time sequence for you:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Identifies the app, product, and subscriber&lt;/li&gt;



&lt;li&gt;Checks for a configured message, promotional offer, or alternate product&lt;/li&gt;



&lt;li&gt;Applies eligibility rules (storefront, subscriber age, last seen, purchase history)&lt;/li&gt;



&lt;li&gt;Returns the correct message to Apple&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;All of this happens in real time, well within Apple’s 700ms limit.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;what-implementing-the-api-yourself-looks-like&quot;&gt;What implementing the API yourself looks like&lt;/h3&gt;



&lt;p&gt;Building an Apple Retention Messaging integration from scratch requires more than just calling the API. Developers have to:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Configure default messages for every product and locale manually&lt;/li&gt;



&lt;li&gt;Maintain an always-on backend that can process Apple’s requests in under 0.7s and handle promo offer signing&lt;/li&gt;



&lt;li&gt;Keep track of which messages are configured for each locale, since Apple doesn’t store this information&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Apple only provides the raw API endpoints, leaving the orchestration, performance, and data management entirely up to the developer. It’s not overly complex, but it’s undeniably cumbersome and time-consuming to test, localize, and iterate.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;how-you-can-simplify-the-process-with-revenuecat&quot;&gt;How you can simplify the process with RevenueCat&lt;/h3&gt;



&lt;p&gt;If you don’t fancy doing the manual build and maintenance, RevenueCat can manage every part of Apple’s Retention Messaging setup and response flow for you:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Uploading messages and configuring default text for each locale&lt;/li&gt;



&lt;li&gt;Generating AI-backed translations automatically, so your retention messages are localized without manual work&lt;/li&gt;



&lt;li&gt;Monitoring message status through the Apple API&lt;/li&gt;



&lt;li&gt;Responding to Apple’s real-time requests with latency safely below 0.7s&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;You’re able to configure all your retention campaigns directly in the RevenueCat dashboard. Define messages, promotional offers, and tailor campaigns to specific user cohorts — for example, by storefront, trial status, or how long someone has been a subscriber — all without touching backend code.&lt;/p&gt;



&lt;p&gt;The retention section in the dashboard sits alongside your &lt;strong&gt;Customer Center&lt;/strong&gt; configuration, so you can manage both user-facing offers and cancellation retention messages in one place.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;getting-started-with-retention-messaging-api-in-revenuecat&quot;&gt;Getting started with Retention Messaging API in RevenueCat&lt;/h2&gt;



&lt;p&gt;Retention Messaging currently requires requesting access from Apple. You can do this quickly following our &lt;a href=&quot;https://www.revenuecat.com/docs/platform-resources/apple-platform-resources/apple-retention-messaging-api#prerequisites&quot;&gt;step-by-step guide&lt;/a&gt; in the RevenueCat docs.&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-28eJIX wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Access update&quot; text=&quot;&lt;blockquote class=&amp;quot;ml-2 border-l-4 border-border-300/10 pl-4 text-text-300&amp;quot;&gt;In April 2026, Apple has expanded access to the Retention Messaging API, with broader availability rolling out in the coming weeks. If you&apos;ve been waiting on the sidelines, now&apos;s the time to get your messages and localization set up in RevenueCat so you can ship the moment access lands.&lt;br /&gt;&lt;br /&gt;Some developers are alos seeing long wait times for production message approvals. This seems to be a delay on Apple&apos;s side and not an issue with any one app.&lt;/blockquote&gt;&quot; icon=&quot;circle-info&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;p&gt;While you’re waiting for approval, you can still prepare your messages and localization strategy now — and go live as soon as Apple grants you access.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;At the moment RevenueCat supports the following messaging types:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Text only message&lt;/strong&gt;: a simple message highlighting subscription features or benefits&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Switch-plan message&lt;/strong&gt;: suggests an alternative subscription plan that the customer could switch to, along with a short message&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Promotional-offer message&lt;/strong&gt;: offers a discounted price for continuing the subscription, either at the same tier or a different tier of service, alongside a short message&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Retention Message API supports messages with images, but RevenueCat will initially focus on text-only, switch-plan, and promotional-offer messages. Support for image-based messages may be added in the future.&lt;/p&gt;



&lt;p&gt;These messages are shown to users after they tap ‘Cancel Subscription’ on the subscription details page. On the Confirm Cancellation screen, users can either complete the cancellation, tap ‘Don’t Cancel’, or, depending on the message, redeem an offer or switch to a suggested subscription.&lt;/p&gt;



&lt;p&gt;For all of the up-to-date details on implementing these in your app using RevenueCat, checkout out our &lt;a href=&quot;https://www.revenuecat.com/docs/platform-resources/apple-platform-resources/apple-retention-messaging-api&quot;&gt;Retention Messaging API documentation&lt;/a&gt;.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[11 Lessons you’ll want to remember from App Growth Annual 2025]]></title><description><![CDATA[Scannable takeaways, snackable insights, and tactics you can ship tomorrow]]></description><link>https://www.revenuecat.com/blog/company/lessons-from-app-growth-annual-2025/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/company/lessons-from-app-growth-annual-2025/</guid><pubDate>Tue, 04 Nov 2025 13:17:54 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/RAGA-2025-wrap-up.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;If you’re looking for a rundown of the collective lessons from 30+ subscription app founders, builders, and growth experts, then you’re in the right place.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;App Growth Annual 2025 is our one-a-year gathering for people building and scaling subscription apps — a full day of live keynotes, hands-on workshops, and a little bit of chaos (the good kind). This year’s speakers spanned category leaders like Duolingo and Ladder, to fast-moving indies and growth consultants.&lt;/p&gt;



&lt;p&gt;Here’s the &lt;strong&gt;11 top takeaways on monetization, growth, and retention&lt;/strong&gt; — plus every RevenueCat product announcement.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-1-duolingo-if-users-love-your-core-product-enough-keep-it-free-and-monetize-around-it-nbsp&quot;&gt;&lt;strong&gt;1. Duolingo: If users love your core product enough, keep it free and monetize around it&amp;nbsp;&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;How do you build a product that millions use for free, but still choose to pay for? &lt;a href=&quot;https://www.linkedin.com/in/natic/&quot;&gt;Natalia Castillejo&lt;/a&gt;, Director of Product at language-learning titan, Duolingo, shared valuable lessons on creating value with freemium products. ​​&lt;/p&gt;



&lt;figure class=&quot;wp-block-pullquote&quot;&gt;&lt;blockquote&gt;&lt;p&gt;Free is core to our growth, not just our mission.&lt;/p&gt;&lt;cite&gt;&lt;a href=&quot;https://www.linkedin.com/in/natic/&quot;&gt;Natalia Castillejo&lt;/a&gt;, Director of Product — Duolingo&lt;/cite&gt;&lt;/blockquote&gt;&lt;/figure&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;figure class=&quot;wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-3 is-layout-flex wp-block-gallery-is-layout-flex&quot;&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;683&quot; data-id=&quot;47347&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Duolingo2-1024x683.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47347&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Duolingo2-1024x683.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Duolingo2-300x200.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Duolingo2-768x512.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Duolingo2-1536x1024.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Duolingo2-2048x1366.jpg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Duolingo2-50x33.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Duolingo2-60x40.jpg 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Duolingo2-696x464.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Duolingo2-560x373.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Duolingo2-444x296.jpg 444w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Duolingo2-708x472.jpg 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Duolingo2-80x53.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Duolingo2-48x32.jpg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;684&quot; data-id=&quot;47345&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S308334-1-1024x684.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47345&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S308334-1-1024x684.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S308334-1-300x200.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S308334-1-768x513.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S308334-1-1536x1026.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S308334-1-2048x1368.jpg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S308334-1-50x33.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S308334-1-60x40.jpg 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S308334-1-696x465.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S308334-1-560x374.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S308334-1-443x296.jpg 443w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S308334-1-707x472.jpg 707w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S308334-1-80x53.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S308334-1-48x32.jpg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;
&lt;/figure&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Keep the core product free to power growth: &lt;/strong&gt;Free is an engine. Brand love &lt;strong&gt;→ &lt;/strong&gt;word-of-mouth &lt;strong&gt;→&lt;/strong&gt; massive top of funnel &lt;strong&gt;→&lt;/strong&gt; more subscription opportunities. If you invest in your free experience, it compounds your paid experience — when people are passionate about the free version of your app, they &lt;em&gt;want &lt;/em&gt;to pay for more.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Gamify habit formation via loss aversion: &lt;/strong&gt;Daily streaks on Duolingo create consistency and build habits with users. By monetizing ways to protect streaks (celebrations, Streak Freezes), they become product levers for premium.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Outcome &amp;gt; features: &lt;/strong&gt;Duolingo learned from unsuccessful features like Duo TV to prioritize user needs — “We started with a business need rather than a learning need.” Similarly, AI-themed messaging on new features flopped, while repositioning around a concrete job (e.g. “become confident speaking”) drastically improved sales.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Micro-delight is more than cosmetic: &lt;/strong&gt;Animations, character reactions, and minor customizations all cascade into growth. Duolingo’s A/B tests show higher engagement and active users when delight is sprinkled throughout the interface.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=fDJ5qzjSZXI&amp;amp;t=1287s&quot;&gt;Watch the full session&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;2-ladder-to-stand-out-in-a-crowded-space-you-need-to-be-willing-to-reinvent&quot;&gt;&lt;strong&gt;2. Ladder: To stand out in a crowded space, you need to be willing to reinvent&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Ready for the growth playbook of a #1 App Store app? &lt;a href=&quot;https://www.linkedin.com/in/gregoryfstewart/&quot;&gt;Greg Stewart&lt;/a&gt;, CEO of Ladder, delivered a masterclass on scaling subscription apps in a competitive market. From honing in on what users really care about, to constant iteration based on customer feedback, Ladder’s success has come from relentless focus on solving user problems.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-pullquote&quot;&gt;&lt;blockquote&gt;&lt;p&gt;We overhauled our entire monetization strategy. If we hadn’t… I don’t think we’d be here.&lt;/p&gt;&lt;cite&gt;&lt;a href=&quot;https://www.linkedin.com/in/gregoryfstewart/&quot;&gt;Greg Stewart&lt;/a&gt;, CEO — Ladder&lt;/cite&gt;&lt;/blockquote&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-4 is-layout-flex wp-block-gallery-is-layout-flex&quot;&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;683&quot; data-id=&quot;47343&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-1-1024x683.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47343&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-1-1024x683.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-1-300x200.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-1-768x512.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-1-1536x1024.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-1-2048x1365.jpg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-1-50x33.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-1-60x40.jpg 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-1-696x464.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-1-560x373.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-1-444x296.jpg 444w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-1-708x472.jpg 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-1-80x53.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-1-48x32.jpg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;684&quot; data-id=&quot;47341&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-2-1024x684.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47341&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-2-1024x684.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-2-300x200.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-2-768x513.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-2-1536x1026.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-2-2048x1368.jpg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-2-50x33.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-2-60x40.jpg 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-2-696x465.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-2-560x374.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-2-443x296.jpg 443w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-2-707x472.jpg 707w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-2-80x53.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-2-48x32.jpg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;
&lt;/figure&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;It’s better to rebuild than flop: &lt;/strong&gt;Ladder’s early pricing was based on market comparison, and it worked for users attracted by a specific coach, but not the wider audience. When growth plateaued, they hit pause on all monetization efforts and went back to the drawing board. Don’t be afraid to overhaul your pricing structure if it’s not working — analyze users, re-segment, and rebuild.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Build for a problem:&lt;/strong&gt; Ladder didn’t want to be another “workout library” — finding workouts wasn’t the problem. Motivation was. Solving for this &lt;a href=&quot;https://www.revenuecat.com/blog/growth/what-drives-users-to-pay-jobs-to-be-done/&quot;&gt;JTBD&lt;/a&gt; meant building what drove workout &lt;em&gt;completions&lt;/em&gt;, not vanity metrics.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Listen to users, ignore everything else: &lt;/strong&gt;Ladder’s product roadmap is dictated by user feedback: “We don’t listen to our investors, we listen to our members.” Use &lt;a href=&quot;https://www.revenuecat.com/blog/growth/review-mining-for-subscription-apps/&quot;&gt;review mining&lt;/a&gt; to define your next ship — e.g. what other apps do users supplement yours with? You’ve found your next feature.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Brand is your differentiator: &lt;/strong&gt;In crowded spaces, your personality is the only thing that can stand out. Ladder cultivated a distinct, confident brand led by expert fitness coaches and storytelling, then spoke directly to users via Tiktok as a primary channel.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=HiVO4RK7KAw&quot;&gt;Watch the full session&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;3-conde-nast-brand-is-a-blessing-and-a-trap&quot;&gt;&lt;strong&gt;3. Cond&lt;/strong&gt;&lt;strong&gt;é&lt;/strong&gt;&lt;strong&gt; Nast: Brand is a blessing — and a trap&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Traditional media may seem like the last place to look for app growth insights, but &lt;a href=&quot;https://www.linkedin.com/in/michael-ribero/&quot;&gt;Michael Ribero&lt;/a&gt;, SVP of Global Consumer Revenue, has turned The Washington Post, Vogue, The New Yorker, and now Condé Nast into digital subscription powerhouses. Here’s how.&lt;/p&gt;



&lt;figure class=&quot;wp-block-pullquote&quot;&gt;&lt;blockquote&gt;&lt;p&gt;Someone’s exposure [to your brand] is not necessarily when they’re thinking about buying. It can be 10, 15, 20 years before that.&lt;/p&gt;&lt;cite&gt;&lt;a href=&quot;https://www.linkedin.com/in/michael-ribero/&quot;&gt;Michael Ribero&lt;/a&gt;, SVP of Global Consumer Revenue — Condé Nast&lt;/cite&gt;&lt;/blockquote&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-5 is-layout-flex wp-block-gallery-is-layout-flex&quot;&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;684&quot; data-id=&quot;47332&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Michael-1024x684.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47332&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Michael-1024x684.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Michael-300x200.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Michael-768x513.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Michael-1536x1026.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Michael-2048x1368.jpg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Michael-50x33.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Michael-60x40.jpg 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Michael-696x465.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Michael-560x374.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Michael-443x296.jpg 443w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Michael-707x472.jpg 707w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Michael-80x53.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Michael-48x32.jpg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;683&quot; data-id=&quot;47334&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Michael-2-1024x683.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47334&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Michael-2-1024x683.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Michael-2-300x200.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Michael-2-768x512.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Michael-2-1536x1024.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Michael-2-2048x1365.jpg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Michael-2-50x33.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Michael-2-60x40.jpg 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Michael-2-696x464.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Michael-2-560x373.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Michael-2-444x296.jpg 444w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Michael-2-708x472.jpg 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Michael-2-80x53.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Michael-2-48x32.jpg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;
&lt;/figure&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Nurture affinity long before purchase: &lt;/strong&gt;The biggest app players are household names, even to people who don’t use them. Seed positive brand associations early and often, across personas, so you’re at the forefront of people’s mind when and if they transition to becoming a buyer.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Keep heritage, but avoid it becoming stale legacy:&lt;/strong&gt; Brand is power, but it’s easy to become stagnant. You don’t want to become “your parents’ app”. Identify the heart of your brand and hold onto it; the rest should be malleable with time and experience.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Utilize bundling and unbundling: &lt;/strong&gt;“Giving people more for less money is an equation that’s always going to work,” says Michael. Maximize ARPU by positioning bundles at the moment of purchase, when buyers are “the most engaged they’ll ever be”. Create smaller unbundled offers or micro-subs to lower entry barriers for hesitant users.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Treat partners and platforms as frenemies: &lt;/strong&gt;Distribution partners can help &lt;em&gt;and &lt;/em&gt;hurt. What’s in it for them? Go into partnerships with your eyes open — decide who controls billing and data, and identify their true priorities.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;a href=&quot;https://youtu.be/0qt-wHxiFMY?si=kH9B6cHslW4VmwfT&quot;&gt;Watch or listen to the full recording on the Sub Club podcast&lt;/a&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;How Condé Nast Experiments, Bundles, and Wins — Michael Ribero,  Condé Nast&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/0qt-wHxiFMY?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;4-lose-it-paywalling-a-previously-free-feature-is-possible-even-if-its-scary&quot;&gt;&lt;strong&gt;4. Lose It!: Paywalling a previously-free feature is possible (even if it’s scary)&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Next up, &lt;a href=&quot;https://www.linkedin.com/in/danielle-goryl-3324a8b/&quot;&gt;Danielle Goryl&lt;/a&gt;, VP of Growth Marketing, and &lt;a href=&quot;https://www.linkedin.com/in/burtonhohman/&quot;&gt;Burton Hohman&lt;/a&gt;, Senior Product Manager, took to the stage to explain how paywalling Lose It!’s barcode scanner — a previously-free feature — paid off, even if it was a risky move.&lt;/p&gt;



&lt;figure class=&quot;wp-block-pullquote&quot;&gt;&lt;blockquote&gt;&lt;p&gt;Every decision lives in that balance: keep free strong, and make premium worth paying for.&lt;/p&gt;&lt;cite&gt;&lt;a href=&quot;https://www.linkedin.com/in/danielle-goryl-3324a8b/&quot;&gt;Danielle Goryl&lt;/a&gt;, VP of Growth Marketing — Lose It!&lt;/cite&gt;&lt;/blockquote&gt;&lt;/figure&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Freemium isn’t a loophole, it’s a tactic:&lt;/strong&gt; It’s tempting to paywall your most-used features, but ensure you keep genuine value free to engage users. Premium should fund innovation, not block usership.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Platform parity isn’t sacred:&lt;/strong&gt; Pricing differently across platforms can lead to fragmentation or confusion — but that doesn’t mean it’s impossible. While iOS users tolerated Lose It!’s barcode scanner being paywalled, Android didn’t. Ultimately, they kept it free-with-ads on Android, and paid for iOS. It’s okay to break “sacred rules”, just lead with data, approach with caution, and be flexible.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Coordinate deeply with support: &lt;/strong&gt;Utilize common negative feedback to rework your paywall copy and pre-empt arguments. Pre-write scripts for expected complaints. Listen to your users and use what they give you to win them over.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Target emotive moments for reviews: &lt;/strong&gt;Prompt for review after positive in-app moments and key events, or during high-intent seasons, to maximize the chance of users &lt;em&gt;actually &lt;/em&gt;leaving a review — and it being positive!&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=n6f0UVbATng&amp;amp;t=150s&quot;&gt;Watch the full session&lt;/a&gt;&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-TlBh3 wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Emotion + review prompt = ❤️&quot; text=&quot;&lt;p&gt;&lt;a href=&amp;quot;https://www.revenuecat.com/blog/engineering/how-to-hack-your-app-store-ratings/#h-hacking-app-store-ratings&amp;quot;&gt;&lt;span style=&amp;quot;font-weight: 400;&amp;quot;&gt;Learn how to build a customer satisfaction engine&lt;/span&gt;&lt;/a&gt;&lt;span style=&amp;quot;font-weight: 400;&amp;quot;&gt; that fuels positive reviews by prompting users after they have an in-app success moment.&lt;/span&gt;&lt;/p&gt;&quot; icon=&quot;bulb&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;5-cardpointers-skip-ads-embrace-advocates&quot;&gt;&lt;strong&gt;5. CardPointers: Skip ads, embrace ‘advocates’&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;“Affiliate program”? Not anymore. Enter revenue-share partnerships: two-way agreements that incentivize creators to promote your app. &lt;a href=&quot;https://www.linkedin.com/in/emcro/&quot;&gt;Emmanuel Crouvisier&lt;/a&gt;, Founder of CardPointers, pitched the case for content creators as the new sales force for subscription apps, and shared how to get buy-in from influencers.&lt;/p&gt;



&lt;figure class=&quot;wp-block-pullquote&quot;&gt;&lt;blockquote&gt;&lt;p&gt;People like people. They don’t so much like companies.&lt;/p&gt;&lt;cite&gt;&lt;a href=&quot;https://www.linkedin.com/in/emcro/&quot;&gt;Emmanuel Crouvisier&lt;/a&gt;, Founder — CardPointers&lt;/cite&gt;&lt;/blockquote&gt;&lt;/figure&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Authenticity outperforms ads&lt;/strong&gt;: Seeing #ad automatically turns people off. Rev-share partnerships feel collaborative, to creators &lt;em&gt;and&lt;/em&gt; their audience. Partnering with creators to use your app means their endorsement is integrated organically&lt;em&gt; &lt;/em&gt;within content. Because it feels authentic, you build trust with their followers, and often generate more revenue than paid ads.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Enable partners to win:&lt;/strong&gt; Creators need to know and love the product for their promo to feel genuine. Offer free premium app access, send media kits, and give demo calls so they understand the app and know how to show off its features.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Incentivize and gamify success: &lt;/strong&gt;Motivate creators by showing their impact and encouraging healthy competition, like an email every time they make a sale, or a leadership board showing most rev-share sales. Build relationships by ensuring you pay on time, and celebrating their personal wins e.g. follower milestones.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Communities are self-sustaining growth loops:&lt;/strong&gt; Infiltrate niche Facebook, Discord, or WhatsApp groups surrounding a topic or interest for access to high-intent audiences and public social proof.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=k2t0nNHQDzI&quot;&gt;Watch the full session&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;6-app-masters-know-your-enemy-but-dont-copy-paste-their-hacks&quot;&gt;&lt;strong&gt;6. App Masters: Know your enemy, but don’t copy-paste their hacks&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Are you willing to break the rules if it means shooting to #1 on the App Store? The modern app store is a battlefield; high-stakes, high-enforcement. &lt;a href=&quot;https://www.linkedin.com/in/stevepyoung/&quot;&gt;Steve P. Young&lt;/a&gt;, Founder of App Masters, exposed the hidden black-hat strategies apps use to climb the charts — and the growing surveillance app stores have to prevent them working.&lt;/p&gt;



&lt;figure class=&quot;wp-block-pullquote&quot;&gt;&lt;blockquote&gt;&lt;p&gt;If you ignore Apple or continue going after the slap on the wrist, that’s when you tend to really get in trouble.&lt;/p&gt;&lt;cite&gt;&lt;a href=&quot;https://www.linkedin.com/in/stevepyoung/&quot;&gt;Steve P. Young&lt;/a&gt;, Founder — App Masters&lt;/cite&gt;&lt;/blockquote&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-6 is-layout-flex wp-block-gallery-is-layout-flex&quot;&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;684&quot; data-id=&quot;47336&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Steve-1024x684.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47336&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Steve-1024x684.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Steve-300x200.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Steve-768x513.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Steve-1536x1026.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Steve-2048x1368.jpg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Steve-50x33.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Steve-60x40.jpg 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Steve-696x465.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Steve-560x374.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Steve-443x296.jpg 443w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Steve-707x472.jpg 707w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Steve-80x53.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Steve-48x32.jpg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;684&quot; data-id=&quot;47328&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Steve-use-1024x684.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47328&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Steve-use-1024x684.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Steve-use-300x200.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Steve-use-768x513.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Steve-use-1536x1026.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Steve-use-2048x1368.jpg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Steve-use-50x33.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Steve-use-60x40.jpg 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Steve-use-696x465.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Steve-use-560x374.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Steve-use-443x296.jpg 443w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Steve-use-707x472.jpg 707w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Steve-use-80x53.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Steve-use-48x32.jpg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;
&lt;/figure&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Platforms are cracking down: &lt;/strong&gt;Apple and Google now enforce review integrity and store compliance at scale. Repeated or blatant violations lead to removal, revenue suspension, or account ban. Shady hacks that worked last quarter could now trigger flags on your account. Treat compliance as part of your growth strategy.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Understand the dark side: &lt;/strong&gt;Awareness ≠ endorsement. Knowing black-hat ASO tactics helps you detect competitors gaming the system, and avoid falling into similar traps. Success belongs to those who know the rules deeply enough to play by them, and still win.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Short-term hacks spike installs — and scrutiny: &lt;/strong&gt;Tactics like lifetime free offers, incentivized ratings, or aggressive paywalls can and do work. But they also draw attention. Sustainable growth comes from optimizing legitimate signals: product-market fit, genuine ASO, strong LTV, and user trust.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Fake reviews are worse than no reviews: &lt;/strong&gt;Your reputation is more than brand, it’s a safety system. Fake or manipulated reviews don’t just hurt users, they have long-term impact on your reputation &lt;em&gt;and &lt;/em&gt;ring alarm bells to app stores. Protecting your review integrity is just as important as optimizing your app page.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=wSXZRe7g5dQ&quot;&gt;Watch the full session&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-7-flighty-a-good-feature-is-its-own-marketing-engine-nbsp&quot;&gt;&lt;strong&gt;7. Flighty: A good feature is its own marketing engine&amp;nbsp;&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;&lt;a href=&quot;https://www.linkedin.com/in/linkedinryan/&quot;&gt;Ryan Jones&lt;/a&gt;, Founder &amp;amp; CEO of Flighty, laid out Flighty’s unique growth trajectory, demonstrating that the most sustainable growth doesn’t come from budget, but from building app experiences so useful that user delight fuels organic growth loops.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-pullquote&quot;&gt;&lt;blockquote&gt;&lt;p&gt;How often do people open the App Store to look for new apps? It doesn’t happen anymore. They go there to solve a problem.&lt;/p&gt;&lt;cite&gt;&lt;a href=&quot;https://www.linkedin.com/in/linkedinryan/&quot;&gt;Ryan Jones&lt;/a&gt;, Founder &amp;amp; CEO — Flighty&lt;/cite&gt;&lt;/blockquote&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;683&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Flighty-1024x683.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47326&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Flighty-1024x683.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Flighty-300x200.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Flighty-768x512.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Flighty-1536x1024.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Flighty-2048x1365.jpg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Flighty-50x33.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Flighty-60x40.jpg 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Flighty-696x464.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Flighty-560x373.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Flighty-444x296.jpg 444w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Flighty-708x472.jpg 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Flighty-80x53.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Flighty-48x32.jpg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/jtbd-paywall-optimization/&quot;&gt;&lt;strong&gt;Define your emotional job-to-be-done&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;: &lt;/strong&gt;Flighty’s value isn’t flight tracking, it’s &lt;em&gt;confidence while flying. &lt;/em&gt;The app solves uncertainty, not logistics, selling calm and control in a chaotic travel experience. Focus on&lt;a href=&quot;https://www.revenuecat.com/blog/growth/solve-app-problems-emotionally/&quot;&gt; emotional resonance&lt;/a&gt; over utility.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Make sharing &lt;/strong&gt;&lt;strong&gt;&lt;em&gt;useful&lt;/em&gt;&lt;/strong&gt;&lt;strong&gt;, not promotional: &lt;/strong&gt;Your biggest promotion comes from moments users &lt;em&gt;want &lt;/em&gt;to share. A shareable flight diary that offers authentic delight. Live flight-share links with zero friction and no sign-in needed: “The third time someone sends that link, their partner just downloads the app.” Every feature is a loop: deliver value, earn trust, invite new users in. Delight and utility goes further than engineered promotion.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Always ship on day one: &lt;/strong&gt;Being first to support new Apple features like Live Activities and Dynamic Island unlocked public visibility, brand leadership, and positive user experiences for Flighty. Don’t wait to see what competitors do; act quickly to open silent acquisition channels.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Your PMF may be unexpected: &lt;/strong&gt;Rather than ‘live flight tracking’, Flighty’s product-market fit came from its data precision. In flight tracking, there’s no forgiveness for errors: “You don’t get second chances, if you tell someone the wrong delay time, they’re gone.” Identify the make-or-break for your users, then build the product around it.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Catch the full recording on the Launched podcast — episode coming soon.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-8-shotsy-indie-is-a-philosophy-not-a-team-size-nbsp&quot;&gt;&lt;strong&gt;8. Shotsy: Indie is a philosophy, not a team size&amp;nbsp;&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;From scrappy indie years to raising $2 million in venture funding, &lt;a href=&quot;https://www.linkedin.com/in/aja-beckett/&quot;&gt;Aja Beckett&lt;/a&gt;, Founder of Shotsy, has many lessons to share from her indie journey. Above all: build from personal pain, grow through community, and raise capital that protects your craft.&lt;/p&gt;



&lt;figure class=&quot;wp-block-pullquote&quot;&gt;&lt;blockquote&gt;&lt;p&gt;It was really important to me to work with VCs who shared the same focus on delighting users as I did.&lt;/p&gt;&lt;cite&gt;&lt;a href=&quot;https://www.linkedin.com/in/aja-beckett/&quot;&gt;Aja Beckett&lt;/a&gt;, Founder — Shotsy&lt;/cite&gt;&lt;/blockquote&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;683&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Shotsy-1024x683.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47324&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Shotsy-1024x683.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Shotsy-300x200.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Shotsy-768x512.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Shotsy-1536x1024.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Shotsy-2048x1365.jpg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Shotsy-50x33.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Shotsy-60x40.jpg 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Shotsy-696x464.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Shotsy-560x373.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Shotsy-444x296.jpg 444w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Shotsy-708x472.jpg 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Shotsy-80x53.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Shotsy-48x32.jpg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Monetize meaningfully: &lt;/strong&gt;Users don’t mind paying for features they believe in, for a product they trust whose mission they align with: “People weren’t just paying for features, they were paying to support something made for them.”&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Authenticity can scale: &lt;/strong&gt;It’s possible to raise capital without losing your indie culture. For Shotsy, funding was about fueling the craft, supporting user benefits, and protecting the product’s future for users. It gave acceleration without dilution of values.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Indie is a mindset: &lt;/strong&gt;Regardless of team size or funding structure, you can stay true to indie roots &lt;em&gt;and &lt;/em&gt;build a venture-backed product — if you have a defined mindset and user obsession at the core of the growth.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Build it and they will come: &lt;/strong&gt;When you solve a problem you live with, and fuel the product with that emotional truth, you attract a community: “Reddit was the heartbeat of our launch.” Early believers shaped the product, promoted it organically, and emotional alignment replaced ad spend.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=iiqCMgpbVD4&quot;&gt;Watch the full session&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h2-9-revenuecats-paywall-builder-is-fast-enough-for-e-sports&quot;&gt;&lt;strong&gt;H2: 9. RevenueCat’s paywall builder is fast enough for e-sports&amp;nbsp;&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Forget App Store rankings — the World Paywall Speedbuilding Championships is the only leaderboard that matters now.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Back in June 2025, we challenged the app community to see how quickly and accurately they could rebuild real-world paywalls in RevenueCat’s &lt;a href=&quot;https://www.revenuecat.com/docs/tools/paywalls&quot;&gt;paywall builder&lt;/a&gt;.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;From 668 applicants in the qualifier round, to top 25, then five semi-finalists who joined App Growth Annual live in New York for the final round, we put RevenueCat Paywalls to the test to discover:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Who is the fastest paywall builder in the world?&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Is RevenueCat Paywalls robust enough to handle being an e-sport?&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;With a lightning-fast final build time of 3:16, software engineer &lt;a href=&quot;https://www.linkedin.com/in/joshuadeguzman/&quot;&gt;Joshua De Guzman&lt;/a&gt; rebuilt Lose It!’s paywall and was named the World Paywall Speedbuilding Champion, taking home $5k and, of course, a custom gold-plated champion’s belt.&lt;/p&gt;



&lt;figure class=&quot;wp-block-gallery has-nested-images columns-3 is-cropped wp-block-gallery-7 is-layout-flex wp-block-gallery-is-layout-flex&quot;&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;683&quot; data-id=&quot;47320&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A03878-1024x683.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47320&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A03878-1024x683.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A03878-300x200.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A03878-768x512.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A03878-1536x1024.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A03878-2048x1365.jpg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A03878-50x33.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A03878-60x40.jpg 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A03878-696x464.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A03878-560x373.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A03878-444x296.jpg 444w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A03878-708x472.jpg 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A03878-80x53.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A03878-48x32.jpg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;684&quot; data-id=&quot;47315&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309160-1024x684.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47315&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309160-1024x684.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309160-300x200.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309160-768x513.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309160-1536x1026.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309160-2048x1368.jpg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309160-50x33.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309160-60x40.jpg 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309160-696x465.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309160-560x374.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309160-443x296.jpg 443w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309160-707x472.jpg 707w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309160-80x53.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309160-48x32.jpg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;683&quot; data-id=&quot;47317&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_9182-1024x683.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47317&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_9182-1024x683.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_9182-300x200.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_9182-768x512.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_9182-1536x1024.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_9182-2048x1365.jpg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_9182-50x33.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_9182-60x40.jpg 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_9182-696x464.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_9182-560x373.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_9182-444x296.jpg 444w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_9182-708x472.jpg 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_9182-80x53.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_9182-48x32.jpg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;684&quot; data-id=&quot;47313&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S308946-1024x684.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47313&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S308946-1024x684.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S308946-300x200.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S308946-768x513.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S308946-1536x1026.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S308946-2048x1368.jpg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S308946-50x33.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S308946-60x40.jpg 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S308946-696x465.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S308946-560x374.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S308946-443x296.jpg 443w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S308946-707x472.jpg 707w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S308946-80x53.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S308946-48x32.jpg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;683&quot; data-id=&quot;47319&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A03871-1024x683.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47319&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A03871-1024x683.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A03871-300x200.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A03871-768x512.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A03871-1536x1024.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A03871-2048x1365.jpg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A03871-50x33.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A03871-60x40.jpg 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A03871-696x464.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A03871-560x373.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A03871-444x296.jpg 444w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A03871-708x472.jpg 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A03871-80x53.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A03871-48x32.jpg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;
&lt;/figure&gt;



&lt;p&gt;Equal parts hackathon, e-sports, and WWE spectacle, we’d say the WPSC is definitely our new favorite sport.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=bcnUYWLo-I4&quot;&gt;Watch the championship final&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h2-10-shippies-x-shipaton-awards-chocolate-is-better-than-trophies&quot;&gt;&lt;strong&gt;H2: 10. Shippies x Shipaton awards: Chocolate is better than trophies&amp;nbsp;&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Each year, we celebrate the best subscription apps have to offer — from the winners of our global hackathon, Shipaton, to recipients of the coveted &lt;a href=&quot;https://appgrowthannual.com/shippies&quot;&gt;Shippies awards&lt;/a&gt;.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;684&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309752-1024x684.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47307&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309752-1024x684.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309752-300x200.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309752-768x513.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309752-1536x1026.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309752-2048x1368.jpg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309752-50x33.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309752-60x40.jpg 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309752-696x465.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309752-560x374.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309752-443x296.jpg 443w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309752-707x472.jpg 707w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309752-80x53.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309752-48x32.jpg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The second year of &lt;a href=&quot;https://www.shipaton.com/&quot;&gt;Shipaton&lt;/a&gt; was phenomenal, with over 55k participants and 800+ apps submitted. After eight weeks of grinding and #BuildinginPublic, it’s amazing to consider the influx of new apps landing on people’s homescreens.&lt;/p&gt;



&lt;p&gt;The Shippies are RevenueCat’s annual app awards, honoring the year’s most innovative, user-friendly, and creative new subscription apps. With categories across onboarding, monetization, and retention, it’s a moment to recognize truly outstanding launches in the industry.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Alongside Shipaton’s winning apps receiving $350k+ in cash prizes, winners of Shipaton and The Shippies received a unique Golden Shippy, &lt;em&gt;and&lt;/em&gt; their very own spotlight billboard in Times Square.&lt;/p&gt;



&lt;figure class=&quot;wp-block-gallery has-nested-images columns-3 is-cropped wp-block-gallery-8 is-layout-flex wp-block-gallery-is-layout-flex&quot;&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;683&quot; height=&quot;1024&quot; data-id=&quot;47311&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_8198-683x1024.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47311&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_8198-683x1024.jpg 683w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_8198-200x300.jpg 200w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_8198-768x1152.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_8198-1024x1536.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_8198-1366x2048.jpg 1366w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_8198-33x50.jpg 33w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_8198-27x40.jpg 27w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_8198-309x464.jpg 309w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_8198-696x1044.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_8198-373x560.jpg 373w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_8198-197x296.jpg 197w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_8198-315x472.jpg 315w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_8198-53x80.jpg 53w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_8198-32x48.jpg 32w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_8198-scaled.jpg 1707w&quot; sizes=&quot;auto, (max-width: 683px) 100vw, 683px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; data-id=&quot;46902&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-4-1024x1024.jpeg&quot; alt=&quot;&quot; class=&quot;wp-image-46902&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-4-1024x1024.jpeg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-4-300x300.jpeg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-4-150x150.jpeg 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-4-768x768.jpeg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-4-50x50.jpeg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-4-40x40.jpeg 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-4-464x464.jpeg 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-4-696x696.jpeg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-4-560x560.jpeg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-4-296x296.jpeg 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-4-472x472.jpeg 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-4-80x80.jpeg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-4-48x48.jpeg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-4.jpeg 1080w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;576&quot; data-id=&quot;47309&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/DJI_20251014102129_0153_D-1-1-1024x576.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47309&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/DJI_20251014102129_0153_D-1-1-1024x576.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/DJI_20251014102129_0153_D-1-1-300x169.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/DJI_20251014102129_0153_D-1-1-768x432.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/DJI_20251014102129_0153_D-1-1-1536x864.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/DJI_20251014102129_0153_D-1-1-2048x1152.jpg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/DJI_20251014102129_0153_D-1-1-50x28.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/DJI_20251014102129_0153_D-1-1-71x40.jpg 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/DJI_20251014102129_0153_D-1-1-696x392.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/DJI_20251014102129_0153_D-1-1-560x315.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/DJI_20251014102129_0153_D-1-1-526x296.jpg 526w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/DJI_20251014102129_0153_D-1-1-840x472.jpg 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/DJI_20251014102129_0153_D-1-1-80x45.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/DJI_20251014102129_0153_D-1-1-48x27.jpg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;
&lt;/figure&gt;



&lt;p&gt;Naturally, we didn’t want to exceed the winners’ luggage weight limit on their flight home*, so winners on the day got to enjoy their Golden Shippy in delicious, gold-lustre-covered chocolate form.&lt;/p&gt;



&lt;p&gt;&lt;em&gt;*The awards didn’t arrive in time&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/company/shipaton-2025-winners/&quot;&gt;Read the list of winning Shipaton apps here&lt;/a&gt; &lt;br&gt;&lt;a href=&quot;https://apps.shipaton.com/&quot;&gt;Explore the Shipaton 2025 app showcase here&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/company/shippies-2025-winners/&quot;&gt;Read the full rundown on The Shippies 2025 winners&lt;/a&gt;&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;11-if-you-care-enough-you-really-can-get-the-pokemon-theme-song-singer-to-make-a-song-about-revenuecat&quot;&gt;&lt;strong&gt;11. If you care enough, you really can get the Pok&lt;/strong&gt;&lt;strong&gt;é&lt;/strong&gt;&lt;strong&gt;mon theme song singer to make a song about RevenueCat&amp;nbsp;&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;We wrapped up the day the only way that made sense… with a live performance from Jason Paige, the voice behind Pokémon’s theme — who also wrote the RevenueCat theme song. Oh, you didn’t know we had a theme song? Of course we do.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Did he sing the Pokémon theme? Obviously. Was the main event really about showcasing the official RevenueCat theme song? Also yes. Did people get up and join in? Turns out, app devs love a sing-along.&lt;/p&gt;



&lt;p&gt;Enough reading — go give it a listen 🎧&lt;/p&gt;



&lt;figure class=&quot;wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-9 is-layout-flex wp-block-gallery-is-layout-flex&quot;&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;683&quot; data-id=&quot;47295&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A04727-1-1024x683.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47295&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A04727-1-1024x683.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A04727-1-300x200.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A04727-1-768x512.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A04727-1-1536x1024.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A04727-1-2048x1365.jpg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A04727-1-50x33.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A04727-1-60x40.jpg 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A04727-1-696x464.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A04727-1-560x373.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A04727-1-444x296.jpg 444w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A04727-1-708x472.jpg 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A04727-1-80x53.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A04727-1-48x32.jpg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;684&quot; data-id=&quot;47293&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S300090-2-1024x684.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47293&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S300090-2-1024x684.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S300090-2-300x200.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S300090-2-768x513.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S300090-2-1536x1026.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S300090-2-2048x1368.jpg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S300090-2-50x33.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S300090-2-60x40.jpg 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S300090-2-696x465.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S300090-2-560x374.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S300090-2-443x296.jpg 443w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S300090-2-707x472.jpg 707w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S300090-2-80x53.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S300090-2-48x32.jpg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;
&lt;/figure&gt;



&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=5rabIf__Ma8&quot;&gt;Listen to the RevenueCat theme song&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;every-product-announcement-at-app-growth-annual-2025&quot;&gt;&lt;strong&gt;Every product announcement at App Growth Annual 2025&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;From AI-powered and video &lt;a href=&quot;https://www.revenuecat.com/feature/paywalls/&quot;&gt;Paywalls&lt;/a&gt; to real-time &lt;a href=&quot;https://www.revenuecat.com/feature/charts/&quot;&gt;Charts&lt;/a&gt;, in-app currency, and daily payouts, here’s everything we’re building now and shipping soon.&amp;nbsp;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Video and AI-generated paywalls: &lt;/strong&gt;Paywalls V2 is expanding — add video components for richer storytelling, use AI to generate paywalls in an instant, and watch every paywall built for mobile automatically work on the web, too. &lt;a href=&quot;https://www.revenuecat.com/docs/tools/paywalls/creating-paywalls/components#video-component&quot;&gt;&lt;em&gt;Video&lt;/em&gt;&lt;/a&gt;&lt;em&gt; and mobile/web compatibility out now, AI-builder coming soon.&lt;/em&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Real-time Charts: &lt;/strong&gt;Purchases and events now appear instantly in real-time across your Charts dashboard. Attribution, integrations and unified metrics mean what you see is always accurate and consistent. &lt;em&gt;Currently in beta, full rollout by end of year.&amp;nbsp;&lt;/em&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Virtual currency: &lt;/strong&gt;New &lt;a href=&quot;https://www.revenuecat.com/blog/engineering/how-to-monetize-your-ai-app-with-virtual-currencies/&quot;&gt;virtual currency framework&lt;/a&gt; lets you add coins, credits, or tokens directly into your app. Create, track, and refund with built-in server-side APIs. Manage balances, redemptions, and offers securely via RevenueCat. &lt;a href=&quot;https://www.revenuecat.com/blog/company/revenuecat-virtual-currency/&quot;&gt;&lt;em&gt;Currently in beta&lt;/em&gt;&lt;/a&gt;&lt;em&gt;, rolling out by end of year.&lt;/em&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;RC Capital — daily payouts: &lt;/strong&gt;Don’t let cash flow slow your growth. RC Capital will offer next-day payouts for 80% of daily app store revenue so you can reinvest quicker. With a transparent 2.5% fee, remaining funds will arrive as usual from Apple/Google. &lt;em&gt;Launching late 2025 for US, full rollout to follow.&amp;nbsp;&lt;/em&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;RevenueCat Funnels: &lt;/strong&gt;Design fully-hosted web-to-app onboarding flows, powered by our Paywalls engine. Remote-configurable, cross-platform, and no-code. Integrates seamlessly with Paywalls V2 and Web Billing.&lt;strong&gt; &lt;/strong&gt;&lt;em&gt;Early access opening late 2025, full rollout coming 2026.&amp;nbsp;&lt;/em&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Customer Center: &lt;/strong&gt;Add a plug-and-play in-app subscription page for users to manage their plans, cancel, or redeem retention offers. Include Zendesk and Intercom integrations, and churn prevention hooks and feedback prompts. &lt;a href=&quot;https://www.revenuecat.com/feature/customer-center/&quot;&gt;&lt;em&gt;Available now!&lt;/em&gt;&lt;/a&gt;&lt;em&gt;&amp;nbsp;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=EVR7Crrm0_w&amp;amp;t=1260s&quot;&gt;Watch the full product keynote here&lt;/a&gt;&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-1JypXu wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Introducing Subscriber Milestones&quot; text=&quot;&lt;p&gt;&lt;span style=&amp;quot;font-weight: 400;&amp;quot;&gt;If you’ve ever admired YouTube’s Play Buttons, now’s your time. We’re celebrating your wins with Subscriber Milestones, a new initiative to mark app growth. You’ll hear from us as you hit Silver (50k), Gold (250k), and Diamond (1m) subscribers — and receive a shiny plaque, shipped straight to you!&lt;/span&gt;&lt;/p&gt;&quot; icon=&quot;star&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;figure class=&quot;wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-10 is-layout-flex wp-block-gallery-is-layout-flex&quot;&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;684&quot; data-id=&quot;47283&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309402-1024x684.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47283&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309402-1024x684.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309402-300x200.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309402-768x513.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309402-1536x1026.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309402-2048x1368.jpg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309402-50x33.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309402-60x40.jpg 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309402-696x465.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309402-560x374.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309402-443x296.jpg 443w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309402-707x472.jpg 707w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309402-80x53.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/7S309402-48x32.jpg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;683&quot; data-id=&quot;47285&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_8199-1-1024x683.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47285&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_8199-1-1024x683.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_8199-1-300x200.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_8199-1-768x512.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_8199-1-1536x1024.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_8199-1-2048x1365.jpg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_8199-1-50x33.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_8199-1-60x40.jpg 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_8199-1-696x464.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_8199-1-560x373.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_8199-1-444x296.jpg 444w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_8199-1-708x472.jpg 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_8199-1-80x53.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/IMG_8199-1-48x32.jpg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;
&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;well-see-you-next-year&quot;&gt;&lt;strong&gt;We’ll see you next year&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;And that’s your whirlwind tour of App Growth Annual 2025! There were way more than just 11 lessons to learn from the full day — we didn’t even mention the 28 exclusive hands-on workshops from app industry experts, or the after-party complete with DJ Jazzy Jeff, airbrush tattoos, and custom caricatures… but you can only fit so much into a blog post.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-gallery has-nested-images columns-2 is-cropped wp-block-gallery-11 is-layout-flex wp-block-gallery-is-layout-flex&quot;&gt;
&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;683&quot; data-id=&quot;47303&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07546-1024x683.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47303&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07546-1024x683.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07546-300x200.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07546-768x512.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07546-1536x1024.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07546-2048x1366.jpg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07546-50x33.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07546-60x40.jpg 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07546-696x464.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07546-560x373.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07546-444x296.jpg 444w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07546-708x472.jpg 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07546-80x53.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07546-48x32.jpg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;683&quot; data-id=&quot;47301&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07583-1024x683.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47301&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07583-1024x683.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07583-300x200.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07583-768x512.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07583-1536x1024.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07583-2048x1365.jpg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07583-50x33.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07583-60x40.jpg 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07583-696x464.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07583-560x373.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07583-444x296.jpg 444w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07583-708x472.jpg 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07583-80x53.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07583-48x32.jpg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;683&quot; data-id=&quot;47299&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07585-1024x683.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47299&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07585-1024x683.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07585-300x200.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07585-768x512.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07585-1536x1024.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07585-2048x1365.jpg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07585-50x33.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07585-60x40.jpg 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07585-696x464.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07585-560x373.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07585-444x296.jpg 444w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07585-708x472.jpg 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07585-80x53.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/85A07585-48x32.jpg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;683&quot; data-id=&quot;47305&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A05058-1024x683.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47305&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A05058-1024x683.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A05058-300x200.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A05058-768x512.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A05058-1536x1024.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A05058-2048x1365.jpg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A05058-50x33.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A05058-60x40.jpg 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A05058-696x464.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A05058-560x373.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A05058-444x296.jpg 444w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A05058-708x472.jpg 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A05058-80x53.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/35A05058-48x32.jpg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;
&lt;/figure&gt;



&lt;p&gt;Feel like you missed out? Join us at App Growth Annual 2026 😉&lt;/p&gt;



&lt;p&gt;You can also:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/playlist?list=PLsFOrkX_y0B6o8zs8PUOWQbUi_nTQn_uD&quot;&gt;Replay all the sessions on YouTube&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/channel/UCeq8LcFQ3ee_p8b-eYTARsg&quot;&gt;Subscribe to Sub Club for future interviews with some of the day’s speakers&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://atepamedia.pic-time.com/-sabrinaneedshiding/gallery&quot;&gt;Browse the event’s photo gallery in search of your new &lt;em&gt;oh-so-candid &lt;/em&gt;headshot&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title><![CDATA[Introducing a unified overview for your web revenue]]></title><description><![CDATA[Everything web, in one place. The new overview in RevenueCat brings setup, insights, and performance together.]]></description><link>https://www.revenuecat.com/blog/company/web-overview-dashboard/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/company/web-overview-dashboard/</guid><pubDate>Tue, 04 Nov 2025 11:53:22 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/1.-A-new-way-to-navigate-RevenueCat.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;More mobile developers are expanding to the web to reach customers beyond the app stores. As user acquisition costs rise and app store policies tighten, the web offers a flexible channel for growth.&lt;/p&gt;



&lt;p&gt;The web makes it easy to test pricing, run campaigns, and sell subscriptions anywhere a link fits.&lt;/p&gt;



&lt;p&gt;But until now, managing this in RevenueCat meant jumping between pages to configure products, purchase links, and integrations.&lt;/p&gt;



&lt;p&gt;The new web overview in the dashboard changes that. It brings setup, insights, and performance into one place, so you can create, analyze, and grow your web revenue directly inside RevenueCat.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-a-single-view-of-your-entire-web-business&quot;&gt;&lt;strong&gt;A single view of your entire web business&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The web overview in the dashboard is your home for everything web in RevenueCat. It brings setup, performance, and optimization together in one single overview.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;538&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Web-Home-2-1024x538.png&quot; alt=&quot;&quot; class=&quot;wp-image-47637&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Web-Home-2-1024x538.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Web-Home-2-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Web-Home-2-768x403.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Web-Home-2-1536x806.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Web-Home-2-2048x1075.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Web-Home-2-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Web-Home-2-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Web-Home-2-696x365.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Web-Home-2-560x294.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Web-Home-2-840x441.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Web-Home-2-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Web-Home-2-48x25.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;At the top, you’ll see key metrics for web revenue, active subscriptions, and MRR. Each chart links directly to deeper analysis, so you can move from overview to insight with a single click.&lt;/p&gt;



&lt;p&gt;Below, you’ll find an overview of all your Web Purchase Links. Each link shows impressions, purchases, revenue, and conversion rate. You can compare them side by side to see which campaigns perform best, or create new ones in seconds for an email, landing page, or ad.&lt;/p&gt;



&lt;p&gt;You can also open Web Settings/Configs from the same view to adjust appearance, checkout design, or connection settings, all without leaving the page.&lt;/p&gt;



&lt;p&gt;The dashboard includes built-in onboarding, educational content, and examples that help you use the web to acquire and retain subscribers. It’s designed to surface new opportunities, guide setup, and help you improve conversion over time. You’ll find practical videos, step-by-step guides, and customer stories that show what’s possible when you use RevenueCat Web to reach new audiences.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“Our goal was to make the web feel as native to RevenueCat as iOS or Android. You shouldn’t need to jump between tools just to understand what’s working. The new dashboard puts all of that in one view.” — &lt;a href=&quot;https://www.linkedin.com/in/edshelley/&quot;&gt;Ed Shelley&lt;/a&gt;, Senior Product Manager &lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Imagine you’re running a last-minute Black Friday campaign for your subscription app. In the dashboard, you can see setup and conversions for each web purchase link, one from your email, another from an ad campaign.&lt;/p&gt;



&lt;p&gt;The web overview in the dashboard gives you a clear picture of your web revenue, from the first click to recurring conversion.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-start-using-the-web-overview-in-your-dashboard-today&quot;&gt;Start using the web overview in your dashboard today&lt;/h2&gt;



&lt;p&gt;More developers are expanding beyond the app stores to capture new audiences and use cases. With RevenueCat Web, you can launch paywalls, run campaigns, and sell directly on the web with confidence. The web overview in the dashboard makes these capabilities easier to use and understand.&lt;/p&gt;



&lt;p&gt;The web overview is live for every RevenueCat customer. When you open RevenueCat today, you’ll find ‘Web’ in the sidebar.&lt;/p&gt;



&lt;p&gt;If you already sell on the web, your setup and data is waiting for you. Start by exploring your top-performing Web Purchase Links to see which offers drive the most conversions.&lt;/p&gt;



&lt;p&gt;If you’re new to web monetization, onboarding will walk you through setup and show how to get started, including templates and a guided flow to publish your first link in minutes, no code required.&lt;/p&gt;



&lt;p&gt;Open it today, explore the overview, and see how the web can help you grow faster.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[The complete guide to OKRs and KPIs for subscription apps]]></title><description><![CDATA[How to align teams, track the metrics that matter, and turn strategy into measurable results]]></description><link>https://www.revenuecat.com/blog/growth/okrs-kpis-subscription-apps/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/okrs-kpis-subscription-apps/</guid><pubDate>Mon, 03 Nov 2025 16:46:28 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/OKRs-and-KPIs.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;I used to think OKRs were a bit like company values: something teams would set, file away, and rarely revisit. Basically, the business version of that gym membership you signed up for but never used…&amp;nbsp;&lt;/p&gt;



&lt;p&gt;That changed when I worked at companies that &lt;em&gt;really&lt;/em&gt; knew how to use them. Turns out, OKRs aren’t just another tick-box activity — they’re a strategic&lt;strong&gt; way to take a long-term vision and turn it into step-by-step action.&lt;/strong&gt; I’d just never seen them done well before.&lt;/p&gt;



&lt;p&gt;Now, I see OKRs as a framework I’d recommend to any company: they help sharpen focus, align teams, and turn strategy into something actionable. I use them not as an extra layer of work, but as a tool to create clarity, collaboration, and real impact. Think of them as the long-term benefits from using the gym (even when abs don’t magically appear after a couple of workouts).&lt;/p&gt;



&lt;p&gt;This article was inspired by a recent workshop I hosted on OKRs and KPIs for subscription apps, alongside &lt;a href=&quot;https://www.linkedin.com/in/rosie-hoggmascall/&quot;&gt;Rosie Hoggmascall&lt;/a&gt; (Author of &lt;a href=&quot;https://growthdives.com/&quot;&gt;Growth Dives&lt;/a&gt; and Growth Lead at &lt;a href=&quot;http://fyxer.ai&quot;&gt;Fyxer.ai&lt;/a&gt;) and &lt;a href=&quot;https://www.linkedin.com/in/hannagrevelius/&quot;&gt;Hanna Grevelius&lt;/a&gt; (Chief Product Officer at &lt;a href=&quot;https://www.brucestudios.com/en&quot;&gt;Bruce Studios&lt;/a&gt;, ex-Golf Gamebook, Fishbrain). We’ll unpack their practical insights — from setting the right KPIs to avoiding common OKR pitfalls — so you can move from chasing data to using it strategically to drive impact.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-are-okrs-vs-kpis&quot;&gt;What are OKRs vs. KPIs?&lt;/h2&gt;



&lt;p&gt;Before diving into the practicalities, it’s important to understand how OKRs and KPIs fit into the bigger picture. Let’s look at it from the top down:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;At the very top sits your &lt;strong&gt;company’s vision&lt;/strong&gt;: the ‘why’ behind what you do and where you’re headed.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Many companies also define a &lt;a href=&quot;https://www.revenuecat.com/blog/growth/north-star-metrics-subscription-growth/&quot;&gt;&lt;strong&gt;North Star metric&lt;/strong&gt;&lt;/a&gt; (NSM): the single most critical measure that stays steady over time and keeps everyone focused on that vision.&lt;/li&gt;



&lt;li&gt;While vision gives you direction, it doesn’t tell you how to get there. &lt;strong&gt;Strategy&lt;/strong&gt; lays out the long-term approach, often spanning years. But it can feel a bit abstract…&amp;nbsp;&lt;/li&gt;



&lt;li&gt;This is where &lt;strong&gt;OKRs&lt;/strong&gt; shine: they break that big-picture strategy into clear, manageable steps — outlining what needs to be achieved and why.&lt;/li&gt;
&lt;/ol&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;844&quot; height=&quot;560&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image.png&quot; alt=&quot;&quot; class=&quot;wp-image-47583&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image.png 844w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-300x199.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-768x510.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-50x33.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-60x40.png 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-696x462.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-560x372.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-446x296.png 446w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-711x472.png 711w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-80x53.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-48x32.png 48w&quot; sizes=&quot;auto, (max-width: 844px) 100vw, 844px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;OKR stands for &lt;strong&gt;objectives and key results&lt;/strong&gt;:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Objective is the directional goal you want to achieve&lt;/strong&gt; e.g. “improve the user experience”.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Key results (KRs) are the measurable outcomes that tell you whether you’re making progress toward that objective &lt;/strong&gt;— they define the KPIs (key performance Indicators) you’ll track.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;On its own, an objective without clear key results is just a vague New Year’s resolution. Particularly for a subscription app, KPIs are the&lt;strong&gt; quantitative measures of success&lt;/strong&gt;; think metrics like churn rate, monthly recurring revenue, user engagement, or activation rate. These numbers make it clear whether your efforts are making a difference.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Once your key results and KPIs are defined, you can plan various initiatives and experiments aimed at achieving them&lt;/strong&gt;, turning strategy into actionable steps.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;787&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-1-1024x787.png&quot; alt=&quot;&quot; class=&quot;wp-image-47585&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-1-1024x787.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-1-300x230.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-1-768x590.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-1-50x38.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-1-52x40.png 52w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-1-604x464.png 604w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-1-696x535.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-1-560x430.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-1-385x296.png 385w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-1-614x472.png 614w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-1-80x61.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-1-48x37.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/image-1.png 1208w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Here’s where it gets a bit more nuanced: &lt;strong&gt;not every KPI is tied to an OKR.&lt;/strong&gt; The KPIs you use in OKRs are directly linked to key results — they are quantitative, time-bound, and aligned with your strategy, representing the metrics you’re actively trying to improve.&lt;/p&gt;



&lt;p&gt;Alongside these, you’ll often track &lt;strong&gt;health KPIs&lt;/strong&gt;: metrics you monitor to ensure your broader strategy stays on track while pursuing specific objectives.&lt;/p&gt;



&lt;p&gt;For example, if your focus this quarter is acquisition and activation, your goals might be to increase new paying subscribers and improve trial-to-paid conversion rates. At the same time, you’ll want to keep an eye on metrics like first-to-second month renewal rate to make sure you’re attracting quality users. An often-overlooked health metric is refund rate, which can highlight whether expectations aren’t being managed properly as you scale acquisition.&lt;/p&gt;



&lt;p&gt;Let’s hope I didn’t overload your brain with all that. Now, we’ll cover how to work out your OKRs and KPIs. Even if you already have KPIs in place, revisiting these steps can help ensure you’re tracking the right metrics. So grab another cup of coffee — we’ve diving in!&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-1-determine-your-north-star-metric&quot;&gt;Step 1: determine your North Star metric&lt;/h2&gt;



&lt;p&gt;&lt;strong&gt;You can’t set effective OKRs until you know your North Star metric&lt;/strong&gt;, aka the single metric that best reflects how you deliver value to customers and capture value as a business. This metric remains consistent over time and guides all your actions. Once you have it, you can work backward to identify the KPIs that matter most and influence your NSM.&lt;/p&gt;



&lt;p&gt;For example, Spotify’s NSM is minutes listened, which is influenced by KPIs like the number of sessions and minutes per session — metrics they likely monitor regularly.&lt;/p&gt;



&lt;p&gt;Here are &lt;a href=&quot;https://www.revenuecat.com/blog/growth/north-star-metrics-subscription-growth/&quot;&gt;five strong examples of North Star metrics&lt;/a&gt; for subscription apps:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Active subscribers&lt;/strong&gt;: keeps the focus on engagement and retention&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Core usage metrics&lt;/strong&gt;: measures the key action that drives value, like workouts completed or songs listened&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Active users&lt;/strong&gt;: useful for freemium models where engagement drives conversion&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Net returning revenue&lt;/strong&gt;: tracks revenue growth from existing subscribers&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Realized LTV per paying customer&lt;/strong&gt;: ensures acquisition stays profitable&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;What your NSM &lt;em&gt;shouldn’t&lt;/em&gt; be is revenue. Using revenue as your NSM can incentivize short-term hacks, such as hiding cancellation options, aggressive discounting, or other tactics that don’t create genuine, long-term customer value. &lt;strong&gt;Your NSM should guide you toward building a product that truly delivers value to your users.&lt;/strong&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-2-identify-the-kpis-per-step-of-your-growth-model&quot;&gt;Step 2: identify the KPIs per step of your growth model&lt;/h2&gt;



&lt;p&gt;Once you have your North Star metric, you can start mapping out your growth funnel: what does your acquisition, activation, engagement, retention, and monetization flow look like, and which metrics matter at each stage?&lt;/p&gt;



&lt;p&gt;From there, you can start mapping out your growth diagram: what does your funnel (and growth loops) look like, and what are the relevant metrics per stage of it? As &lt;a href=&quot;https://www.revenuecat.com/blog/author/ryan-kotzebue/&quot;&gt;Ryan Kotzebue&lt;/a&gt;, explains in his article on &lt;a href=&quot;https://www.revenuecat.com/blog/growth/subscription-metrics-mobile-apps/&quot;&gt;subscription metrics&lt;/a&gt;, subscription apps fundamentally revolve around two things:&amp;nbsp;&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Selling subscriptions (acquisition)&lt;/li&gt;



&lt;li&gt;Retaining subscribers (retention)&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Layered on top of that is monetization, which ensures your app is sustainable. To track these effectively, you need KPIs for each stage of the funnel. The ‘best’ KPIs depend on your app, your growth drivers, and the actions relevant to your business.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;But before we get to that, I want to address one of the most common questions I get from startups: how do KPIs vary per growth stage?&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-kpis-per-growth-stage&quot;&gt;KPIs per growth stage&lt;/h3&gt;



&lt;p&gt;At different stages, you’ll focus more or less on certain metrics:&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Early stage: &lt;/strong&gt;&amp;nbsp;you’re likely still figuring out which metrics matter. What does retention look like? What drives value for users? Which metrics identify your product-market fit, and what numbers help answer ‘&lt;em&gt;can we get people to pay for this?&lt;/em&gt;’&amp;nbsp;&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Scaling up&lt;/strong&gt;: shift KPI focus toward engagement and retention to build long-term loyal customers and unlocks additional acquisition channels.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Later stage&lt;/strong&gt;: once you have a solid base, look more closely at monetization and efficiency, e.g.&amp;nbsp; how to increase ARPPU and unlock expansion revenue to reduce churn and grow lifetime value.&lt;/li&gt;
&lt;/ol&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-Z150lSP wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Pro tip&quot; text=&quot;&lt;p&gt;During early stage growth, depending on your model and funding, you may also need to consider unit economics or volume (e.g. a marketplace app).&amp;nbsp;&lt;/p&gt;&quot; icon=&quot;bulb&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;p&gt;Metrics across all stages are important, but which ones you track as KPIs depends on which part of the customer journey you want to understand.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Let’s look at some recommended (and less recommended) KPIs for each stage of the funnel.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-acquisition-kpis&quot;&gt;Acquisition KPIs&lt;/h3&gt;



&lt;p&gt;When it comes to acquisition, many teams start with the basics: &lt;strong&gt;cost of acquisition&lt;/strong&gt; (CAC) or &lt;strong&gt;return on ad spend&lt;/strong&gt; (ROAS). But the real question isn’t just what you’re spending — it’s whether you’re attracting profitable customers and earning enough per user to scale sustainably.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/ltv-cac-subscription-apps-alternatives/&quot;&gt;A common trap is relying on the LTV-to-CAC ratio&lt;/a&gt;. For subscription apps, this is a shaky metric: it’s lagging, unstable, and can easily give you a false sense of growth.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Instead, focus on metrics that give you a clearer picture of customer profitability, such as:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Average revenue per paying user (ARPPU) &lt;/strong&gt;at meaningful milestones (Day 0, Day 7, Day 30, Day 90, etc.)&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Payback period:&lt;/strong&gt; how long it takes for cohorts to recoup CAC&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Gross contribution after CAC&lt;/strong&gt;: how much profit remains after acquisition costs at Month 3, 6, and 12&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Many apps get distracted by platform metrics like &lt;strong&gt;cost per click&lt;/strong&gt; or &lt;strong&gt;click-through rate&lt;/strong&gt;. These have their place for channel optimization, but they won’t tell you &lt;a href=&quot;https://www.revenuecat.com/blog/growth/metrics-for-scaling-paid-ads/#h-realized-ltv-per-paying-customer-average-revenue-per-paying-user-arppu&quot;&gt;whether you can scale profitably&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;Another common misstep, as Hanna pointed out in our workshop, is focusing on total downloads. It’s an easy number to inflate with ad spend, but it rarely reflects real value. As she put it with a great analogy: “Being proud of downloads without engagement is like bragging about having lots of Tinder matches… but never actually going on dates.”&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-activation-kpis&quot;&gt;Activation KPIs&lt;/h3&gt;



&lt;p&gt;We’re looking at the percentage of acquired users who activate:&amp;nbsp;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Trial start:&lt;/strong&gt; installs that start a trial&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Trial-to-paid: &lt;/strong&gt;trials that convert to paid&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Download-to-paid: &lt;/strong&gt;installs that convert to paid&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;These metrics reveal where drop-offs happen, and help pinpoint whether it’s due to fewer trials starting or lower trial conversion — which becomes even more relevant if you don’t offer a trial at all.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;em&gt;Note: Some apps classify these metrics under acquisition, while others place them under activation; it often depends on team ownership and whether traffic quality is a major focus&lt;/em&gt;.&lt;/p&gt;



&lt;p&gt;You’ll also want to track the &lt;em&gt;aha!&lt;/em&gt;&lt;strong&gt; &lt;/strong&gt;moment — the point when users first experience real value. You can experiment early on by measuring engagement with key features to find which best predict paying or retained users. For example, at Fishbrain, they let users upload a past catch immediately, reducing time-to-value and boosting activation.&lt;/p&gt;



&lt;p&gt;Other useful signals:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Time to aha! moment&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Onboarding completion rate&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Plan type selected&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Each of these metrics offer value as they can influence monetization later on. What’s less helpful is just counting total trials started — that often drives volume over quality and lower-value users.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-engagement-kpis&quot;&gt;Engagement KPIs&lt;/h3&gt;



&lt;p&gt;A common starting point is tracking &lt;strong&gt;daily, weekly, or monthly active users (DAU/WAU/MAU). &lt;/strong&gt;But alone this doesn’t offer much insight. ‘Active’ shouldn’t mean simply opening the app; it should reflect meaningful use.&lt;/p&gt;



&lt;p&gt;Many subscription apps also track &lt;strong&gt;stickiness&lt;/strong&gt; by dividing DAU/MAU (or WAU/MAU for less frequent use cases). This helps you gauge how effectively your app builds user habits over time.&lt;/p&gt;



&lt;p&gt;Other useful &lt;a href=&quot;https://www.revenuecat.com/blog/growth/app-engagement-metrics-subscription-apps/&quot;&gt;engagement metrics&lt;/a&gt; focus on feature usage, helping you understand which features are most valuable to users. One metric that’s often overemphasized, however, is session length — for most apps, it doesn’t necessarily reflect real value or meaningful use.&lt;/p&gt;



&lt;p&gt;The goal with engagement KPIs is to identify metrics that:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Capture usage frequency and, where relevant, duration&lt;/li&gt;



&lt;li&gt;Reflect a depth of interaction (beyond simply opening the app)&lt;/li&gt;



&lt;li&gt;Provide early insights into retention and potentially an &lt;a href=&quot;https://www.revenuecat.com/blog/growth/how-to-spot-churn-before-it-happens/&quot;&gt;early warning of churn&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;Relate closely to monetization and conversion&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Two additional metrics often tracked as &lt;strong&gt;health indicators&lt;/strong&gt; are &lt;strong&gt;average rating &lt;/strong&gt;(on iOS and Android), as well as, &lt;strong&gt;number of reviews&lt;/strong&gt;. A sudden drop in ratings or review volume can highlight user experience issues. And &lt;a href=&quot;https://www.revenuecat.com/blog/growth/why-ratings-and-reviews-in-aso-are-more-important-than-ever/&quot;&gt;if you’re focused on ASO, these are critical for growth and visibility.&lt;/a&gt;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-retention-kpis&quot;&gt;Retention KPIs&lt;/h3&gt;



&lt;p&gt;Retention is one of the strongest indicators of long-term success, but how you measure it depends on your subscription model. Common retention periods include Day 1, 7, 30, 90, and 365, as well as the renewal rate percentage.&lt;/p&gt;



&lt;p&gt;This is particularly critical for:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Monthly subscriptions&lt;/strong&gt;: focus on the first-month renewal rate&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Annual subscriptions&lt;/strong&gt;: track renewal rate and first-year renewal rate&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Keep in mind that retention metrics are often lagging indicators, which is why pairing them with engagement KPIs can give you earlier insights.&lt;/p&gt;



&lt;p&gt;Another key metric is &lt;strong&gt;churn rate&lt;/strong&gt; — split by voluntary (user-initiated cancelations) vs. involuntary (payment failures). This distinction helps you prioritize the right retention strategies.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-monetization-kpis&quot;&gt;Monetization KPIs&lt;/h3&gt;



&lt;p&gt;We’ve already touched on the &lt;a href=&quot;https://www.revenuecat.com/blog/growth/what-is-lifetime-value-ltv-apps/&quot;&gt;challenges of using Lifetime Value (LTV)&lt;/a&gt; for acquisition. When it comes to monetization, the key metric is &lt;strong&gt;revenue per user&lt;/strong&gt;. Generally, ARPPU (average revenue per paying user) — also referred to as &lt;a href=&quot;https://www.revenuecat.com/docs/dashboard-and-metrics/charts/realized-ltv-per-paying-customer-chart#:~:text=Realized%20LTV%20(Lifetime%20Value)%20per,of%20customers%20in%20that%20cohort.&quot;&gt;Realized LTV per paying user &lt;/a&gt;— is a strong measure for tracking this over time and calculating your payback period.&lt;/p&gt;



&lt;p&gt;While revenue itself isn’t a strong North Star metric, many apps track &lt;a href=&quot;https://www.revenuecat.com/docs/dashboard-and-metrics/charts/monthly-recurring-revenue-mrr-chart&quot;&gt;&lt;strong&gt;monthly recurring revenue&lt;/strong&gt; (MRR)&lt;/a&gt; or &lt;strong&gt;net revenue retention&lt;/strong&gt; (NRR), as they tie together retention, upsells, and downgrades. However, for OKRs specifically, these can be a bit too broad to drive focused action.&lt;/p&gt;



&lt;p&gt;Another valuable metric, particularly for later-stage apps, is &lt;strong&gt;expansion revenue&lt;/strong&gt; %, which tracks upsells, plan upgrades, and add-ons.&lt;/p&gt;



&lt;p&gt;Finally, &lt;strong&gt;refund rates&lt;/strong&gt; are often overlooked but can significantly erode your revenue if left unchecked, making them an important health KPI to monitor.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-3-bring-your-kpis-together-and-measure-performance&quot;&gt;Step 3. Bring your KPIs together and measure performance&lt;/h2&gt;



&lt;p&gt;Once you’ve selected your KPIs of choice, it’s time to bring them together. Rosie shared that she likes to take a super old-school approach (refreshing in an era obsessed with AI!) by drawing out the growth model by hand, then transferring it into a Google Sheet to track performance.&lt;/p&gt;



&lt;p&gt;Next, she compares the metrics to relevant benchmarks — the &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps-2025/&quot;&gt;State of Subscription Report 2025&lt;/a&gt; is a great resource for this. A word of caution: &lt;a href=&quot;https://www.revenuecat.com/blog/growth/sub-club-podcast-phil-carter-2025/&quot;&gt;benchmarks aren’t the be-all and end-all&lt;/a&gt;. They can vary widely across apps, so it’s also important to factor in historical data and common sense when deciding what’s realistic for your own app.&lt;/p&gt;



&lt;p&gt;She then recommends color-coding metrics by performance; something I also do every quarter for the brands I work with.&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Green:&lt;/strong&gt; working well, not a focus point right now&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Orange: &lt;/strong&gt;working, but room for improvement&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Red: &lt;/strong&gt;needs improving&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;If you’re a startup, please don’t be disheartened by lots of red, as that’s completely normal! This is where strategy comes in. Take a step back (and another one), and ask yourself: which areas need the most improvement first, and which changes will have the biggest impact on the rest of your funnel?&lt;/p&gt;



&lt;p&gt;When I’m debating which metric to focus on, I estimate the potential improvement this quarter then create a rough calculation of the impact that change could have over the coming year. This helps put different areas into perspective and narrow the focus. It’s a useful exercise to do individually or in small teams, then cross-compare calculations and assumptions.&lt;/p&gt;



&lt;p&gt;Remember: OKRs are all about focus. Trying to include ten KPIs under one broad OKR that spans the entire funnel adds little value. &lt;strong&gt;It’s better to hone in on a few high-impact metrics that truly drive your objectives.&lt;/strong&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-4-finalize-your-okrs&quot;&gt;Step 4. Finalize your OKRs&lt;/h2&gt;



&lt;p&gt;Now it’s time to start designing your OKRs. Remember: your objective is what you hope to achieve or change, while your key results use KPIs as precise measures of success. KRs represent outcomes that move you toward your objective, not a checklist of tasks or initiatives.&lt;/p&gt;



&lt;p&gt;The way I think about it: &lt;strong&gt;you should be confident that if you hit your key results, you’ll achieve your objective.&lt;/strong&gt; That level of certainty isn’t possible with a simple list of tasks.&lt;/p&gt;



&lt;p&gt;For example, let’s say your OKR looks like this:&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Objective:&lt;/strong&gt; Increase the % of annual subscriptions&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Key result 1:&lt;/strong&gt; increase the % of new subscribers choosing annual over monthly by 20%&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Key result 2: &lt;/strong&gt;increase the number of upsells to annual by 15%&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;There are many initiatives you could test to achieve these KRs. Not all will work, but you can be confident that if more new and existing subscribers choose the annual option, it will positively impact monetization.&lt;/p&gt;



&lt;p&gt;A less effective OKR would look like this:&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Objective:&lt;/strong&gt; increase the % of annual subscriptions&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Key result 1: &lt;/strong&gt;run five email campaigns promoting annual plans&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Key result 2: &lt;/strong&gt;add upsell emails into the onboarding flow&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Key result 3: &lt;/strong&gt;launch a paywall test where annual plans are the default&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Key result 5: &lt;/strong&gt;add a pop-up offering a one-off discount on annual plans&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;You could run all these initiatives and still fail to increase the % of annual subscriptions. That’s why key results need to be measurable outcomes, so you know whether you’re actually moving toward your objective. This also gives you the flexibility to pivot if your current approach isn’t driving results.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-shared-objectives-separate-kpis&quot;&gt;Shared objectives, separate KPIs&lt;/h3&gt;



&lt;p&gt;It’s important to align OKRs across teams, ideally at the company level, with multiple teams contributing through their own KPIs. This encourages collaboration and prevents an overflow of too many OKRs.&lt;/p&gt;



&lt;p&gt;That said, make sure the KPIs aren’t competing. Hanna shared a great example: two key metrics Fishbrain tracked were ad revenue and subscription revenue. Focusing on both created conflicting goals, which led to misalignment instead of collaboration. So always double-check that your KPIs bring teams closer together rather than create competition.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-okrs-should-be-challenging&quot;&gt;OKRs should be challenging&lt;/h3&gt;



&lt;p&gt;When creating OKRs, involve your team and ask: will these really push us? OKRs aren’t meant to be fully achieved every quarter. A common benchmark of success is 0–1, with the goal of achieving an average of 0.6–0.7 across your main 3–5 OKRs. This ensures your goals are ambitious enough to drive meaningful progress.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-5-share-your-okrs-internally&quot;&gt;Step 5. Share your OKRs internally&amp;nbsp;&lt;/h2&gt;



&lt;p&gt;This step really deserves its own focus because it’s so important. I once went on a work trip with most of our team to discuss a change in direction. We spent hours brainstorming, debating, and finalizing the OKRs for the upcoming quarter. I was excited to share them internally and happily presented them to the rest of the team.&lt;/p&gt;



&lt;p&gt;Here’s the problem: the Head of Product hadn’t attended the optional work trip, so he missed all the context behind the OKRs. This was a double mistake on my part:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Not involving a key stakeholder&lt;/strong&gt; in finalizing and setting the OKRs&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Not telling the story&lt;/strong&gt; behind why those OKRs were chosen, and taking people along on that journey&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;He ended up providing really valuable feedback, and ultimately he was fully onboard — but it was a tough conversation. He didn’t appreciate being skipped over and didn’t understand where this major shift had come from.&lt;/p&gt;



&lt;p&gt;The takeaway: &lt;strong&gt;communicate the &lt;/strong&gt;&lt;strong&gt;&lt;em&gt;story&lt;/em&gt;&lt;/strong&gt;&lt;strong&gt; behind your OKRs as clearly as the OKRs themselves&lt;/strong&gt;. Rosie emphasizes that OKRs should be so clear that any team member could recite them without needing to look.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-6-build-an-okr-rhythm&quot;&gt;Step 6. Build an OKR rhythm&lt;/h2&gt;



&lt;p&gt;OKRs need to be &lt;strong&gt;ingrained in your day-to-day work&lt;/strong&gt;. While you set them quarterly, you should be reviewing relevant KPIs &lt;strong&gt;weekly&lt;/strong&gt;, usually through dashboards, and reflecting on OKR progress &lt;strong&gt;each sprint&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;At the end of the quarter, it’s time to &lt;strong&gt;score your OKRs&lt;/strong&gt;. Some teams do this subjectively (how close did we get to achieving the objective?), while others score each key result from &lt;strong&gt;0–1&lt;/strong&gt; based on progress relative to the starting point, and calculate the average. Make sure to &lt;strong&gt;celebrate achievements&lt;/strong&gt;, even if you aren’t hitting 1s across the board — hitting 1s consistently usually means your OKRs were too easy.&lt;/p&gt;



&lt;p&gt;OKRs become most powerful after a few quarters, as you develop a rhythm for working, reflecting, and learning what’s effective. Each quarter, review your KPIs to ensure they remain relevant. You may need to revise them during the quarter. Rosie’s advice is to &lt;strong&gt;use KPIs until they break&lt;/strong&gt;, because as your app evolves, metrics that once mattered may need adjustment.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-mythbusters-kpi-edition&quot;&gt;Mythbusters: KPI edition&lt;/h2&gt;



&lt;p&gt;Before including a KPI in your growth model or reviewing it, ask yourself:&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;1. Is it truthful?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;As Rosie Hoggmascall put it in the webinar, truthful metrics drive value — they can’t be gamed or inflated artificially.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;2. Is it simple to understand?&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Avoid overly complex metrics that are hard to explain or rarely used. Companies sometimes get distracted by clever, calculated metrics instead of focusing on clear, actionable ones.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;3. Is it leading?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;While lagging metrics like churn are important, they should be complemented with leading indicators. For example, average revenue per user after seven days can help predict improvements in lifetime value.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;4. Can you trust the data?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;A KPI is only as good as the data behind it. If teams doubt the accuracy of tracking, they’ll doubt the metric itself. Regularly audit your tracking setup.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;5. Does it align teams?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;KPIs should bring teams together, not create conflicting goals. For instance, measuring one team on trials started and another on trial-to-paid conversion can cause tension; driving more trials might hurt conversion quality.&lt;/p&gt;



&lt;p&gt;These checks are essential whenever you add a KPI. Just because you can measure something doesn’t mean you should. Fewer, more meaningful KPIs will give you clearer signals, and you can always dig deeper when needed.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-okrs-are-a-powerful-tool-when-used-correctly&quot;&gt;OKRs are a powerful tool… when used &lt;em&gt;correctly&lt;/em&gt;&lt;/h2&gt;



&lt;p&gt;At their best, OKRs are much more than another quarterly to-do item or a set of forgotten slides. They &lt;strong&gt;translate your strategy into clear, measurable steps&lt;/strong&gt; that everyone on your team understands and feels ownership of. KPIs keep you honest, showing whether your work is actually making a difference and whether you’re focusing on the right things.&lt;/p&gt;



&lt;p&gt;For subscription apps, growth depends on balancing acquisition, activation, engagement, retention, and monetization — OKRs and KPIs provide the structure behind this balance. They allow you to &lt;strong&gt;zoom out on the big vision while zooming in on the metrics that prove progress&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;If there’s one key takeaway: don’t drown yourself in data, and don’t get lost in vanity metrics. Be intentional:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Choose a &lt;strong&gt;North Star metric&lt;/strong&gt; that reflects value for both your business and your customers&lt;/li&gt;



&lt;li&gt;Build &lt;strong&gt;KPIs around the stages of your funnel&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;Use &lt;strong&gt;OKRs to drive focus and collaboration each quarter&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;When approached this way, you’re not just tracking numbers for the sake of it (or dreading OKR check-ins like I once did). You’re making &lt;strong&gt;real progress toward your vision&lt;/strong&gt;, staying connected to the bigger picture, and creating impact that compounds over time.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Understanding the native SDK wrapper pattern in Kotlin Multiplatform]]></title><description><![CDATA[In this deep dive, we’ll explore how RevenueCat’s delegation pattern wraps native Android and iOS SDKs, enables effortless bidirectional conversion, and minimizes wrapper overhead.]]></description><link>https://www.revenuecat.com/blog/engineering/kmp-wrapper-pattern/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/kmp-wrapper-pattern/</guid><pubDate>Mon, 03 Nov 2025 15:50:09 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/11/Understanding-the-native-SDK-wrapper-pattern-in-Kotlin-Multiplatform.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Kotlin Multiplatform (KMP) has revolutionized how developers approach cross-platform development, allowing code to be shared across Android, iOS, and other platforms while maintaining native performance and capabilities.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;But when building a multiplatform SDK, one of the most challenging decisions is whether to&amp;nbsp; reimplement all the platform-specific logic from scratch, or wrap existing native SDKs?&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/getting-started/installation/kotlin-multiplatform&quot;&gt;RevenueCat’s Purchases KMP SDK&lt;/a&gt; chose the wrapping approach. The engineering decisions behind its implementation come from a desire to maintain clean, type-safe interfaces while delegating to battle-tested native code. The result is a wrapper system that &lt;strong&gt;avoids data duplication&lt;/strong&gt;, &lt;strong&gt;maintains state consistency&lt;/strong&gt;, and &lt;strong&gt;provides seamless bidirectional conversion&lt;/strong&gt; between KMP and native types.&lt;/p&gt;



&lt;p&gt;In the following deep dive, we’ll explore the delegation pattern used by &lt;a href=&quot;https://www.revenuecat.com/&quot;&gt;RevenueCat&lt;/a&gt;, and how it gracefully wraps native Android and iOS SDKs, the engineering decisions that make bidirectional conversion effortless, and the subtle optimizations that keep the wrapper overhead minimal.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-understanding-the-core-problem-why-wrap-instead-of-reimplement&quot;&gt;&lt;strong&gt;Understanding the core problem: Why wrap instead of reimplement&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;When building a multiplatform SDK, you face a fundamental architectural choice between sharing code and preserving platform-specific behavior. In our case at RevenueCat, we needed to integrate with the App Store on iOS and Google Play on Android, both of which have complex, platform-specific APIs.&lt;/p&gt;



&lt;p&gt;So there’s two options:&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Option 1. Pure KMP reimplementation:&lt;/strong&gt; Reimplement all the business logic in common code and use expect/actual only for the thinnest possible platform layer. This gives you maximum control but requires duplicating complex logic that already exists in well-tested native SDKs.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Option 2. Wrap existing native SDKs:&lt;/strong&gt; Leverage existing, battle-tested native implementations and create a thin KMP wrapper that provides a unified interface. This reduces implementation complexity but introduces the challenge of maintaining a clean abstraction layer.&lt;/p&gt;



&lt;p&gt;RevenueCat chose the latter, wrapping our existing Android and iOS SDKs (which themselves wrap the Android Billing Client and iOS StoreKit). This decision made sense for several reasons:&lt;/p&gt;



&lt;p&gt;The native SDKs have years of production-hardening and edge case handling. Billing and subscription logic involves complex state machines, network retry logic, receipt validation, and platform-specific quirks that would be expensive to reimplement.&lt;/p&gt;



&lt;p&gt;The wrapper approach allows us to maintain a single source of truth for business logic in the native SDKs, while the KMP layer focuses purely on providing a unified API surface.&lt;/p&gt;



&lt;p&gt;However, this introduces a new challenge: how do you design a wrapper that doesn’t create data synchronization problems, minimize performance overhead, and maintain type safety across the boundary?&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;the-expectactual-foundation&quot;&gt;&lt;strong&gt;The expect/actual foundation&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;If you have tried any Kotlin Multiplatform architecture, you’ll see it starts with Kotlin’s expect/actual mechanism. The common code declares what the API should look like, while platform-specific code provides the actual implementation.&lt;/p&gt;



&lt;p&gt;The common interface looks like below in the RevenueCats KMP SDK:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Ytzll wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;public expect class Purchases {\n    public companion object {\n        public val sharedInstance: Purchases\n        public var logLevel: LogLevel\n        public fun configure(configuration: PurchasesConfiguration): Purchases\n        public fun canMakePayments(features: List&lt;BillingFeature&gt;, callback: (Boolean) -&gt; Unit)\n    }\n\n    public fun getOfferings(onError: (error: PurchasesError) -&gt; Unit, onSuccess: (Offerings) -&gt; Unit)\n    public fun purchase(storeProduct: StoreProduct, onError: ..., onSuccess: ...)\n    \/\/ ... many more functions\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This is a pure interface declaration, no implementation, no platform specifics. Developers using the SDK see only this clean API. The platform differences are completely hidden.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;the-wrapper-delegation-pattern&quot;&gt;&lt;strong&gt;The wrapper delegation pattern&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The actual implementations reveal the clever delegation strategy. Let’s examine the Android implementation:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-2eeuYQ wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;import com.revenuecat.purchases.Purchases as AndroidPurchases\n\npublic actual class Purchases private constructor(\n    private val androidPurchases: AndroidPurchases\n) {\n    public actual companion object {\n        private var _sharedInstance: Purchases? = null\n\n        public actual fun configure(configuration: PurchasesConfiguration): Purchases {\n            with(configuration) {\n                commonConfigure(\n                    context = AndroidProvider.requireApplication(),\n                    apiKey = apiKey,\n                    appUserID = appUserId,\n                    purchasesAreCompletedBy = purchasesAreCompletedBy.toHybridString(),\n                    platformInfo = PlatformInfo(\n                        flavor = BuildKonfig.platformFlavor,\n                        version = frameworkVersion,\n                    ),\n                    store = (store ?: Store.PLAY_STORE).toAndroidStore(),\n                    dangerousSettings = dangerousSettings.toAndroidDangerousSettings(),\n                    shouldShowInAppMessagesAutomatically = showInAppMessagesAutomatically,\n                    verificationMode = verificationMode.name,\n                    pendingTransactionsForPrepaidPlansEnabled = pendingTransactionsForPrepaidPlansEnabled\n                )\n            }\n\n            return Purchases(AndroidPurchases.sharedInstance).also { _sharedInstance = it }\n        }\n    }\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The critical detail: &lt;code&gt;private val androidPurchases&lt;/code&gt;: &lt;code&gt;AndroidPurchases&lt;/code&gt;. The KMP Purchases class doesn’t duplicate the native implementation, it &lt;strong&gt;wraps&lt;/strong&gt; it. Every KMP method delegates to the wrapped native object.&lt;/p&gt;



&lt;p&gt;The iOS implementation follows the same pattern:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-2rbdak wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;import cocoapods.PurchasesHybridCommon.RCPurchases as IosPurchases\n\npublic actual class Purchases private constructor(\n    private val iosPurchases: IosPurchases\n) {\n    public actual companion object {\n        private var _sharedInstance: Purchases? = null\n\n        public actual fun configure(configuration: PurchasesConfiguration): Purchases {\n            with(configuration) {\n                configureWithAPIKey(\n                    apiKey = apiKey,\n                    appUserID = appUserId,\n                    observerMode = purchasesAreCompletedBy.toHybridString() != \&amp;quot;REVENUE_CAT\&amp;quot;,\n                    userDefaultsSuiteName = userDefaults,\n                    platformFlavor = BuildKonfig.platformFlavor,\n                    platformFlavorVersion = frameworkVersion,\n                    usesStoreKit2IfAvailable = storeKitVersion.usesStoreKit2IfAvailable,\n                    \/\/ ... more configuration\n                )\n            }\n\n            return Purchases(IosPurchases.sharedInstance()).also { _sharedInstance = it }\n        }\n    }\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Notice the symmetry: both platforms wrap their native singleton (&lt;code&gt;AndroidPurchases.sharedInstance&lt;/code&gt; and &lt;code&gt;IosPurchases.sharedInstance()&lt;/code&gt;), but the KMP code presents a unified interface to the consumer.&lt;/p&gt;



&lt;p&gt;This pattern has a profound implication: there is &lt;strong&gt;no data duplication&lt;/strong&gt;. The KMP wrapper doesn’t copy data from the native object, it holds a reference to it. This eliminates an entire class of bugs related to state synchronization.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;the-mapping-layer-bridging-kmp-and-native-types&quot;&gt;&lt;strong&gt;The mapping layer: bridging KMP and native types&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The delegation pattern works well for the main SDK class, but what about data types? When you call &lt;code&gt;getOfferings()&lt;/code&gt;, the native SDK returns platform-specific types (&lt;code&gt;com.revenuecat.purchases.Offerings &lt;/code&gt;on Android, &lt;code&gt;RCOfferings&lt;/code&gt; on iOS). How do you convert these to a common KMP type?&lt;/p&gt;



&lt;p&gt;This is where the mapping layer shines. RevenueCat implements a wrapper pattern for data types that maintains the same delegation principle. Let’s examine &lt;code&gt;StoreProduct&lt;/code&gt;, which represents a purchasable item.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-common-interface&quot;&gt;&lt;strong&gt;The common interface&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;First, the common code defines an interface:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z19O468 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;public interface StoreProduct {\n    public val id: String\n    public val type: ProductType\n    public val category: ProductCategory?\n    public val price: Price\n    public val title: String\n    public val localizedDescription: String?\n    public val period: Period?\n\n    \/\/ Android-specific properties (null on iOS)\n    public val subscriptionOptions: SubscriptionOptions?\n    public val defaultOption: SubscriptionOption?\n\n    \/\/ iOS-specific properties (empty\/null on Android)\n    public val discounts: List&lt;StoreProductDiscount&gt;\n    public val introductoryDiscount: StoreProductDiscount?\n\n    public val purchasingData: PurchasingData\n    public val presentedOfferingContext: PresentedOfferingContext?\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This is a unified interface that exposes both Android and iOS concepts. Some properties are platform-specific (marked in comments), but the interface itself is common. This design allows platform-aware code while maintaining a single type definition.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-android-wrapper-implementation&quot;&gt;&lt;strong&gt;The Android wrapper implementation&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Now look at how the Android platform implements this:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZkG7g9 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;import com.revenuecat.purchases.models.StoreProduct as NativeAndroidStoreProduct\n\npublic fun StoreProduct.toAndroidStoreProduct(): NativeAndroidStoreProduct =\n    (this as AndroidStoreProduct).wrapped\n\npublic fun NativeAndroidStoreProduct.toStoreProduct(): StoreProduct =\n    AndroidStoreProduct(this)\n\nprivate class AndroidStoreProduct(\n    val wrapped: NativeAndroidStoreProduct,\n): StoreProduct {\n    override val id: String = wrapped.id\n    override val type: ProductType = wrapped.type.toProductType()\n    override val category: ProductCategory? = type.toProductCategoryOrNull()\n    override val price: Price = wrapped.price.toPrice()\n    override val title: String = wrapped.title\n    override val localizedDescription: String = wrapped.description\n    override val period: Period? = wrapped.period?.toPeriod()\n    override val subscriptionOptions: SubscriptionOptions? =\n        wrapped.subscriptionOptions?.toSubscriptionOptions()\n    override val defaultOption: SubscriptionOption? =\n        wrapped.defaultOption?.toSubscriptionOption()\n    override val discounts: List&lt;StoreProductDiscount&gt; = emptyList()\n    override val introductoryDiscount: StoreProductDiscount? = null\n    override val purchasingData: PurchasingData = AndroidPurchasingData(wrapped.purchasingData)\n    override val presentedOfferingContext: PresentedOfferingContext? =\n        wrapped.presentedOfferingContext?.toPresentedOfferingContext()\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Several remarkable patterns emerge here:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;The wrapper class is private&lt;/strong&gt;: Consumers never see &lt;code&gt;AndroidStoreProduct&lt;/code&gt;. They only interact with the &lt;code&gt;StoreProduct&lt;/code&gt; interface. This encapsulation is critical for maintaining API flexibility.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;The wrapped native object is stored&lt;/strong&gt;:&lt;code&gt; val wrapped: NativeAndroidStoreProduct&lt;/code&gt; holds a reference to the actual Android SDK object. Every property access delegates to this wrapped instance.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Properties are evaluated lazily by delegation&lt;/strong&gt;: When you access &lt;code&gt;storeProduct.id&lt;/code&gt;, it reads &lt;code&gt;wrapped.id&lt;/code&gt; at that moment. There’s no caching or copying, the value comes directly from the source of truth.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Platform-specific properties return appropriate defaults&lt;/strong&gt;: The Android implementation returns &lt;code&gt;emptyList()&lt;/code&gt; for &lt;code&gt;discounts&lt;/code&gt; (an iOS-only feature) and &lt;code&gt;null&lt;/code&gt; for &lt;code&gt;introductoryDiscount&lt;/code&gt;. This graceful degradation is key to maintaining a unified interface.&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-ios-wrapper-implementation&quot;&gt;&lt;strong&gt;The iOS wrapper implementation&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The iOS side mirrors this structure:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-d8m95 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;import cocoapods.PurchasesHybridCommon.RCStoreProduct as NativeIosStoreProduct\n\npublic fun NativeIosStoreProduct.toStoreProduct(): StoreProduct =\n    IosStoreProduct(this)\n\npublic fun StoreProduct.toIosStoreProduct(): NativeIosStoreProduct =\n    (this as IosStoreProduct).wrapped\n\nprivate class IosStoreProduct(val wrapped: NativeIosStoreProduct): StoreProduct {\n    override val id: String = wrapped.productIdentifier()\n    override val type: ProductType = wrapped.productType().toProductType()\n    override val category: ProductCategory = wrapped.productCategory().toProductCategory()\n    override val price: Price = wrapped.toPrice()\n    override val title: String = wrapped.localizedTitle()\n    override val localizedDescription: String = wrapped.localizedDescription()\n    override val period: Period? = wrapped.subscriptionPeriod()?.toPeriod()\n    override val subscriptionOptions: SubscriptionOptions? = null\n    override val defaultOption: SubscriptionOption? = null\n    override val discounts: List&lt;StoreProductDiscount&gt; = wrapped.discounts()\n        .map { it as IosStoreProductDiscount }\n        .map { it.toStoreProductDiscount() }\n    override val introductoryDiscount: StoreProductDiscount? =\n        wrapped.introductoryDiscount()?.toStoreProductDiscount()\n    override val purchasingData: PurchasingData = IosPurchasingData(wrapped)\n    override val presentedOfferingContext: PresentedOfferingContext? = null\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The symmetry looks good. Both platforms follow the exact same pattern: wrap the native object, delegate property access, return platform-appropriate values for unsupported features.&lt;/p&gt;



&lt;p&gt;Notice the difference in API style: Android uses property syntax (&lt;code&gt;wrapped.id&lt;/code&gt;), while iOS uses function calls (&lt;code&gt;wrapped.productIdentifier()&lt;/code&gt;). This reflects the underlying platform conventions, Kotlin properties on Android, Objective-C methods via Cocoapods on iOS. The wrapper abstracts these differences into a uniform interface.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;the-bidirectional-conversion-strategy&quot;&gt;&lt;strong&gt;The bidirectional conversion strategy&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The genius of RevenueCat’s mapping layer lies in its bidirectional conversion functions. Look at the conversion functions again:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1kMt95 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/\/ Android\npublic fun StoreProduct.toAndroidStoreProduct(): NativeAndroidStoreProduct =\n    (this as AndroidStoreProduct).wrapped\n\npublic fun NativeAndroidStoreProduct.toStoreProduct(): StoreProduct =\n    AndroidStoreProduct(this)&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;When you convert from KMP to native (&lt;code&gt;toAndroidStoreProduct()&lt;/code&gt;), it doesn’t create a new object or copy data. It simply &lt;strong&gt;unwraps&lt;/strong&gt; the reference to the native object that was already there. This is a cast followed by a property access, effectively zero cost at runtime.&lt;/p&gt;



&lt;p&gt;When you convert from native to KMP (&lt;code&gt;toStoreProduct()&lt;/code&gt;), it wraps the native object in the private wrapper class. This allocates one small wrapper object, but the heavy data (product details, pricing information, etc.) remains in the native object.&lt;/p&gt;



&lt;p&gt;This bidirectional conversion enables a powerful programming model:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1UBaNk wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/\/ SDK receives native Android product from the billing library\nval nativeProduct: NativeAndroidStoreProduct = getFromAndroidBillingClient()\n\n\/\/ Wrap it for KMP consumers\nval kmpProduct: StoreProduct = nativeProduct.toStoreProduct()\n\n\/\/ Later, when calling a native API, unwrap it\nval purchaseParams = PurchaseParams.Builder()\n    .setProduct(kmpProduct.toAndroidStoreProduct())\n    .build()&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The native object flows through the KMP layer without being copied. This pattern appears throughout the SDK:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1OGLlC wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;public actual fun purchase(\n    storeProduct: StoreProduct,\n    onError: (error: PurchasesError, userCancelled: Boolean) -&gt; Unit,\n    onSuccess: (storeTransaction: StoreTransaction, customerInfo: CustomerInfo) -&gt; Unit,\n) {\n    androidPurchases.purchaseWith(\n        PurchaseParams.Builder(\n            activity = AndroidProvider.requireActivity(),\n            purchasingData = storeProduct.toAndroidStoreProduct().purchasingData\n        ).build()\n    ) { purchase, customerInfo -&gt;\n        onSuccess(\n            purchase.toStoreTransaction(),\n            customerInfo.toCustomerInfo()\n        )\n    }\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;storeProduct&lt;/code&gt; comes in as a KMP type, gets unwrapped to call the native API (&lt;code&gt;toAndroidStoreProduct()&lt;/code&gt;), and the results get wrapped back into KMP types (&lt;code&gt;toStoreTransaction(), toCustomerInfo()&lt;/code&gt;). The wrapper layer acts as a zero-copy bridge.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;handling-platform-differences-gracefully&quot;&gt;&lt;strong&gt;Handling platform differences gracefully&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;One of the most remarkable aspects of RevenueCat’s wrapper design is how it handles unavoidable platform differences. The App Store and Google Play have fundamentally different subscription models:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;iOS subscriptions&lt;/strong&gt; use subscription groups with promotional offers, introductory pricing, and win-back offers&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Android subscriptions&lt;/strong&gt; use base plans with multiple subscription options, each containing pricing phases&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Rather than forcing one model onto the other, RevenueCat exposes both in the common interface through nullable properties:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-2qO1z1 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;public interface StoreProduct {\n    \/\/ Android-only\n    public val subscriptionOptions: SubscriptionOptions?\n    public val defaultOption: SubscriptionOption?\n\n    \/\/ iOS-only\n    public val discounts: List&lt;StoreProductDiscount&gt;\n    public val introductoryDiscount: StoreProductDiscount?\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This design allows platform-specific code to access platform features while common code works with the intersection:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-I6c4W wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/\/ Platform-specific code can check for Android features\nif (product.subscriptionOptions != null) {\n    \/\/ We&apos;re on Android, can access subscription options\n    val monthlyOption = product.subscriptionOptions.basePlan.monthlyOption\n}\n\n\/\/ Common code works with guaranteed properties\nval productPrice = product.price\nval productId = product.id&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;For method-level platform differences, RevenueCat uses different strategies. Some methods throw helpful errors:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z10nx0Y wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;public actual fun getPromotionalOffer(\n    product: StoreProduct,\n    discount: StoreProductDiscount,\n    onError: (error: PurchasesError) -&gt; Unit,\n    onSuccess: (offer: PromotionalOffer) -&gt; Unit,\n): Unit = error(\n    \&amp;quot;Getting promotional offers is not possible on Android. \&amp;quot; +\n    \&amp;quot;Did you mean StoreProduct.subscriptionOptions?\&amp;quot;\n)\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Others gracefully degrade:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-2mEudE wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;public actual fun checkTrialOrIntroPriceEligibility(\n    products: List&lt;StoreProduct&gt;,\n    callback: (Map&lt;StoreProduct, IntroEligibilityStatus&gt;) -&gt; Unit,\n) {\n    logHandler.v(\n        tag = \&amp;quot;Purchases\&amp;quot;,\n        msg = \&amp;quot;Checking trial or introductory price eligibility is only available on iOS\&amp;quot;\n    )\n    callback(products.associateWith { IntroEligibilityStatus.UNKNOWN })\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This design communicates platform capabilities clearly. A runtime error catches platform-mismatched code during development, while graceful degradation provides sensible behavior when features genuinely aren’t available.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;the-property-delegation-optimization&quot;&gt;&lt;strong&gt;The property delegation optimization&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;RevenueCat takes the delegation pattern even further with Kotlin’s property delegation syntax:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZeEQTn wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;public actual val isConfigured: Boolean by AndroidPurchases.Companion::isConfigured&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This delegates the &lt;code&gt;isConfigured&lt;/code&gt; property directly to the native SDK’s property using a method reference. It’s the ultimate zero-overhead wrapper, no custom getter, no function call overhead, just pure delegation to the underlying field.&lt;/p&gt;



&lt;p&gt;You see this pattern used for simple properties that don’t need type conversion:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-23Udgr wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;public actual var simulatesAskToBuyInSandbox: Boolean\n    get() = IosPurchases.simulatesAskToBuyInSandbox()\n    set(value) = IosPurchases.setSimulatesAskToBuyInSandbox(value)&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The getter directly calls the native getter. The setter directly calls the native setter. The wrapper is transparent.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;real-world-implications-and-performance-characteristics&quot;&gt;&lt;strong&gt;Real-world implications and performance characteristics&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;This wrapper architecture has specific performance characteristics worth understanding:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Allocation overhead is minimal&lt;/strong&gt;: Each wrapped object allocates one small wrapper instance, but the actual data remains in the native object. For a &lt;code&gt;StoreProduct&lt;/code&gt;, you allocate a tiny &lt;code&gt;AndroidStoreProduct&lt;/code&gt; or &lt;code&gt;IosStoreProduct&lt;/code&gt; wrapper, while the full product details live in the native SDK’s memory.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;No synchronization overhead&lt;/strong&gt;: Because the wrapper doesn’t copy data, there’s no synchronization to maintain. The wrapper always reflects the current state of the native object.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Method call overhead is single-dispatch&lt;/strong&gt;: Every method call goes through one level of delegation: KMP wrapper → native implementation. Modern JVMs and iOS runtimes inline this effectively.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Type conversion happens on-demand&lt;/strong&gt;: When you access product.price, the conversion from native Price to KMP Price happens at that moment. If you never access certain properties, they’re never converted.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Bidirectional conversion is zero-copy&lt;/strong&gt;: Converting KMP → native is a type cast and property access. Converting native → KMP allocates only the wrapper object.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The trade-off is that you must ensure all conversions are correct. A bug in the mapping layer would propagate through the entire SDK. This is why RevenueCat’s mapping functions are tested extensively and why keeping them simple (pure delegation) reduces bug surface area.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;wrapping-up&quot;&gt;&lt;strong&gt;&lt;em&gt;Wrapping&lt;/em&gt;&lt;/strong&gt;&lt;strong&gt; up&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;We’ve explored how &lt;a href=&quot;https://www.revenuecat.com/docs/getting-started/installation/kotlin-multiplatform&quot;&gt;RevenueCat’s KMP SDK&lt;/a&gt; uses a great wrapper delegation pattern to bridge native Android and iOS implementations with a unified multiplatform API. By now, you should have a clear sense of how to design a shared architecture that feels both native and maintainable across platforms.&lt;/p&gt;



&lt;p&gt;The key idea isn’t just the expect/actual pattern or wrapper delegation,&amp;nbsp; it’s how these techniques work together to balance code reuse with platform fidelity. When done right, you get the best of both worlds: clean abstractions, zero-copy efficiency, and a scalable foundation for future multiplatform work.&lt;/p&gt;



&lt;p&gt;This architecture demonstrates that wrapping native SDKs doesn’t mean compromising on performance or API quality. By carefully designing the wrapper to delegate rather than duplicate, RevenueCat achieves the best of both worlds: a unified API surface powered by battle-tested native implementations.Whether you’re wrapping existing native libraries in KMP, designing data transfer objects across platform boundaries, or building SDK abstractions, these patterns provide a foundation for clean, performant multiplatform code. The key insight is simple but clear: &lt;strong&gt;don’t copy, delegate&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;If you’d like to learn how we decided to adopt the wrapper pattern, check out &lt;a href=&quot;https://www.revenuecat.com/blog/engineering/how-we-built-the-revenuecat-sdk-for-kotlin-multiplatform/&quot;&gt;How We Built the RevenueCat SDK for Kotlin Multiplatform&lt;/a&gt;.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Make your paywall do more than sell: 7 unexpected uses for your paywall]]></title><description><![CDATA[How great paywalls go beyond the buy button to educate, build trust and grow retention]]></description><link>https://www.revenuecat.com/blog/growth/paywalls-unexpected-uses/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/paywalls-unexpected-uses/</guid><pubDate>Wed, 29 Oct 2025 17:51:04 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Make-your-paywall-do-more-than-sell.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;I’ve always found the term &lt;em&gt;paywall&lt;/em&gt; a little strange. It’s a wall that says: &lt;strong&gt;pay up now. &lt;/strong&gt;It’s harsh. Cold. A brick barrier standing between you and what you want to do. If you don’t pay, you can’t pass — or, in the case of freemium apps, you have to awkwardly climb over the proverbial wall.&amp;nbsp;But it doesn’t have to be just that. The term ‘&lt;a href=&quot;https://www.revenuecat.com/glossary/#paywall&quot;&gt;paywall&lt;/a&gt;’ itself limits the idea, as it frames that screen as solely about payment. But in reality, paywall screens can do so much more.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-examples-of-paywall-purposes-beyond-monetization&quot;&gt;Examples of paywall purposes (beyond monetization)&lt;/h2&gt;



&lt;p&gt;Here are all the things a good paywall can do — but only if you think beyond the transaction.&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Educate and frame value&lt;/li&gt;



&lt;li&gt;Build trust&lt;/li&gt;



&lt;li&gt;Create an emotional connection&lt;/li&gt;



&lt;li&gt;Guide user behavior&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Reinforce progress&lt;/li&gt;



&lt;li&gt;Improve retention&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Gather insights into your customers&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;While these ideas will inspire you to improve your paywall, it’s crucial to set up &lt;a href=&quot;https://www.revenuecat.com/blog/growth/guide-to-mobile-paywalls-subscription-apps/&quot;&gt;paywall tests &lt;/a&gt;first, and take a structured approach to experimenting with your paywall. You should particularly keep in mind the differences between iOS and Android, especially in terms of user demographics and behavior.&lt;/p&gt;



&lt;p&gt;You also need to consider &lt;em&gt;where&lt;/em&gt; your paywall appears, and what it needs to achieve. For example, a paywall immediately after onboarding may not need to educate as much, because the onboarding itself has already done the heavy lifting.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;I once interviewed &lt;a href=&quot;https://www.linkedin.com/in/rosie-hoggmascall/&quot;&gt;Rosie Hoggmascall&lt;/a&gt;, Growth at Fyxer AI and author of Growth Dives, on &lt;a href=&quot;https://www.revenuecat.com/blog/growth/how-top-apps-approach-paywalls/&quot;&gt;what the best subscription apps get right about paywalls&lt;/a&gt;. She shared a great example from a previous app. They tested three flows:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;A: Welcome screen → onboarding → home → paywall = 2% trial opt-in&lt;/li&gt;



&lt;li&gt;B: Welcome screen → paywall → onboarding → home = 8% trial opt-in&lt;/li&gt;



&lt;li&gt;C: Welcome screen → new three-slide carousel → paywall → onboarding → home = 15% trial opt-in&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The experiment showed that context matters in deciding what your paywall should do beyond selling. A paywall deeper in your app, for instance, may not need as much lead-in, and instead could focus on highlighting progress or deepening the emotional connection with users.&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-1bQwLV wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Find inspiration with real paywall examples on Paywalls.com&quot; text=&quot;&lt;p&gt;Browse real examples at &lt;a href=&amp;quot;https://www.paywalls.com/&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noopener&amp;quot;&gt;Paywalls.com&lt;/a&gt;: filter paywall screens by different UI elements, app category, and trending and top-growth paywalls.&lt;/p&gt;&quot; icon=&quot;sparks&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;p&gt;So, here are seven unexpected ways you can put your paywall to work, along with real-world examples.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-1-educate-and-frame-value&quot;&gt;1. Educate and frame value&lt;/h2&gt;



&lt;p&gt;If you want people to pay, you first need to clearly convey the value they’ll get and &lt;strong&gt;help them understand why your app is worth it. &lt;/strong&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/ugly-paywalls-conversion-testing/?utm_source=chatgpt.com&quot;&gt;Golf Gamebook does this particularly well&lt;/a&gt;. Their paywalls highlight exactly what users can do with the app, such as live leaderboards and creating tournaments:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;964&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Golf-Gamebook-paywall-combined-964x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-47551&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Golf-Gamebook-paywall-combined-964x1024.png 964w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Golf-Gamebook-paywall-combined-283x300.png 283w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Golf-Gamebook-paywall-combined-768x815.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Golf-Gamebook-paywall-combined-47x50.png 47w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Golf-Gamebook-paywall-combined-38x40.png 38w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Golf-Gamebook-paywall-combined-437x464.png 437w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Golf-Gamebook-paywall-combined-696x739.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Golf-Gamebook-paywall-combined-527x560.png 527w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Golf-Gamebook-paywall-combined-279x296.png 279w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Golf-Gamebook-paywall-combined-445x472.png 445w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Golf-Gamebook-paywall-combined-75x80.png 75w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Golf-Gamebook-paywall-combined-45x48.png 45w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Golf-Gamebook-paywall-combined.png 1183w&quot; sizes=&quot;auto, (max-width: 964px) 100vw, 964px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;This approach helps users see what they can achieve and why a payment makes sense. On another paywall, they clearly outline the user outcomes, focusing on the tangible results golfers hope to see: “lower their handicap 4x faster”.&lt;/p&gt;



&lt;p&gt;While Golf Gamebook may not have the most (typically) pretty paywall, a recent blog post from &lt;a href=&quot;https://www.linkedin.com/in/hannagrevelius/&quot;&gt;Hanna Grevelius&lt;/a&gt;, CPO at Bruce Studios, &lt;a href=&quot;https://www.revenuecat.com/blog/growth/ugly-paywalls-conversion-testing/&quot;&gt;tested these paywalls&lt;/a&gt; and found that simple, clear paywalls (or ‘ugly’ ones, if you’re feeling brutally honest!) consistently outperform more branded or polished variants.&lt;strong&gt; In short, getting value across matters far more than fancy design.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Another strong example comes from banking app &lt;a href=&quot;https://vivid.money/en-eu/&quot;&gt;Vivid&lt;/a&gt;, who clearly present the different features that come with each paid plan.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;774&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Vivid-paywall-combined-1024x774.png&quot; alt=&quot;&quot; class=&quot;wp-image-47549&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Vivid-paywall-combined-1024x774.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Vivid-paywall-combined-300x227.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Vivid-paywall-combined-768x580.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Vivid-paywall-combined-1536x1160.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Vivid-paywall-combined-50x38.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Vivid-paywall-combined-53x40.png 53w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Vivid-paywall-combined-614x464.png 614w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Vivid-paywall-combined-696x526.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Vivid-paywall-combined-560x423.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Vivid-paywall-combined-392x296.png 392w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Vivid-paywall-combined-625x472.png 625w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Vivid-paywall-combined-80x60.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Vivid-paywall-combined-48x36.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Vivid-paywall-combined.png 1664w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;It can be overwhelming to figure out which plan you need and whether it’s worth it, but Vivid makes it easy. Users can swipe to compare the main differences, scroll for more details, and immediately understand what they’ll gain.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note: &lt;/strong&gt;I will say slight minus points for focusing on features over &lt;a href=&quot;https://www.revenuecat.com/blog/growth/jtbd-paywall-optimization/&quot;&gt;job-to-be-done&lt;/a&gt; (JTBD), but I can imagine with a bank you need to be crystal clear on how features differ per plan.&amp;nbsp;&lt;/em&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;2-build-trust&quot;&gt;2. Build trust&amp;nbsp;&lt;/h2&gt;



&lt;p&gt;It’s easy to assume that just because someone downloaded your app and tried it out, they automatically trust you. But even if they came through a referral or already know your brand, &lt;strong&gt;trust still needs to be earned.&lt;/strong&gt; Think of it like dating: one good date doesn’t mean 100% trust overnight; it takes time.&lt;/p&gt;



&lt;p&gt;Your paywall can help build that trust in two key ways:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Social proof (e.g. reviews, ratings, App Store features)&lt;/li&gt;



&lt;li&gt;Clarity around the payment setup&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;A great example of this was &lt;a href=&quot;https://www.enjoybloom.com/&quot;&gt;Bloom&lt;/a&gt;, a self-guided therapy app (since acquired by Spring Health, now discontinued), which used a two-part paywall:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;The first part built a sense of progress (more on that later) and established trust with honesty — &lt;a href=&quot;https://www.revenuecat.com/blog/engineering/how-to-build-a-blinkist-style-paywall-using-revenuecat-webhooks-and-zapier/&quot;&gt;similar to Blinkist’s paywall&lt;/a&gt; — by clearly explaining how the trial works and assuring users they could get a full refund, even if they forgot to cancel. Very few apps highlight this so boldly.&lt;/li&gt;



&lt;li&gt;The second part leaned on social proof:&lt;/li&gt;
&lt;/ol&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Loved by two million users&lt;/li&gt;



&lt;li&gt;App of the day&lt;/li&gt;



&lt;li&gt;4.8/5 rating with 21,000+ reviews&lt;/li&gt;



&lt;li&gt;#1 app for self-guided therapy&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The result? A paywall that does far more than sell; it builds trust in the app and reassures users that they’re making the right choice.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;907&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Bloom-paywall-combined-907x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-47547&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Bloom-paywall-combined-907x1024.png 907w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Bloom-paywall-combined-266x300.png 266w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Bloom-paywall-combined-768x867.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Bloom-paywall-combined-44x50.png 44w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Bloom-paywall-combined-35x40.png 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Bloom-paywall-combined-411x464.png 411w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Bloom-paywall-combined-696x786.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Bloom-paywall-combined-496x560.png 496w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Bloom-paywall-combined-262x296.png 262w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Bloom-paywall-combined-418x472.png 418w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Bloom-paywall-combined-71x80.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Bloom-paywall-combined-43x48.png 43w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Bloom-paywall-combined.png 1116w&quot; sizes=&quot;auto, (max-width: 907px) 100vw, 907px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;A key part of building trust is following &lt;a href=&quot;https://www.revenuecat.com/blog/growth/is-monetization-hurting-your-apps-user-experience/&quot;&gt;ethical monetization practices&lt;/a&gt;, rather than relying on &lt;a href=&quot;https://www.revenuecat.com/blog/growth/black-hat-aso-app-store-optimization/&quot;&gt;black hat tactics&lt;/a&gt; to gain attention or traction. You need clarity of your payment structure. Bloom executed this well:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Pricing is always presented on a per-period basis, rather than only per week, to avoid misleading comparisons&lt;/li&gt;



&lt;li&gt;When offering a trial with a yearly plan, it clearly states that monthly and lifetime plans don’t include a trial (rather than just not mentioning a trial, it clearly states “no trial”)&lt;/li&gt;



&lt;li&gt;Users are informed exactly when they will be charged and how to cancel their subscription&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;A more unusual approach? Let your users set their own prices. During my paywall research, I came across &lt;a href=&quot;https://www.rocketmoney.com/&quot;&gt;Rocket Money&lt;/a&gt; (formerly Truebill, another notable example of an acquired company). Instead of imposing a price, the app allows users to choose how much they want to pay, giving them control and reinforcing trust. I’ve personally never seen this be done before.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;473&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Rocket-Money-paywall-473x1024.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47504&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Rocket-Money-paywall-473x1024.jpg 473w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Rocket-Money-paywall-139x300.jpg 139w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Rocket-Money-paywall-768x1663.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Rocket-Money-paywall-709x1536.jpg 709w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Rocket-Money-paywall-23x50.jpg 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Rocket-Money-paywall-18x40.jpg 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Rocket-Money-paywall-214x464.jpg 214w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Rocket-Money-paywall-696x1507.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Rocket-Money-paywall-259x560.jpg 259w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Rocket-Money-paywall-137x296.jpg 137w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Rocket-Money-paywall-218x472.jpg 218w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Rocket-Money-paywall-37x80.jpg 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Rocket-Money-paywall-22x48.jpg 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Rocket-Money-paywall.jpg 923w&quot; sizes=&quot;auto, (max-width: 473px) 100vw, 473px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;I suppose they have to get creative, as after all, Rocket Money is a subscription service for managing subscriptions. But ultimately, anything that builds trust on the paywall is compelling, since it also positively impacts retention. With four million premium members, this social proof further reinforces that the service is worth the investment. (And if you’re wondering if this is a pricing test, I’m pretty confident it’s not, as they’ve been using this approach since their Truebill times.)&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;3-create-an-emotional-connection&quot;&gt;3. Create an emotional connection&lt;/h2&gt;



&lt;p&gt;Behind most app users is &lt;a href=&quot;https://www.revenuecat.com/blog/growth/solve-app-problems-emotionally/&quot;&gt;an emotional driver&lt;/a&gt;, something that motivates them to use your app and keeps them coming back. According to &lt;a href=&quot;https://hbr.org/2015/11/the-new-science-of-customer-emotions&quot;&gt;The New Science of Customer Emotions&lt;/a&gt;, there are ten emotional drivers behind human behavior:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Stand out from the crowd&lt;/li&gt;



&lt;li&gt;Have confidence in the future&lt;/li&gt;



&lt;li&gt;Enjoy a sense of well-being&lt;/li&gt;



&lt;li&gt;Feel a sense of freedom&lt;/li&gt;



&lt;li&gt;Feel a sense of thrill&lt;/li&gt;



&lt;li&gt;Feel a sense of belonging&lt;/li&gt;



&lt;li&gt;Protect the environment&lt;/li&gt;



&lt;li&gt;Be the person I want to be&lt;/li&gt;



&lt;li&gt;Feel secure&lt;/li&gt;



&lt;li&gt;Succeed in life&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;&lt;strong&gt;To build an emotional connection, start by identifying which of these drivers resonate most with your target audience. &lt;/strong&gt;Conduct &lt;a href=&quot;https://www.revenuecat.com/blog/growth/what-drives-users-to-pay-jobs-to-be-done/&quot;&gt;in-depth customer research&lt;/a&gt;, dive deep into what drives their behaviour, and why they see your app as a solution to their problem.&lt;/p&gt;



&lt;p&gt;Once you understand your audience, your paywall becomes the perfect place to convey that emotional connection to new users. This can be communicated through:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Value proposition language that aligns with their motivations&lt;/li&gt;



&lt;li&gt;Talking about the outcomes they’ll achieve with your app&lt;/li&gt;



&lt;li&gt;Visuals and design that reinforce the feeling of understanding&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;a href=&quot;https://www.joinladder.com/&quot;&gt;Ladder&lt;/a&gt;, a workout app, does this well with a simple phrase on their paywall: “Get results, without planning workouts.” It communicates the 10th driver — helping users succeed — while removing a common pain point: planning workouts. Ladder excels at &lt;a href=&quot;https://subclub.com/episode/boost-conversion-and-retention-with-jobs-to-be-done-daphne-tideman-growth-advisor&quot;&gt;understanding their audience’s JTBD&lt;/a&gt; and applying that insight consistently across every touchpoint, from ads to the App Store, paywall, and the app itself.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;452&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-paywall-452x1024.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47506&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-paywall-452x1024.jpg 452w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-paywall-132x300.jpg 132w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-paywall-768x1741.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-paywall-678x1536.jpg 678w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-paywall-22x50.jpg 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-paywall-18x40.jpg 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-paywall-205x464.jpg 205w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-paywall-696x1577.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-paywall-247x560.jpg 247w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-paywall-131x296.jpg 131w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-paywall-208x472.jpg 208w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-paywall-35x80.jpg 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-paywall-21x48.jpg 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Ladder-paywall.jpg 882w&quot; sizes=&quot;auto, (max-width: 452px) 100vw, 452px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Compared to these standout examples, most paywalls are painfully standard. In reviewing hundreds of paywalls, I was struck by how many simply defaulted to the duplicate tired headlines, such as:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Ready to start?&lt;/li&gt;



&lt;li&gt;Get a free trial&lt;/li&gt;



&lt;li&gt;See how your trial works&lt;/li&gt;



&lt;li&gt;Choose your plan&lt;/li&gt;



&lt;li&gt;Unlock all features&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;I think this stems from a fear of being unclear. But especially deeper within your app, users start to recognize your paywall. That’s the perfect moment to s&lt;strong&gt;hift focus toward your value proposition rather than just asking them to pay&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;A good example of this balance is &lt;a href=&quot;https://www.koho.ca/&quot;&gt;KOHO&lt;/a&gt;, a Canadian financial app. During onboarding, they take the classic approach — educating users about their options and clarifying pricing — which sets a strong foundation via the initial paywall:&lt;/p&gt;



&lt;p&gt;But later in the app, when users start looking into building their credit score, KOHO shifts focus to the feeling of security, aka the ninth emotional driver. Their paywall becomes more visual and simplified, highlighting the tangible benefits of a better credit score, such as qualifying for a better loan, getting a new car, or even buying a house — &lt;strong&gt;focusing on the outcome, and the emotion behind it&lt;/strong&gt;.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;902&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Koho-paywall-combined-902x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-47545&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Koho-paywall-combined-902x1024.png 902w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Koho-paywall-combined-264x300.png 264w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Koho-paywall-combined-768x872.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Koho-paywall-combined-44x50.png 44w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Koho-paywall-combined-35x40.png 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Koho-paywall-combined-409x464.png 409w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Koho-paywall-combined-696x790.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Koho-paywall-combined-493x560.png 493w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Koho-paywall-combined-261x296.png 261w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Koho-paywall-combined-416x472.png 416w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Koho-paywall-combined-70x80.png 70w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Koho-paywall-combined-42x48.png 42w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Koho-paywall-combined.png 1110w&quot; sizes=&quot;auto, (max-width: 902px) 100vw, 902px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Another powerful way to create an emotional connection is by using references or individuals your users relate to, injecting personality into your app.&lt;strong&gt; &lt;/strong&gt;This can be tricky to achieve in a single screen, which is why some apps experiment with &lt;a href=&quot;https://www.revenuecat.com/blog/growth/weird-paywalls-drive-subscription-growth/&quot;&gt;unusual or quirky paywalls&lt;/a&gt; to stand out.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://coinstats.app/&quot;&gt;CoinStats&lt;/a&gt;, a cryptocurrency app, does this particularly well. They regularly update and test paywalls with fun, seasonal, or pop-culture references, keeping the experience fresh and engaging for their users.&lt;/p&gt;



&lt;p&gt;In one example, they featured Giga Chad (apparently well-known among crypto traders) dressed as Santa on their paywall — no guessing the season they tested this! This approach creates a sense of familiarity and humanizes the app, strengthening the emotional connection.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;535&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/CoinStats.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47512&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/CoinStats.jpg 535w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/CoinStats-157x300.jpg 157w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/CoinStats-26x50.jpg 26w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/CoinStats-21x40.jpg 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/CoinStats-242x464.jpg 242w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/CoinStats-293x560.jpg 293w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/CoinStats-155x296.jpg 155w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/CoinStats-247x472.jpg 247w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/CoinStats-42x80.jpg 42w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/CoinStats-25x48.jpg 25w&quot; sizes=&quot;auto, (max-width: 535px) 100vw, 535px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;CoinStats has &lt;a href=&quot;https://www.businessofapps.com/insights/paywall-optimization-reimagined/&quot;&gt;shared the data on this&lt;/a&gt;, and they found that these contextual, playful paywalls have had a positive impact on conversion rates on both Android and iOS.&lt;/p&gt;



&lt;p&gt;Going weird and funny can be an effective way to build an emotional connection, as long as the content is relevant and appropriate for the moment in the user journey.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;4-guide-user-behavior&quot;&gt;4. Guide user behavior&lt;/h2&gt;



&lt;p&gt;Most users have no idea what plan is right for them, and even if they need to subscribe. &lt;strong&gt;Your paywall can help reduce this friction by nudging them toward the best choice.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;You’ve probably seen these common questions pop up at paywalls:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Should I opt for a monthly or annual plan?&lt;/li&gt;



&lt;li&gt;How does the trial work?&lt;/li&gt;



&lt;li&gt;What do I get at each tier?&lt;/li&gt;



&lt;li&gt;Which tier will suit me best?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Many apps address these questions in basic ways, such as framing the price differences between plans, and these methods remain the most popular because they simplify decision-making and reduce uncertainty for users. We see this with &lt;a href=&quot;https://www.duolingo.com/&quot;&gt;Duolingo&lt;/a&gt;, the language learning app, and &lt;a href=&quot;https://www.fitplanapp.com/&quot;&gt;Fitplan&lt;/a&gt;, a workout app below:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;451&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Duolingo-paywall-451x1024.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47514&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Duolingo-paywall-451x1024.jpg 451w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Duolingo-paywall-132x300.jpg 132w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Duolingo-paywall-768x1745.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Duolingo-paywall-676x1536.jpg 676w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Duolingo-paywall-22x50.jpg 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Duolingo-paywall-18x40.jpg 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Duolingo-paywall-204x464.jpg 204w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Duolingo-paywall-696x1581.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Duolingo-paywall-247x560.jpg 247w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Duolingo-paywall-130x296.jpg 130w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Duolingo-paywall-208x472.jpg 208w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Duolingo-paywall-35x80.jpg 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Duolingo-paywall-21x48.jpg 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Duolingo-paywall.jpg 880w&quot; sizes=&quot;auto, (max-width: 451px) 100vw, 451px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Both apps guide users effectively by:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Clearly showing price per plan&lt;/li&gt;



&lt;li&gt;Highlighting what the plans include at the top (Fitplan)&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Displaying trial length clearly (in Duolingo’s case they make it the CTA)&lt;/li&gt;



&lt;li&gt;Breaking down the price per week/month, making it easier to compare options&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;They also each guide choices, but in slightly different ways:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Duolingo emphasizes the most popular options and indicates the number of members allowed on a Family Plan.&lt;/li&gt;



&lt;li&gt;Fitplan highlights that their annual subscription is the Best Value&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;These seem like simple changes, but implemented in an ethical way they can guide user behavior towards the right choice.&lt;/p&gt;



&lt;p&gt;We also often underestimate the power of reducing friction and noise, compared to adding more information. &lt;a href=&quot;https://www.linkedin.com/in/vahebaghdasaryan/&quot;&gt;Vahe Baghdasaryan&lt;/a&gt;, Growth Manager at Flo Health, shared &lt;a href=&quot;https://www.revenuecat.com/blog/growth/paywall-redesigns-case-studies/&quot;&gt;four redesigns of popular paywalls&lt;/a&gt; — and in three of them, simplifying the paywall led to improvements in conversion rates. Once again: &lt;strong&gt;simplicity creates clarity&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;Another strong example is &lt;a href=&quot;https://linktr.ee/s/linktree-app-for-ios-android&quot;&gt;Linktree&lt;/a&gt;, a link-in-bio app that serves multiple audiences, ranging from creators to businesses. Their paywall clearly explains each plan in simple terms, helping users understand which one might be right for them, while also offering the option to read more of the benefits:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;904&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Linktree-paywall-combined-904x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-47543&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Linktree-paywall-combined-904x1024.png 904w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Linktree-paywall-combined-265x300.png 265w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Linktree-paywall-combined-768x870.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Linktree-paywall-combined-44x50.png 44w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Linktree-paywall-combined-35x40.png 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Linktree-paywall-combined-409x464.png 409w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Linktree-paywall-combined-696x789.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Linktree-paywall-combined-494x560.png 494w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Linktree-paywall-combined-261x296.png 261w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Linktree-paywall-combined-417x472.png 417w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Linktree-paywall-combined-71x80.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Linktree-paywall-combined-42x48.png 42w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Linktree-paywall-combined.png 1111w&quot; sizes=&quot;auto, (max-width: 904px) 100vw, 904px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The best apps take this a step further by personalizing paywalls based on platform, country, or stage in the user journey. For example, you may focus on different features and usages depending on where someone is based or what they’ve used in your app so far.&lt;/p&gt;



&lt;p&gt;While this might sound like a lot of work, it’s often straightforward with tools like &lt;a href=&quot;https://www.revenuecat.com/blog/growth/revenuecat-paywalls-v2&quot;&gt;RevenueCat paywalls&lt;/a&gt;. Product-market fit can vary by country, so the features and plans you emphasize should match the local use case to maximize conversion.&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-1IP0of wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Learn more&quot; text=&quot;&lt;p&gt;&lt;a href=&amp;quot;https://www.revenuecat.com/blog/growth/guide-to-mobile-paywalls-subscription-apps&amp;quot;&gt;Here&apos;s 24 ways to use targeting&lt;/a&gt; to optimize pricing, packaging, and paywalls for custom audiences.&lt;/p&gt;&quot; icon=&quot;bulb&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;5-reinforce-progress&quot;&gt;5. Reinforce progress&lt;/h2&gt;



&lt;p&gt;Especially for apps in fitness, education, and productivity, showing progress on your paywall can be a powerful motivator; it reminds users that your app is helping them move forward.&lt;/p&gt;



&lt;p&gt;We saw this in the earlier example of Bloom, the self-help app. Starting therapy can be a big and scary thing, so simply acknowledging that the first step of registration is a step completed can help users feel a sense of accomplishment right away — thus, they’re more likely to want to complete the list of action points.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.opal.so/&quot;&gt;Opal&lt;/a&gt;, a focus app, uses a similar approach. Their trial explanation builds clarity and sets expectations for results with a &lt;a href=&quot;https://www.youtube.com/watch?v=aJp7m4TYK7E&quot;&gt;timeline design&lt;/a&gt;:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;452&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Opal-paywall-452x1024.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47520&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Opal-paywall-452x1024.jpg 452w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Opal-paywall-132x300.jpg 132w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Opal-paywall-768x1741.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Opal-paywall-678x1536.jpg 678w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Opal-paywall-22x50.jpg 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Opal-paywall-18x40.jpg 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Opal-paywall-205x464.jpg 205w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Opal-paywall-696x1577.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Opal-paywall-247x560.jpg 247w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Opal-paywall-131x296.jpg 131w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Opal-paywall-208x472.jpg 208w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Opal-paywall-35x80.jpg 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Opal-paywall-21x48.jpg 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Opal-paywall.jpg 882w&quot; sizes=&quot;auto, (max-width: 452px) 100vw, 452px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;This paywall says: you got your “focus diagnosis” today. By blocking apps, you’ll immediately improve your focus, and by day six, you should start to see results before your trial ends. This not only communicates value, but outlines the value users will see &lt;em&gt;before &lt;/em&gt;the trial ends — practically making the free trial a no-lose situation. It also offers value while educating users: “Start your Free Week and gain 2+ hours back”. (If only I’d found Opal back when I was deep in the throes of &lt;a href=&quot;https://www.revenuecat.com/blog/growth/gamification-in-apps-complete-guide/&quot;&gt;my Township addiction&lt;/a&gt;…)&lt;/p&gt;



&lt;p&gt;I also love the way &lt;a href=&quot;https://www.alltrails.com/en-gb/&quot;&gt;AllTrails&lt;/a&gt;, the hiking app, does this through positive framing of the progress you’ll make:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;473&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/AllTrails-paywall.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47522&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/AllTrails-paywall.jpg 473w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/AllTrails-paywall-139x300.jpg 139w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/AllTrails-paywall-23x50.jpg 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/AllTrails-paywall-18x40.jpg 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/AllTrails-paywall-214x464.jpg 214w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/AllTrails-paywall-259x560.jpg 259w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/AllTrails-paywall-137x296.jpg 137w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/AllTrails-paywall-218x472.jpg 218w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/AllTrails-paywall-37x80.jpg 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/AllTrails-paywall-22x48.jpg 22w&quot; sizes=&quot;auto, (max-width: 473px) 100vw, 473px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;After you’ve used the app to hike, their paywall states: “AllTrails+ members are 3 times more likely to hit the trail”. This combines progress with education, showing what the premium subscription offers while motivating continued use.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://web.meetcleo.com/&quot;&gt;Cleo&lt;/a&gt;, a banking app, takes it even further: selecting your subscription becomes one of the last to-dos on your progress list to encourage you to finish it. And yes, loving your credit score is now a possibility! This is a refreshing take.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;451&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Cleo-paywall-451x1024.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47524&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Cleo-paywall-451x1024.jpg 451w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Cleo-paywall-132x300.jpg 132w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Cleo-paywall-768x1745.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Cleo-paywall-676x1536.jpg 676w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Cleo-paywall-22x50.jpg 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Cleo-paywall-18x40.jpg 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Cleo-paywall-204x464.jpg 204w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Cleo-paywall-696x1581.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Cleo-paywall-247x560.jpg 247w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Cleo-paywall-130x296.jpg 130w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Cleo-paywall-208x472.jpg 208w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Cleo-paywall-35x80.jpg 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Cleo-paywall-21x48.jpg 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Cleo-paywall.jpg 880w&quot; sizes=&quot;auto, (max-width: 451px) 100vw, 451px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Other ways to reinforce progress include displaying progress bars at the top/bottom of the paywall or achievement callouts. For example, &lt;a href=&quot;https://www.thrivemarket.co.uk/&quot;&gt;Thrive Market&lt;/a&gt;, a grocery store, shows a progress bar at the top of their paywall. This helps you feel like it’s simple and easy to complete process.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;452&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Thrive-Market-paywall-452x1024.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47526&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Thrive-Market-paywall-452x1024.jpg 452w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Thrive-Market-paywall-132x300.jpg 132w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Thrive-Market-paywall-768x1741.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Thrive-Market-paywall-678x1536.jpg 678w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Thrive-Market-paywall-22x50.jpg 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Thrive-Market-paywall-18x40.jpg 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Thrive-Market-paywall-205x464.jpg 205w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Thrive-Market-paywall-696x1577.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Thrive-Market-paywall-247x560.jpg 247w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Thrive-Market-paywall-131x296.jpg 131w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Thrive-Market-paywall-208x472.jpg 208w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Thrive-Market-paywall-35x80.jpg 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Thrive-Market-paywall-21x48.jpg 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Thrive-Market-paywall.jpg 882w&quot; sizes=&quot;auto, (max-width: 452px) 100vw, 452px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;A more complex example is &lt;a href=&quot;https://www.noom.com/&quot;&gt;Noom&lt;/a&gt;, the weight loss app. On their paywall, they highlight that you’ve created and reserved a personalized plan:&lt;/p&gt;



&lt;p&gt;Using a landing-page style paywall, you scroll through a screen that:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Highlights the progress you’ll make on your plan on your weight loss journey&lt;/li&gt;



&lt;li&gt;Shows the benefits/features of your customized plan&lt;/li&gt;



&lt;li&gt;Lists the terms and conditions&lt;/li&gt;
&lt;/ul&gt;



&lt;figure class=&quot;wp-block-embed is-type-wp-embed is-provider-wistia-inc wp-block-embed-wistia-inc&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; class=&quot;wp-embedded-content&quot; sandbox=&quot;allow-scripts&quot; security=&quot;restricted&quot; title=&quot;Noom paywall Video&quot; src=&quot;https://fast.wistia.net/embed/iframe/uwp9bby6yb?dnt=1#?secret=uxn3AUSjmy&quot; data-secret=&quot;uxn3AUSjmy&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; width=&quot;346&quot; height=&quot;750&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;This approach makes a lot of sense for Noom, which sits at the higher end of subscription pricing (£94.99 every 2 months), a &lt;a href=&quot;https://www.revenuecat.com/blog/growth/2025-app-monetization-trends/&quot;&gt;monetization trend&lt;/a&gt; we’re seeing more often for apps. In an industry where results aren’t instant, they reinforce urgency with &lt;a href=&quot;https://www.revenuecat.com/blog/growth/subscription-pricing-psychology-how-to-influence-purchasing-decisions/#h-principle-3-the-scarcity-bias&quot;&gt;a pricing bias&lt;/a&gt; of scarcity: your personalized plan is only saved for 15 minutes, nudging users to take immediate action.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;6-improve-retention&quot;&gt;6. Improve retention&lt;/h2&gt;



&lt;p&gt;The most obvious way paywalls can influence retention is by &lt;strong&gt;guiding choices and encouraging longer subscriptions&lt;/strong&gt;. For example, highlighting annual value or offering trials only on annual plans, as 5 Minute Journal does:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;452&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/5-Minute-Journal-paywall-452x1024.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47530&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/5-Minute-Journal-paywall-452x1024.jpg 452w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/5-Minute-Journal-paywall-132x300.jpg 132w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/5-Minute-Journal-paywall-768x1741.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/5-Minute-Journal-paywall-678x1536.jpg 678w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/5-Minute-Journal-paywall-22x50.jpg 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/5-Minute-Journal-paywall-18x40.jpg 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/5-Minute-Journal-paywall-205x464.jpg 205w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/5-Minute-Journal-paywall-696x1577.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/5-Minute-Journal-paywall-247x560.jpg 247w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/5-Minute-Journal-paywall-131x296.jpg 131w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/5-Minute-Journal-paywall-208x472.jpg 208w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/5-Minute-Journal-paywall-35x80.jpg 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/5-Minute-Journal-paywall-21x48.jpg 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/5-Minute-Journal-paywall.jpg 882w&quot; sizes=&quot;auto, (max-width: 452px) 100vw, 452px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;I personally think this technique, while beneficial, isn’t necessarily boosting real retention. Yes, you’ll likely see an increase in average revenue per paying user (ARPPU), but &lt;a href=&quot;https://www.revenuecat.com/blog/growth/annual-subscriptions-apps-pros-cons/&quot;&gt;annual subscriptions&lt;/a&gt; can mask retention issues, as users may not be actively using the app.&lt;/p&gt;



&lt;p&gt;I believe paywalls drive better retention when they focus on much of what we’ve already discussed:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Creating an emotional connection with the app&lt;/li&gt;



&lt;li&gt;Reinforcing a feeling of progress, or showing the potential progress users can make&lt;/li&gt;



&lt;li&gt;Prioritizing customer value over discounts&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;To measure this effectively, you need to look beyond conversion rates and examine retention metrics, such as 90-day ARPPU and engagement with different paywalls. It’s harder to track (and takes longer to measure), but analyzing these metrics can reveal which paywall messaging drives high-quality, engaged users.&lt;br&gt;I love how &lt;a href=&quot;https://www.headspace.com/app&quot;&gt;Headspace&lt;/a&gt;, the meditation app, approaches this challenge. Their paywall emphasizes that building a meditation practice takes time — not just the savings of an annual subscription — helping users see the long-term value before switching from monthly to annual. This makes you feel like you want to dedicate time to meditation and invest in 12 months of mindfulness.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;451&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Headspace-paywall-451x1024.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47532&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Headspace-paywall-451x1024.jpg 451w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Headspace-paywall-132x300.jpg 132w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Headspace-paywall-768x1743.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Headspace-paywall-677x1536.jpg 677w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Headspace-paywall-22x50.jpg 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Headspace-paywall-18x40.jpg 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Headspace-paywall-204x464.jpg 204w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Headspace-paywall-696x1579.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Headspace-paywall-247x560.jpg 247w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Headspace-paywall-130x296.jpg 130w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Headspace-paywall-208x472.jpg 208w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Headspace-paywall-35x80.jpg 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Headspace-paywall-21x48.jpg 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Headspace-paywall.jpg 881w&quot; sizes=&quot;auto, (max-width: 451px) 100vw, 451px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-7-gather-insights-into-your-customers&quot;&gt;7. Gather insights into your customers&lt;/h2&gt;



&lt;p&gt;So far, we’ve focused on user-centered benefits, and rightly so. But paywalls also offer a powerful opportunity to gather insights that can enhance your app and business strategy.&lt;/p&gt;



&lt;p&gt;Often, I encourage apps to first &lt;a href=&quot;https://www.revenuecat.com/blog/growth/7-meta-ad-testing-frameworks-for-subscription-apps/&quot;&gt;test different messaging and designs via ads&lt;/a&gt; and even their app store, to see what resonates with their target audience. However, this is more top-of-the-funnel — and even if you have the traffic to measure success based on the &lt;a href=&quot;https://www.revenuecat.com/glossary/#trial-conversion-rate&quot;&gt;trial-to-paid conversion rate&lt;/a&gt;, you still want to ensure the angle is correct.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/revenuecat-paywalls-v2/&quot;&gt;Paywalls&lt;/a&gt; are a great place to test these angles and fine-tune them. They’ll also help you learn which angles work later in the funnel (when you are showing your paywall to free users) versus earlier on.&lt;/p&gt;



&lt;p&gt;Not only can you test different messaging and designs in context, but you can also gather direct feedback from users who don’t convert, via short surveys following your paywall. These insights can inform improvements to the paywall and the app as a whole.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;What you’ll ask will depend on what you want to learn:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Reason for not converting: &lt;/strong&gt;what was the main reason you didn’t subscribe?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;If there are clarity issues:&lt;/strong&gt; did you have any unanswered questions about the subscription?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Pricing issues:&lt;/strong&gt; what would make the subscription worth the price for you?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;This will capture feedback in the moment, when their hesitations are at the highest.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;should-you-do-all-of-this-with-your-paywall&quot;&gt;Should you do all of this with your paywall?&lt;/h2&gt;



&lt;p&gt;So there’s tons of ways your paywall can help you do more than sell. Does that mean you should pursue all of these tactics?&amp;nbsp;&lt;/p&gt;



&lt;p&gt;The simple answer: no.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Prioritize intentionally based on your app, target audience, and paywall placement.&lt;/strong&gt; Doing more than selling isn’t about cramming in extra information (this often increases cognitive load for the user). Focus on what matters most at &lt;em&gt;that&lt;/em&gt; stage in the journey.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Vahe recently shared a &lt;a href=&quot;https://www.revenuecat.com/blog/growth/paywall-redesigns-case-studies/&quot;&gt;great case study&lt;/a&gt; from a food app experiment on &lt;a href=&quot;https://www.paywalls.design/&quot;&gt;Paywalls.Design&lt;/a&gt;:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;696&quot; height=&quot;464&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-65.png&quot; alt=&quot;&quot; class=&quot;wp-image-47377&quot; style=&quot;width:800px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-65.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-65-300x200.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-65-50x33.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-65-60x40.png 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-65-560x373.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-65-444x296.png 444w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-65-80x53.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-65-48x32.png 48w&quot; sizes=&quot;auto, (max-width: 696px) 100vw, 696px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The second paywall increased the install-to-trial conversion rate by 72%. Why? It focused on what was &lt;em&gt;relevant&lt;/em&gt; for the audience: social proof to increase trust. They achieved this by sharing a notable statistic about the app’s results: “86% of users improved their diet”. This stat was previously more hidden in the paywall design. Another great example of simple = better.&lt;/p&gt;



&lt;p&gt;That’s not to say extra information is always bad. Some apps succeed with multi-role, landing-page style paywalls, like Noom or &lt;a href=&quot;https://greg.app/&quot;&gt;Greg&lt;/a&gt;, a plant identification and care app (I personally need this as I have a tendency to accidentally kill all my plants). These paywalls prove that you can’t assume you know what will work. The key is testing and &lt;strong&gt;tailoring your paywall to inform and engage&lt;/strong&gt;, rather than just sell.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-wp-embed is-provider-wistia-inc wp-block-embed-wistia-inc&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; class=&quot;wp-embedded-content&quot; sandbox=&quot;allow-scripts&quot; security=&quot;restricted&quot; title=&quot;Greg paywall Video&quot; src=&quot;https://fast.wistia.net/embed/iframe/mog42a0fi8?dnt=1#?secret=lwUAd11sK1&quot; data-secret=&quot;lwUAd11sK1&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; width=&quot;346&quot; height=&quot;750&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;Look at how long that paywall is! Even then, it’s not trying to cover everything we’ve discussed. Instead, it focuses on two key goals:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Educate users: &lt;/strong&gt;communicating the app’s value and educating users about what they can achieve&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Build trust: &lt;/strong&gt;building trust through a clear trial, App Store features, reviews, and the option to contact customer support&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The takeaway? The priority is to define what each paywall needs to accomplish and then experiment with different ways to convey that information. &lt;strong&gt;Your paywall can do far more than just sell, but only if you’re intentional about what it does and why.&lt;/strong&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Lessons from Condé Nast’s data-driven approach to retention and reactivation]]></title><description><![CDATA[Condé Nast's Michael Ribero unpacks how media brands use bundling, post-purchase upsells, and smart pricing to maximize LTV. ]]></description><link>https://www.revenuecat.com/blog/growth/michael-ribero-conde-nast-sub-club-podcast-2025/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/michael-ribero-conde-nast-sub-club-podcast-2025/</guid><pubDate>Wed, 29 Oct 2025 17:14:54 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/RC-Blog-Cover-Michael-Ribero-2.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;When you think of subscription apps, you might not immediately think of legacy media brands like &lt;em&gt;Vogue&lt;/em&gt; or &lt;em&gt;Wired&lt;/em&gt;. But perhaps you should! With decades of rich history and a vast portfolio of iconic publications, &lt;a href=&quot;https://www.condenast.com/&quot;&gt;Condé Nast&lt;/a&gt; has successfully adapted to the modern subscription landscape, balancing innovation with tradition.&lt;/p&gt;



&lt;p&gt;This week on the Sub Club podcast, we sat down with &lt;a href=&quot;https://www.linkedin.com/in/michael-ribero/&quot;&gt;Michael Ribero&lt;/a&gt;,&amp;nbsp;SVP, Global Consumer Revenue at Condé Nast, to discuss the strategies driving growth and engagement across their premium offerings. From running hundreds of experiments each year to navigating the complexities of free vs. paid content, Michael shares insights that can help any subscription business grow sustainably in today’s competitive market.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;How Condé Nast Experiments, Bundles, and Wins — Michael Ribero,  Condé Nast&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/0qt-wHxiFMY?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;iframe loading=&quot;lazy&quot; width=&quot;100%&quot; height=&quot;180&quot; frameborder=&quot;no&quot; scrolling=&quot;no&quot; seamless=&quot;&quot; src=&quot;https://share.transistor.fm/e/535711a4?color=FFFFFF&amp;amp;background=30343C&quot;&gt;&lt;/iframe&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-value-driven-growth&quot;&gt;&lt;strong&gt;Value-driven growth&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Much of Condé Nast’s success can be attributed to its focus on value-driven growth: continually adding new value for subscribers to keep them engaged and loyal. Michael explains that evolving an app or service over time to meet users’ changing needs is key to driving long-term retention. The company’s premium offerings are designed not only to attract new subscribers but to keep existing ones coming back for more.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-experimentation-at-scale&quot;&gt;&lt;strong&gt;Experimentation at scale&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Testing is at the heart of Michael’s strategy. Running hundreds of A/B tests every year, Michael and his team at Condé Nast make data-driven decisions on everything from pricing to product features. “We don’t believe in guessing what works. Our users tell us what works,” he says. By constantly testing and iterating, they stay aligned with user needs, finding what resonates and scaling it quickly.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-retention-and-re-engagement&quot;&gt;&lt;strong&gt;Retention and re-engagement&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Retention is a top priority, and Michael highlights how churn isn’t always the final word. When a user’s needs change, such as when they return to the job market or explore new hobbies, they may become interested in re-subscribing. Michael shares how offering tailored win-back offers and refreshing the premium experience keeps former customers coming back for more.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-free-vs-paid-content&quot;&gt;&lt;strong&gt;Free vs. paid content&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Balancing free and paid content is a delicate challenge. Michael discusses how Condé Nast ensures the free experience remains valuable while encouraging users to convert to premium plans. He also shares lessons learned from experimenting with paywalls and how making mistakes along the way ultimately leads to better results.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-building-community&quot;&gt;&lt;strong&gt;Building community&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Michael explains how community building is crucial to Condé Nast’s strategy. By hosting real-world events and creating offline connections, the company fosters deeper engagement that extends beyond the app. This holistic approach to community helps ensure that users feel connected to the brand in meaningful ways.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-takeaway-growth-follows-value&quot;&gt;&lt;strong&gt;The takeaway: Growth follows value&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;For Condé Nast, retention starts with relevance, and relevance comes from value. Every test, feature, and offer loops back to the same question: &lt;em&gt;Does this make life better for the user?&lt;/em&gt; It’s a framework any subscription app can learn from.&lt;br&gt;&lt;br&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=0qt-wHxiFMY&quot;&gt;&lt;strong&gt;Watch the full conversation&lt;/strong&gt; on Sub Club.&lt;br&gt;&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[AI has broken subscription app pricing models: the end of one-size-fits-all subscriptions]]></title><description><![CDATA[When every user activity costs money, 'freemium' stops being free]]></description><link>https://www.revenuecat.com/blog/growth/ai-subscription-app-pricing/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/ai-subscription-app-pricing/</guid><pubDate>Wed, 29 Oct 2025 12:27:18 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/AI-apps-subscription-economics-1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Traditional subscription businesses rely on &lt;strong&gt;predictability&lt;/strong&gt;: one user, one plan, one roughly-stable cost to serve. Whether a subscriber opens a meditation app once a week or every day, the margins don’t shift much for publishers.&lt;/p&gt;



&lt;p&gt;AI-powered subscription apps, however, break that model entirely.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;So how are AI-based subscription apps approaching pricing? And how is this having a knock-on impact on subscription app economics? Well, first we need to understand how AI apps break down their costs.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-do-ai-apps-cost-more-to-run&quot;&gt;&lt;strong&gt;Why do AI apps cost more to run?&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;All apps cost something to operate — servers, storage, analytics, APIs — but AI apps flip the cost equation. While traditional apps pay for hosting, and mostly pay fixed or low-variable fees, AI apps pay for ‘thinking’ (GPU compute), and need to pay every time a user interacts.&lt;/p&gt;



&lt;p&gt;Traditional apps scale efficiently — once they’re built, serving more users barely increases the cost. However, for AI apps, every prompt, chat, or render, increases the bill.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;This means each user’s cost profile can vary wildly. Take ChatGPT: a PhD student running complex research queries can be dozens of times more expensive to serve than a casual user generating a few novelty images every couple of weeks.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Cost is impacted by &lt;strong&gt;engagement, not installs. &lt;/strong&gt;More use = more spend. That fact, combined with variability between users, makes it increasingly difficult to sustain a one-size-fits-all pricing model or forecast lifetime value with confidence.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;the-ai-goldrush-is-colliding-with-economic-reality&quot;&gt;&lt;strong&gt;The AI goldrush is colliding with economic reality&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Recently, the cracks in the ‘AI Goldrush’ have started to show. Headlines now warn that the AI bubble is bursting, as many startups &lt;a href=&quot;https://www.wheresyoured.at/why-everybody-is-losing-money-on-ai/&quot;&gt;spend far more on compute and infrastructure than they generate&lt;/a&gt; in revenue. Despite those costs, some of the biggest players and most well-funded startups are still draining cash on aggressive, short-term growth tactics via AI.&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Lovable, an AI-powered no-code development platform gained some LinkedIn virality for &lt;a href=&quot;https://www.linkedin.com/posts/lovable-dev_this-weekend-while-lovable-is-free-to-use-activity-7339717629621760001-rJRH?utm_source=share&amp;amp;utm_medium=member_ios&amp;amp;rcm=ACoAABAvYKYB3UFpHZYoozFqoKcTjy_hiNUmGgc&quot;&gt;giving away free credits over a weekend&lt;/a&gt; to drive short-term engagement.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Google’s Gemini is offering a full &lt;a href=&quot;https://gemini.google/gb/subscriptions/?hl=en-GB&quot;&gt;one-month free trial&lt;/a&gt; (almost unheard of in today’s app industry), and bundling it with access to Fitbit Premium, Google Home upgrades, and 2TB of cloud storage, when you subscribe.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Even tools like Perplexity and Character.AI continue to experiment with compute-heavy free tiers to attract scale.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;These tactics may spike installs and engagement, but they expose the underlying tension in AI’s business model: every ‘free’ generation costs someone real money. For many apps, that someone is the founder burning margin in the name of growth.&lt;/p&gt;



&lt;p&gt;And then there’s the other half of the problem: hype-fueled installs that vanish just as fast as they arrive. Most AI apps spike on curiosity, then fall off a cliff after day one. Business Insider reported that so-called ‘vibe coding’ tools like Lovable have seen &lt;a href=&quot;https://www.businessinsider.com/ai-vibe-coding-tools-traffic-plunge-summer-arr-hype-2025-9?utm_source=chatgpt.com&quot;&gt;traffic plunge nearly 40 percent since their summer hype peak,&lt;/a&gt; exposing weak retention and shaky ROI. If 2024 and 2025 were about racing to integrate AI, &lt;strong&gt;2026 will be about learning to monetize it sustainably.&lt;/strong&gt; The difference between a hype-driven app and a long-term business now comes down to how intelligently you price, position, and deliver AI value.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;how-top-ai-companies-are-taking-control-of-costs&quot;&gt;&lt;strong&gt;How top AI companies are taking control of costs&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The first wave of AI success stories looked unstoppable. Engagement was up, installs were spiking, and investors couldn’t fund the hype fast enough. But as usage scaled, many founders discovered the same hard truth: &lt;a href=&quot;https://www.reuters.com/legal/transactional/ai-startup-valuations-raise-bubble-fears-funding-surges-2025-10-03/&quot;&gt;growth didn’t mean profit.&lt;/a&gt;&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Inference costs and the invisible ‘compute tax’ rose faster than revenue — the more people used these tools, the worse the margins became.&lt;/p&gt;



&lt;p&gt;In response, AI apps tightened their rules:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.wheresyoured.at/why-everybody-is-losing-money-on-ai/&quot;&gt;&lt;strong&gt;Perplexity&lt;/strong&gt;&lt;/a&gt; cut free usage, added rate limits for anonymous users, and pushed upsells to paid Pro and Max tiers — where inference costs could be priced more rationally.&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://plaky.com/learn/plaky/notion-pricing/#:~:text=Here&apos;s%20a%20quick%20comparison%20of,the%20Business%20and%20Enterprise%20plans.&quot;&gt;&lt;strong&gt;Notion&lt;/strong&gt;&lt;/a&gt; moved AI features into more expensive Business and Enterprise plans; a quiet but strategic shift that isolates inference spend from the freemium user base and reinforcing value of top-tier subscriptions.&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.theverge.com/2024/9/3/24234698/canva-price-increase-300-percent-ai-features/&quot;&gt;&lt;strong&gt;Canva&lt;/strong&gt;&lt;/a&gt; fully tiered its Magic Studio AI tools: limited access for free users, versus expanded limits and faster processing for Pro and Teams. In 2024, they raised Teams pricing by up to &lt;strong&gt;300%&lt;/strong&gt;, explicitly citing AI expansion.&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://help.runwayml.com/hc/en-us/articles/15124877443219-How-do-credits-work?&quot;&gt;&lt;strong&gt;Runway ML&lt;/strong&gt;&lt;/a&gt; adopted a credit-based model where even short Gen-4 video generations consume significant credits. Its $12/month plan covers only ~50 seconds of AI video, signaling that each generation is a cost event, not a freebie.&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.jasper.ai/pricing?&quot;&gt;&lt;strong&gt;Jasper&lt;/strong&gt;&lt;/a&gt; doubled down on enterprise — new pricing and positioning, plus emphasis on collaboration and workflow features, signals a move from low-priced consumer tiers to high-value, high-usage contracts.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The message is clear: &lt;strong&gt;AI power now sits behind the paywall.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;All of these companies realized that AI isn’t a freemium land grab. It’s a high-cost infrastructure business. Those who survive the shake-out will be the ones who can align user value, inference cost, and willingness to pay into a single, sustainable equation.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;acquisition-strategy-in-the-age-of-ai&quot;&gt;&lt;strong&gt;Acquisition strategy in the age of AI&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;AI changes the growth math. For most apps, acquisition has always been a volume game: Get users in, optimize LTV, scale spend. But when each new user costs money to serve, and the &lt;em&gt;aha! &lt;/em&gt;moment&amp;nbsp; burns GPU time, app growth needs a new playbook.&lt;/p&gt;



&lt;p&gt;There are two main tactics I’ve observed AI subscription apps adopting. Let’s take a look.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;1-targeting-quality-over-quantity&quot;&gt;&lt;strong&gt;1. Targeting quality over quantity&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;In a compute-limited world, not all users are equal. Founders need to &lt;strong&gt;focus on margin-qualified acquisition&lt;/strong&gt;; attracting users whose use case, willingness to pay, and usage intensity align with sustainable LTV.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;This could look like:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Narrower targeting based on intent&lt;/li&gt;



&lt;li&gt;Early segmentation during onboarding&lt;/li&gt;



&lt;li&gt;Prioritizing organic or referral channels where CAC scales slower than compute cost&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;a href=&quot;https://www.linkedin.com/in/davidvargasmontiel/&quot;&gt;David Vargas&lt;/a&gt;, independent growth consultant, has noticed AI subscription apps shifting their focus from maximizing &lt;strong&gt;reach &lt;/strong&gt;to maximizing &lt;strong&gt;efficiency&lt;/strong&gt;:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“Running UA for AI apps isn’t just about lowering CAC — it’s about managing GPU burn. Every new user triggers compute costs, so the real game is balancing growth with efficiency.”&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;When it comes to paid user acquisition (UA), AI apps can factor in new costs to budget: “Most of the time, we study pricing and include GPU costs within the subscription, so we’re safe to play with paid campaigns without hurting margins.”&amp;nbsp;&lt;/p&gt;



&lt;p&gt;In AI, even the acquisition funnel itself has a cost. The smartest operators design their campaigns around unit economics, not vanity metrics. David’s also noticed a growing trend in AI apps skipping free altogether:&lt;/p&gt;



&lt;p&gt;Many AI apps today skip freemium and go fully paid with a hard paywall This avoids GPU costs from non-paying users and makes acquisition much more predictable.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;2-blending-acquisition-and-infrastructure&quot;&gt;&lt;strong&gt;2. Blending acquisition and infrastructure&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The balancing act between marketing and app infrastructure is an area of app growth that’s only growing in importance, and it’s a new frontier for many of us.&amp;nbsp;As &lt;a href=&quot;https://www.linkedin.com/in/ehtasham-balland-04701a104/&quot;&gt;Ehtasham Balland&lt;/a&gt;, Marketing Operations Manager at 9D Technologies, explains: “The success of monetizing AI apps differs from traditional ones — you have to &lt;strong&gt;balance user value, marketing efficiency, and infrastructure costs.&lt;/strong&gt;”&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“Profitability is driven by how well GPU, servers, and backend systems are optimized &lt;em&gt;alongside&lt;/em&gt; smart customer acquisition. The real edge lies in combining marketing precision with lean, optimized infrastructure for sustainable growth.”&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Ehtasham’s point reframes growth as a shared responsibility between marketing and engineering. It’s not enough to have great campaigns and attract loads of users — the backend needs to be able to support them &lt;em&gt;profitably&lt;/em&gt;.&lt;/p&gt;



&lt;p&gt;This is the new reality of AI user acquisition: &lt;strong&gt;it’s not a funnel anymore, it’s a feedback loop &lt;/strong&gt;between marketing and compute spend. The most disciplined teams now model GPU usage the same way SaaS marketers model server costs, blending growth metrics with infrastructure efficiency.&lt;/p&gt;



&lt;p&gt;The takeaway? The future of AI growth won’t be defined by who can acquire the most users, but by &lt;strong&gt;who can afford to keep them&lt;/strong&gt;.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;the-free-trial-dilemma-when-try-before-you-buy-burns-cash&quot;&gt;&lt;strong&gt;The free trial dilemma: when ‘try before you buy’ burns cash&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;In most app categories, free trials are a growth staple. They build trust, reduce friction, and let users experience value before committing. But in AI, every free trial costs the business.&lt;/p&gt;



&lt;p&gt;AI subscription apps face a paradox:&lt;strong&gt; the users most engaged during a trial are also the most expensive to serve&lt;/strong&gt;. Each generation, image, or video has a direct marginal cost, and trial users — especially curious, high-frequency ones — can rack up real losses before conversion.&lt;/p&gt;



&lt;p&gt;The smarter path for lesser-known products isn’t necessarily no trial, but controlled exposure. That means limiting trials by:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Inference volume (e.g. 10 generations or 100 tokens)&lt;/li&gt;



&lt;li&gt;Time windows that encourage quick commitment (e.g. 24-hour passes)&lt;/li&gt;



&lt;li&gt;Feature selection: letting users explore lightweight features but gating compute-heavy ones&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;In AI, free trials shouldn’t mimic SaaS. They should act as calibrated test drives — enough to deliver the &lt;em&gt;aha! &lt;/em&gt;moment, without swallowing your GPU budget.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Photo Lab, an AI portrait editor app, demonstrates the power of ‘demo without inference’. Even before users start a free trial or upload their own photos, the App Store images showcase filters on a stock model, demonstrating value without spending a cent on compute. During onboarding, users can once again see previews of the AI filters on stock models, letting them effectively test the AI feature without actually generating anything. It’s a smart way to keep engagement high while protecting margins. Efficient, persuasive, and GPU-friendly.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;724&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/AI-image-example-1024x724.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47253&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/AI-image-example-1024x724.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/AI-image-example-300x212.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/AI-image-example-768x543.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/AI-image-example-50x35.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/AI-image-example-57x40.jpg 57w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/AI-image-example-656x464.jpg 656w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/AI-image-example-696x492.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/AI-image-example-560x396.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/AI-image-example-418x296.jpg 418w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/AI-image-example-667x472.jpg 667w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/AI-image-example-80x57.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/AI-image-example-48x34.jpg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/AI-image-example.jpg 1118w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The question isn’t whether trials make sense, but what they cost you per user. If your trial converts users profitably, it’s marketing. If not, you’re just burning cash.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;how-to-design-monetization-around-roi-not-novelty&quot;&gt;&lt;strong&gt;How to design monetization around ROI, not novelty&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;As top-tier AI companies tighten their pricing strategies to manage mounting compute costs, consumers are simultaneously recalibrating what these tools are really worth — and which ones justify a recurring subscription.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Early adopters of AI paid for curiosity, but now users demand accuracy and reliability. The most successful AI apps &lt;strong&gt;map pricing to cost-to-serve and emotional payoff&lt;/strong&gt;. Instead of charging a flat fee, they monetize the user’s confidence, i.e. how much certainty, speed, or control they need.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Read on for some of the clever ways publishers are reinforcing the value of their AI subscriptions.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-return-of-the-bundle&quot;&gt;&lt;strong&gt;The return of the bundle&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;One tactic is bundling your AI-heavy apps with other lower-cost one. For example, Google Gemini Pro &lt;a href=&quot;https://gemini.google/gb/subscriptions/?hl=en-GB&quot;&gt;offers a rare one-month free trial&lt;/a&gt;, bundled with Fitbit Premium, Google Home, 2TB storage, and NotebookLM. This bundling reframes AI from a chatbot, to a full lifestyle upgrade. For users, it feels like more for your money; for Google, it spreads the compute cost across a wider ecosystem. AI becomes the incentive, not the core product.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;turn-support-into-a-status-feature&quot;&gt;&lt;strong&gt;Turn support into a status feature&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Perplexity’s €229/month Max plan includes priority customer support — a reminder than certainty and reliability is a product in itself. When AI can be wrong or slow, fast human backup becomes a premium differentiator.&lt;/p&gt;



&lt;p&gt;Similarly, Character.AI monetizes queue time. ‘Priority Chat Access’ lets subscribers skip slowdown during busy hours, turning a technical constraint into a prestige benefit. In both cases, what’s really sold isn’t access but assurance. AI apps are learning to commoditize on support, speed, and reliability.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;introduce-contextual-pricing&quot;&gt;&lt;strong&gt;Introduce contextual pricing&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Just as ride-share apps adjust prices based on demand, AI pricing can increasingly flex around resource intensity. Every AI task consumes a different amount of compute. Generating a short text summary costs pennies, while producing a high-resolution video or complex reasoning chain can cost dollars.&lt;/p&gt;



&lt;p&gt;In the future, users may see more pricing shaped by how ‘heavy’ their requests are:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Lower prices for asynchronous or batch jobs (like overnight processing or background analysis)&lt;/li&gt;



&lt;li&gt;Higher prices for real-time or creative work (like video generation or live chat with minimal latency)&lt;/li&gt;



&lt;li&gt;Discounts or credits for off-peak usage, when GPUs are cheaper to run&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The smartest companies will use routing intelligence to manage this complexity automatically. This would involve sending lightweight tasks to smaller, cheaper models, running repeated queries on-device, and reserving expensive models for high-value work.&lt;/p&gt;



&lt;p&gt;By matching the right model to the right moment, and explaining that trade-off to users, AI apps can make pricing feel fair, predictable, and aligned with the real cost of intelligence.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;final-thoughts-from-hype-to-habit&quot;&gt;&lt;strong&gt;Final thoughts: from hype to habit&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The AI gold rush is over. However, what comes next isn’t collapse,&amp;nbsp; it’s course correction. The winners of the post-bubble era won’t be the ones who generate the most engagement or ship the flashiest models, but the ones who learn to price intelligence like infrastructure and design around the true cost of value.&lt;/p&gt;



&lt;p&gt;AI founders are discovering that compute is the new CAC: every generation, every query, every inference comes with a measurable cost. Smart publishers are no longer chasing scale; they’re engineering sustainability. That means putting guardrails on usage, aligning pricing with resource intensity, and building emotional utility — confidence, time leverage and identity — into every paid tier.&lt;/p&gt;



&lt;p&gt;In this new phase, success will depend less on what your model can do, and more on &lt;strong&gt;how you package, meter, and justify it.&lt;/strong&gt; AI is shifting from an open field to a managed ecosystem, where margins depend on precision over promises.&lt;/p&gt;



&lt;p&gt;In short, AI founders should:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Know their inference cost per active user&lt;/li&gt;



&lt;li&gt;Understand psychological value levers&lt;/li&gt;



&lt;li&gt;Design pricing for retention over reach&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;If the last two years were about building what’s possible, the next two will be about building what’s profitable. The apps that thrive won’t be the ones that give intelligence away — they’ll be the ones that make users feel good paying for it.&lt;/p&gt;


&lt;div class=&quot;lazyblock-dd0db17b8671-Z10Ar8h wp-block-lazyblock-dd0db17b8671&quot;&gt;&lt;blogpostpodcastcta title=&quot; 12 AI Growth Lessons for Subscription Apps&quot; description=&quot;Phil Carter (Elemental Growth) explains why the speed and cost-efficiency of smaller models outweigh the benefits of newer models. Plus 11 other lessons for growing your app with AI.&quot; links=&quot;[{&amp;quot;link-title&amp;quot;:&amp;quot;YouTube&amp;quot;,&amp;quot;link-url&amp;quot;:&amp;quot;https:\/\/www.youtube.com\/watch?v=UYIgu02h8cs&amp;quot;,&amp;quot;link-image&amp;quot;:&amp;quot;youtube&amp;quot;},{&amp;quot;link-title&amp;quot;:&amp;quot;Spotify&amp;quot;,&amp;quot;link-url&amp;quot;:&amp;quot;https:\/\/open.spotify.com\/episode\/74hESsillo6m6vwenqQ7eb?si=3c54a5fb27b344f7&amp;quot;,&amp;quot;link-image&amp;quot;:&amp;quot;spotify&amp;quot;},{&amp;quot;link-title&amp;quot;:&amp;quot;Apple Podcasts&amp;quot;,&amp;quot;link-url&amp;quot;:&amp;quot;https:\/\/podcasts.apple.com\/us\/podcast\/feed\/id1538057974?ls=1&amp;quot;,&amp;quot;link-image&amp;quot;:&amp;quot;apple-podcasts&amp;quot;}]&quot;&gt;
&lt;/blogpostpodcastcta&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[How to configure RevenueCat Redemption links in React Native]]></title><description><![CDATA[Unlock web purchases in your React Native app with one tap ]]></description><link>https://www.revenuecat.com/blog/engineering/how-to-configure-revenuecat-redemption-links-in-react-native/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/how-to-configure-revenuecat-redemption-links-in-react-native/</guid><pubDate>Mon, 27 Oct 2025 13:48:45 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Frame.jpg" length="0" type="image/*"/><content:encoded>&lt;p&gt;Redemption links let customers buy on the web and unlock access in your app with a single tap. RevenueCat generates a &lt;strong&gt;one-time-use deep link&lt;/strong&gt; after checkout; when the user opens it on their device the purchase is tied to their App User ID and the app can grant entitlements immediately. Because the checkout can be &lt;strong&gt;anonymous&lt;/strong&gt;, you don’t need to pass an App User ID at purchase time — users can buy on the web and ‘claim’ the purchase on mobile via the link.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;In this tutorial you’ll wire up deep links in an Expo app two ways: first with &lt;strong&gt;Expo Linking&lt;/strong&gt;, then with &lt;strong&gt;Expo Router&lt;/strong&gt;; so redemption links open your app, you verify entitlements, and the premium features unlock for your user.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;This guide assumes you have already created products and enabled Web Billing in RevenueCat, which is done from the RevenueCat dashboard.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-understand-how-redemption-links-work&quot;&gt;Understand how Redemption Links work&lt;/h2&gt;



&lt;p&gt;When a customer completes the Web Billing checkout, either through RevenueCat Web SDK or a hosted Web Purchase Link, they receive a redemption link. This redemption link will act as a deep link into the app, so when a customer taps the link on a mobile device, they are automatically redirected to your app. In the app, RevenueCat’s mobile SDK will then associate the purchase with the customer, based on the URL parameters of the deep link.&lt;/p&gt;



&lt;p&gt;To make this all work we need to implement deep linking functionality in our React Native app. Depending on the navigation framework (&lt;a href=&quot;https://docs.expo.dev/router/introduction/&quot;&gt;Expo Router&lt;/a&gt; or &lt;a href=&quot;https://reactnavigation.org/&quot;&gt;React Navigation&lt;/a&gt;) we’re using, there are two different ways to accomplish this.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-1-configure-web-redemption-links-in-revenuecat-dashboard&quot;&gt;Step 1: Configure web redemption links in RevenueCat dashboard&lt;/h2&gt;



&lt;p&gt;To enable redemption links, navigate to your project in the RevenueCat dashboard, then the Web tab. In the &lt;strong&gt;Web configuration&lt;/strong&gt; section, open the configuration and open the &lt;strong&gt;Redemption links&lt;/strong&gt; section. Click to enable Redemption Links for either the environments you need. After that, copy the &lt;strong&gt;Custom URL Scheme&lt;/strong&gt;, we are going to need it later.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;501&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/redemption-links-1024x501.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-47227&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/redemption-links-1024x501.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/redemption-links-300x147.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/redemption-links-768x375.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/redemption-links-1536x751.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/redemption-links-2048x1001.jpg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/redemption-links-50x24.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/redemption-links-82x40.jpg 82w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/redemption-links-696x340.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/redemption-links-560x274.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/redemption-links-840x411.jpg 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/redemption-links-80x39.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/redemption-links-48x23.jpg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-2-handle-redemption-links-in-your-react-native-app&quot;&gt;Step 2: Handle redemption links in your React Native app&lt;/h2&gt;



&lt;p&gt;As mentioned there are two different ways to handle deep linking in your React Native. You should go with option A if your app uses React Navigation (or a similar navigation library); and option B if your app is using Expo Router.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-option-a-handle-redemption-links-with-expo-linking&quot;&gt;Option A: Handle redemption links with Expo Linking&amp;nbsp;&lt;/h3&gt;



&lt;p&gt;Expo’s Linking API lets your app respond to incoming URLs and route to a specific screen. The Expo docs cover custom schemes as well as Universal Links/App Links. We’ll show a custom scheme for clarity.&amp;nbsp; &lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Add a URL scheme you copied earlier to your app.json&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;We could use the scheme field to add the earlier copied URL scheme to our app. However you might already be using another url scheme, in which case you want the RevenueCat URL Scheme to exist separately. To do this with Expo you need to add the following fields in app.json:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z16zUC2 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;\&amp;quot;ios\&amp;quot;: {\n      \&amp;quot;supportsTablet\&amp;quot;: true,\n      \&amp;quot;bundleIdentifier\&amp;quot;: \&amp;quot;your-bundle-id\&amp;quot;,\n      \&amp;quot;infoPlist\&amp;quot;: {\n        \&amp;quot;CFBundleURLTypes\&amp;quot;: [\n          {\n            \&amp;quot;CFBundleURLSchemes\&amp;quot;: [\n              \&amp;quot;your-app-scheme\&amp;quot;\n            ]\n          },\n          {\n            \&amp;quot;CFBundleURLSchemes\&amp;quot;: [\n              \&amp;quot;rc-3fbf200a7c\&amp;quot;\n            ]\n          }\n        ]\n      }\n    },&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Run &lt;code&gt;npx expo prebuild&lt;/code&gt; to generate the &lt;code&gt;ios&lt;/code&gt; folder and contents. You can validate that schemes are configured correctly by opening Xcode and going to: Target → Info → URL Types. You should see your existing URL scheme and the RevenueCat URL scheme listed there.&lt;/p&gt;



&lt;p&gt;For Android, the field to use is intentFilters:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1CIkJI wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;\&amp;quot;android\&amp;quot;: {\n      \&amp;quot;intentFilters\&amp;quot;: [\n        {\n          \&amp;quot;action\&amp;quot;: \&amp;quot;VIEW\&amp;quot;,\n          \&amp;quot;data\&amp;quot;: [\n            {\n              \&amp;quot;scheme\&amp;quot;: \&amp;quot;your-app-scheme\&amp;quot;\n            },\n            {\n              \&amp;quot;scheme\&amp;quot;: \&amp;quot;rc-3fbf200a7c\&amp;quot;\n            }\n          ],\n          \&amp;quot;category\&amp;quot;: [\n            \&amp;quot;BROWSABLE\&amp;quot;,\n            \&amp;quot;DEFAULT\&amp;quot;\n          ]\n        }\n      ],&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;If you’re not using Expo you can configure the Android and iOS deep links with React Navigation following &lt;a href=&quot;https://reactnavigation.org/docs/deep-linking/#set-up-with-bare-react-native-projects&quot;&gt;this guide&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Listen for incoming URLs&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Once your URL schemes are configured you need to implement the code for observing links that launch your app. The code below is a simple implementation for handling Redemption links.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1B8zkD wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;import * as Linking from &apos;expo-linking&apos;;\nimport Purchases from &apos;react-native-purchases&apos;;\n\nexport default function Home() {\n  const url = Linking.useURL();\n\n  useEffect(() =&gt; {\n    if (!url) return;\n\n    async function redeem() {\n      const redemption = await Purchases.parseAsWebPurchaseRedemption(url);\n      if (redemption) {\n        await Purchases.redeemWebPurchase(redemption);\n      }\n    }\n\n    redeem();\n  }, [url]);\n\n  return (\n   \n  );\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-option-b-handle-redemption-links-with-expo-router&quot;&gt;Option B: Handle redemption links with Expo Router&lt;/h3&gt;



&lt;p&gt;If your app uses Expo Router, you don’t need a custom listener or route for handling redemption links. Instead, you can use Expo Router’s +native-intent.tsx and redirectSystemPath to intercept incoming native intents globally.&amp;nbsp;&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-chEYs wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;import Purchases from &apos;react-native-purchases&apos;;\n\nexport async function redirectSystemPath({\n  path,\n  initial,\n}: {\n  path: string;\n  initial: boolean;\n}) {\n  try {\n    \/\/ Try to parse the incoming URL as a RevenueCat redemption link\n    const webPurchaseRedemption = await Purchases.parseAsWebPurchaseRedemption(path);\n\n    if (webPurchaseRedemption) {\n      \/\/ Redeem the web purchase\n      const result = await Purchases.redeemWebPurchase(webPurchaseRedemption);\n      console.log(&apos;Redemption result:&apos;, result);\n    }\n\n    \/\/ After handling, navigate users into the main tab layout\n    return &apos;\/(tabs)&apos;;\n  } catch (error) {\n    console.error(&apos;Error in redirectSystemPath:&apos;, error);\n    return &apos;\/(tabs)&apos;;\n  }\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Alternatively, you can also redirect users to a custom route that informs users when their redemption link was redeemed successfully, or if it failed for any reason.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-3-test-the-full-flow-end-to-end&quot;&gt;Step 3: Test the full flow end-to-end&lt;/h2&gt;



&lt;p&gt;You can then test that the deep linking works with the following command:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-2ngAVX wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;npx uri-scheme open &apos;rc-3fbf200a7c:\/\/redeem_web_purchase?redemption_token=token&apos; --ios&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;If the previous steps have been done correctly, your app should open, and you should see logs indicating whether the redemption succeeded or failed, depending whether you used a real redemption link or not. All that’s left to do is to improve the UX of this feature by, for example, building a custom screen that congratulates the user for starting their premium subscription.&lt;/p&gt;



&lt;p&gt;Before going to production you can test Redemption links by doing a sandbox web purchase and testing with that link. After sending yourself the redemption link, and opening it on a device with your app installed, you should see the app open, and the subscription get redeemed.&lt;/p&gt;



&lt;p&gt;For web checkout itself, you can either embed RevenueCat’s Web SDK or use Web Purchase Links to spin up a hosted paywall with minimal code. Both approaches feed into the same redemption link pattern you wired above.&amp;nbsp; &lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-further-resources&quot;&gt;Further resources&lt;/h2&gt;



&lt;p&gt;Once your deep links are working reliably, redemption links become a powerful tool for marketing and support — from win-back emails that auto-unlock on tap, to gifting or upgrade flows that work seamlessly across iOS, Android, and web.&lt;/p&gt;



&lt;p&gt;For more info, check out out Docs:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/web/web-billing/redemption-links&quot;&gt;Redemption Links&lt;/a&gt; (behavior, one-time use, anonymous checkout + association on open).&amp;nbsp; &lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/web/web-billing/overview&quot;&gt;Web Billing Overview &amp;amp; Config&lt;/a&gt; (products, pricing, localization, tax, Stripe).&amp;nbsp; &lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title><![CDATA[Building a tip jar feature with RevenueCat]]></title><description><![CDATA[A simple, low-pressure way to let users support your app — without a subscription.]]></description><link>https://www.revenuecat.com/blog/engineering/building-a-tip-jar-feature-with-revenuecat/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/building-a-tip-jar-feature-with-revenuecat/</guid><pubDate>Fri, 24 Oct 2025 14:58:12 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/tip-jar.jpg" length="0" type="image/*"/><content:encoded>&lt;p&gt;At Droidcon Berlin, I met a bunch of indie developers who told me the same thing: &lt;em&gt;“I’d love to monetize my app, but it’s too simple for a paywall. No one is going to subscribe just to use a timer / wallpaper pack / calculator / flashlight.”&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;And they’re right — forcing subscriptions into lightweight apps often creates more friction and annoyance than revenue.&lt;/p&gt;



&lt;p&gt;But there’s an option that annoys less: &lt;strong&gt;a tip jar.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;A tip jar lets users choose when to support you rather than forcing commitment upfront. It’s low-pressure, works great for utility apps and passion projects, and can be surprisingly effective when done right in a beloved product.&lt;/p&gt;



&lt;p&gt;In this guide, I’ll show you how to build a fully-functional tip jar using RevenueCat, including:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;How to structure &lt;strong&gt;tip products in the Test Store first&lt;/strong&gt;, so you can build the full UX without real store setup&lt;/li&gt;



&lt;li&gt;A &lt;strong&gt;plug-and-play React Native implementation&lt;/strong&gt; using &lt;code&gt;&lt;a href=&quot;https://github.com/revenuecat/react-native-purchases&quot;&gt;react-native-purchases&lt;/a&gt;&lt;/code&gt; and &lt;code&gt;react-native-purchases-ui&lt;/code&gt;&lt;/li&gt;



&lt;li&gt;How to &lt;strong&gt;move from Test Store &lt;/strong&gt;to App Store Connect and Google Play Console when you’re ready for launch&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;You can ship this in under 15 minutes — and launch it when you’re confident it works.&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-1FzS27 wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Real-world example: tipping in a simple game&quot; text=&quot;&lt;p&gt;Indie developer Peter Porfy implemented this approach in his puzzle game &lt;span class=&amp;quot;s1&amp;quot;&gt;&lt;b&gt;No Ads 2048&lt;/b&gt;&lt;/span&gt;. Instead of a single “buy me a coffee” option, he offered multiple tip amounts.&lt;/p&gt;
&lt;p&gt;Interestingly, players started choosing higher-value tips more often when given several options. &lt;a href=&amp;quot;https://apps.apple.com/us/app/no-ads-2048/id6465691202&amp;quot;&gt;You can find the the app here.&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;This is exactly the kind of lightweight monetization tip jars are designed for — simple apps where users want to support the developer without committing to a subscription.&lt;/p&gt;&quot; icon=&quot;sparks&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-1-create-your-consumable-purchases-in-revenuecat-dashboard&quot;&gt;Step 1: Create your consumable purchases in RevenueCat dashboard&lt;/h2&gt;



&lt;p&gt;We’ll build this tip jar using consumable purchases. Unlike subscriptions or lifetime unlocks, consumables can be purchased repeatedly, which makes them perfect for tips. Think “buy me a coffee” rather than “unlock premium forever”.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-start-in-revenuecat-s-test-store-no-app-store-setup-required&quot;&gt;Start in RevenueCat’s Test Store (no App Store setup required)&lt;/h3&gt;



&lt;p&gt;RevenueCat now includes a feature called Test Store, which lets you define fake-but-functional products entirely inside RevenueCat. These behave just like real purchases — they return &lt;code&gt;CustomerInfo&lt;/code&gt;, show up in dashboards, and trigger entitlements — but no App Store / Google Play configuration is needed yet. This lets you iterate on pricing, copy, UX, and code before committing to real store setup.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-enable-test-store&quot;&gt;Enable Test Store&lt;/h3&gt;



&lt;p&gt;Start by enabling the Test Store which you can do in the &lt;strong&gt;Apps &amp;amp; providers&lt;/strong&gt; section in the sidebar on the dashboard. There you can find this section:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;501&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-2-1024x501.jpeg&quot; alt=&quot;&quot; class=&quot;wp-image-47129&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-2-1024x501.jpeg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-2-300x147.jpeg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-2-768x375.jpeg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-2-1536x751.jpeg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-2-50x24.jpeg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-2-82x40.jpeg 82w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-2-696x340.jpeg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-2-560x274.jpeg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-2-840x411.jpeg 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-2-80x39.jpeg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-2-48x23.jpeg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-2.jpeg 2048w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Click &lt;strong&gt;Create Test Store&lt;/strong&gt;, and copy the &lt;strong&gt;API key for testing &lt;/strong&gt;value for later use. We’re going to need it when we set up the SDK.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-create-test-store-products&quot;&gt;Create Test Store products&lt;/h3&gt;



&lt;p&gt;Next step is to create your Test Store products. I suggest making the following products in RevenueCat as the possible tip amounts for your tip jar. You can of course create any level of amounts for the customer to tip, but aim to follow a consistent productID naming.&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Level&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Product ID&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Price&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Small tip / buy me a coffee&lt;/td&gt;&lt;td&gt;com.yourapp.tip.small&lt;/td&gt;&lt;td&gt;$1.99&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Medium tip / buy me two coffees&lt;/td&gt;&lt;td&gt;com.yourapp.tip.medium&lt;/td&gt;&lt;td&gt;$4.99&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Big tip / buy me a pizza&lt;/td&gt;&lt;td&gt;com.yourapp.tip.large&lt;/td&gt;&lt;td&gt;$9.99&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;Follow these steps below to setup the products:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Go to &lt;strong&gt;RevenueCat → Product catalog → Products → + New Product&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;Choose store: Test Store&lt;/li&gt;



&lt;li&gt;Enter a Product Identifier (e.g. com.yourapp.tip.small)&lt;/li&gt;



&lt;li&gt;Set a test price ($1.99, $4.99, $9.99 — whatever you plan to launch with)&lt;/li&gt;
&lt;/ol&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;501&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-3-1024x501.jpeg&quot; alt=&quot;Screenshot of setting up a new product in RevenueCat dashboard&quot; class=&quot;wp-image-47132&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-3-1024x501.jpeg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-3-300x147.jpeg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-3-768x375.jpeg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-3-1536x751.jpeg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-3-50x24.jpeg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-3-82x40.jpeg 82w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-3-696x340.jpeg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-3-560x274.jpeg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-3-840x411.jpeg 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-3-80x39.jpeg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-3-48x23.jpeg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-3.jpeg 2048w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Repeat for each tip amount. You also need to group these tip amounts to an offering, so we can easily show them in a paywall. Follow the steps below to add the created products into a new offering,&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Go to &lt;strong&gt;RevenueCat → Offerings&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;Create a new offering (e.g. tips)&lt;/li&gt;



&lt;li&gt;Add your Test Store products to it&lt;/li&gt;
&lt;/ol&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;501&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-5-1024x501.jpeg&quot; alt=&quot;Screenshot of setting up a new offering in RevenueCat dashboard&quot; class=&quot;wp-image-47136&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-5-1024x501.jpeg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-5-300x147.jpeg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-5-768x375.jpeg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-5-1536x751.jpeg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-5-50x24.jpeg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-5-82x40.jpeg 82w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-5-696x340.jpeg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-5-560x274.jpeg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-5-840x411.jpeg 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-5-80x39.jpeg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-5-48x23.jpeg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-5.jpeg 2048w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;step-2-build-a-paywall-in-the-revenuecat-dashboard&quot;&gt;Step 2: Build a Paywall in the RevenueCat Dashboard&lt;/h2&gt;



&lt;p&gt;Rather than manually coding a paywall UI, we’ll use &lt;strong&gt;RevenueCat Paywalls&lt;/strong&gt;, which let you design and deploy the entire purchase screen from the dashboard — including layout, copy, and products.&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Go to &lt;strong&gt;RevenueCat → Tools → Paywalls → + New Paywall&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;Choose one of the ready-made templates or build a fully custom paywall&lt;/li&gt;



&lt;li&gt;Select your &lt;strong&gt;Test Store products&lt;/strong&gt; as paywall packages&lt;/li&gt;



&lt;li&gt;Save and publish the Paywall&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;For this guide I repurposed our &lt;a href=&quot;https://www.revenuecat.com/docs/offerings/virtual-currency&quot;&gt;Virtual Currencies&lt;/a&gt; sample paywall for tips, since it’s originally used for buying consumable products as well. You now have a fully-hosted paywall definition that the SDK can use in your app, without having to write any UI code. &lt;/p&gt;



&lt;p&gt;Next step is to connect everything we’ve built in the dashboard to our app.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;501&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-4-1024x501.jpeg&quot; alt=&quot;Screenshot of RevenueCat Paywall builder &quot; class=&quot;wp-image-47134&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-4-1024x501.jpeg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-4-300x147.jpeg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-4-768x375.jpeg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-4-1536x751.jpeg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-4-50x24.jpeg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-4-82x40.jpeg 82w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-4-696x340.jpeg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-4-560x274.jpeg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-4-840x411.jpeg 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-4-80x39.jpeg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-4-48x23.jpeg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-4.jpeg 2048w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-3-install-and-configure-the-sdk&quot;&gt;Step 3: Install and configure the SDK&lt;/h2&gt;



&lt;p&gt;Using RevenueCat with React Native/Expo app requires you to install two SDKs, one for payment logic, and another for all the UI components such as paywalls and &lt;a href=&quot;https://www.revenuecat.com/docs/tools/customer-center&quot;&gt;Customer Center&lt;/a&gt;. In your React Native app, install the core SDK and Paywall UI package:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1smSNv wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;yarn add react-native-purchases react-native-purchases-ui\n# or\nnpm install react-native-purchases react-native-purchases-ui&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Now run your project and add the following code to the root level. Meaning either&lt;code&gt; _layout.tsx&lt;/code&gt; file or &lt;code&gt;index.tsx&lt;/code&gt;.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-J3M5C wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;import Purchases, { LOG_LEVEL } from &apos;react-native-purchases&apos;;\n\nexport default function RootLayout() {\n  const colorScheme = useColorScheme();\n\n  useEffect(() =&gt; {\n    Purchases.setLogLevel(LOG_LEVEL.VERBOSE);\n    Purchases.configure({apiKey: &apos;test_RVCJxmUuftIfuKAfYeMiHbLOrWw&apos;});\t\n  }, []);\n\n  return (\n    &lt;ThemeProvider value={colorScheme === &apos;dark&apos; ? DarkTheme : DefaultTheme}&gt;\n      &lt;Stack&gt;\n        &lt;Stack.Screen name=\&amp;quot;(tabs)\&amp;quot; options={{ headerShown: false }} \/&gt;\n        &lt;Stack.Screen name=\&amp;quot;modal\&amp;quot; options={{ presentation: &apos;modal&apos;, title: &apos;Modal&apos; }} \/&gt;\n      &lt;\/Stack&gt;\n      &lt;StatusBar style=\&amp;quot;auto\&amp;quot; \/&gt;\n    &lt;\/ThemeProvider&gt;\n  );\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;After doing that your app should initialize RevenueCat successfully. You will start to see the following type of logs in your console. If you’re working with Expo Go, you can go ahead and reload the project and RevenueCat should work. You will get logs that tell you RevenueCat is working in &lt;strong&gt;Browser Mode&lt;/strong&gt; — this means that you can’t for example make real purchases or display the native paywalls.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Zwx4IX wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;Logs for your project will appear below. Press Ctrl+C to exit.\niOS Bundled 3590ms node_modules\/expo-router\/entry.js (1429 modules)\niOS Bundled 38ms node_modules\/expo-router\/entry.js (1 module)\nLOG  Expo Go app detected. Using RevenueCat in Browser Mode.&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;With the Test Store we could already buy products, but since we want to use RevenueCat Paywalls, we need to switch to a development build in Expo, in order to install the native code parts. From the command line run &lt;code&gt;npx expo run:ios&lt;/code&gt;&lt;/p&gt;



&lt;p&gt;After this you’ll start seeing new type of logs:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Xrbcr wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;DEBUG  [RevenueCat] \u2139\ufe0f GetCustomerInfoOperation: Started\nDEBUG  [RevenueCat] \u2139\ufe0f Serial request done: GET \/v1\/subscribers\/$RCAnonymousID%3A526344dd895847649b76e314f2bce46d\/offerings, 0 requests left in the queue\n DEBUG  [RevenueCat] \u2139\ufe0f There are no requests currently running, starting request GET \/v1\/subscribers\/$RCAnonymousID%3A526344dd895847649b76e314f2bce46d\n LOG  [RevenueCat] Using etag &apos;d8a9a548a1de7ff4&apos; for request to &apos;https:\/\/api.revenuecat.com\/v1\/subscribers\/$RCAnonymousID%3A526344dd895847649b76e314f2bce46d&apos;. Validation time: 2025-10-22 09:12:13 +0000\n DEBUG  [RevenueCat] \u2139\ufe0f API request started: GET &apos;\/v1\/subscribers\/$RCAnonymousID%3A526344dd895847649b76e314f2bce46d&apos;\n LOG  [RevenueCat] Storing etag &apos;d8a9a548a1de7ff4&apos; for request to &apos;https:\/\/api.revenuecat.com\/v1\/subscribers\/$RCAnonymousID%3A526344dd895847649b76e314f2bce46d&apos; (createdSuccess)\n DEBUG  [RevenueCat] \u2139\ufe0f API request completed: GET &apos;\/v1\/subscribers\/$RCAnonymousID%3A526344dd895847649b76e314f2bce46d&apos; (304)\nRequest-ID: &apos;a3a36adb-c810-4186-bd1f-09a38e10d62f&apos;; Amzn-Trace-ID: &apos;Root=1-68f89ff9-2e3036473924438a1e277252&apos;\n LOG  [RevenueCat] Updating CustomerInfo &apos;$RCAnonymousID:526344dd895847649b76e314f2bce46d&apos; request date: 2025-10-22 09:12:25 +0000\n DEBUG  [RevenueCat] \ud83d\ude3b CustomerInfo updated from network.\n DEBUG  [RevenueCat] \u2139\ufe0f GetCustomerInfoOperation: Finished&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This means you’ve successfully initialized the RevenueCat SDK. The next step is to add the code for displaying the paywall. For that we are going to use the &lt;code&gt;RevenueCatUI.presentPaywall&lt;/code&gt; call that will show a paywall modal, and we’ll connect it to a simple button that says &lt;em&gt;“Tip me”&lt;/em&gt;. &lt;/p&gt;



&lt;p&gt;In your editor add the following code:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-zKWwj wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;export default function HomeScreen() {\n  return (\n    &lt;ParallaxScrollView\n      headerBackgroundColor={{ light: &apos;#A1CEDC&apos;, dark: &apos;#1D3D47&apos; }}\n      headerImage={\n        &lt;Image\n          source={require(&apos;@\/assets\/images\/partial-react-logo.png&apos;)}\n          style={styles.reactLogo}\n        \/&gt;\n      }&gt;\n      &lt;ThemedView style={styles.titleContainer}&gt;\n        &lt;ThemedText type=\&amp;quot;title\&amp;quot;&gt;Welcome!&lt;\/ThemedText&gt;\n        &lt;HelloWave \/&gt;\n      &lt;\/ThemedView&gt;\n      &lt;ThemedText&gt;\n      &lt;\/ThemedText&gt;\n      &lt;Button title=\&amp;quot;Tip me\&amp;quot; onPress={() =&gt; PurchasesUI.presentPaywall()} \/&gt;\n    &lt;\/ParallaxScrollView&gt;\n  );\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Now when you click the button you should be presented with the same paywall you built in RevenueCat dashboard:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;576&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Rotato-Image-718D-1024x576.png&quot; alt=&quot;Screenshot of iOS simulator running RevenueCat Paywall&quot; class=&quot;wp-image-47138&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Rotato-Image-718D-1024x576.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Rotato-Image-718D-300x169.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Rotato-Image-718D-768x432.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Rotato-Image-718D-1536x864.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Rotato-Image-718D-2048x1152.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Rotato-Image-718D-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Rotato-Image-718D-71x40.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Rotato-Image-718D-696x392.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Rotato-Image-718D-560x315.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Rotato-Image-718D-526x296.png 526w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Rotato-Image-718D-840x472.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Rotato-Image-718D-80x45.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Rotato-Image-718D-48x27.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Pressing on the buttons to purchase will show you a native modal asking if you want to test a failed or successful purchase. Play around with this — if you feel like it, you can also tie actions to the purchase results, for example to navigate to a separate thank you screen after a user has tipped you successfully.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;step-4-setting-up-your-products-in-app-store-connect-and-google-play-console&quot;&gt;Step 4: Setting up your products in App Store Connect and Google Play Console&lt;/h2&gt;



&lt;p&gt;Everything looks good now on the simulator and emulator. The Test Store is great for this kind of local testing, helping you verify your in-app purchases and entitlements without needing to publish your app.&lt;/p&gt;



&lt;p&gt;However, before going live, you should also test using your App Store Connect and Google Play Console setups. Real store testing ensures your product identifiers, pricing, and configurations all work as expected in production. You should use the Test Store for quick local testing, but always confirm everything functions correctly in the actual store environments before release.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;app-store-connect&quot;&gt;App Store Connect&lt;/h3&gt;



&lt;p&gt;To connect your app to real stores such as the App Store and Google Play, navigate back to the &lt;strong&gt;Apps &amp;amp; Providers&lt;/strong&gt; page and select the stores you want to integrate. Let’s start with the &lt;strong&gt;App Store&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;First, your app must exist in &lt;strong&gt;App Store Connect&lt;/strong&gt;. Register your &lt;strong&gt;bundle ID&lt;/strong&gt; and create the app in App Store Connect. Also &lt;a href=&quot;https://www.revenuecat.com/docs/service-credentials/itunesconnect-app-specific-shared-secret&quot;&gt;enable communication between RevenueCat and App Store Connect.&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;After your app is set up in App Store Connect, you can actually create products directly from the &lt;strong&gt;RevenueCat dashboard&lt;/strong&gt; and have them synced automatically to App Store Connect. To do this, go to &lt;strong&gt;Product catalog&lt;/strong&gt;, create a new product, and select &lt;strong&gt;App Store&lt;/strong&gt; as the store. RevenueCat will then prompt you to authorize the creation of the corresponding product in App Store Connect.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;501&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/3-・-Medium-Copy-15@2x-1024x501.jpg&quot; alt=&quot;Screenshot of RevenueCat dashboard and App Store Connect product creation.&quot; class=&quot;wp-image-47175&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/3-・-Medium-Copy-15@2x-1024x501.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/3-・-Medium-Copy-15@2x-300x147.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/3-・-Medium-Copy-15@2x-768x375.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/3-・-Medium-Copy-15@2x-1536x751.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/3-・-Medium-Copy-15@2x-2048x1001.jpg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/3-・-Medium-Copy-15@2x-50x24.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/3-・-Medium-Copy-15@2x-82x40.jpg 82w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/3-・-Medium-Copy-15@2x-696x340.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/3-・-Medium-Copy-15@2x-560x274.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/3-・-Medium-Copy-15@2x-840x411.jpg 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/3-・-Medium-Copy-15@2x-80x39.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/3-・-Medium-Copy-15@2x-48x23.jpg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;You’ll still need to fill in certain product details in App Store Connect, such as &lt;strong&gt;pricing, availability, and screenshots&lt;/strong&gt;. Open App Store Connect and complete these fields to finalize your setup. Our &lt;a href=&quot;https://www.revenuecat.com/docs/getting-started/entitlements/ios-products&quot;&gt;App Store Connect product setup&lt;/a&gt; guide can help you verify that your products are set up correctly.&lt;/p&gt;



&lt;p&gt;As the last step, replace your &lt;strong&gt;Test Store API key&lt;/strong&gt; with the &lt;strong&gt;App Store API key&lt;/strong&gt;, which you can find in the &lt;strong&gt;RevenueCat dashboard&lt;/strong&gt; under &lt;strong&gt;API Keys&lt;/strong&gt;. Finally, build your app for a physical device instead of the simulator to complete the integration.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;google-play-console&quot;&gt;Google Play Console&lt;/h3&gt;



&lt;p&gt;Next, let’s connect your products to &lt;strong&gt;Google Play Console&lt;/strong&gt;. Make sure your app is already created in the Play Console with the correct package name.&lt;/p&gt;



&lt;p&gt;To enable this connection, you’ll need to set up &lt;strong&gt;Google Play Service Credentials&lt;/strong&gt;. These allow RevenueCat to securely communicate with your Play Developer account to manage products and validate purchases. You can follow our full step-by-step guide here: &lt;a href=&quot;https://www.revenuecat.com/docs/service-credentials/creating-play-service-credentials&quot;&gt;Creating Google Play Service Credentials.&lt;br&gt;&lt;br&gt;&lt;/a&gt;After correctly setting up your Service Credentials, it can take up to 36 hours to be activated. Once that happens you can create products in the RevenueCat Dashboard. Follow our&lt;a href=&quot;https://www.revenuecat.com/docs/getting-started/entitlements/android-products&quot;&gt; Google Play product setup guide &lt;/a&gt;for next steps.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-your-tip-jar-is-ready&quot;&gt;Your tip jar is ready!&lt;/h2&gt;



&lt;p&gt;Implementing a tip jar using RevenueCat with consumable in-app purchases is a straightforward way to offer your users a means to support your app without committing to a subscription. This approach allows users to express their appreciation at their convenience, providing a flexible monetization strategy for simple yet valuable applications. By following these steps, you can quickly integrate this feature into your React Native with only few lines of code.&lt;/p&gt;



&lt;p&gt;If you run in to any problems, or you want to chat more about using tip jars for monetizing, &lt;a href=&quot;https://perttu.dev/about&quot;&gt;please let me know&lt;/a&gt;! &lt;/p&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Understanding Google Play subscription proration: a developer’s guide]]></title><description><![CDATA[Google Play's subscription proration system gives you fine-grained control over how users are charged when changing plans.]]></description><link>https://www.revenuecat.com/blog/engineering/google-proration/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/google-proration/</guid><pubDate>Thu, 23 Oct 2025 23:07:50 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Google-Play-Proration.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;When users upgrade from your $4.99/month basic plan to your $9.99/month premium plan mid-billing cycle, what happens when they’ve already paid? Do they get charged immediately? Does their billing date change? The answer depends entirely on which &lt;strong&gt;proration mode&lt;/strong&gt; you choose, and choosing the wrong one can cost you revenue or create a confusing user experience.&lt;/p&gt;



&lt;p&gt;If you’ve ever wondered why Google Play offers five different subscription replacement modes (or what ‘proration’ even means in this context), you’re in the right place. Read on for a breakdown of each mode with concrete examples, and explore the technical implementation details from the &lt;a href=&quot;https://www.revenuecat.com/docs/getting-started/installation/android&quot;&gt;RevenueCat Android SDK&lt;/a&gt;, to help you choose the right approach for your app.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-is-proration-anyway&quot;&gt;&lt;strong&gt;What is proration, anyway?&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The proration is the process of calculating fair billing when a user switches subscription plans mid-cycle. The term comes from the Latin &lt;em&gt;pro rata&lt;/em&gt; (“in proportion”), and it’s all about making sure users pay the right amount when their subscription changes.&lt;/p&gt;



&lt;p&gt;Google Play provides five distinct proration modes, each handling the timing of charges and billing cycles differently. Let’s say James is on your &lt;strong&gt;Tier 1&lt;/strong&gt; subscription at $2/month and wants to switch to &lt;strong&gt;Tier 2&lt;/strong&gt; at $36/year on April 15, halfway through his monthly billing cycle. Here’s what happens with each mode.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-five-replacement-modes&quot;&gt;&lt;strong&gt;The five replacement modes&lt;/strong&gt;&lt;/h2&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-without-proration-the-reset&quot;&gt;&lt;strong&gt;1. WITHOUT_PRORATION (the reset)&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The old subscription is cancelled immediately, the new one starts right away, but the user isn’t charged until the old subscription expires.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-2aCNa8 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;enum class GoogleReplacementMode(\n    @BillingFlowParams.SubscriptionUpdateParams.ReplacementMode val playBillingClientMode: Int,\n) : ReplacementMode {\n    \/**\n     * Old subscription is cancelled, and new subscription takes effect immediately.\n     * User is charged for the full price of the new subscription on the old\n     * subscription&apos;s expiration date.\n     *\/\n    WITHOUT_PRORATION(\n        BillingFlowParams.SubscriptionUpdateParams.ReplacementMode.WITHOUT_PRORATION\n    ),\n    \/\/ ...\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; On April 15, James upgrades to Tier 2 and immediately gets access to the premium features. However, the remaining $1 from his half-used monthly subscription is simply forfeited. He won’t be charged for the new tier until May 1 (when his old subscription would have expired), at which point he pays the full $36 for Tier 2. From that point forward, his billing date becomes May 1 each year.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt; When you want simplicity and are okay with essentially giving away the rest of the current billing period. This mode is straightforward but can be costly if you have expensive subscriptions.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Gotcha:&lt;/strong&gt; The user essentially gets free access to the new tier until their old subscription expires. If James was on an annual plan, you’d be giving him six months of free premium access!&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;2-withtimeproration-the-date-pusher&quot;&gt;&lt;strong&gt;2. WITH_TIME_PRORATION (the date pusher)&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The new subscription starts immediately, but the unused time from the old subscription pushes out the first payment date for the new plan.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1tWPPa wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/**\n * Old subscription is cancelled, and new subscription takes effect immediately.\n * Any time remaining on the old subscription is used to push out the first\n * payment date for the new subscription.\n *\n * The purchase will fail if this mode is used when switching between\n * SubscriptionOptions of the same StoreProduct.\n *\/\nWITH_TIME_PRORATION(\n    BillingFlowParams.SubscriptionUpdateParams.ReplacementMode.WITH_TIME_PRORATION\n),\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; When James upgrades on April 15, his Tier 1 subscription ends immediately. The $1 remaining from his old subscription acts as credit toward the new plan. Since the new plan costs $36/year (or $3/month), that $1 credit covers approximately 10 days of service (April 16–25). This means his first charge for the new tier happens around April 26, and he’ll be charged $36 annually from that date going forward.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt; When you want to honor the value of the old subscription without complicating the math. Users appreciate not ‘losing’ money, but your billing dates become unpredictable.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Gotcha:&lt;/strong&gt; Different users on the same plan end up with different billing dates depending on when they upgraded. This can complicate reporting and churn analysis.&lt;/p&gt;



&lt;p&gt;You should keep in mind that this mode &lt;strong&gt;will fail&lt;/strong&gt; if used when switching between different subscription options &lt;em&gt;of the same product&lt;/em&gt;. For example, switching from an annual plan to a monthly plan of the same product. Only use this when changing between entirely different products.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;3-chargefullprice-the-immediate-extension&quot;&gt;&lt;strong&gt;3. CHARGE_FULL_PRICE (the immediate + extension)&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Users are charged immediately for the full price of the new plan, and the unused time from the old plan extends their subscription period.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1U5k1q wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/**\n * Replacement takes effect immediately, and the user is charged full price\n * of new plan and is given a full billing cycle of subscription, plus\n * remaining prorated time from the old plan.\n *\/\nCHARGE_FULL_PRICE(\n    BillingFlowParams.SubscriptionUpdateParams.ReplacementMode.CHARGE_FULL_PRICE\n),\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; On April 15 when James upgrades, he’s immediately charged the full $36 for the new tier. In return, he gets a full year of service plus an extra 10 days, the prorated value of his unused $1 credit from the old subscription. This means his subscription runs until April 25 of the following year, at which point he’s charged $36 again. Every year thereafter, April 25 becomes his new billing date.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt; When you want immediate revenue and have the cash flow to justify giving users extra time. This mode generates revenue upfront, which is great for your MRR, but you’re essentially extending their subscription for free.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Gotcha:&lt;/strong&gt; You’re giving away extra subscription time (10 days in this example). Multiply that across thousands of users upgrading from monthly to annual plans, and you could be giving away weeks or months of service.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;4-chargeproratedprice-the-fair-deal&quot;&gt;&lt;strong&gt;4. CHARGE_PRORATED_PRICE (the fair deal)&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The new subscription starts immediately, the billing cycle stays the same, and the user is charged the prorated difference right now.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-FR2lP wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/**\n * Replacement takes effect immediately, and the billing cycle remains the same.\n *\n * Example: Since Tier 2 subscription price per time unit ($36\/year = $3\/month)\n * is greater than Tier 1 subscription price per time unit ($2\/month), this mode\n * can be used. James is charged the difference for the remaining 15 days.\n *\/\nCHARGE_PRORATED_PRICE(\n    BillingFlowParams.SubscriptionUpdateParams.ReplacementMode.CHARGE_PRORATED_PRICE\n),\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; When James upgrades on April 15, Google Play calculates that he has $1 in unused credit from Tier 1, but the remaining 15 days at the new Tier 2 price would cost $1.50 (since the new tier costs $3/month, half of that is $1.50). The difference is $0.50, which James is charged immediately. Then on May 1, his original billing date, he’s charged the full $36 for a year of Tier 2 service. Every May 1 thereafter, he continues to pay $36, keeping his billing date consistent.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt; This is often the ‘fairest’ option from both a user and revenue perspective. Users pay only for what they use, billing dates stay consistent, and you get immediate revenue for the upgrade.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Important requirement:&lt;/strong&gt; This only works when the new plan has a &lt;strong&gt;higher price per time unit&lt;/strong&gt; than the old plan. In our example, $3/month &amp;gt; $2/month, so it works. If you’re moving someone from annual to monthly billing, this mode won’t be available.&lt;/p&gt;



&lt;p&gt;This is best for upgrades where you want to maintain consistent billing dates and charge users fairly for the change.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;5-deferred-the-wait-and-see&quot;&gt;&lt;strong&gt;5. DEFERRED (the wait-and-see)&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Nothing happens until the old subscription expires. Then the new subscription kicks in.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1w0WH8 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/**\n * Replacement takes effect when the old plan expires, and the new price\n * will be charged at the same time.\n *\/\nDEFERRED(BillingFlowParams.SubscriptionUpdateParams.ReplacementMode.DEFERRED),\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; When James initiates the upgrade on April 15, he sees a message confirming “You’ll be upgraded to Tier 2 on May 1”. For the next two weeks nothing changes, he continues to enjoy his Tier 1 features and access. Then on May 1, his old subscription expires, the new Tier 2 subscription activates, and he’s charged $36. From that point forward, he’s billed $36 annually on May 1.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt; For downgrades, or when you want to honor the full value of the current subscription period. This is the most conservative option and avoids any complexity with refunds or prorated charges.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;User experience:&lt;/strong&gt; Great for downgrades (users get to keep premium features until their subscription ends) but potentially frustrating for upgrades (users have to wait to access features they want to pay for).&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-deferred-mode-gotcha-a-technical-deep-dive&quot;&gt;&lt;strong&gt;The DEFERRED mode gotcha: a technical deep dive&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Here’s where things get interesting. When implementing DEFERRED mode, there’s a subtle but critical callback handling issue that can bite you if you’re not careful.&lt;/p&gt;



&lt;p&gt;The problem is when a user initiates a deferred upgrade, which product ID do you use to store the callback context? Let’s look at how RevenueCat handles this in the Android SDK:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1QmHIU wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;synchronized(this@BillingWrapper) {\n    \/\/ When using DEFERRED proration mode, callback needs to be associated\n    \/\/ with the *old* product we are switching from, because the transaction\n    \/\/ we receive on successful purchase is for the old product.\n    val productId =\n        if (replaceProductInfo?.replacementMode == GoogleReplacementMode.DEFERRED) {\n            replaceProductInfo.oldPurchase.productIds.first()\n        } else {\n            googlePurchasingData.productId\n        }\n    purchaseContext[productId] = PurchaseContext(\n        googlePurchasingData.productType,\n        presentedOfferingContext,\n        subscriptionOptionId,\n        replaceProductInfo?.replacementMode as? GoogleReplacementMode?,\n    )\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Why this matters:&lt;/strong&gt; With DEFERRED mode, Google Play immediately returns a successful transaction response, but that transaction is for the &lt;strong&gt;old product&lt;/strong&gt;, not the new one. The new product transaction won’t come through until the old subscription expires.&lt;/p&gt;



&lt;p&gt;If you naively stored your callback under the new product ID, you’d never receive the success callback because the transaction event comes through with the old product ID.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;In our example:&lt;/strong&gt; When a user initiates an upgrade from tier_1_monthly to tier_2_annual using DEFERRED mode, Google Play immediately returns a successful transaction but crucially, that transaction is associated with tier_1_monthly, not the new product. If you stored your callback under tier_1_monthly, it gets triggered correctly. However, if you naively stored it under tier_2_annual, your callback would never fire, leaving your app in a broken state where the user thinks the upgrade failed.&lt;/p&gt;



&lt;p&gt;This is one of those implementation details that seems obvious in hindsight but can cause hours of debugging when you’re handling purchase callbacks and they mysteriously never fire.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;choosing-the-right-mode-a-decision-guide&quot;&gt;&lt;strong&gt;Choosing the right mode: A decision guide&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The selection of proration mode should be driven by your business model and user experience goals. Start by determining whether the change is a downgrade or upgrade. For downgrades, DEFERRED is almost always the right choice since it lets users keep their premium features until the subscription naturally expires, which maintains goodwill.&lt;/p&gt;



&lt;p&gt;For upgrades, the decision becomes more nuanced. If you need immediate revenue and the new plan is more expensive per time unit than the old plan, CHARGE_PRORATED_PRICE is typically your best option. It charges users fairly for just the difference, keeps billing dates consistent, and generates immediate revenue. If the new plan isn’t more expensive per time unit (such as switching from monthly to annual billing at a discount), you’ll need to use CHARGE_FULL_PRICE instead, which charges the full amount immediately but extends the subscription period by the prorated credit.&lt;/p&gt;



&lt;p&gt;On the other hand, if generating immediate revenue isn’t a priority and you want to maximize user satisfaction, WITH_TIME_PRORATION honors the full value of the user’s previous subscription by pushing out their first payment date. Just be aware this creates varying billing dates across your user base.&lt;/p&gt;



&lt;p&gt;For simplicity at the cost of potential revenue loss, WITHOUT_PRORATION gives users free access to the new tier until their old subscription expires. This works fine for inexpensive subscriptions but can become costly at scale.&lt;/p&gt;



&lt;p&gt;So the recommendation is, for most apps, CHARGE_PRORATED_PRICE offers the best balance of fairness, revenue timing, and user experience for upgrades, while DEFERRED is ideal for downgrades to maintain goodwill.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;implementation-in-revenuecat&quot;&gt;&lt;strong&gt;Implementation in RevenueCat&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;If you’re using RevenueCat, handling proration is straightforward:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1JGGMB wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;import com.revenuecat.purchases.models.GoogleReplacementMode\n\n\/\/ For an upgrade\nPurchases.sharedInstance.purchaseWith(\n    activity = this,\n    packageToPurchase = newPackage,\n    googleReplacementMode = GoogleReplacementMode.CHARGE_PRORATED_PRICE\n)\n\n\/\/ For a downgrade\nPurchases.sharedInstance.purchaseWith(\n    activity = this,\n    packageToPurchase = newPackage,\n    googleReplacementMode = GoogleReplacementMode.DEFERRED\n)\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The SDK handles all the complexity we discussed including the DEFERRED callback gotcha automatically.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;common-pitfalls&quot;&gt;&lt;strong&gt;Common pitfalls&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;One of the most common mistakes is using WITH_TIME_PRORATION when switching between different options of the same product, such as moving from premium_monthly to premium_annual. Google Play will reject this request because these are considered different subscription options of the same base product, not entirely different products. If you need to handle these transitions, you’ll have to use a different proration mode.&lt;/p&gt;



&lt;p&gt;Another issue involves time zones. Proration calculations happen server-side using Google’s timezone, not the user’s device timezone. If you’re doing any client-side date math to display when the next charge will occur or when a deferred upgrade will take effect, make sure you account for potential timezone differences between your calculations and Google’s backend.&lt;/p&gt;



&lt;p&gt;When implementing DEFERRED mode, it’s critical to update your UI appropriately. If a user initiates a deferred upgrade, showing a message like “Upgrade successful, enjoy premium features now!” would be misleading since they won’t actually get those features until their current subscription expires. Instead, you need to check the replacement mode and display something like “You’ll be upgraded to Premium on May 1” to set proper expectations.&lt;/p&gt;



&lt;p&gt;Finally, don’t assume that all proration modes are always available for every product change. The mode you want to use might not be valid for the specific transition you’re attempting. Your code should handle potential failures gracefully and fall back to a simpler mode when needed. For example, if CHARGE_PRORATED_PRICE fails, you might fall back to WITHOUT_PRORATION as a safe default:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1J55EX wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;try {\n    purchaseWith(\n        googleReplacementMode = GoogleReplacementMode.CHARGE_PRORATED_PRICE\n    )\n} catch (e: PurchasesException) {\n    \/\/ Fall back to a simpler mode\n    purchaseWith(\n        googleReplacementMode = GoogleReplacementMode.WITHOUT_PRORATION\n    )\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;real-world-revenue-impact&quot;&gt;&lt;strong&gt;Real-world revenue impact&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The choice of proration mode has financial implications at scale. Consider a scenario where 10,000 users upgrade from a $9.99 monthly plan to a $99.99 annual plan, with users upgrading on average halfway through their billing cycle.&lt;/p&gt;



&lt;p&gt;With WITHOUT_PRORATION, you’re effectively forfeiting $5 per user (half of the remaining monthly subscription value), which across 10,000 users amounts to &lt;strong&gt;$50,000 in lost revenue&lt;/strong&gt;. While this mode offers simplicity, that’s a substantial cost.&lt;/p&gt;



&lt;p&gt;Using CHARGE_PRORATED_PRICE, you’d charge each user approximately $4.16 for the remaining half month at the annual rate, generating &lt;strong&gt;$41,600 in immediate revenue&lt;/strong&gt;. This mode captures most of the value you’d otherwise forfeit while maintaining user trust through fair billing.&lt;/p&gt;



&lt;p&gt;WITH_TIME_PRORATION delays revenue by roughly 15 days per user as their first charge is pushed out by the prorated credit. Beyond the direct revenue delay, this creates complications for month-over-month MRR calculations since different users have different billing dates, potentially skewing your growth metrics and making churn analysis more complex.&lt;/p&gt;



&lt;p&gt;The bottom line: choosing a proration mode isn’t just a technical decision, it’s a business decision with real revenue implications that scale with your user base.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;testing-your-implementation&quot;&gt;&lt;strong&gt;Testing your implementation&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Thorough testing of proration modes requires using Google Play’s test tracks with a variety of scenarios. Start with the most common case: mid-cycle upgrades, such as moving from monthly to annual billing or from a basic to premium tier. These represent the majority of real-world subscription changes your users will make.&lt;/p&gt;



&lt;p&gt;Next, test downgrade scenarios where users move from annual to monthly billing or from premium to basic tiers. These flows often behave differently and may require different UI messaging, especially if you’re using DEFERRED mode.&lt;/p&gt;



&lt;p&gt;Don’t neglect edge cases that can expose timing bugs. Test upgrades initiated on the very last day of a billing period, where proration calculations might behave unexpectedly. Similarly, test upgrades on the first day of a billing period when users have just renewed. Multiple rapid subscription changes where a user changes plans several times in quick succession can also reveal race conditions in callback handling.&lt;/p&gt;



&lt;p&gt;For DEFERRED mode specifically, verify that your success callback fires correctly even though the transaction is associated with the old product ID rather than the new one. Additionally, confirm that the new subscription actually activates on the expected date when the old subscription expires, as this delayed activation is easy to miss in testing if you’re not explicitly checking for it.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;tldr&quot;&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Google Play’s subscription proration system gives you fine-grained control over how users are charged when changing plans. Each of the five modes serves distinct use cases:&amp;nbsp;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;CHARGE_PRORATED_PRICE works best for fair, immediate upgrades where you want to maintain consistent billing dates&lt;/li&gt;



&lt;li&gt;DEFERRED is ideal for downgrades and preserving user goodwill&lt;/li&gt;



&lt;li&gt;WITH_TIME_PRORATION makes sense when honoring the full value of the old subscription matters more than billing date consistency&lt;/li&gt;



&lt;li&gt;CHARGE_FULL_PRICE generates immediate revenue at the cost of extending subscription periods&lt;/li&gt;



&lt;li&gt;WITHOUT_PRORATION offers simplicity when you’re willing to write off the remaining subscription value&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The most important thing is to be intentional about your choice. Consider your users’ expectations, your revenue model, and your analytics infrastructure when making this decision.&lt;/p&gt;



&lt;p&gt;And remember: if you’re using DEFERRED mode, make sure your callbacks are listening to the right product ID. Your future self will thank you when you’re not debugging phantom purchase flows at 2am.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/&quot;&gt;RevenueCat&lt;/a&gt; handles all of this complexity automatically, including the tricky callback management for DEFERRED purchases. Check out our&lt;a href=&quot;https://www.revenuecat.com/docs/getting-started/installation/android&quot;&gt; Android SDK&lt;/a&gt; to see the implementation in action. For further reading, check out the references below:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/subscription-guidance/managing-subscriptions#google-play&quot;&gt;RevenueCat Docs: Upgrades, Downgrades, &amp;amp; Management&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://developer.android.com/google/play/billing/subscriptions#proration&quot;&gt;Google Play Billing: Subscription proration examples&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode&quot;&gt;BillingClient API Reference&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title><![CDATA[Boosting ARPU with ads: How to monetize free users without degrading UX]]></title><description><![CDATA[A step-by-step guide to integrating ad revenue without losing users]]></description><link>https://www.revenuecat.com/blog/growth/ad-monetization-subscription-apps/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/ad-monetization-subscription-apps/</guid><pubDate>Wed, 22 Oct 2025 17:01:20 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/How-to-monetize-free-users-without-harming-UX.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Mobile apps, especially the ones that rely solely on subscription-based models, tend to group users into two camps: they either pay, or they ‘churn’ by remaining a non-paying user.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;But this is far from accurate, and ignores the path to monetize free users: with ads.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-when-to-consider-adding-ads-to-your-app&quot;&gt;&lt;strong&gt;When to consider adding ads to your app&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Top-performing app teams are already using ads to increase their ARPU, even across free users, and boost their top-line to become more profitable in record time.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Now, before jumping in and introducing ads to your app, consider these things:&lt;/p&gt;



&lt;p&gt;The first and most important thing to consider is &lt;strong&gt;scale — meaning the number of daily active users (DAUs) your mobile application currently has&lt;/strong&gt;. The ad monetization game makes the most sense at scale.&lt;/p&gt;



&lt;p&gt;For example, I recommend considering this a task in your business when you can start making at least $100 a day in profit. If you have at least 10,000 DAUs and expect each to see an ad daily, with an average effective cost per mille (eCPM) of $10, then it makes sense to consider ads.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;194&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/scale-1024x194.png&quot; alt=&quot;&quot; class=&quot;wp-image-47149&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/scale-1024x194.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/scale-300x57.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/scale-768x145.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/scale-1536x291.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/scale-50x9.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/scale-125x24.png 125w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/scale-696x132.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/scale-560x106.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/scale-840x159.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/scale-80x15.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/scale-48x9.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/scale.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;You also need to consider your DAUs’ location. If your user base is primarily in tier two or tier three countries, your expected scale will need to be much bigger than 10,000 DAUs.&lt;/p&gt;



&lt;p&gt;Once you have sufficient DAU and your subscription monetization is performing in the top percentile of industry benchmarks (onboarding, paywall, pricing, trials), it makes sense to reinvest a portion of the incremental profit from new revenue streams. In other words, keep subscription optimization your first priority.&lt;/p&gt;



&lt;p&gt;I’d also suggest you consider adding ads only if you have &lt;strong&gt;the technical capacity to add this new revenue stream to your stack&lt;/strong&gt;. If not, tools like &lt;a href=&quot;https://www.appstack.tech/&quot;&gt;Appstack&lt;/a&gt; can help you unify all your data sources in a single place, including ad mediation.&lt;/p&gt;



&lt;p&gt;Finally, &lt;strong&gt;make sure to have enough time for it&lt;/strong&gt;. Ad monetization has a long learning curve, there is little valuable information online, and it’s hard to get high-quality insights worth your time. So consider that it will require more of your time than expected. For beginners, I always recommend &lt;a href=&quot;https://felixbraberg.substack.com/p/a-beginners-guide-to-ad-monetization-797&quot;&gt;listening to this podcast&lt;/a&gt; from Two and a Half Gamers, hosted by &lt;a href=&quot;https://www.linkedin.com/in/felix-braberg-7a732b51/&quot;&gt;Felix Braberg&lt;/a&gt;.&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-Z1NwCYM wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;RevenueCat now tracks your ad revenue alongside subscriptions&quot; text=&quot;&lt;p&gt;Apps using ad mediation platforms like Google AdMob or AppLovin can send ad events directly to RevenueCat via the SDK — giving hybrid monetization apps a complete, &lt;a href=&amp;quot;https://www.revenuecat.com/feature/charts/&amp;quot;&gt;unified view of your business in one dashboard&lt;/a&gt;.&lt;!-- notionvc: 2adc82bf-316e-428d-be77-f0369e459e8a --&gt;&lt;/p&gt;&quot; icon=&quot;bulb&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-common-challenges-when-monetizing-free-users-with-ads&quot;&gt;&lt;strong&gt;Common challenges when monetizing free users with ads&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;If your app seems qualified and you’re ready to monetize free users, the first thing to do is know what you’re getting in for. Adding ads to your mobile app is not as easy as it appears.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;After working with multiple apps, these are some of the most frequent challenges I see when it comes to ad monetization.&lt;/p&gt;



&lt;p&gt;Firstly — team setup. Most marketing teams don’t have the technical foundation needed to set ad monetization up correctly. I’ve seen numerous app studios try to do this with the internal team and never achieve anything substantial.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;My recommendation: &lt;strong&gt;hire a freelancer with relevant experience&lt;/strong&gt;, or &lt;strong&gt;pair your marketing team with an experienced developer&lt;/strong&gt; — this balances one individual with a clear technical understanding, and one with the vision for the product and business goals.&lt;/p&gt;



&lt;p&gt;The second word of warning is &lt;strong&gt;expect to iterate&lt;/strong&gt;. You won’t get it right on your first try, (though I hope you prove me wrong). It’s easy to be overly ambitious. Try to break the goal into small, testable steps. For example, if you’re aiming for a complex Firebase Remote Config setup across multiple ad networks connected to your mediation… start simple:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Connect the Firebase SDK&lt;/li&gt;



&lt;li&gt;Add and monetize a new ad unit&lt;/li&gt;



&lt;li&gt;Expand step by step&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;One word of warning is on ad logic. Something I’ve personally battled is &lt;strong&gt;apps that have ad logic hard-coded into them&lt;/strong&gt;. This is a nightmare; it’s nearly impossible to decode, slows down iteration, and blocks migration to a fully remote setup. If you only take one piece of advice, adjust this before you begin.&lt;/p&gt;



&lt;p&gt;If you’re transitioning to a new ad monetization stack, &lt;strong&gt;maintaining stable ad revenue during the change is a significant win &lt;/strong&gt;— it’s not easy to do, so take a moment to celebrate your accomplishment!&lt;/p&gt;



&lt;p&gt;Finally, know that &lt;strong&gt;this work can feel lonely&lt;/strong&gt;! The ad monetization community is small, and there’s not much public information to learn from or communities to find. It’s okay to struggle with your development and experiments, but keep pushing through. It’s worth it in the end.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-endless-dilemma-revenue-over-retention&quot;&gt;&lt;strong&gt;The endless dilemma: revenue over retention&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Everything in ad monetization comes down to a simple question: &lt;strong&gt;how can we increase ARPU via ads without pushing users to churn?&lt;/strong&gt;&amp;nbsp;&lt;/p&gt;



&lt;p&gt;In other words, how can I show as many ads as possible to a single user, without affecting their behaviour and willingness to open the app repeatedly? Here are three considerations:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Your app’s category: &lt;/strong&gt;Whether users are willing to put up with ads largely depends on the app’s purpose. Ads placed on banking or fintech applications are not standard, but ads on gaming apps are incredibly common. Weigh up the patience your users will have for ads.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Sacrifice for gain: &lt;/strong&gt;In short, &lt;strong&gt;are you willing to sacrifice a cohort of users to gain a potential uplift in revenue?&lt;/strong&gt; While frequency, timing, placement, and other variables can considerably increase (or decrease) your churn rate, there is no guaranteed way to remove the risk that comes with ads. Are you confident enough to risk it?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Testing strategy:&lt;/strong&gt; Be bold with your experiments. Run aggressive tests with a significant share of your user base to gather reliable, fast data — this is the most accurate way to predict how far you can push users without hurting retention. Avoid wasting time being cautious, as it only delays finding your ARPU ceiling.&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-5-levers-to-safely-increase-arpu-and-monitor-churn&quot;&gt;&lt;strong&gt;5 Levers to safely increase ARPU (and monitor churn)&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;While you can’t remove all risk of harming user retention, there are ways to reduce it.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-ecpm-management&quot;&gt;&lt;strong&gt;eCPM management&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The Effective Cost Per Mille (eCPM) is a key ad monetization metric that measures total revenue generated per 1,000 ad impressions. It’s calculated as &lt;em&gt;(total earnings / total impressions) x 1,000.&lt;/em&gt;&amp;nbsp;&lt;/p&gt;



&lt;p&gt;The goal is to &lt;strong&gt;have the highest possible eCPM value while maximizing the number of impressions&lt;/strong&gt;. Finding the equilibrium point is hard.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;784&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/ecpm-1024x784.png&quot; alt=&quot;&quot; class=&quot;wp-image-47151&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/ecpm-1024x784.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/ecpm-300x230.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/ecpm-768x588.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/ecpm-1536x1176.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/ecpm-50x38.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/ecpm-52x40.png 52w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/ecpm-606x464.png 606w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/ecpm-696x533.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/ecpm-560x429.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/ecpm-387x296.png 387w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/ecpm-617x472.png 617w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/ecpm-80x61.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/ecpm-48x37.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/ecpm.png 1564w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;One tip is to treat this balance between impressions and eCPM differently depending on the user location:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Tier 1 countries: &lt;/strong&gt;Aim to get a high eCPM with low impressions to reduce churn while increasing the amount of in-app purchases&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Tier 2/3 countries: &lt;/strong&gt;Aim for a reduced eCPM and high amount of impressions — these users are less likely to buy an in-app purchase, and are more used to watching ads to get an expected reward&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;With your ad mediation provider, you can play with manual bids or automatic setup, although the second option tends to match all the ad requests to have a show rate close to 100%.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-upsell-to-in-app-purchases&quot;&gt;&lt;strong&gt;Upsell to in-app purchases&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Increasing ad monetization shouldn’t be about filling your product with ads — it should be about &lt;strong&gt;incentivizing users to upgrade&lt;/strong&gt; &lt;strong&gt;their experience by purchasing an entitlement&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;While it might seem like this approach could hurt retention, you can avoid that by &lt;strong&gt;limiting ad impressions for new users&lt;/strong&gt; &lt;strong&gt;and instead targeting highly-engaged users&lt;/strong&gt; after a set number of days — those who’ve already shown a willingness to watch ads rather than pay.&lt;/p&gt;



&lt;p&gt;For example, I worked with an app whose main goal was to drive premium conversions but offered a rewarded ad as an alternative way to complete an action. It worked incredibly well: users who wanted to skip the ad chose to pay instead. This is one of the most effective ways to boost ARPU through voluntary choice.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-ad-unit-placement&quot;&gt;&lt;strong&gt;Ad unit placement&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Give ads strategic placement in-app: &lt;strong&gt;placement that gives enough friction that it encourages them to pay&lt;/strong&gt;, but not so much it pushes the user to leave the app.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;428&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/unnamed-1024x428.png&quot; alt=&quot;&quot; class=&quot;wp-image-47154&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/unnamed-1024x428.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/unnamed-300x125.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/unnamed-768x321.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/unnamed-1536x642.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/unnamed-50x21.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/unnamed-96x40.png 96w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/unnamed-696x291.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/unnamed-560x234.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/unnamed-840x351.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/unnamed-80x33.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/unnamed-48x20.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/unnamed.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;In the past, I had massive success with a subscription app that placed an ad in a specific section of the product where the user wanted to download an image. The app allowed users to download a particular background image as one of its features (it was not the main feature, but thousands of users were doing this action every day). Users were willing to watch an ad to avoid paying because the user intent was high in this specific flow.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-ad-format&quot;&gt;&lt;strong&gt;Ad format&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The format of ads could be a banner, interstitial, rewarded, etc. Based on my experience, the primary focus for subscription apps should be &lt;strong&gt;understanding how to leverage interstitials and rewarded ads,&lt;/strong&gt; as these two have the highest eCPM.&lt;/p&gt;



&lt;p&gt;On top of that, depending on the ad placement, you need control of the ad type, e.g. whether the interstitials or rewarded ads will show an image or video. For example, if the placement could be sensitive to user churn, having a specific interstitial ad ID with an image type makes sense. But if you are confident that the placement is ideal to maximize revenue, and users would be willing to watch an ad, you could show a rewarded ad with a video type.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-ai-predictive-flow&quot;&gt;&lt;strong&gt;AI predictive flow&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Last but not least, a great way to increase ARPU without affecting user retention is by using Firebase Remote Config and AI predictive capabilities to s&lt;strong&gt;how users the right ad at the right time&lt;/strong&gt;. This is great for subscription applications that use AdMob as their ad mediation provider.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Don’t get too comfortable though — I still recommend keeping an eye on the impressions each ad unit is getting to look out for any issues.&amp;nbsp;&lt;/p&gt;



&lt;h1 class=&quot;wp-block-heading&quot; id=&quot;h-the-ad-monetization-framework-for-apps&quot;&gt;&lt;strong&gt;The ad monetization framework for apps&lt;/strong&gt;&lt;/h1&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-22jQIn wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Goal&quot; text=&quot;&lt;p&gt;Increase ARPU by creating an advanced setup with Firebase’s Remote Config as your main testing and deployment tool.&lt;/p&gt;&quot; icon=&quot;star&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;p&gt;Now for implementing your ads — the framework below is my go-to since any &lt;a href=&quot;https://www.revenuecat.com/blog/growth/build-app-growth-team/&quot;&gt;app growth team&lt;/a&gt; can implement it for free using Google Workspace tools, plus it doesn’t require a developer to design and create experiments.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;To guarantee the framework’s resilience, all logic conditions must happen under the Firebase project. Knowing the function and purpose of each tool will help you understand how the stack works together:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Firebase: &lt;/strong&gt;Where ad experiments are executed using Remote Configuration and A/B tests&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Google AdMob: &lt;/strong&gt;Responsible for ingesting your ad inventory into the exchange, managing ad requests to fill your placements and monetize your product&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Google Analytics:&lt;/strong&gt; The tool that lets you measure the impact of your ad experiments via metrics like user retention, ad revenue, purchase revenue, etc.
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;It also helps you to build audiences and create custom dimensions to design remote conditions for your A/B tests&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-level-of-complexity&quot;&gt;&lt;strong&gt;Level of complexity&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Depending on your experience working with ad monetization, I recommend doing one of three things before starting:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Low complexity:&lt;/strong&gt; If you’ve never used AdMob or tried changing eCPM floors to run soft experiments, I recommend doing that first. Play with bids, create ad units, make report templates, and learn how the solution works.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Medium:&lt;/strong&gt; Before doing advanced setups with a JSONs schema, prepare your app to receive a simple string when running an A/B test. For example, use a different ad unit ID string to run your first experiments against your baseline.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;High:&lt;/strong&gt; If you have a decent experience running multiple experiments and an understanding of how the framework operates. I recommend using a JSON approach instead of string, boolean, or number. It will help you scale faster.&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-working-with-conditions&quot;&gt;&lt;strong&gt;Working with conditions&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Conditions are essentially rules you set up in the Firebase console to serve different configuration settings to subsets of your user base. It follows the waterfall effect, so be clear about the way you structure your conditions.&lt;/p&gt;



&lt;p&gt;This is a list of rule types I use the most, which you can use to create conditions on Firebase. Check out the &lt;a href=&quot;https://firebase.google.com/docs/remote-config/parameters#condition_rule_types&quot;&gt;Firebase Remote Config parameters&lt;/a&gt; guide for the complete documentation.&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Type&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Value&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;app&lt;/td&gt;&lt;td&gt;List of available apps in the project&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;app_version&lt;/td&gt;&lt;td&gt;Specify the version(s) of your app to target&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;platform&lt;/td&gt;&lt;td&gt;iOS, Android, Web&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;language&lt;/td&gt;&lt;td&gt;Select one or more languages&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;country&lt;/td&gt;&lt;td&gt;Select one or more regions or countries&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;user_audiencies&lt;/td&gt;&lt;td&gt;Select from a list of Google Analytics audiences&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;user_propperty&lt;/td&gt;&lt;td&gt;Select from a list of Google Analytics user properties&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;date&lt;/td&gt;&lt;td&gt;A specified date and time&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;Make sure each parameter you create in Firebase has a reason to exist. &lt;strong&gt;Before using any conditions, ask yourself if it’s necessary to have them&lt;/strong&gt;. Maybe the ad unit itself (AdMob) has the condition by default. For example, you don’t need to include the platform condition if your ad unit is from an iOS project.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-maximizing-the-number-of-impressions-nbsp&quot;&gt;&lt;strong&gt;Maximizing the number of impressions&amp;nbsp;&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;You can design your setup in two ways to ensure the highest ad impressions in your app. One lives inside your Remote Config setup (custom JSON fallback). The other lives in your mediation platform, like AdMob mediation groups.&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt;&lt;strong&gt;In-app JSON fallback (custom logic)&lt;/strong&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot;&gt;&lt;strong&gt;Mediation groups&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt;Your app reads a JSON config and decides which ad unit to try next. It’s recommended that this is used for specific cases where the team has deep knowledge about the topic and needs control over the waterfall logic.&lt;/td&gt;&lt;td colspan=&quot;2&quot;&gt;The place where you can configure the bidding in the mediation UI.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;br&gt;✅ Very granular control (per segment/geo) without shipping a new build&lt;br&gt;✅ Fast remote tweaks&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;br&gt;❌ Complex to build/test/maintain at scale (edge cases, frequency caps, error handling)&lt;br&gt;❌ Easy to fragment logic across geos/formats&lt;br&gt;❌ Since the mediation layer orchestrates bidding, you’ll typically miss out on in-app bidding’s unified auction&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;br&gt;✅ Easier to operate day-to-day&lt;br&gt;✅ Plays nicely with real-time bidding (more competition, usually better eCPM, less manual tuning)&lt;br&gt;✅ No extra app code for fallback logic&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;br&gt;❌ Slightly less granular than a fully custom setup&lt;br&gt;❌ Changes may take time to propagate (e.g., enabling/pausing can take up to ~1 hour)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-design-system-how-to-create-your-first-template&quot;&gt;&lt;strong&gt;Design system: How to create your first template&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;To create your advanced ad monetization framework using JSON as a data type within your Remote Config setup, you need to understand how the main components of the ‘design system’ work. This includes the possible elements of the code, their benefits, functions, how to apply them, and if they should be included or not.&lt;/p&gt;



&lt;p&gt;Here’s a quickfire breakdown of the design system elements:&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-ad-units-nbsp&quot;&gt;&lt;strong&gt;Ad units:&amp;nbsp;&lt;/strong&gt;&lt;/h4&gt;



&lt;p&gt;These parameters will be focused on helping you to identify, localize, and control each ad unit.&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Unit_id_name:&lt;/strong&gt; Serves as a readable, user-friendly identifier for the specific AdMob unit in your code or configuration.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Description: &lt;/strong&gt;Provides a textual explanation of the ad unit’s purpose or placement within the app.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Ad_unit_id: &lt;/strong&gt;The unique identifier provided by AdMob for each ad unit. It’s used to fetch and display ads from AdMob.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Format:&lt;/strong&gt; Specifies the type of ad being displayed (e.g., banner, interstitial, rewarded).&lt;/li&gt;



&lt;li&gt;Toggle_ad_unit: A boolean value to turn the ad unit on (true) or off (false).&lt;/li&gt;
&lt;/ul&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-frequencies-nbsp&quot;&gt;&lt;strong&gt;Frequencies:&amp;nbsp;&lt;/strong&gt;&lt;/h4&gt;



&lt;p&gt;These parameters will help you define the intensity and volume of the impressions you serve to your users&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Frequency:&lt;/strong&gt; This indicates how often the ad should be shown. For example, a frequency of one might mean the ad shows every time a particular event occurs, while a frequency of two shows every other time.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Is_skippable:&lt;/strong&gt; This boolean parameter determines whether or not the user has the option to skip the ad after a specific duration (you may also have the chance to do it on your mediation platform).&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Always_on count_intervals:&lt;/strong&gt; A boolean value that, when set to true, ensures that the ad unit is always active and shown irrespective of any other conditional logic (be cautious with this one. It can bring problems to the logic).&lt;/li&gt;
&lt;/ul&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-segmentation-nbsp&quot;&gt;&lt;strong&gt;Segmentation:&amp;nbsp;&lt;/strong&gt;&lt;/h4&gt;



&lt;p&gt;You can effectively personalize your app’s ad experience, showing the right kind of ads to the right users at the right time.&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Segment name: &lt;/strong&gt;This serves as your app’s identifier for a specific user group. The segment name could be anything that describes the user group effectively, such as “High_Engagement” or “New_Users.”&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Segment_conditions:&lt;/strong&gt; These criteria define how users are grouped into the segment. Conditions can include behavioral attributes like “time_spent_on_screen_per_day” or transactional attributes like “total_purchase_value.”&lt;/li&gt;
&lt;/ul&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-cross-promotion-nbsp&quot;&gt;&lt;strong&gt;Cross-promotion:&amp;nbsp;&lt;/strong&gt;&lt;/h4&gt;



&lt;p&gt;These parameters give you more control over your cross-promotion strategy, and ensure that you maximize user engagement and revenue streams effectively.&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Cross_promotion_ad_name:&lt;/strong&gt; Identifies the name of the cross-promotion ad campaign.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Description: &lt;/strong&gt;Provides a brief description of the cross-promotion ad.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Format:&lt;/strong&gt; Specifies the format of the cross-promotion ad, like modal, native, etc.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Fallback:&lt;/strong&gt; Acts as a backup plan to display the cross-promotion ad in case the primary ad (like a rewarded video) fails to load.&lt;/li&gt;
&lt;/ul&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-premium-users-nbsp&quot;&gt;&lt;strong&gt;Premium users:&amp;nbsp;&lt;/strong&gt;&lt;/h4&gt;



&lt;p&gt;Control ads’ visibility for users with a premium subscription to your app.&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Block_ads_for_premium:&lt;/strong&gt; This Boolean parameter controls whether ads are displayed to premium users or not. When set to true, ads are not shown to users who have purchased a premium subscription; when set to false, premium users will still see ads.&lt;/li&gt;
&lt;/ul&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-examples-set-up&quot;&gt;&lt;strong&gt;Examples set up:&lt;/strong&gt;&lt;/h4&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;481&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-63-481x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-47143&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-63-481x1024.png 481w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-63-141x300.png 141w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-63-24x50.png 24w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-63-19x40.png 19w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-63-218x464.png 218w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-63-263x560.png 263w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-63-139x296.png 139w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-63-222x472.png 222w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-63-38x80.png 38w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-63-23x48.png 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-63.png 614w&quot; sizes=&quot;auto, (max-width: 481px) 100vw, 481px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;752&quot; height=&quot;954&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-62.png&quot; alt=&quot;&quot; class=&quot;wp-image-47141&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-62.png 752w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-62-236x300.png 236w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-62-39x50.png 39w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-62-32x40.png 32w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-62-366x464.png 366w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-62-696x883.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-62-441x560.png 441w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-62-233x296.png 233w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-62-372x472.png 372w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-62-63x80.png 63w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-62-38x48.png 38w&quot; sizes=&quot;auto, (max-width: 752px) 100vw, 752px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-you-re-ready-to-monetize&quot;&gt;&lt;strong&gt;You’re ready to monetize&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;After that whirlwind walkthrough, you’re ready to go forth and monetize across free users with ads. It can be a lot of work, but once your workflow is setup, you can reap the rewards!&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Remember:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Ads can be additive — if UX stays sacred:&lt;/strong&gt; Treat ads as value-exchange, avoid interrupting core flows/paywalls, and place them at natural stops. This is how you raise ARPU without hurting retention.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Start only when the scale exists:&lt;/strong&gt; Ad monetization makes sense once you can reach ~$100/day profit potential and have meaningful DAU (e.g., ~10k with ~1 impression/day at a ~$10 eCPM).&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;strong&gt;Geo matters:&lt;/strong&gt; Tier one: fewer, higher-value impressions, tier two/three: more impressions are acceptable if they don’t harm retention, and users expect ads.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Why we chose native paywalls]]></title><description><![CDATA[If your paywall feels like a web page, you’ve already lost]]></description><link>https://www.revenuecat.com/blog/engineering/why-we-chose-native-paywalls/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/why-we-chose-native-paywalls/</guid><pubDate>Tue, 21 Oct 2025 07:20:17 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Why-We-Chose-Native-Paywalls-1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;&lt;em&gt;Designed to be quick, dependable, and seamless in your app experience.&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;In building RevenueCat Paywalls, we made a key architectural decision: to &lt;strong&gt;render paywalls natively instead of inside a WebView&lt;/strong&gt;. That didn’t mean hard-coding layouts into the app — paywalls remain fully server-driven and remotely configurable — they simply render using platform UI instead of a browser engine. That choice impacts everything from load performance to accessibility, and from stability to long-term maintainability. Here’s why we made that call, what it delivers for your users, and how it enables your team to ship faster with confidence.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-when-it-comes-to-conversion-every-second-counts&quot;&gt;When it comes to conversion, every second counts&lt;/h2&gt;



&lt;p&gt;Paywalls sit at the tightest point in your revenue funnel. Delays or blank states aren’t just UX issues, they’re conversion leaks:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;No WebView engine to spin up&lt;/strong&gt;: A WebView has to initialize a separate rendering process before it can draw anything. Developers routinely see multi-second first-load stalls and even ‘blank’ states on initial launch. Native UI components are already included with the app binary, so rendering begins immediately, no need to wait for WebView to load.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Less platform fragility&lt;/strong&gt;: Web-based layers are tied to browser engines that update independently of your app, sometimes shifting rendering behaviors in subtle ways. Native screens remove that extra dependency layer, giving you more predictable performance.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Accessibility support, out of the box&lt;/strong&gt;: System features like Dynamic Type, VoiceOver/TalkBack, contrast settings, and UIAccessibility traits are inherited automatically with native components.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;strong&gt;What you get:&lt;/strong&gt; faster first paint and fewer surprises when users reach the point of purchase.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-native-feels-native-and-that-matters&quot;&gt;Native “feels native” — and that matters&lt;/h2&gt;



&lt;p&gt;The closer your paywall matches platform conventions, the less cognitive friction your users feel.&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Typography and Dynamic Type&lt;/strong&gt;: Apple’s Human Interface Guidelines (HIG) recommend supporting Dynamic Type so text respects user settings. Native text controls handle this out of the box. In a WebView, you’d need to rebuild that behavior yourself.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Gestures, haptics, accessibility, motion&lt;/strong&gt;: Interactions and animations behave exactly as users expect because they use the same system primitives as the rest of the app.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Platform-consistent on Android&lt;/strong&gt;: Native paywalls inherit Material styling and motion for free, rather than hand-coding lookalikes in HTML and CSS.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;strong&gt;What you get: &lt;/strong&gt;a paywall that looks and behaves like it belongs — on both iOS and Android — because it does.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-style-default&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;546&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-01-at-22.54.15-1024x546.png&quot; alt=&quot;RevenuCat Paywalls web UI&quot; class=&quot;wp-image-46514&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-01-at-22.54.15-1024x546.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-01-at-22.54.15-300x160.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-01-at-22.54.15-768x410.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-01-at-22.54.15-1536x819.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-01-at-22.54.15-2048x1092.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-01-at-22.54.15-50x27.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-01-at-22.54.15-75x40.png 75w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-01-at-22.54.15-696x371.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-01-at-22.54.15-560x299.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-01-at-22.54.15-555x296.png 555w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-01-at-22.54.15-840x448.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-01-at-22.54.15-80x43.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-01-at-22.54.15-48x26.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-backwards-compatibility-built-in&quot;&gt;Backwards compatibility, built-in&lt;/h2&gt;



&lt;p&gt;RevenueCat Paywalls are built to remain stable even as your app and our SDK evolve. Every paywall you configure is versioned and stored on our servers, so it renders consistently across supported SDK versions.&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Stable defaults&lt;/strong&gt;: If a device is running an older SDK without support for the latest paywall features, RevenueCat automatically serves a default paywall so the purchase flow never breaks&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Version-aware updates&lt;/strong&gt;: As you adopt new SDK versions, you can take advantage of the latest components and layout options, knowing older clients will continue to display a reliable fallback&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Continuous evolution&lt;/strong&gt;: This approach balances stability and progress, ensuring paywalls created today remain usable — while giving teams the option to adopt new designs and capabilities when ready&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;strong&gt;What you get:&lt;/strong&gt; paywalls that are backwards-compatible by default, and forward-compatible when you, and your users, choose to evolve.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-substantiating-the-choice&quot;&gt;Substantiating the choice&lt;/h2&gt;



&lt;p&gt;Here’s the shorter ‘engineering brief’ behind our decision:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Startup time:&lt;/strong&gt; Removing WebView engine initialization improves first paint and reduces the risk of blank states on first open&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Operational risk:&lt;/strong&gt; Avoiding a second rendering engine minimizes unplanned breakages after OS or component updates&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;System integration:&lt;/strong&gt; Native UI automatically inherits Dynamic Type, accessibility, haptics, and gestures, aligning with HIG and Material guidance without extra plumbing&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Iteration speed:&lt;/strong&gt; RevenueCat Paywalls is remotely configurable and experiment-ready — iteration isn’t tied to app releases even though rendering is fully native&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;No JS bridge, no hidden WebView&lt;/strong&gt;: All purchasing logic stays inside the app process, handled through a PurchaseHandler object — there’s no message-passing across WKWebView or Android System WebView boundaries&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-ideal-tool-for-a-revenue-critical-screen&quot;&gt;The ideal tool for a revenue-critical screen&lt;/h2&gt;



&lt;p&gt;There’s no single architecture that’s best for every use case. But for a focused, conversion-critical surface like a paywall, the trade-offs break clearly:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Native maximizes &lt;strong&gt;speed&lt;/strong&gt;, &lt;strong&gt;reliability&lt;/strong&gt;, and &lt;strong&gt;platform fit&lt;/strong&gt;, where they matter most&lt;/li&gt;



&lt;li&gt;Remote configuration and experiments keep your &lt;strong&gt;iteration loop tight&lt;/strong&gt; without introducing an embedded browser and its moving parts&lt;/li&gt;
&lt;/ul&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-1bQwLV wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Find inspiration with real paywall examples on Paywalls.com&quot; text=&quot;&lt;p&gt;Browse real examples at &lt;a href=&amp;quot;https://www.paywalls.com/&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noopener&amp;quot;&gt;Paywalls.com&lt;/a&gt;: filter paywall screens by different UI elements, app category, and trending and top-growth paywalls.&lt;/p&gt;&quot; icon=&quot;sparks&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-for-engineers-who-like-to-verify&quot;&gt;For engineers who like to verify&lt;/h2&gt;



&lt;p&gt;If you’d rather read code than blog posts, you don’t have to take our word for any of this. RevenueCat Paywalls UI libraries are available in GitHub:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/RevenueCat/purchases-ios/tree/main/RevenueCatUI&quot;&gt;iOS (SwiftUI renderer): PaywallView.swift and PaywallData+Default.swift&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://github.com/RevenueCat/purchases-android/tree/main/ui/revenuecatui&quot;&gt;Android (Jetpack Compose renderer): ComponentView and sealed PaywallComponent models&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;That’s why we chose native paywalls, and why our customers can ship faster while giving users a purchase flow that loads instantly, looks right, and works the same tomorrow as it did today.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[How to build an app growth team that actually drives results]]></title><description><![CDATA[Your growth team shouldn't be a reskin of product or marketing — but what should it be? ]]></description><link>https://www.revenuecat.com/blog/growth/build-app-growth-team/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/build-app-growth-team/</guid><pubDate>Fri, 17 Oct 2025 11:08:55 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Building-app-growth-teams-that-drive-results.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Let’s start with a home truth: your growth team isn’t the same as your product team.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;While the best growth strategies are often product-led and customer-centric, there is more to growth than product alone, you need:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Marketing to drive initial traction&lt;/li&gt;



&lt;li&gt;Brand to create a relationship&lt;/li&gt;



&lt;li&gt;Customer support to maintain that relationship&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Heck, you even need legal to make sure you’re conscious of what is and isn’t allowed.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Growth isn’t product.&lt;/strong&gt;&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-Z1JmRS wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;And no, it’s not marketing, either.&quot; text=&quot;&lt;p&gt;&lt;span style=&amp;quot;font-weight: 400;&amp;quot;&gt;While generating traction and acquiring users (aka, marketing) is important, we’ve all learned — often the hard way — that the whole system collapses if you’re not retaining users, keeping them happy, and turning them into advocates. This means growth isn’t product, and it isn’t marketing. So where &lt;/span&gt;&lt;i&gt;&lt;span style=&amp;quot;font-weight: 400;&amp;quot;&gt;does &lt;/span&gt;&lt;/i&gt;&lt;span style=&amp;quot;font-weight: 400;&amp;quot;&gt;it fall in an org chart?&lt;/span&gt;&lt;/p&gt;&quot; icon=&quot;circle-info&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-defining-what-makes-an-app-growth-team&quot;&gt;Defining what makes an app growth team&lt;/h2&gt;



&lt;p&gt;Once we acknowledge these two blunt truths (I’m Dutch, so I don’t beat around the bush), it becomes easier to understand what growth actually is. It’s not a department within your organization.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;App growth is a disciplined, cross-functional approach, focused on what truly scales your business.&lt;/strong&gt; So a growth team is simply a group of people dedicated to driving that scale (again, &lt;em&gt;not &lt;/em&gt;a department).&lt;/p&gt;



&lt;p&gt;If we look at Phil Carter’s &lt;a href=&quot;https://www.revenuecat.com/blog/growth/the-subscription-value-loop-a-framework-for-subscription-app-growth/&quot;&gt;Subscription Value Loop framework&lt;/a&gt;, we can see app subscription growth is the result of three key stages:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Value capture&lt;/strong&gt;: Converting free users to paid, so you can reinvest in the organization (monetization)&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Value creation&lt;/strong&gt;: Building a world-class product that delivers real value (activation/retention)&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Value delivery&lt;/strong&gt;: Distributing that value cost-effectively across channels (acquisition/referral)&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/sub-club-podcast-phil-carter-2025/&quot;&gt;Getting this loop to work&lt;/a&gt; requires every part of your organization to work together.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;576&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2024/04/subscription-value-loop-1024x576.png&quot; alt=&quot;Subscription Value Loop&quot; class=&quot;wp-image-26146&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2024/04/subscription-value-loop-1024x576.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2024/04/subscription-value-loop-300x169.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2024/04/subscription-value-loop-768x432.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2024/04/subscription-value-loop-71x40.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2024/04/subscription-value-loop-696x392.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2024/04/subscription-value-loop-560x315.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2024/04/subscription-value-loop-526x296.png 526w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2024/04/subscription-value-loop-840x472.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2024/04/subscription-value-loop-80x45.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2024/04/subscription-value-loop-48x27.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2024/04/subscription-value-loop.png 1456w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;a href=&quot;https://philgcarter.substack.com/p/the-subscription-value-loop&quot;&gt;&lt;em&gt;Source: Phil’s newsletter on Substack&lt;/em&gt;&lt;/a&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;This is where growth teams come in. When done right, they’re incredibly powerful. Depending on your stage, goals, and bottlenecks, you’ll need different skills and people in your cross-functional crew.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Think of it like the Avengers: a seemingly random group of superheroes thrown together save the world. On paper, they shouldn’t work — one’s a billionaire in a weaponized suit, and another’s basically an intergalactic Viking god. Yet, it works. Each brings a unique (and sometimes weird) perspective that’s crucial to the mission.The same goes for your growth team. Each member will come from a different background and bring their own strengths, but together, they’ll drive &lt;em&gt;real&lt;/em&gt; impact.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;how-a-growth-team-works-goal-and-process&quot;&gt;How a growth team works: goal and process&lt;/h2&gt;



&lt;p&gt;It all starts with the team’s goal, just like any other team. What are you focusing on? Where’s the biggest growth opportunity? Personally, I figure this out by running a full growth audit, which helps pinpoint the most impactful areas to work on.&lt;/p&gt;



&lt;p&gt;What that normally involves:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Reviewing all customer insights and data to deeply understand the target audience&lt;/li&gt;



&lt;li&gt;Analyzing performance data across platforms, from acquisition all the way through to retention&lt;/li&gt;



&lt;li&gt;Conducting a light review of key channels — their setup, performance, and gaps&lt;/li&gt;



&lt;li&gt;Interviewing key team members to assess the current growth strategy and approach&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;In short, I’m examining every part of the growth model to uncover: &lt;em&gt;Where are we underperforming, and why?&lt;/em&gt; Often, metrics are connected, so it’s about identifying the root cause.&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-Z1a4gmo wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Example&quot; text=&quot;&lt;p&gt;&lt;span style=&amp;quot;font-weight: 400;&amp;quot;&gt;In a recent audit for a subscription app, I noticed &lt;/span&gt;&lt;a href=&amp;quot;https://www.revenuecat.com/glossary/#arpu-average-revenue-per-user&amp;quot;&gt;&lt;span style=&amp;quot;font-weight: 400;&amp;quot;&gt;ARPU&lt;/span&gt;&lt;/a&gt;&lt;span style=&amp;quot;font-weight: 400;&amp;quot;&gt; was lower than expected. At first glance, that seemed like a monetization issue. But digging deeper, I found the real cause: a very high percentage of users were on monthly plans, which pulled the average down. After this, I explored other retention and monetization metrics, ran calculations to estimate the potential impact of optimizing that one lever, and started building a case for where to focus.&lt;/span&gt;&lt;/p&gt;&quot; icon=&quot;sparks&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;p&gt;From there, the next step is to clearly define the growth team’s goal:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;What is the exact measure of success?&lt;/li&gt;



&lt;li&gt;How are we measuring it?&lt;/li&gt;



&lt;li&gt;What is the current baseline?&lt;/li&gt;



&lt;li&gt;What is the timeline or deadline for improvement?&lt;/li&gt;



&lt;li&gt;What are the key themes — the areas we’ll explore or test to move the needle on this metric?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;As mentioned earlier, you can only start building your growth team &lt;em&gt;after&lt;/em&gt; you’ve defined this focus. Once that’s locked in, the team can rally around the goal and begin working through a structured growth process:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Analyze data to identify opportunities&lt;/li&gt;



&lt;li&gt;Ideate potential experiments&lt;/li&gt;



&lt;li&gt;Prioritize experiments using a clear framework&lt;/li&gt;



&lt;li&gt;Run experiments&lt;/li&gt;



&lt;li&gt;Analyze results&lt;/li&gt;
&lt;/ul&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;972&quot; height=&quot;625&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-58.png&quot; alt=&quot;&quot; class=&quot;wp-image-46925&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-58.png 972w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-58-300x193.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-58-768x494.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-58-50x32.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-58-62x40.png 62w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-58-696x448.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-58-560x360.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-58-460x296.png 460w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-58-734x472.png 734w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-58-80x51.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-58-48x31.png 48w&quot; sizes=&quot;auto, (max-width: 972px) 100vw, 972px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;The Growth Loop&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;This process is continuous and should be &lt;strong&gt;supported by a solid meeting cadence&lt;/strong&gt;. The growth meeting is where the team comes together to review progress, discuss experiment outcomes, and align on the next sprint’s focus.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;A strong growth meeting cadence typically looks like:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Weekly or bi-weekly growth meetings&lt;/strong&gt; to drive momentum&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Short standups&lt;/strong&gt; for quick updates in between&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Monthly alignment meetings&lt;/strong&gt; with other departments (e.g. product, marketing, data)&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Quarterly strategic reviews&lt;/strong&gt; to step back and reassess priorities&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;can-a-growth-team-focus-on-multiple-metrics&quot;&gt;Can a growth team focus on multiple metrics?&lt;/h3&gt;



&lt;p&gt;In an ideal world, no. They should be hyper-focused on &lt;strong&gt;one key metric, to maximize impact&lt;/strong&gt;. But in reality, especially for early-stage or smaller companies, that’s often not practical. There may not be enough volume or velocity to run enough meaningful experiments on just one area.&lt;/p&gt;



&lt;p&gt;In those cases, the team can focus on two (maximum three) metrics, but with clear ownership. Assign a dedicated owner to each metric to ensure accountability and avoid spreading the team too thin. This helps maintain clarity, speed, and impact.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;is-your-subscription-app-ready-for-a-growth-team&quot;&gt;Is your subscription app ready for a growth team?&lt;/h2&gt;



&lt;p&gt;Put like this, growth teams sound pretty incredible! But another harsh truth (&lt;em&gt;Dutch&lt;/em&gt;, I warned you) is that &lt;strong&gt;not every company needs a growth team &lt;/strong&gt;— at least, not in the traditional sense.&amp;nbsp;&lt;br&gt;Before picking out your superhero names, you need &lt;strong&gt;product-market fit &lt;/strong&gt;(PMF): signals that your app resonates with your audience. This might look like people being willing to pay for your app, using it consistently, or referring others. Your PMF doesn’t need to be perfect, but you need &lt;em&gt;some &lt;/em&gt;traction signals.&lt;/p&gt;



&lt;p&gt;Trying to scale growth without PMF will lead you to the classic leaky bucket analogy. (It may be overused, but it’s just &lt;em&gt;so&lt;/em&gt; accurate.) The growth person won’t be able to grow your app fast enough, and your app growth will be stunted by issues that require time to understand and resolve. In other words, a leaky bucket.&lt;/p&gt;



&lt;p&gt;If you’re pre-PMF and want to grow, you could consider a first growth hire with strong product or go-to-market background, but the approach will still be different to ‘typical’ growth (i.e. longer sprints, more research, focus on getting PMF).&lt;/p&gt;



&lt;p&gt;At the early stages in a small app startup, &lt;strong&gt;growth is everyone’s job&lt;/strong&gt;. Often, it’s the founder leading the charge, or if they lack the experience, a fractional growth lead steps in to guide the strategy and execution.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-3-common-growth-team-structures&quot;&gt;3 Common growth team structures&lt;/h2&gt;



&lt;p&gt;As you grow your team, you’ll start forming more ad-hoc growth teams—&amp;nbsp; often in a cross-functional setup — and eventually bring on a full-time growth lead to run them. Over time, this evolves into multiple dedicated growth teams, each focused on a specific KPI. These teams might be structured by area (e.g. acquisition), target market, or geography, but &lt;strong&gt;they all align under a shared, organization-wide growth strategy&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;There are three common growth team structures (&lt;em&gt;note that the departments and roles in these visuals are just examples&lt;/em&gt;):&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-independent-growth-team-structure&quot;&gt;1. Independent growth team structure&lt;/h3&gt;



&lt;p&gt;A standalone team focused on a specific growth lever (like acquisition or retention). As you scale, you can spin up multiple independent teams, each with a different focus.&lt;/p&gt;



&lt;p&gt;The independent model is more common in larger organizations and is rarely the starting point — mainly because there’s not enough ongoing work to justify a fully-dedicated team, and it often requires a significant organizational shift.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;392&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-60.png&quot; alt=&quot;&quot; class=&quot;wp-image-46929&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-60.png 700w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-60-300x168.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-60-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-60-71x40.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-60-696x390.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-60-560x314.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-60-529x296.png 529w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-60-80x45.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-60-48x27.png 48w&quot; sizes=&quot;auto, (max-width: 700px) 100vw, 700px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-cross-functional-growth-team-structure&quot;&gt;2. Cross-functional growth team structure&lt;/h3&gt;



&lt;p&gt;Team members come from different departments but collaborate on growth initiatives while still contributing to their original teams.&lt;/p&gt;



&lt;p&gt;Each model has its pros and cons, but for the majority of companies starting out and keen to set up a growth team, I generally suggest starting with the cross-functional growth team structure as it gives speed without needing new headcount.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;750&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Mixed-structure.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-46938&quot; style=&quot;width:500px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Mixed-structure.jpg 700w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Mixed-structure-280x300.jpg 280w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Mixed-structure-47x50.jpg 47w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Mixed-structure-37x40.jpg 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Mixed-structure-433x464.jpg 433w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Mixed-structure-696x746.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Mixed-structure-523x560.jpg 523w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Mixed-structure-276x296.jpg 276w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Mixed-structure-441x472.jpg 441w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Mixed-structure-75x80.jpg 75w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Mixed-structure-45x48.jpg 45w&quot; sizes=&quot;auto, (max-width: 700px) 100vw, 700px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-mixed-model-growth-team-structure&quot;&gt;3. Mixed model growth team structure&lt;/h3&gt;



&lt;p&gt;The team is essentially cross-functional, but you have a separate ‘growth’ department that also sits in those growth teams.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;If you have several existing growth hires, chances are you’re operating in this structure already.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;503&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-59.png&quot; alt=&quot;&quot; class=&quot;wp-image-46927&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-59.png 700w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-59-300x216.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-59-50x36.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-59-56x40.png 56w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-59-646x464.png 646w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-59-696x500.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-59-560x402.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-59-412x296.png 412w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-59-657x472.png 657w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-59-80x57.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-59-48x34.png 48w&quot; sizes=&quot;auto, (max-width: 700px) 100vw, 700px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;building-your-growth-team-who-should-be-in-it&quot;&gt;Building your growth team: who should be in it?&lt;/h2&gt;



&lt;p&gt;Who’s in your growth team really depends on what you’re focusing on. It’s easy to get caught up in who should be involved, but ultimately &lt;strong&gt;your growth team is fluid.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Think of the Avengers — technically, they ended up with 17 members, even though they started with just six. Now, 17 is &lt;em&gt;definitely&lt;/em&gt; too many for a growth team (I’d aim for four–eight people depending on your company size and growth focus), but the point stands: &lt;strong&gt;your team will evolve as your focus shifts&lt;/strong&gt;. You’ll get a Spider-Man, Scarlet Witch, or Ant-Man of your own.&lt;/p&gt;



&lt;p&gt;You might kick things off focusing on retention, only to later pivot to activation or monetization, which requires a different mix of skills and people. It also depends on who’s already on your team and how you like to work.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;To help, I’ve outlined some example team setups based on different focus areas. But first, let’s start with who’s leading the team.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;who-leads-your-growth-team&quot;&gt;Who leads your growth team?&lt;/h3&gt;



&lt;p&gt;Your first growth hire or growth lead is important. They set the tone for the team’s approach, mindset, and overall culture. They’ll lead the key meetings, drive the strategy to hit the growth goal, and ensure the team sticks to the process.&lt;/p&gt;



&lt;p&gt;On a week-to-week basis, their responsibilities typically include:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Ensuring every experiment starts with a clear, strong hypothesis&lt;/li&gt;



&lt;li&gt;Prioritizing experiments based on impact and effort&lt;/li&gt;



&lt;li&gt;Extracting learnings from each experiment and sharing them&lt;/li&gt;



&lt;li&gt;Maintaining and updating the experiment backlog&lt;/li&gt;



&lt;li&gt;Bringing the wider organization into the growth process, both for ideas and support&lt;/li&gt;
&lt;/ul&gt;



&lt;h4 class=&quot;wp-block-heading&quot;&gt;What should you look for in a growth lead?&lt;/h4&gt;



&lt;p&gt;I recommend finding someone who is:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Structured&lt;/strong&gt;: Especially early on, when they’ll be building out the foundations of your growth process&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Flexible&lt;/strong&gt;: Able to adapt quickly when priorities or circumstances shift&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Strategic, yet execution-focused&lt;/strong&gt;: They need to define the big picture &lt;em&gt;and&lt;/em&gt; keep the team moving forward day to day&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;A strong leader&lt;/strong&gt;: Even if they’re not the team’s direct line manager, they should be capable of leading, motivating, and aligning the group&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Ideally, they’ll also have experience with the specific growth lever you’re focusing on. For example, if your growth goal is acquisition, it might make sense for a marketing lead to take charge. If it’s retention, someone from product may be better suited.&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-Zz15Cz wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Learn more&quot; text=&quot;&lt;p&gt;&lt;span style=&amp;quot;font-weight: 400;&amp;quot;&gt;Read this blog for a breakdown on when to make your &lt;/span&gt;&lt;a href=&amp;quot;https://www.revenuecat.com/blog/growth/first-growth-hire-subscription-app/&amp;quot;&gt;&lt;span style=&amp;quot;font-weight: 400;&amp;quot;&gt;first growth hire&lt;/span&gt;&lt;/a&gt;&lt;span style=&amp;quot;font-weight: 400;&amp;quot;&gt;, and who to look for &lt;/span&gt;&lt;/p&gt;&quot; icon=&quot;bulb&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;p&gt;Now, onto those different potential setups.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;1-monetization-growth-team&quot;&gt;1. Monetization growth team&lt;/h3&gt;



&lt;p&gt;This team’s work usually centers on &lt;a href=&quot;https://www.revenuecat.com/feature/experiments/&quot;&gt;&lt;strong&gt;pricing experiments&lt;/strong&gt;&lt;/a&gt; and &lt;strong&gt;optimizing the early customer journey&lt;/strong&gt; — such as packages, &lt;a href=&quot;https://www.revenuecat.com/blog/growth/paywalls-study-guide/&quot;&gt;paywall&lt;/a&gt; experience, and trial flow.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Key metrics may include:&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Optimizing &lt;a href=&quot;https://www.revenuecat.com/feature/paywalls/&quot;&gt;paywall&lt;/a&gt; conversion rates&lt;/li&gt;



&lt;li&gt;Improving trial-to-paid conversions&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/mojo-60-percent-arpu-growth-five-months/&quot;&gt;Increasing ARPU&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;strong&gt;Typical team members include:&lt;/strong&gt;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;[Growth] product manager&lt;/li&gt;



&lt;li&gt;UX/UI designer&lt;/li&gt;



&lt;li&gt;Software engineer (often backend, given pricing changes)&lt;/li&gt;



&lt;li&gt;Analytics support (data analyst or data scientist), since &lt;a href=&quot;https://www.revenuecat.com/blog/engineering/mobile-app-a-b-price-testing-guide/&quot;&gt;pricing experiments&lt;/a&gt; can be tricky to measure&lt;/li&gt;



&lt;li&gt;CRO specialist (depending on the product manager’s skillset and company size)&lt;/li&gt;



&lt;li&gt;(Potentially) finance or RevOps for internal approval on pricing changes&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Because monetization is closely linked to activation (especially the trial journey), you may also involve a &lt;a href=&quot;https://www.revenuecat.com/blog/growth/beginners-guide-to-mobile-crm-for-subscription-apps/&quot;&gt;CRM&lt;/a&gt; or &lt;a href=&quot;https://www.revenuecat.com/blog/growth/lifecycle-marketing-campaigns-optimize-revenue/&quot;&gt;lifecycle marketer&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;&lt;em&gt;Note that I haven’t split out Android vs. iOS developers because that depends entirely on your testing approach. Some teams test on Android first (smaller user base, lower risk); others go with iOS (main monetization channel or larger audience). Some test on both. There’s no right or wrong here; it just influences who you bring into the team.&lt;/em&gt;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;2-activation-growth-team&quot;&gt;2. Activation growth team&lt;/h3&gt;



&lt;p&gt;Here the focus is on the early user journey:&lt;strong&gt; activating new users&lt;/strong&gt; and &lt;strong&gt;retaining them&lt;/strong&gt; through their first month.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Key metrics may include:&lt;/strong&gt;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Day one &lt;a href=&quot;https://www.revenuecat.com/glossary/#activation&quot;&gt;activation&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;Onboarding completion&lt;/li&gt;



&lt;li&gt;Percentage of users completing key actions&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;strong&gt;Typical team members include &lt;/strong&gt;the same base setup as monetization, plus:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Front-end engineering support&lt;/li&gt;



&lt;li&gt;A copywriter, especially if you’re focused on onboarding emails, push notifications, or in-app messaging&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Brand team involvement is common when bigger flow or experience changes are needed. A marketer may also be involved in optimizing pre-app touchpoints — what users see before they even open the app matters for activation.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;3-retention-growth-team&quot;&gt;3. Retention growth team&lt;/h3&gt;



&lt;p&gt;You’re successfully activating users but need to &lt;strong&gt;keep them long-term&lt;/strong&gt;. Enter a vital but often overlooked hero: customer care.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;They’re frequently &lt;strong&gt;the voice of your customers&lt;/strong&gt;, providing &lt;strong&gt;insight beyond app store reviews or metrics&lt;/strong&gt;. Direct user research — via customer support or a dedicated user researcher or product manager — is critical.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Typical team members include:&lt;/strong&gt;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;[Growth] product manager&lt;/li&gt;



&lt;li&gt;Lifecycle/CRM marketer&lt;/li&gt;



&lt;li&gt;Designer&lt;/li&gt;



&lt;li&gt;Data analyst&lt;/li&gt;



&lt;li&gt;Customer care or user researcher&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;4-referral-growth-team&quot;&gt;4. Referral growth team&lt;/h3&gt;



&lt;p&gt;If word-of-mouth drives your growth, putting resources into a &lt;a href=&quot;https://www.revenuecat.com/blog/growth/how-to-build-a-referral-program-for-mobile-apps/&quot;&gt;referral program&lt;/a&gt;-focused growth team can be most important.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Key metrics may include:&lt;/strong&gt;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Percentage of users who refer&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Referral-driven signups&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;This team often closely resembles the &lt;a href=&quot;https://www.revenuecat.com/blog/growth/subscription-app-churn-reasons-how-to-fix/&quot;&gt;retention&lt;/a&gt; team setup, but other &lt;strong&gt;typical team members include:&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Growth or product manager — specifically to oversee referrals&lt;/li&gt;



&lt;li&gt;Design support&lt;/li&gt;



&lt;li&gt;Engineering&lt;/li&gt;



&lt;li&gt;CRM manager&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Depending on size, you might have a dedicated referral specialist, but most subscription apps have a combination of the above team members supporting this effort as a collective.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;5-acquisition-growth-team&quot;&gt;5. Acquisition growth team&lt;/h3&gt;



&lt;p&gt;Finally, if your primary aim is acquiring new users or showing &lt;a href=&quot;https://www.revenuecat.com/blog/growth/what-is-lifetime-value-ltv-apps/&quot;&gt;lifetime value&lt;/a&gt;, you’re looking at an acquisition growth team. Usually, growth team structures support short-term channels rather than longer-term awareness channels (like influencer marketing), which take longer to show results and don’t always fit the classic growth process.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Key metrics may include:&lt;/strong&gt;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Cost of acquisition&lt;/li&gt;



&lt;li&gt;Paid signups&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.revenuecat.com/glossary/#ltv-cac-ratio&quot;&gt;LTV: CAC ratio&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Lazer-focused on getting new users onto the app, this setup really depends on the channels you’re targeting most. &lt;strong&gt;Typical team members include:&lt;/strong&gt;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Growth marketing lead or paid ads specialist&lt;/li&gt;



&lt;li&gt;Creative strategist for visual ad campaigns&lt;/li&gt;



&lt;li&gt;Product manager to optimize the post-click user journey&lt;/li&gt;



&lt;li&gt;CRO specialist, designer, and developer (especially if there’s a web-to-app flow)&lt;/li&gt;



&lt;li&gt;Copywriter, graphic designer/video editor, data analyst (honorable mentions)&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;If ads perform poorly or generate negative feedback/refunds, bring customer care into the loop. Brand teams often stay involved here for alignment.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;overview-of-growth-team-roles&quot;&gt;Overview of growth team roles&lt;/h3&gt;



&lt;p&gt;Below is a summary matrix of potential involvement, where &lt;strong&gt;green&lt;/strong&gt; means very likely involved, &lt;strong&gt;yellow&lt;/strong&gt; means optional, and &lt;strong&gt;white&lt;/strong&gt; means unlikely:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;754&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Growth-team-roles-summary-1024x754.png&quot; alt=&quot;&quot; class=&quot;wp-image-46935&quot; style=&quot;width:800px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Growth-team-roles-summary-1024x754.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Growth-team-roles-summary-300x221.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Growth-team-roles-summary-768x565.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Growth-team-roles-summary-1536x1130.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Growth-team-roles-summary-50x37.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Growth-team-roles-summary-54x40.png 54w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Growth-team-roles-summary-631x464.png 631w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Growth-team-roles-summary-696x512.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Growth-team-roles-summary-560x412.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Growth-team-roles-summary-402x296.png 402w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Growth-team-roles-summary-641x472.png 641w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Growth-team-roles-summary-80x59.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Growth-team-roles-summary-48x35.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Growth-team-roles-summary.png 1560w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;As you can see, a lot depends on your specific situation. Use the above as a framework to get you thinking about your own organization — but don’t stress if your setup looks different, or if roles are merged or named differently. That’s 100% okay.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;4-rules-for-effective-growth-and-product-team-collaboration&quot;&gt;4 Rules for effective growth and product team collaboration&lt;/h2&gt;



&lt;p&gt;You’re probably sick of me saying that your growth team isn’t your product team, but when your product is an app, the lines can blur — and tensions can run high as a result.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;While the best growth is product-led, the two teams can clash. Product usually focuses on long-term vision, stability, and building a solid foundation, while growth moves fast, experiments constantly, and pushes for quick wins. It’s a balancing act.&lt;/p&gt;



&lt;p&gt;For your growth team to succeed, some ground rules are essential:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Align on roadmap and goals&lt;/strong&gt; so both teams have a shared vision, and can see how each one’s work fuels the other’s&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Agree on how you assign resources&lt;/strong&gt; so growth planning isn’t overshadowed by product priorities (or vice versa)&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Ensure mutual respect for each other’s processes&lt;/strong&gt; — they will differ, as will priorities, but both are equally important&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Focus on the end user with one North Star metric&lt;/strong&gt; that unites both teams&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Product should be a core part of the growth team in any structure, which helps minimize alignment issues. But if there are teething pains, just remember that at the end of the day, both teams share the same mission: serving the user and hitting shared goals.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;hiring-the-right-people-dont-underestimate-team-fit&quot;&gt;Hiring the right people: don’t underestimate team fit&lt;/h2&gt;



&lt;p&gt;You can have the best structure in place and still fail if your team doesn’t have the right chemistry. Growth teams thrive on &lt;em&gt;healthy tension&lt;/em&gt;: dreamers and pragmatists, risk-takers and risk-reducers. One of my favorite ways to think about this is the &lt;strong&gt;Planner vs. Explorer&lt;/strong&gt; &lt;strong&gt;model&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;The strongest growth teams aren’t perfectly harmonious with zero conflict — they argue (politely and constructively), and that’s a good thing. Those debates mean they’re thinking deeply, considering different sides of challenges. Under pressure to hit targets we’re often in full go-go-go mode. That’s when you need someone to say, “Wait a second. Let’s go back to our North Star. What about [new perspective]?”&lt;/p&gt;



&lt;p&gt;I first learned this while building the growth team at Heights. I came in excited to just go, go, go…only to get pushback from the Head of Product and Product Manager. They asked tough questions, and I was like, “No time, gotta save the world/grow our brand!” But that pushback kept coming — it was often the product team raising critical questions or being more risk-averse, and ultimately they became my balance.&lt;/p&gt;



&lt;p&gt;I understood this better when our founder introduced us to the concept of &lt;a href=&quot;https://www.linkedin.com/posts/daphnetideman_are-you-an-explorer-or-a-planner-you-need-activity-7333130059521679361-HGZw/&quot;&gt;&lt;strong&gt;Planners vs. Explorers&lt;/strong&gt;&lt;/a&gt;:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Planners&lt;/strong&gt; are risk-averse, like to think things through, and thrive under clear direction and KPIs. They focus on details, prefer perfecting what they work on, and are often deep specialists.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Explorers&lt;/strong&gt; are output- and impact-driven, always following the data. They’re hackers over crafters, broader skillsets, more T-shaped.&lt;/li&gt;
&lt;/ul&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;550&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-61-1024x550.png&quot; alt=&quot;&quot; class=&quot;wp-image-46931&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-61-1024x550.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-61-300x161.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-61-768x412.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-61-1536x825.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-61-50x27.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-61-74x40.png 74w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-61-696x374.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-61-560x301.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-61-551x296.png 551w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-61-840x451.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-61-80x43.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-61-48x26.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-61.png 1564w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Of course, people rarely fall 100% into either category, and it varies by situation. (In growth work, I’m about 80–90% Explorer. Planning my wedding? Definitely 95% Planner. Classic bridezilla.)&lt;/p&gt;



&lt;p&gt;We tend to think of growth folks as Explorers, but really, you need both. A team full of Explorers is chaos: a million experiments and ideas, zero structure or direction, constantly-shifting priorities, and trying to do too much at once. On the flip side, a team of just Planners moves too slowly, obsessing over perfecting experiments or optimizing what already exists.There are countless personality frameworks out there, most of which will help you build your growth team. This one works for me, but more importantly it highlights a key truth: you need &lt;em&gt;balance&lt;/em&gt; in your team to get the most out of it.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-avengers-assemble&quot;&gt;Avengers, assemble!&lt;/h2&gt;



&lt;p&gt;Okay, that was a lot. Are you feeling ready to find your superheroes?&lt;/p&gt;



&lt;p&gt;You have product-market fit. You’ve got the data and insights. You’re at the stage where building a growth team makes sense. But &lt;em&gt;how&lt;/em&gt; you bring that team together matters too — sometimes more than who is actually in the team.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;If you’re feeling overwhelmed, just take it step by step:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Clarify the focus&lt;/strong&gt;: What is the growth team solving for? What’s the biggest opportunity right now?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Decide who leads&lt;/strong&gt;: Based on your focus and the skills you need, who makes the most sense to drive this?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Assemble the team&lt;/strong&gt;: Who should be in the room to actually move the needle? Be intentional here.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Check the team dynamic&lt;/strong&gt;: Do you have a good balance of skills, mindsets, and personalities?&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Once you’ve done that, it’s time to start. Follow the growth process, learn from what works (and what doesn’t), and keep iterating.It’s not about getting it perfect from day one; it’s about building a team that can &lt;em&gt;learn fast, move smart,&lt;/em&gt; and grow from there.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[The 2025 Shippies: Your winners]]></title><description><![CDATA[Meet the 2025 winners: six standout teams (and one very determined solo dev) whose apps are now lighting up Times Square]]></description><link>https://www.revenuecat.com/blog/company/shippies-2025-winners/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/company/shippies-2025-winners/</guid><pubDate>Thu, 16 Oct 2025 18:10:11 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-6.jpeg" length="0" type="image/*"/><content:encoded>&lt;p&gt;Every year at &lt;strong&gt;App Growth Annual&lt;/strong&gt;, we take a moment to celebrate the best subscription apps have to offer. The &lt;strong&gt;Shippies&lt;/strong&gt; honor creativity and effective onboarding, monetization, and retention.&lt;/p&gt;



&lt;p&gt;This year’s winners took home the &lt;strong&gt;&lt;s&gt;Golden&lt;/s&gt; Chocolate Shippy&lt;/strong&gt;, eternal glory, and their very own &lt;strong&gt;billboard on Times Square&lt;/strong&gt; (because what says “you nailed onboarding” better than a giant panda, bean, or fitness coach lighting up Manhattan?).&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;576&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-7-1024x576.jpeg&quot; alt=&quot;&quot; class=&quot;wp-image-46916&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-7-1024x576.jpeg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-7-300x169.jpeg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-7-768x432.jpeg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-7-1536x864.jpeg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-7-50x28.jpeg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-7-71x40.jpeg 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-7-696x392.jpeg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-7-560x315.jpeg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-7-526x296.jpeg 526w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-7-840x472.jpeg 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-7-80x45.jpeg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-7-48x27.jpeg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-7.jpeg 1920w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-anchor-s-away-focus-friend-by-hank-green&quot;&gt;Anchor’s Away: &lt;strong&gt;Focus Friend&lt;/strong&gt; by Hank Green&lt;/h2&gt;



&lt;p&gt;The &lt;strong&gt;Anchor’s Away&lt;/strong&gt; category celebrates new apps that launch with polish, purpose, and promise.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Focus Friend by Hank Green &lt;/strong&gt;(yes, &lt;em&gt;that&lt;/em&gt; Hank Green) nailed it. The app turns focus sessions into a cozy, low-stakes ritual with a smiling bean who cheers you on. It’s the antidote to ‘I should really be working’ guilt: A little emotional design magic, paired with brilliant simplicity.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Why it won:&lt;/strong&gt;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Emotional design — the bean gives a gentle nudge instead of a guilt trip&lt;/li&gt;



&lt;li&gt;Low friction, with no complex setup, you just tap &lt;em&gt;focus&lt;/em&gt;&lt;/li&gt;



&lt;li&gt;An aesthetic polish that is delightfully simple and calm&lt;/li&gt;



&lt;li&gt;Early traction: 500k+ Play Store downloads and a 4.2★ rating within weeks&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Focus Friend unseated ChatGPT from the App Store charts for a bit, proving once again that cute beans beat AI (at least sometimes).&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-1024x1024.jpeg&quot; alt=&quot;&quot; class=&quot;wp-image-46898&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-1024x1024.jpeg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-300x300.jpeg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-150x150.jpeg 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-768x768.jpeg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-50x50.jpeg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-40x40.jpeg 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-464x464.jpeg 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-696x696.jpeg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-560x560.jpeg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-296x296.jpeg 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-472x472.jpeg 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-80x80.jpeg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-48x48.jpeg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled.jpeg 1080w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-lone-skipper-resubs&quot;&gt;Lone Skipper: &lt;strong&gt;ReSubs&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The &lt;strong&gt;Lone Skipper&lt;/strong&gt; award is for the indie devs out there. The ones steering the ship solo; building, shipping, and maintaining apps with exceptional craft.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;ReSubs&lt;/strong&gt; helps users track all their subscriptions (and maybe finally cancel that one free trial from 2021). It’s a masterclass in clean design, regular updates, and cohesive UX all built and maintained by one person: Chris Krueger.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Why it won:&lt;/strong&gt;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Cohesive and elegant design&lt;/li&gt;



&lt;li&gt;Constant flow of thoughtful updates&lt;/li&gt;



&lt;li&gt;Built &lt;em&gt;and&lt;/em&gt; maintained by a solo developer&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;It’s proof that with focus, craftsmanship, and coffee, one person can absolutely run a subscription empire.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-1-1024x1024.jpeg&quot; alt=&quot;&quot; class=&quot;wp-image-46900&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-1-1024x1024.jpeg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-1-300x300.jpeg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-1-150x150.jpeg 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-1-768x768.jpeg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-1-50x50.jpeg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-1-40x40.jpeg 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-1-464x464.jpeg 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-1-696x696.jpeg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-1-560x560.jpeg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-1-296x296.jpeg 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-1-472x472.jpeg 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-1-80x80.jpeg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-1-48x48.jpeg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-1.jpeg 1080w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-smooth-sailor-recime&quot;&gt;Smooth Sailor: &lt;strong&gt;ReciMe&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The &lt;strong&gt;Smooth Sailor&lt;/strong&gt; award goes to the app with the best onboarding: where users go from download to &lt;em&gt;aha!&lt;/em&gt; moment in seconds.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;ReciMe&lt;/strong&gt; is the world’s most popular recipe organizer, and it shows. From the moment you open the app, it understands what you’re trying to do — save a recipe, not learn another new tool. After a few qualifying questions, you’re prompted to search for and import a recipe, right there during onboarding. It’s a gutsy way to prove your product does exactly what it claims to do, within the first 60 seconds of downloading.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;543&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-16-at-13.59.49-1024x543.png&quot; alt=&quot;&quot; class=&quot;wp-image-46912&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-16-at-13.59.49-1024x543.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-16-at-13.59.49-300x159.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-16-at-13.59.49-768x407.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-16-at-13.59.49-1536x815.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-16-at-13.59.49-2048x1087.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-16-at-13.59.49-50x27.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-16-at-13.59.49-75x40.png 75w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-16-at-13.59.49-696x369.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-16-at-13.59.49-560x297.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-16-at-13.59.49-558x296.png 558w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-16-at-13.59.49-840x446.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-16-at-13.59.49-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-16-at-13.59.49-48x25.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;strong&gt;Why it won:&lt;/strong&gt;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Lightning-fast path to value — the USP is obvious from minute one&lt;/li&gt;



&lt;li&gt;Smart onboarding that adapts to the user&lt;/li&gt;



&lt;li&gt;Proven impact as the go-to recipe app for millions&lt;/li&gt;
&lt;/ul&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-4-1024x1024.jpeg&quot; alt=&quot;&quot; class=&quot;wp-image-46902&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-4-1024x1024.jpeg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-4-300x300.jpeg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-4-150x150.jpeg 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-4-768x768.jpeg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-4-50x50.jpeg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-4-40x40.jpeg 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-4-464x464.jpeg 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-4-696x696.jpeg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-4-560x560.jpeg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-4-296x296.jpeg 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-4-472x472.jpeg 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-4-80x80.jpeg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-4-48x48.jpeg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-4.jpeg 1080w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-port-of-entry-wink&quot;&gt;Port of Entry: &lt;strong&gt;Wink&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Monetization isn’t just about what you charge, it’s about &lt;em&gt;when&lt;/em&gt; and &lt;em&gt;how&lt;/em&gt; you charge. The &lt;strong&gt;Port of Entry&lt;/strong&gt; award celebrates apps with standout paywalls, pricing, and checkout strategies.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Wink&lt;/strong&gt; made bold moves in experimentation this year, testing everything from pricing bundles to animated paywalls. Their weekend promos alone boosted revenue by over 20%, while churn-triggered offers and seamless web checkout flows gave users multiple smooth entry points to upgrade.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Why it won:&lt;/strong&gt;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Strategic experimentation across pricing and design&lt;/li&gt;



&lt;li&gt;Smart promotions that actually moved the needle&lt;/li&gt;



&lt;li&gt;Lifecycle monetization and web + in-app synergy&lt;/li&gt;
&lt;/ul&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-5-1024x1024.jpeg&quot; alt=&quot;&quot; class=&quot;wp-image-46904&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-5-1024x1024.jpeg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-5-300x300.jpeg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-5-150x150.jpeg 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-5-768x768.jpeg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-5-50x50.jpeg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-5-40x40.jpeg 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-5-464x464.jpeg 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-5-696x696.jpeg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-5-560x560.jpeg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-5-296x296.jpeg 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-5-472x472.jpeg 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-5-80x80.jpeg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-5-48x48.jpeg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-5.jpeg 1080w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-life-preserver-weward&quot;&gt;Life Preserver: &lt;strong&gt;WeWard&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Retention is hard. Keeping users motivated even harder. The &lt;strong&gt;Life Preserver&lt;/strong&gt; award honors the app that mastered both.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;WeWard&lt;/strong&gt; kept users coming back (and walking more) through habit loops, social motivation, and emotional reinforcement. Weekly leaderboards and celebratory streaks didn’t just keep users active, they dropped churn by 22% over nine months.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Why it won:&lt;/strong&gt;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Habit-forming design that drives daily engagement&lt;/li&gt;



&lt;li&gt;Social motivation through community rankings&lt;/li&gt;



&lt;li&gt;22% reduction in churn thanks to reinforcement and sharing&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;This is what sustainable engagement looks like: fun, rewarding, and some healthy competition.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-2-1024x1024.jpeg&quot; alt=&quot;&quot; class=&quot;wp-image-46906&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-2-1024x1024.jpeg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-2-300x300.jpeg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-2-150x150.jpeg 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-2-768x768.jpeg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-2-50x50.jpeg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-2-40x40.jpeg 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-2-464x464.jpeg 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-2-696x696.jpeg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-2-560x560.jpeg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-2-296x296.jpeg 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-2-472x472.jpeg 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-2-80x80.jpeg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-2-48x48.jpeg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-2.jpeg 1080w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-treasure-chest-ladder&quot;&gt;Treasure Chest: &lt;strong&gt;Ladder&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The &lt;strong&gt;Treasure Chest&lt;/strong&gt; award celebrates apps that know how to turn user intent into business impact, monetizing not just subscriptions, but brand affinity.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;507&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-16-at-14.00.12-1024x507.png&quot; alt=&quot;&quot; class=&quot;wp-image-46910&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-16-at-14.00.12-1024x507.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-16-at-14.00.12-300x149.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-16-at-14.00.12-768x381.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-16-at-14.00.12-1536x761.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-16-at-14.00.12-2048x1015.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-16-at-14.00.12-50x25.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-16-at-14.00.12-81x40.png 81w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-16-at-14.00.12-696x345.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-16-at-14.00.12-560x278.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-16-at-14.00.12-840x416.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-16-at-14.00.12-80x40.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-16-at-14.00.12-48x24.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;strong&gt;Ladder&lt;/strong&gt; does this brilliantly. Their Pro plan provides full access to everything the app has to offer, including a range of social features like direct messaging. As you’re onboarding, you receive one of those direct messages from a coach whose workout program you follow. Want to respond and have 1:1 interactions with your coach? Upgrade to Elite. Combine that with a merch shop that’s being fed by referral-driven loyalty, and Ladder’s monetization strategy is as smart as it is seamless.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Why it won:&lt;/strong&gt;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Monetizing high-intent users who spend up to 4x more&lt;/li&gt;



&lt;li&gt;Upsells that feel human and contextual&lt;/li&gt;



&lt;li&gt;Extra revenue through merch for superfans&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;It’s a perfect example of aligning monetization with motivation, and making it look good doing it&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-3-1024x1024.jpeg&quot; alt=&quot;&quot; class=&quot;wp-image-46908&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-3-1024x1024.jpeg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-3-300x300.jpeg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-3-150x150.jpeg 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-3-768x768.jpeg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-3-50x50.jpeg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-3-40x40.jpeg 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-3-464x464.jpeg 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-3-696x696.jpeg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-3-560x560.jpeg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-3-296x296.jpeg 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-3-472x472.jpeg 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-3-80x80.jpeg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-3-48x48.jpeg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-3.jpeg 1080w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-golden-shippy-moment&quot;&gt;The Golden Shippy moment&lt;/h2&gt;



&lt;p&gt;Each winner walked away with the iconic &lt;strong&gt;Chocolate Shippy trophy&lt;/strong&gt; (and will have the proper, metal statue sent to their homes to save on luggage fees!) and has seen their apps and logos lighting up &lt;strong&gt;Times Square&lt;/strong&gt;. A surreal reward for a year of bold ideas and hard work.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;576&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-6-1024x576.jpeg&quot; alt=&quot;&quot; class=&quot;wp-image-46914&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-6-1024x576.jpeg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-6-300x169.jpeg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-6-768x432.jpeg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-6-1536x864.jpeg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-6-50x28.jpeg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-6-71x40.jpeg 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-6-696x392.jpeg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-6-560x315.jpeg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-6-526x296.jpeg 526w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-6-840x472.jpeg 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-6-80x45.jpeg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-6-48x27.jpeg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Untitled-6.jpeg 1920w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-until-next-year&quot;&gt;Until next year…&lt;/h2&gt;



&lt;p&gt;The 2025 Shippies reminded us that great apps are more than clever code and catchy onboarding flows. They’re built by people who &lt;em&gt;care&lt;/em&gt; about design, delight, and making something that genuinely helps their users.&lt;/p&gt;



&lt;p&gt;So to every app out there that shipped this year: keep going. Keep experimenting. Keep polishing.&lt;/p&gt;



&lt;p&gt;We’ll see you at &lt;strong&gt;App Growth Annual 2026&lt;/strong&gt; — and maybe next time, it’ll be your app up on that billboard!&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Understanding the internal of Flow, StateFlow, and SharedFlow]]></title><description><![CDATA[In this article, you'll dive deep into the internal mechanisms of Flow, StateFlow, and SharedFlow, exploring how they work under the hood.]]></description><link>https://www.revenuecat.com/blog/engineering/flow-internals/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/flow-internals/</guid><pubDate>Wed, 15 Oct 2025 23:47:33 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Flow.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;&lt;a href=&quot;https://kotlinlang.org/docs/coroutines-overview.html&quot;&gt;Kotlin Coroutines&lt;/a&gt; introduced &lt;a href=&quot;https://kotlinlang.org/docs/flow.html&quot;&gt;Flow&lt;/a&gt; as a reactive stream abstraction, fundamentally changing how Android developers handle asynchronous data streams. While &lt;code&gt;LiveData&lt;/code&gt; served the Android community for years, Flow emerged as a more flexible, and coroutine-native solution. But the power of Flow goes far beyond its clean API, it’s in the sophisticated internal machinery that makes it both performant and safe.&lt;/p&gt;



&lt;p&gt;In this article, you’ll dive deep into the internal mechanisms of &lt;code&gt;Flow&lt;/code&gt;, &lt;code&gt;StateFlow&lt;/code&gt;, and &lt;code&gt;SharedFlow&lt;/code&gt;, exploring how they work under the hood, the engineering decisions that power them, and the subtle optimizations that make them production-ready.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-understanding-the-core-abstraction-what-makes-flow-special&quot;&gt;&lt;strong&gt;Understanding the core abstraction: What makes Flow special&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;At its heart, Flow is an asynchronous data stream that sequentially emits values. But what distinguishes Flow from other reactive streams is its adherence to two fundamental properties:&amp;nbsp;&lt;strong&gt;context preservation&lt;/strong&gt;&amp;nbsp;and&amp;nbsp;&lt;strong&gt;exception transparency&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Context preservation&lt;/strong&gt;&amp;nbsp;means a flow encapsulates its own execution context and never leaks it downstream. You can’t accidentally emit from the wrong dispatcher.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1SuQpf wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;val myFlow = flow {\n\/\/ withContext(Dispatchers.IO) { \/\/ This would throw IllegalStateException\n    emit(1)\/\/ OK - emits in the collector&apos;s context\n    coroutineScope {\n        emit(2)\/\/ OK - still the same coroutine context\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Exception transparency&lt;/strong&gt;&amp;nbsp;ensures that when an emission fails, the flow immediately stops and propagates the exception. This makes flows predictable and composable, you can reason about error handling locally without worrying about upstream flows swallowing exceptions.&lt;/p&gt;



&lt;p&gt;These properties are not just guidelines, they’re enforced by the runtime. The &lt;code&gt;Flow&lt;/code&gt; API is carefully designed to prevent violations, and attempting to break these rules results in exception. For example, if you’re trying to collect the &lt;code&gt;Flow&lt;/code&gt; above, you’ll face “&lt;code&gt;java.lang.IllegalStateException: Flow invariant is violated&lt;/code&gt;” exception.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;the-flow-interface-and-abstractflow-implementation&quot;&gt;&lt;strong&gt;The Flow interface and AbstractFlow implementation&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;If you examine the &lt;code&gt;Flow&lt;/code&gt; interface, it’s pretty minimal:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZjCj6o wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;public interface Flow&lt;out T&gt; {\n    public suspend fun collect(collector: FlowCollector&lt;T&gt;)\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;A single suspending function. That’s it. This simplicity is deliberate, Flow is cold by nature, meaning each collection creates a new execution. The complexity lies in how this simple interface is implemented.&lt;/p&gt;



&lt;p&gt;The recommended way to implement &lt;code&gt;Flow&lt;/code&gt; is through&amp;nbsp;&lt;code&gt;AbstractFlow&lt;/code&gt;, which provides critical safety guardrails:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1Q1Ri9 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@ExperimentalCoroutinesApi\npublic abstract class AbstractFlow&lt;T&gt; : Flow&lt;T&gt;, CancellableFlow&lt;T&gt; {\n    public final override suspend fun collect(collector: FlowCollector&lt;T&gt;) {\n        val safeCollector = SafeCollector(collector, coroutineContext)\n        try {\n            collectSafely(safeCollector)\n        } finally {\n            safeCollector.releaseIntercepted()\n        }\n    }\n\n    public abstract suspend fun collectSafely(collector: FlowCollector&lt;T&gt;)\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The&amp;nbsp;&lt;code&gt;AbstractFlow&lt;/code&gt;&amp;nbsp;implementation wraps every collector with a&amp;nbsp;&lt;code&gt;SafeCollector&lt;/code&gt;. This wrapper is the enforcer of context preservation, it tracks the coroutine context and throws&amp;nbsp;&lt;code&gt;IllegalStateException&lt;/code&gt;&amp;nbsp;if you try to emit from a different context. This is how the flow builder prevents&amp;nbsp;&lt;code&gt;withContext&lt;/code&gt;&amp;nbsp;calls during emission.&lt;/p&gt;



&lt;p&gt;When you call&amp;nbsp;&lt;code&gt;emit()&lt;/code&gt;&amp;nbsp;on a &lt;code&gt;SafeCollector&lt;/code&gt;, it performs a context check before allowing the emission like the internal codes below:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-DFpnK wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/\/ Inside SafeCollector implementationpublic override suspend fun emit(value: T) {\n    return suspendCoroutineUninterceptedOrReturn sc@{ uCont -&gt;\n        try {\n            emit(uCont, value)\n        } catch (e: Throwable) {\n\/\/ save the fact that exception was thrown\n            lastEmissionContext = DownstreamExceptionContext(e, uCont.context)\n            throw e\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;SafeCollector&lt;/code&gt; compares the current coroutine context with the collector’s context. If they don’t match, it knows you’ve switched contexts illegally and throws an exception. This safety is what makes &lt;code&gt;Flow&lt;/code&gt;‘s context preservation guarantee possible.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;hot-vs-cold-sharedflow-enters-the-picture&quot;&gt;&lt;strong&gt;Hot vs Cold: SharedFlow enters the picture&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;While regular &lt;code&gt;Flow&lt;/code&gt; is cold (each collector triggers independent execution), many use cases require hot flows, flows that emit values regardless of whether anyone is collecting. This is where&amp;nbsp;&lt;code&gt;SharedFlow&lt;/code&gt;&amp;nbsp;comes in.&lt;/p&gt;



&lt;p&gt;&lt;code&gt;SharedFlow&lt;/code&gt; is fundamentally different from &lt;code&gt;Flow&lt;/code&gt;. It’s a&amp;nbsp;&lt;strong&gt;broadcast&lt;/strong&gt;&amp;nbsp;mechanism that shares emitted values among all active collectors. Think of it like a radio station, it broadcasts whether anyone is listening or not (though its behavior adapts based on whether there are subscribers).&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-sharedflow-architecture&quot;&gt;&lt;strong&gt;The SharedFlow architecture&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;If you examine the&amp;nbsp;&lt;code&gt;SharedFlow&lt;/code&gt;&amp;nbsp;interface, you’ll notice it extends&amp;nbsp;&lt;code&gt;Flow&lt;/code&gt;:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1v6z80 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;public interface SharedFlow&lt;out T&gt; : Flow&lt;T&gt; {\n    public val replayCache: List&lt;T&gt;\n    override suspend fun collect(collector: FlowCollector&lt;T&gt;): Nothing\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The key difference? The&amp;nbsp;&lt;code&gt;collect&lt;/code&gt;&amp;nbsp;function’s return type is&amp;nbsp;&lt;code&gt;Nothing&lt;/code&gt;. This signals that&amp;nbsp;&lt;strong&gt;SharedFlow never completes&lt;/strong&gt;. A call to&amp;nbsp;&lt;code&gt;collect()&lt;/code&gt;&amp;nbsp;on a &lt;code&gt;SharedFlow&lt;/code&gt; will run forever unless cancelled. This is the essence of hot flows, they’re always active.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-internal-buffer-architecture&quot;&gt;&lt;strong&gt;The internal buffer architecture&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The real sophistication lies in&amp;nbsp;&lt;code&gt;SharedFlowImpl&lt;/code&gt;, which manages a complex circular buffer to handle replay cache, buffering, and queued emitters. Let’s examine its structure:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZsYbxd wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/\/ codes are from the kotlinx.coroutines\ninternal open class SharedFlowImpl&lt;T&gt;(\n    private val replay: Int,\n    private val bufferCapacity: Int,\n    private val onBufferOverflow: BufferOverflow\n) : AbstractSharedFlow&lt;SharedFlowSlot&gt;(), MutableSharedFlow&lt;T&gt;, CancellableFlow&lt;T&gt;, FusibleFlow&lt;T&gt; {\n\/*\n        Logical structure of the buffer\n\n                  buffered values\n             \/-----------------------\\\n                          replayCache      queued emitters\n                          \/----------\\\/----------------------\\\n         +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+\n         |   | 1 | 2 | 3 | 4 | 5 | 6 | E | E | E | E | E | E |   |   |   |\n         +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+\n               ^           ^           ^                      ^\n               |           |           |                      |\n              head         |      head + bufferSize     head + totalSize\n               |           |           |\n     index of the slowest  |    index of the fastest\n      possible collector   |     possible collector\n               |           |\n               |     replayIndex == new collector&apos;s index\n               \\---------------------- \/\n          range of possible minCollectorIndex\n\n          head == minOf(minCollectorIndex, replayIndex) \/\/ by definition\n          totalSize == bufferSize + queueSize \/\/ by definition\n\n       INVARIANTS:\n          minCollectorIndex = activeSlots.minOf { it.index } ?: (head + bufferSize)\n          replayIndex &lt;= head + bufferSize\n     *\/private var buffer: Array&lt;Any?&gt;? = null\/\/ allocated when needed, always power of twoprivate var replayIndex = 0L\/\/ minimal index from which new collector gets valuesprivate var minCollectorIndex = 0L\/\/ minimal index of active collectorsprivate var bufferSize = 0\/\/ number of buffered valuesprivate var queueSize = 0\/\/ number of queued emitters&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This comment from the coroutines library is a goldmine of implementation detail. The buffer is a circular array that logically contains three regions:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Replay cache&lt;/strong&gt;&amp;nbsp;(from&amp;nbsp;&lt;code&gt;replayIndex&lt;/code&gt;&amp;nbsp;to&amp;nbsp;&lt;code&gt;head + bufferSize&lt;/code&gt;): Values that new collectors immediately receive&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Buffered values&lt;/strong&gt;&amp;nbsp;(from&amp;nbsp;&lt;code&gt;head&lt;/code&gt;&amp;nbsp;to&amp;nbsp;&lt;code&gt;head + bufferSize&lt;/code&gt;): Values available to collectors&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Queued emitters&lt;/strong&gt;&amp;nbsp;(from&amp;nbsp;&lt;code&gt;head + bufferSize&lt;/code&gt;&amp;nbsp;to&amp;nbsp;&lt;code&gt;head + totalSize&lt;/code&gt;): Suspended emitters waiting for slow collectors&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;The circular buffer optimization is important for performance. Instead of shifting elements when the head moves forward, the implementation uses modulo arithmetic to wrap around:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-5JtzI wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;private fun Array&lt;Any?&gt;.getBufferAt(index: Long) = get(index.toInt() and (size - 1))\nprivate fun Array&lt;Any?&gt;.setBufferAt(index: Long, item: Any?) = set(index.toInt() and (size - 1), item)&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The&amp;nbsp;&lt;code&gt;and (size - 1)&lt;/code&gt;&amp;nbsp;operation is a fast modulo for power-of-two sizes. This is why the buffer is always allocated in powers of two, it turns expensive division into a single bitwise AND.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;the-slot-allocation-system&quot;&gt;&lt;strong&gt;The slot allocation system&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Both &lt;code&gt;StateFlow&lt;/code&gt; and &lt;code&gt;SharedFlow&lt;/code&gt; use a slot allocation system to track active collectors. This is managed by&amp;nbsp;&lt;code&gt;AbstractSharedFlow&lt;/code&gt;:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Kp3o7 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;internal abstract class AbstractSharedFlow&lt;S : AbstractSharedFlowSlot&lt;*&gt;&gt; : SynchronizedObject() {\n    protected var slots: Array&lt;S?&gt;? = null\/\/ allocated when neededprivate set\n    protected var nCollectors = 0\/\/ number of allocated (!free) slotsprivate set\n    private var nextIndex = 0\/\/ oracle for the next free slot index&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;When a collector starts, it allocates a slot:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1oojj3 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;protected fun allocateSlot(): S {\n    val subscriptionCount: SubscriptionCountStateFlow?\n    val slot = synchronized(this) {\n        val slots = when (val curSlots = slots) {\n            null -&gt; createSlotArray(2).also { slots = it }\n            else -&gt; if (nCollectors &gt;= curSlots.size) {\n                curSlots.copyOf(2 * curSlots.size).also { slots = it }\n            } else {\n                curSlots\n            }\n        }\n        var index = nextIndex\n        var slot: S\n        while (true) {\n            slot = slots[index] ?: createSlot().also { slots[index] = it }\n            index++\n            if (index &gt;= slots.size) index = 0\n            if ((slot as AbstractSharedFlowSlot&lt;Any&gt;).allocateLocked(this)) break\n        }\n        nextIndex = index\n        nCollectors++\n        subscriptionCount = _subscriptionCount\n        slot\n    }\n    subscriptionCount?.increment(1)\n    return slot\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This allocation strategy has several clever optimizations:&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Slot reuse&lt;/strong&gt;: Slots are never destroyed, only marked as free. When a new collector arrives, it reuses an existing slot rather than allocating a new one. This eliminates allocation churn in scenarios where collectors come and go frequently.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Amortized O(1) allocation&lt;/strong&gt;: The array doubles in size when full, giving amortized constant-time allocation just like &lt;code&gt;ArrayList&lt;/code&gt;.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Predictable next slot search&lt;/strong&gt;: The&amp;nbsp;&lt;code&gt;nextIndex&lt;/code&gt;&amp;nbsp;oracle remembers where the last successful allocation happened, making the next search start from a likely free slot instead of always starting from zero.&lt;/p&gt;



&lt;p&gt;On the other hand, for &lt;code&gt;SharedFlow&lt;/code&gt;, each slot tracks the collector’s position in the buffer:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1qDrCw wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;internal class SharedFlowSlot : AbstractSharedFlowSlot&lt;SharedFlowImpl&lt;*&gt;&gt;() {\n    @JvmField\n    var index = -1L\/\/ current \&amp;quot;to-be-emitted\&amp;quot; index, -1 means free@JvmField\n    var cont: Continuation&lt;Unit&gt;? = null\/\/ collector waiting for new valueoverride fun allocateLocked(flow: SharedFlowImpl&lt;*&gt;): Boolean {\n        if (index &gt;= 0) return false\/\/ not free\n        index = flow.updateNewCollectorIndexLocked()\n        return true\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The&amp;nbsp;&lt;code&gt;index&lt;/code&gt;&amp;nbsp;field is pretty important here, it tracks where this collector is in the stream of values. When a new value is emitted, the &lt;code&gt;SharedFlow&lt;/code&gt; checks all slots and resumes those whose&amp;nbsp;&lt;code&gt;index&lt;/code&gt;&amp;nbsp;is behind the buffer.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;the-emission-flow-in-sharedflow&quot;&gt;&lt;strong&gt;The emission flow in SharedFlow&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Now, let’s explore what happens when you emit a value to a &lt;code&gt;SharedFlow&lt;/code&gt; with&amp;nbsp;&lt;code&gt;tryEmit()&lt;/code&gt;:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1ntnC7 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;override fun tryEmit(value: T): Boolean {\n    var resumes: Array&lt;Continuation&lt;Unit&gt;?&gt; = EMPTY_RESUMES\n    val emitted = synchronized(this) {\n        if (tryEmitLocked(value)) {\n            resumes = findSlotsToResumeLocked(resumes)\n            true\n        } else {\n            false\n        }\n    }\n    for (cont in resumes) cont?.resume(Unit)\n    return emitted\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The critical observation: emissions happen in two phases, and&amp;nbsp;&lt;strong&gt;continuations are resumed outside the lock&lt;/strong&gt;. This prevents deadlocks when using unconfined dispatchers and is a recurring pattern throughout the coroutines library.&lt;/p&gt;



&lt;p&gt;Inside&amp;nbsp;&lt;code&gt;tryEmitLocked&lt;/code&gt;, the behavior depends on whether there are active collectors:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1yUoNx wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;private fun tryEmitLocked(value: T): Boolean {\n\/\/ Fast path without collectors -&gt; no bufferingif (nCollectors == 0) return tryEmitNoCollectorsLocked(value)\n\n\/\/ With collectors we&apos;ll have to bufferif (bufferSize &gt;= bufferCapacity &amp;amp;&amp;amp; minCollectorIndex &lt;= replayIndex) {\n        when (onBufferOverflow) {\n            BufferOverflow.SUSPEND -&gt; return false\/\/ will suspend\n            BufferOverflow.DROP_LATEST -&gt; return true\/\/ just drop incoming\n            BufferOverflow.DROP_OLDEST -&gt; {}\/\/ force enqueue &amp;amp; drop oldest\n        }\n    }\n    enqueueLocked(value)\n    bufferSize++\n    if (bufferSize &gt; bufferCapacity) dropOldestLocked()\n    if (replaySize &gt; replay) {\n        updateBufferLocked(replayIndex + 1, minCollectorIndex, bufferEndIndex, queueEndIndex)\n    }\n    return true\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;When there are no collectors, &lt;code&gt;SharedFlow&lt;/code&gt; takes a fast path:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z16ty6c wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;private fun tryEmitNoCollectorsLocked(value: T): Boolean {\n    assert { nCollectors == 0 }\n    if (replay == 0) return true\/\/ no need to replay, just forget it\n    enqueueLocked(value)\n    bufferSize++\n    if (bufferSize &gt; replay) dropOldestLocked()\n    minCollectorIndex = head + bufferSize\n    return true\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This is an important optimization: when there are no subscribers, &lt;code&gt;SharedFlow&lt;/code&gt; only maintains the replay cache. It doesn’t allocate extra buffer space, and buffer overflow strategies don’t apply, the behavior is effectively&amp;nbsp;&lt;code&gt;BufferOverflow.DROP_OLDEST&lt;/code&gt;&amp;nbsp;with buffer size equal to&amp;nbsp;&lt;code&gt;replay&lt;/code&gt;.&lt;/p&gt;



&lt;p&gt;When&amp;nbsp;&lt;code&gt;tryEmit&lt;/code&gt;&amp;nbsp;returns false (buffer is full with SUSPEND strategy),&amp;nbsp;&lt;code&gt;emit()&lt;/code&gt;&amp;nbsp;must suspend:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1w9ffL wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;private suspend fun emitSuspend(value: T) = suspendCancellableCoroutine&lt;Unit&gt; sc@{ cont -&gt;\n    var resumes: Array&lt;Continuation&lt;Unit&gt;?&gt; = EMPTY_RESUMES\n    val emitter = synchronized(this) lock@{\n        if (tryEmitLocked(value)) {\n            cont.resume(Unit)\n            resumes = findSlotsToResumeLocked(resumes)\n            return@lock null\n        }\n\/\/ add suspended emitter to the buffer\n        Emitter(this, head + totalSize, value, cont).also {\n            enqueueLocked(it)\n            queueSize++\n            if (bufferCapacity == 0) resumes = findSlotsToResumeLocked(resumes)\n        }\n    }\n    emitter?.let { cont.disposeOnCancellation(it) }\n    for (r in resumes) r?.resume(Unit)\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The suspended emitter is stored directly in the buffer as an&amp;nbsp;&lt;code&gt;Emitter&lt;/code&gt;&amp;nbsp;object. When space becomes available (because a slow collector catches up or is cancelled), the &lt;code&gt;SharedFlow&lt;/code&gt; will find these&amp;nbsp;&lt;code&gt;Emitter&lt;/code&gt;&amp;nbsp;objects and resume them:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-21B7K0 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;for (curEmitterIndex in newBufferEndIndex until newQueueEndIndex) {\n    val emitter = buffer.getBufferAt(curEmitterIndex)\n    if (emitter !== NO_VALUE) {\n        emitter as Emitter\n        resumes[resumeCount++] = emitter.cont\n        buffer.setBufferAt(curEmitterIndex, NO_VALUE)\n        buffer.setBufferAt(newBufferEndIndex, emitter.value)\n        newBufferEndIndex++\n        if (resumeCount &gt;= maxResumeCount) break\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This is great: queued emitters aren’t stored in a separate data structure. They live in the same circular buffer as values, marked by their type. This unifies the buffer management logic.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;stateflow-a-specialized-sharedflow&quot;&gt;&lt;strong&gt;StateFlow: A specialized SharedFlow&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;&lt;code&gt;StateFlow&lt;/code&gt; is essentially a &lt;code&gt;SharedFlow&lt;/code&gt; with specific configuration and additional constraints. Looking at the constructor:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1stVyf wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;public fun &lt;T&gt; MutableStateFlow(value: T): MutableStateFlow&lt;T&gt; = StateFlowImpl(value ?: NULL)&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The&amp;nbsp;&lt;code&gt;StateFlowImpl&lt;/code&gt;&amp;nbsp;extends&amp;nbsp;&lt;code&gt;AbstractSharedFlow&lt;/code&gt;&amp;nbsp;and implements both&amp;nbsp;&lt;code&gt;MutableStateFlow&lt;/code&gt;&amp;nbsp;and&amp;nbsp;&lt;code&gt;SharedFlow&lt;/code&gt;:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-i6Hki wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;private class StateFlowImpl&lt;T&gt;(\n    initialState: Any\/\/ T | NULL\n) : AbstractSharedFlow&lt;StateFlowSlot&gt;(), MutableStateFlow&lt;T&gt;, CancellableFlow&lt;T&gt;, FusibleFlow&lt;T&gt; {\n    private val _state = atomic(initialState)\n    private var sequence = 0\/\/ serializes updates, value update in process when odd&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The key difference from &lt;code&gt;SharedFlow&lt;/code&gt;: &lt;code&gt;StateFlow&lt;/code&gt; always has exactly one value, and it uses equality-based conflation. The&amp;nbsp;&lt;code&gt;_state&lt;/code&gt;&amp;nbsp;is an atomic reference, and the&amp;nbsp;&lt;code&gt;sequence&lt;/code&gt;&amp;nbsp;counter implements a clever synchronization protocol.&lt;/p&gt;



&lt;p&gt;&lt;code&gt;StateFlow&lt;/code&gt;‘s update mechanism is more complicated than a simple lock:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z21xPhs wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;private fun updateState(expectedState: Any?, newState: Any): Boolean {\n    var curSequence: Int\n    var curSlots: Array&lt;StateFlowSlot?&gt;?\n    synchronized(this) {\n        val oldState = _state.value\n        if (expectedState != null &amp;amp;&amp;amp; oldState != expectedState) return false\n        if (oldState == newState) return true\/\/ conflation via equality\n        _state.value = newState\n        curSequence = sequence\n        if (curSequence and 1 == 0) {\/\/ even means quiescent\n            curSequence++\/\/ make it odd (update in progress)\n            sequence = curSequence\n        } else {\n\/\/ update already in progress, notify it\n            sequence = curSequence + 2\/\/ keep it oddreturn true\n        }\n        curSlots = slots\n    }\n\/\/ Resume collectors outside the lockwhile (true) {\n        curSlots?.forEach { it?.makePending() }\n        synchronized(this) {\n            if (sequence == curSequence) {\n                sequence = curSequence + 1\/\/ make even again (quiescent)return true\n            }\n            curSequence = sequence\n            curSlots = slots\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This is&amp;nbsp;&lt;strong&gt;flat combining,&lt;/strong&gt; a lock-free technique where the first updater takes responsibility for applying subsequent updates. Here’s how it works:&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Even sequence&lt;/strong&gt;&amp;nbsp;means the &lt;code&gt;StateFlow&lt;/code&gt; is quiescent (no update in progress). When an update arrives, it increments the sequence to make it odd, marking an update in progress.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Odd sequence&lt;/strong&gt;&amp;nbsp;means an update is in progress. If another thread tries to update during this time, it just increments the sequence by 2 (keeping it odd) and returns. The first updater will see the sequence changed and know it needs to do another loop to pick up the new value.&lt;/p&gt;



&lt;p&gt;This protocol ensures that only one thread at a time is iterating through collectors, while allowing concurrent updates to be queued without additional synchronization overhead. It’s a batching optimization, multiple rapid updates can be coalesced into a single iteration through collectors.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;stateflow-slot-implementation&quot;&gt;&lt;strong&gt;StateFlow slot implementation&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;&lt;code&gt;StateFlow&lt;/code&gt; slots are simpler than &lt;code&gt;SharedFlow&lt;/code&gt; slots because &lt;code&gt;StateFlow&lt;/code&gt; doesn’t need to track an index (there’s only ever one value):&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z2nPMrE wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;private class StateFlowSlot : AbstractSharedFlowSlot&lt;StateFlowImpl&lt;*&gt;&gt;() {\n    private val _state = WorkaroundAtomicReference&lt;Any?&gt;(null)\n\n    override fun allocateLocked(flow: StateFlowImpl&lt;*&gt;): Boolean {\n        if (_state.value != null) return false\/\/ not free\n        _state.value = NONE\/\/ allocatedreturn true\n    }\n\n    fun makePending() {\n        _state.loop { state -&gt;\n            when {\n                state == null -&gt; return\/\/ free slot, skip\n                state === PENDING -&gt; return\/\/ already pending\n                state === NONE -&gt; {\n                    if (_state.compareAndSet(state, PENDING)) return\n                }\n                else -&gt; {\/\/ must be a suspended continuationif (_state.compareAndSet(state, NONE)) {\n                        (state as CancellableContinuationImpl&lt;Unit&gt;).resume(Unit)\n                        return\n                    }\n                }\n            }\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Each slot can be in one of four states:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;code&gt;null&lt;/code&gt;: free, available for allocation&lt;/li&gt;



&lt;li&gt;&lt;code&gt;NONE&lt;/code&gt;: allocated but no pending value or suspension&lt;/li&gt;



&lt;li&gt;&lt;code&gt;PENDING&lt;/code&gt;: has a pending value to collect&lt;/li&gt;



&lt;li&gt;&lt;code&gt;CancellableContinuationImpl&amp;lt;Unit&amp;gt;&lt;/code&gt;: suspended, waiting for a value&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The state transitions are carefully designed to be lock-free using CAS (&lt;a href=&quot;https://en.wikipedia.org/wiki/Compare-and-swap&quot;&gt;compare-and-swap&lt;/a&gt;) operations. This is designed for performance, &lt;code&gt;makePending()&lt;/code&gt;&amp;nbsp;is called inside the update loop while holding the &lt;code&gt;StateFlow&lt;/code&gt; lock, but the CAS operations don’t block.&lt;/p&gt;



&lt;p&gt;If you look into the collection logic, it demonstrates &lt;code&gt;StateFlow&lt;/code&gt;‘s conflation behavior:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-14MEO0 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;override suspend fun collect(collector: FlowCollector&lt;T&gt;): Nothing {\n    val slot = allocateSlot()\n    try {\n        if (collector is SubscribedFlowCollector) collector.onSubscription()\n        val collectorJob = currentCoroutineContext()[Job]\n        var oldState: Any? = null\n        while (true) {\n            val newState = _state.value\n            collectorJob?.ensureActive()\n\/\/ Conflate using equalityif (oldState == null || oldState != newState) {\n                collector.emit(NULL.unbox(newState))\n                oldState = newState\n            }\n            if (!slot.takePending()) {\n                slot.awaitPending()\n            }\n        }\n    } finally {\n        freeSlot(slot)\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The conflation check&amp;nbsp;&lt;code&gt;oldState != newState&lt;/code&gt;&amp;nbsp;is where equality-based conflation happens. If the value didn’t change (according to&amp;nbsp;&lt;code&gt;equals()&lt;/code&gt;), the collector doesn’t re-emit. This is the core of &lt;code&gt;StateFlow&lt;/code&gt;‘s “distinct until changed” behavior.&lt;/p&gt;



&lt;p&gt;The loop structure is optimized:&amp;nbsp;&lt;code&gt;takePending()&lt;/code&gt;&amp;nbsp;first tries a fast path without suspending. Only if there’s no pending value does it call&amp;nbsp;&lt;code&gt;awaitPending()&lt;/code&gt;&amp;nbsp;to suspend:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1XG6uw wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;suspend fun awaitPending(): Unit = suspendCancellableCoroutine sc@{ cont -&gt;\n    assert { _state.value !is CancellableContinuationImpl&lt;*&gt; }\n    if (_state.compareAndSet(NONE, cont)) return@sc\n    assert { _state.value === PENDING }\n    cont.resume(Unit)\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This avoids suspension if a value became available between the&amp;nbsp;&lt;code&gt;takePending()&lt;/code&gt;&amp;nbsp;check and the&amp;nbsp;&lt;code&gt;awaitPending()&lt;/code&gt;&amp;nbsp;call, another race condition handled gracefully.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;the-subscription-count-mechanism&quot;&gt;&lt;strong&gt;The subscription count mechanism&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Both &lt;code&gt;SharedFlow&lt;/code&gt; and &lt;code&gt;StateFlow&lt;/code&gt; expose a&amp;nbsp;&lt;code&gt;subscriptionCount&lt;/code&gt;&amp;nbsp;property, but its implementation is subtle. You might expect it to be a simple &lt;code&gt;StateFlow&lt;/code&gt;, but it’s not:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z2lolp4 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;private class SubscriptionCountStateFlow(initialValue: Int) : StateFlow&lt;Int&gt;,\n    SharedFlowImpl&lt;Int&gt;(1, Int.MAX_VALUE, BufferOverflow.DROP_OLDEST)\n{\n    init { tryEmit(initialValue) }\n\n    override val value: Int\n        get() = synchronized(this) { lastReplayedLocked }\n\n    fun increment(delta: Int) = synchronized(this) {\n        tryEmit(lastReplayedLocked + delta)\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;It’s a&amp;nbsp;&lt;code&gt;SharedFlow&lt;/code&gt;&amp;nbsp;masquerading as a&amp;nbsp;&lt;code&gt;StateFlow&lt;/code&gt;. Why? The comment (from the &lt;code&gt;kotlinx.coroutines&lt;/code&gt; library) in the code explains:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1rtp9D wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;The importance of non-conflating can be demonstrated with the following example:\nval shared = flowOf(239).stateIn(this, SharingStarted.Lazily, 42)\nprintln(shared.first())\nyield()\nprintln(shared.first())\n\nIf the flow is shared within the same dispatcher, the `SharingStarted.Lazily` will\nnever be able to start the source: `first` sees the initial value and immediately\nunsubscribes, leaving the asynchronous `SharingStarted` with conflated zero.&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;If &lt;code&gt;subscriptionCount&lt;/code&gt; was a regular &lt;code&gt;StateFlow&lt;/code&gt;, it would conflate&amp;nbsp;&lt;code&gt;0 -&amp;gt; 1 -&amp;gt; 0&lt;/code&gt;&amp;nbsp;into just&amp;nbsp;&lt;code&gt;0&lt;/code&gt;, and listeners wouldn’t see the intermediate&amp;nbsp;&lt;code&gt;1&lt;/code&gt;. By using &lt;code&gt;SharedFlow&lt;/code&gt; with&amp;nbsp;&lt;code&gt;BufferOverflow.DROP_OLDEST&lt;/code&gt;&amp;nbsp;and unlimited buffer, every subscription change is delivered, critical for&amp;nbsp;&lt;code&gt;SharingStarted&lt;/code&gt;&amp;nbsp;strategies that need to observe every subscriber arrival.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;collector-index-management-and-resumption&quot;&gt;&lt;strong&gt;Collector index management and resumption&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The most complex part of &lt;code&gt;SharedFlow&lt;/code&gt; is managing collector indices when values are emitted and consumed. Let’s examine&amp;nbsp;&lt;code&gt;updateCollectorIndexLocked&lt;/code&gt;, which is called when a collector frees its slot or advances its index:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-SIVhk wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;internal fun updateCollectorIndexLocked(oldIndex: Long): Array&lt;Continuation&lt;Unit&gt;?&gt; {\n    assert { oldIndex &gt;= minCollectorIndex }\n    if (oldIndex &gt; minCollectorIndex) return EMPTY_RESUMES\/\/ nothing changesval head = head\n    var newMinCollectorIndex = head + bufferSize\n    if (bufferCapacity == 0 &amp;amp;&amp;amp; queueSize &gt; 0) newMinCollectorIndex++\n\n\/\/ Find new minimum collector index\n    forEachSlotLocked { slot -&gt;\n        if (slot.index &gt;= 0 &amp;amp;&amp;amp; slot.index &lt; newMinCollectorIndex) {\n            newMinCollectorIndex = slot.index\n        }\n    }\n\n    assert { newMinCollectorIndex &gt;= minCollectorIndex }\n    if (newMinCollectorIndex &lt;= minCollectorIndex) return EMPTY_RESUMES\n\n\/\/ Calculate how many emitters can be resumedvar newBufferEndIndex = bufferEndIndex\n    val maxResumeCount = if (nCollectors &gt; 0) {\n        val newBufferSize0 = (newBufferEndIndex - newMinCollectorIndex).toInt()\n        minOf(queueSize, bufferCapacity - newBufferSize0)\n    } else {\n        queueSize\n    }\n\n\/\/ Resume emitters and move their values to buffervar resumes: Array&lt;Continuation&lt;Unit&gt;?&gt; = EMPTY_RESUMES\n    if (maxResumeCount &gt; 0) {\n        resumes = arrayOfNulls(maxResumeCount)\n        var resumeCount = 0\n        val buffer = buffer!!\n        for (curEmitterIndex in newBufferEndIndex until newQueueEndIndex) {\n            val emitter = buffer.getBufferAt(curEmitterIndex)\n            if (emitter !== NO_VALUE) {\n                emitter as Emitter\n                resumes[resumeCount++] = emitter.cont\n                buffer.setBufferAt(curEmitterIndex, NO_VALUE)\n                buffer.setBufferAt(newBufferEndIndex, emitter.value)\n                newBufferEndIndex++\n                if (resumeCount &gt;= maxResumeCount) break\n            }\n        }\n    }\n\n\/\/ Update buffer state\n    updateBufferLocked(newReplayIndex, newMinCollectorIndex, newBufferEndIndex, newQueueEndIndex)\n    cleanupTailLocked()\n    if (resumes.isNotEmpty()) resumes = findSlotsToResumeLocked(resumes)\n    return resumes\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This function does multiple things atomically:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Recomputes minCollectorIndex&lt;/strong&gt;: Finds the slowest remaining collector&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Calculates buffer space freed&lt;/strong&gt;: As the minimum advances, buffer entries before the new minimum are no longer needed&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Resumes queued emitters&lt;/strong&gt;: When space is freed, suspended emitters can resume and their values move from the queue to the buffer&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Updates all indices&lt;/strong&gt;: Adjusts&amp;nbsp;&lt;code&gt;replayIndex&lt;/code&gt;,&amp;nbsp;&lt;code&gt;minCollectorIndex&lt;/code&gt;,&amp;nbsp;&lt;code&gt;bufferSize&lt;/code&gt;, and&amp;nbsp;&lt;code&gt;queueSize&lt;/code&gt;&amp;nbsp;consistently&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Resumes waiting collectors&lt;/strong&gt;: If emitters added values to the buffer, collectors waiting for values can resume&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;All of this happens under a single lock acquisition, ensuring atomicity. The continuations are then resumed outside the lock to prevent deadlocks.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;performance-characteristics-and-design-trade-offs&quot;&gt;&lt;strong&gt;Performance characteristics and design trade-offs&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The implementation makes several performance trade-offs that are worth understanding:&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;StateFlow&lt;/code&gt; updates are O(N) in the number of collectors&lt;/strong&gt;. Every update iterates through all slots to call&amp;nbsp;&lt;code&gt;makePending()&lt;/code&gt;. For most real-world use cases with a small number of collectors (usually 1-3), this is fine and simpler than more complex data structures.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;SharedFlow&lt;/code&gt; emissions are also O(N)&lt;/strong&gt;. Finding slots to resume requires iterating through all slots. Again, for typical use cases, this linear scan is faster than maintaining a heap or skip list of indices.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Allocation optimization over CPU optimization&lt;/strong&gt;. The circular buffer, slot reuse, and flat combining all prioritize reducing allocations. In a garbage-collected environment like the JVM, this is often more important than raw CPU efficiency.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Lock-based synchronization&lt;/strong&gt;. Both &lt;code&gt;StateFlow&lt;/code&gt; and &lt;code&gt;SharedFlow&lt;/code&gt; use synchronized blocks rather than pure lock-free algorithms. This is pragmatic, locks are fast on modern JVMs, and the uncontended case (most updates) is very cheap. The complex lock-free algorithms required for truly concurrent updates would be harder to maintain and potentially slower due to CAS retry loops.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Resume outside the lock&lt;/strong&gt;. This is perhaps quite an important optimization. Resuming continuations can trigger arbitrary user code, so it must happen outside any locks. The two-phase pattern (collect resumes under lock, resume outside lock) appears throughout the codebase.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;conclusion&quot;&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;In this article, you’ve explored the internal mechanisms of &lt;code&gt;Flow&lt;/code&gt;, &lt;code&gt;StateFlow&lt;/code&gt;, and &lt;code&gt;SharedFlow&lt;/code&gt;, examining the sophisticated engineering that makes them both performant and correct. The internal implementations showcase pragmatic engineering choices: simple algorithms optimized for common cases, careful attention to memory allocation, and graceful handling of concurrent access without over-engineering for rare edge cases.&lt;/p&gt;



&lt;p&gt;Understanding these internals helps you make better decisions about when to use &lt;code&gt;StateFlow&lt;/code&gt; vs &lt;code&gt;SharedFlow&lt;/code&gt;, how buffer sizes affect performance, and what the performance characteristics of different configurations are. Whether you’re building reactive UI layers with &lt;code&gt;StateFlow&lt;/code&gt;, implementing event buses with &lt;code&gt;SharedFlow&lt;/code&gt;, or designing custom Flow operators, this knowledge provides the foundation for writing correct, performant coroutine-based code.&lt;/p&gt;



&lt;p&gt;As always, happy coding!&lt;/p&gt;



&lt;p&gt;—&amp;nbsp;&lt;a href=&quot;https://github.com/skydoves&quot;&gt;&lt;strong&gt;Jaewoong&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Are you wasting time overanalyzing ads? The case for (and against) creative testing]]></title><description><![CDATA[How to find the balance between dissecting every detail of your ads, and taking shots in the dark ]]></description><link>https://www.revenuecat.com/blog/growth/overanalyze-creative-analysis-paid-ads/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/overanalyze-creative-analysis-paid-ads/</guid><pubDate>Wed, 15 Oct 2025 16:21:06 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Are-you-waisting-time-by-analyzing-creative-tests_.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Creative analysis is a hot topic. Some people swear by it, pouring hours into dissecting every ad, but there’s a growing number of experts beginning to dismiss its importance for strong paid social performance. The argument is that with so much noise and chance, there’s no point in trying to understand what makes a winner a winner.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;So it begs the question: are we wasting time analyzing creative performance? Or is it still critical to scaling winners?&amp;nbsp;&lt;/p&gt;



&lt;p&gt;I suppose we should dive in.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-creative-is-king-but-creative-analysis-is-critical&quot;&gt;&lt;strong&gt;Creative is king, but creative analysis is critical&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;We’re all in agreement: creative is the primary lever we have to pull on paid social channels like Meta and TikTok. Every UA manager, Head of Marketing, and founder will tell you the same thing.&lt;br&gt;&lt;br&gt;But if creative is king, that means every aspect of the creative process that goes &lt;em&gt;into&lt;/em&gt; producing a creative is somewhat important. Right?&lt;/p&gt;



&lt;p&gt;Coming up with new creative concepts is important. Testing them is important. And understanding &lt;em&gt;why&lt;/em&gt; certain creatives work and others flop is important too. That’s where &lt;strong&gt;creative analysis&lt;/strong&gt; comes in.&lt;/p&gt;



&lt;p&gt;When it comes to creative analysis, there are really two camps:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-camp-one-the-we-analyze-everything-people&quot;&gt;&lt;strong&gt;Camp one: The we-analyze-everything people&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Camp one is the data-obsessed folk. They’ll dig into every element of a creative. Not just concepts, hooks, and formats, but down to font size, typography, background hue, the speed of transitions — even voiceover volume.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Every variable is fair game.&lt;br&gt;&lt;br&gt;Picture huge spreadsheets, overwhelmingly-detailed naming conventions and, of course, a helping hand from our good friend Chat GPT.&lt;/p&gt;



&lt;p&gt;The idea is: “If we unpack and understand every single detail, we’ll uncover the formula for what makes a winning creative”.&lt;em&gt;&lt;br&gt;&lt;/em&gt;&lt;em&gt;&lt;br&gt;&lt;/em&gt;But is this true?&lt;/p&gt;



&lt;p&gt;Well, first let’s talk about this approach at a high level. A lot of good comes from this approach. &lt;strong&gt;It forces rigor&lt;/strong&gt; — you build processes, generate hypotheses, and feed learnings back into your creative flywheel. And without that final step of feeding learnings back into ideation, you run the risk of turning creative testing into throwing stuff at the wall and seeing what sticks.&lt;/p&gt;



&lt;p&gt;But there are downsides. If you spend too much time obsessing over minute variables, &lt;strong&gt;you risk miscategorizing randomness or trend-driven luck as insights&lt;/strong&gt;. That meme ad didn’t win because the font was blue; it won because the trend was hot and timing was perfect. Next week, the trend dies, and you’re left chasing ghosts.&lt;/p&gt;



&lt;p&gt;It’s also ridiculously &lt;strong&gt;time-consuming&lt;/strong&gt;. You can spend hours dissecting every last detail only to find yourself no closer to better results. Or worse, you start believing that &lt;em&gt;more analysis = a higher win rate&lt;/em&gt;. When in practice, that’s often not the case.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;👇 &lt;strong&gt;A note on randomness&lt;/strong&gt;&lt;br&gt;Randomness plays a bigger role in ad wins than we’d like to admit. Sometimes an intern throws together a quick ad inspired by a new TikTok trend, and that two-hour effort ends up being your top performer for months. Meanwhile, the hundreds of micro-insights you spent hours on barely move the needle.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;It’s not even the 80/20 rule — think more like a 99.9/0.1 rule:&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;99.9% of what you’re analysing won’t change performance in a meaningful way.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;That said, this approach &lt;em&gt;can&lt;/em&gt; pay off. At &lt;a href=&quot;https://www.perceptycs.com/&quot;&gt;Perceptycs&lt;/a&gt;, we’ve found countless winning iterations for our clients by following a rigorous (albeit pretty painful) post-experiment analysis process.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-camp-two-the-why-bother-speculating-people&quot;&gt;&lt;strong&gt;Camp two: The why-bother-speculating people&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;By comparison, the second camp looks at all this and says: &lt;em&gt;forget it.&amp;nbsp;&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;&lt;em&gt;“There are millions of variables in play. You’ll never isolate why something worked. Just keep producing new ideas.”&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;There’s truth here too. The Meta algorithm processes billions of signals, more than we can ever meaningfully analyze. Even if you &lt;strong&gt;think &lt;/strong&gt;you’ve cracked the code, you may just be stifling creativity with arbitrary rules.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Generally, the people in this camp prioritize big swings: fresh concepts, wild angles, better creators, newer trends.&lt;/p&gt;



&lt;p&gt;This &lt;strong&gt;combats the over-analysis trap of camp one&lt;/strong&gt;, and often leads to higher win rates. Fresh ideas drive breakthroughs more often than endless iterations do.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Yes, you can turn an ‘okay’ &lt;a href=&quot;https://www.revenuecat.com/blog/growth/subscription-app-creative-testing/&quot;&gt;creative into a winner by creating variations and improving over time&lt;/a&gt;, but this still isn’t guaranteed. And nothing beats a unicorn concept rising to the top overnight.&lt;/p&gt;



&lt;p&gt;However, there are of course downsides to this approach too.&lt;strong&gt; If you never look back, you miss chances to turn ‘okay’ ads into winners.&lt;/strong&gt; There have been many many occasions where careful iteration (refining a promising format, swapping angles, tweaking hooks) transformed average performers into consistent long-term winners — without analysis, you leave that opportunity on the table.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-a-balanced-approach-to-creative-testing-nbsp&quot;&gt;&lt;strong&gt;A balanced approach to creative testing&amp;nbsp;&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Like anything in the app world, the answer isn’t clearcut. Neither of these camps are ‘correct’. For most teams, I think the best approach sits in the middle — avoid analysis paralysis, without ignoring the lessons you can learn from creative retros.&lt;/p&gt;



&lt;p&gt;Start by asking yourself three questions:&lt;/p&gt;



&lt;p&gt;1.&amp;nbsp; How much can we act on immediately?&lt;br&gt;2. What is likely to have the largest impact if we do act on it?&lt;br&gt;3. What new hypotheses do we have?&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-how-much-can-we-act-on-immediately&quot;&gt;&lt;strong&gt;1. How much can we act on immediately?&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Any single insight can usually be acted on pretty quickly. Spot a new hook that’s outperforming others? Spin up more variants. Notice a static format that’s working? Brief a few iterations this week. Easy.&lt;/p&gt;



&lt;p&gt;But when you stack up dozens (or hundreds) of micro-insights, things get unmanageable. You’ll never test them all. Which begs the question: &lt;strong&gt;why spend hours digging into variables you’ll never act on?&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Chances are, if you’re doing things right, you’ll naturally default to the highest-impact variables anyway: concepts, hooks, creators, formats, angles.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Of course, how much you can act on depends heavily on resources. If you’re running thousands of active ads at any one time, you can afford to get more granular because you actually have the bandwidth to follow through. But if you’re testing 30 creatives a month, you’ll drown if you try to chase every variable. In that scenario, you’re better off sticking to the core drivers and leaving the font-size-and-color debates for someone with unlimited production capacity.&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-Z1tp4zk wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Pro tip&quot; text=&quot;&lt;p&gt;Check out &lt;a href=&amp;quot;https://www.revenuecat.com/blog/growth/subscription-app-creative-testing/&amp;quot;&gt;this blog&lt;/a&gt; from David Vargas for three well-rounded creative testing frameworks, based on different resource levels.&amp;nbsp;&lt;/p&gt;&quot; icon=&quot;bulb&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-what-is-likely-to-have-the-largest-impact&quot;&gt;&lt;strong&gt;2. What is likely to have the largest impact?&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;This is where prioritisation comes in. For most teams, the big levers are:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Concepts&lt;/li&gt;



&lt;li&gt;Hooks&lt;/li&gt;



&lt;li&gt;Creators&lt;/li&gt;



&lt;li&gt;Formats&lt;/li&gt;



&lt;li&gt;Angles (value proposition)&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;These are the variables you can reliably experiment with to drive consistent improvements over time.&lt;br&gt;&lt;br&gt;Yes, smaller tweaks: font color, typography, background music volume etc. can sometimes produce a bump. And if you’ve already seen a granular change make a clear difference in your own data, it’s probably worth testing further. But &lt;strong&gt;those cases are the exception, not the rule&lt;/strong&gt;. There’s only so many font tests you can run before you hit diminishing or zero returns.&lt;br&gt;&lt;br&gt;You don’t want to waste cycles chasing micro-variables when it’s the big levers that consistently shape outcomes. While it’s tempting to get lost in the weeds, [for the majority of teams] time is better spent sticking to the levers that reliably move performance.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-what-new-hypotheses-do-we-have&quot;&gt;&lt;strong&gt;3. What new hypotheses do we have?&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Creative analysis only matters if it produces testable hypotheses. Otherwise, you’re just collecting trivia.&lt;/p&gt;



&lt;p&gt;Your thought process might look like this:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Funny hooks outperformed serious ones in the last test → let’s produce a batch of ads with different funny hooks and see if this holds true&lt;/li&gt;



&lt;li&gt;A creative with a bold font color suddenly spiked performance → let’s test a few more color variations to validate whether it’s a fluke or a lever&lt;/li&gt;



&lt;li&gt;Every winning ad last month featured a bright yellow t-shirt → let’s hypothesise that high-contrast clothing improves thumb-stopping power and run variants to test it&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;That’s how you &lt;strong&gt;turn observation into structured experimentation&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;But be warned: there’s a slippery slope of leaning too heavily on the ‘because’. Maybe a yellow t-shirt works because it’s high-contract, sure. But maybe it was another reason, or one of a thousand possible reasons — or coincidence.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Unless you’ve seen something validated repeatedly across multiple tests, treat your ‘because’ as speculation, not gospel.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;I recommend writing down your assumptions each time, and even gathering multiple interpretations from your team. Different people will be inclined to favour different reasonings, and that diversity of thought can spark stronger hypotheses.&lt;/p&gt;



&lt;p&gt;Document, hypothesise, test. But keep your conclusions humble until the data proves them out.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-ad-creative-retros-in-practice&quot;&gt;&lt;strong&gt;Ad creative retros in practice&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Not all retros are created equal. I recommend teams have two types of retros.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Short-term retros&lt;/strong&gt; (end of each test cycle) that stay focused on the big levers: concepts, hooks, creators, formats, angles. These are the variables you can act on &lt;em&gt;immediately &lt;/em&gt;— get new briefs written, spin up new iterations, and roll into the next testing cycle. Keep it tight, keep it actionable.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Larger retros &lt;/strong&gt;(monthly, quarterly, even biannual) are deep-dives that give you the chance to zoom out across dozens or even hundreds of ads — revealing emerging patterns that are invisible in the short term.&lt;/p&gt;



&lt;p&gt;Maybe all your sustained winners from the past three months shared the same storyboard structure. Maybe every underperformer came from the same creator. Maybe funny hooks consistently lag behind serious ones. These aren’t one-off quirks, they’re validated trends.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;The bigger the dataset, the stronger the conclusion.&lt;/strong&gt; With more data, your insights carry more weight and are less likely to be the result of randomness or a fleeting trend. This is where you can form more solid, evidence-backed opinions about &lt;em&gt;why&lt;/em&gt; something works, and bake those into strategy with confidence.&lt;/p&gt;



&lt;p&gt;Short-term retros keep your testing cycle sharp. Larger retros help you identify structural truths about your creative performance and guide long-term strategy. You need both.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-are-you-wasting-time-analyzing-creative-tests&quot;&gt;&lt;strong&gt;Are you wasting time analyzing creative tests?&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The short answer is no. The a-little-longer answer is &lt;em&gt;not if you strike the right balance&lt;/em&gt;.&lt;/p&gt;



&lt;p&gt;Analyze too little, and you’re just throwing ideas at the wall. Analyze too much, and you risk drowning in data that doesn’t matter.&lt;/p&gt;



&lt;p&gt;Instead, aim for insight-driven efficiency:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Only consider what’s actionable based on your available resources&lt;/li&gt;



&lt;li&gt;Prioritize variables that are most likely to drive big swings&lt;/li&gt;



&lt;li&gt;Generate hypotheses and test them, but don’t over-trust your ‘because’&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;By anchoring your process like this, you’ll build a creative loop that produces winners consistently, without burning your team out or wasting weeks chasing the wrong variables.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[What makes an app worth buying? Lessons from BlueThrone’s shift from volume to value]]></title><description><![CDATA[BlueThrone’s Josh Peleg shares what app buyers really value today — from predictable recurring revenue to the marketing moats driving seven-figure exits.]]></description><link>https://www.revenuecat.com/blog/engineering/josh-peleg-bluethrone-sub-club-podcast-2025/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/josh-peleg-bluethrone-sub-club-podcast-2025/</guid><pubDate>Wed, 15 Oct 2025 10:53:22 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/josh-peleg-bluethrone-sub-club-podcast-2025.png" length="0" type="image/*"/><content:encoded>&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;if-youre-building-an-app-today-theres-a-good-chance-youve-thought-about-selling-it&quot;&gt;If you’re building an app today, there’s a good chance you’ve thought about selling it.&lt;/h3&gt;



&lt;p&gt;But what actually makes an app attractive to buyers — and what mistakes can cost you the deal?&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://subclub.com/episode/buying-vs-building-scaling-beyond-a-single-app-josh-peleg-bluethrone&quot;&gt;This week on the Sub Club podcast&lt;/a&gt;, I sat down with &lt;strong&gt;&lt;a href=&quot;https://www.linkedin.com/in/joshpeleg/&quot;&gt;Josh Peleg&lt;/a&gt;&lt;/strong&gt;, Head of Business Development and M&amp;amp;A at &lt;strong&gt;&lt;a href=&quot;https://bluethrone.io/&quot;&gt;BlueThrone&lt;/a&gt;&lt;/strong&gt;, one of the world’s leading app acquirers. Josh shared how BlueThrone evolved from buying hundreds of small utility apps to focusing on a few high-performing category leaders, and what founders can learn from that journey.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;Buying vs. Building: Scaling Beyond a Single App — Josh Peleg, BlueThrone&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/T3YIc-clWo0?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;iframe loading=&quot;lazy&quot; width=&quot;100%&quot; height=&quot;180&quot; frameborder=&quot;no&quot; scrolling=&quot;no&quot; seamless=&quot;&quot; src=&quot;https://share.transistor.fm/e/9314ae4a?color=FFFFFF&amp;amp;background=30343C&quot;&gt;&lt;/iframe&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-downside-of-a-go-wide-approach&quot;&gt;&lt;strong&gt;The downside of a “go-wide” approach&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Early on, BlueThrone took a “go-wide” approach — acquiring dozens of simple utility apps like flashlight and QR scanner tools. The model generated quick cash, but those shallow apps lost traction fast.&lt;/p&gt;



&lt;p&gt;That experience led to what Josh calls &lt;em&gt;BlueThrone 2.0&lt;/em&gt;: a more focused model built around &lt;strong&gt;depth rather than volume&lt;/strong&gt;. Today, the company only acquires apps with proven product-market fit, organic growth, and strong retention.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-evolving-your-playbook&quot;&gt;&lt;strong&gt;Evolving your playbook&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Josh also shared what makes an app &lt;em&gt;acquisition-ready&lt;/em&gt;. The biggest lever: &lt;strong&gt;predictable recurring revenue&lt;/strong&gt;. Buyers consistently value subscriptions that renew month after month more highly than ad-based or one-time-purchase models.&lt;/p&gt;



&lt;p&gt;He cautioned against founders trying to inflate numbers before a sale — such as running short-term promotions to “pump” revenue — since those tactics tend to backfire during due diligence. Buyers want to see sustainable, repeatable performance, not temporary spikes.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-beyond-the-numbers&quot;&gt;Beyond the numbers&lt;/h2&gt;



&lt;p&gt;As AI accelerates development and lowers technical barriers, &lt;strong&gt;marketing has become the new competitive moat&lt;/strong&gt;. The founders landing meaningful exits today aren’t just strong builders — they’re marketers who know how to create community and drive organic growth.&lt;/p&gt;



&lt;p&gt;Josh and David also explored the rise of &lt;strong&gt;hybrid monetization&lt;/strong&gt;, borrowing ideas from gaming — such as consumables, day passes, and rewarded ads — to capture more value from users who might never subscribe. It’s a playbook that’s starting to define the next generation of consumer apps.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-takeaway&quot;&gt;The takeaway&lt;/h2&gt;



&lt;p&gt;Whether you’re an indie developer dreaming of your first exit or a growth-stage founder optimizing for long-term value, this episode offers a rare inside look at how modern app acquisitions really work — and what it takes to build a business that buyers can’t ignore.&lt;/p&gt;


&lt;div class=&quot;lazyblock-dd0db17b8671-Z29uRAQ wp-block-lazyblock-dd0db17b8671&quot;&gt;&lt;blogpostpodcastcta title=&quot;Buying vs. Building: Scaling Beyond a Single App — Josh Peleg, BlueThrone&quot; description=&quot;On the podcast: red flags that tank app valuations, why subscription-only apps are leaving money on the table, and how bootstrapped founders are cashing out for millions in months, not years.&quot; links=&quot;[{&amp;quot;link-title&amp;quot;:&amp;quot;YouTube&amp;quot;,&amp;quot;link-url&amp;quot;:&amp;quot;https:\/\/www.youtube.com\/watch?v=T3YIc-clWo0&amp;quot;,&amp;quot;link-image&amp;quot;:&amp;quot;youtube&amp;quot;},{&amp;quot;link-title&amp;quot;:&amp;quot;Spotify&amp;quot;,&amp;quot;link-url&amp;quot;:&amp;quot;https:\/\/open.spotify.com\/show\/6jmxautTyDTjwqRYyg9BXF&amp;quot;,&amp;quot;link-image&amp;quot;:&amp;quot;spotify&amp;quot;},{&amp;quot;link-title&amp;quot;:&amp;quot;Apple&amp;quot;,&amp;quot;link-url&amp;quot;:&amp;quot;https:\/\/podcasts.apple.com\/us\/podcast\/feed\/id1538057974?ls=1&amp;quot;,&amp;quot;link-image&amp;quot;:&amp;quot;apple-podcasts&amp;quot;}]&quot;&gt;
&lt;/blogpostpodcastcta&gt;&lt;/div&gt;

&lt;div class=&quot;lazyblock-dd0db17b8671-2ayWif wp-block-lazyblock-dd0db17b8671&quot;&gt;&lt;blogpostpodcastcta title=&quot;Join the Sub Club&quot; description=&quot;Interviews and playbooks from the minds behind the world&apos;s biggest apps.&quot; links=&quot;[{&amp;quot;link-title&amp;quot;:&amp;quot;Spotify&amp;quot;,&amp;quot;link-url&amp;quot;:&amp;quot;https:\/\/open.spotify.com\/show\/6jmxautTyDTjwqRYyg9BXF&amp;quot;,&amp;quot;link-image&amp;quot;:&amp;quot;spotify&amp;quot;},{&amp;quot;link-title&amp;quot;:&amp;quot;Apple Podcasts&amp;quot;,&amp;quot;link-url&amp;quot;:&amp;quot;https:\/\/podcasts.apple.com\/gb\/podcast\/sub-club-by-revenuecat\/id1538057974&amp;quot;,&amp;quot;link-image&amp;quot;:&amp;quot;apple-podcasts&amp;quot;},{&amp;quot;link-title&amp;quot;:&amp;quot;YouTube&amp;quot;,&amp;quot;link-url&amp;quot;:&amp;quot;https:\/\/www.youtube.com\/@SubClubPodcast&amp;quot;,&amp;quot;link-image&amp;quot;:&amp;quot;youtube&amp;quot;}]&quot;&gt;
&lt;/blogpostpodcastcta&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[Shipaton 2025 Winners]]></title><description><![CDATA[Announcing the winners of 2025 Shipaton]]></description><link>https://www.revenuecat.com/blog/company/shipaton-2025-winners/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/company/shipaton-2025-winners/</guid><pubDate>Mon, 13 Oct 2025 13:57:51 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/hackathon-blog-header-blue.jpg" length="0" type="image/*"/><content:encoded>&lt;p&gt;This year’s Shipaton brought together tens of thousands of participants from around the world, who collectively submitted 812 projects.&lt;/p&gt;



&lt;p&gt;The results once again highlight what makes this community unique: rapid iteration, creative monetization, and a commitment to building valuable products that reach real users.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Now, as we celebrate the incredible creativity and effort that defined this year’s event, it’s time to reveal the winners of Shipaton 2025 — and for some of them, the celebration has already gone public. People have begun spotting Shipaton apps lighting up on billboards in New York:&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-rich is-provider-twitter wp-block-embed-twitter&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;blockquote class=&quot;twitter-tweet&quot; data-width=&quot;500&quot; data-dnt=&quot;true&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;Nothing like waking up and getting blasted in the face by &lt;a href=&quot;https://twitter.com/RevenueCat?ref_src=twsrc%5Etfw&quot;&gt;@RevenueCat&lt;/a&gt; shipaton winners 🤣 &lt;a href=&quot;https://twitter.com/hashtag/shipaton?src=hash&amp;amp;ref_src=twsrc%5Etfw&quot;&gt;#shipaton&lt;/a&gt; &lt;a href=&quot;https://t.co/95fHQXW0GK&quot;&gt;pic.twitter.com/95fHQXW0GK&lt;/a&gt;&lt;/p&gt;— Dan Fahey (@SuperFlyDan) &lt;a href=&quot;https://twitter.com/SuperFlyDan/status/1977665362486595939?ref_src=twsrc%5Etfw&quot;&gt;October 13, 2025&lt;/a&gt;&lt;/blockquote&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-grand-prize-build-amp-grow-award&quot;&gt;Grand Prize: Build &amp;amp; Grow Award&lt;/h2&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-judging-criteria&quot;&gt;Judging criteria&lt;/h3&gt;



&lt;p&gt;The Grand Prize recognizes the single best overall submission across all categories. Judges evaluated projects for:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Innovation&lt;/strong&gt;: Does the app bring a novel idea, feature, or use case to the market?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Execution&lt;/strong&gt;: Is the implementation polished, stable, and visually cohesive?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Feasibility&lt;/strong&gt;: Could the app realistically launch and scale beyond the hackathon?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Integration&lt;/strong&gt;: Does it make effective use of the required SDKs and APIs?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;This award represents the complete package: a project that balances ambition with real-world potential.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1st-place-payout&quot;&gt;1st Place: &lt;a href=&quot;https://revenuecat-shipaton-2025.devpost.com/submissions/762703-payout&quot;&gt;Payout&lt;/a&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;805&quot; height=&quot;573&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-33.png&quot; alt=&quot;&quot; class=&quot;wp-image-46794&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-33.png 805w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-33-300x214.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-33-768x547.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-33-50x36.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-33-56x40.png 56w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-33-652x464.png 652w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-33-696x495.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-33-560x399.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-33-416x296.png 416w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-33-663x472.png 663w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-33-80x57.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-33-48x34.png 48w&quot; sizes=&quot;auto, (max-width: 805px) 100vw, 805px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;a href=&quot;https://apps.apple.com/us/app/payout-claim-make-them-pay/id6748968935?ppid=7cf6e543-88e2-4ef2-96c0-90fc9d7cb9fb&quot;&gt;App Store&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://play.google.com/store/apps/details?id=com.payout.app&quot;&gt;Play Store&amp;nbsp;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Payout took the top spot in Shipaton 2025 for both its technical audacity and tangible real-world impact. The app helps users discover class-action settlements they may already qualify for — transforming an obscure, paperwork-heavy process into something transparent, automated, and accessible. Millions of dollars in class-action payouts go unclaimed every year simply because consumers never hear about them, or don’t realize they’re eligible. Payout surfaces these opportunities in plain English, estimates potential compensation, and sends real-time notifications when new settlements open. In doing so, it makes the idea of ‘checking for class-action cash’ as routine as checking a bank balance — no law degree required.&lt;/p&gt;



&lt;p&gt;What truly set Payout apart was how it was built. The entire app — design, code, and assets — was produced through AI-assisted development using Claude Code and Cursor. Not a single line of code was written by hand.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Payout’s numbers are also impressive with over 17,000 users, $30,017 in revenue, and 1,750 paying subscribers, supported by more than 500,000 impressions across social media.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-buildinpublic-award&quot;&gt;&lt;strong&gt;#BuildInPublic Award&lt;/strong&gt;&lt;/h2&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-judging-criteria-0&quot;&gt;&lt;strong&gt;Judging criteria&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The #BuildInPublic Award celebrates teams that shared their journey openly and used community feedback to improve their apps. Judges evaluated:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Transparency and storytelling&lt;/strong&gt;: How well did participants communicate their process, wins, and challenges?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Engagement&lt;/strong&gt;: Did public sharing generate useful discussion or inspire others?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Learning and iteration&lt;/strong&gt;: Did feedback from the public meaningfully improve the app’s design, features, or messaging?&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1st-place-gurwi-learn-anything&quot;&gt;&lt;strong&gt;1st Place: &lt;/strong&gt;&lt;a href=&quot;https://revenuecat-shipaton-2025.devpost.com/submissions/760246-gurwi-learn-anything&quot;&gt;&lt;strong&gt;Gurwi – Learn Anything&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;544&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-34-1024x544.png&quot; alt=&quot;&quot; class=&quot;wp-image-46796&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-34-1024x544.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-34-300x159.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-34-768x408.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-34.png 2048w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;a href=&quot;https://apps.apple.com/app/id6737016341&quot;&gt;App Store&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://play.google.com/store/apps/details?id=com.gurwi&quot;&gt;Play Store&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Gurwi came from frustration with Colombia’s struggling education system and one founder’s determination to fix it. After graduating from high school in Riohacha — one of the country’s poorest regions — founder &lt;strong&gt;Camilo Peñalver&lt;/strong&gt; realized how unprepared he was for adult life. Years of self-teaching led him to a pivotal insight: the real gap wasn’t motivation, but access. Education needed to be reimagined for clarity, practicality, and scale. When his &lt;a href=&quot;https://x.com/camilopenalver/status/1941188493595771127&quot;&gt;video proposing an app “to learn anything”&lt;/a&gt; went viral with over 200,000 views, the mission became clear — build a mobile platform that teaches what traditional systems overlook.&lt;/p&gt;



&lt;p&gt;Gurwi turns learning into an engaging, visual, and multilingual experience. Each lesson is interactive and structured around short, 10–15 minute modules that replace long videos and PDFs with a dynamic page-by-page format. Users tap through content filled with images, animations, and questions, earning points and streaks as they go. Lessons can be played aloud, paused, or adjusted for speed and are available in Spanish, English, and Portuguese. Beneath that simplicity lies an ambitious engineering effort: a custom .gurwi file format for rendering lessons, a companion content editor called &lt;strong&gt;Gurwi Educators&lt;/strong&gt;, and a robust backend built with Flutter, Supabase, and PostgreSQL.&lt;/p&gt;



&lt;p&gt;Developed by a two-person team under immense personal and financial pressure, Gurwi has already reached &lt;strong&gt;over 13,000 users&lt;/strong&gt; and earned &lt;strong&gt;more than 1,000 app store reviews&lt;/strong&gt; with an average &lt;strong&gt;4.9 rating&lt;/strong&gt;. Gurwi is a prime example of what you can achieve when Building in Public.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-rich is-provider-twitter wp-block-embed-twitter&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;blockquote class=&quot;twitter-tweet&quot; data-width=&quot;500&quot; data-dnt=&quot;true&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;Introducing Gurwi&lt;br&gt;&lt;br&gt;The app that&apos;s here to change how knowledge is created and shared — and with it, we’ll win the &lt;a href=&quot;https://twitter.com/RevenueCat?ref_src=twsrc%5Etfw&quot;&gt;@RevenueCat&lt;/a&gt; &lt;a href=&quot;https://twitter.com/hashtag/Shipaton?src=hash&amp;amp;ref_src=twsrc%5Etfw&quot;&gt;#Shipaton&lt;/a&gt;.&lt;br&gt;&lt;br&gt;Time to go full-on &lt;a href=&quot;https://twitter.com/hashtag/BuildInPublic?src=hash&amp;amp;ref_src=twsrc%5Etfw&quot;&gt;#BuildInPublic&lt;/a&gt;! &lt;a href=&quot;https://t.co/nJFs7V5lUZ&quot;&gt;pic.twitter.com/nJFs7V5lUZ&lt;/a&gt;&lt;/p&gt;— Camilo Peñalver (@camilopenalver) &lt;a href=&quot;https://twitter.com/camilopenalver/status/1941188493595771127?ref_src=twsrc%5Etfw&quot;&gt;July 4, 2025&lt;/a&gt;&lt;/blockquote&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2nd-place-echo-reminder&quot;&gt;&lt;strong&gt;2nd Place: &lt;/strong&gt;&lt;a href=&quot;https://revenuecat-shipaton-2025.devpost.com/submissions/773491-echo-reminder&quot;&gt;&lt;strong&gt;Echo Reminder&lt;/strong&gt;&lt;/a&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;Shipaton 2025: Echo Reminder, Voice ToDo Lists&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/xGh3FqCjn3U?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;&lt;a href=&quot;https://apps.apple.com/us/app/echo-reminder-voice-todo-list/id6752544263&quot;&gt;App Store&amp;nbsp;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Echo Reminder rethinks how people capture thoughts on the go. Developer &lt;strong&gt;Luca&lt;/strong&gt; wanted a faster, more natural way to set reminders — something between voice notes and traditional task apps. Instead of tapping through menus or relying on Siri’s often clumsy transcription, Echo lets users simply speak. The app automatically parses voice input into structured reminders — titles, times, and repeat schedules — making it effortless to stay organized mid-conversation, mid-commute, or mid-idea.&lt;/p&gt;



&lt;p&gt;The app’s clean design and intuitive voice interface are powered by React Native and Expo, using Supabase for data sync and an Express backend with Whisper and GPT-5-mini for transcription and structured parsing. Despite being the team’s first iOS release, Echo shipped successfully and now provides fast, accurate voice scheduling that feels native to how people actually think and talk.&lt;/p&gt;



&lt;p&gt;What made Echo stand out was how transparently it was built. Luca and Sydney fully embraced the &lt;strong&gt;#BuildInPublic&lt;/strong&gt; mindset, sharing their journey across &lt;a href=&quot;https://www.tiktok.com/@lukato.io&quot;&gt;TikTok&lt;/a&gt;, &lt;a href=&quot;https://www.instagram.com/lukato.io/&quot;&gt;Instagram&lt;/a&gt;, &lt;a href=&quot;https://www.youtube.com/@lukatoio&quot;&gt;YouTube&lt;/a&gt;, and &lt;a href=&quot;https://x.com/KatoLuca&quot;&gt;X&lt;/a&gt;. Each post documented not just progress, but process — from feature updates and design challenges to moments of uncertainty and breakthrough. Their authentic storytelling earned organic engagement, reconnecting them with old friends, and drawing in new followers.&lt;/p&gt;



&lt;p&gt;They even took “building in public” offline, working from coffee shops to observe firsthand how people interacted with the app. These real-world insights revealed small but impactful issues — keyboards that didn’t dismiss properly, unclear voice prompts — which led to onboarding improvements and more intuitive flows.&lt;/p&gt;



&lt;p&gt;Their top three shared moments perfectly capture the energy of their journey: &lt;a href=&quot;https://www.instagram.com/reel/DNoLkScJbMC/&quot;&gt;Video 1&lt;/a&gt;, &lt;a href=&quot;https://www.instagram.com/reel/DN4UYIpCTg3/&quot;&gt;Video 2&lt;/a&gt;, and &lt;a href=&quot;https://www.instagram.com/reel/DOxSqYkDqED/&quot;&gt;Video 3&lt;/a&gt;.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3rd-place-tomo-japan&quot;&gt;&lt;strong&gt;3rd Place: &lt;/strong&gt;&lt;a href=&quot;https://revenuecat-shipaton-2025.devpost.com/submissions/760277-tomo-japan&quot;&gt;&lt;strong&gt;Tomo Japan&lt;/strong&gt;&lt;/a&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;Tomo Japan RevenueCat Shipaton Submission Video&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/j_n3MH4-bWk?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;&lt;a href=&quot;https://apps.apple.com/us/app/tomo-japan/id6752227712&quot;&gt;App Store&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Tomo Japan is both a travel companion and a personal milestone. After five years in finance, the developer taught himself iOS development with a single goal: build a Japan itinerary app. Their first attempt years ago never made it past the UI stage, but Shipaton became the moment to finish what they started. The result, Tomo Japan (‘Tomodachi’ meaning ‘friend’ in Japanese), brings that journey full circle: from learning to code to launching a polished, Swift-native app that helps others experience Japan.&lt;/p&gt;



&lt;p&gt;Designed as a friendly, curated guide, Tomo Japan helps travelers navigate Japan’s rich but often overwhelming travel landscape. The app features handpicked destinations, detailed city guides, seasonal highlights, itineraries, and local gems that rarely appear in mainstream guidebooks.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Under the hood, Tomo Japan showcases thoughtful technical craftsmanship. Built entirely in SwiftUI, it leverages Firebase for data storage, authentication, and photos, while Supabase serves as a validation and content management layer before data is automated into Firestore. Beyond the code, the project’s success was amplified by daily #BuildInPublic updates across &lt;a href=&quot;https://x.com/tammyho52&quot;&gt;X&lt;/a&gt; and &lt;a href=&quot;https://www.tiktok.com/@tomojapanapp&quot;&gt;TikTok&lt;/a&gt;. Judges also loved the detailed and useful &lt;a href=&quot;https://medium.com/@th52&quot;&gt;Medium posts the developer published as part of the project&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-revenuecat-design-award&quot;&gt;&lt;strong&gt;RevenueCat Design Award&lt;/strong&gt;&lt;/h2&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-judging-criteria-1&quot;&gt;&lt;strong&gt;Judging criteria&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The Design Award celebrates craftsmanship and creativity. Judges looked for:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Innovation&lt;/strong&gt;: Fresh ideas in UX or visual systems&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Aesthetic quality&lt;/strong&gt;: Beautiful, intuitive interfaces that spark delight&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Experience&lt;/strong&gt;: Smooth gestures, satisfying animations, and clear feedback loops&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1st-place-dayloop-everyday-timelapse&quot;&gt;&lt;strong&gt;1st Place: &lt;/strong&gt;&lt;a href=&quot;https://revenuecat-shipaton-2025.devpost.com/submissions/760256-dayloop-everyday-timelapse&quot;&gt;&lt;strong&gt;Dayloop: Everyday Timelapse&lt;/strong&gt;&lt;/a&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;Dayloop: Everyday Timelapse&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/vGQ2Mi9RiFc?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;&lt;a href=&quot;https://apps.apple.com/app/id6740197860&quot;&gt;App Store&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Dayloop turns your everyday moments into cinematic timelapse videos — no editing skills required. Whether it’s a year of selfies, a fitness transformation, pregnancy progress, or your pet growing up, the app automatically aligns portraits and compiles them into a smooth, beautiful animation. With features like Auto Face Alignment, a Ghost Photo overlay for perfect framing, and a playful timeline slider, Dayloop makes visual storytelling effortless and deeply personal.&lt;/p&gt;



&lt;p&gt;Built in Swift and SwiftUI using Apple’s Vision Framework, Dayloop focuses on precision, privacy, and delight. Photos remain local to the device, ensuring data never leaves the user’s hands. Behind its pretty interface are countless hours spent debugging orientation bugs, managing memory, and fine-tuning image alignment to make the experience feel seamless.&lt;/p&gt;



&lt;p&gt;Since launch, Dayloop has resonated across use cases and audiences, from fitness enthusiasts to parents to creators documenting daily life. The developer’s next focus is on growth — testing niche marketing campaigns, adding camera and export enhancements, and expanding into new languages.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2nd-place-skillme&quot;&gt;&lt;strong&gt;2nd Place: &lt;/strong&gt;&lt;a href=&quot;https://revenuecat-shipaton-2025.devpost.com/submissions/777541-skillme&quot;&gt;&lt;strong&gt;SkillMe&lt;/strong&gt;&lt;/a&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;Can Design Be Invisible? - Ship A Ton 2025 Submission&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/GM9jR3jWIko?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;&lt;a href=&quot;https://apps.apple.com/de/app/skillme-learn-any-skill/id6749891663&quot;&gt;App Store&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;SkillMe helps you learn any skill — one daily challenge at a time. From cooking to coding to handstands, the app breaks down any goal into personalized, step-by-step exercises powered by AI. Users set their goal, take a quick self-assessment, and instantly receive a tailored learning plan with daily challenges, progress tracking, and motivational reminders. Each challenge includes clear instructions, difficulty levels, and expected outcomes, making improvement feel achievable and consistent.&lt;/p&gt;



&lt;p&gt;Built for iPhone in SwiftUI, SkillMe’s AI system dynamically generates challenges and even adapts the paywall copy to each user’s chosen goal — encouraging them with context-specific nudges like “Don’t lose your progress on becoming the next Gordon Ramsay” or “You’re one daily challenge away from turning the world upside down.”&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3rd-place-pitchlab-professional-grade-baseball-pitch-tracking&quot;&gt;&lt;strong&gt;3rd Place: &lt;/strong&gt;&lt;a href=&quot;https://revenuecat-shipaton-2025.devpost.com/submissions/760353-pitchlab-professional-grade-baseball-pitch-tracking&quot;&gt;&lt;strong&gt;PitchLab: Professional-Grade Baseball Pitch Tracking&lt;/strong&gt;&lt;/a&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;Introducing PitchLab 1.0 - Professional grade pitch analysis using just your iPhone camera.&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/gZITndtsZbo?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;&lt;a href=&quot;https://apps.apple.com/us/app/pitchlab-baseball/id6738223162&quot;&gt;App Store&amp;nbsp;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;PitchLab turns an iPhone into a professional-grade pitch tracking system — delivering analytics once limited to $20,000 radar setups. Built by a professional pitcher who spent years relying on those tools to reach the Major Leagues, PitchLab democratizes access to elite-level pitching data for athletes at every level. Using only a single camera, the app measures velocity, spin rate, spin axis, induced break, and pitch location with near-radar accuracy.&lt;/p&gt;



&lt;p&gt;Under the hood, PitchLab blends computer vision, deep learning, and physics modeling into a streamlined, real-time system. A custom-trained neural network tracks baseballs in flight; a physics engine reconstructs 3D trajectories; and CoreML enables smooth, on-device inference at up to 60 frames per second. As a testament to its accuracy, the app is already in use by collegiate programs, training facilities, and MLB organizations.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-buzziest-launch-award&quot;&gt;&lt;strong&gt;Buzziest Launch Award&lt;/strong&gt;&lt;/h2&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-judging-criteria-2&quot;&gt;&lt;strong&gt;Judging criteria&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;This category spotlights the most creative, high-energy launches. Judges considered:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Visibility&lt;/strong&gt;: How effectively the team promoted their app across channels&lt;br&gt;&lt;strong&gt;Creativity&lt;/strong&gt;: Use of unique stunts, videos, or storytelling that captured attention&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Engagement&lt;/strong&gt;: Measurable or anecdotal buzz from the hackathon community and beyond&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1st-place-readhim&quot;&gt;&lt;strong&gt;1st Place: &lt;/strong&gt;&lt;a href=&quot;https://revenuecat-shipaton-2025.devpost.com/submissions/785932-readhim&quot;&gt;&lt;strong&gt;ReadHim&lt;/strong&gt;&lt;/a&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;806&quot; height=&quot;538&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-38.png&quot; alt=&quot;&quot; class=&quot;wp-image-46804&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-38.png 806w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-38-300x200.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-38-768x513.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-38-50x33.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-38-60x40.png 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-38-696x465.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-38-560x374.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-38-443x296.png 443w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-38-707x472.png 707w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-38-80x53.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-38-48x32.png 48w&quot; sizes=&quot;auto, (max-width: 806px) 100vw, 806px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;a href=&quot;https://apps.apple.com/us/app/readhim/id6751736922&quot;&gt;App Store&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;ReadHim was designed to make the buzziest launch of Shipaton 2025. With less than a month to ideate, build, and market their first-ever App Store release, co-founders Jay and Joseph went all-in on an idea they knew would spark conversation. The app gives women a data-driven way to decode romantic text conversations — analyzing tone, patterns, and red flags to help them understand a partner’s true intentions. By uploading screenshots, users receive a report powered by OCR and a fine-tuned GPT-OSS-120B model that detects manipulation patterns, interprets romantic intent, and even suggests what to text next.&lt;/p&gt;



&lt;p&gt;Through viral marketing, the team grew an Instagram meme account that amassed over 5.2 million views, partnered with a TikTok influencer with over 2.3M TikTok followers, and executed a creative stunt featuring supercars and a robot dog promoting the app downtown. In just ten days, ReadHim achieved $1,100 in MRR.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2nd-place-shutter-declutter-photo-cleaner&quot;&gt;&lt;strong&gt;2nd Place: &lt;/strong&gt;&lt;a href=&quot;https://revenuecat-shipaton-2025.devpost.com/submissions/797661-shutter-declutter-photo-cleaner&quot;&gt;&lt;strong&gt;Shutter Declutter: Photo Cleaner&lt;/strong&gt;&lt;/a&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;806&quot; height=&quot;537&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-39.png&quot; alt=&quot;&quot; class=&quot;wp-image-46806&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-39.png 806w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-39-300x200.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-39-768x512.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-39-50x33.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-39-60x40.png 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-39-696x464.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-39-560x373.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-39-444x296.png 444w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-39-708x472.png 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-39-80x53.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-39-48x32.png 48w&quot; sizes=&quot;auto, (max-width: 806px) 100vw, 806px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;a href=&quot;https://apps.apple.com/us/app/shutter-declutter-pic-cleaner/id6745152835&quot;&gt;App Store&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Shutter Declutter turns photo cleanup into a daily ritual instead of a dreaded chore. The idea came after the developer hit the familiar ‘iPhone Storage Full’ notification, and realized that deleting thousands of photos at once was overwhelming.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Shutter Declutter makes tidying your camera roll simple and satisfying: each day, it shows you photos taken on that date in past years, and you swipe to delete the ones you don’t want — just like Tinder, but for your photos.&lt;/p&gt;



&lt;p&gt;The app’s launch was a breakout success. Downloads surged after early grassroots marketing: social media posts, cold emails, posters around town, and even getting featured in The Verge. It reached thousands of active users and over 1,000 paying subscribers, driven largely by organic, word-of-mouth growth.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3rd-place-memolune&quot;&gt;&lt;strong&gt;3rd Place: &lt;/strong&gt;&lt;a href=&quot;https://revenuecat-shipaton-2025.devpost.com/submissions/811645-memolune&quot;&gt;&lt;strong&gt;MemoLune&lt;/strong&gt;&lt;/a&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;539&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-40-1024x539.png&quot; alt=&quot;&quot; class=&quot;wp-image-46808&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-40-1024x539.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-40-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-40-768x404.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-40-1536x809.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-40-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-40-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-40-696x366.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-40-560x296.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-40-840x442.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-40-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-40-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-40.png 1998w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;a href=&quot;https://apps.apple.com/jp/app/%E3%83%A1%E3%83%A2%E3%82%8B%E3%82%93-memolune/id6752797808&quot;&gt;App Store&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;MemoLune captures the simplicity of jotting a thought as naturally as sending a message. The idea came when the developer noticed a friend using a one-person group chat just to leave memos; an act so simple, it felt like the right model for a better note-taking app. They set out to build MemoLune over 100 consecutive days, turning the process into a story itself.&lt;/p&gt;



&lt;p&gt;The result is a lightweight, multilingual memo app that blends voice input, OCR, and chat-like design to make capturing ideas effortless. Users can speak, snap photos, or type their thoughts, with instant transcription and text extraction. Notes can be revisited via a calendar view, helping users rediscover what they were thinking on any given day.&lt;/p&gt;



&lt;p&gt;Released live during the developer’s keynote at PyCon JP, the app quickly found its customers. Within the first week, the developer was invited to deliver four talks on the project at different events and was also scheduled to appear on a radio program to discuss the story behind the launch.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-hamm-award&quot;&gt;&lt;strong&gt;HAMM Award&lt;/strong&gt;&lt;/h2&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-judging-criteria-3&quot;&gt;&lt;strong&gt;Judging criteria&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The &lt;strong&gt;Help Apps Make Money (HAMM) Award&lt;/strong&gt; recognizes the strongest monetization strategy. Judges reviewed each project for:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Clarity of strategy&lt;/strong&gt;: Are revenue streams well-defined and realistic for the target market?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Creativity&lt;/strong&gt;: Does the app explore hybrid or unconventional monetization models?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Financial viability&lt;/strong&gt;: Could the approach sustain a long-term business or competitive edge?&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1st-place-vector-guard&quot;&gt;&lt;strong&gt;1st Place: &lt;/strong&gt;&lt;a href=&quot;https://revenuecat-shipaton-2025.devpost.com/submissions/767760-vector-guard&quot;&gt;&lt;strong&gt;Vector Guard&lt;/strong&gt;&lt;/a&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;806&quot; height=&quot;537&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-41.png&quot; alt=&quot;&quot; class=&quot;wp-image-46810&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-41.png 806w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-41-300x200.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-41-768x512.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-41-50x33.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-41-60x40.png 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-41-696x464.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-41-560x373.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-41-444x296.png 444w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-41-708x472.png 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-41-80x53.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-41-48x32.png 48w&quot; sizes=&quot;auto, (max-width: 806px) 100vw, 806px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;a href=&quot;https://apps.apple.com/us/app/vector-guard-bug-identifier/id6749871217&quot;&gt;App Store&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Vector Guard turns public health data into protection, bridging the gap between research and real lives. The app transforms complex CDC surveillance data into an accessible, offline-first platform that helps users identify disease-carrying ticks and mosquitoes instantly.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;The app’s core innovation is its 1:50 Justice Model, where every $2.99 premium subscription automatically funds 50 free accounts in high-risk ZIP codes — no applications, no ads, no internet required. Built in Swift, the app combines CDC open data, AI-driven image recognition, and multilingual accessibility to deliver prevention tools directly to the people who need them most. Vector Guard demonstrates how thoughtful design and fair monetization can turn public data into public good — making disease prevention not a privilege, but a human right.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2nd-place-napkinmatic-ai3d&quot;&gt;2nd Place: &lt;a href=&quot;https://revenuecat-shipaton-2025.devpost.com/submissions/812011-napkinmatic-ai3d&quot;&gt;Napkinmatic AI3D&lt;/a&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;nai3d rc devpost&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/fuaEaOllXds?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;&lt;a href=&quot;https://apps.apple.com/us/app/napkinmatic-ai3d/id6590601686&quot;&gt;App Store&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://play.google.com/store/apps/details?id=com.ai3d.napkinmatic&quot;&gt;Play Store&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Napkinmatic AI3D transforms casual sketches into creative magic — turning doodles on paper into digital masterpieces, interactive 3D models, and animated videos. Inspired by the universal act of sketching on napkins in cafés and classrooms, the app reimagines creativity at its most spontaneous. Users simply snap a photo of their napkin drawing, and within seconds, see it come to life through AI-powered transformations.&lt;/p&gt;



&lt;p&gt;Built with React Native and Unity/Three.js, the app combines mobile accessibility with immersive rendering. The backend runs Python AI services for visual transformations, while RevenueCat powers a hybrid monetization system: users purchase ‘Napkin Credits’ that convert into Coins, or subscribe for monthly creative bundles.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3rd-place-kigaru-talks&quot;&gt;&lt;strong&gt;3rd Place: &lt;/strong&gt;&lt;a href=&quot;https://revenuecat-shipaton-2025.devpost.com/submissions/767091-kigaru-talks&quot;&gt;&lt;strong&gt;Kigaru Talks&lt;/strong&gt;&lt;/a&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;501&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-13-at-16.41.51-1024x501.png&quot; alt=&quot;&quot; class=&quot;wp-image-46820&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-13-at-16.41.51-1024x501.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-13-at-16.41.51-300x147.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-13-at-16.41.51-768x376.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-13-at-16.41.51-1536x752.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-13-at-16.41.51-2048x1002.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-13-at-16.41.51-50x24.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-13-at-16.41.51-82x40.png 82w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-13-at-16.41.51-696x341.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-13-at-16.41.51-560x274.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-13-at-16.41.51-840x411.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-13-at-16.41.51-80x39.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Screenshot-2025-10-13-at-16.41.51-48x23.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;a href=&quot;https://apps.apple.com/jp/app/kigaru-talks/id6749827005?l=en-US&quot;&gt;App Store&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://play.google.com/store/apps/details?id=com.kigarutalks.conversations&quot;&gt;Play Store&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Kigaru Talks helps learners speak Japanese with confidence, not just correctness. The app was designed after years of teaching American military members stationed in Japan who could ace written tests but froze in real conversations. That insight became the foundation for Kigaru Talks: a lighthearted, judgment-free companion that helps people build fluency through real conversation.&lt;/p&gt;



&lt;p&gt;The app uses real-time speech recognition, AI-tuned dialogue at JLPT levels, and gentle correction loops that convert mistakes into flashcards for review. Conversations adapt naturally to each learner’s ability and progress, while memory features ensure continuity across sessions. Designed for safety and personalization, Kigaru doesn’t grade or score users — it encourages practice at their own pace.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-revenuecat-peace-prize&quot;&gt;&lt;strong&gt;RevenueCat Peace Prize&lt;/strong&gt;&lt;/h2&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-judging-criteria-4&quot;&gt;&lt;strong&gt;Judging criteria&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The Peace Prize recognizes technology that drives positive social impact. Judges evaluated:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Impact&lt;/strong&gt;: How effectively the app addresses a meaningful societal or community issue&lt;br&gt;&lt;strong&gt;Feasibility&lt;/strong&gt;: Can the project realistically achieve its goals with available tech and scale?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Reach&lt;/strong&gt;: Potential to improve lives — either for large audiences or deeply within smaller groups&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1st-place-heartbeat-hero&quot;&gt;&lt;strong&gt;1st Place: &lt;/strong&gt;&lt;a href=&quot;https://revenuecat-shipaton-2025.devpost.com/submissions/789701-heartbeat-hero&quot;&gt;&lt;strong&gt;Heartbeat Hero&lt;/strong&gt;&lt;/a&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;Heartbeat Hero Shipaton Demo&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/RYn1gSTS30o?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;&lt;a href=&quot;https://apps.apple.com/us/app/heartbeat-hero/id6736655661&quot;&gt;App Store&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Heartbeat Hero turns your iPhone or iPad into a CPR coach — teaching users to perform life-saving compressions with accurate rhythm, depth, and confidence. It’s designed for everyone: learners, students, and everyday people who want to be ready when seconds matter. The app offers five training modes — Learn, Rhythm, Depth, AI Call Simulation (999/911), and a Real AED Map — all running entirely offline for reliability and privacy. Students receive full access free, while core learning tools remain open to everyone.&lt;/p&gt;



&lt;p&gt;The project began as a WWDC Swift Student Challenge 2024 Distinguished Winner, later rebuilt from the ground up for public release. Inspired by the developer’s firefighter uncle, who saved a life using CPR, Heartbeat Hero was created to give anyone the knowledge and confidence to act. Its breakthrough innovation lies in Depth Practice — combining ARKit, IMU fusion, and adaptive filtering to measure chest compression depth with millimeter accuracy, no special hardware required. Accessibility is equally central, with voice guidance, haptic cues, torch flashes, and a Focus Mode designed to support users with ADHD, dyslexia, or reading difficulties.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2nd-place-hearing-buddy&quot;&gt;&lt;strong&gt;2nd Place: &lt;/strong&gt;&lt;a href=&quot;https://revenuecat-shipaton-2025.devpost.com/submissions/803648-hearing-buddy&quot;&gt;&lt;strong&gt;Hearing Buddy&lt;/strong&gt;&lt;/a&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;515&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-46-1024x515.png&quot; alt=&quot;&quot; class=&quot;wp-image-46824&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-46-1024x515.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-46-300x151.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-46-768x386.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-46-1536x773.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-46-50x25.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-46-80x40.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-46-696x350.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-46-560x282.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-46-840x422.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-46-48x24.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-46.png 2048w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;a href=&quot;https://apps.apple.com/us/app/live-transcribe-hearing-buddy/id6747363502&quot;&gt;App Store&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://apps.apple.com/us/app/hearing-buddy-everywhere/id6752637457&quot;&gt;Mac App Store&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Hearing Buddy helps people with hearing challenges follow conversations in real time — providing accurate, private, and affordable captions powered by Apple’s newest on-device speech recognition. With accessibility at its core, it’s a simple, powerful companion that listens alongside you, transcribes speech instantly, and helps you stay connected in classrooms, workplaces, and everyday life.&lt;/p&gt;



&lt;p&gt;The developer created Hearing Buddy for their partner, who is hard of hearing, after seeing how difficult it could be to catch every word in group conversations. Under the hood, Hearing Buddy uses the new Apple Speech framework in iOS 26 for fast, offline transcription, with CoreML-powered speaker detection to differentiate voices.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3rd-place-moodhaven&quot;&gt;&lt;strong&gt;3rd Place: &lt;/strong&gt;&lt;a href=&quot;https://revenuecat-shipaton-2025.devpost.com/submissions/781146-moodhaven&quot;&gt;&lt;strong&gt;MoodHaven&lt;/strong&gt;&lt;/a&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;532&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-47-1024x532.png&quot; alt=&quot;&quot; class=&quot;wp-image-46826&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-47-1024x532.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-47-300x156.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-47-768x399.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-47-1536x797.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-47-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-47-77x40.png 77w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-47-696x361.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-47-560x291.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-47-840x436.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-47-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-47-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-47.png 2048w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;a href=&quot;https://apps.apple.com/us/app/moodhaven-mood-tracker/id6752584907?uo=4&quot;&gt;App Store&lt;/a&gt;&amp;nbsp;&lt;/p&gt;



&lt;p&gt;MoodHaven helps parents track and understand their child’s moods, sleep, medication, and behavioral incidents — revealing patterns that lead to better care and clearer conversations with professionals; turning scattered notes and exhausted memories into organized insights families can rely on.&lt;/p&gt;



&lt;p&gt;The idea began at home. The developer’s seven-year-old son has faced serious mental health challenges for years, navigating a system that often fails children who can’t yet explain what they feel. Appointments were too short. Diagnoses shifted. Medications changed faster than anyone could track. The need for clarity — for real, data-driven context — became deeply personal. Built in Swift with the help of AI tools like Cursor and Codex, MoodHaven blends thoughtful design with approachable technology to help you navigate your child’s mental health.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-best-vibes-award&quot;&gt;&lt;strong&gt;Best Vibes Award&lt;/strong&gt;&lt;/h2&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-judging-criteria-5&quot;&gt;&lt;strong&gt;Judging Criteria&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;This award honors creativity through the use of vibe-coding tools — AI and creative platforms that enhance development or design. Judges assessed:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Integration and application&lt;/strong&gt;: How well the AI tool or partner product improved workflow or user experience&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Creativity&lt;/strong&gt;: Whether the team used the technology in unexpected, delightful, or innovative ways&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Execution&lt;/strong&gt;: The quality and polish of the final product built with these tools&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1st-place-otter-day-weekday-guesser&quot;&gt;&lt;strong&gt;1st Place: &lt;/strong&gt;&lt;a href=&quot;https://revenuecat-shipaton-2025.devpost.com/submissions/803724-otter-day-weekday-guesser&quot;&gt;&lt;strong&gt;Otter Day: Weekday Guesser&lt;/strong&gt;&lt;/a&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;806&quot; height=&quot;537&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-48.png&quot; alt=&quot;&quot; class=&quot;wp-image-46828&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-48.png 806w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-48-300x200.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-48-768x512.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-48-50x33.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-48-60x40.png 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-48-696x464.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-48-560x373.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-48-444x296.png 444w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-48-708x472.png 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-48-80x53.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-48-48x32.png 48w&quot; sizes=&quot;auto, (max-width: 806px) 100vw, 806px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;a href=&quot;https://apps.apple.com/us/app/otter-day-weekday-guesser/id6747994124&quot;&gt;App Store&lt;/a&gt;&amp;nbsp;&lt;br&gt;&lt;a href=&quot;https://play.google.com/store/apps/details?id=fpdigitallabs.otter&amp;amp;pli=1&quot;&gt;Play Store&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Otter Day turns an old-school mental math trick into an interactive, story-driven learning game. In just minutes, players can learn to tell the day of the week for any date in history — July 4, 1776? Thursday. Your 70th birthday? Friday.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;The app was built solo, using Perplexity Pro for dialogue and visuals, KlingAI for otter animations, and ElevenLabs for voiceovers. The developer leaned on AI tools as creative collaborators; refining art, story, and UI while maintaining a handcrafted tone.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2nd-place-dripped&quot;&gt;&lt;strong&gt;2nd Place: &lt;/strong&gt;&lt;a href=&quot;https://revenuecat-shipaton-2025.devpost.com/submissions/810475-dripped&quot;&gt;&lt;strong&gt;Dripped&lt;/strong&gt;&lt;/a&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;806&quot; height=&quot;453&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-49.png&quot; alt=&quot;&quot; class=&quot;wp-image-46830&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-49.png 806w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-49-300x169.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-49-768x432.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-49-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-49-71x40.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-49-696x391.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-49-560x315.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-49-527x296.png 527w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-49-80x45.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-49-48x27.png 48w&quot; sizes=&quot;auto, (max-width: 806px) 100vw, 806px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;a href=&quot;https://apps.apple.com/in/app/dripped-personal-stylist/id6749790183&quot;&gt;App Store&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Dripped is the answer to the eternal question: “What should I wear today?” Built by a self-proclaimed ‘bad dresser’, the app was inspired by frustration with daily indecision and mismatched outfits. After wasting countless mornings and relying on ChatGPT for quick color checks, the creator decided to build a personal AI stylist — one that could understand their wardrobe, suggest outfits automatically, and save time every single day.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;The app is powered by SwiftUI, Metal, and a Bun backend. What truly sets Dripped apart is its unique PR-driven vibe coding workflow: open an issue GitHub tagging Claude Code, which generates a pull request implementing the feature or fix, CodeRabbit performs lint review, and last a custom GitHub Action triggers an Xcode Cloud workflow to ship a TestFlight build to test on the go.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3rd-place-maestlog-your-personal-symphony-journal&quot;&gt;&lt;strong&gt;3rd Place: &lt;/strong&gt;&lt;a href=&quot;https://revenuecat-shipaton-2025.devpost.com/submissions/806435-maestlog-your-personal-symphony-journal&quot;&gt;&lt;strong&gt;MaestLog: Your Personal Symphony Journal&lt;/strong&gt;&lt;/a&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;806&quot; height=&quot;537&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-50.png&quot; alt=&quot;&quot; class=&quot;wp-image-46832&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-50.png 806w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-50-300x200.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-50-768x512.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-50-50x33.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-50-60x40.png 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-50-696x464.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-50-560x373.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-50-444x296.png 444w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-50-708x472.png 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-50-80x53.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-50-48x32.png 48w&quot; sizes=&quot;auto, (max-width: 806px) 100vw, 806px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;a href=&quot;https://apps.apple.com/en/app/maestlog/id6752569728?l=en-US&quot;&gt;App Store&amp;nbsp;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;MaestLog is an elegant concert diary built for classical music lovers who want to preserve their listening journeys. It began with the realization that memories of live performances fade quickly. After attending countless concerts with their violinist partner, the developer found that details — dates, orchestras, pieces — were slipping away. With MaestLog, users can log their concerts, complete with dates, venues, performers, and detailed program information. Each record includes personal reflections and ratings, building a living archive of musical memories.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Starting with zero mobile development experience, the creator learned Swift, built a full iOS app, and integrated RevenueCat subscriptions — all in three weeks. Using tools like Claude Code, CodeRabbit, and Codex, every step was a collaborative learning experience between human and AI.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-onesignal-boost-award&quot;&gt;OneSignal Boost Award&lt;/h2&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-judging-criteria-6&quot;&gt;Judging criteria&lt;/h3&gt;



&lt;p&gt;The OneSignal Boost Award honors teams that demonstrated best-in-class use of the OneSignal API. Judges assessed:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Integration quality&lt;/strong&gt;: Was OneSignal implemented cleanly and stably?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Impact on experience&lt;/strong&gt;: How did notifications improve retention, engagement, or usability?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Creativity&lt;/strong&gt;: Did the team employ notifications in clever or unexpected ways, such as personalized triggers or advanced segmentation?&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1st-place-cooked-this-cooking-diary-and-tracker&quot;&gt;1st Place: &lt;a href=&quot;https://revenuecat-shipaton-2025.devpost.com/submissions/777760-cooked-this-cooking-diary-and-tracker&quot;&gt;Cooked This: Cooking Diary and Tracker&lt;/a&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;Introducing Cooked This iOS App: Cooking Diary &amp;amp; Tracker&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/2hbY4qjEmwg?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;&lt;a href=&quot;https://apps.apple.com/gb/app/cooked-this/id6749899791?platform=iphone&quot;&gt;App Store&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Cooked This reimagines cooking as a measurable, motivating habit — like fitness tracking, but for your kitchen. The app helps home cooks log meals, track variety, and celebrate milestones, transforming cooking from a routine task into a rewarding practice.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Cooked This’ use of the OneSignal SDK stood out to judges: rich notifications as a behavioral design tool, encouraging users to log meals, maintain streaks, and celebrate small wins. Rather than relying on arbitrary metrics, the app rewards real progress — new dishes tried, cooking frequency maintained, or simply showing up. The result is a positive feedback loop that builds sustainable habits. The developer emphasized careful tuning of reminders and milestones to avoid fatigue, balancing encouragement with autonomy.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2nd-place-voicetree-ai-meeting-notes-for-work-amp-study&quot;&gt;2nd Place: &lt;a href=&quot;https://revenuecat-shipaton-2025.devpost.com/submissions/798523-voicetree-ai-meeting-notes-for-work-study&quot;&gt;Voicetree – AI Meeting Notes for Work &amp;amp; Study&lt;/a&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;806&quot; height=&quot;532&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-51.png&quot; alt=&quot;&quot; class=&quot;wp-image-46834&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-51.png 806w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-51-300x198.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-51-768x507.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-51-50x33.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-51-61x40.png 61w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-51-696x459.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-51-560x370.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-51-448x296.png 448w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-51-715x472.png 715w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-51-80x53.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-51-48x32.png 48w&quot; sizes=&quot;auto, (max-width: 806px) 100vw, 806px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;a href=&quot;https://apps.apple.com/us/app/id6747253996&quot;&gt;App Store&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Voicetree was built out of a simple but universal frustration: how many times have you left a meeting, only to immediately forget what was decided? For two indie developers juggling multiple products, this daily pain point sparked the idea for a smarter, faster, and more human note-taking tool.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Voicetree is an AI-powered meeting assistant that records or uploads audio, transcribes it in real time, and transforms it into structured, editable notes. From there, users can generate summaries, blog posts, email drafts, or even chat directly with their transcripts to extract insights — delivering clarity without friction, so they can focus on conversations, not note-taking. Built in React Native and Expo with custom Swift integrations for Apple Watch, Siri intents, live activities, and widgets.&lt;/p&gt;



&lt;p&gt;Beyond its technical polish, the team impressed judges with strong product thinking — defining a clear MVP, prioritizing user trust, and validating traction early on, with over 1,000 installs and $2,000 in revenue within weeks of launch. Judges praised its user journeys, highlighting the use of email and push notifications, experimentation with in-app messaging, and the related blog post from the team.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3rd-place-friendy&quot;&gt;3rd Place: &lt;a href=&quot;https://revenuecat-shipaton-2025.devpost.com/submissions/788499-friendy&quot;&gt;Friendy+&lt;/a&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;806&quot; height=&quot;537&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-52.png&quot; alt=&quot;&quot; class=&quot;wp-image-46836&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-52.png 806w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-52-300x200.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-52-768x512.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-52-50x33.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-52-60x40.png 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-52-696x464.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-52-560x373.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-52-444x296.png 444w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-52-708x472.png 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-52-80x53.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-52-48x32.png 48w&quot; sizes=&quot;auto, (max-width: 806px) 100vw, 806px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;a href=&quot;https://apps.apple.com/us/app/friendy/id6752370787&quot;&gt;App Store&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Friendy+ was born from a modern networking problem: we meet countless interesting people at events, but weeks later we can’t remember what they do, where we met, or why we wanted to follow up. These ‘weak ties’ are often the most valuable connections — professionally and personally — but they’re also the hardest to maintain. Friendy+ turns that challenge into an opportunity with a simple, elegant app designed to help users capture new contacts, recall details instantly, and stay in touch more intentionally.&lt;/p&gt;



&lt;p&gt;What impressed judges most was the app’s use of OneSignal journeys and transactional messaging to provide persona-based messaging journeys that encourage follow-up, and track engagement through outcomes.&lt;/p&gt;



&lt;p&gt;Through a six-part YouTube series, the developers shared their process, pivots, and lessons learned. Early feedback revealed that their initial audience (close friends) wasn’t the right fit, so they quickly pivoted to focus on professional acquaintances instead.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-4th-place-studient&quot;&gt;4th Place: &lt;a href=&quot;https://revenuecat-shipaton-2025.devpost.com/submissions/778789-studient&quot;&gt;Studient&lt;/a&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;792&quot; height=&quot;573&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-1.jpeg&quot; alt=&quot;&quot; class=&quot;wp-image-46838&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-1.jpeg 792w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-1-300x217.jpeg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-1-768x556.jpeg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-1-50x36.jpeg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-1-55x40.jpeg 55w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-1-641x464.jpeg 641w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-1-696x504.jpeg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-1-560x405.jpeg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-1-409x296.jpeg 409w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-1-652x472.jpeg 652w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-1-80x58.jpeg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-1-48x35.jpeg 48w&quot; sizes=&quot;auto, (max-width: 792px) 100vw, 792px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;a href=&quot;https://apps.apple.com/us/app/studient-ai/id6751546811&quot;&gt;App Store&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://play.google.com/store/apps/details?id=com.daya.studient&amp;amp;hl=en_GB&quot;&gt;Play Store&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Studient sets out to make studying smarter, faster, and a lot less painful. Built in just seven days for Shipaton, it’s an AI-powered learning companion that turns any PDF into structured study materials — complete with flashcards, quizzes, and summaries. The idea came from a simple late-night frustration: if AI can generate code and design, why not let it generate personalized study tools too?&amp;nbsp;&lt;/p&gt;



&lt;p&gt;From a technical standpoint, Studient was an ambitious experiment in vibe coding. Built with Flutter, Studient runs smoothly on both iOS and Android, while OneSignal delivers friendly study reminders. Judges praised the app’s originality, use of Journeys, and the polished user experience.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-5th-place-camp-notes&quot;&gt;5th Place: &lt;a href=&quot;https://revenuecat-shipaton-2025.devpost.com/submissions/772561-camp-notes&quot;&gt;Camp Notes&lt;/a&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;Camp Notes - Track Every Camping Adventure&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/DLPU1-HE7WI?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;&lt;a href=&quot;https://apps.apple.com/us/app/camp-notes-camping-journal/id6749878726&quot;&gt;App Store&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Camp Notes helps campers remember the best sites, avoid the bad ones, and share their outdoor experiences. The idea started after the developer went on a few camping trips with his wife, and realized there was no easy way to log which campsites were worth revisiting and which to skip.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;With Camp Notes, users can record detailed campsite visits, including photos, notes, ratings, and attendees, while contributing to a growing, crowdsourced database of campgrounds. Built natively in SwiftUI with Firebase powering real-time sync, Camp Notes displays thoughtful design and technical craftsmanship. Judges were especially impressed with the use of omnichannel messaging for onboarding and reengagement.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-kotlin-multiplatform-reach-award&quot;&gt;Kotlin Multiplatform Reach Award&lt;/h2&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-judging-criteria-7&quot;&gt;Judging criteria&lt;/h3&gt;



&lt;p&gt;This award recognizes teams that built exceptional cross-platform apps using &lt;strong&gt;Kotlin and Compose Multiplatform&lt;/strong&gt;. Judges looked for:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Technical execution&lt;/strong&gt;: Was the app stable and feature-complete on both iOS and Android?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Design consistency&lt;/strong&gt;: Did the experience feel native across platforms while maintaining a unified brand identity?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Community contribution&lt;/strong&gt;: Did the team share their learnings, challenges, or resources publicly to support other Kotlin developers?&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1st-place-momental&quot;&gt;1st Place: &lt;a href=&quot;https://revenuecat-shipaton-2025.devpost.com/submissions/764218-momental-meditate-sleep-focus&quot;&gt;Momental&lt;/a&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;806&quot; height=&quot;341&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-53.png&quot; alt=&quot;&quot; class=&quot;wp-image-46840&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-53.png 806w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-53-300x127.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-53-768x325.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-53-50x21.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-53-95x40.png 95w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-53-696x294.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-53-560x237.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-53-80x34.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-53-48x20.png 48w&quot; sizes=&quot;auto, (max-width: 806px) 100vw, 806px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;a href=&quot;https://apps.apple.com/app/id6749689590?pt=127554842&amp;amp;ct=website_homepage&amp;amp;mt=8&quot;&gt;App Store&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://play.google.com/store/apps/details?id=ai.momental&amp;amp;utm_source=website&amp;amp;utm_medium=referral&amp;amp;utm_campaign=website_download&amp;amp;referrer=utm_source%3Dwebsite&quot;&gt;Play Store&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Momental emerged from the creator’s search for stillness amid constant digital noise. After traveling to a monastery in Nepal to study meditation, the calm quickly vanished back home — buried under notifications, logins, and the over-engineered complexity of modern mindfulness apps. That experience sparked a clear design philosophy: meditation doesn’t need more content or community features; it needs less friction.&lt;/p&gt;



&lt;p&gt;The result is a beautifully-minimalist meditation and focus app built on one principle: one page, one tap, nothing more. Users can meditate, fall asleep, or focus using clean timers and customizable soundscapes. Built with Kotlin Multiplatform, Momental runs natively on iOS and Android, combining AI-generated and open-source audio edited for perfect quality. There’s no login, no ads, and no onboarding.&lt;/p&gt;



&lt;p&gt;Despite its simplicity, Momental quickly gained traction, with over 4,000 sessions recorded in its first month and an unexpected range of use cases, from teachers helping students focus to tinnitus sufferers finding relief.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2nd-place-posturely&quot;&gt;2nd Place: &lt;a href=&quot;https://revenuecat-shipaton-2025.devpost.com/submissions/760712-posturely&quot;&gt;Posturely&lt;/a&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;Posturely - Revenuecat Shipaton 2025 Submission&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/zSK9wxqGyWc?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;&lt;a href=&quot;https://apps.apple.com/in/app/posturely-sit-straight/id6752023992&quot;&gt;App Store&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://play.google.com/store/apps/details?id=com.mobil80.posturely&quot;&gt;Google Play&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Posturely started with an observation: hours spent coding, working, or even solving puzzles can silently wear down your posture — and your focus, energy, and confidence with it. By combining input from your phone camera, laptop webcam, and even AirPods tilt sensors, it monitors posture in real time and gently reminds you to adjust before discomfort sets in.&lt;/p&gt;



&lt;p&gt;The app offers real-time detection, personalized feedback, and guided exercises, all built around a friendly giraffe mascot that keeps the experience approachable rather than clinical. Users can view progress through posture streaks and reports, and even block distracting apps until exercises are completed. Built with Kotlin Multiplatform, Posturely runs across iOS, Android, and desktop with a single shared codebase. It integrates Supabase for backend data sync, and takes a privacy-first approach, keeping all posture data on the user’s device. Judges praised the developer’s focus on supporting three platforms and being very creative.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3rd-place-steps-share&quot;&gt;3rd Place: &lt;a href=&quot;https://revenuecat-shipaton-2025.devpost.com/submissions/768624-steps-share&quot;&gt;Steps Share&lt;/a&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;Steps Share Shipaton video&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/78NuHU3vP7Q?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;&lt;a href=&quot;https://apps.apple.com/us/app/steps-share-pedometer/id6751459595&quot;&gt;Apple store&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://play.google.com/store/apps/details?id=com.itdeveapps.stepsshare&quot;&gt;Google Play&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Fitness gets more fun when it’s shared — this is the fundamental idea behind Steps Share. After watching friends swap step-count screenshots in a WhatsApp group, the developer set out to build a tracker where accountability was built-in from the first tap. Steps Share turns daily movement into a friendly challenge, letting users compare progress in real time through live rings and ‘Friend Duels’.&lt;/p&gt;



&lt;p&gt;Built with Kotlin Multiplatform, Steps Share syncs data through Firebase and connects to both Google Fit and Apple HealthKit. Currently in beta, users who connected with at least one friend increased their daily steps by 22% — proof that small doses of social motivation drive real results.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-4th-place-drawit-a-multiplatform-draw-amp-guess-game&quot;&gt;4th Place: &lt;a href=&quot;https://revenuecat-shipaton-2025.devpost.com/submissions/809450-drawit-a-multiplatform-draw-guess-game&quot;&gt;DrawIt: A Multiplatform Draw &amp;amp; Guess Game&lt;/a&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;806&quot; height=&quot;524&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-54.png&quot; alt=&quot;&quot; class=&quot;wp-image-46842&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-54.png 806w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-54-300x195.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-54-768x499.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-54-50x33.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-54-62x40.png 62w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-54-696x452.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-54-560x364.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-54-455x296.png 455w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-54-726x472.png 726w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-54-80x52.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-54-48x31.png 48w&quot; sizes=&quot;auto, (max-width: 806px) 100vw, 806px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;a href=&quot;https://apps.apple.com/in/app/draw-it/id6751777472&quot;&gt;App Store&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://play.google.com/store/apps/details?id=com.guessink.game&quot;&gt;Google Play&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;DrawIt reimagines the classic party game of sketching and guessing for the cross-platform era. Players can create private rooms, invite friends, draw clues in real time, and race to guess words while climbing the leaderboard. The experience is fast, social, and packed with small design details such crisp animations, satisfying sound effects, and a playful interface that feels at home on both mobile and desktop.&lt;/p&gt;



&lt;p&gt;DrawIt runs seamlessly across iOS, Android, and desktop, even supporting Apple Pencil input. The team engineered a real-time backend using Firebase — leveraging Firestore, Cloud Functions, and Cloud Run — to manage game rounds, word selection, and leaderboard updates.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-5th-place-clipugc&quot;&gt;&lt;strong&gt;5th Place: &lt;/strong&gt;&lt;a href=&quot;https://revenuecat-shipaton-2025.devpost.com/submissions/812028-clipugc&quot;&gt;&lt;strong&gt;ClipUGC&lt;/strong&gt;&lt;/a&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;806&quot; height=&quot;537&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-55.png&quot; alt=&quot;&quot; class=&quot;wp-image-46844&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-55.png 806w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-55-300x200.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-55-768x512.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-55-50x33.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-55-60x40.png 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-55-696x464.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-55-560x373.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-55-444x296.png 444w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-55-708x472.png 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-55-80x53.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-55-48x32.png 48w&quot; sizes=&quot;auto, (max-width: 806px) 100vw, 806px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;a href=&quot;https://play.google.com/store/apps/details?id=com.measify.clipugc&quot;&gt;Play Store&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://apps.apple.com/pk/app/clipugc-ai-ugc-video-maker/id6752866581&quot;&gt;App Store&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;ClipUGC was built to solve a familiar indie-builder problem: you can ship products, but marketing — especially those high-conversion, influencer-style hook videos — feel out of reach. Agency work is pricey, and many AI tools are tuned for corporate teams with equally corporate pricing. ClipUGC pares the job down to what creators actually need.&lt;/p&gt;



&lt;p&gt;The workflow is clear: generate or customize an AI influencer from text prompts, upload a demo video, integrate the hook, and let the app generate a polished intro video that makes people curious. UI is sprinkled with small moments of delight, like a confetti finish and hidden tap-to-unlock easter eggs. The result is a practical tool that helps indie devs, startups, and small businesses create on-brand hook videos in minutes.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-staff-and-sponsors-award&quot;&gt;&lt;strong&gt;Staff and Sponsors Award&lt;/strong&gt;&lt;/h2&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-judging-criteria-8&quot;&gt;&lt;strong&gt;Judging criteria&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Reserved for RevenueCat employees and sponsor teams, this award honors the top overall internal project. Judges focused on:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Concept originality&lt;/strong&gt;: Does the idea stand out or solve a novel problem?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Execution and design&lt;/strong&gt;: Is it production-quality and enjoyable to use?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Monetization&lt;/strong&gt;: Does it demonstrate thoughtful or experimental revenue design?&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1st-place-crystal-abyss&quot;&gt;&lt;strong&gt;1st Place: &lt;/strong&gt;&lt;a href=&quot;https://revenuecat-shipaton-2025.devpost.com/submissions/779955-crystal-abyss&quot;&gt;&lt;strong&gt;Crystal Abyss&lt;/strong&gt;&lt;/a&gt;&lt;/h3&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;523&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-56-1024x523.png&quot; alt=&quot;&quot; class=&quot;wp-image-46846&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-56-1024x523.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-56-300x153.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-56-768x392.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-56-1536x785.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-56-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-56-78x40.png 78w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-56-696x355.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-56-560x286.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-56-840x429.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-56-80x41.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-56-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-56.png 2048w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;a href=&quot;https://apps.apple.com/us/app/crystal-abyss/id6751184987&quot;&gt;App Store&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Crystal Abyss reimagines the classic Columns puzzle formula through the lens of Monument Valley’s serene minimalism and Dante’s Divine Comedy’s haunting depth. Players drop stacks of shimmering jewels through the nine circles of hell, clearing matches and uncovering meditative rhythms beneath the chaos. Each level represents one of Dante’s circles — from the still calm of Limbo to the fractal frenzy of Treachery.&lt;/p&gt;



&lt;p&gt;Built with SpriteKit and SwiftUI, Crystal Abyss merges art direction with smooth, physics-driven gameplay. Every animation, from the cascade of falling jewels to the glow of completed matches, was crafted to evoke a sense of transcendence. Behind the scenes, the project became a case study in AI-assisted development: using Claude and Codex, the developer vibe coded the entire game.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-it-s-anchors-away-for-shipaton-2025&quot;&gt;It’s anchors away for Shipaton 2025&lt;/h2&gt;



&lt;p&gt;Over the past two months, you’ve absolutely outdone yourselves. From solo builders launching their first-ever apps to seasoned developers pushing the boundaries of what’s possible with AI and monetization, the creativity and determination we’ve seen during Shipaton 2025 have been nothing short of inspiring. In just eight weeks, participants turned ideas into reality — shipping projects that were polished, original, and full of heart.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Finally, from all of Team RevenueCat: congratulations to all the winners! And thank you to everyone who contributed, mentored, or simply encouraged someone else to ship.&lt;/p&gt;



&lt;p&gt;While it might be the end of Shipaton 2025, it’s just the beginning of your apps. We can’t wait to see where they go.&amp;nbsp;&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;p&gt;How did you find Shipaton? Did you have fun? Were there things you wish we had done differently?&amp;nbsp;&lt;/p&gt;



&lt;p&gt;We’d love to hear your thoughts. Let us know on &lt;a href=&quot;https://x.com/RevenueCat&quot;&gt;Twitter&lt;/a&gt; or &lt;a href=&quot;https://www.linkedin.com/company/revenuecat/&quot;&gt;LinkedIn&lt;/a&gt;, and keep an eye out for a survey we’ll be sending to all participants to gather your feedback.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[SubComposeLayout and BoxWithConstraints internals in Jetpack Compose]]></title><description><![CDATA[In this article, you'll dive deep into SubcomposeLayout, the internal mechanisms that power it, how BoxWithConstraints leverages it.]]></description><link>https://www.revenuecat.com/blog/engineering/subcomposelayout-internals/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/subcomposelayout-internals/</guid><pubDate>Sun, 12 Oct 2025 22:42:24 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/SubcomposeLayout-BoxWithConstraints.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Jetpack Compose has revolutionized Android UI development with its declarative paradigm, where UI is a function of state. At its core, Compose follows a well-defined execution flow:&amp;nbsp;&lt;strong&gt;Composition → Measurement → Layout&lt;/strong&gt;. During composition, you declare what your UI should look like. During measurement, the system determines the size of each component. Finally, during layout, components are positioned on the screen.&lt;/p&gt;



&lt;p&gt;But what if you need to break this flow? What if you need to know the measurement constraints before deciding what to compose? This is where&amp;nbsp;&lt;strong&gt;&lt;code&gt;SubcomposeLayout&lt;/code&gt;&lt;/strong&gt;&amp;nbsp;comes in, a versatile primitive that allows you to subcompose content during the measure pass, enabling you to use measurement information to drive composition decisions.&lt;/p&gt;



&lt;p&gt;In this article, you’ll dive deep into &lt;code&gt;SubcomposeLayout&lt;/code&gt;, exploring how it works under the hood, the internal mechanisms that power it, how &lt;code&gt;BoxWithConstraints&lt;/code&gt; leverages it to provide constraint-aware composition, and exploring real-world use cases including &lt;a href=&quot;https://github.com/RevenueCat/purchases-android&quot;&gt;RevenueCat’s Android SDK&lt;/a&gt; and Compose Material3 library.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-understanding-the-core-problem-why-subcomposelayout-exists&quot;&gt;&lt;strong&gt;Understanding the core problem: Why SubcomposeLayout exists&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;In a standard Compose layout, you compose your content first, then measure it. This works perfectly for most cases, but some scenarios require you to know the constraints before deciding what to compose:&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Scenario 1: Adaptive Layouts&lt;/strong&gt;&amp;nbsp;You want to show a different UI structure based on available width, a wide layout for tablets and a narrow layout for phones. You can’t make this decision until you know the constraints.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Scenario 2: Lazy Lists&lt;/strong&gt;&amp;nbsp;LazyColumn needs to compose only the visible items. It can’t know which items are visible until it measures the available space.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Scenario 3: Constraint-Based Composition&lt;/strong&gt;&amp;nbsp;You need to compose different children based on the exact constraints passed by the parent, or you need to measure one child and use its size to determine what other children to compose.&lt;/p&gt;



&lt;p&gt;The traditional Compose flow can’t solve these problems because composition happens before measurement. &lt;code&gt;SubcomposeLayout&lt;/code&gt; inverts this relationship, allowing you to compose during measurement.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;the-subcomposelayout-api-surface&quot;&gt;&lt;strong&gt;The SubcomposeLayout API surface&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;If you look into the API of &lt;code&gt;SubcomposeLayout&lt;/code&gt;, you’ll see it’s designed as a direct analogue to the standard Layout composable, but with a important difference in its measure policy:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z4l2BJ wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Composable\nfun SubcomposeLayout(\n    modifier: Modifier = Modifier,\n    measurePolicy: SubcomposeMeasureScope.(Constraints) -&gt; MeasureResult,\n)&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The measure policy receives a&amp;nbsp;&lt;code&gt;SubcomposeMeasureScope&lt;/code&gt;, which extends&amp;nbsp;&lt;code&gt;MeasureScope&lt;/code&gt;&amp;nbsp;with one important additional capability:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-nFvn0 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;interface SubcomposeMeasureScope : MeasureScope {\n    fun subcompose(slotId: Any?, content: @Composable () -&gt; Unit): List&lt;Measurable&gt;\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This single function is the gateway to dynamic composition. When you call&amp;nbsp;&lt;code&gt;subcompose()&lt;/code&gt;&amp;nbsp;during measurement, it composes the given content immediately and returns a list of&amp;nbsp;&lt;code&gt;Measurable&lt;/code&gt;&amp;nbsp;children that you can then measure and lay out. The&amp;nbsp;&lt;code&gt;slotId&lt;/code&gt;&amp;nbsp;parameter is used to identify and track different composition slots, enabling recomposition, reuse, and proper state management.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;internal-mechanisms-of-subcomposelayout&quot;&gt;&lt;strong&gt;Internal mechanisms of SubcomposeLayout&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The real magic happens inside&amp;nbsp;&lt;code&gt;LayoutNodeSubcompositionsState&lt;/code&gt;, a complex state management system that orchestrates the entire subcomposition process. This class is stored directly on the &lt;code&gt;LayoutNode&lt;/code&gt;, maintaining a 1-1 mapping between the state and the node.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-three-tier-node-organization&quot;&gt;&lt;strong&gt;The three-tier node organization&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;If you explore the internal implementation, you’ll discover that &lt;code&gt;SubcomposeLayout&lt;/code&gt; organizes its child nodes into three distinct regions within the&amp;nbsp;&lt;code&gt;root.foldedChildren&lt;/code&gt;&amp;nbsp;list:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1uXOrV wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;[Active nodes] [Reusable nodes] [Precomposed nodes]&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Active nodes&lt;/strong&gt;: These are the slots currently being used in the latest measure pass. They’re tracked in the&amp;nbsp;&lt;code&gt;slotIdToNode&lt;/code&gt;&amp;nbsp;map for quick lookup by slot ID.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Reusable nodes&lt;/strong&gt;: These are nodes that were previously active but are no longer being used. Instead of disposing them immediately (which would destroy their composition state), &lt;code&gt;SubcomposeLayout&lt;/code&gt; keeps them in a reusable pool. The count is tracked via&amp;nbsp;&lt;code&gt;reusableCount&lt;/code&gt;.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Precomposed nodes&lt;/strong&gt;: These are nodes that have been composed ahead of time (via the&amp;nbsp;&lt;code&gt;precompose()&lt;/code&gt;&amp;nbsp;function) but haven’t been used in a measure pass yet. They’re tracked in the&amp;nbsp;&lt;code&gt;precomposeMap&lt;/code&gt;&amp;nbsp;and counted via&amp;nbsp;&lt;code&gt;precomposedCount&lt;/code&gt;.&lt;/p&gt;



&lt;p&gt;This three-tier organization is the foundation of &lt;code&gt;SubcomposeLayout&lt;/code&gt;‘s performance optimization strategy.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-subcompose-execution-flow&quot;&gt;&lt;strong&gt;The subcompose execution flow&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;When you call&amp;nbsp;&lt;code&gt;subcompose(slotId, content)&lt;/code&gt;&amp;nbsp;during measurement, the internal machinery follows a sophisticated lookup and allocation strategy. Let’s trace through the code in&amp;nbsp;&lt;code&gt;LayoutNodeSubcompositionsState.subcompose()&lt;/code&gt;:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z2njdF7 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;fun subcompose(slotId: Any?, content: @Composable () -&gt; Unit): List&lt;Measurable&gt; {\n    makeSureStateIsConsistent()\n    val layoutState = root.layoutState\n    checkPrecondition(\n        layoutState == LayoutState.Measuring ||\n            layoutState == LayoutState.LayingOut ||\n            layoutState == LayoutState.LookaheadMeasuring ||\n            layoutState == LayoutState.LookaheadLayingOut\n    ) {\n        \&amp;quot;subcompose can only be used inside the measure or layout blocks\&amp;quot;\n    }\n\n    val node =\n        slotIdToNode.getOrPut(slotId) {\n            val precomposed = precomposeMap.remove(slotId)\n            if (precomposed != null) {\n                precomposedCount--\n                precomposed\n            } else {\n                takeNodeFromReusables(slotId) ?: createNodeAt(currentIndex)\n            }\n        }\n\n\/\/ Position the node correctly in the children listif (root.foldedChildren.getOrNull(currentIndex) !== node) {\n        val itemIndex = root.foldedChildren.indexOf(node)\n        requirePrecondition(itemIndex &gt;= currentIndex) {\n            \&amp;quot;Key \\\&amp;quot;$slotId\\\&amp;quot; was already used. If you are using LazyColumn\/Row please make \&amp;quot; +\n                \&amp;quot;sure you provide a unique key for each item.\&amp;quot;\n        }\n        if (currentIndex != itemIndex) {\n            move(itemIndex, currentIndex)\n        }\n    }\n    currentIndex++\n\n    subcompose(node, slotId, pausable = false, content)\n\n    return if (layoutState == LayoutState.Measuring || layoutState == LayoutState.LayingOut) {\n        node.childMeasurables\n    } else {\n        node.childLookaheadMeasurables\n    }\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The execution follows this precise sequence:&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Step 1: State validation –&lt;/strong&gt; The function first ensures the internal state is consistent and verifies that we’re actually in a measure or layout pass. You cannot call&amp;nbsp;&lt;code&gt;subcompose()&lt;/code&gt;&amp;nbsp;during composition, it’s strictly a measurement-time operation.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Step 2: Node lookup and allocation –&lt;/strong&gt; The system checks&amp;nbsp;&lt;code&gt;slotIdToNode&lt;/code&gt;&amp;nbsp;to see if this slot ID already has an active node. If not, it follows a fallback chain:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Check if the slot was precomposed (&lt;code&gt;precomposeMap&lt;/code&gt;)&lt;/li&gt;



&lt;li&gt;Try to reuse a compatible node from the reusable pool (&lt;code&gt;takeNodeFromReusables()&lt;/code&gt;)&lt;/li&gt;



&lt;li&gt;Create a brand new LayoutNode (&lt;code&gt;createNodeAt()&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;&lt;strong&gt;Step 3: Position management –&lt;/strong&gt;&amp;nbsp;Once we have a node, we need to ensure it’s at the correct position in the&amp;nbsp;&lt;code&gt;foldedChildren&lt;/code&gt;&amp;nbsp;list. The&amp;nbsp;&lt;code&gt;currentIndex&lt;/code&gt;&amp;nbsp;tracks where we are in the active region. If the node is found at a different index, it’s moved to the correct position. This maintains the invariant that active nodes are always at the front of the list, in the order they were subcomposed.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Step 4: Composition&lt;/strong&gt;&amp;nbsp;– The&amp;nbsp;&lt;code&gt;subcompose(node, slotId, pausable, content)&lt;/code&gt;&amp;nbsp;internal function handles the actual composition into the node. It manages the ReusableComposition lifecycle, handles content changes, and applies paused compositions if applicable.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Step 5: Return measurables&lt;/strong&gt;&amp;nbsp;– Finally, the function returns the appropriate measurables based on whether we’re in a lookahead pass or a regular measure pass.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-slot-reuse-optimization&quot;&gt;&lt;strong&gt;The slot reuse optimization&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;One of the most sophisticated aspects of &lt;code&gt;SubcomposeLayout&lt;/code&gt; is its slot reuse mechanism. When a slot is no longer needed, instead of immediately disposing it, the system can keep it in the reusable pool. This is managed by&amp;nbsp;&lt;code&gt;disposeOrReuseStartingFromIndex()&lt;/code&gt;:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z2v0OQF wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;fun disposeOrReuseStartingFromIndex(startIndex: Int) {\n    reusableCount = 0\n    val foldedChildren = root.foldedChildren\n    val lastReusableIndex = foldedChildren.size - precomposedCount - 1\n    var needApplyNotification = false\n    if (startIndex &lt;= lastReusableIndex) {\n\/\/ construct the set of available slot ids\n        reusableSlotIdsSet.clear()\n        for (i in startIndex..lastReusableIndex) {\n            val slotId = getSlotIdAtIndex(foldedChildren, i)\n            reusableSlotIdsSet.add(slotId)\n        }\n\n        slotReusePolicy.getSlotsToRetain(reusableSlotIdsSet)\n\/\/ iterating backwards so it is easier to remove itemsvar i = lastReusableIndex\n        Snapshot.withoutReadObservation {\n            while (i &gt;= startIndex) {\n                val node = foldedChildren[i]\n                val nodeState = nodeToNodeState[node]!!\n                val slotId = nodeState.slotId\n                if (slotId in reusableSlotIdsSet) {\n                    reusableCount++\n                    if (nodeState.active) {\n                        node.resetLayoutState()\n                        nodeState.reuseComposition(forceDeactivate = false)\n\n                        if (nodeState.composedWithReusableContentHost) {\n                            needApplyNotification = true\n                        }\n                    }\n                } else {\n                    ignoreRemeasureRequests {\n                        nodeToNodeState.remove(node)\n                        nodeState.composition?.dispose()\n                        root.removeAt(i, 1)\n                    }\n                }\n\/\/ remove it from slotIdToNode so it is not considered active\n                slotIdToNode.remove(slotId)\n                i--\n            }\n        }\n    }\n\n    if (needApplyNotification) {\n        Snapshot.sendApplyNotifications()\n    }\n\n    makeSureStateIsConsistent()\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This function is called after measurement completes. Any nodes from&amp;nbsp;&lt;code&gt;startIndex&lt;/code&gt;&amp;nbsp;onwards are no longer active. The system:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Collects all the slot IDs that could potentially be reused&lt;/li&gt;



&lt;li&gt;Calls the&amp;nbsp;&lt;code&gt;slotReusePolicy.getSlotsToRetain()&lt;/code&gt;&amp;nbsp;to let the policy decide which slots to keep&lt;/li&gt;



&lt;li&gt;For kept slots, marks them as reusable and deactivates their composition&lt;/li&gt;



&lt;li&gt;For discarded slots, disposes the composition and removes the node entirely&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;The deactivation is handled by&amp;nbsp;&lt;code&gt;NodeState.reuseComposition()&lt;/code&gt;:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-3E8tn wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;private fun NodeState.reuseComposition(forceDeactivate: Boolean) {\n    if (!forceDeactivate &amp;amp;&amp;amp; composedWithReusableContentHost) {\n\/\/ Deactivation through ReusableContentHost is controlled with the active flag\n        active = false\n    } else {\n\/\/ Otherwise, create a new instance to avoid state change notifications\n        activeState = mutableStateOf(false)\n    }\n\n    if (pausedComposition != null) {\n\/\/ Cancelling disposes composition, so no additional work is needed.\n        cancelPausedPrecomposition()\n    } else if (forceDeactivate) {\n        record(SLOperation.ReuseForceSyncDeactivation)\n        composition?.deactivate()\n    } else {\n        val outOfFrameExecutor = outOfFrameExecutor\n        if (outOfFrameExecutor != null) {\n            record(SLOperation.ReuseScheduleOutOfFrameDeactivation)\n            deactivateOutOfFrame(outOfFrameExecutor)\n        } else {\n            if (!composedWithReusableContentHost) {\n                record(SLOperation.ReuseSyncDeactivation)\n                composition?.deactivate()\n            } else {\n                record(SLOperation.ReuseDeactivationViaHost)\n            }\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The deactivation strategy depends on whether the composition used &lt;code&gt;ReusableContentHost&lt;/code&gt;. If it did, changing the&amp;nbsp;&lt;code&gt;active&lt;/code&gt;&amp;nbsp;flag to false will trigger &lt;code&gt;ReusableContentHost&lt;/code&gt; to deactivate its content. Otherwise, the composition is directly deactivated either synchronously or scheduled out-of-frame via the &lt;code&gt;OutOfFrameExecutor&lt;/code&gt;.&lt;/p&gt;



&lt;p&gt;When a reusable slot is needed again,&amp;nbsp;&lt;code&gt;takeNodeFromReusables()&lt;/code&gt;&amp;nbsp;implements a smart matching algorithm:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1QKs7Q wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;private fun takeNodeFromReusables(slotId: Any?): LayoutNode? {\n    if (reusableCount == 0) {\n        return null\n    }\n    val foldedChildren = root.foldedChildren\n    val reusableNodesSectionEnd = foldedChildren.size - precomposedCount\n    val reusableNodesSectionStart = reusableNodesSectionEnd - reusableCount\n    var index = reusableNodesSectionEnd - 1\n    var chosenIndex = -1\n\/\/ first try to find a node with exactly the same slotIdwhile (index &gt;= reusableNodesSectionStart) {\n        if (getSlotIdAtIndex(foldedChildren, index) == slotId) {\n\/\/ we have a node with the same slotId\n            chosenIndex = index\n            break\n        } else {\n            index--\n        }\n    }\n    if (chosenIndex == -1) {\n\/\/ try to find a first compatible slotId from the end of the section\n        index = reusableNodesSectionEnd - 1\n        while (index &gt;= reusableNodesSectionStart) {\n            val node = foldedChildren[index]\n            val nodeState = nodeToNodeState[node]!!\n            if (\n                nodeState.slotId === ReusedSlotId ||\n                    slotReusePolicy.areCompatible(slotId, nodeState.slotId)\n            ) {\n                nodeState.slotId = slotId\n                chosenIndex = index\n                break\n            }\n            index--\n        }\n    }\n    return if (chosenIndex == -1) {\n\/\/ no compatible nodes foundnull\n    } else {\n        if (index != reusableNodesSectionStart) {\n\/\/ we need to rearrange the items\n            move(index, reusableNodesSectionStart, 1)\n        }\n        reusableCount--\n        val node = foldedChildren[reusableNodesSectionStart]\n        val nodeState = nodeToNodeState[node]!!\n\/\/ create a new instance to avoid change notifications\n        nodeState.record(SLOperation.Reused)\n        nodeState.activeState = mutableStateOf(true)\n        nodeState.forceReuse = true\n        nodeState.forceRecompose = true\n        node\n    }\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The matching algorithm has two phases:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Exact match&lt;/strong&gt;: First, it tries to find a reusable node with the exact same slot ID. This is ideal because the content is likely very similar.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Compatible match&lt;/strong&gt;: If no exact match is found, it falls back to finding a compatible slot using the&amp;nbsp;&lt;code&gt;slotReusePolicy.areCompatible()&lt;/code&gt;&amp;nbsp;method.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;When a reusable node is taken, it’s marked with&amp;nbsp;&lt;code&gt;forceReuse = true&lt;/code&gt;&amp;nbsp;and&amp;nbsp;&lt;code&gt;forceRecompose = true&lt;/code&gt;. The&amp;nbsp;&lt;code&gt;forceReuse&lt;/code&gt;&amp;nbsp;flag tells the composition system to use&amp;nbsp;&lt;code&gt;setContentWithReuse()&lt;/code&gt;&amp;nbsp;instead of the regular&amp;nbsp;&lt;code&gt;setContent()&lt;/code&gt;, which allows the Compose runtime to maximize reuse of composition state. The&amp;nbsp;&lt;code&gt;forceRecompose&lt;/code&gt;&amp;nbsp;flag ensures the content is recomposed even if the composition already exists.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-measure-policy-implementation&quot;&gt;&lt;strong&gt;The measure policy implementation&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;The actual measure policy is created by&amp;nbsp;&lt;code&gt;createMeasurePolicy()&lt;/code&gt;, which returns a specialized object that handles both regular and lookahead measure passes:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1Joj3W wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;fun createMeasurePolicy(\n    block: SubcomposeMeasureScope.(Constraints) -&gt; MeasureResult\n): MeasurePolicy {\n    return object : LayoutNode.NoIntrinsicsMeasurePolicy(error = NoIntrinsicsMessage) {\n        override fun MeasureScope.measure(\n            measurables: List&lt;Measurable&gt;,\n            constraints: Constraints,\n        ): MeasureResult {\n            scope.layoutDirection = layoutDirection\n            scope.density = density\n            scope.fontScale = fontScale\n            if (!isLookingAhead &amp;amp;&amp;amp; root.lookaheadRoot != null) {\n\/\/ Approach pass\n                currentApproachIndex = 0\n                val result = approachMeasureScope.block(constraints)\n                val indexAfterMeasure = currentApproachIndex\n                return createMeasureResult(result) {\n                    currentApproachIndex = indexAfterMeasure\n                    result.placeChildren()\n\/\/ dispose\n                    disposeUnusedSlotsInApproach()\n                    disposeOrReuseStartingFromIndex(currentIndex)\n                }\n            } else {\n\/\/ Lookahead pass, or the main pass if not in a lookahead scope.\n                currentIndex = 0\n                val result = scope.block(constraints)\n                val indexAfterMeasure = currentIndex\n                return createMeasureResult(result) {\n                    currentIndex = indexAfterMeasure\n                    result.placeChildren()\n                    if (root.lookaheadRoot == null) {\n\/\/ If this is in lookahead scope, we need to dispose *after*\/\/ approach placement, to give approach pass the opportunity to\/\/ transfer the ownership of subcompositions before disposing.\n                        disposeOrReuseStartingFromIndex(currentIndex)\n                    }\n                }\n            }\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This implementation handles three distinct measure scenarios:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Regular measure pass&lt;/strong&gt;&amp;nbsp;(when not in a lookahead scope): Resets&amp;nbsp;&lt;code&gt;currentIndex&lt;/code&gt;&amp;nbsp;to 0, calls the user’s measure block, then disposes or reuses any unused slots after placement.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Lookahead pass&lt;/strong&gt;&amp;nbsp;(when&amp;nbsp;&lt;code&gt;isLookingAhead == true&lt;/code&gt;): Similar to regular measure, but defers disposal until after the approach pass completes. This gives the approach pass an opportunity to take ownership of subcompositions.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Approach pass&lt;/strong&gt;&amp;nbsp;(when&amp;nbsp;&lt;code&gt;!isLookingAhead &amp;amp;&amp;amp; root.lookaheadRoot != null&lt;/code&gt;): Uses a separate&amp;nbsp;&lt;code&gt;currentApproachIndex&lt;/code&gt;&amp;nbsp;and&amp;nbsp;&lt;code&gt;approachMeasureScope&lt;/code&gt;. This pass can compose items that weren’t composed in lookahead, and it manages its own set of precomposed slots tracked in&amp;nbsp;&lt;code&gt;approachPrecomposeSlotHandleMap&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The reason for wrapping the result in&amp;nbsp;&lt;code&gt;createMeasureResult()&lt;/code&gt;&amp;nbsp;is to ensure that disposal happens during&amp;nbsp;&lt;code&gt;placeChildren()&lt;/code&gt;, not during measurement. This is critical because placement is the final phase where we know definitively which children are actually being used.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;how-boxwithconstraints-leverages-subcomposelayout&quot;&gt;&lt;strong&gt;How BoxWithConstraints leverages SubcomposeLayout&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;&lt;code&gt;BoxWithConstraints&lt;/code&gt; is perhaps the most elegant demonstration of &lt;code&gt;SubcomposeLayout&lt;/code&gt;‘s feature. Its entire implementation is remarkably concise:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1uHxaT wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Composable\n@UiComposable\nfun BoxWithConstraints(\n    modifier: Modifier = Modifier,\n    contentAlignment: Alignment = Alignment.TopStart,\n    propagateMinConstraints: Boolean = false,\n    content: @Composable @UiComposable BoxWithConstraintsScope.() -&gt; Unit,\n) {\n    val measurePolicy = maybeCachedBoxMeasurePolicy(contentAlignment, propagateMinConstraints)\n    SubcomposeLayout(modifier) { constraints -&gt;\n        val scope = BoxWithConstraintsScopeImpl(this, constraints)\n        @Suppress(\&amp;quot;ComposableLambdaInMeasurePolicy\&amp;quot;)\n        val measurables = subcompose(Unit) { scope.content() }\n        with(measurePolicy) { measure(measurables, constraints) }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Let’s trace the execution flow when BoxWithConstraints is measured:&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Step 1: Measure begins –&lt;/strong&gt;&amp;nbsp;The parent calls measure on the &lt;code&gt;BoxWithConstraints&lt;/code&gt;‘ &lt;code&gt;LayoutNode&lt;/code&gt;, passing the constraints it wants to impose.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Step 2: Scope creation –&lt;/strong&gt;&amp;nbsp;Inside the measure lambda, a&amp;nbsp;&lt;code&gt;BoxWithConstraintsScopeImpl&lt;/code&gt;&amp;nbsp;is created, wrapping the constraints and providing access to them as Dp values:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z2iPRIC wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;private data class BoxWithConstraintsScopeImpl(\n    private val density: Density,\n    override val constraints: Constraints,\n) : BoxWithConstraintsScope, BoxScope by BoxScopeInstance {\n    override val minWidth: Dp\n        get() = with(density) { constraints.minWidth.toDp() }\n\n    override val maxWidth: Dp\n        get() =\n            with(density) {\n                if (constraints.hasBoundedWidth) constraints.maxWidth.toDp() else Dp.Infinity\n            }\n\n    override val minHeight: Dp\n        get() = with(density) { constraints.minHeight.toDp() }\n\n    override val maxHeight: Dp\n        get() =\n            with(density) {\n                if (constraints.hasBoundedHeight) constraints.maxHeight.toDp() else Dp.Infinity\n            }\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This scope implements&amp;nbsp;&lt;code&gt;BoxWithConstraintsScope&lt;/code&gt;, which extends&amp;nbsp;&lt;code&gt;BoxScope&lt;/code&gt;, giving the content access to both box alignment modifiers and constraint information.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Step 3: Subcomposition with constraint access&lt;/strong&gt;&amp;nbsp;– The important moment:&amp;nbsp;&lt;code&gt;subcompose(Unit) { scope.content() }&lt;/code&gt;&amp;nbsp;is called. This composes the user’s content lambda&amp;nbsp;&lt;strong&gt;right now&lt;/strong&gt;, during measurement, with the scope as the receiver. Because the scope contains the constraints, the user’s composable code can read&amp;nbsp;&lt;code&gt;maxWidth&lt;/code&gt;,&amp;nbsp;&lt;code&gt;maxHeight&lt;/code&gt;, and other constraint properties to make composition decisions:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z22wfki wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;BoxWithConstraints {\n    if (maxWidth &gt; 600.dp) {\n        WideScreenLayout()\n    } else {\n        NarrowScreenLayout()\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;When the user’s lambda executes,&amp;nbsp;&lt;code&gt;maxWidth&lt;/code&gt;&amp;nbsp;is a property access on the&amp;nbsp;&lt;code&gt;BoxWithConstraintsScopeImpl&lt;/code&gt;&amp;nbsp;instance, which reads from the&amp;nbsp;&lt;code&gt;constraints&lt;/code&gt;&amp;nbsp;that were passed to the measure lambda. This is how the “future” (measurement constraints) informs the “past” (composition decisions).&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Step 4: Measure and layout –&lt;/strong&gt;&amp;nbsp;After subcomposition returns the measurables, &lt;code&gt;BoxWithConstraints&lt;/code&gt; delegates to a standard &lt;code&gt;Box&lt;/code&gt; measure policy to handle the actual sizing and alignment logic. The Box measure policy measures each child and positions them according to the&amp;nbsp;&lt;code&gt;contentAlignment&lt;/code&gt;&amp;nbsp;and any individual&amp;nbsp;&lt;code&gt;align&lt;/code&gt;&amp;nbsp;modifiers.&lt;/p&gt;



&lt;p&gt;This implementation is pretty clever, but simple. By using &lt;code&gt;SubcomposeLayout&lt;/code&gt;, &lt;code&gt;BoxWithConstraints&lt;/code&gt; doesn’t need to implement any complex state management, node tracking, or reuse logic, it’s all handled by the &lt;code&gt;SubcomposeLayout&lt;/code&gt; infrastructure. The entire implementation is just: create a scope, subcompose with that scope, measure the results.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;real-world-use-cases&quot;&gt;&lt;strong&gt;Real-world use cases&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;&lt;code&gt;SubcomposeLayout&lt;/code&gt; is the foundational primitive behind many essential Compose components:&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;LazyColumn and LazyRow&lt;/strong&gt;: These use &lt;code&gt;SubcomposeLayout&lt;/code&gt; to compose only the visible items based on the available space and scroll position. As you scroll, items are subcomposed just-in-time, measured, and laid out. When they scroll off-screen, they’re moved to the reusable pool for recycling.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;TabRow&lt;/strong&gt;: &lt;code&gt;TabRow&lt;/code&gt; uses &lt;code&gt;SubcomposeLayout&lt;/code&gt; to measure the tabs first, then subcompose the indicator based on the measured tab positions and sizes.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Scaffold&lt;/strong&gt;: The Scaffold layout uses subcomposition to measure the top bar and bottom bar first, then subcompose the content area with the remaining space.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Adaptive layouts&lt;/strong&gt;: Material3 Adaptive use &lt;code&gt;BoxWithConstraints&lt;/code&gt; (and by extension, &lt;code&gt;SubcomposeLayout&lt;/code&gt;) to show different layouts based on screen size and orientation.&lt;/p&gt;



&lt;p&gt;Another great example from &lt;a href=&quot;https://github.com/RevenueCat/purchases-android&quot;&gt;RevenueCat’s Android SDK&lt;/a&gt; is the use of &lt;code&gt;BoxWithConstraints&lt;/code&gt; to build UI components with dynamic widths. Since &lt;a href=&quot;https://www.revenuecat.com/blog/engineering/server-driven-android/&quot;&gt;RevenueCat’s paywall UI is &lt;strong&gt;server-driven&lt;/strong&gt;&lt;/a&gt;, it needs to handle a wide range of flexible layouts, configured through a web-based, Figma-like dashboard.&lt;/p&gt;



&lt;p&gt;For instance, one of the paywall templates allows developers to dynamically configure the number of purchase options directly from the dashboard. Depending on the setup, this could be just one or two options, or even ten.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;536&quot; height=&quot;250&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/1.png&quot; alt=&quot;&quot; class=&quot;wp-image-46666&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/1.png 536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/1-300x140.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/1-50x23.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/1-86x40.png 86w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/1-80x37.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/1-48x22.png 48w&quot; sizes=&quot;auto, (max-width: 536px) 100vw, 536px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;In this case, we use &lt;code&gt;BoxWithConstraints&lt;/code&gt; to calculate the width of each item, ensuring that all items have equal widths and can be either centered on the screen or stretched to fill the available space.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1YdCxI wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;    fun BoxWithConstraintsScope.packageWidth(numberOfPackages: Float): Dp {\n        val packages = packagesToDisplay(numberOfPackages)\n        val totalPadding = Template4UIConstants.packagesHorizontalPadding * 2\n        val totalSpaceBetweenPackages = Template4UIConstants.packageHorizontalSpacing * (packages - 1)\n        val availableWidth = maxWidth - totalPadding - totalSpaceBetweenPackages\n        return availableWidth \/ packages\n    }\n\n    BoxWithConstraints {\n        val numberOfPackages = state.templateConfiguration.packages.all.size\n        val packageWidth = packageWidth(numberOfPackages.toFloat())\n        Row(\n            ..\n        ) {\n            state.templateConfiguration.packages.all.forEach { packageInfo -&gt;\n                SelectPackageButton(\n                    state,\n                    packageInfo,\n                    viewModel,\n                    Modifier.width(packageWidth), \/\/ calculated width size\n                )\n            }\n        }\n    }&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;performance-considerations&quot;&gt;&lt;strong&gt;Performance considerations&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;However, you should be aware of the performance characteristics of using &lt;code&gt;SubcomposeLayout&lt;/code&gt; and &lt;code&gt;BoxWithConstraints&lt;/code&gt; Subcomposing during measurement is inherently more expensive than standard composition. When you call&amp;nbsp;&lt;code&gt;subcompose()&lt;/code&gt;, the Compose runtime must:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Set up a new composition or reuse an existing one&lt;/li&gt;



&lt;li&gt;Run the composition lambda&lt;/li&gt;



&lt;li&gt;Apply state changes&lt;/li&gt;



&lt;li&gt;Materialize the composition into LayoutNodes&lt;/li&gt;



&lt;li&gt;Return the measurables&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;This all happens synchronously during the measure pass. If you’re not careful, you can create measure passes that take too long, leading to dropped frames. The slot reuse mechanism mitigates this by avoiding full recomposition when content is similar, but reuse isn’t free, it still requires reactivation and state reconciliation.&lt;/p&gt;



&lt;p&gt;Another limitation is that &lt;code&gt;SubcomposeLayout&lt;/code&gt; doesn’t support intrinsic measurements. If you look at the measure policy implementation, you’ll see it extends&amp;nbsp;&lt;code&gt;LayoutNode.NoIntrinsicsMeasurePolicy&lt;/code&gt;, which throws an exception if intrinsic measurements are requested:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1vPeMh wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;private val NoIntrinsicsMessage =\n    \&amp;quot;Asking for intrinsic measurements of SubcomposeLayout \&amp;quot; +\n        \&amp;quot;layouts is not supported. This includes components that are built on top of \&amp;quot; +\n        \&amp;quot;SubcomposeLayout, such as lazy lists, BoxWithConstraints, TabRow, etc. To mitigate \&amp;quot; +\n        \&amp;quot;this:\\n\&amp;quot; +\n        \&amp;quot;- if intrinsic measurements are used to achieve &apos;match parent&apos; sizing, consider \&amp;quot; +\n        \&amp;quot;replacing the parent of the component with a custom layout which controls the order in \&amp;quot; +\n        \&amp;quot;which children are measured, making intrinsic measurement not needed\\n\&amp;quot; +\n        \&amp;quot;- adding a size modifier to the component, in order to fast return the queried \&amp;quot; +\n        \&amp;quot;intrinsic measurement.\&amp;quot;&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The reason is fundamental: intrinsic measurement asks “what size would this layout want to be?” without actually measuring. But &lt;code&gt;SubcomposeLayout&lt;/code&gt; doesn’t know what content it will compose until it receives the actual constraints, so it can’t answer intrinsic measurement queries.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;conclusion&quot;&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;In this article, you’ve learned how &lt;code&gt;SubcomposeLayout&lt;/code&gt; works under the hood, exploring its sophisticated three-tier node organization, slot reuse mechanism, and measure-time composition flow. You’ve seen how BoxWithConstraints leverages this infrastructure to provide a simple but powerful API for constraint-aware composition.&lt;/p&gt;



&lt;p&gt;By understanding these internal mechanisms, you can make better decisions about when to use &lt;code&gt;SubcomposeLayout&lt;/code&gt;-based components and how to optimize their performance. Whether you’re building adaptive layouts with &lt;code&gt;BoxWithConstraints&lt;/code&gt;, creating custom lazy layouts, or designing new measurement-driven composition patterns, &lt;code&gt;SubcomposeLayout&lt;/code&gt; provides the foundation for breaking the traditional composition-measurement boundary.&lt;/p&gt;



&lt;p&gt;As always, happy coding!&lt;/p&gt;



&lt;p&gt;—&amp;nbsp;&lt;a href=&quot;https://github.com/skydoves&quot;&gt;&lt;strong&gt;Jaewoong&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Forget chasing viral ads — build a creative testing system that scales]]></title><description><![CDATA[How to engineer repeatable growth through systematic creative testing, for any budget ]]></description><link>https://www.revenuecat.com/blog/growth/subscription-app-creative-testing/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/subscription-app-creative-testing/</guid><pubDate>Wed, 08 Oct 2025 15:46:22 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Stop-trying-to-interpret-your-ad-wins-—-do-this-instead.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Creatives are one of the most powerful levers for growth — and with the speed and possibilities AI offers, their importance has only multiplied. We all know that &lt;a href=&quot;https://www.revenuecat.com/blog/growth/creative-volume-meta-ad/&quot;&gt;producing more creatives should increase your odds of finding winners&lt;/a&gt;, but there’s a problem.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;There’s too much &lt;strong&gt;noise&lt;/strong&gt;. Every other post on LinkedIn introduces a new complex AI system that promises to ‘100x your creative process’. My feed is full of posts bragging about testing ‘thousands of creatives per week’. It sounds impressive, but it raises the question: do you need &lt;strong&gt;volume &lt;/strong&gt;to compete?&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Is the solution to automate creative and pump out hundreds of ads at a time? Or is this just the latest AI hype?&amp;nbsp;&lt;/p&gt;



&lt;p&gt;In this article, we’ll look at &lt;strong&gt;what actually matters in creative testing&lt;/strong&gt;:&amp;nbsp;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Identifying which creatives move the growth needle&lt;/li&gt;



&lt;li&gt;Aligning your &lt;a href=&quot;https://www.revenuecat.com/blog/growth/7-meta-ad-testing-frameworks-for-subscription-apps/&quot;&gt;ad testing strategy&lt;/a&gt; with your budget&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-stop-producing-for-the-sake-of-testing-start-producing-for-the-sake-of-scalability&quot;&gt;&lt;strong&gt;Stop producing for the sake of testing — start producing for the sake of &lt;/strong&gt;&lt;strong&gt;&lt;em&gt;scalability&lt;/em&gt;&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Before you can identify winners and recreate that success, you need to have a good setup that serves your needs, while adapting to budget constraints.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;This is my tried-and-tested setup that allows you to &lt;a href=&quot;https://www.revenuecat.com/blog/growth/high-velocity-creative-testing-framework-apps-meta/&quot;&gt;scale creative success&lt;/a&gt; by allocating more of your budget to winning creatives:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;386&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-2-1024x386.png&quot; alt=&quot;&quot; class=&quot;wp-image-46629&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-2-1024x386.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-2-300x113.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-2-768x290.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-2-50x19.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-2-106x40.png 106w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-2-696x262.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-2-560x211.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-2-840x317.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-2-80x30.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-2-48x18.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-2.png 1536w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;But that’s not the only setup that works for scalability.&lt;/p&gt;



&lt;p&gt;If your limitations are tighter, ask yourself these two questions to figure out the best setup for your &lt;a href=&quot;https://www.revenuecat.com/blog/growth/meta-ads-cac-creative-testing/&quot;&gt;creative testing&lt;/a&gt;:&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;1. Do I already have winning creatives, or do I have to test from scratch?&lt;/strong&gt;&amp;nbsp;&lt;/p&gt;



&lt;p&gt;This question determines your initial setup. If you’ve already run campaigns and seen what kind of creatives drive good performance, then you can start the new campaigns using these ideas. If not, your setup will have to continuously adapt until you discover the concepts that unlock growth.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;2. How much money can I spend per day?&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;This answer will determine the regions and platforms you can target, the event that you can optimize for, and the number of campaigns, ad groups and creatives that make sense. Before diving into the mathematics of answering this question, let’s take a detour to determine &lt;strong&gt;what a winner looks like in terms of metrics.&lt;/strong&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;three-types-of-ad-creatives-to-identify&quot;&gt;&lt;strong&gt;Three types of ad creatives to identify&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;As everything in life, ad success isn’t black and white. There’s not just ‘winners’ and ‘losers’, there’s some grey areas.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Broadly speaking, here’s the three types of &lt;a href=&quot;https://www.revenuecat.com/blog/growth/informed-empathy-user-interviews-ad-creatives/&quot;&gt;ad creative&lt;/a&gt; you’ll come up against.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Winning creatives &lt;/strong&gt;are the ones that drastically improve performance in all aspects. They don’t tank when you put more budget on them, and they take much longer to be burned out.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Poorly-performing creatives &lt;/strong&gt;are pretty self-explanatory: they never perform at the level you need.&lt;/p&gt;



&lt;p&gt;Then you have &lt;strong&gt;average creatives.&lt;/strong&gt; This is the grey area — average creatives are those that get some spend and perform decently (though worse than winning ads), but you can’t scale them very aggressively. Average creatives are still important, as they add variety in your ad group and diversify your spend once winning creatives start to flag.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Within this group we also include the false positives and false negatives:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;False positives&lt;/strong&gt;: Perform well when they have low spend, but perform badly when you force the algorithms to spend on them&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;False negatives&lt;/strong&gt;: Don’t get spend when among winning creatives, but can perform well when isolated in separate ad groups&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;TL;DR: the &lt;strong&gt;spend/traffic&lt;/strong&gt; a creative receives is a critical variable that determines the best action to take on that specific ad.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;what-does-a-winning-creative-look-like-for-app-growth&quot;&gt;&lt;strong&gt;What does a winning creative look like for app growth?&amp;nbsp;&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The heart of this article is to layout what a winning creative looks like — and since I’m a believer in educating through real data, here’s real data on the performance a winner brings to your campaign, compared to average creatives.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;642&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-3-1024x642.png&quot; alt=&quot;&quot; class=&quot;wp-image-46631&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-3-1024x642.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-3-300x188.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-3-768x481.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-3-50x31.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-3-64x40.png 64w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-3-696x436.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-3-560x351.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-3-472x296.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-3-753x472.png 753w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-3-80x50.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-3-48x30.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-3.png 1170w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Impressive, right? With this creative, we reduced the cost-per-event by 65%, while our spend was fully absorbed by them. The creative also performed well in upper funnel metrics like CPI, CTR, hook rate and hold rate.&lt;/p&gt;



&lt;p&gt;This is what defines a real winning creative:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;They drastically &lt;strong&gt;improve performance&lt;/strong&gt;, not only in your optimization goal, but also engagement-related upper funnel metrics&lt;/li&gt;



&lt;li&gt;They do this &lt;strong&gt;consistently&lt;/strong&gt;, for a longer period of time [than other creatives]&lt;/li&gt;



&lt;li&gt;They do this with a&lt;strong&gt; higher spend&lt;/strong&gt;*&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;em&gt;*In the example above, you see a short time because these winners were moved to isolated ad groups — more on this later!&lt;/em&gt;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;how-to-establish-a-baseline-that-filters-your-winning-creatives&quot;&gt;&lt;strong&gt;How to establish a baseline that filters your winning creatives&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Once you’ve got your creatives defined, you need to know how to rank their success. This means establishing a baseline for the different &lt;a href=&quot;https://www.revenuecat.com/blog/growth/metrics-for-scaling-paid-ads/&quot;&gt;ad metrics and KPIs&lt;/a&gt; you’ll use to measure success and plan actions for ads. Your baseline KPIs will essentially tell you if your next creative has potential to be a winner.&lt;/p&gt;



&lt;p&gt;This baseline should be determined&lt;strong&gt; by the winning creative &lt;/strong&gt;— if you were able to produce a great performance with these, it means you can do it again (if you produce creatives of a similar quality!).&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Here’s what I look at, in order from highest to lowest priority:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Customer acquisition cost (CAC) / cost-per-acquisition (CPA)&lt;/strong&gt;: The primary action you’re optimizing for should be your north-star metric — keep this cost at or below your target, based on your business economics&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Spend:&lt;/strong&gt; Winning creatives typically receive &lt;strong&gt;80–95%&lt;/strong&gt; of daily spend — if a creative receives &lt;strong&gt;less than 50%&lt;/strong&gt; of the budget after two days, treat it as a likely loser or false positive&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Install to conversion event:&lt;/strong&gt; Winning creatives convert to your optimization goal at a faster pace — this metric helps identify why some users install but fail to complete the target action&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Cost-per-install (CPI):&lt;/strong&gt; Doesn’t need to be the lowest, but high-performing creatives usually deliver better-than-average CPI&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;CTR:&lt;/strong&gt; Indicates user intent and how effectively the creative captures attention&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Install rate:&lt;/strong&gt; Measures how efficiently users who click go on to install the app — winning creatives should convert better than average creatives&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Hook rate:&lt;/strong&gt; A critical indicator of early potential — normally much higher in winning creatives&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Hold rate:&lt;/strong&gt; Measures how long users stay engaged; though it can fluctuate, it’s a strong signal of creative quality and retention&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Installs-per-mille (IPM):&lt;/strong&gt; Winning creatives tend to consistently drive higher IPM&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Ad score:&lt;/strong&gt; A broad summary of social engagement to identify which creatives drive meaningful interaction — to calculate it: &lt;em&gt;(Reactions x 2) + (Comments x 5) + (Saves/Shares x 10)&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;strong&gt;💡 A note on CAC/CPA&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;It’s important to consider &lt;em&gt;which event&lt;/em&gt; your campaign is optimizing for. If you’re optimizing for an upper-funnel action like registration or trial start, you might see creatives with an impressively low CPA — but very poor conversion to paid subscription afterward.&lt;/p&gt;



&lt;p&gt;This often happens when algorithms over-deliver ads to younger users (ages 18–24) who are curious enough to try the app but rarely subscribe.&lt;/p&gt;



&lt;p&gt;In these cases, make sure the audience attracted by that creative aligns with your actual target segment. If not, monitor your conversion rate closely — a downward trend may signal that your best-performing creatives are simply attracting the wrong users.&lt;/p&gt;



&lt;p&gt;For example, this is a snapshot of my Meta accounts:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;499&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/David-meta-dash-1024x499.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-46645&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/David-meta-dash-1024x499.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/David-meta-dash-300x146.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/David-meta-dash-768x374.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/David-meta-dash-50x24.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/David-meta-dash-82x40.jpg 82w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/David-meta-dash-696x339.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/David-meta-dash-560x273.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/David-meta-dash-840x410.jpg 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/David-meta-dash-80x39.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/David-meta-dash-48x23.jpg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/David-meta-dash.jpg 1329w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;You can check other metrics like frequency, CPMs, cost per 1k accounts reached, or cost per 6s view, but the list above includes the ones I suggest using as a consistent baseline to measure success.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-creative-ad-optimization-for-every-budget-size-three-testing-frameworks&quot;&gt;&lt;strong&gt;Creative ad optimization for every budget size: three testing frameworks&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;So, you know what a winner looks like by metrics, but how should you approach creative optimization at each budget stage?&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;from-dollar0-to-dollar500&quot;&gt;&lt;strong&gt;From $0 to $500&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;So you have less room to test, but you still can make it work. In these cases, I always recommend &lt;strong&gt;testing one platform&lt;/strong&gt; (normally iOS) and &lt;strong&gt;one GEO&lt;/strong&gt; (normally US), while you optimize for your main event (e.g. start trial, or direct purchase if you go with a hard paywall).&lt;br&gt;&lt;br&gt;Your setup should be very simple: &lt;strong&gt;one campaign&lt;/strong&gt;, and &lt;strong&gt;one ad group&lt;/strong&gt; focused on the main event. If you split ad groups, you won’t generate enough events per day, meaning you won’t finish the learning phase and your performance will tank.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;In terms of # of creatives, I always go with eight–10 creatives, distributed depending on the answer to our question above:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;If you already had winners from previous experiences, do three–four winning creatives and two–three new concepts you want to test&lt;/li&gt;



&lt;li&gt;If you’re starting from scratch, simply invest in the best creatives you can produce&lt;/li&gt;
&lt;/ul&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;933&quot; height=&quot;410&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-4.png&quot; alt=&quot;&quot; class=&quot;wp-image-46633&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-4.png 933w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-4-300x132.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-4-768x337.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-4-50x22.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-4-91x40.png 91w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-4-696x306.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-4-560x246.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-4-840x369.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-4-80x35.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-4-48x21.png 48w&quot; sizes=&quot;auto, (max-width: 933px) 100vw, 933px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;If you run a channel like Meta or TikTok, you’ll know within a couple of days whether the test concepts are winner, since these networks quickly push most spend towards the best performers.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;There will be false positives and negatives&lt;/strong&gt;, but if you push new concepts and they don’t get spend, you can be almost sure they won’t get a better performance than your current top-spending creatives.  &lt;br&gt;&lt;br&gt;It doesn’t matter if you go from scratch or with pre-existing winners, you &lt;em&gt;must&lt;/em&gt; &lt;strong&gt;rotate the creatives that don’t spend&lt;/strong&gt; every two–threee days, otherwise they’ll never get a good performance.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Also &lt;strong&gt;rotate winning assets if you start to see their KPIs get worse&lt;/strong&gt; over time. The same as test concepts can become a winner, a winning asset can become a loser due to &lt;a href=&quot;https://www.revenuecat.com/blog/growth/detect-ad-fatigue-mobile-apps/&quot;&gt;ad fatigue&lt;/a&gt;. Ultimately, there will always be a slot unlocked for tests, either because the previous test hasn’t spent, or because the winner has ad fatigue.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;from-dollar500-to-dollar5000&quot;&gt;&lt;strong&gt;From $500 to $5,000&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;This is my favorite budget stage, as it allows you to split ad groups for testing purposes while still controlling performance and spending the majority of your budget on the best assets.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;At this stage, you should already know &lt;strong&gt;which concepts are the best for your goal&lt;/strong&gt;.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;This is the setup I suggest, since you can launch &lt;strong&gt;three test ad groups&lt;/strong&gt; and &lt;strong&gt;two BAUs for each campaign&lt;/strong&gt; (assuming you run iOS campaigns with SKAN reporting). This allows you to put up to &lt;strong&gt;30-50 creatives every week&lt;/strong&gt; for testing, alongside up to &lt;strong&gt;20 winners&lt;/strong&gt; to absorb most of the budget.&lt;br&gt;&lt;br&gt;You’ll likely see some testing assets get most of the spend, but with a worse CAC/CPA than your BAU assets. In this case, these should &lt;strong&gt;all be considered losers&lt;/strong&gt; — pause them and rotate. (But remember to analyze and compare the engagement metrics, in case you can iterate on the idea and find a real winning asset)  &lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;552&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/500-to-5000-testing-campaign-structure-1024x552.png&quot; alt=&quot;&quot; class=&quot;wp-image-46648&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/500-to-5000-testing-campaign-structure-1024x552.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/500-to-5000-testing-campaign-structure-300x162.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/500-to-5000-testing-campaign-structure-768x414.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/500-to-5000-testing-campaign-structure-1536x828.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/500-to-5000-testing-campaign-structure-2048x1103.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/500-to-5000-testing-campaign-structure-50x27.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/500-to-5000-testing-campaign-structure-74x40.png 74w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/500-to-5000-testing-campaign-structure-696x375.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/500-to-5000-testing-campaign-structure-560x302.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/500-to-5000-testing-campaign-structure-549x296.png 549w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/500-to-5000-testing-campaign-structure-840x453.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/500-to-5000-testing-campaign-structure-80x43.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/500-to-5000-testing-campaign-structure-48x26.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;em&gt;Note: there’s less ads pictured than I recommend, just for clarity within the image&lt;/em&gt;&lt;br&gt;&lt;br&gt;With this setup, you have the opportunity to double-confirm false positives and negatives with isolated ad groups. It’s normal to get a lot of&lt;strong&gt; false positives. &lt;/strong&gt;In this instance, there’s two possibilities:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;If the asset performed better than BAU&lt;/strong&gt;, create an isolated ad group (if necessary, create a new campaign if you don’t have more space in the existing campaign) and see how it evolves when you put a significant amount of spend on it. If it keeps performing better, it’s a real winner — make the most of it in the isolated ad group!&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;If it quickly gets a much worse CAC than BAU&lt;/strong&gt;, it means it was a false positive. As usual, don’t forget to check all the metrics in case the concept has winner potential.&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;&lt;strong&gt;False negatives &lt;/strong&gt;will start to appear on this stage as well. The best approach is following follow the same strategy: isolate them in a new ad group and wait for one–two days. Typically, you’ll see a poor performance when you force spend on them — if not, you’ve hit gold and identified a genuine false negative that turned into a winner!&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;dollar5000-to-infinite&quot;&gt;&lt;strong&gt;$5,000 to infinite&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;At the higher end of budget, things get messy. You have a huge mass of assets to rotate, double-confirm, and scale all at once.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;You’ll likely have &lt;strong&gt;different GEOs&lt;/strong&gt; and &lt;strong&gt;multiple campaigns per GEO&lt;/strong&gt; where you can have &lt;strong&gt;four–five BAU ad groups&lt;/strong&gt;, &lt;strong&gt;10–15 testing groups&lt;/strong&gt;, and &lt;strong&gt;five–10 isolated groups&lt;/strong&gt; to double-confirm false positives/negatives.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;The number of ad groups that work as BAU is really determined by the performance. In my experience, I’ve had accounts where I could have five campaigns with three BAU ad groups on each, and others where my winning creatives ad fatigue meant I had to rotate the winners faster — which obviously limited the number of BAUs.  &lt;/p&gt;



&lt;p&gt;This requires a ton of manual work, but also accelerates your creative process proportionally. In these situations what you really need to focus on is &lt;strong&gt;ensuring your BAU ad groups have a stable performance&lt;/strong&gt;, since they’re spending most of the budget.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;If you see inclining trends in the CAC of these ad groups, &lt;strong&gt;it’s time to shorten the number of BAU ad groups&lt;/strong&gt; and focus on optimizing their performance &lt;em&gt;before&lt;/em&gt; adding more test ad groups. Otherwise, you risk rising CPA/CAC and disrupting the logic behind your setup.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;theres-no-perfect-formula-to-ad-wins&quot;&gt;&lt;strong&gt;There’s no perfect formula to ad wins&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;So there you have it — several detailed setups for optimizing your ads, and a breakdown of how to measure success.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;However, there’s no one in the world that can give you a perfect setup for every case. Everyone has techniques for winning ads, whether they’re KPI formulas or AI tools — but each app is unique.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Your app and creatives have their own intricacies and idiosyncracies, so don’t be afraid to tweak this strategy to work for you. You might not have budget to double-confirm assets, or maybe your winners perform well longer than average so you can leverage performance without many rotations.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Stop focusing on creative volume, stop chasing winners without understanding them first — start with the basics, and learn along the way. There’s no better teacher than real data, and real experiments.&amp;nbsp;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Understanding SupervisorJob in Kotlin Coroutines]]></title><description><![CDATA[In this article, you will learn what SupervisorJob is, how it works under the hood, and explored real-world use cases from viewModelScope and the RevenueCat SDK.]]></description><link>https://www.revenuecat.com/blog/engineering/supervisorjob-kotlin/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/supervisorjob-kotlin/</guid><pubDate>Mon, 06 Oct 2025 04:22:09 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/SupervisorJob-1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Coroutines are a powerful, language-level feature in Kotlin for asynchronous programming, and they’ve become the official solution across Android, Kotlin Multiplatform, and even backend development.&lt;/p&gt;



&lt;p&gt;Coroutines are lightweight alternatives to threads. They can suspend without blocking system resources, making them highly efficient and well-suited for fine-grained concurrency. Kotlin provides useful coroutine APIs, such as builders, coroutine contexts, &lt;code&gt;Job&lt;/code&gt;, and &lt;code&gt;Dispatchers&lt;/code&gt;, that give you sophisticated ways to manage complex and nuanced concurrency scenarios.&lt;/p&gt;



&lt;p&gt;In this article, you’ll dive into one of these concepts, &lt;code&gt;SupervisorJob&lt;/code&gt;, exploring how it works, the internal mechanisms behind it, and how the &lt;a href=&quot;https://github.com/RevenueCat/purchases-android&quot;&gt;RevenueCat SDK for Android&lt;/a&gt; leverages it to handle asynchronous programming.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-understanding-the-core-difference-nbsp-job-nbsp-vs-nbsp-supervisorjob&quot;&gt;&lt;strong&gt;Understanding the core difference:&amp;nbsp;Job&amp;nbsp;vs.&amp;nbsp;SupervisorJob&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;In Kotlin’s structured concurrency, the default behavior of a &lt;code&gt;Job&lt;/code&gt; is to enforce a “one-for-all, all-for-one” policy. When any child coroutine in a scope fails with an exception, it immediately cancels its parent, which in turn cancels all other sibling coroutines. This is a safe and predictable default for many use cases, but it’s not always desirable.&lt;/p&gt;



&lt;p&gt;The &lt;code&gt;SupervisorJob&lt;/code&gt; is a specialized type of &lt;code&gt;Job&lt;/code&gt; designed to break this rigid failure propagation. Its purpose is to create a scope where children can fail independently without affecting the supervisor job itself or its other children. This enables fault isolation, an important pattern for building resilient applications where one failing task should not bring down the entire system.&lt;/p&gt;



&lt;p&gt;Let’s see what are the differences between a &lt;code&gt;Job&lt;/code&gt; and &lt;code&gt;SupervisorJob&lt;/code&gt; :&lt;/p&gt;



&lt;p&gt;&lt;code&gt;Job&lt;/code&gt; (the default) enforces strict structured concurrency. Failure is propagated upwards. If a child coroutine launched within a &lt;code&gt;coroutineScope&lt;/code&gt; or &lt;code&gt;CoroutineScope(Job())&lt;/code&gt; fails with an exception, it cancels its parent job. The parent then immediately cancels all of its other children.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z2vjcRQ wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;val scope = CoroutineScope(Job())\nscope.launch { \/* Child 1 *\/ }\nscope.launch { throw Exception(\&amp;quot;Child 2 Failed!\&amp;quot;) } \/\/ This will cancel the parent Job\nscope.launch { \/* Child 3 *\/ } \/\/ This will be cancelled too&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;&lt;code&gt;SupervisorJob&lt;/code&gt; (the resilient parent) modifies the cancellation behavior. Failure is not propagated upwards. If a child coroutine launched within a &lt;code&gt;CoroutineScope(SupervisorJob())&lt;/code&gt; fails, it does not affect the parent &lt;code&gt;SupervisorJob&lt;/code&gt; or any of its other children. The failure is isolated to that specific child.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1ciNUy wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;val scope = CoroutineScope(SupervisorJob())\nscope.launch { \/* Child 1 will keep running *\/ }\nscope.launch { throw Exception(\&amp;quot;Child 2 Failed!\&amp;quot;) } \/\/ This failure is isolated\nscope.launch { \/* Child 3 will keep running&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;internal-mechanisms-of-supervisorjob&quot;&gt;Internal mechanisms of SupervisorJob&lt;/h2&gt;



&lt;p&gt;If you look into the API surface of &lt;code&gt;SupervisorJob(parent)&lt;/code&gt; function is a simple factory that instantiates a private implementation class, &lt;code&gt;SupervisorJobImpl&lt;/code&gt;.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-21GuKC wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Suppress(\&amp;quot;FunctionName\&amp;quot;)\npublic fun SupervisorJob(parent: Job? = null) : CompletableJob = SupervisorJobImpl(parent)\n\nprivate class SupervisorJobImpl(parent: Job?) : JobImpl(parent) {\n    override fun childCancelled(cause: Throwable): Boolean = false\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The entire implementation of &lt;code&gt;SupervisorJobImpl&lt;/code&gt; is a single-line override. To understand this, we must first understand what it is overriding.&lt;/p&gt;



&lt;p&gt;A standard &lt;code&gt;Job&lt;/code&gt;, created via &lt;code&gt;Job()&lt;/code&gt;, is an instance of &lt;code&gt;JobImpl&lt;/code&gt;, which inherits its behavior from &lt;code&gt;JobSupport&lt;/code&gt;. In &lt;code&gt;JobSupport&lt;/code&gt;, when a child coroutine fails, it eventually calls &lt;code&gt;childCancelled(cause)&lt;/code&gt; on its parent’s &lt;code&gt;ChildHandle&lt;/code&gt;. The default implementation of this method in a standard &lt;code&gt;Job&lt;/code&gt; is designed to propagate the failure upwards:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZT5Ufp wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/\/ In a regular JobSupport instance\npublic open fun childCancelled(cause: Throwable): Boolean {\n    \/\/ A CancellationException is considered normal, don&apos;t cancel the parent.\n    if (cause is CancellationException) return true\n\n    \/\/ For any other exception, cancel the parent itself.\n    return cancelImpl(cause)\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This is the mechanism of failure propagation. A non-cancellation exception from a child causes the parent to cancel itself.&lt;/p&gt;



&lt;p&gt;On the other hand, &lt;code&gt;SupervisorJobImpl&lt;/code&gt; overrides this method with a single, simple statement:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1btxPj wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;override fun childCancelled(cause: Throwable): Boolean = false&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;It looks very simple, but it behaves more than just simple:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;The Override: By always returning &lt;code&gt;false&lt;/code&gt;, the &lt;code&gt;SupervisorJob&lt;/code&gt; is telling the coroutine machinery: “A child has notified me of its failure, but I have not handled the exception, and I will not be cancelling myself because of it.”&lt;/li&gt;



&lt;li&gt;The Effect: This effectively breaks the upward propagation of failure. The child’s failure is contained. The supervisor job remains active, and its other children continue to run unaffected. The responsibility for handling the failed child’s exception is now delegated elsewhere, typically to a &lt;code&gt;CoroutineExceptionHandler&lt;/code&gt; in the child’s context or by the consumer of an &lt;code&gt;async&lt;/code&gt; &lt;code&gt;Deferred&lt;/code&gt; result.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;This small but profound change is the entire internal mechanism that defines a &lt;code&gt;SupervisorJob&lt;/code&gt;.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-supervisorscope-builder&quot;&gt;The &lt;code&gt;supervisorScope&lt;/code&gt; builder&lt;/h3&gt;



&lt;p&gt;The &lt;code&gt;supervisorScope&lt;/code&gt; function provides a convenient way to create an ad-hoc supervisory scope. Its internal mechanism is to create a temporary, specialized coroutine, &lt;code&gt;SupervisorCoroutine&lt;/code&gt;, which acts as the root of the new scope.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZWExlE wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;public suspend fun &lt;R&gt; supervisorScope(block: suspend CoroutineScope.() -&gt; R): R {\n    \/\/ ...\n    val coroutine = SupervisorCoroutine(uCont.context, uCont)\n    \/\/ ...\n}\n\nprivate class SupervisorCoroutine&lt;in T&gt;(...) : ScopeCoroutine&lt;T&gt;(...) {\n    override fun childCancelled(cause: Throwable): Boolean = false\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Just like &lt;code&gt;SupervisorJobImpl&lt;/code&gt;, the &lt;code&gt;SupervisorCoroutine&lt;/code&gt; is a specialized coroutine whose only unique feature is that it overrides &lt;code&gt;childCancelled&lt;/code&gt; to return &lt;code&gt;false&lt;/code&gt;. When you launch new coroutines inside a &lt;code&gt;supervisorScope&lt;/code&gt; block, their parent &lt;code&gt;Job&lt;/code&gt; will be this &lt;code&gt;SupervisorCoroutine&lt;/code&gt;. Therefore, any failures in those children will be stopped at the &lt;code&gt;SupervisorCoroutine&lt;/code&gt;, preventing the failure from leaking out and cancelling the outer scope that called &lt;code&gt;supervisorScope&lt;/code&gt;.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;real-world-use-cases&quot;&gt;Real-world use cases&lt;/h2&gt;



&lt;p&gt;The &lt;a href=&quot;https://github.com/RevenueCat/purchases-android&quot;&gt;RevenueCat Purchases SDK&lt;/a&gt; manages in-app subscriptions, demonstrating this principle perfectly through its strategic use of &lt;code&gt;SupervisorJob&lt;/code&gt; in its &lt;code&gt;BlockstoreHelper&lt;/code&gt; class. The &lt;code&gt;BlockstoreHelper&lt;/code&gt; has a clever and specific job: it interacts with &lt;a href=&quot;https://developer.android.com/identity/block-store&quot;&gt;Google’s Block Store API&lt;/a&gt; to back up and restore an anonymous user ID. This is a user-friendly feature designed to help users seamlessly restore their purchases on a new device, even if they haven’t created an account.&lt;/p&gt;



&lt;p&gt;An exception thrown during a Block Store operation&amp;nbsp;must not&amp;nbsp;be allowed to propagate and crash the host application, so the &lt;code&gt;BlockstoreHelper&lt;/code&gt; achieves this necessary isolation by defining its own dedicated &lt;code&gt;CoroutineScopes&lt;/code&gt;, each configured with a &lt;code&gt;SupervisorJob&lt;/code&gt;.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z2eygPq wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;internal class BlockstoreHelper\nconstructor(\n    \/\/ ... dependencies\n    private val ioScope: CoroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.IO.limitedParallelism(1)),\n    private val mainScope: CoroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main),\n) {\n    \/\/ ...\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;So, any suspend function running inside &lt;code&gt;ioScope&lt;/code&gt; or &lt;code&gt;mainScope&lt;/code&gt; won’t propagate failures to other requests within the same scope, allowing them to continue running safely.&lt;/p&gt;



&lt;p&gt;Another great example of use cases of &lt;code&gt;SupervisorJob&lt;/code&gt; is the &lt;code&gt;viewModelScope&lt;/code&gt; in Android &lt;code&gt;ViewModel&lt;/code&gt;. A &lt;code&gt;ViewModel&lt;/code&gt; often manages multiple, independent, and long-running tasks that should not interfere with each other.&lt;/p&gt;



&lt;p&gt;Imagine a user profile screen in a social media app. The &lt;code&gt;ViewModel&lt;/code&gt; needs to:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Fetch the user’s profile information.&lt;/li&gt;



&lt;li&gt;Observe a real-time Flow of incoming messages.&lt;/li&gt;



&lt;li&gt;Listen for updates to the user’s “online” status from another Flow.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;These are three independent operations. If the message Flow fails due to a network blip, you certainly don’t want to stop fetching the user’s profile or listening for their online status.&lt;/p&gt;



&lt;p&gt;You’re probably already using &lt;code&gt;viewModelScope&lt;/code&gt; naturally and without any doubts, often following official examples like the ones shown below:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-2nEfBe wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;class ProfileViewModel(\n    private val profileRepository: ProfileRepository,\n    private val chatRepository: ChatRepository,\n    private val statusRepository: StatusRepository\n) : ViewModel() {\n\n    \/\/ viewModelScope uses a SupervisorJob by default!\n    \/\/ It&apos;s equivalent to CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)\n\n    fun fetches() {\n        \/\/ Task 1: Fetch profile data\n        viewModelScope.launch {\n            val profile = profileRepository.fetchUserProfile()\n            \/\/ ..\n        }\n\n        \/\/ Task 2: Observe incoming messages\n        viewModelScope.launch {\n            val messages = chatRepository.getIncomingMessages()\n            \/\/ ..\n        }\n\n        \/\/ Task 3: Observe online status\n        viewModelScope.launch {\n            val status = statusRepository.getOnlineStatus()\n            \/\/ ..\n        }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;viewModelScope&lt;/code&gt; extension property wisely uses a &lt;code&gt;SupervisorJob&lt;/code&gt; under the hood since the purpose of &lt;code&gt;ViewModel&lt;/code&gt; is clear. If the &lt;code&gt;getIncomingMessages&lt;/code&gt; suspend function throws an unhandled exception, only that specific &lt;code&gt;launch&lt;/code&gt; block will fail. The other two coroutines, fetching the profile and observing the online status, will continue to run unaffected. Without a &lt;code&gt;SupervisorJob&lt;/code&gt;, a single network error in the chat system would crash the entire &lt;code&gt;ViewModel&lt;/code&gt;‘s scope, potentially leaving the UI in an inconsistent and unresponsive state.&lt;/p&gt;



&lt;p&gt;If you explore the internal codes of &lt;code&gt;viewModelScope&lt;/code&gt;, you will notice it’s already using the &lt;code&gt;SupervisorJob&lt;/code&gt;:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-CctXi wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;public val ViewModel.viewModelScope: CoroutineScope\n    get() =\n        synchronized(VIEW_MODEL_SCOPE_LOCK) {\n            getCloseable(VIEW_MODEL_SCOPE_KEY)\n                ?: createViewModelScope().also { scope -&gt;\n                    addCloseable(VIEW_MODEL_SCOPE_KEY, scope)\n                }\n        }\n        \ninternal fun createViewModelScope(): CloseableCoroutineScope {\n    val dispatcher =\n        try {\n            Dispatchers.Main.immediate\n        } catch (_: NotImplementedError) {\n            EmptyCoroutineContext\n        } catch (_: IllegalStateException) {\n            EmptyCoroutineContext\n        }\n    return CloseableCoroutineScope(coroutineContext = dispatcher + SupervisorJob()) \/\/ here!\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;



&lt;p&gt;In this article, you’ve learned what &lt;code&gt;SupervisorJob&lt;/code&gt; is, how it works under the hood, and explored real-world use cases from &lt;code&gt;viewModelScope&lt;/code&gt; and the RevenueCat SDK. By understanding its unique failure-handling behavior, you can design coroutine hierarchies that are more resilient, preventing one failing child from cancelling an entire scope.&lt;/p&gt;



&lt;p&gt;As always, happy coding!&lt;/p&gt;



&lt;p&gt;— &lt;a href=&quot;https://github.com/skydoves&quot;&gt;&lt;strong&gt;Jaewoong&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[From review to roadmap: How mining reviews can inform your subscription app’s features]]></title><description><![CDATA[Proven techniques for turning scattered reviews into future improvements ]]></description><link>https://www.revenuecat.com/blog/growth/review-mining-for-subscription-apps/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/review-mining-for-subscription-apps/</guid><pubDate>Thu, 02 Oct 2025 19:04:09 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/Using-reviews-to-drive-app-improvements.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Sometimes, I steal from customers.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Wait — before you judge me, I’ll caveat:&amp;nbsp; it’s not customer data or money. I steal their words (and it’s for their own good).&lt;/p&gt;



&lt;p&gt;Why? Because buried in app store reviews are the raw, emotional truths your team needs to build better features, write better copy, and stop guessing what users actually want.&lt;/p&gt;



&lt;p&gt;When I first confessed this, I felt pretty proud of my rebellious revelation. Especially&amp;nbsp; when others fed back that they’d become fellow customer-centric thieves, eagerly using customers’ words for good.&lt;/p&gt;



&lt;p&gt;That was until I met the real Robin Hood, &lt;a href=&quot;https://www.linkedin.com/in/juliana-jackson/&quot;&gt;Juliana Jackson&lt;/a&gt;. As Cloud Director Data Science at &lt;a href=&quot;https://www.jellyfish.com/en-gb/&quot;&gt;Jellyfish&lt;/a&gt; and writer of the newsletter &lt;a href=&quot;https://julianajackson.substack.com/&quot;&gt;Beyond the Mean&lt;/a&gt; , Juliana has taken those same insights from app reviews and turned them into strategic gold — helping major apps make sense of customer feedback.&lt;/p&gt;



&lt;p&gt;After learning this at a recent conference, I immediately badgered her into chatting with me about all things review mining.. She graciously let me ask some (very nerdy) questions, which&amp;nbsp; turned into this guide.&lt;/p&gt;



&lt;p&gt;So here it is, your roadmap to ‘stealing’ words from your customers and putting them to powerful use. Huge thanks to Juliana Jackson for generously sharing her approach and making it all feel so doable.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-steal-from-app-reviews&quot;&gt;Why steal from app reviews?&lt;/h2&gt;



&lt;p&gt;We begin with the most important question: Why? Why invest time in analyzing your app reviews?&lt;/p&gt;



&lt;p&gt;Juliana broke it down like this: Any kind of unstructured data is valuable because it offers &lt;strong&gt;a different lens through which to view your product&lt;/strong&gt;.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;a href=&quot;https://julianajackson.substack.com/&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;551&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-1-1024x551.png&quot; alt=&quot;&quot; class=&quot;wp-image-46534&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-1-1024x551.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-1-300x161.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-1-768x413.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-1-1536x827.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-1-50x27.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-1-74x40.png 74w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-1-696x375.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-1-560x301.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-1-550x296.png 550w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-1-840x452.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-1-80x43.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-1-48x26.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-1.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/a&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;Source: julianajackson.substack.com&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;These are things that happen &lt;em&gt;outside&lt;/em&gt; your control; raw, emotional signals that help you understand how your app subscribers &lt;em&gt;feel&lt;/em&gt;. And those are the kinds of insights that everyone from developers to designers can connect with — and no one can argue against their importance.&lt;/p&gt;



&lt;p&gt;It shifts you from &lt;strong&gt;pushing your own agenda to reflecting theirs&lt;/strong&gt;.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Another reason I’ve become such a big fan of reviews (and a self-declared professional thief) is this:&lt;strong&gt; &lt;/strong&gt;even if you don’t uncover a single insight about features or bugs, you’ll absolutely gain something else — &lt;strong&gt;real, honest customer language. &lt;/strong&gt;That alone can unlock huge improvements across the entire journey, from acquisition through to retention.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-case-study-the-impact-of-review-mining&quot;&gt;Case study: The impact of review mining&lt;/h2&gt;



&lt;p&gt;In case the idea of going through all your reviews is off-putting (understandable), let’s walk through an example of the impact first.&lt;/p&gt;



&lt;p&gt;Juliana worked with a hugely popular food and beverage app in Europe that had over 500k reviews. We can’t share who they are, but we guarantee most of you have enjoyed their food at one point or another.&lt;/p&gt;



&lt;p&gt;The goal was better understanding of customer behavior to drive app improvements. Simple enough, right?&lt;/p&gt;



&lt;p&gt;Not quite. Early analysis revealed a surprising pattern: ratings and reviews often didn’t align. For example, a user might leave a five-star rating, followed by a rant about how difficult the app was to use. This made it difficult to use ratings as a guide for feedback.&lt;/p&gt;



&lt;p&gt;So as part of their data processing, Juliana and her team separated ratings from reviews to focus on the actual sentiment behind the words, rather than blindly trusting the star count. They then went deeper, segmenting the data by platform (Android vs. iOS) and by app version.&lt;/p&gt;



&lt;p&gt;Juliana also shared that app stores show an app’s aggregate rating, but the underlying algorithms heavily weight recent reviews and ratings because they provide the most accurate and relevant picture of an app’s &lt;em&gt;current&lt;/em&gt; quality, stability, and user experience. This helps users make informed decisions based on the app’s most up-to-date state.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;However, it’s a nuanced approach: while prioritizing recency provides essential, up-to-the-minute feedback, and encourages developers to constantly improve, it can also inadvertently obscure or diminish the visibility of long-standing or recurring issues that might have been highlighted in older reviews.&lt;/p&gt;



&lt;p&gt;This analysis surfaced a range of hypotheses to improve the user experience. It also uncovered distinct user behaviors and unmet needs. For example, Android users were more focused on practicality and convenience, while iOS users cared more about premium design. Meaning Android users and iOS users had a completely different user journey, different issues, and different needs. These insights led to personalized onboarding flows and targeted app optimizations for each version.&lt;/p&gt;



&lt;p&gt;The team also discovered widespread issues with login and registration, e.g. specific screen dimensions weren’t performing as well as others. Once addressed, the improvements weren’t just reflected in usage metrics; they showed up in the tone of the reviews themselves.&lt;/p&gt;



&lt;p&gt;The research proved invaluable and was one of Juliana’s favorite projects to work on. Much of the product backlog and many of the experience improvements came directly from this review analysis work.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-when-is-it-time-to-implement-an-app-store-review-process&quot;&gt;When is it time to implement an app store review process?&lt;/h2&gt;



&lt;p&gt;In the early days, when reviews were few and far between, it was usually customer care or even the founder scanning through them manually, says Juliana. It’s not the most efficient process, but with low volume, it works.&lt;/p&gt;



&lt;p&gt;Then at a certain point, doing it manually just doesn’t cut it. You start missing patterns, trends, and actionable insights. Maybe you get lazy as a result, not reading every review as diligently as you used to before. That’s when AI and a more structured process become essential.&lt;/p&gt;



&lt;p&gt;I’ve always struggled to pinpoint that tipping point — aka when is it actually worth getting systematic? I braced for the classic ‘it depends’ answer when I asked Juliana, but instead she gave two clear signals that it’s time to level up your review analysis:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Review quantity&lt;/strong&gt;: When your total number of reviews hits 5k+&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Review velocity: &lt;/strong&gt;When you’re receiving 100+ new reviews per month&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Of course, review frequency varies wildly between apps. Food and beverage apps, for example, may see spikes from specific promotions or seasonal deals. Running or training apps might experience bursts around New Year’s or summertime. So instead of looking at your peak volume, focus on your &lt;em&gt;average&lt;/em&gt; to assess whether you’re ready to introduce a model.&lt;/p&gt;



&lt;p&gt;If you’re seeing high volume &lt;em&gt;and&lt;/em&gt; consistent velocity, that’s your cue — it’s time to take a more structured approach.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-before-you-start-review-mining&quot;&gt;Before you start review mining&lt;/h2&gt;



&lt;p&gt;It’s tempting to dive straight into scouring your reviews. I’ll admit even as I was writing, I had to double back and remind myself of this step.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Review mining without a clear &lt;/strong&gt;&lt;strong&gt;&lt;em&gt;purpose&lt;/em&gt;&lt;/strong&gt;&lt;strong&gt; is a waste of time.&lt;/strong&gt; As Juliana puts it: “You just end up with a really expensive dashboard”. Before you dig in, you need to define your purpose:&amp;nbsp;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;What are you trying to learn?&amp;nbsp;&lt;/li&gt;



&lt;li&gt;What decisions do you hope to inform?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Juliana emphasized starting with the product roadmap and &lt;strong&gt;understanding what stakeholders value — and &lt;/strong&gt;&lt;strong&gt;&lt;em&gt;why&lt;/em&gt;&lt;/strong&gt;. She interviews each stakeholder individually to learn what they’re hoping to uncover, &lt;em&gt;before&lt;/em&gt; doing any analysis.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;For example:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Are you trying to improve retention with the analysis?&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Are you trying to reduce bugs and functional issues?&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Are you trying to understand which features people value vs. which they don’t?&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;You need to know the answers to these questions to set up the right prompts and pull out the most relevant data. &lt;strong&gt;Think of it as doing user research, except your users are your stakeholders.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Juliana also uses this knowledge later on in the process to anchor insights to specific goals and clearly communicate why something should feed into the next release — meaning she’s able to drive far more impact.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;This approach helps avoid getting lost in the inevitable noise that comes with analyzing large volumes of unstructured data. Instead, focus on &lt;strong&gt;answering the right questions&lt;/strong&gt; and &lt;strong&gt;identifying the most valuable opportunities&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;So, before you even open your review dashboard or start pulling insights, take a step back. Decide the core questions you want to answer, and make sure everyone is aligned on why you’re doing this.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-5-techniques-for-review-mining-on-app-stores&quot;&gt;5 Techniques for review mining on app stores&lt;/h2&gt;



&lt;p&gt;I’m an old-school thief (think handmade lock picks) and I love manually combing through reviews and immersing myself in the words. I’ve often manually tagged reviews to get me thinking about what’s being said and the why behind it. Like I said, old-school. Whilst I do believe there’s a lot of value in getting into the head of your customer, it becomes very exhausting and time-consuming after a few hundred reviews.&lt;/p&gt;



&lt;p&gt;Lucky for us, Juliana is a pro: she doesn’t have just a more efficient and scalable approach to review mining — she has five structured options to choose from, depending on your needs and resources.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;We’ll dive into all five in more detail, but here’s a quick overview and how to choose what approach is best for you.&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Approach&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Best for&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Who does the work&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;When to use&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;1. Direct LLM prompting&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Very small datasets and early-stage teams&lt;/td&gt;&lt;td&gt;Fast, cheap, zero setup&lt;br&gt;Good for directional insights&lt;/td&gt;&lt;td&gt;Prone to hallucination, limited to small data&lt;br&gt;Privacy risks if PII is included&lt;br&gt;Requires repeat analysis&lt;/td&gt;&lt;td&gt;You (manual prompts)&lt;/td&gt;&lt;td&gt;You’re just starting and have &amp;lt;5,000 reviews&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;2. LLM-assisted, structured analysis&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Lean teams with mid-size data and light technical skills&lt;/td&gt;&lt;td&gt;More structure supports larger datasets&lt;br&gt;Allows time-based comparisonStill affordable&lt;/td&gt;&lt;td&gt;Still not statistically validated&lt;br&gt;Requires more technical knowledge&amp;nbsp;&lt;br&gt;Still limited scalability&lt;/td&gt;&lt;td&gt;You (potentially with some technical support)&lt;/td&gt;&lt;td&gt;You want more control than direct LLM prompting, but have limited resources to invest in NLP tools or custom models/data scientists&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;3. NLP tools&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Mid-stage apps with growing complexity&lt;/td&gt;&lt;td&gt;Professionally built models often with dashboards and easier to scale&lt;/td&gt;&lt;td&gt;Tool selection matters&lt;br&gt;May be costly&amp;nbsp;&lt;br&gt;Requires careful evaluation&lt;br&gt;Are out of the box so no customization included&lt;/td&gt;&lt;td&gt;The tool (off-the-shelf)&lt;/td&gt;&lt;td&gt;You have thousands of reviews and need regular analysis and reporting, but miss the expertise in house&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;4. Custom model (expert-built)&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Complex apps or those needing custom logic or predictive power&lt;/td&gt;&lt;td&gt;Tailored to your app, user journeys, and segments;&lt;br&gt;Enables deeper insights&lt;/td&gt;&lt;td&gt;Requires budget and trusted partner&amp;nbsp;&lt;br&gt;Slower to launch&lt;/td&gt;&lt;td&gt;Freelance data scientist or agency&lt;/td&gt;&lt;td&gt;When you want segmentation, predictive modelling, or advanced signal filtering&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;5. In-house data scientist&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Large-scale apps or data-driven orgs&lt;/td&gt;&lt;td&gt;Full ownership&lt;br&gt;Integrates easier into sprint cycles&amp;nbsp;&lt;br&gt;Drives deep insights across teams&lt;/td&gt;&lt;td&gt;Higher cost, only worth it if ROI is clear&lt;/td&gt;&lt;td&gt;Full-time hire&lt;/td&gt;&lt;td&gt;You have high DAU/WAU, complex data, and need continuous insight generation&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;You might start with the simplest option and scale up as you start to see the value of analyzing your reviews, but generally the larger your app and the more complex your customer journey is, the more likely you’ll need one of the latter options.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-direct-llm-prompting&quot;&gt;1. Direct LLM prompting&lt;/h3&gt;



&lt;p&gt;If you’re working with a smaller dataset, this is likely the easiest and most accessible option. It’s inexpensive and, with a bit of prompting knowledge, totally manageable. You simply feed the app reviews into an LLM and ask questions like this:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;What are the main themes we’re seeing?&lt;/li&gt;



&lt;li&gt;What features are customers talking about most?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;But don’t get too carried away with the simplicity. Data protection still matters — yes, even Robin Hood has a moral code. Juliana stresses the importance of stripping out any personal information, like names or addresses, before feeding anything into AI tools. Be conscious of legal legislations around AI like the &lt;a href=&quot;https://julianajackson.substack.com/p/eu-ai-act-explained&quot;&gt;EU AI Act&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;That part’s relatively easy: remove the personal data. What’s trickier with this first option is what many of us have encountered: the dreaded LLM hallucination. Especially with large volumes of text; models can get lazy, trail off, or stop before fully analyzing the dataset.&lt;/p&gt;



&lt;p&gt;Which brings us to the next approach — ideal if you’re working with a larger dataset and want a bit more structure.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-llm-assisted-structured-analysis&quot;&gt;2. LLM-assisted, structured analysis&lt;/h3&gt;



&lt;p&gt;For leaner teams or those with larger datasets, Juliana recommends another scrappy but effective method:&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-high-level-workflow&quot;&gt;High-level workflow:&lt;/h4&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Data acquisition (Google Sheets):&lt;/strong&gt;
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Customer reviews or other textual data are systematically organized within a &lt;strong&gt;Google Sheet&lt;/strong&gt;. Each distinct piece of text to be analyzed resides in a dedicated cell or row.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Workflow automation (Google Apps Script):&lt;/strong&gt;
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Google Apps Script&lt;/strong&gt;, a serverless JavaScript platform, is deployed to manage the interaction. This script is engineered to:
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Read the relevant text data from the specified columns within your Google Sheet&lt;/li&gt;



&lt;li&gt;Construct and dispatch requests to the Google Cloud Natural Language API&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;(Here is where you can use Claude or any coding copilot to help you write the code that runs the script.)&lt;/p&gt;



&lt;ol start=&quot;3&quot; class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Intelligent processing (Google Cloud Natural Language API):&lt;/strong&gt;
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;The &lt;strong&gt;Google Cloud Natural Language API&lt;/strong&gt; receives the text data. This pre-trained machine learning service then applies its algorithms to:
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Determine sentiment:&lt;/strong&gt; It assigns a score (typically between -1.0 for highly negative and +1.0 for highly positive) and a magnitude (indicating the strength of the emotion, irrespective of its polarity) for the overall document sentiment&lt;/li&gt;



&lt;li&gt;&lt;em&gt;(The API can also perform other analyses like entity extraction or content classification, if configured)&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Insight integration (Google Sheets):&lt;/strong&gt;
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Upon receiving the structured analysis results from the &lt;strong&gt;Google Cloud Natural Language API&lt;/strong&gt;, the &lt;strong&gt;Google Apps Script&lt;/strong&gt; dynamically writes these sentiment scores and magnitudes back into corresponding columns within your original &lt;strong&gt;Google Sheet&lt;/strong&gt;, providing immediate visibility&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-prerequisites-and-setup-notes&quot;&gt;Prerequisites and setup notes:&lt;/h4&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Google Cloud project and billing:&lt;/strong&gt; Accessing the Google Cloud Natural Language API requires an active Google Cloud project with a linked billing account. While the Natural Language API offers a significant free tier for initial usage, a billing account is mandatory for API access.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;API key/service account:&lt;/strong&gt; Authentication for the Natural Language API typically uses either an API key (simpler for quick setups) or, for production environments, a &lt;strong&gt;service account&lt;/strong&gt;. A service account provides secure, programmatic access for your Apps Script project to interact with Google Cloud services, following the principle of least privilege. Permissions for the Natural Language API must be explicitly granted to this account.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;For more on how to do this (as for us non-techies it can be a bit technical), Juliana has a whole free walkthrough on YouTube: &lt;a href=&quot;https://www.youtube.com/watch?v=ZnUfCD58E9I&quot;&gt;How to Use Google NLP with GSheets and GPT-3 to Analyze Sentiment&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;This hybrid approach gives you more structure than raw prompting and allows you to handle a larger dataset. It also helps you compare reviews over time and generate more consistent outputs.&lt;/p&gt;



&lt;p&gt;That said, it’s still not perfect. You can’t fully trust or depend on the insights to be statistically robust. But it’s a solid starting point if you want to move beyond manual scanning without diving headfirst into full-scale tooling.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;📌 Note &lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;Whilst Juliana doesn’t recommend LLMs as a long-term approach, it’s a good way to build a proof of concept and test how it works before moving on to a permanent solution.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-natural-language-processing-nlp-tools&quot;&gt;3. Natural language processing (NLP) tools&lt;/h3&gt;



&lt;p&gt;NLP tools take care of the heavy lifting when it comes to processing reviews and building structured models. Unlike out-of-the-box LLMs, the models behind these tools are typically built by pros and designed to be statistically sound.&lt;/p&gt;



&lt;p&gt;There are plenty of NLP tools out there, and more are emerging every week. Juliana has used a few solid ones herself, but don’t feel limited to her list:&lt;/p&gt;



&lt;p&gt;“&lt;a href=&quot;https://www.brandwatch.com/p/suite-overview&quot;&gt;Brandwatch&lt;/a&gt;, &lt;a href=&quot;https://www.sprinklr.com/products/platform/ai/&quot;&gt;Sprinklr&lt;/a&gt;, &lt;a href=&quot;https://chattermill.com/&quot;&gt;Chattermill&lt;/a&gt;, or &lt;a href=&quot;https://www.qualtrics.com/en-gb/&quot;&gt;Qualtrics XM&lt;/a&gt; are out-of-the-box tools that work here. I’ll add the caveat that they are out of the box, so they won’t be customized to the business — generally that’s okay until the business gets to the point of needing a lot of customization.”&lt;/p&gt;



&lt;p&gt;To ensure you make the right decision regarding investing in an NLP tool, you can use Juliana’s &lt;a href=&quot;https://julianajackson.substack.com/p/nlp-tool-evaluation-checklist&quot;&gt;free NLP Tool Evaluation Checklist&lt;/a&gt; to choose the right one. It includes the 10 key criteria Juliana looks for, plus red flags to watch out for:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Type of nlp capability&lt;/li&gt;



&lt;li&gt;Model transparency &amp;amp; methodology&lt;/li&gt;



&lt;li&gt;Validation &amp;amp; performance metrics&lt;/li&gt;



&lt;li&gt;Taxonomy fit &amp;amp; customizability&lt;/li&gt;



&lt;li&gt;Context &amp;amp; language nuance handling&lt;/li&gt;



&lt;li&gt;Multilingual support&lt;/li&gt;



&lt;li&gt;Bot/spam/noise filtering&lt;/li&gt;



&lt;li&gt;Fine-tuning &amp;amp; feedback loop&lt;/li&gt;



&lt;li&gt;Data privacy &amp;amp; regulatory compliance&lt;/li&gt;



&lt;li&gt;Interpretability &amp;amp; decision support&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Juliana’s biggest thing to watch for? &lt;strong&gt;Don’t blindly trust raw outputs&lt;/strong&gt;. Look for tools that validate their accuracy using metrics like F1 score, precision, and recall.&lt;/p&gt;



&lt;p&gt;For simple apps, options one or two (LLM-based approaches) may be perfectly fine. Take something like Waterllama, a hydration tracker. Even if it has 100k+ reviews, the app’s use case is straightforward; there aren’t too many user journeys or layers of complexity.&lt;/p&gt;



&lt;p&gt;Now contrast that with IKEA’s app, which, fittingly for Juliana (who lives in Sweden), was top of mind. The complexity is on another level:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;There’s an offline/online hybrid experience&lt;/li&gt;



&lt;li&gt;Hundreds of distinct products, each with their own reviews&lt;/li&gt;



&lt;li&gt;Global reach with geographic nuances&lt;/li&gt;



&lt;li&gt;The app acts more like a discovery tool than a standalone product&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;In that case, a one-size-fits-all tool won’t cut it. You need a solution designed specifically around your business model and data landscape.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-4-custom-model-expert-built&quot;&gt;4. Custom model (expert-built)&lt;/h3&gt;



&lt;p&gt;This is where you bring in a freelancer or agency to build a tailored model based on your customer journeys, segments, and product setup. If you’re looking for &lt;a href=&quot;https://juliana-jackson.com/introduction-to-nlp-ai/&quot;&gt;more predictive power, or want to segment sentiment by cohort&lt;/a&gt;, this is the route to go.&lt;/p&gt;



&lt;p&gt;It also ensures you’re working with someone who can assess &lt;strong&gt;statistical significance&lt;/strong&gt;, so you’re not mistaking noise for a real signal.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-5-in-house-data-scientist&quot;&gt;5. In-house data scientist&lt;/h3&gt;



&lt;p&gt;Thanks to the rise of AI, Juliana says data scientists are officially &lt;em&gt;back&lt;/em&gt;. You’ll likely hit a point where you want to do more advanced things: segmenting feedback, predicting churn risk, and identifying drivers of high-value users.&lt;/p&gt;



&lt;p&gt;That’s when hiring a dedicated data scientist makes sense, especially if you have a large base of daily or weekly active users. It’s really a question of ROI: &lt;strong&gt;will the insights justify the investment?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Your team setup matters, too. If someone on your team has foundational skills but needs support to scale, bringing in a data scientist can level up the whole operation.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-applying-insights-from-app-reviews-and-using-them-to-improve-your-app&quot;&gt;Applying insights from app reviews and using them to improve your app&lt;/h2&gt;



&lt;p&gt;If you started with clear questions and goals, you should now be uncovering rich insights tied to your area of focus — whether that’s onboarding, retention, or something else. From here, use your usual prioritization framework to decide what to tackle first. That likely means evaluating:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;The number of users impacted&lt;/li&gt;



&lt;li&gt;The effort required to solve the issue&lt;/li&gt;



&lt;li&gt;The potential ROI&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Don’t just treat reviews as a source for bug fixes — they can spark smart A/B test hypotheses. If multiple users mention a confusing button or a missing feature, that’s a signal worth validating through experimentation.&lt;/p&gt;



&lt;p&gt;Feeling overwhelmed by the flood of insights? Zoom in on core functionality: what’s going to help users better accomplish their &lt;a href=&quot;https://www.revenuecat.com/blog/growth/what-drives-users-to-pay-jobs-to-be-done/&quot;&gt;job to be done&lt;/a&gt;? A great way to cut through the noise is to focus on emotion. &lt;a href=&quot;https://www.revenuecat.com/blog/growth/solve-app-problems-emotionally/&quot;&gt;Strong emotional reactions&lt;/a&gt; — frustration, confusion, relief — often point to moments that matter. &lt;strong&gt;Emotions teach you so much about what drives long-term loyalty.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;If you’re seeing conflicting insights, go deeper. How many users are saying this? Are there differences in who is saying it, how long they’ve been a customer, where they came from, or what app version they’re using?&lt;/p&gt;



&lt;p&gt;One of the standout things Juliana shared was the importance of combining qualitative and quantitative insights.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;“We can gain a much deeper understanding of our customers by enriching our first-party behavioral data with high-quality qualitative data from customer voice and search intent analysis. This process of data enrichment fills the contextual gaps, providing a fuller, more accurate story of how people are consuming our product.”&lt;/p&gt;



&lt;p&gt;Finally, Juliana recommends baking review insights into your product sprint rituals. &lt;strong&gt;Make it a habit to revisit this feedback every sprint&lt;/strong&gt;, not as a one-off project, but as part of how your team continuously improves.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-other-data-sources-to-consider-for-customer-feedback&quot;&gt;Other data sources to consider for customer feedback&lt;/h2&gt;



&lt;p&gt;While we’ve focused on app reviews, they’re really just the tip of the iceberg. The same principles of review mining can, and should, be applied to all forms of unstructured data, including:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;User interviews&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Search queries&lt;/li&gt;



&lt;li&gt;Customer care conversations&lt;/li&gt;



&lt;li&gt;Social media comments&lt;/li&gt;



&lt;li&gt;Reddit threads&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;You’ll notice most of these don’t happen inside your app. That’s because &lt;a href=&quot;https://julianajackson.substack.com/p/brand-moments-experience&quot;&gt;only 5% of the customer journey occurs there.&lt;/a&gt; If you’re trying to better understand your users or improve acquisition, you need to zoom out. &lt;strong&gt;Your app data gives you one piece of the puzzle, but the rest is happening across the web.&lt;/strong&gt;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-search-queries-are-a-goldmine&quot;&gt;Search queries are a goldmine&lt;/h3&gt;



&lt;p&gt;Juliana emphasized the value of search queries, both inside and outside your app. Whether it’s what users type in your app’s search bar, what they’re Googling before downloading, or what they ask in your help center, these short phrases are pure intent. You’re seeing what people expect your app to deliver before they even interact with it.&lt;/p&gt;



&lt;p&gt;A great tool to understand this that Juliana recommends is &lt;a href=&quot;https://alsoasked.com/&quot;&gt;AlsoAsked&lt;/a&gt;. Imagine you have a pilates workout app. If you type this into AlsoAsked you can learn a wealth of insights on concerns and questions that you could consider addressing in your onboarding:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;829&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-1024x829.png&quot; alt=&quot;&quot; class=&quot;wp-image-46532&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-1024x829.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-300x243.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-768x622.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-50x40.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-49x40.png 49w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-573x464.png 573w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-696x564.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-560x454.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-365x296.png 365w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-583x472.png 583w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-80x65.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image-48x39.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/image.png 1284w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;em&gt;Results in the UK from AlsoAsked for the term “Pilates workout app”&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;Pair that with review analysis, and suddenly you have a clear picture of the ‘jobs’ your product is being hired to do.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-consider-competitor-reviews-with-caution&quot;&gt;Consider competitor reviews [with caution]&lt;/h3&gt;



&lt;p&gt;For smaller apps with less data, you can look at competitor reviews, alongside benchmarks like &lt;a href=&quot;https://sensortower.com/state-of-mobile-2025&quot;&gt;SensorTower&lt;/a&gt;, to see how you’re performing. Just be mindful of data privacy here (as Juliana diligently reminded me): it isn’t your data to use.&lt;/p&gt;



&lt;p&gt;If you use a tool like &lt;a href=&quot;https://appfigures.com/&quot;&gt;Appfigures&lt;/a&gt; for competitive analysis, you’re on safer ground since they act as the data controller, not you.&lt;/p&gt;



&lt;p&gt;App reviews are just the beginning. The same approach applies to call transcripts, Reddit threads, support tickets, and even in-app search data. &lt;strong&gt;Wherever your customers are talking, they’re giving you clues — if you’re ready to listen&lt;/strong&gt;. Having a robust and scalable approach to analysing unstructured data is a competitive advantage for subscription apps.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-7-steps-to-review-mining&quot;&gt;7 Steps to review mining&lt;/h2&gt;



&lt;p&gt;To recap, here’s how to begin:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Define your goals&lt;/strong&gt;: What do you want to learn?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Assess your volume&lt;/strong&gt;: Got &amp;gt;5k total reviews and 100+ new ones a month? It’s time to automate&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Choose your approach:&lt;/strong&gt; Manual deep-dive? LLMs? NLP tools? Expert support?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Scrub your data&lt;/strong&gt;: Always remove personal info before analysis&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Analyze and prioritize&lt;/strong&gt;: Use your existing frameworks to filter signals from noise&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Connect and act&lt;/strong&gt;: Integrate the insights into your product roadmap&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Track change over time&lt;/strong&gt;: Don’t just analyze once — make it a habit&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Juliana was crystal clear on one thing: &lt;strong&gt;don’t treat this like a side quest&lt;/strong&gt;. Review analysis only drives real impact when it’s embedded into your product cycle — visible in sprint planning, roadmap decisions, and team conversations.&lt;/p&gt;



&lt;p&gt;One of her favorite ways to drive action? &lt;strong&gt;Cross-functional workshops&lt;/strong&gt;. Bring product, marketing, and CX into the same room to look at key insights together. It creates alignment and momentum that a lonely dashboard never could.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Review mining isn’t just user research.&lt;/strong&gt; It’s a way to ‘steal’ insights directly from your users and use them to build better, smarter experiences.&lt;/p&gt;



&lt;p&gt;Whatever approach you take, the priority is the same:&lt;/p&gt;



&lt;p&gt;Objectively listen. Learn what your users need, then make something better because of it — don’t just use reviews for social proof, use them for good.&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;p&gt;&lt;em&gt;Disclaimer: This article shares general guidance on analysing reviews and other sources of unstructured data based on personal experience and an expert interview. Always consult your legal and data privacy team before processing customer data or using third-party tools.&lt;/em&gt;&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;p&gt;&lt;strong&gt;About Juliana Jackson&lt;/strong&gt;: Juliana is an enterprise strategist specializing in AI, product, digital experience, and organizational clarity. Cloud Director Data Science at &lt;a href=&quot;https://www.jellyfish.com/en-gb/&quot;&gt;Jellyfish&lt;/a&gt;, (previously the Associate Director of Data &amp;amp; Digital Experience at Monks), she’s known for saying what others won’t. Her straight talk and relentless focus on the end customer are what drive real impact, sharing weekly advice on AI and data strategy in her newsletter &lt;a href=&quot;https://julianajackson.substack.com/&quot;&gt;Beyond the Mean&lt;/a&gt;.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[What every app can learn from Subway Surfers’ 4.5B downloads]]></title><description><![CDATA[Balancing revenue and user trust in the world’s most popular endless runner]]></description><link>https://www.revenuecat.com/blog/growth/subway-surfers-mathias-gredal-norvig-sub-club-2025/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/subway-surfers-mathias-gredal-norvig-sub-club-2025/</guid><pubDate>Wed, 01 Oct 2025 10:09:40 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/10/subway-surfers-mathias-gredal-norvig-sub-club-2025.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;When you think about the most successful apps of all time, &lt;a href=&quot;https://apps.apple.com/us/app/subway-surfers/id512939461&quot;&gt;Subway Surfers&lt;/a&gt; should probably come to mind. Released in 2012 by the Denmark-based gaming studio &lt;a href=&quot;https://sybogames.com/&quot;&gt;SYBO&lt;/a&gt;, Subway Surfers is an endless runner mobile game that has achieved incredible global popularity and longevity (to date, it has over 4.5B downloads).&lt;/p&gt;



&lt;p&gt;This week on the Sub Club podcast, we spoke with SYBO CEO &lt;a href=&quot;https://www.linkedin.com/in/noervig/&quot;&gt;Mathias Gredal Nørvig&lt;/a&gt;. We asked Mathias about the strategies he and his team have employed over the years to build a freemium mobile gaming app that balances generating revenue and preserving a great user experience that keeps users coming back for more.&lt;/p&gt;



&lt;iframe loading=&quot;lazy&quot; width=&quot;100%&quot; height=&quot;180&quot; frameborder=&quot;no&quot; scrolling=&quot;no&quot; seamless=&quot;&quot; src=&quot;https://share.transistor.fm/e/5e6c6716?color=FFFFFF&amp;amp;background=30343C&quot;&gt;&lt;/iframe&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;What Subscription Apps Can Learn: Monetization From Gaming — Mathias Gredal Nørvig, Subway Surfers&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/nKBjv5viero?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-riding-the-virality-wave&quot;&gt;&lt;strong&gt;Riding the virality wave&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;When you’re building a subscription app business, one of the biggest decisions you have to make is how much of your ad budget should go toward paid advertising. It may come as a surprise, but SYBO actually doesn’t spend much on paid. Instead, they’ve invested in a talented in-house creative marketing team that churns out organic ads to both create and ride viral waves. Case in point, when the popular Netflix show Squid Game was released in 2021, the SYBO team made a &lt;a href=&quot;https://www.tiktok.com/@subwaysurfers/video/7017099009055575302&quot;&gt;TikTok video&lt;/a&gt; referencing a moment in the show with the Subway Surfers logo cleverly superimposed. Not every campaign is a hit, but the ones that do take off get millions of views and lead to major spikes in searches and downloads across platforms.&lt;/p&gt;



&lt;p&gt;When asked about SYBO’s ad spend, Mathias said, “The short answer is that we spent nothing — we spent salaries. So it’s all organic, but it’s also fair to say that we use very small budgets to boost things when we see that they go viral.” By choosing to invest in people rather than pouring most of their ad budget into paid advertising, SYBO has created a content marketing flywheel that punches above its weight. “They are super nimble and very efficient at producing,” Mathias said. “The [content marketing] people that have helped us along the way and those that are helping us now are worth their own weight in gold.”&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-ads-done-right&quot;&gt;&lt;strong&gt;Ads done right&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The perennial question with the freemium model is how to generate revenue without creating a frustrating user experience. Like many free-to-play mobile games, Subway Surfers includes rewarded ads as a way for users to “pay” for the game using their attention rather than money. These ads allow players in tier-two and tier-three markets (people who may never subscribe) to contribute value as they enjoy the free app experience.&lt;/p&gt;



&lt;p&gt;But Mathias and his team are careful to monitor what kind of content the ad networks serve up to Subway Surfers players. Given that a large portion of their user base are minors, the SYBO team has safeguards to protect these users in particular from viewing ad content that could be considered objectionable or harmful. “When you install the game, you show your age, and if you are younger than the legal age in your country, then you get placed in what we call the ‘copper’ segment,” Mathias said. “And if you’re in the copper group … you are not shown anything that would not be copper-compliant. But even [adult users] should not be able to see ads for gambling, guns, pornography, or anything that is R-rated. And that’s because we don’t believe that that’s the way we should be making business.”&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-all-access-pass&quot;&gt;&lt;strong&gt;All-access pass?&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;We’ve talked before on the Sub Club podcast about how app businesses can take advantage of alternate and hybrid monetization strategies beyond standard subscription tiers. If you think about it, there’s a pretty big gap between completely free access and a $99/year paid subscription — and where there’s a gap, there’s usually an opportunity. With millions of players around the world, the mobile gaming industry has been at the forefront of monetization, and one thing app businesses can learn from it is that sometimes the subscription model doesn’t make sense. As Mathias points out, “We all have these discoveries where we realize we’ve been spending a hundred dollars more than we wanted on something that we haven’t used since last March, and that’s an annoying feeling.”&lt;/p&gt;



&lt;p&gt;For some apps, day passes or season passes can be a great monetization strategy — particularly for apps that don’t fit the mold of a standard subscription app. Think about a document scanning app that the user really only needs to use once to accomplish a task, or a skiing app that users only need to use during the peak ski season. “The season pass gives you a very clear overview of ‘these are the things you can get in this period of time if you spend this amount of money,’” Mathias said. “And then it requires you to engage with the app or game, and it requires you to play to get to it, but it unlocks a separate track of rewards.” Giving users more options to pay with one-time consumables, day passes, or season passes allows apps that otherwise struggle to monetize with subscriptions to generate revenue while also providing a better user experience.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-conclusion&quot;&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Mobile gaming apps are often ahead of the curve when it comes to user acquisition and retention. Prioritizing free access that’s made possible by rewarded ad videos and hybrid monetization strategies like season passes, mobile gaming apps like Subway Surfers are (pun intended) playing the long game — providing a fun, accessible freemium app experience that keeps users coming back for more. So what can other mobile apps learn from their success? As Mathias puts it, “Monetization and gamification … is about figuring out how to make the user journey as frictionless as possible.”&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[5 Proven models for testing genuine customer demand — before you write any code]]></title><description><![CDATA[Will they pay? Find out before you invest resources into building]]></description><link>https://www.revenuecat.com/blog/growth/customer-validation-subscription-app/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/customer-validation-subscription-app/</guid><pubDate>Tue, 30 Sep 2025 13:10:44 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/5-models-for-testing-customer-demand.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;I speak to a lot to startup founders, and there are some phrases that ring an alarm bell:&amp;nbsp;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;“We’ve got a great app, but people aren’t paying.”&lt;/li&gt;



&lt;li&gt;“We invested hundreds of hours building [insert feature], but it’s not getting the response we expected.”&lt;/li&gt;



&lt;li&gt;“We’re running out of runway, the next feature we build needs to be the right one.”&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;No one likes the feeling of having put blood, sweat, and tears into building an incredible app — only to have people not react the way they’d hoped. That path leads to building out of fear and urgency, rather than momentum and demand.&lt;/p&gt;



&lt;p&gt;The solution? Surprisingly simple, but surprisingly &lt;em&gt;rare&lt;/em&gt;: &lt;strong&gt;test willingness to pay before you write a single line of code&lt;/strong&gt;. Focus on early validation, so you’re not just hearing that people ‘love’ your app or feature, but they’re actually ready to pay for it.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;That is what I’d tell those startups, had I met them on time.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-but-will-people-pay-for-something-they-ve-never-seen-before&quot;&gt;But will people pay for something they’ve never seen before?&lt;/h2&gt;



&lt;p&gt;The short (and slightly Dutch-direct) answer is yes. A notable example is The Pump, a fitness app co-founded by Arnold Schwarzenegger, which &lt;a href=&quot;https://www.revenuecat.com/blog/growth/how-to-pre-sell-app-subscriptions-on-the-web-before-launch/&quot;&gt;generated half a million dollars in pre-launch revenue&lt;/a&gt;. They validated demand by leveraging their Pump Club newsletter, proving that people valued workout content directly from Arnold and would pay for access to an app built around him.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;663&quot; height=&quot;283&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-38.png&quot; alt=&quot;&quot; class=&quot;wp-image-46448&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-38.png 663w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-38-300x128.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-38-50x21.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-38-94x40.png 94w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-38-560x239.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-38-80x34.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-38-48x20.png 48w&quot; sizes=&quot;auto, (max-width: 663px) 100vw, 663px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Okay, great, for Arnie, but most of us don’t have a bodybuilding legend in our corner. So let’s look at someone very different: a school teacher.&lt;/p&gt;



&lt;p&gt;Eric Duffett spent a few months on Udemy and an app development course to learn the basics of building apps. After experimenting and learning from early successes and failures, he created &lt;a href=&quot;https://shotpattern.app/&quot;&gt;Shot Pattern&lt;/a&gt;, a golf app, with zero existing audience. Instead of waiting for launch, he started sharing screenshots of early designs on Twitter. Each post brought in new sign-ups, and interest spiked when he previewed a data-driven ‘expected value’ tool he was building.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;462&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Golf-app-screenshot-1024x462.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-46453&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Golf-app-screenshot-1024x462.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Golf-app-screenshot-300x135.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Golf-app-screenshot-768x347.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Golf-app-screenshot-1536x693.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Golf-app-screenshot-50x23.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Golf-app-screenshot-89x40.jpg 89w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Golf-app-screenshot-696x314.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Golf-app-screenshot-560x253.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Golf-app-screenshot-840x379.jpg 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Golf-app-screenshot-80x36.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Golf-app-screenshot-48x22.jpg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Golf-app-screenshot.jpg 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The result? A steady stream of feedback that shaped Eric’s setup, so much so that his trial-to-paid conversion rates came in well above industry averages during those early days.&lt;/p&gt;



&lt;p&gt;The lesson: you don’t need a massive audience to pre-validate. Traction often comes from solving a real pain point. I’m seeing this firsthand with a startup I’m currently working on. We’re offering a longer free trial in exchange for feedback, and people aren’t just signing up—they’re writing detailed motivations about why they want in, what they’re looking for, and even sharing the trial with others. The initial traction came from a small Meta ads budget, but the results showed up in the form of an engaged community behind the idea.&lt;/p&gt;



&lt;p&gt;But here’s the real validation test: when launch day comes, will they &lt;em&gt;actually&lt;/em&gt; pay?&lt;/p&gt;



&lt;p&gt;This is why we test demand.&lt;/p&gt;



&lt;h1 class=&quot;wp-block-heading&quot; id=&quot;h-common-pitfalls-when-testing-demand&quot;&gt;Common pitfalls when testing demand&lt;/h1&gt;



&lt;p&gt;Before we get into tactics, let’s cover some of the common risks when validating your app:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-sure-i-d-pay-that-is-an-unintentional-lie&quot;&gt;1. ‘Sure, I’d pay that’ is an unintentional lie&lt;/h3&gt;



&lt;p&gt;The book &lt;a href=&quot;https://www.momtestbook.com/&quot;&gt;&lt;em&gt;The Mom Test&lt;/em&gt;&lt;/a&gt; became popular for a reason: your mom (and friends, and basically anyone who wants to be nice) won’t give you hard truths. Even strangers can fall into the same trap — people like to please.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;If I think about all the things I’ve said I’d be willing to pay for or want to buy, I’d be very broke if I actually put my money where my mouth is. (Thankfully, I’m all talk and strangely frugal when it comes to buying things for myself — or paying for parking.)&lt;/p&gt;



&lt;p&gt;To sum up, we need to be conscious of our techniques. Choose methods that push people as close as possible to an &lt;em&gt;actual &lt;/em&gt;purchase. Most suggestions in this blog are designed to do exactly that: increasing the level of commitment step by step as they progress through the app. But honest signals are only half the battle.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-testing-with-an-irrelevant-audience&quot;&gt;2. Testing with an irrelevant audience&lt;/h3&gt;



&lt;p&gt;The wrong targeting plus false compliments is a deadly combination. Go too broad, and you’ll get a mix of love/hate feedback that leaves you spinning.&lt;/p&gt;



&lt;p&gt;When I see an app with wildly contradicting signals from a tiny audience, that usually tells me something else: the app isn’t clear yet on who their true customer is.&lt;/p&gt;



&lt;p&gt;You should be narrowing in on an audience where:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;You can effectively solve their problem&lt;/li&gt;



&lt;li&gt;You can stand out from the crowd&lt;/li&gt;



&lt;li&gt;They’re willing to pay for that solution&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-clicks-sales&quot;&gt;3. Clicks ≠ sales&lt;/h3&gt;



&lt;p&gt;Clicks might feel like progress, but they aren’t the same as paying customers (same for email sign-ups, sadly). &lt;strong&gt;Interest and commitment are not equal.&lt;/strong&gt; I said I’d buy all those things, but when push came to shove and they asked for my credit card details, my frugal side prevailed.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;I’ve seen founders get hyped about big pre-launch email lists, only to watch 2% convert. Painful.&lt;/p&gt;



&lt;p&gt;That said, once customers &lt;em&gt;are&lt;/em&gt; paying for your app, clicks become meaningful as they can signal which features they value most.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-4-messaging-matters&quot;&gt;4. Messaging matters&lt;/h3&gt;



&lt;p&gt;All of these techniques ask people to buy something that doesn’t fully exist yet. That’s a big ask. So your messaging has to work extra hard. Make sure you:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Stay clear: &lt;/strong&gt;No confusion about what you’re offering&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Build excitement: &lt;/strong&gt;Help people see the vision&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Build trust: &lt;/strong&gt;Show you’re real and will deliver&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Create urgency: &lt;/strong&gt;Give them a reason to act now&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;I say &lt;em&gt;messaging&lt;/em&gt; matters because it won’t just come down to your words, but also how you convey them. The images and videos you use to bring them to life can make the difference between “Yeah, sounds nice” and “Take my money now!”.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-key-models-for-testing-real-demand&quot;&gt;Key models for testing&lt;em&gt; real &lt;/em&gt;demand&lt;/h2&gt;



&lt;p&gt;There are multiple ways to test and validate demand even before you’ve built a product. And if you’ve already been building for a while before stumbling across this article, don’t worry. These techniques are organized by phase, so you can plug in wherever you are.&lt;/p&gt;



&lt;p&gt;The rule of thumb: the further along you are in building, the later the technique you’ll use. And the later the technique, the stronger the validation.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;683&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-39-1024x683.png&quot; alt=&quot;&quot; class=&quot;wp-image-46450&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-39-1024x683.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-39-300x200.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-39-768x512.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-39-1536x1024.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-39-50x33.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-39-60x40.png 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-39-696x464.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-39-560x373.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-39-444x296.png 444w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-39-708x472.png 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-39-80x53.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-39-48x32.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-39.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-phase-one-discovery-techniques-learning-what-problems-matter&quot;&gt;Phase one: Discovery techniques (learning what problems matter)&lt;/h3&gt;



&lt;p&gt;Phase one starts with discovery techniques. These don’t involve customers paying yet, but they force you to deeply understand what people have paid for before, and what they’re already saying in an unbiased way. I’ve kept them in because without this foundation, it’s hard to run effective phase two tests.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-1-spend-time-in-relevant-communities&quot;&gt;1. Spend time in relevant communities&lt;/h4&gt;



&lt;p&gt;In early days, one of the best ways to understand demand is hanging out where your target audience already spends time. People won’t be shouting, “I wish there was an app for XYZ”, but they will be asking questions, venting frustrations, and sharing problems.&lt;/p&gt;



&lt;p&gt;This is exactly what Eric Duffett did. Believe it or not, there’s a whole Twitter community for golfers. Eric used this community to learn from real golfers and even to validate early features and ideas.&lt;/p&gt;



&lt;p&gt;Communities are great for surfacing pain points. But they won’t always tell you what people actually want in a solution. Once you’ve got a general direction of the problem, it’s time to….&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-2-talk-to-real-users&quot;&gt;2. Talk to real users&lt;/h4&gt;



&lt;p&gt;Gosh, how people shy away from this. &lt;a href=&quot;https://www.revenuecat.com/blog/growth/customer-interviews-pricing-strategy/&quot;&gt;Customer interviews&lt;/a&gt; are where so many founders hesitate, but they’re essential.&lt;/p&gt;



&lt;p&gt;Compare Eric’s journey: with Shot Pattern, he quickly learned from his audience in month one. However, with his first app — essentially ‘meditation for golf’ — he spent years developing, recording content, and even contacting over 300 instructors. After five years of redesigns, he discovered (too late) that golfers didn’t actually &lt;em&gt;want&lt;/em&gt; what he was offering.&lt;/p&gt;



&lt;p&gt;Interviews aren’t about asking, “Would you like this?” (people will just say yes to be nice). Instead, try running &lt;a href=&quot;https://www.revenuecat.com/blog/growth/jtbd-paywall-optimization/&quot;&gt;jobs-to-be-done research&lt;/a&gt; and digging into:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;What’s the real problem they’re facing?&lt;/li&gt;



&lt;li&gt;How have they tried solving it before?&lt;/li&gt;



&lt;li&gt;What did they like/dislike about existing solutions?&lt;/li&gt;



&lt;li&gt;What have they already spent to solve this problem?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Because here’s the truth: past spending is a much better predictor of future spending than empty promises.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/how-to-launch-your-app/&quot;&gt;Market research&lt;/a&gt; is also essential for validating and identifying your unique value proposition, plus it can help determine initial pricing through &lt;a href=&quot;https://www.revenuecat.com/blog/growth/guide-to-app-pricing-research-methods/&quot;&gt;pricing research techniques&lt;/a&gt; and &lt;a href=&quot;https://www.revenuecat.com/blog/growth/what-drives-users-to-pay-jobs-to-be-done/&quot;&gt;asking the right questions&lt;/a&gt;.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-phase-two-transactional-validation-testing-willingness-to-pay&quot;&gt;Phase two: Transactional validation (testing willingness to pay)&lt;/h3&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-3-fake-door-testing-aka-painted-door-landing-pages&quot;&gt;3. Fake door testing (aka painted door landing pages)&lt;/h4&gt;



&lt;p&gt;At this stage, you might have no app — just a dream and a pay button. Except…it’s not real. When someone clicks, you tell them it isn’t ready yet and invite them to sign up for early access or an exclusive offer.&lt;/p&gt;



&lt;p&gt;A little bit cheeky, but it gets you as close as possible to willingness-to-pay, &lt;em&gt;before &lt;/em&gt;your app is ready. Many founders run fake door testing with small Meta ad campaigns — not for scale, but to see how a cold audience reacts. You can test different concepts, messages, and prices, while also building an initial list of engaged prospects for future feedback. &lt;a href=&quot;https://www.revenuecat.com/blog/growth/7-meta-ad-testing-frameworks-for-subscription-apps/&quot;&gt;Meta is great for running quick tests&lt;/a&gt; and experiments to validate different creatives, audiences and more. Once you’ve narrowed down your concept, you can proceed to accepting real payments.&lt;/p&gt;



&lt;p&gt;Now, remember what I said: clicks still aren’t the same as payments. But they’re a stronger signal than vague interest. People thought they were about to buy — and that’s a lot closer to reality. Just remember: this method will still overestimate actual conversion rates, because no one’s entered a real payment form yet. You haven’t put a ring on it (or in this case, you haven’t got their credit card information).&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-4-paid-waitlist-or-founder-s-offers&quot;&gt;4. Paid waitlist or founder’s offers&lt;/h4&gt;



&lt;p&gt;The previous waiting list is free to join, but as you start to validate your concept and prototype it, you may want to switch to a paid validation. We all know how many people drop off at the final step. I’ve seen this firsthand: a waitlist of ~500 people who said they’d buy the minute we launched… only to turn into ~60 actual purchases. Interest fades, life moves on, and hype alone won’t pay your bills.&lt;/p&gt;



&lt;p&gt;That’s why, once you’ve nailed down your concept and are working on a prototype, it’s worth moving to a ‘buy now, get access later’ model. Yes, it can feel scary to charge before launch — what if you pivot, or people get upset if the offer shifts? A simple way to de-risk this is to offer refundable pre-orders. Customers still show strong intent, but you give them peace of mind.&lt;/p&gt;



&lt;p&gt;A great example: Gabriel Wyner’s Fluent Forever app. Through Kickstarter, he raised over $500k in pre-launch support. His tiers made it easy to accommodate different levels of commitment: $5 provided updates and input on features, while the most popular tier—&amp;nbsp; &lt;em&gt;Early-Intermediate Speaker&lt;/em&gt; at $40 — offered beta access, a month’s full subscription, a training guide, and a discount on a lifetime plan. Over 1,500 backers chose that tier alone (a startup’s dream).&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;644&quot; height=&quot;308&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-37.png&quot; alt=&quot;&quot; class=&quot;wp-image-46446&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-37.png 644w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-37-300x143.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-37-50x24.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-37-84x40.png 84w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-37-560x268.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-37-80x38.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-37-48x23.png 48w&quot; sizes=&quot;auto, (max-width: 644px) 100vw, 644px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;It’s tempting to skip straight to validation that hands the money to you, but looking at Gabriel Wyner’s Fluent Forever Kickstarter shows why depth matters. He didn’t just toss up a pay button, he created trust and excitement with:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;A video walking through the product&lt;/li&gt;



&lt;li&gt;Established authority as a language-learning expert&lt;/li&gt;



&lt;li&gt;A five-minute walkthrough of the concept, prototype screens, methodology, and proof&lt;/li&gt;



&lt;li&gt;Reward tiers that added value beyond just the app&lt;/li&gt;



&lt;li&gt;Transparent pricing and a clear roadmap of what features would unlock at different funding levels&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;You don’t &lt;em&gt;need&lt;/em&gt; all of that, but the depth of content clearly helped him validate more effectively.&lt;/p&gt;



&lt;p&gt;That said, notice what the landing page revealed: “If we meet our minimum funding goals, we’ll start by creating a beta version of our app for Spanish (Latin America)… ready by April 2018.” Translation: they hadn’t built anything yet. Validation came first.&lt;/p&gt;



&lt;p&gt;One final note — &lt;strong&gt;urgency drives action&lt;/strong&gt;. Limited early-bird pricing, capped subscription slots, or time-sensitive deals all give people a reason to commit now, not later.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-nbsp-5-pre-sell-subscriptions-mvp-access-via-web&quot;&gt;&amp;nbsp;5. Pre‑sell subscriptions / MVP access via web&lt;/h4&gt;



&lt;p&gt;At this stage, you’re closer to launch. You’ve validated demand in phase one, tested willingness to pay in phase two, and now you can move to actually pre-selling subscriptions.&lt;/p&gt;



&lt;p&gt;If you already have a warm email list or community, this can be the fastest validation method. You can run the entire pre-sale through email before even publishing a public landing page.&lt;/p&gt;



&lt;p&gt;For this stage, you don’t have to have a full existing app or even a subscription to begin with. &lt;a href=&quot;https://www.businessinsider.com/headspace-cofounders-nba-delta-the-guardian-brought-meditation-million-users?international=true&amp;amp;r=US&amp;amp;IR=T&quot;&gt;Headspace famously started with in-person meditation sessions&lt;/a&gt;. Only after those kept selling out did they expand into an app.&lt;/p&gt;



&lt;p&gt;With preselling, the web is your friend:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;It avoids the friction of app downloads&lt;/li&gt;



&lt;li&gt;You can run a simple landing page + Stripe checkout&lt;/li&gt;



&lt;li&gt;With &lt;a href=&quot;https://www.revenuecat.com/docs/web/web-billing/redemption-links&quot;&gt;RevenueCat redemption links&lt;/a&gt;, users who pre-pay can unlock premium content once the app goes live&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The extra benefit of this is that implementing a&lt;a href=&quot;https://www.revenuecat.com/blog/growth/how-to-pre-sell-app-subscriptions-on-the-web-before-launch/?utm_source=chatgpt.com&quot;&gt; web pre-sale allows you to keep the 15-30% Apple would take&lt;/a&gt;, which makes a huge difference in those early days. And at this point, the positioning is clear: early access to an app that’s about to ship.&lt;/p&gt;



&lt;p&gt;💡 &lt;strong&gt;Pro tip: &lt;/strong&gt;Check out our full breakdown on &lt;a href=&quot;https://www.revenuecat.com/blog/growth/how-to-pre-sell-app-subscriptions-on-the-web-before-launch/&quot;&gt;how to pre-sell subscriptions on the web&lt;/a&gt; to guide you through the process.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-5-models-for-testing-customer-demand-and-validating-your-app&quot;&gt;5 Models for testing customer demand and validating your app&lt;/h2&gt;



&lt;p&gt;Now we’ve walked through five core validation techniques, here’s a quick comparison to help you decide which approach fits your stage, budget, and risk tolerance.&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Technique&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Phase&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Set-up time&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Cost&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Signal strength&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Best for&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Risk level&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Communities&lt;/td&gt;&lt;td&gt;Discovery&lt;/td&gt;&lt;td&gt;Low&lt;/td&gt;&lt;td&gt;Low&lt;/td&gt;&lt;td&gt;Low&lt;/td&gt;&lt;td&gt;Identifying pain points&lt;/td&gt;&lt;td&gt;Very low&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Talking to users&lt;/td&gt;&lt;td&gt;Discovery&lt;/td&gt;&lt;td&gt;Low–med&lt;/td&gt;&lt;td&gt;Low&lt;/td&gt;&lt;td&gt;Low–med&lt;/td&gt;&lt;td&gt;Validating problems &amp;amp; past spend&lt;/td&gt;&lt;td&gt;Very low&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Fake door test&lt;/td&gt;&lt;td&gt;Transactional&lt;/td&gt;&lt;td&gt;Medium&lt;/td&gt;&lt;td&gt;Low–med&lt;/td&gt;&lt;td&gt;Medium&lt;/td&gt;&lt;td&gt;Testing positioning &amp;amp; pricing&lt;/td&gt;&lt;td&gt;Low&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Paid waitlist or founders’ offer&lt;/td&gt;&lt;td&gt;Transactional&lt;/td&gt;&lt;td&gt;Med–high&lt;/td&gt;&lt;td&gt;Low–med&lt;/td&gt;&lt;td&gt;High&lt;/td&gt;&lt;td&gt;Proving intent to pay&lt;/td&gt;&lt;td&gt;Medium&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Pre-sell subscriptions / MVP access&lt;/td&gt;&lt;td&gt;Transactional&lt;/td&gt;&lt;td&gt;High&lt;/td&gt;&lt;td&gt;Medium&lt;/td&gt;&lt;td&gt;Very high&lt;/td&gt;&lt;td&gt;Launch-ready or near-launch apps&lt;/td&gt;&lt;td&gt;Med–high&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-a-step-by-step-framework-to-run-a-demand-test&quot;&gt;A step-by-step framework to run a demand test&lt;/h2&gt;



&lt;p&gt;There are five steps to setting up a demand test for success:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Define your success metric and what you want to learn&lt;/li&gt;



&lt;li&gt;Identify who to reach and how&lt;/li&gt;



&lt;li&gt;Set up the experiment&lt;/li&gt;



&lt;li&gt;Implement the validation technique&lt;/li&gt;



&lt;li&gt;Reflect and iterate&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Let’s walk through them step by step.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-1-define-your-success-metric-and-what-you-want-to-learn&quot;&gt;Step 1: Define your success metric and what you want to learn&lt;/h3&gt;



&lt;p&gt;Decide what you want to learn from the test. This will help you define the right metric to focus on. For example:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Number of people interested → signups&lt;/li&gt;



&lt;li&gt;Percentage of people who actually pay → conversion rate&lt;/li&gt;



&lt;li&gt;Who will stick around → retention metric&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Use benchmarks where available as a starting point, like the &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps-2025/&quot;&gt;RevenueCat State of Subscription Apps Report 2025&lt;/a&gt;, but please adjust them to be more realistic for this initial phase. It’s unlikely you’re going to hit scalable metrics at this stage; you’re looking for signals that your app is on the right track.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Write down all your assumptions and the potential risks — this helps you measure which beliefs hold true after the test, and design your experiment in the best possible way.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;For example, imagine you’re building a credit score tracking app, and your assumption is that your audience is more likely to be people improving their credit score to get a mortgage, rather than someone trying to get a loan. If this is an assumption you want to validate during demand testing, you should design your experiment to validate it, for example, by testing several ads per audience to compare performance.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-2-identify-who-to-reach-and-how&quot;&gt;Step 2: Identify who to reach and how&lt;/h3&gt;



&lt;p&gt;Now it’s time to clarify your target users: who is most likely to pay for your product? You may have set customer profiles in mind, or want to define some personas as part of your research.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Once you have a clear idea of &lt;em&gt;who &lt;/em&gt;your target users are, you need to actually reach them. Some good ways are:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Communities (forums, social media groups, Discord servers, etc.)&lt;/li&gt;



&lt;li&gt;Email lists&lt;/li&gt;



&lt;li&gt;Paid ads and organic social media&lt;/li&gt;



&lt;li&gt;Influencers or sponsorships&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Don’t worry if your audience is small, there are multiple ways to reach relevant users.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-3-set-up-the-experiment&quot;&gt;Step 3: Set up the experiment&lt;/h3&gt;



&lt;p&gt;For early discovery (techniques one–two), this means defining what you want to learn.&lt;/p&gt;



&lt;p&gt;For transactional tests (techniques three–five), this often involves building a landing page. Key elements:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Clear value proposition&lt;/li&gt;



&lt;li&gt;Visuals to explain the offering&lt;/li&gt;



&lt;li&gt;Social proof/trust signals&lt;/li&gt;



&lt;li&gt;Urgency triggers (limited-time offers, early-bird pricing)&lt;/li&gt;



&lt;li&gt;Strong call-to-action (CTA)&lt;/li&gt;



&lt;li&gt;Optional ‘more info’ sections to dive deeper&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Don’t just set up conversion tracking for the page, you should also track user interaction, e.g. clicks on specific sections, to understand interest — even if users don’t convert immediately.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-4-implement-the-validation-technique&quot;&gt;Step 4: Implement the validation technique&lt;/h3&gt;



&lt;p&gt;After discovery, you want to move quickly to techniques that involve real transactions (four–five).&lt;/p&gt;



&lt;p&gt;Set up payment options via web to capture more insights and reduce friction: &lt;a href=&quot;https://www.revenuecat.com/docs/web/integrations/stripe&quot;&gt;Stripe&lt;/a&gt;, &lt;a href=&quot;https://www.revenuecat.com/docs/web/integrations/paddle&quot;&gt;Paddle&lt;/a&gt;, or &lt;a href=&quot;https://www.revenuecat.com/docs/web/web-billing/redemption-links&quot;&gt;RevenueCat redemption links&lt;/a&gt; all work. Web pre-sales also avoid app-store fees and give flexibility in testing offers and messaging.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-5-reflect-and-iterate&quot;&gt;Step 5: Reflect and iterate&lt;/h3&gt;



&lt;p&gt;You’ve launched! Take a moment to be pleased with yourself, then dig into the data.&lt;/p&gt;



&lt;p&gt;Expect some tests to fail — it’s part of learning pricing, positioning, and offering. You can gain as much from an experiment that went badly as a successful one.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Analyze your results:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Did users fail to pay because they weren’t convinced, or was the offer misaligned?&lt;/li&gt;



&lt;li&gt;Which sections of your page drew attention? What did users care most about?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Conduct further user tests for qualitative feedback to improve messaging, visuals, and overall experience. Then, adjust your concept, page, and offering based on what you learn. Then, of course, re-test. And repeat the process 🔄&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-people-are-willing-to-pay-now-what&quot;&gt;People are willing to pay, now what?&lt;/h2&gt;



&lt;p&gt;This is only the start of your research journey. At first, you’re progressing through validation techniques, but once you’ve got those initial buyers, there’s still so much more to learn.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Ask ‘who are they and what triggered their interest?’. Understanding this can help you initially optimize the landing page and identify areas for further refining, which in turn informs your experiment backlog. For example, do you need to focus more on pricing tiers or communication?&lt;/p&gt;



&lt;p&gt;From there, you can ask for feedback on your product and gather testimonials to build trust with your audience. Having a close bond with initial customers is invaluable, so don’t take their time for granted. Some will just love being part of something new and exciting, while others will appreciate the VIP experience you give them.&lt;/p&gt;



&lt;p&gt;Just as clicks don’t equal willingness to pay, willingness to pay doesn’t mean retention. Monitor these initial cohorts closely to determine who stays and who doesn’t. Why do they leave?&amp;nbsp;&lt;/p&gt;



&lt;p&gt;You can learn so much from these strategic tests, and as we’ve seen Arnie and Eric’s case studies, the right buzz and interest can set your app up for long-term success.&amp;nbsp;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Exploring Modifier.Node for creating custom Modifiers in Jetpack Compose]]></title><description><![CDATA[In this article, you will learn how to create custom modifiers using the three primary APIs, Modifier.then(), Modifier.composed(), and Modifier.Node]]></description><link>https://www.revenuecat.com/blog/engineering/compose-custom-modifier/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/compose-custom-modifier/</guid><pubDate>Tue, 30 Sep 2025 01:47:21 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Modifier.Node_.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;In modern Android development, Jetpack Compose has become a modern UI toolkit, not only for building Android UIs but also for supporting Kotlin Multiplatform projects. Its ecosystem continues to grow rapidly, making it an essential part of today’s Android development.&lt;/p&gt;



&lt;p&gt;At the core of Compose lies the &lt;code&gt;Modifier&lt;/code&gt;. A modifier is more than just a way to apply styles and themes, it’s a design pattern that enables components to remain independent while still being easily customizable. By creating custom modifiers, you can encapsulate behavior once and reuse it throughout your app, making your UI code both cleaner and more flexible.&lt;/p&gt;



&lt;p&gt;In this article, we’ll explore how to create custom modifiers with primary three different APIs, &lt;code&gt;Modifier.then()&lt;/code&gt;, &lt;code&gt;Modifier.composed()&lt;/code&gt;, and &lt;code&gt;Modifier.Node&lt;/code&gt;, and demonstrates how &lt;a href=&quot;https://github.com/RevenueCat/purchases-android&quot;&gt;RevenueCat’s Android SDK&lt;/a&gt; leverages &lt;code&gt;Modifier.Node&lt;/code&gt; to deliver better UI performance.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-modifier-then&quot;&gt;Modifier.then&lt;/h2&gt;



&lt;p&gt;This is the easiest way to create a custom modifier by using the &lt;code&gt;Modifier.then()&lt;/code&gt; function, letting you combine multiple modifiers through chaining and return the final result, as shown in the example below:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-xSum3 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Composable\nfun Modifier.composableModifier(): Modifier {\n    val color = LocalContentColor.current.copy(alpha = 0.5f)\n    return this then Modifier.background(color)\n}\n\n@Composable\nfun MyComposable() {\n    val composedModifier = Modifier.composableModifier() \/\/ Cannot be extracted any higher\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;infix fun Modifier.then(other: Modifier)&lt;/code&gt; is the fundamental operator responsible for chaining modifiers in Jetpack Compose. It does not create a flat list but rather a recursive, two-element data structure called &lt;code&gt;CombinedModifier&lt;/code&gt;. This structure functions as a form of cons list or linked list, optimized for the specific directional traversal patterns required by the Compose UI toolkit.&lt;/p&gt;



&lt;p&gt;Let’s say there’s a simple modifier, that allows developers to chain modifiers declaratively to build up the properties of a UI element:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-17Whnc wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;Modifier\n    .padding(16.dp)      \/\/ First (outer)\n    .background(Color.Blue) \/\/ Second\n    .clickable { }       \/\/ Third (inner)&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;One might assume this creates a &lt;code&gt;List&amp;lt;Modifier.Element&amp;gt;&lt;/code&gt;. However, this is not the case. The &lt;code&gt;Modifier.then()&lt;/code&gt; function, which is implicitly called by each subsequent modifier in the chain, constructs a nested, tree-like structure. This design is a deliberate and crucial architectural choice for performance and correctness.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;If you look into the internal codes of the &lt;code&gt;Modifier.then()&lt;/code&gt; function, you’ll find it internally creates a new &lt;code&gt;CombinedModifier&lt;/code&gt; instance.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZUqhCm wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\ninfix fun then(other: Modifier): Modifier =\n    if (other === Modifier) this else CombinedModifier(this, other)\n        \n class CombinedModifier(internal val outer: Modifier, internal val inner: Modifier) : Modifier {\n    override fun &lt;R&gt; foldIn(initial: R, operation: (R, Modifier.Element) -&gt; R): R =\n        inner.foldIn(outer.foldIn(initial, operation), operation)\n\n    override fun &lt;R&gt; foldOut(initial: R, operation: (Modifier.Element, R) -&gt; R): R =\n        outer.foldOut(inner.foldOut(initial, operation), operation)\n\n    override fun any(predicate: (Modifier.Element) -&gt; Boolean): Boolean =\n        outer.any(predicate) || inner.any(predicate)\n\n    override fun all(predicate: (Modifier.Element) -&gt; Boolean): Boolean =\n        outer.all(predicate) &amp;amp;&amp;amp; inner.all(predicate)\n\n    override fun equals(other: Any?): Boolean =\n        other is CombinedModifier &amp;amp;&amp;amp; outer == other.outer &amp;amp;&amp;amp; inner == other.inner\n\n    override fun hashCode(): Int = outer.hashCode() + 31 * inner.hashCode()\n\n    override fun toString() =\n        \&amp;quot;[\&amp;quot; +\n            foldIn(\&amp;quot;\&amp;quot;) { acc, element -&gt;\n                if (acc.isEmpty()) element.toString() else \&amp;quot;$acc, $element\&amp;quot;\n            } +\n            \&amp;quot;]\&amp;quot;\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Its sole purpose is to take two modifiers, the existing chain (&lt;code&gt;this&lt;/code&gt;) and a new one (&lt;code&gt;other&lt;/code&gt;), and join them using the &lt;code&gt;CombinedModifier&lt;/code&gt; class. The &lt;code&gt;CombinedModifier&lt;/code&gt; is not a collection; it is a simple, two-element container. It acts as a node in a linked list.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1WBCb1 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;class CombinedModifier(internal val outer: Modifier, internal val inner: Modifier) : Modifier&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;code&gt;outer&lt;/code&gt;: This holds the modifier that came *before* in the chain.&lt;/li&gt;
&lt;/ul&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;code&gt;inner&lt;/code&gt;: This holds the modifier that was just added.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;When you write &lt;code&gt;Modifier.padding(8.dp).background(Color.Red)&lt;/code&gt;, the resulting structure is: &lt;code&gt;CombinedModifier(outer = CombinedModifier(outer = padding, inner = background), inner = clickable)&lt;/code&gt;&lt;/p&gt;



&lt;p&gt;This creates a left-associative, recursive structure that looks like this: &lt;code&gt;((padding then background) then clickable)&lt;/code&gt;&lt;/p&gt;



&lt;p&gt;This “linked list” structure is the key to understanding how modifiers are processed. The creative &lt;code&gt;CombinedModifier&lt;/code&gt; structure is realized through its traversal methods. A standard list has one way to iterate (from start to end). &lt;code&gt;CombinedModifier&lt;/code&gt; has two, with opposite directions, which are important for the different phases of the UI pipeline.&lt;/p&gt;



&lt;p&gt;So, ultimately, &lt;code&gt;Modifier.then&lt;/code&gt; is the simple yet optimized function that enables the entire declarative and chainable modifier system, forming the backbone of UI customization in Jetpack Compose.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;modifiercomposed&quot;&gt;Modifier.composed&lt;/h2&gt;



&lt;p&gt;Another available API is &lt;code&gt;Modifier.composed()&lt;/code&gt;, which lets you create a custom modifier that can leverage composable functions inside the lambda parameter.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1esI72 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;fun Modifier.myStatefulModifier() = composed {\n    val myState by remember { mutableStateOf(0f) }\n    \/\/ ... use myState\n    Modifier.drawBehind { \/* ... *\/ }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Internally, it behaves much like &lt;code&gt;Modifier.then&lt;/code&gt;, since it creates a new instance of &lt;code&gt;ComposedModifier&lt;/code&gt; and combines it with the existing modifier using &lt;code&gt;Modifier.then&lt;/code&gt;, as shown below:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-2wsIu4 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;fun Modifier.composed(\n    inspectorInfo: InspectorInfo.() -&gt; Unit = NoInspectorInfo,\n    factory: @Composable Modifier.() -&gt; Modifier,\n): Modifier = this.then(ComposedModifier(inspectorInfo, factory))&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;While &lt;code&gt;Modifier.composed&lt;/code&gt; makes it easy to create custom modifiers, this API is &lt;strong&gt;no longer recommended&lt;/strong&gt; because of the performance issues it introduces. The method allows you to invoke &lt;code&gt;@Composable&lt;/code&gt; functions, such as &lt;code&gt;remember&lt;/code&gt;, when creating a modifier instance. This is useful for attaching an instance-specific state, which lets the same modifier object be reused safely in multiple places.&lt;/p&gt;



&lt;p&gt;However, if you use &lt;code&gt;Modifier.composed&lt;/code&gt; without actually calling any &lt;code&gt;@Composable&lt;/code&gt; functions, it becomes unnecessary overhead. In this case, the modifier is no longer considered “&lt;em&gt;skippable”&lt;/em&gt;, which forces the runtime to perform additional work during recomposition. As a result, every recomposition re-executes the modifier chain to update state, leading to degraded performance.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;modifiernode-the-state-and-logic&quot;&gt;Modifier.Node: The state and logic&lt;/h2&gt;



&lt;p&gt;&lt;code&gt;Modifier.Node&lt;/code&gt; has been introduced since Compose UI version 1.3.0, and now this is the most recommended API for creating a custom Modifier against &lt;code&gt;Modifier.composed&lt;/code&gt;. While the &lt;code&gt;Modifier.composed&lt;/code&gt; factory provided an early mechanism for creating custom, stateful modifiers, it came with a significant performance cost: the creation of a new subcomposition for every modifier instance. This overhead could lead to degraded performance, especially in dynamic UIs like lists.&lt;/p&gt;



&lt;p&gt;The &lt;code&gt;Modifier.Node&lt;/code&gt; system was introduced to solve this problem directly. It is a new, lower-level API that allows developers to create stateful modifiers that are lightweight, lifecycle-aware, and integrated into Compose’s core rendering pipeline, without the overhead of subcomposition.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;modifiernode&quot;&gt;Modifier.Node&lt;/h3&gt;



&lt;p&gt;The &lt;code&gt;Modifier.Node&lt;/code&gt; implementation is the heart of your custom modifier. It is a stateful, mutable class that holds the modifier’s properties and implements its core logic. Critically, a &lt;code&gt;Modifier.Node&lt;/code&gt; instance can survive across multiple recompositions and can even be reused if its configuration remains the same.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-aWlOY wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/\/ The Node: Holds state (color) and logic (drawCircle)\nprivate class CircleNode(var color: Color) : DrawModifierNode, Modifier.Node() {\n    override fun ContentDrawScope.draw() {\n        \/\/ Implements the drawing logic\n        drawCircle(color)\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;Element&lt;/code&gt; has two primary responsibilities:&lt;/p&gt;



&lt;p&gt;1.&amp;nbsp; create(): Instantiates the &lt;code&gt;Modifier.Node&lt;/code&gt; the very first time the modifier is applied.&lt;/p&gt;



&lt;p&gt;2.&amp;nbsp; update(node: CircleNode): This is the key to performance. On subsequent recompositions, if the &lt;code&gt;Element&lt;/code&gt; has changed (determined by its &lt;code&gt;equals&lt;/code&gt; method), the &lt;code&gt;update&lt;/code&gt; function is called on the existing &lt;code&gt;Node&lt;/code&gt; instance. This allows you to update the &lt;code&gt;Node&apos;s&lt;/code&gt; state without the expensive cost of creating a new object.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; It is critical that your &lt;code&gt;ModifierNodeElement&lt;/code&gt; correctly implements &lt;code&gt;equals&lt;/code&gt; and &lt;code&gt;hashCode&lt;/code&gt;. Using a data class is the easiest way to ensure this. Without a correct implementation, &lt;code&gt;update&lt;/code&gt; may be called unnecessarily, defeating the performance benefits.&lt;/p&gt;
&lt;/blockquote&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-modifier-factory&quot;&gt;The Modifier Factory&lt;/h3&gt;



&lt;p&gt;This is the clean, public API surface function that developers will use. It simply uses the &lt;code&gt;then&lt;/code&gt; operator to chain the new &lt;code&gt;ModifierNodeElement&lt;/code&gt; onto the existing modifier chain.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-2tHIqO wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/\/ The Factory: The clean public API\nfun Modifier.circle(color: Color): Modifier = this.then(CircleElement(color))&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;You can now use your custom modifier just like any other built-in modifier function. By separating the stateless factory (&lt;code&gt;Element&lt;/code&gt;) from the stateful worker (&lt;code&gt;Node&lt;/code&gt;), it minimizes allocations and maximizes object reuse. Its rich set of specialized node types and lifecycle-aware APIs provides developers with direct, safe, and efficient access to every phase of the UI pipeline.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/getting-started/installation/android&quot;&gt;RevenueCat’s Android SDK&lt;/a&gt; also leverages Modifier.Node to achieve better UI performance. We recently migrated from the older Modifier.composed() API to &lt;code&gt;Modifier.Node&lt;/code&gt; when implementing the placeholder feature. You can check out &lt;a href=&quot;https://github.com/RevenueCat/purchases-android/blob/main/ui/revenuecatui/src/main/kotlin/com/revenuecat/purchases/ui/revenuecatui/composables/Placeholder.kt&quot;&gt;Placeholder.kt file&lt;/a&gt; to see the full changes and how this works in a real-world example.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;



&lt;p&gt;&amp;nbsp;In this article, you’ve explored how to create custom modifiers using the three primary APIs, &lt;code&gt;Modifier.then()&lt;/code&gt;, &lt;code&gt;Modifier.composed()&lt;/code&gt;, and &lt;code&gt;Modifier.Node&lt;/code&gt;, and learned how the &lt;a href=&quot;https://www.revenuecat.com/docs/getting-started/installation/android&quot;&gt;RevenueCat SDK&lt;/a&gt; leverages &lt;code&gt;Modifier.Node&lt;/code&gt; to improve UI performance. Understanding the trade-offs between these approaches is key: while &lt;code&gt;Modifier.then()&lt;/code&gt; is simple and lightweight, &lt;code&gt;Modifier.composed()&lt;/code&gt; introduces performance costs when misused, and &lt;code&gt;Modifier.Node&lt;/code&gt; offers a more modern, efficient way to build custom behaviors. By applying these patterns thoughtfully, you can create modifiers that are not only reusable and expressive but also optimized for performance, making your Compose UIs more stable.&lt;/p&gt;



&lt;p&gt;As always, happy coding!&lt;/p&gt;



&lt;p&gt;—&amp;nbsp;&lt;a href=&quot;https://github.com/skydoves&quot;&gt;Jaewoong&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[New York App Week 2025: Full schedule and how to join]]></title><description><![CDATA[Discover the complete schedule for New York App Week 2025 (Oct 13–16)]]></description><link>https://www.revenuecat.com/blog/company/new-york-app-week-2025-schedule/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/company/new-york-app-week-2025-schedule/</guid><pubDate>Mon, 29 Sep 2025 13:04:05 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Untitled-1200-x-728-px-1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;&lt;a href=&quot;https://www.appweek.events/&quot;&gt;New York App Week&lt;/a&gt; is just around the corner! From &lt;strong&gt;October 13–16, 2025&lt;/strong&gt;, New York City is becoming a hub for app growth, with four days of meetups, workshops, runs, dinners, and networking events — all centered around RevenueCat’s &lt;strong&gt;&lt;a href=&quot;https://appgrowthannual.com/&quot;&gt;App Growth Annual&lt;/a&gt;&lt;/strong&gt; conference on October 14. This community-driven initiative (proudly supported by RevenueCat) is designed to bring app builders and growth enthusiasts together across the city. And here’s the best part: &lt;strong&gt;you don’t need to attend App Growth Annual to join any App Week event.&lt;/strong&gt; Each event is independently open — so whether or not you’re at the conference, you can still &lt;strong&gt;discover, connect, and grow&lt;/strong&gt; all week long.&lt;/p&gt;



&lt;p&gt;❗️ &lt;strong&gt;Note:&lt;/strong&gt; In-person App Growth Annual tickets are now closed / waitlisted due to high demand, but you can still &lt;strong&gt;&lt;a href=&quot;https://appgrowthannual.com/virtual&quot;&gt;attend virtually for free&lt;/a&gt;&lt;/strong&gt; and catch all the main-stage action online. &lt;/p&gt;



&lt;p&gt;Now, let’s dive into the full App Week schedule. Here’s every event and how to join:&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-sunday-october-12&quot;&gt;&lt;strong&gt;Sunday, October 12&lt;/strong&gt;&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/ChatGPT-Image-Sep-30-2025-12_22_48-PM.png&quot; alt=&quot;&quot; class=&quot;wp-image-46436&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/ChatGPT-Image-Sep-30-2025-12_22_48-PM.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/ChatGPT-Image-Sep-30-2025-12_22_48-PM-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/ChatGPT-Image-Sep-30-2025-12_22_48-PM-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/ChatGPT-Image-Sep-30-2025-12_22_48-PM-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/ChatGPT-Image-Sep-30-2025-12_22_48-PM-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/ChatGPT-Image-Sep-30-2025-12_22_48-PM-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/ChatGPT-Image-Sep-30-2025-12_22_48-PM-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/ChatGPT-Image-Sep-30-2025-12_22_48-PM-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/ChatGPT-Image-Sep-30-2025-12_22_48-PM-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/ChatGPT-Image-Sep-30-2025-12_22_48-PM-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/ChatGPT-Image-Sep-30-2025-12_22_48-PM-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/ChatGPT-Image-Sep-30-2025-12_22_48-PM-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/ChatGPT-Image-Sep-30-2025-12_22_48-PM-48x48.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;strong&gt;Sunday Beers with Friends of the Cat: App week warmup with @thomasbcn&lt;/strong&gt; (6–9pm, location TBC) — &lt;em&gt;Join the pre-kickoff for New York App Work&lt;/em&gt;&lt;br&gt;​Organized by Thomas Petit, with drinks sponsored by RevenueCat, Sunday Beers is the opportunity to join a small group of founders, marketers and growth PMs for informal chats on mobile growth. Surrounded by the drinks, food, and heat of Hell’s Kitchen, NY, get together with like-minded folks ahead of the big week to connect and chill out.  &lt;br&gt;&lt;strong&gt;RSVP&lt;/strong&gt;: &lt;em&gt;Attendance will be limited; attendance by approval — request a spot &lt;strong&gt;&lt;a href=&quot;https://luma.com/kqrrcjwo&quot;&gt;here&lt;/a&gt;&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-monday-october-13&quot;&gt;&lt;strong&gt;Monday, October 13&lt;/strong&gt;&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;640&quot; height=&quot;394&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-29.png&quot; alt=&quot;&quot; class=&quot;wp-image-46386&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-29.png 640w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-29-300x185.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-29-50x31.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-29-65x40.png 65w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-29-560x345.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-29-481x296.png 481w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-29-80x49.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-29-48x30.png 48w&quot; sizes=&quot;auto, (max-width: 640px) 100vw, 640px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;The Solarium Bar at the Hotel Chelsea is a New York icon, and one of the places you can connect with other app growth professionals during New York App Week&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;&lt;strong&gt;Exclusive Evening in the Solarium (with STRV)&lt;/strong&gt; (6–9pm @ The Hotel Chelsea) — &lt;em&gt;An intimate cocktail night for founders, executives, and senior app leaders&lt;/em&gt; &lt;br&gt;Co-hosted by &lt;strong&gt;RevenueCat and STRV&lt;/strong&gt; at the legendary Hotel Chelsea’s Solarium Bar, this exclusive gathering offers open bar service, elegant bites, and a curated guest list of mobile growth movers and shakers. It’s &lt;em&gt;not&lt;/em&gt; a sit-down dinner — instead, expect a relaxed evening of mingling and meaningful conversations in one of NYC’s most iconic venues.&lt;br&gt;&lt;strong&gt;&lt;em&gt;RSVP: &lt;/em&gt;&lt;/strong&gt;&lt;em&gt;Space is very limited; attendance by approval — apply &lt;a href=&quot;https://luma.com/zrswc3dd&quot;&gt;&lt;strong&gt;here&lt;/strong&gt;&lt;/a&gt; to request an invite&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Apps Capital Dinner: Founders &amp;amp; Investors&lt;/strong&gt; (6.30–9pm, location TBA) — &lt;em&gt;Looking to acquire an app or find a buyer for your own?&lt;/em&gt; &lt;br&gt;This private dinner, hosted by &lt;strong&gt;EVHM Capital&lt;/strong&gt;, brings together consumer app founders and the investors who back and acquire them: Angels, VC, PE, and M&amp;amp;A. &lt;br&gt;&lt;strong&gt;RSVP&lt;/strong&gt;: &lt;em&gt;Sign up &lt;a href=&quot;https://luma.com/altobyft&quot;&gt;&lt;strong&gt;here&lt;/strong&gt;&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Health &amp;amp; Wellness Hootenanny&lt;/strong&gt; (7–9pm @ 169 Bar) — &lt;em&gt;Kick off App Week with a casual meet-and-greet focused on health &amp;amp; wellness apps (though everyone’s welcome!)&lt;/em&gt; &lt;br&gt;Hosted by &lt;strong&gt;Toby Sola&lt;/strong&gt;, founder of&amp;nbsp;&lt;a href=&quot;https://www.brightmind.com/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Brightmind Meditation&lt;/a&gt;, this fun gathering at the iconic 169 Bar invites app makers to swap ideas, share a recent lesson learned (and their biggest current challenge), and enjoy good company in a funky, historic NYC venue. Bonus: the first ten people to arrive get free snacks (think empanadas and dumplings), plus two drinks on the house. &lt;br&gt;&lt;strong&gt;RSVP&lt;/strong&gt;: &lt;em&gt;Sign up &lt;a href=&quot;https://luma.com/0tfr1ob0&quot;&gt;&lt;strong&gt;here&lt;/strong&gt;&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-tuesday-october-14-nbsp-app-growth-annual-2025&quot;&gt;&lt;strong&gt;Tuesday, October 14:&amp;nbsp;App Growth Annual 2025&lt;/strong&gt;&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;800&quot; height=&quot;420&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-30.png&quot; alt=&quot;&quot; class=&quot;wp-image-46388&quot; style=&quot;width:800px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-30.png 800w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-30-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-30-768x403.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-30-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-30-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-30-696x365.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-30-560x294.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-30-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-30-48x25.png 48w&quot; sizes=&quot;auto, (max-width: 800px) 100vw, 800px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;strong&gt;App Growth Annual&lt;/strong&gt; (all day @ The Glasshouse, NYC + online) is the flagship event of App Week. &lt;/p&gt;



&lt;p&gt;The world’s top app founders, growth leaders, and industry experts gather at &lt;strong&gt;App Growth Annual&lt;/strong&gt; for a full day of keynotes, tactical talks, and hands-on workshops — capped off with an epic afterparty at NYC’s Glasshouse, featuring Jason Paige and DJ Jazzy Jeff. &lt;/p&gt;



&lt;p&gt;Whether you’re one of the lucky ~300 who nabbed an in-person ticket, or are tuning in virtually, get ready for a content-packed day (and night). In-person registration is now closed, but &lt;strong&gt;the conference will be livestreamed — and anyone can still sign up to catch &lt;/strong&gt;all the main stage sessions and big announcements. &lt;/p&gt;



&lt;p&gt;&lt;strong&gt;RSVP&lt;/strong&gt;: &lt;em&gt;Virtual attendance is free — register &lt;a href=&quot;https://appgrowthannual.com&quot;&gt;&lt;strong&gt;here&lt;/strong&gt;&lt;/a&gt; to get your online access.&lt;/em&gt; (If you applied for in-person attendance earlier and got approved, we’ll see you at The Glasshouse!)&lt;/p&gt;



&lt;p&gt;✨ Pro tip: Even if you’re not at the conference, there are &lt;strong&gt;App Week meetups every other day&lt;/strong&gt; that you can attend freely. App Week is for everyone in the community, not just conference-goers!&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-wednesday-october-15&quot;&gt;&lt;strong&gt;Wednesday, October 15&lt;/strong&gt;&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;684&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-31-1024x684.png&quot; alt=&quot;&quot; class=&quot;wp-image-46390&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-31-1024x684.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-31-300x200.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-31-768x513.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-31-1536x1025.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-31-2048x1367.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-31-50x33.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-31-60x40.png 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-31-696x465.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-31-560x374.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-31-443x296.png 443w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-31-707x472.png 707w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-31-80x53.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-31-48x32.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Join OneSignal for a climb at New York’s The Edge, if you’re feeling brave&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;&lt;strong&gt;Runna ✕ RevenueCat 5K Run&lt;/strong&gt; (7.30am, along the Hudson River) — &lt;em&gt;Start your Wednesday with a breath of fresh air and a burst of endorphins&lt;/em&gt; &lt;br&gt;Join fellow app builders for a friendly &lt;strong&gt;5K run&lt;/strong&gt; along one of Manhattan’s most scenic routes, co-hosted by running app &lt;strong&gt;Runna&lt;/strong&gt; and RevenueCat. All paces are welcome, whether you’re a seasoned athlete or prefer a casual jog (walkers are welcome too!). The route goes along the Hudson River Greenway and even loops up the High Line, offering amazing skyline views. Finish at &lt;strong&gt;Bluestone Lane Cafe&lt;/strong&gt; by the Vessel, where coffee and breakfast await — a perfect chance to refuel and network with fellow app enthusiasts. Every participant gets a 2-week free trial of the Runna app to track their training, and finishers earn some exclusive swag (&lt;em&gt;did someone say limited-edition finisher’s medal and running cap?&lt;/em&gt; 👀)&lt;br&gt;&lt;strong&gt;RSVP&lt;/strong&gt;: &lt;em&gt;Lace up and register &lt;a href=&quot;https://luma.com/xv1h15wq&quot;&gt;&lt;strong&gt;here&lt;/strong&gt;&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;‘Software Sommelier’ by Lickability&lt;/strong&gt; (10am–12pm @ White Noise Coffee) — &lt;em&gt;Code and caffeine, anyone?&lt;/em&gt; &lt;br&gt;Product agency &lt;strong&gt;Lickability&lt;/strong&gt; is hosting a cozy, caffeinated design lab where you bring your app or prototype and get it ‘taste-tested’ by expert designers and developers. Think of it like Apple’s WWDC design labs — but in a coffee shop with a latte in hand. You’ll receive honest, actionable UX/UI feedback from the Lickability team in a friendly, hands-on setting. It’s a fantastic opportunity to polish your app’s design, connect with fellow builders, and walk away with fresh ideas (and probably a caffeine buzz).&lt;br&gt;&lt;strong&gt;RSVP&lt;/strong&gt;: &lt;em&gt;Space is limited to keep it intimate, reserve your spot &lt;a href=&quot;https://luma.com/i9koyhb3&quot;&gt;&lt;strong&gt;here&lt;/strong&gt;&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;City Climb &amp;amp; Lunch at The Edge (Hosted by OneSignal)&lt;/strong&gt; (Climb starts ~11.45am; lunch at 1pm @ Edge, Hudson Yards) — &lt;em&gt;Networking with a side of adrenaline&lt;/em&gt; &lt;br&gt;&lt;strong&gt;OneSignal&lt;/strong&gt; invites you to an unforgettable afternoon atop &lt;strong&gt;Edge NYC&lt;/strong&gt;, the highest outdoor sky deck in the Western Hemisphere. The event starts with an optional &lt;strong&gt;City Climb&lt;/strong&gt; — a thrill-seeking group of 18 will scale the outside of a 1,200-foot skyscraper (!) and lean out from the building’s peak. (Yes, you read that right. It’s the highest open-air building ascent in the world.) Not into heights? No worries! Join in at 1pm on the Sky Deck for a &lt;strong&gt;gourmet lunch and open bar&lt;/strong&gt; with jaw-dropping 360° views of Manhattan. With a semi-private space and curated food stations, plus plenty of time to mingle once climbers return to celebrate — this is a truly unique way to connect with fellow app professionals.&lt;br&gt;&lt;strong&gt;RSVP&lt;/strong&gt;: &lt;em&gt;Due to venue requirements, please request an invitation&lt;/em&gt; &lt;a href=&quot;https://onesignal.com/company-events/the-edge&quot;&gt;&lt;strong&gt;&lt;em&gt;here&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt; &lt;em&gt;(limited spots for the climb especially)&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;RevenueCat ✕ Applause: Golf @ Chelsea Piers&lt;/strong&gt; (5–8pm @ Chelsea Piers Driving Range) — &lt;em&gt;Fore! It’s time to unwind after a long day with some swings and smiles&lt;/em&gt; &lt;br&gt;Join the RevenueCat crew and &lt;strong&gt;Applause&lt;/strong&gt; for an evening at the Chelsea Piers &lt;strong&gt;golf driving range&lt;/strong&gt;. Whether you’re a scratch golfer or have never swung a club, this casual event is all about fun. Enjoy drinks and food as the sun sets over the Hudson, practice your drive with spectacular waterfront views, and network with other app folks between turns at the tee. Rumor has it a &lt;strong&gt;surprise celebrity guest&lt;/strong&gt; might show up — you won’t want to miss that photo op!  &lt;br&gt;&lt;strong&gt;RSVP&lt;/strong&gt;: &lt;em&gt;This event is invite-only (to keep the bays manageable) — request to join &lt;a href=&quot;https://luma.com/3qtuekbu&quot;&gt;&lt;strong&gt;here&lt;/strong&gt;&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;iOSoho &lt;strong&gt;✕&lt;/strong&gt; New York Android Engineers meetup&lt;/strong&gt; (6–9pm @ 397 West 38th Street, Studio 1505) — &lt;em&gt;Cross-platform rivalry who?&lt;/em&gt;&lt;br&gt;New York’s longest-running iOS meetup collaborates with the city’s biggest Android meetup for a killer double feature. First up: the story behind &lt;strong&gt;Analog&lt;/strong&gt;, a gorgeous film photography app and its journey from camera rolls to code. Then, a talk on &lt;strong&gt;AI (without the hype)&lt;/strong&gt;: what it can (and can’t) do for developers right now. Expect thoughtful insights, a lively Q&amp;amp;A, and plenty of hallway chatter. Doors open at 6pm, talks start at 7pm, and yes, there’ll be pizza. &lt;br&gt;&lt;strong&gt;RSVP:&lt;/strong&gt; &lt;em&gt;Sign up&lt;/em&gt; &lt;a href=&quot;https://www.meetup.com/iosoho/events/311233570/&quot;&gt;&lt;em&gt;here&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Replit NYC App Week Meetup&lt;/strong&gt; (6–9pm, location will be shared with confirmed attendees) — &lt;em&gt;Replit is coming to App Week!&lt;/em&gt; &lt;br&gt;Meet the team, hang out with fellow devs, and see what’s cooking at the intersection of AI and mobile. Whether you’re a long-time Replit user or just curious about what they’re building next, this is your chance to connect IRL. Expect good vibes, good demos, and plenty of stickers. &lt;br&gt;&lt;strong&gt;RSVP:&lt;/strong&gt; &lt;em&gt;Sign up&lt;/em&gt; &lt;a href=&quot;https://luma.com/replit-NYC-App-week&quot;&gt;&lt;em&gt;here&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Aperture Sessions: App Leaders Dinner&lt;/strong&gt; (7–9pm, East Village) — &lt;em&gt;An exclusive dinner for the crème de la crème of the app world&lt;/em&gt; &lt;br&gt;&lt;strong&gt;Hannah Parvaz&lt;/strong&gt; (founder of Aperture and award-winning marketer) is bringing her famed ‘Aperture Sessions’ to NYC for App Week, in partnership with RevenueCat. This invite-only &lt;strong&gt;App Leaders Dinner&lt;/strong&gt; gathers a room of founders and growth leaders for a night of great drinks, delicious bites, and even better conversation. No boring presentations, no sales pitches. Just real talk and camaraderie among peers who are scaling apps to the next level. (Previous Aperture Sessions have hosted folks from Meta, Google, Coinbase, Bumble, and more — so you never know who you’ll bump elbows with.) The dinner will be at a &lt;em&gt;secret&lt;/em&gt; upscale location in the East Village, disclosed only to confirmed attendees. &lt;br&gt;&lt;strong&gt;RSVP&lt;/strong&gt;: &lt;em&gt;Spaces are extremely limited — request an invite &lt;a href=&quot;https://luma.com/jy2wo1n2&quot;&gt;&lt;strong&gt;here&lt;/strong&gt;&lt;/a&gt; and the hosts will get back to you if approved&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Turkish Tech Founders Meetup&lt;/strong&gt; (7–10pm @ Slate NYC) – &lt;em&gt;Yemek, networking ve teknolojı!&lt;/em&gt; &lt;br&gt;Co-hosted by &lt;strong&gt;Neon Apps&lt;/strong&gt; and RevenueCat, in collaboration with Turks in Tech, this meetup welcomes members of the Turkish tech and app developer community (and friends!) for an evening of networking in NYC. Come enjoy Turkish delights (both the apps &lt;em&gt;and &lt;/em&gt;the food), share stories, and connect with founders, investors, and developers linked to Turkey’s vibrant app scene. You don’t have to be Turkish to attend, but expect a warm, welcoming atmosphere celebrating one of the world’s most dynamic tech communities. &lt;br&gt;&lt;strong&gt;RSVP&lt;/strong&gt;: &lt;em&gt;Sign up &lt;a href=&quot;https://luma.com/364mkthm&quot;&gt;here&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-thursday-october-16&quot;&gt;&lt;strong&gt;Thursday, October 16&lt;/strong&gt;&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;683&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-32-1024x683.png&quot; alt=&quot;&quot; class=&quot;wp-image-46413&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-32-1024x683.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-32-300x200.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-32-768x512.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-32-1536x1024.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-32-2048x1365.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-32-50x33.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-32-60x40.png 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-32-696x464.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-32-560x373.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-32-444x296.png 444w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-32-708x472.png 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-32-80x53.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-32-48x32.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Connect with other app folks on the court for a game of Americano-style padel&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;&lt;strong&gt;‘Sweaty App Growth Morning’ Workout @ Barry’s&lt;/strong&gt; (10am @ Barry’s Bootcamp, NYC) — &lt;em&gt;After three days of app growth talks and evening mixers, it’s time to sweat it out!&lt;/em&gt; &lt;br&gt;Join fellow App Week attendees for a group &lt;strong&gt;HIIT workout&lt;/strong&gt; at &lt;strong&gt;Barry’s&lt;/strong&gt;, the famous high-intensity interval training studio known for making even celebs drip sweat. This private class will get your heart pumping and muscles working, led by one of Barry’s top instructors. Expect a killer playlist, red room energy, and camaraderie as you push through treadmill sprints and strength circuits together. All fitness levels are welcome (Barry’s instructors can modify exercises for newbies), so don’t be shy! It’s a fantastic way to energize your morning and maybe even form a few bonds through shared pain 💪 &lt;br&gt;&lt;strong&gt;RSVP&lt;/strong&gt;: &lt;em&gt;Coming soon&lt;/em&gt; — &lt;em&gt;a registration link will be provided to secure your spot in the class (limited capacity, because nobody likes an overly crowded gym!)&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Women in Apps Brunch&lt;/strong&gt; (11.30am–1.30pm @ Manuela) — &lt;em&gt;Bringing together the incredible women of the app industry for food and inspiration&lt;/em&gt; &lt;br&gt;Hosted by &lt;strong&gt;Molly Williams&lt;/strong&gt;, this sit-down brunch at the chic Manuela restaurant (SoHo) is all about community and conversation among women founders, builders, marketers, and dreamers in the app world. Over delicious food in a beautiful setting, attendees will share ideas, swap stories, and celebrate the successes (and challenges overcome) of women in tech and apps. Come prepared for meaningful connections and plenty of inspiration. Allies and supporters are welcome too. &lt;br&gt;&lt;strong&gt;RSVP&lt;/strong&gt;: &lt;em&gt;Grab your seat&lt;/em&gt; &lt;a href=&quot;https://luma.com/t7n6toih&quot;&gt;&lt;strong&gt;&lt;em&gt;here&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt; — &lt;em&gt;(spots nearly full)&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Padel Americano: Founders Racket Club ✕ RevenueCat&lt;/strong&gt; (6–8pm @ Williamsburg) — &lt;em&gt;Game, set, app&lt;/em&gt;&lt;br&gt;We’re taking to the courts in Williamsburg for an &lt;strong&gt;Americano-style padel tournament&lt;/strong&gt; hosted by Founders Racket Club and RevenueCat. Never played? Don’t worry — rackets and coaching are included, plus food and drinks to keep the energy up between matches. Whether you come to smash winners or just sip and spectate, it’s a guaranteed good time. &lt;br&gt;&lt;strong&gt;RSVP:&lt;/strong&gt; &lt;em&gt;Sign up &lt;a href=&quot;https://luma.com/8ksy2kxc&quot;&gt;here&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;APPetite for Growth (Dinner w/ Jampp &amp;amp; YouAppi)&lt;/strong&gt; (8pm @ Invesco QQQ Festival Campus, Pier 17) — &lt;em&gt;We’re capping off App Week with a feast for both your palate and your mind&lt;/em&gt; &lt;br&gt;&lt;strong&gt;Jampp&lt;/strong&gt; and &lt;strong&gt;YouAppi&lt;/strong&gt; (with a little help from RevenueCat) are hosting &lt;strong&gt;APPetite for Growth&lt;/strong&gt;, a curated dinner experience featuring &lt;strong&gt;world-class cuisine by chef Marcus Samuelsson&lt;/strong&gt; and a gathering of top app marketing minds. Set at the scenic Pier 17 overlooking the East River, this dinner will pair gourmet dishes with tasting menu discussions on the future of mobile growth. Enjoy an open bar and a multi-course culinary experience while networking with leaders who are shaping what’s next in user acquisition, monetization, and engagement. The perfect blend of &lt;strong&gt;sip, savor, and strategize&lt;/strong&gt;. &lt;br&gt;&lt;strong&gt;RSVP&lt;/strong&gt;: &lt;em&gt;This is an application-only event (seating is very limited). Apply&lt;/em&gt; &lt;a href=&quot;https://resources.jampp.com/appetite-for-growth/&quot;&gt;&lt;strong&gt;&lt;em&gt;here&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt; &lt;em&gt;to join the guest list&lt;/em&gt;&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;p&gt;&lt;strong&gt;We can’t wait to see you at New York App Week!&lt;/strong&gt; Whether you’re pounding the pavement in the 5K, learning in a coffee shop, climbing a skyscraper, or clinking glasses at a dinner, App Week is all about bringing our community together. If you’re in NYC, be sure to RSVP for the events that interest you. If you’re remote, tune into App Growth Annual online and join the conversation on social. Let’s make this week one to remember — see you there! 🚀🎉&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Sell the job, not the features: how JTBD paywalls boosted conversion by 169%]]></title><description><![CDATA[A five-step JTBD workflow for optimizing paywalls]]></description><link>https://www.revenuecat.com/blog/growth/jtbd-paywall-optimization/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/jtbd-paywall-optimization/</guid><pubDate>Thu, 25 Sep 2025 17:06:43 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/JTBD-led-paywall-tests.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;&lt;a href=&quot;https://www.linkedin.com/in/lea-samrani/&quot;&gt;Léa Samrani&lt;/a&gt; just &lt;em&gt;gets&lt;/em&gt; app growth. She’s worked in product roles at apps Bumble, Uptime, and Passion, all of which have millions of users. (Yeah, I’m fangirling a little over here.)&lt;/p&gt;



&lt;p&gt;So I had to ask her: where has she seen the biggest return-on-investment (ROI) in terms of &lt;a href=&quot;https://revenuecat.com/blog/growth/2025-app-monetization-trends/\&quot;&gt;improving app monetization&lt;/a&gt;?&lt;/p&gt;



&lt;p&gt;Spoiler alert: it wasn’t new features, it wasn’t new designs or focusing on improving retention.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;It was the unsung hero: &lt;strong&gt;Jobs to be Done (JTBD)&lt;/strong&gt;. Aka, understanding what your end user is &lt;em&gt;actually&lt;/em&gt; trying to achieve.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Since then, Léa has advised over 45+&lt;strong&gt; &lt;/strong&gt;apps as a freelance Product and Growth advisor, and the biggest ROI consistently comes from focusing on JTBD. As she puts it: &lt;strong&gt;“If we could publish the ROI number, &lt;/strong&gt;&lt;strong&gt;&lt;em&gt;everyone&lt;/em&gt;&lt;/strong&gt;&lt;strong&gt; would spend more time on user interviews.”&lt;/strong&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-jtbd-success-stories&quot;&gt;JTBD success stories&lt;/h2&gt;



&lt;p&gt;But not everyone wants to spend time speaking to users and understanding their JTBD. So Léa’s developed a strategic approach to JTBD research — one that immediately feeds into paywall and onboarding optimizations, driving quick wins and justifying deeper investment in customer insights.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;The results speak for themselves. Here are just a few she’s proud of:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Kids app, &lt;a href=&quot;https://smarttales.app/&quot;&gt;Smart Tales&lt;/a&gt;: 72% increase in free-to-paid conversion rate&lt;/li&gt;



&lt;li&gt;Teenager app: 322% increase in ARPU&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Community learning app: 169% increase in free-to-paid conversion rate&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Those are some &lt;em&gt;impressive&lt;/em&gt; figures. But what’s most interesting? All these apps were in the same education category, yet each uncovered a completely different JTBD. Proof that you can’t assume, and you definitely can’t copy-paste a JTBD from your competitors.&lt;/p&gt;



&lt;p&gt;Léa says this is what makes JTBD-led optimizations both the easiest &lt;em&gt;and&lt;/em&gt; hardest trick in the book: there’s plenty of content out there on JTBD, but doing the &lt;a href=&quot;https://revenuecat.com/blog/growth/customer-interviews-pricing-strategy/&quot;&gt;customer interviews&lt;/a&gt; — and implementing the insights well — is the hard part. You can’t just copy your competitors. You have to go out and deeply &lt;strong&gt;understand&lt;/strong&gt; &lt;strong&gt;&lt;em&gt;your&lt;/em&gt;&lt;/strong&gt; &lt;strong&gt;users&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;And here’s the other catch: it’s never just one test. The teenager app involved around 10 experiments, while the community learning one was about 20! This isn’t about finding a single silver bullet; it’s about &lt;strong&gt;building a strategic roadmap to sustainably improve your free-to-paid conversion.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;I sat down with Léa to unpack the success of SmartTales, and walk through her step-by-step approach to using JTBD to optimise your paywall.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;✨ Pro tip&lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;With &lt;a href=&quot;https://www.revenuecat.com/blog/growth/revenuecat-paywalls-v2/#:~:text=Paywalls%20are%20built%20on%2Ddevice,app%20update%20for%20each%20one.&quot;&gt;RevenueCat’s Paywalls v2&lt;/a&gt; recently released, testing your paywall is quicker than ever — making it even more worthwhile to invest in upfront research and set your future experiments up for success.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-most-founders-don-t-want-to-focus-on-jtbd-why&quot;&gt;Most founders don’t want to focus on JTBD — why?&lt;/h2&gt;



&lt;p&gt;Imagine you’re a founder (if you are one, no imagination needed). You’ve poured countless hours, sweat, and tears into building your startup from the ground up. Every inch of it reflects the problem you’ve seen time and time again — maybe even struggled with yourself. You’re immensely proud of what you’ve built.&lt;/p&gt;



&lt;p&gt;Then, a team member or external advisor (I’ve played this bad cop role before) says:&lt;/p&gt;



&lt;p&gt;“You need to focus less on what &lt;em&gt;you&lt;/em&gt; think is the most important problem. Take a step back, figure out what your customers’ real problems are, then talk about those problems.”&lt;/p&gt;



&lt;p&gt;*Cue internal scream*&lt;/p&gt;



&lt;p&gt;It feels so wrong. You’ve created something &lt;em&gt;amazing&lt;/em&gt; to solve a problem, and now you’re being told to abandon that and focus on ‘selling techniques.’ No thanks!&lt;/p&gt;



&lt;p&gt;But JTBD is far from a ‘selling technique’. The reality is that &lt;strong&gt;good products often struggle to communicate the problem they solve.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Léa and I have both faced pushback on using the JTBD framework, but the truth is, the person suggesting this isn’t trying to undermine the original reason for your app (even though it still hurts). They’re trying to help you take your business to the next level by taking a step away from your first-hand experience, and focusing on the highest-paying, best-converting end user.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;However, that’s hard to take on board when the next advice includes:&lt;/p&gt;



&lt;p&gt;&lt;em&gt;“By the way, it’s going to take hours and hours of user interviews. Have fun!”&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;*Cue second internal scream*&lt;/p&gt;



&lt;p&gt;And there you have it — the reason most founders shy away from JTBD research. There’s constant pressure to move quickly, grow fast, so the idea of slowing down and learning to conduct interviews doesn’t exactly sound appealing.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Still not sold?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Think of it this way: if it takes 30–50 hours to conduct this research, but you see results like the case studies in the intro (72%–169% increase in free-to-paid conversion, 322% increase in ARPU) — would you consider that a positive ROI?&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Almost certainly, because that value will ripple through the rest of your funnel. So, how can you achieve those results?&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-by-step-jtbd-workflow-for-subscription-app-paywalls-nbsp&quot;&gt;Step-by-step JTBD workflow for subscription app paywalls&amp;nbsp;&lt;/h2&gt;



&lt;p&gt;Let’s dive into when and how to use Léa’s approach, and walk through the case of &lt;a href=&quot;https://smarttales.app/&quot;&gt;Smart Tales&lt;/a&gt;, an educational app for kids. (We’ll touch on the other two examples, but keep those anonymous for the brands involved.)&lt;/p&gt;



&lt;p&gt;Unlike our hypothetical founder, the Smart Tales founders were ready and willing to put in the work from the start. They met Léa through the &lt;a href=&quot;https://www.systm.co/&quot;&gt;SYSTM growth program&lt;/a&gt;, where she was their coach, and they were rewarded for their hard work with a&lt;strong&gt; 72% increase in free-to-paid conversion rate &lt;/strong&gt;across a series of experiments — incredible results.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Here’s how they did it, and how you can too.&amp;nbsp;&lt;/p&gt;


&lt;div class=&quot;lazyblock-a5682b0841d2-28F3a0 wp-block-lazyblock-a5682b0841d2&quot;&gt;&lt;h3 data-custom-text=&quot;&quot; data-text=&quot;1. Identify signals you need to focus on JTBD&quot; id=&quot;1-identify-signals-you-need-to-focus-on-jtbd&quot;&gt;1. Identify signals you need to focus on JTBD&lt;/h3&gt;&lt;/div&gt;


&lt;p&gt;The first step is the shortest — you need to notice the problem.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Smart Tales has a genuinely great product, and their retention figures reflect that. Even now, with over 11,000 reviews, they maintain a 4.6 rating on the Apple App Store. However, at the time, the front of the funnel was lagging. They were focused on highlighting the quality of their lessons and content, but they were missing the core JTBD. While their app helped kids practice math, science, and reading, that wasn’t the real problem they needed to solve.&lt;/p&gt;



&lt;p&gt;In general, &lt;strong&gt;strong retention paired with low conversion rates (and often low click-through rates) is a key indicator of a JTBD issue.&lt;/strong&gt;&lt;/p&gt;


&lt;div class=&quot;lazyblock-a5682b0841d2-Z1YnFCH wp-block-lazyblock-a5682b0841d2&quot;&gt;&lt;h3 data-custom-text=&quot;&quot; data-text=&quot;2. Practice to conduct strong user interviews&quot; id=&quot;2-practice-to-conduct-strong-user-interviews&quot;&gt;2. Practice to conduct strong user interviews&lt;/h3&gt;&lt;/div&gt;


&lt;p&gt;Léa explains that customer care logs, reviews, and user tests are all great, but they don’t allow you to dive deeply into the customer’s job and the problem you’re trying to solve. These sources can be too leading — often feature-focused, rather than asking the essential questions you need to uncover.&lt;/p&gt;



&lt;p&gt;Conducting user interviews &lt;em&gt;well&lt;/em&gt; is the hardest part. But Smart Tales, once again, didn’t deter. They practiced before conducting some of the best user interviews Léa had ever seen. She &lt;strong&gt;strongly advises taking the time to practice your user interviews first if you don’t have experience.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;How? Ideally, don’t talk to friends and family, who you (hopefully) know too well. Instead, try interviewing colleagues or acquaintances at other brands about a completely unrelated product.&lt;/p&gt;



&lt;p&gt;Léa once played the interview guinea pig herself, allowing a client to interview her about her living room table. What JTBD was that table serving her? It wasn’t even related to subscription apps, but that’s the key:&lt;strong&gt; it needs to be something you know nothing about to avoid falling into assumption mode.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;What had seemed like the most standard, run-of-the-mill purchase ever for Léa ended up revealing how much that table meant to her and what it symbolized in terms of buying her first home. She’ll never look at that table the same way again!&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-5-write-your-questions-and-check-them&quot;&gt;2.5. Write your questions (and check them)&lt;/h3&gt;



&lt;p&gt;I’ve walked through &lt;a href=&quot;https://www.revenuecat.com/blog/growth/what-drives-users-to-pay-jobs-to-be-done/&quot;&gt;JTBD questions to understand what drives customers to pay&lt;/a&gt; before, but I couldn’t resist asking Léa her favorite questions (yes, I’m a JTBD nerd, what do you want from me?). Her favorite question was:&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;What do you think the app was going to enable you to do?&amp;nbsp;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Or phrased differently: &lt;em&gt;What did you think you could do with this product?&lt;/em&gt;&lt;strong&gt; &lt;/strong&gt;You’re trying to understand: what did they expect to feel, and why did they buy it? How you phrase these questions is key.&lt;/p&gt;



&lt;p&gt;Léa once asked a customer about why they purchased a VPN system, their response? “Err… security?” Oops, a bit too literal. While ‘security’ might be the surface-level reason, you need to uncover &lt;em&gt;why &lt;/em&gt;they wanted security. What was that security going to enable them to do? For example, peace of mind that their data is secure.&lt;/p&gt;



&lt;p&gt;If interviewees struggle to answer, Léa suggests asking about their buying journey — the moment they decided to invest in your app. Ask plenty of contextual questions about when and where the decision took place, as this will help them recall what they were worried about or hoping for.&lt;/p&gt;



&lt;p&gt;Reading this, you can see why conducting these interviews and reading those signals is a bit of an art form. It takes practice. So, just like Smart Tales, take the time to prepare—not only your questions but yourself for conducting strong interviews. If you’re worried, Léa suggests conducting the interview with someone else, as they can help ensure you’re diving deep enough or take notes so you can focus entirely on the interview.&lt;/p&gt;


&lt;div class=&quot;lazyblock-a5682b0841d2-Zun6UK wp-block-lazyblock-a5682b0841d2&quot;&gt;&lt;h3 data-custom-text=&quot;&quot; data-text=&quot;3. Examine your user interviews to understand your JTBD&quot; id=&quot;3-examine-your-user-interviews-to-understand-your-jtbd&quot;&gt;3. Examine your user interviews to understand your JTBD&lt;/h3&gt;&lt;/div&gt;


&lt;p&gt;It can be tempting after an interview to throw all your notes into an AI tool and ask it to tell you your JTBD. Please, &lt;em&gt;please&lt;/em&gt; don’t.&lt;/p&gt;



&lt;p&gt;I was thrilled to see that Léa, like me, takes the ‘old-fashioned’ approach of discussing JTBD, walking through findings and insights together. While AI is a great tool for some types of analysis, there are many subtleties in user interviews that AI can miss, as well as broader context about your app that is key. For example,&lt;strong&gt; the right JTBD isn’t necessarily the one mentioned the most, but the one you can solve better than your competitors.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;What Smart Tales identified as their biggest JTBD was unexpected. It wasn’t teaching kids math, science, and reading. It was helping parents deal with that dreaded screen switch-off moment.&lt;/p&gt;



&lt;p&gt;Parents (and cool aunties like me) know this moment &lt;em&gt;all too well&lt;/em&gt;.&lt;/p&gt;



&lt;p&gt;For example, I offered to take two of my cousins’ kids to the park the other day. They were all quietly sitting on their various iPads, reluctant to come. I thought I had all the convincing power on my side: the dog (that they love) was coming, there was a playground, even hot chocolate and shortbread (I’m not above bribing them). But nope, not good enough.&lt;/p&gt;



&lt;p&gt;While we eventually got the eldest ready to go, all hell broke loose with the youngest. He was perfectly happy behind his screen and &lt;em&gt;not&lt;/em&gt; happy to be dragged out. Cue crying and screaming. But don’t worry, once we got to the park, he was overjoyed, racing around having the best time ever. The journey there, though? Let’s just say it was rough.&lt;/p&gt;



&lt;p&gt;This is the problem (slightly ironically) that Smart Tales solves, they learned from their interviews. The app ensures kids spend non-addictive time behind their screens, so when switch-off time comes, it isn’t the end of the world. And even if the switch-off time isn’t here yet, they’re still spending positive, enriching time on their devices.&lt;/p&gt;



&lt;p&gt;If we try to phrase this as the JTBD, it’s:&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;When&lt;/strong&gt; my kid is using a screen&lt;br&gt;&lt;strong&gt;I want a &lt;/strong&gt;way to ensure they can learn something&lt;br&gt;&lt;strong&gt;So that &lt;/strong&gt;they are not mindlessly scrolling and addicted&lt;/p&gt;



&lt;p&gt;The problem they were solving was screen addiction. With this understanding, it was time to start improving their paywall performance.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-why-you-can-t-copy-your-competitor-s-jtbd&quot;&gt;Why you can’t copy your competitor’s JTBD&lt;/h4&gt;



&lt;p&gt;As an aside, let’s dip into the other app examples. While all the cases Léa shared were education apps, they each had a completely different JTBD.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;For the second case, the &lt;a href=&quot;https://revenuecat.com/blog/growth/how-to-scale-app-niche-audience/&quot;&gt;app audience&lt;/a&gt; was slightly older (teenagers), and the JTBD was helping them use the app to pass their exams, giving them confidence that by using the app, they could achieve the grades they wanted and get into their dream universities. For the community learning app, the JTBD came down not to learning, but to &lt;a href=&quot;https://www.revenuecat.com/blog/growth/solve-app-problems-emotionally/&quot;&gt;a feeling of belonging&lt;/a&gt; in a community.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Even with very similar apps and JTBDs, it’s the nuances in your language and showing how you’ll help users achieve their JTBD that set you apart.&lt;/p&gt;


&lt;div class=&quot;lazyblock-a5682b0841d2-pg7Lc wp-block-lazyblock-a5682b0841d2&quot;&gt;&lt;h3 data-custom-text=&quot;&quot; data-text=&quot;4. Improving the paywall starts before the paywall&quot; id=&quot;4-improving-the-paywall-starts-before-the-paywall&quot;&gt;4. Improving the paywall starts before the paywall&lt;/h3&gt;&lt;/div&gt;


&lt;p&gt;Often when we think of paywall experiments and optimizations, we focus solely on the paywall itself. While you can definitely use your JTBD to improve the paywall, Léa finds the most significant impact often happens earlier in the process.&lt;/p&gt;



&lt;p&gt;Use the start of the journey to test, validate, and refine your JTBD (there’s a &lt;a href=&quot;https://www.revenuecat.com/blog/growth/testing-strategies-for-low-traffic-apps/&quot;&gt;whole guide on using these methods here&lt;/a&gt;). Léa explains that this early stage is where you see the biggest volume of users — especially for startups — so you can make a large initial impact, assuming your retention is already strong.&lt;/p&gt;



&lt;p&gt;From there, begin thinking about onboarding: how will that process help users achieve their JTBD?&lt;/p&gt;



&lt;p&gt;For Smart Tales and the app for teenagers, both apps initially directed users straight to the paywall with little to no context. Considering the JTBD, the team tested adding positive friction through onboarding. This looked like introducing helpful context and questions, to guide users understanding how the app will help them achieve their JTBD.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;Smart Tales 2024 onboarding&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/PwcrgGeQ8pQ?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Smart Tales’ onboarding screens&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;This doesn’t mean adding questions &lt;em&gt;you&lt;/em&gt; want answered, like “Where did you hear about us?” or “How old are you?”. That’s just negative friction.&lt;/p&gt;



&lt;p&gt;Instead, one thing Léa loves to test is integrating user reviews that reflect the core JTBD, then subtly asking the user, &lt;em&gt;‘Can you relate?’&lt;/em&gt; It builds trust and signals that the app understands them, especially when this messaging stays consistent throughout the journey. Smart Tales does exactly this in their onboarding:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;520&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-25-520x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-46340&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-25-520x1024.png 520w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-25-152x300.png 152w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-25-768x1511.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-25-780x1536.png 780w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-25-25x50.png 25w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-25-20x40.png 20w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-25-236x464.png 236w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-25-696x1370.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-25-285x560.png 285w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-25-150x296.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-25-240x472.png 240w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-25-41x80.png 41w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-25-24x48.png 24w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-25.png 813w&quot; sizes=&quot;auto, (max-width: 520px) 100vw, 520px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Screen from the 2024 Smart Tale onboarding&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;Another strong example comes from Headway, the book summary app. They clearly understand their audience’s core problem: not having enough time to read full books.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;451&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-20-451x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-46330&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-20-451x1024.png 451w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-20-132x300.png 132w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-20-677x1536.png 677w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-20-22x50.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-20-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-20-204x464.png 204w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-20-696x1580.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-20-247x560.png 247w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-20-130x296.png 130w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-20-208x472.png 208w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-20-35x80.png 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-20-21x48.png 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-20.png 705w&quot; sizes=&quot;auto, (max-width: 451px) 100vw, 451px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Headway social proof in onboarding&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;You can even test a similar approach directly on the paywall. One of &lt;a href=&quot;https://www.revenuecat.com/blog/growth/revenuecat-paywalls-v2/#:~:text=Paywalls%20are%20built%20on%2Ddevice,app%20update%20for%20each%20one.&quot;&gt;RevenueCat’s Paywall v2&lt;/a&gt; templates includes space to showcase a JTBD-focused review, helping reinforce value right at the decision point.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;560&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-21-560x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-46332&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-21-560x1024.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-21-164x300.png 164w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-21-27x50.png 27w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-21-22x40.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-21-254x464.png 254w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-21-306x560.png 306w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-21-162x296.png 162w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-21-258x472.png 258w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-21-44x80.png 44w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-21-26x48.png 26w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-21.png 658w&quot; sizes=&quot;auto, (max-width: 560px) 100vw, 560px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;RevenueCat’s JTBD-focused review paywall template&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;For the community learning app, one of the most impactful experiments was changing the timing of the paywall. They discovered the &lt;em&gt;aha! &lt;/em&gt;moment came after six lessons — enough to show users they could consistently learn and rely on the app to structure their progress. Even though more users saw the paywall earlier, placing it after those six lessons drove better results. The takeaway? Timing matters, and &lt;strong&gt;the ideal moment to show the paywall is when users start to feel their JTBD is being met&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;This consistent focus on JTBD across the journey can make testing more complex. Léa pointed out it’s rarely one big test that drives a lift — it’s a series of thoughtful experiments, with consistent language and messaging that compounds over time.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;So what kind of tests worked best? A mix. Léa found combining larger experiments (like adding positive friction to onboarding) with smaller ones (like tweaking App Store copy and screenshots) delivered the strongest results.&lt;/p&gt;


&lt;div class=&quot;lazyblock-a5682b0841d2-9AKmz wp-block-lazyblock-a5682b0841d2&quot;&gt;&lt;h3 data-custom-text=&quot;&quot; data-text=&quot;5. Begin to optimize your paywall directly&quot; id=&quot;5-begin-to-optimize-your-paywall-directly&quot;&gt;5. Begin to optimize your paywall directly&lt;/h3&gt;&lt;/div&gt;


&lt;p&gt;From there, use those learnings around copy, social proof, and more to optimize the paywall.&lt;/p&gt;



&lt;p&gt;The community learning app ran paywall tests &lt;strong&gt;changing the copy on the paywall from features-focused to JTBD-focused&lt;/strong&gt;. Too many paywalls simply list out endless features, rather than exploring the value &lt;em&gt;behind &lt;/em&gt;those features and explaining what the app will actually help the user achieve. &lt;a href=&quot;https://www.revenuecat.com/blog/growth/paywall-conversion-boosters/&quot;&gt;Strong copywriting on your paywall&lt;/a&gt; goes a long way.&lt;/p&gt;



&lt;p&gt;An example of how &lt;em&gt;not&lt;/em&gt; to do this, in my opinion, is Uxcel Go, the UX learning app (sticking with the education category!). If you look at their paywall, it’s entirely feature-focused:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;732&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-25-at-18.01.25-1024x732.png&quot; alt=&quot;&quot; class=&quot;wp-image-46350&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-25-at-18.01.25-1024x732.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-25-at-18.01.25-300x215.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-25-at-18.01.25-768x549.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-25-at-18.01.25-50x36.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-25-at-18.01.25-56x40.png 56w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-25-at-18.01.25-649x464.png 649w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-25-at-18.01.25-696x498.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-25-at-18.01.25-560x400.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-25-at-18.01.25-414x296.png 414w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-25-at-18.01.25-660x472.png 660w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-25-at-18.01.25-80x57.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-25-at-18.01.25-48x34.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-25-at-18.01.25.png 1320w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The closest Uxcel Go comes to a JTBD is “Invest in your design career today”, but even that feels vague and surface-level. &lt;em&gt;Why&lt;/em&gt; do I want to invest in it? &lt;em&gt;What&lt;/em&gt; do I want to achieve?&lt;/p&gt;



&lt;p&gt;While Smart Tales’ original headline, “Accelerate your kid’s growth”, was closer to a JTBD, but it still wasn’t the core JTBD that emerged from their research.&lt;/p&gt;



&lt;p&gt;They were consistent in their messaging throughout the onboarding:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;976&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-25-at-18.00.32-976x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-46348&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-25-at-18.00.32-976x1024.png 976w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-25-at-18.00.32-286x300.png 286w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-25-at-18.00.32-768x805.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-25-at-18.00.32-48x50.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-25-at-18.00.32-38x40.png 38w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-25-at-18.00.32-442x464.png 442w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-25-at-18.00.32-696x730.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-25-at-18.00.32-534x560.png 534w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-25-at-18.00.32-282x296.png 282w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-25-at-18.00.32-450x472.png 450w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-25-at-18.00.32-76x80.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-25-at-18.00.32-46x48.png 46w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-25-at-18.00.32.png 1150w&quot; sizes=&quot;auto, (max-width: 976px) 100vw, 976px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Left: previous feature-focused paywall, right: updated paywall after multiple experiments&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;Now, this was the result of multiple tests, but one thing that really stood out to me was how much less copy there is in the final version. The onboarding is doing the heavy lifting in communicating the value, which allows the paywall to be simpler and more focused. And it works because it clearly centers on the JTBD and what matters to the parents, rather than listing out features. Another interesting shift? The visual. The original was very functional; the final version focused on emotion.&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-1bQwLV wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Find inspiration with real paywall examples on Paywalls.com&quot; text=&quot;&lt;p&gt;Browse real examples at &lt;a href=&amp;quot;https://www.paywalls.com/&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noopener&amp;quot;&gt;Paywalls.com&lt;/a&gt;: filter paywall screens by different UI elements, app category, and trending and top-growth paywalls.&lt;/p&gt;&quot; icon=&quot;sparks&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-jtbd-research-and-your-pricing-and-packaging&quot;&gt;JTBD research and your pricing and packaging&lt;/h4&gt;



&lt;p&gt;Sometimes, JTBD research even shows that you may need to fundamentally rethink your pricing and packaging. In Léa’s experience, &lt;em&gt;adding&lt;/em&gt; a package is usually an easier sell internally, but &lt;em&gt;changing&lt;/em&gt; or &lt;em&gt;removing&lt;/em&gt; one can be trickier. That’s why she recommends starting with a lower-friction experiment — something that’s easier to get buy-in for and can show results quickly — then tackling harder, longer experiments.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;There are two key things to consider:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;You may be underpricing.&lt;/strong&gt; If so, Léa recommends testing a higher price earlier on. The beauty of JTBD is that you can often charge more &lt;em&gt;without&lt;/em&gt; changing the product, because you’re finally resonating with the audience in the right way.&lt;br&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Not every test will be a win, and that’s okay.&lt;/strong&gt; Both Léa and I have seen JTBD-led experiments perform better than average, but that doesn’t mean you’ll nail it on the first try. The key is not to test too small. A test that returns no significant result can be worse than one that shows a slight drop, as it tells you less.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Either way, keep testing and keep researching. Remember how many experiments it took the examples to get there.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-using-jtbd-to-optimize-your-paywalls-nbsp&quot;&gt;Using JTBD to optimize your paywalls&amp;nbsp;&lt;/h2&gt;



&lt;p&gt;Reading through this, you might be tempted to think: well, that sounds simple enough. And in theory, it is. As Léa said, it’s the hardest and easiest thing all at once. The hard part usually isn’t the experiments themselves, it’s the research. That’s why Léa zooms in so sharply on user interviews. Her approach: do one form of JTBD research well.&lt;/p&gt;



&lt;p&gt;When Léa talks about Smart Tales, you can hear the admiration in her voice: they truly committed to the process, staying open-minded and doing the hard work.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;So when you’re halfway through your stack of interviews, think about Smart Tales — they recently hit $1M in ARR, a milestone that only 0.5% of apps ever reach. In the list of reasons they credit for success, they include: &lt;strong&gt;​​&lt;/strong&gt;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;“Tens of customer interviews to truly understand the needs of parents and children.”&lt;/strong&gt;&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;“Hundreds of A/B tests to optimize every aspect of the app’s performance.”&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;If you want to optimize your paywall using JTBD, it doesn’t start at the paywall. Start by preparing for strong interviews, analyze them deeply, then work your way back from the front of the funnel — testing and refining as you go.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Simple enough, right?&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;800&quot; height=&quot;800&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-27.png&quot; alt=&quot;&quot; class=&quot;wp-image-46344&quot; style=&quot;width:650px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-27.png 800w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-27-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-27-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-27-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-27-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-27-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-27-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-27-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-27-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-27-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-27-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-27-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-27-48x48.png 48w&quot; sizes=&quot;auto, (max-width: 800px) 100vw, 800px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Credit: Marshmallow Games – Smart Tale LinkedIn Post&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Unlocking growth: How to supercharge your paywalls with offers]]></title><description><![CDATA[Explore types of promotional offer and learn how to configure them in RevenueCat's Paywall Editor]]></description><link>https://www.revenuecat.com/blog/growth/paywalls-introductory-offers/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/paywalls-introductory-offers/</guid><pubDate>Thu, 25 Sep 2025 04:35:00 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Unlocking-growth_-How-to-supercharge-your-Paywalls-with-Offers.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Modern subscription apps rely on more than just ‘Subscribe’ and ‘Cancel’. To maximize conversions, you need to leverage introductory offers, offer codes, and promotional offers. &lt;a href=&quot;https://www.revenuecat.com/docs/tools/paywalls&quot;&gt;RevenueCat Paywalls&lt;/a&gt; make it easy to configure and display these offers to the right customers at the right time, without writing endless custom logic.&lt;/p&gt;



&lt;p&gt;Read on for the different types of offers Paywalls can support, how to configure them in the Paywall Editor, and some real-world examples of how apps use them to boost revenue and user satisfaction.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-do-offers-matter&quot;&gt;Why do offers matter?&lt;/h2&gt;



&lt;p&gt;Imagine you’re running a fitness app. First-time subscribers might be encouraged by a ‘7 days free’ intro trial, while past subscribers might return if you give them ‘3 months at 50% off’. A language learning app might offer a seasonal ‘Back to school’ discount via promo codes, while a music streaming service might offer loyal users a personalized promotion.&lt;/p&gt;



&lt;p&gt;The key is: &lt;strong&gt;different offers for different customer journeys&lt;/strong&gt;. RevenueCat Paywalls provide the flexibility to support all of these use cases.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;introductory-offers&quot;&gt;Introductory Offers&lt;/h2&gt;



&lt;p&gt;An &lt;a href=&quot;https://www.revenuecat.com/docs/tools/paywalls/creating-paywalls/supporting-offers&quot;&gt;introductory offer&lt;/a&gt; is the primary mechanism for user acquisition, designed to lower the barrier to a first-time purchase. This typically manifests as a free trial period or reduced initial price. When a product on the App Store or Google Play Store has an introductory offer, RevenueCat will automatically present it to eligible customers at checkout.&lt;/p&gt;



&lt;p&gt;But to make the most of it, your paywall content should highlight the intro offer. To configure this, follow this guide below:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;In the Paywall Editor, click on the text component you want to customize.&lt;/li&gt;



&lt;li&gt;Click the ➕ icon next to &lt;strong&gt;Text field for an introductory offer&lt;/strong&gt;.&lt;/li&gt;



&lt;li&gt;Enter a unique string, such as:
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;“Start today and get your first week free!”&lt;/li&gt;



&lt;li&gt;“Your first 3 months are only $0.99 each.”&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;For example, if you’re building a meditation app, you could display “Relax for free this week, your 7-day trial starts now!” only to eligible new users, like the image below:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;356&quot; height=&quot;422&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/0-1.png&quot; alt=&quot;&quot; class=&quot;wp-image-46305&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/0-1.png 356w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/0-1-253x300.png 253w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/0-1-42x50.png 42w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/0-1-34x40.png 34w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/0-1-250x296.png 250w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/0-1-67x80.png 67w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/0-1-40x48.png 40w&quot; sizes=&quot;auto, (max-width: 356px) 100vw, 356px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;There are multiple ways to configure introductory offers depending on platforms. Let’s explore each.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-play-store-offers&quot;&gt;Play Store offers&lt;/h3&gt;



&lt;p&gt;On Google Play, a single product can include multiple introductory offers.&amp;nbsp;For example, a subscription could include either:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;1 month free&lt;/li&gt;



&lt;li&gt;3 months at 50% off&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;RevenueCat lets you display the correct message for these cases with the &lt;strong&gt;Play Store only: Multiple Introductory Offers Text Field&lt;/strong&gt;. You can even use &lt;strong&gt;secondary offer variables&lt;/strong&gt; to show the price and duration of the second offer.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;344&quot; height=&quot;158&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/1-1.png&quot; alt=&quot;&quot; class=&quot;wp-image-46307&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/1-1.png 344w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/1-1-300x138.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/1-1-50x23.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/1-1-87x40.png 87w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/1-1-80x37.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/1-1-48x22.png 48w&quot; sizes=&quot;auto, (max-width: 344px) 100vw, 344px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;For example, a productivity app might say:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;“Enjoy 1 month free” for students,&lt;/li&gt;



&lt;li&gt;“Get 3 months at 50% off” for professionals.&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-app-store-offer-codes&quot;&gt;App Store offer codes&lt;/h3&gt;



&lt;p&gt;Apple allows developers to distribute &lt;strong&gt;offer codes&lt;/strong&gt;, which users can redeem directly inside your app. RevenueCat Paywalls supports this by adding a &lt;strong&gt;redemption button&lt;/strong&gt;.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;596&quot; height=&quot;610&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/2.png&quot; alt=&quot;&quot; class=&quot;wp-image-46309&quot; style=&quot;width:326px;height:auto&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/2.png 596w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/2-293x300.png 293w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/2-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/2-39x40.png 39w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/2-453x464.png 453w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/2-547x560.png 547w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/2-289x296.png 289w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/2-461x472.png 461w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/2-78x80.png 78w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/2-48x48.png 48w&quot; sizes=&quot;auto, (max-width: 596px) 100vw, 596px&quot;&gt;&lt;/figure&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;When tapped, the &lt;strong&gt;native iOS redemption sheet&lt;/strong&gt; opens&lt;/li&gt;



&lt;li&gt;Users enter their code, accept the offer, and continue the subscription flow&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;For example, a language learning app at a conference might hand out offer codes for ‘1 free month’, then the app seamlessly handles redemption through RevenueCat.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-app-store-promotional-offers&quot;&gt;App Store promotional offers&lt;/h3&gt;



&lt;p&gt;Promotional offers are designed to win back previous subscribers or reward loyal customers. These offers can be configured in App Store Connect and linked to your RevenueCat paywall.&lt;/p&gt;



&lt;p&gt;You can configure with the steps below:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;In the Paywall Editor, open your package component&lt;/li&gt;



&lt;li&gt;Enter the &lt;strong&gt;Promotional Offer Identifier&lt;/strong&gt; (from App Store Connect)&lt;/li&gt;



&lt;li&gt;Configure unique strings for eligible users&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;If a user is eligible (based on Apple’s rules, e.g. they’ve had a subscription before), RevenueCat will show the promotional offer text fields automatically.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;customizing-content-based-on-eligibility&quot;&gt;Customizing content based on eligibility&lt;/h2&gt;



&lt;p&gt;RevenueCat allows paywalls to adapt automatically depending on whether a user is eligible for an offer. This means the same screen can look different to two customers, giving a personalized experience.&lt;/p&gt;



&lt;p&gt;Eligibility usually falls into two categories: &lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Introductory offers for new users&lt;/li&gt;



&lt;li&gt;Promotional offers for returning subscribers&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;When a user qualifies, RevenueCat exposes variables like ‘offer_price’ and ‘offer_duration’. These values can be added directly into the paywall text. For example, a new customer might see “Get started with your first 3 months at $1.99/month”, while an existing one sees “Continue your journey for $9.99/month”.&lt;/p&gt;



&lt;p&gt;The key takeaway is that content should not remain static. By tailoring language and pricing details to the individual, you build trust, reduce confusion, and increase the likelihood that someone completes a purchase. From a learning perspective, think of this like conditional rendering in a UI framework: the display changes depending on the user’s state, but the logic is handled by the system itself.&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-1bQwLV wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Find inspiration with real paywall examples on Paywalls.com&quot; text=&quot;&lt;p&gt;Browse real examples at &lt;a href=&amp;quot;https://www.paywalls.com/&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noopener&amp;quot;&gt;Paywalls.com&lt;/a&gt;: filter paywall screens by different UI elements, app category, and trending and top-growth paywalls.&lt;/p&gt;&quot; icon=&quot;sparks&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-targeting-different-audiences&quot;&gt;Targeting different audiences&lt;/h2&gt;



&lt;p&gt;While eligibility reflects what Apple or Google determines about a user’s subscription history, &lt;strong&gt;targeting&lt;/strong&gt; gives you control as a developer over which paywall different audiences should see.&lt;/p&gt;



&lt;p&gt;You can base targeting on customer attributes, the placement of the paywall in your app, or even experimentation groups for A/B testing. For instance, a language learning app might show an introductory trial during onboarding, a win-back discount to returning users, and a student-specific plan to customers flagged with a student attribute.&lt;/p&gt;



&lt;p&gt;This approach does more than personalize the message; it provides a way to shape your business strategy. Users feel that the offer is relevant to them, lapsed subscribers are given incentives to return, and you can systematically test which offers perform better. In practice, targeting transforms paywalls from a single funnel into multiple tailored journeys, each aligned with a different audience segment.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-example-language-learning-app-with-revenuecat-paywalls&quot;&gt;Example: Language learning app with RevenueCat Paywalls&lt;/h2&gt;



&lt;p&gt;Imagine you’re the product lead for a language learning app called LinguaPro. Your business relies heavily on subscription revenue, and your main challenge is maximizing conversions across three user types:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Brand-new users&lt;/strong&gt; installing the app for the first time&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Returning users&lt;/strong&gt; who previously subscribed but churned&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Special groups&lt;/strong&gt; such as students who may respond to discounted pricing&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;You decide to use RevenueCat Paywalls to handle both offer eligibility and audience targeting.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-customizing-content-by-eligibility&quot;&gt;1. Customizing content by eligibility&lt;/h3&gt;



&lt;p&gt;When LinguaPro is first installed, the App Store automatically marks new users as eligible for an introductory offer. With RevenueCat, you configure the paywall text to adapt depending on eligibility.&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Eligible (new user): &lt;/strong&gt;The paywall dynamically inserts ‘offer_price’ and ‘offer_duration’. The screen displays: “Start your journey with 1 month free, then continue at just $9.99/month.”&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Not eligible (returning or existing user): &lt;/strong&gt;The same paywall shows a different message: “Keep learning for $9.99/month, cancel anytime.”&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Here, you don’t create two separate paywalls. You create one, and RevenueCat allows you to change the wording based on eligibility.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-targeting-different-audiences&quot;&gt;2. Targeting different audiences&lt;/h3&gt;



&lt;p&gt;Eligibility handles whether a customer can &lt;em&gt;technically&lt;/em&gt; access an offer. But you also want business logic on top of that, deciding which paywall to serve in the first place.&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Onboarding flow: &lt;/strong&gt;All new users are shown the introductory-offer paywall&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Returning subscribers: &lt;/strong&gt;When a lapsed user opens the app, you serve a different paywall built around a promotional offer: “Welcome back! Reactivate your subscription for 3 months at 50% off.”&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Student segment: &lt;/strong&gt;Customers who verified themselves as students receive a student-discount paywall: “As a student, get full access for $4.99/month.”&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;By combining targeting with eligibility, the experience becomes even more precise. For example, a student who is also a returning subscriber won’t be shown the intro trial (they’re not eligible), but instead the targeted &lt;em&gt;student discount&lt;/em&gt; paywall.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-measuring-outcomes&quot;&gt;3. Measuring outcomes&lt;/h3&gt;



&lt;p&gt;Within a few months, you run A/B tests on targeted groups:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Some lapsed users get “3 months at 50% off.”&lt;/li&gt;



&lt;li&gt;Others get “1 month free, then $9.99.”&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;RevenueCat’s experiments show that the first option results in &lt;strong&gt;25% higher reactivation&lt;/strong&gt;, so you adopt it permanently for that segment.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-offers-will-you-try&quot;&gt;What offers will you try?&lt;/h2&gt;



&lt;p&gt;Supporting offers is not just about ticking boxes, it’s about showing the right deal to the right user, at the right time. By combining introductory offers, promo codes, and targeted promotions, you can boost conversions, reduce churn, and create a more engaging user journey.&lt;/p&gt;



&lt;p&gt;Whether it’s a free trial for new users, a promo discount to win back churned subscribers, or a code handed out at an event, RevenueCat makes it easy to integrate these flows without writing boilerplates. &lt;/p&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Enhance in-app purchase experiences with slide to unlock in Jetpack Compose]]></title><description><![CDATA[In this article, you’ll explore the open-source slide-to-unlock library, built by RevenueCat, and learn how to integrate it with RevenueCat’s in-app purchases in Jetpack Compose ]]></description><link>https://www.revenuecat.com/blog/engineering/compose-slide-to-unlock/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/compose-slide-to-unlock/</guid><pubDate>Wed, 24 Sep 2025 08:13:37 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Slide-to-subscribe.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;When Apple first introduced the “Slide to Unlock” feature on the iPhone, it wasn’t just a quirky design, it was a deliberate interaction choice. Compared to a normal button, sliding offered a more engaging and meaningful way to unlock a device.&lt;/p&gt;



&lt;p&gt;While newer devices have replaced “Slide to Unlock” with swipe gestures or biometric unlocking, the underlying principle remains the same: interaction should feel intentional, intuitive, and rewarding. Apple’s slider was one of the earliest examples of how even a simple UI decision can influence user engagement.&lt;/p&gt;



&lt;p&gt;In this article, you’ll explore the open-source &lt;a href=&quot;https://github.com/revenueCat/slide-to-unlock/&quot;&gt;slide-to-unlock library&lt;/a&gt;, built by RevenueCat, and learn how to integrate it with RevenueCat’s in-app purchases in Jetpack Compose through practical, real-world examples.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-slide-to-unlock-in-jetpack-compose&quot;&gt;Slide to unlock in Jetpack Compose&lt;/h2&gt;



&lt;p&gt;The slide-to-unlock library is designed for &lt;a href=&quot;https://kotlinlang.org/docs/multiplatform.html&quot;&gt;Kotlin Multiplatform&lt;/a&gt;, so you can use it in both Android and KMP projects. To add slide-to-unlock to your project, include the following dependency in your Gradle file:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1RVL7E wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;implementation(\&amp;quot;com.revenuecat.purchases:slide-to-unlock:1.0.2\&amp;quot;)&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;For Kotlin Multiplatform, add the dependency below to your module’s build.gradle.kts file:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-2pYdou wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;sourceSets {\n    val commonMain by getting {\n        dependencies {\n            implementation(libs.compose.slidetounlock)\n        }\n    }\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The usage is pretty simple. You can just implement it by using the `SlideToUnlock` composable with creating a state at the call site like below:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z2lpoe3 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;var isSlided by remember { mutableStateOf(false) }\n\nSlideToUnlock(\n    isSlided = isSlided,\n    modifier = Modifier.fillMaxWidth(),\n    onSlideCompleted = { isSlided = true },\n)&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;&lt;code&gt;SlideToUnlock&lt;/code&gt; is highly customizable, you can adjust nearly every aspect of the slider, including &lt;a href=&quot;https://github.com/revenueCat/slide-to-unlock/?tab=readme-ov-file#customizing-colors&quot;&gt;colors&lt;/a&gt;,&lt;a href=&quot;https://github.com/revenueCat/slide-to-unlock/?tab=readme-ov-file#fully-customize-thumb-and-hint-composables&quot;&gt; thumb, hint text&lt;/a&gt;, &lt;a href=&quot;https://github.com/revenueCat/slide-to-unlock/?tab=readme-ov-file#customizing-the-gesture-behavior&quot;&gt;gesture behavior&lt;/a&gt;, and &lt;a href=&quot;https://github.com/revenueCat/slide-to-unlock/?tab=readme-ov-file#tracking-slide-fraction-changes&quot;&gt;tracking slide fractions&lt;/a&gt;. You can also provide your own composables for the thumb and hint to achieve a fully tailored experience. For more details on customization, please refer to the &lt;a href=&quot;https://github.com/revenueCat/slide-to-unlock/&quot;&gt;documentation&lt;/a&gt;.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;revenuecat-integration&quot;&gt;RevenueCat integration&lt;/h2&gt;



&lt;p&gt;This library supports RevenueCat integration, allowing you to easily implement features like &lt;em&gt;Slide to Purchase&lt;/em&gt; or &lt;em&gt;Slide to Subscribe&lt;/em&gt; by adding the dependency below:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z2l8mnB wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;implementation(\&amp;quot;com.revenuecat.purchases:slide-to-unlock-purchases:1.0.2\&amp;quot;)&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;You can now use the &lt;code&gt;SlideToPurchases&lt;/code&gt; component, which triggers in-app purchases once the slide action is completed. Its usage is very similar to the &lt;code&gt;SlideToUnlock&lt;/code&gt; composable, but it requires a few additional parameters needed to complete purchases through the RevenueCat SDK.&lt;/p&gt;



&lt;p&gt;The library provides several overloaded &lt;code&gt;SlideToPurchases&lt;/code&gt; composables to cover different purchase scenarios, such as product types, subscription upgrades, and promotional offers, while abstracting away the underlying purchase logic.The most common use case is simple: fetch your offerings from RevenueCat and pass the desired &lt;code&gt;Package&lt;/code&gt; to the composable. The component takes care of everything else.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZYmQuT wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;\/\/ inside your coroutine scope\nval currentOffering = Purchases.sharedInstance.awaitOfferings().current\nval monthlyPackage = currentOffering?.getPackage(\&amp;quot;monthly\&amp;quot;)\n\nif (monthlyPackage != null) {\n    var purchaseState by remember { mutableStateOf&lt;PurchaseState?&gt;(null) }\n\n    SlideToPurchases(\n        packageToPurchase = monthlyPackage,\n        modifier = Modifier\n            .fillMaxWidth()\n            .padding(16.dp),\n        onPurchaseStateChanged = { newPurchaseState -&gt;\n            purchaseState = newPurchaseState\n            \/\/ Handle state changes, e.g., show a dialog on success\/error\n        }\n    )\n\n    \/\/ Optionally display the state\n    when (val state = purchaseState) {\n        is PurchaseState.Loading -&gt; { \/* Show a loading indicator *\/ }\n        is PurchaseState.Success -&gt; { \/* Navigate to a success screen *\/ }\n        is PurchaseState.Error -&gt; { \/* Show an error message *\/ }\n        null -&gt; { \/* Initial state *\/ }\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Similar to the &lt;code&gt;Purchases.sharedInstance.awaitPurchase()&lt;/code&gt; function, you can perform in-app purchases using several options: &lt;code&gt;StoreProduct&lt;/code&gt;, &lt;code&gt;Package&lt;/code&gt;, &lt;code&gt;SubscriptionOption&lt;/code&gt;, &lt;code&gt;PromotionalOffer&lt;/code&gt;, and &lt;code&gt;WinBackOffer&lt;/code&gt;. For more details, check out the&lt;a href=&quot;https://github.com/revenueCat/slide-to-unlock/?tab=readme-ov-file#overloads&quot;&gt; overloads documentation&lt;/a&gt;.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;building-a-custom-paywalls-with-slide-to-unlock&quot;&gt;Building a custom paywalls with slide to unlock&lt;/h2&gt;



&lt;p&gt;Now let’s take a look at how to build a custom paywall that includes &lt;em&gt;Slide to Unlock&lt;/em&gt;. If you want to create your own custom paywalls, you can achieve it by using RevenueCat’s &lt;a href=&quot;https://www.revenuecat.com/docs/tools/paywalls/creating-paywalls#using-the-editor&quot;&gt;Paywall Editor&lt;/a&gt;, which is based on a &lt;a href=&quot;https://www.revenuecat.com/blog/engineering/server-driven-android/&quot;&gt;server-driven UI&lt;/a&gt;.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;However, if you need a more personalized design, such as containing very customized UI components that aren’t supported by the Paywall Editor, you’ll need to create your own custom paywalls. In that case, you can manually fetch the current offerings and render the screens based on your requirements.&lt;/p&gt;



&lt;p&gt;Currently, RevenueCat’s Paywall Editor doesn’t support Slide to Unlock officially, so in this article we’ll walk through a workaround for integrating it into your custom paywalls. First things first: open the RevenueCat Paywall Editor and create a new paywall without a footer, leaving enough space at the bottom like the image below:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;748&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/0-1024x748.png&quot; alt=&quot;&quot; class=&quot;wp-image-46263&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/0-1024x748.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/0-300x219.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/0-768x561.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/0-50x37.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/0-55x40.png 55w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/0-635x464.png 635w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/0-696x509.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/0-560x409.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/0-405x296.png 405w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/0-646x472.png 646w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/0-80x58.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/0-48x35.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/0.png 1286w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Next, fetch the current offering as shown in the code below:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZnAWoe wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;try {\n  val offerings = Purchases.sharedInstance.awaitOfferings()\n  offerings.current?.let { currentOffering -&gt;\n    \/\/ you have a current offering now here\n  }\n} catch (e: PurchasesException) {\n  \/\/ fetching offering exception\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Then, retrieve the available package information from the offering and position the &lt;code&gt;Paywall&lt;/code&gt; composable component alongside &lt;code&gt;SlideToUnlock&lt;/code&gt;, as demonstrated here:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZuOSL9 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot; Box(\n    modifier = Modifier\n      .fillMaxSize()\n      .background(Color.White),\n  ) {\n    Paywall(\n      options = PaywallOptions.Builder(\n        dismissRequest = { viewModel.navigateUp() },\n      ).setOffering(offering).build(),\n    )\n\n    val availablePackage = offering?.availablePackages?.first()\n    val activity = (LocalContext.current as? Activity)\n    var isSlided by remember { mutableStateOf(false) }\n    \n    if (availablePackage != null &amp;amp;&amp;amp; activity != null) {\n      SlideToUnlock(\n        modifier = Modifier\n          .align(Alignment.BottomCenter)\n          .fillMaxWidth()\n          .padding(bottom = 60.dp, start = 20.dp, end = 20.dp),\n        isSlided = isSlided,\n        hintTexts = HintTexts.defaultHintTexts().copy(\n          defaultText = stringResource(\n            com.revenuecat.articles.paywall.compose.core.designsystem.R.string.slide_subscribe,\n          ),\n        ),\n        onSlideCompleted = {\n          isSlided = true\n          viewModel.handleEvent(\n            PaywallEvent.Purchases(\n              activity = activity,\n              availablePackage = availablePackage,\n            ),\n          )\n        },\n      )\n    }\n  }\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;That’s it! You’ll now see the result below, a seamless combination of the paywall you built in the Paywall Editor and the Slide to Unlock component.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;507&quot; height=&quot;981&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/1.png&quot; alt=&quot;&quot; class=&quot;wp-image-46265&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/1.png 507w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/1-155x300.png 155w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/1-26x50.png 26w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/1-21x40.png 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/1-240x464.png 240w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/1-289x560.png 289w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/1-153x296.png 153w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/1-244x472.png 244w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/1-41x80.png 41w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/1-25x48.png 25w&quot; sizes=&quot;auto, (max-width: 507px) 100vw, 507px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;You can check out the full source code on GitHub, an open source project &lt;a href=&quot;https://github.com/RevenueCat/cat-paywall-compose/tree/main/feature/paywalls/src/main/kotlin/com/revenuecat/articles/paywall/paywalls&quot;&gt;Cat Paywall Compose’s paywalls directory&lt;/a&gt;.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;wrapping-up&quot;&gt;Wrapping Up&lt;/h2&gt;



&lt;p&gt;In this article, you’ve learned how to use the &lt;a href=&quot;https://github.com/revenueCat/slide-to-unlock/&quot;&gt;&lt;em&gt;slide-to-unlock&lt;/em&gt; library&lt;/a&gt; and integrate it into a custom paywall. While RevenueCat’s Paywall Editor offers a fast and convenient way to build paywalls, sometimes you’ll want to go further and experiment with more personalized or playful interactions.&lt;/p&gt;



&lt;p&gt;There are many strategies to increase user engagement and improve subscription conversion rates, clear value communication, compelling design, optimized pricing, and interactive UI patterns all play a role. &lt;em&gt;Slide to Unlock&lt;/em&gt; adds an extra layer of interactivity that feels intuitive, deliberate, and rewarding for users, helping to reduce friction and increase commitment to the purchase flow.&lt;/p&gt;



&lt;p&gt;As you continue refining your paywalls, consider testing different designs, messaging, and engagement patterns to find what resonates best with your audience. Combined with &lt;a href=&quot;https://www.revenuecat.com/feature/charts/&quot;&gt;RevenueCat’s analytics&lt;/a&gt; and &lt;a href=&quot;https://www.revenuecat.com/feature/experiments/&quot;&gt;A/B testing capabilities&lt;/a&gt;, approaches like &lt;em&gt;slide-to-unlock&lt;/em&gt; can be great tools in building subscription experiences that are not only effective but also enjoyable.&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Google Play’s AI revamp: What apps need to know (and do next)]]></title><description><![CDATA[AI-driven discovery, new subscription hubs, and curated spaces will change how apps get found and how they keep users.]]></description><link>https://www.revenuecat.com/blog/growth/google-play-store-ai-revamp-2025/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/google-play-store-ai-revamp-2025/</guid><pubDate>Tue, 23 Sep 2025 15:18:03 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2022/07/Frame-3801-2.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Google &lt;a href=&quot;https://blog.google/products/google-play/curation-update-september-2025/&quot;&gt;announced&lt;/a&gt; a set of AI-forward updates designed to keep users exploring and transacting on Play:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Guided Search:&lt;/strong&gt; Users can search by goals (“learn Spanish,” “get fit at home”) with AI-organized results.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;New “You” tab:&lt;/strong&gt; A personal hub for subscriptions, rewards, recommendations, and user profiles. The You tab starts rolling out this week in Play Points markets, with additional countries from October 1.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Curated Spaces:&lt;/strong&gt; Seasonal and thematic collections that feature apps across verticals. Examples include WNBA placements in the U.S. and an Entertainment space in Korea (short-form dramas, webcomics, streaming), with select short-form content viewable directly in Play (including in the U.S.).&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Gaming upgrades:&lt;/strong&gt; AI assistants for gameplay, richer game detail pages, and Play Games on PC now generally available.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Together, these updates make the store feel more personalized and more competitive for app visibility.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-this-matters-for-subscription-apps&quot;&gt;Why this matters for subscription apps&lt;/h2&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Discovery is now intent-driven.&lt;/strong&gt; Play will surface apps based on &lt;em&gt;outcomes&lt;/em&gt; rather than keywords. That means listings must clearly state what problem you solve (“Daily IELTS drills,” “10-minute meditation habit”), not just your app category.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;The You tab makes subscriptions more visible and manageable.&lt;/strong&gt; Subscriptions are front-and-center. Users can review and churn more easily, so win-backs, pauses, and downgrade paths matter more than ever.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Curated spaces reward fresh, themed content.&lt;/strong&gt; Apps that ship seasonal packs, new modules, or live events will be favored for editorial placement. Static apps risk being overlooked.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Cross-device expectations rise.&lt;/strong&gt; With Play Games on PC expanding, users expect purchases and subscriptions to carry across platforms. Broken entitlements or mismatched paywalls will hurt trust.&lt;/li&gt;
&lt;/ol&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;460&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/guided-search-android-460x1024.jpeg&quot; alt=&quot;&quot; class=&quot;wp-image-46300&quot; style=&quot;width:300px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/guided-search-android-460x1024.jpeg 460w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/guided-search-android-135x300.jpeg 135w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/guided-search-android-768x1710.jpeg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/guided-search-android-690x1536.jpeg 690w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/guided-search-android-920x2048.jpeg 920w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/guided-search-android-22x48.jpeg 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/guided-search-android-18x40.jpeg 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/guided-search-android-208x464.jpeg 208w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/guided-search-android-696x1549.jpeg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/guided-search-android-252x560.jpeg 252w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/guided-search-android-133x296.jpeg 133w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/guided-search-android-212x472.jpeg 212w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/guided-search-android-36x80.jpeg 36w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/guided-search-android.jpeg 1000w&quot; sizes=&quot;auto, (max-width: 460px) 100vw, 460px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;Guided Search organizes results by intent (e.g. “find a home”). &lt;a href=&quot;https://blog.google/products/google-play/curation-update-september-2025/&quot;&gt;Source&lt;/a&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-to-do-this-week&quot;&gt;What to do this week&lt;/h2&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Re-write your store listing for outcomes.&lt;/strong&gt; Lead with the &lt;em&gt;result&lt;/em&gt; your app delivers in the short description, first 2–3 bullets, and opening screenshot.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Audit subscription flows.&lt;/strong&gt; Make sure cancel → win-back flows (pause, discount, downgrade) are in place and clearly messaged.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Plan a seasonal or thematic drop.&lt;/strong&gt; Ship one new pack, challenge, or content update within 30 days to increase eligibility for curated placements.&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-to-do-this-quarter&quot;&gt;What to do this quarter&lt;/h2&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Map your top intents.&lt;/strong&gt; Build a mini “intent map” of 6–8 user jobs your app solves, and align your listing (headline, screenshots, promo video) to each.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Ship a 90-day content cadence.&lt;/strong&gt; Schedule thematic updates tied to seasonal or cultural moments (e.g., back-to-school, new year challenges).&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Prepare for Play’s new community features.&lt;/strong&gt; Enhanced app detail pages and Q&amp;amp;A are coming. Seed FAQs and plan for moderation now.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Monitor leading indicators.&lt;/strong&gt; Watch explore impressions, trial-to-paid conversion, and churn correlated with new Play surfaces.&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-bigger-picture&quot;&gt;The bigger picture&lt;/h2&gt;



&lt;p&gt;According to our &lt;strong&gt;State of Subscription Apps 2025&lt;/strong&gt; report, median trial-to-paid conversion rates hover around 14%&lt;em&gt;,&lt;/em&gt; but the best apps consistently outperform by aligning messaging and lifecycle with user intent. Play’s AI revamp is effectively forcing developers to compete on that same axis: the clearer you articulate outcomes, the more discoverable you’ll be.&lt;/p&gt;



&lt;p&gt;For indie devs and small teams, the takeaway is simple: optimize now for outcome-driven discovery and strong retention flows, or miss out on visibility and growth as Play surfaces evolve.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-further-reading&quot;&gt;Further reading&lt;/h2&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Acquisition benchmarks&lt;/strong&gt; &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps-2025/&quot;&gt;State of Subscription Apps 2025&lt;/a&gt; — use conversion and retention benchmarks to see if Play’s new discovery model is improving your funnel.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Win-back campaigns&lt;/strong&gt; &lt;a href=&quot;https://www.revenuecat.com/blog/growth/how-to-build-a-win-back-campaign-with-revenuecat-web-billing/&quot;&gt;How to Build a Win-Back Campaign with RevenueCat Web Billing&lt;/a&gt; — practical tutorial for re-engaging churned users, critical now that subscription management is front-and-center in Play.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Why users cancel&lt;/strong&gt; &lt;a href=&quot;https://www.revenuecat.com/blog/growth/subscription-app-churn-reasons-how-to-fix/?utm_source=chatgpt.com&quot;&gt;Top 5 cancellation reasons (and fixes)&lt;/a&gt; — data-backed causes of churn and fixes you can apply before users hit “Manage subscription.”&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Better cancellation flows&lt;/strong&gt; &lt;a href=&quot;https://www.revenuecat.com/blog/growth/app-cancellation-flow-best-practices/&quot;&gt;Cancellation flow best practices&lt;/a&gt; — examples from leading apps to keep exits clear, fair, and reversible.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Stay in the loop&lt;/strong&gt; &lt;a href=&quot;https://www.revenuecat.com/subclub/&quot;&gt;Sub Club&lt;/a&gt; — subscribe to the newsletter (see the form below) to stay up-to-date with growth playbooks and industry news.&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title><![CDATA[What to know before you make your first growth hire for a subscription app]]></title><description><![CDATA[Hiring your first app growth role? Most founders get it wrong — here’s what actually matters ]]></description><link>https://www.revenuecat.com/blog/growth/first-growth-hire-subscription-app/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/first-growth-hire-subscription-app/</guid><pubDate>Tue, 23 Sep 2025 09:48:57 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/First-growth-hire-for-subscription-apps.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;You’ve been scaling up — dare I say, &lt;em&gt;hustling &lt;/em&gt;— as a founder and early team. You’ve worked hard to build and improve your subscription app, and it’s finally starting to pay off. That initial traction is here, and for the first time, you’ve got the option to hire someone focused on growth.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Exciting? Definitely. But also (if we’re being honest) a little scary.&lt;/p&gt;



&lt;p&gt;I’ve had this conversation with a lot of founders, reviewed their setup, and helped them figure out not just &lt;em&gt;if&lt;/em&gt; they’re ready to hire, but &lt;em&gt;who&lt;/em&gt; they actually need. And the truth is, much of the advice I give ends up being the same. So it felt like time to bring it all together in one place — enter this blog.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-when-should-you-make-a-growth-hire&quot;&gt;When should you make a growth hire?&lt;/h2&gt;



&lt;p&gt;I like to start by zooming out: before we get into hard skills, soft skills, or interview questions, you need to make sure you’re truly ready to hire and that you’re setting the role up for success from day one.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Growth roles are often hired too early. &lt;/strong&gt;The most important consideration is whether you have product-market fit (PMF) — you should have signals that your app is right for your audience, like solid initial retention and strong word of mouth.&lt;/p&gt;



&lt;p&gt;This matters for a few reasons:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;You can’t know which channels to focus on, or how you’ll grow&lt;/strong&gt;, until you have product-market fit. Who you need for growth may change as you figure this out. I’ve often seen startups discover their initial audience wasn’t their true PMF audience and need to pivot.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;It’s hard to grow with a leaky funnel.&lt;/strong&gt; Product-market fit takes time to find, even with an app where product improvements happen faster than a physical product. After six months, you might think your Head of Growth has underperformed — when really, they’ve been fixing core product issues.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Not all growth hires have experience in finding product-market fit.&lt;/strong&gt; You might be better off bringing on a product hire or go-to-market specialist first.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Another thing not talked about enough is your data infrastructure before hiring for growth. Even if I’m a fit to support a brand, one of the top reasons I turn them down is because their data isn’t ready. You don’t need a fancy dataset, but &lt;strong&gt;having tools in place to measure key parts of your customer journey and attribution is essential&lt;/strong&gt;. Otherwise, your growth hire will spend their first weeks building that foundation, which delays impact.&lt;/p&gt;



&lt;p&gt;The same goes for customer research. Your growth hire needs to immerse themselves in your users. If you don’t already have structured insights — like surveys, interviews, or feedback tagging — it’s harder for them to connect data to real human behavior. They have to know who you’re selling to!&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-deciding-the-role-setup-for-your-growth-hire&quot;&gt;Deciding the role setup for your growth hire&lt;/h2&gt;



&lt;p&gt;Before we dive into the nitty-gritty of hard and soft skills in growth roles, you need to define &lt;em&gt;what &lt;/em&gt;kind of role you need. There are typically three elements you need to think about:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Fractional vs. full-time&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Generalist vs. specialist&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Experienced vs. junior&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-fractional-vs-full-time-nbsp&quot;&gt;1. Fractional vs. full-time&amp;nbsp;&lt;/h3&gt;



&lt;p&gt;It can be tough to know which growth levers will work before you have a growth hire. If you’re still in a very early stage or unsure, I strongly believe in starting with a fractional growth role. They can move you in the right direction — especially if you have other team members who can support them (like a product manager, developer, designer, CRM specialist, etc.).&lt;/p&gt;



&lt;p&gt;At some point, fractional support can hold you back. This usually happens when you have too many freelancers and things get fragmented, or when you need someone who’s around every day. You can’t expect timely replies if they’re only working a day or two a week.&lt;/p&gt;



&lt;p&gt;I like to start with a fractional hire to test the waters and get initial traction, then bring on a full-time hire. Sometimes you can convince the fractional hire to go full-time, but don’t always assume that will happen.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-generalist-vs-specialist-nbsp&quot;&gt;2. Generalist vs. specialist&amp;nbsp;&lt;/h3&gt;



&lt;p&gt;For most organizations, a generalist makes more sense for the first hire. Someone with broad knowledge across growth, from acquisition to monetization, who has deeper expertise in your main growth levers. For example, if you’re struggling to activate new users, you want someone with experience fixing that.&lt;/p&gt;



&lt;p&gt;The challenge with specialists early on is that they tend to focus on their niche. But growth is all connected — what looks like an acquisition problem can also require optimization, onboarding, and communication (email, push notifications). So, unless you already have others with expertise in those areas (like a product manager), I’d recommend starting broader and hiring specialists later as you grow.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-experienced-vs-junior&quot;&gt;3. Experienced vs. junior&lt;/h3&gt;



&lt;p&gt;Sometimes this comes down to experience vs. mindset, rather than just experienced vs. junior. Mindset isn’t optional. I’ve seen founders get excited about a very experienced hire who didn’t quite fit the approach or team culture, and every time, that hire didn’t work out. (This is why we’ll go over key soft skills — because mindset matters.)&lt;/p&gt;



&lt;p&gt;When it comes to experience, it depends on who else in your organization can guide and mentor them. One of my best team members when I was Head of Growth had zero relevant experience and was just 19 when she started. &lt;a href=&quot;https://www.linkedin.com/in/alexia-contoguris/&quot;&gt;Alexia Contoguris&lt;/a&gt; is now a successful Growth Manager, but she had strong mentorship throughout.&lt;/p&gt;



&lt;p&gt;Don’t think of a junior hire just as a ‘budget cut.’ What can appear cheap can hurt you in the long run. &lt;a href=&quot;https://www.linkedin.com/in/josephfitzgibbon/&quot;&gt;Joseph Fitzgibbon&lt;/a&gt;, founder of &lt;a href=&quot;https://www.growthandcompany.com/&quot;&gt;Growth &amp;amp; Company&lt;/a&gt;, has helped hundreds of companies hire for growth roles and has seen this firsthand:&lt;/p&gt;



&lt;p&gt;&lt;em&gt;“I often see founders hiring in junior people who are cheap, but they won’t learn on the job if no one is able to teach them. So the founder(s)’s experience of growth is a key dimension in deciding between experienced and junior. If they don’t know what they’re doing, then they need to buy in help either way — either a course, a fractional, or an experienced Head of Growth.”&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;So if you have a clear strategy, direct experience yourself, and just need help executing, hiring someone junior can work — but be sure to provide guidance, training, and external support to help them grow.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-does-the-job-role-look-like&quot;&gt;What does the job role look like?&lt;/h2&gt;



&lt;p&gt;Growth roles vary a &lt;em&gt;lot&lt;/em&gt;. I once analyzed dozens of job descriptions for ‘Head of Growth’ roles, and each one was completely different, with only a few overlapping skills. It felt like an impossible Venn diagram.&lt;/p&gt;



&lt;p&gt;Before clicking ‘post ad’, you need to identify what skills you want the hire to have, and how they’ll be using them. &lt;strong&gt;Let’s break down the skills that tend to be most relevant, and how I review them with candidates&lt;/strong&gt;. (Resist the temptation to skip the section on soft skills — I see you!)&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-soft-skills&quot;&gt;Soft skills&lt;/h3&gt;



&lt;p&gt;What surprised me in those job descriptions was how 80% of the focus was on hard skills — channel knowledge, tooling experience etc. I’m not saying relevant experience isn’t valuable. But don’t underestimate the power of soft skills. The knowledge your growth hire needs will change constantly, and with the pace of the industry, even an expert will need to keep learning.&lt;/p&gt;



&lt;p&gt;Joseph also noticed another ‘skill’ that founders get caught up:&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;em&gt;“A big mistake that founders make is to focus on where a candidate has been before and put too much emphasis on their experience vs. ability. Industry knowledge is generally overrated — it’s easy to learn, expires quickly, and is not as relevant as it looks on paper.&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;&lt;em&gt;Hiring someone who has been at Airbnb is actually not a great hire for a small travel company as the sizes of business, reality of the role etc. is massively different, even if it’s in the same industry.”&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;Even if you don’t include soft skills explicitly in your job posting, have a clear list of the skills you want to review during interviews. This will vary depending on the role and team they join, but here are some general ones I always check for.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-1-ability-to-balance-strategic-thinking-and-tactical-execution&quot;&gt;1. Ability to balance strategic thinking and tactical execution&lt;/h4&gt;



&lt;p&gt;You might think this is a hard skill — knowing frameworks or tactics. But in my experience, it’s actually a soft skill: the ability to make good judgment calls, balance focus, and resist chasing every shiny new thing.&lt;/p&gt;



&lt;p&gt;In a large organization, a growth role is likely to be more managerial and strategic, but that probably isn’t your first growth hire. In a startup, especially if the founder doesn’t have growth experience, you’ll want someone who can mix strategic thinking with hands-on execution.&lt;/p&gt;



&lt;p&gt;This combination is hard to find. It’s easy to be wowed by shiny tactics like testing a new channel or exploiting a new regulation change. But that can lead to short-term growth-chasing instead of &lt;strong&gt;building scalable approaches&lt;/strong&gt;. You need someone who can do both.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;806&quot; height=&quot;806&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/short-term-v-long-term-focus.png&quot; alt=&quot;&quot; class=&quot;wp-image-46285&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/short-term-v-long-term-focus.png 806w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/short-term-v-long-term-focus-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/short-term-v-long-term-focus-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/short-term-v-long-term-focus-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/short-term-v-long-term-focus-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/short-term-v-long-term-focus-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/short-term-v-long-term-focus-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/short-term-v-long-term-focus-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/short-term-v-long-term-focus-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/short-term-v-long-term-focus-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/short-term-v-long-term-focus-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/short-term-v-long-term-focus-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/short-term-v-long-term-focus-48x48.png 48w&quot; sizes=&quot;auto, (max-width: 806px) 100vw, 806px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Benefits on growth from balancing both the short and long-term&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;h5 class=&quot;wp-block-heading&quot; id=&quot;h-how-i-test-for-this&quot;&gt;How I test for this&lt;/h5&gt;



&lt;p&gt;The way I test for this is by giving candidates an assignment with a wide range of data and insights (including customer insights) across different areas. I ask them to share their approach and identify where they see the biggest opportunity. I also ask what other data they’d want to see to get a clearer picture of where to focus.&lt;/p&gt;



&lt;p&gt;I usually do this live on a call, about an hour long, to keep it fair and make sure they’re not getting outside help. It also mirrors the fast-paced environment of a growth role. For example, if the role focuses on acquisition and onboarding, I might share funnel stats from ads to app store to onboarding to trial sign-ups.&lt;/p&gt;



&lt;p&gt;This approach reveals a &lt;em&gt;lot&lt;/em&gt;. Often, candidates try to optimize every step, which isn’t realistic in an hour and shows a tactical mindset. Others talk only in broad strategic terms without suggesting concrete experiments or next steps.&lt;/p&gt;



&lt;p&gt;What you want is someone who reviews the data and customer insights, narrows down where to focus, and can zoom in on one key area. They should also think beyond the obvious; wanting to understand the bigger picture before choosing where to prioritize. For example, if trial sign-ups are low, they might want to explore which plans people choose, how sign-up rates compare across channels, or how your pricing stacks up against competitors.&lt;/p&gt;



&lt;p&gt;Whether you do this through an assignment or targeted questions, the key is finding that balance. You can also learn a lot from their past roles, how their team was set up and what responsibilities they had. &lt;strong&gt;You want someone who knows how to strategically pick focus areas but can also roll up their sleeves and execute.&lt;/strong&gt;&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-2-ability-to-take-feedback&quot;&gt;2. Ability to take feedback&lt;/h4&gt;



&lt;p&gt;Despite the stereotypes about people in growth, there’s no room for ego or stubbornness in growth. Especially in a role where the ‘best practices’ are constantly challenged and you need tons of insights to make smart decisions. Growth comes from the whole organization, so your first hire will be working with lots of different people, and they need to be open to feedback and ideas from &lt;em&gt;all&lt;/em&gt; of them.&lt;/p&gt;



&lt;p&gt;If you do a live assignment like the one above, it’s a perfect way to test this. I usually give live feedback at the end of the call and watch their reaction closely. Consider facial expressions and how they respond. Is it a simple “Thanks”, or do they ask questions to understand better? Explanation can be helpful, but too many justifications of “Well, I did that because…” can imply defensiveness. My favorite response? Questions, because that shows another key trait…&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-3-curiosity&quot;&gt;3. Curiosity&lt;/h4&gt;



&lt;p&gt;The old saying ‘curiosity killed the cat’ definitely doesn’t apply in growth — unless you add the second part, ‘but satisfaction brought it back’. Growth people need to be curious: about what the data is telling them, what customers are saying, what the team thinks, and what they can learn next.&lt;/p&gt;



&lt;p&gt;The sure sign of a curious growth hire? &lt;strong&gt;They ask questions in every interview.&lt;/strong&gt; They want to learn about you as much as you want to learn about them. They ask things they couldn’t find answers to online, they make suggestions, and seem eager to absorb new information.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-4-raw-intelligence&quot;&gt;4. Raw intelligence&lt;/h4&gt;



&lt;p&gt;This was one that Joseph suggested, and it felt very true. I’m not talking about academic intelligence, IQ level, or how many degrees people have, but about how people approach things — from the questions they ask, to the way they tackle problems.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Thinking back to my junior at Heights, she was quick to understand everything and keen to learn more. Many of the best growth people I worked with were clever in a way that drove them to learn, be curious, and &lt;strong&gt;think of unusual paths to success&lt;/strong&gt;.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-hard-skills&quot;&gt;Hard skills&lt;/h3&gt;



&lt;p&gt;As mentioned, these skills really vary depending on the experience level of your hire. The below is most for those with some experience. For juniors, you’ll want to look at the soft skill that relates to each hard skill — for example, for data analytics, someone who genuinely loves numbers and analysis (they get excited about the idea of a pivot table!).&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-1-experience-creating-and-improving-the-growth-strategy&quot;&gt;1. Experience creating and improving the growth strategy&lt;/h4&gt;



&lt;p&gt;This one’s obvious, but assuming you want someone more experienced, this is a must-have. It’s great if they’ve done it in a subscription app before, but I wouldn’t say it’s essential. There’s a learning curve moving into apps, but I’d rather pick someone with the right mindset and experience over a specific subscription app background.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-2-data-analytics&quot;&gt;2. Data analytics&lt;/h4&gt;



&lt;p&gt;&lt;em&gt;Obviously, they need to know how to use RevenueCat. (Just kidding, it’s very intuitive, they’ll figure it out in no time!)&lt;/em&gt; Roles tend to focus on experience with [insert analytics tool], but I think it’s more the experience of analyzing data and understanding the full customer journey that’s important. Once someone has worked with one or two analytics tools, learning new ones is usually straightforward. Focus on data analysis experience, and consider your tool stack a nice-to-have.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-3-experience-running-experiments&quot;&gt;3. Experience running experiments&lt;/h4&gt;



&lt;p&gt;Experimentation is a huge part of turning subscriptions into success. You don’t want a growth hire who just throws stuff at the wall, hoping something sticks. Things won’t keep sticking, trust me on that. They need to see the value in experiments, actively pursue them, and learn from them. Ask them how they structured experiments in the past and what that process looked like.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-4-cro-and-ux-experience&quot;&gt;4. CRO and UX experience&lt;/h4&gt;



&lt;p&gt;Expertise here is super valuable. With apps, the app &lt;em&gt;is&lt;/em&gt; the product, so CRO knowledge helps not just with optimizing purchase flows, but also activation, retention, and monetization. Understanding UX is another area I’d recommend including for most growth roles. Knowing (and placing value) on user experience is key to good app design and retention; this belief should already be ingrained when you hire them.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-5-specific-area-knowledge-related-to-your-growth-opportunities&quot;&gt;5. Specific area knowledge related to your growth opportunities&lt;/h4&gt;



&lt;p&gt;We touched on this early — even generalists usually have one–two areas they’re most passionate about or experienced in. This could be something like monetization, retention, or more specific areas like paywall optimization. It could also be channel-specific skills, like ASO or paid ads, which they’ll manage until you can hire an expert.&lt;/p&gt;



&lt;p&gt;If there is a must-have area for you, or a mission-critical area you need to optimize for success, include this as a required hard skill.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-a-final-word-of-warning-keep-it-specific&quot;&gt;A final word of warning: keep it specific&lt;/h3&gt;



&lt;p&gt;When I analyzed growth roles, I noticed many ads list 20–30 different skills that are ‘must-have’. It reminded me of my nephew at the Harry Potter gift store in Warner Bros. Studio. In a burst of excitement, he raced around, filling his little arms with everything from a Hedwig stuffed toy to a book of spells — because duh, every wizard needs that.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Amused, I watched his mum explain his holiday budget to him. Though slightly deflated, he did some quick math and put a few things back. I’d like to say he was thrilled on the car ride home… but after six hours at the studio, he promptly passed out.&lt;/p&gt;



&lt;p&gt;The point? As much as you want it all, you can’t have it all — and honestly, you don’t need it all. It won’t fit your budget, and some skills aren’t essential. Focus on the very specific skills that matter most, not a ‘must-have everything’ checklist.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;💡 &lt;strong&gt;Pro tip&lt;/strong&gt;&lt;br&gt;One of my favorite first interview questions is: “What do you &lt;em&gt;not&lt;/em&gt; enjoy working on?” followed by, “What areas do you have little experience in?” Everyone has these, and it’s a quick check to see if they’ll dislike or struggle with any fundamental parts of the role that are key to your success.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-setting-your-hire-up-for-success&quot;&gt;Setting your hire up for success&lt;/h2&gt;



&lt;p&gt;&lt;a href=&quot;https://www.linkedin.com/in/rosie-hoggmascall/&quot;&gt;Rosie Hoggmascall&lt;/a&gt; (Growth lead at Fyxer.ai) and I once interviewed a group of growth leads about their careers. We wanted to understand why so many growth hires fail or leave within the first year. Our findings were eye-opening and inspired us to &lt;a href=&quot;https://daphnetideman.com/growthonboardingchecklist&quot;&gt;create a short course on the topic&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;One of the biggest patterns was poor, or even nonexistent, onboarding. Hires were brought in without structured onboarding or clear guidance, while founders juggled a million other things. As a result, it often took much longer than necessary for them to understand the organization, and many didn’t even know what questions to ask.&lt;/p&gt;



&lt;p&gt;The takeaway is &lt;strong&gt;take the time to build a clear, structured plan for their first 30, 60, and 90 days&lt;/strong&gt;:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Who should your hire meet with?&amp;nbsp;&lt;/li&gt;



&lt;li&gt;What insights do they need to review?&amp;nbsp;&lt;/li&gt;



&lt;li&gt;What deliverables do you expect?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The goal isn’t to limit their focus, but to ensure they truly understand the objectives they need to hit, and avoid spinning their wheels for months, hearing ‘we’ve tried that before’.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-time-to-get-hiring&quot;&gt;Time to get hiring&lt;/h2&gt;



&lt;p&gt;If you’ve made it this far, you’ve probably worked out that you’re ready to start searching for your growth role. Congrats!&lt;/p&gt;



&lt;p&gt;Growth is a broad field, and if you’re not careful, your job description can turn into an unrealistic wishlist. That creates two problems: attracting overconfident generalists who sound great on paper but aren’t the right fit, and/or losing focus on the few key skills that actually matter &lt;em&gt;right now&lt;/em&gt;.&lt;/p&gt;



&lt;p&gt;The best way to avoid this? Run your job spec by others. Share it with your team, ask a fellow founder, or even better, ask someone who specialises in hiring growth roles.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Questions to ask:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Who do you think we’re looking for based on this?&lt;/li&gt;



&lt;li&gt;What do you think isn’t important for us based on this job description?&lt;/li&gt;



&lt;li&gt;Given our growth model and team, is there anything we’ve missed?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;And before you post that role, run through this quick readiness checklist:&lt;/p&gt;



&lt;p&gt;✔️ You have product-market fit (or strong leading indicators)&lt;br&gt;✔️ You have the ability to measure key parts of your funnel and attribution&lt;br&gt;✔️ You’ve identified your current growth bottlenecks&lt;br&gt;✔️ You know which soft and hard skills are truly critical for this stage&lt;br&gt;✔️ You have the time and structure in place to properly onboard your hire&lt;/p&gt;



&lt;p&gt;Keep a critical eye throughout the process and stay focused on what truly matters. If you do that, you’re much more likely to find someone who not only looks good on paper, but actually drives growth in your subscription app.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[How to build a win-back campaign with RevenueCat Web Billing]]></title><description><![CDATA[​​Use RevenueCat Web Billing and Zapier to bring churned users backRevenueCat Web Billing win-back campaign]]></description><link>https://www.revenuecat.com/blog/growth/how-to-build-a-win-back-campaign-with-revenuecat-web-billing/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/how-to-build-a-win-back-campaign-with-revenuecat-web-billing/</guid><pubDate>Fri, 19 Sep 2025 13:10:16 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/2.-How-to-build-a-win-back-campaign-with-RevenueCat-Web-Billing.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Losing a customer often feels like the end of the line but it rarely is that. It happens with every business, however what sets out the winner from the losers is being able to bring those users back. Winning back the customer is all about re-engaging the user to reconsider subscribing again. One very powerful win-back method is to give the user a discount, if they continue their subscription.&lt;/p&gt;



&lt;p&gt;In this article, we’ll walk through how you can create a web-based win-back campaign for your mobile apps using RevenueCat’s Web Billing — without needing to create or manage your own backend for writing a line of code.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-what-is-a-win-back-campaign&quot;&gt;What is a win-back campaign?&lt;/h3&gt;



&lt;p&gt;A win-back campaign is a way to try to earn back the business of a churned customer. When a user cancels their subscription, you can attempt to re-engage them and bring them back to using the service. This could involve for example sending a push notification, or an email, that offers the user to resubscribe with a discount.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;You can monitor unsubscribe events in RevenueCat’s dashboard, and by using the webhooks functionality automatically email the user when they unsubscribe, nudging them to come back with a discounted offer on the subscription.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-why-use-web-billing-for-win-back-campaigns&quot;&gt;Why use Web Billing for win-back campaigns?&lt;/h3&gt;



&lt;p&gt;RevenueCat’s Web Billing allows users to make purchases through the web instead of through the traditional in-app purchase flow. It integrates seamlessly with RevenueCat’s ecosystem, so a purchase made on the web still unlocks features inside your app. RevenueCat handles all the subscription management for you, including billing, status tracking, and more.&lt;/p&gt;



&lt;p&gt;One of the major benefits that comes with RevenueCat Web Billing is that it can exist side-by-side with your iOS and Android in-app purchases. Additionally the commission on Web Billing is smaller than those of Apple and Google. Subscriptions made through Web Billing have an additional Stripe transaction fee of 2.9% + 30¢ per transaction, and an option Stripe Tax fee: 50¢ per transaction in tax-registered locations. Meanwhile the commission for in-app subscriptions for Apple and Google is 15-30% depending if you are in the small business program or not.&lt;/p&gt;



&lt;p&gt;This means that every subscription made through Web billing can bring potentially 12.1-27.1% more revenue when a user subscribes. This difference in fees allows you to use for example to offer a discount on the win-back, while still keeping the same margin as for the existing subscription that a user churned out from.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-to-build-a-win-back-campaign-with-revenuecat&quot;&gt;How to build a win-back campaign with RevenueCat&lt;/h2&gt;



&lt;p&gt;In this tutorial we are going to build a win-back campaign that is similar to what we just described. First the user will subscribe, and later cancel which will lead to their subscription expiring, at that moment our win-back campaign will trigger and send an email to the user offering a discount. The email will contain a link to a web-based purchase page where they can subscribe again, outside of the mobile app.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;We want to keep things simple, and although it would be possible to build all of this using by building your own backend solution, we can get by with much less. RevenueCat provides hosted payment pages and functionality for making services do things based on subscription events. Your app should have RevenueCat SDK installed, other than we don’t need to make changes to the app side of this but can instead configure everything through RevenueCat’s dashboard&lt;/p&gt;



&lt;p&gt;We’ll use two main features: &lt;strong&gt;Redemption Links&lt;/strong&gt;, which allow users to redeem offers and associate purchases with their existing accounts, and &lt;strong&gt;Webhooks&lt;/strong&gt;, which allow RevenueCat to notify external services (like email marketing platforms) about subscription events such as expirations.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;501&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-8@1x-1024x501.png&quot; alt=&quot;&quot; class=&quot;wp-image-46273&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-8@1x-1024x501.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-8@1x-300x147.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-8@1x-768x375.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-8@1x-50x24.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-8@1x-82x40.png 82w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-8@1x-696x340.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-8@1x-560x274.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-8@1x-840x411.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-8@1x-80x39.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-8@1x-48x23.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-8@1x.png 1440w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-use-zapier-to-send-win-back-emails&quot;&gt;Use Zapier to Send Win-Back Emails&lt;/h3&gt;



&lt;p&gt;For this tutorial, we’ll use Zapier to send win-back emails because it’s fast and simple to demonstrate. However, you can also use more robust marketing platforms, and some — like OneSignal — have direct integrations with RevenueCat, eliminating even the need to manually configure webhooks.&lt;/p&gt;



&lt;p&gt;The general flow is straightforward. When a user’s subscription expires, RevenueCat will send a webhook event. Zapier will catch that webhook and trigger an email to the user. The email might say something like, “We’re sad to see you go. Here’s a link for a discount,” and will include a link to a web-hosted paywall page where they can easily resubscribe at a discounted rate. We will get to the details in a minute.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-web-paywall-links&quot;&gt;Web Paywall Links&lt;/h3&gt;



&lt;p&gt;The link inside the email will point the user to a Web Paywall Link. This is a hosted page provided by RevenueCat where users can purchase a subscription plan without needing to download the app again or interact with the App Store or Play Store. RevenueCat handles all aspects of billing, sends email receipts, and provides users with a subscription management portal where they can update payment methods, cancel subscriptions, and more.&lt;/p&gt;



&lt;p&gt;Once the user completes the purchase, we use Redemption Links to tie their new web subscription back to their existing user account inside the app. This ensures they immediately get access to the correct entitlements after the discounted subscription is complete.&lt;/p&gt;



&lt;p&gt;One of the best parts of this flow is that it requires almost no new code. You won’t need to build a web page, write HTML, or write JavaScript. Nearly everything can be set up using the RevenueCat dashboard with a little bit of configuration on your mobile app.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-1-prepare-the-app-to-use-redemption-links&quot;&gt;Step 1: Prepare the app to use redemption links&lt;/h2&gt;



&lt;p&gt;Testing our win-back campaign will require using a real device instead of a simulator as we will need real subscription events to be triggered via the App Store Sandbox. RevenueCat relies on actual events from App Store Connect to power subscription status updates and webhook triggers.&lt;/p&gt;



&lt;p&gt;You need to ensure that RevenueCat is capturing your user’s email. This can be achieved by setting attributes:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z27BcPt wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;swift&quot; content=&quot;&amp;quot;Purchases.shared.attribution.setAttributes([\&amp;quot;$email\&amp;quot;: \&amp;quot;customer@email.com\&amp;quot;])&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The attribute has a dollar sign in front of it, as it is a reserved attribute, showing up differently than custom attributes in RevenueCat dashboard and the webhook payload. If your app is already registering a user’s email in RevenueCat you don’t have to make any changes to the app.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-2-connect-stripe-to-revenuecat&quot;&gt;Step 2: Connect Stripe to RevenueCat&lt;/h2&gt;



&lt;p&gt;The first step to setting up Web Billing is to connect a Stripe account to RevenueCat. Importantly, Stripe is connected at the &lt;strong&gt;account level&lt;/strong&gt;, not the project level. The owner of your RevenueCat account must complete this connection. Once Stripe is linked, anyone within the RevenueCat account can configure Web Billing settings.&lt;/p&gt;



&lt;p&gt;Inside the RevenueCat dashboard, under the Account section, you can connect a Stripe account by launching the RevenueCat app within the Stripe app marketplace. After installing the app — and choosing test mode for this tutorial — you’ll see RevenueCat available within your Stripe dashboard. Once installed, returning to the RevenueCat dashboard should show Stripe successfully connected.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-3-create-a-new-web-billing-app&quot;&gt;Step 3: Create a new Web Billing app&lt;/h2&gt;



&lt;p&gt;Now, open your RevenueCat project. You’ll see the existing app setup, including configured products and a paywall already associated with it. However, for web billing, you’ll create a new app inside your project, choosing the &lt;strong&gt;Web Billing&lt;/strong&gt; type.&lt;/p&gt;



&lt;p&gt;When creating the new Web Billing app:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Link it to the Stripe account you just connected.&lt;/li&gt;



&lt;li&gt;Choose your default currency (e.g., USD).&lt;/li&gt;



&lt;li&gt;Fill out basic app information such as name and support email.&lt;/li&gt;



&lt;li&gt;Provide an App Store URL, even if it’s just a placeholder&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Once the Web Billing app is created, you can optionally add an app icon for better branding during checkout and invoice displays.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;501&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-4@1x-1024x501.png&quot; alt=&quot;&quot; class=&quot;wp-image-46257&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-4@1x-1024x501.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-4@1x-300x147.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-4@1x-768x375.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-4@1x-50x24.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-4@1x-82x40.png 82w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-4@1x-696x340.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-4@1x-560x274.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-4@1x-840x411.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-4@1x-80x39.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-4@1x-48x23.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-4@1x.png 1440w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-customize-the-appearance-of-web-paywall&quot;&gt;Customize the appearance of web paywall&lt;/h3&gt;



&lt;p&gt;RevenueCat allows you to customize the appearance of the hosted web paywall and customer portal. Using the Appearance Editor, you can match the style to your mobile app by adjusting background colors, button styles, accent colors, and more. After making your customizations, save the changes.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;626&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-3@1x-1024x626.png&quot; alt=&quot;&quot; class=&quot;wp-image-46255&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-3@1x-1024x626.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-3@1x-300x183.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-3@1x-768x469.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-3@1x-50x31.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-3@1x-65x40.png 65w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-3@1x-696x425.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-3@1x-560x342.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-3@1x-484x296.png 484w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-3@1x-772x472.png 772w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-3@1x-80x49.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-3@1x-48x29.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-3@1x.png 1440w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-4-set-up-products&quot;&gt;Step 4: Set up products&lt;/h2&gt;



&lt;p&gt;Next, you’ll configure products inside the Web Billing app. For the win-back campaign, you’ll create a discounted monthly subscription product — offering 50% off compared to the regular app store price.&lt;/p&gt;



&lt;p&gt;Define a new product in the Web Billing app:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Name it clearly (e.g., “Paw Plus_149_Monthly”).&lt;/li&gt;



&lt;li&gt;Set it as an &lt;strong&gt;auto-renewing subscription&lt;/strong&gt;.&lt;/li&gt;



&lt;li&gt;Set the price to $1.49 (or what matches your desired discount).&lt;br&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Attach this new product to the existing &lt;strong&gt;Pro&lt;/strong&gt; entitlement, ensuring that when users subscribe via the web, they unlock the same premium content as they would through the iOS app.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-5-create-an-offering-and-web-paywall-link&quot;&gt;Step 5: Create an offering and web paywall link&lt;/h2&gt;



&lt;p&gt;With the new product created, the next step is to build an &lt;strong&gt;Offering&lt;/strong&gt;, a grouping of available products for purchase&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;501&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-5@1x-1024x501.png&quot; alt=&quot;&quot; class=&quot;wp-image-46271&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-5@1x-1024x501.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-5@1x-300x147.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-5@1x-768x375.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-5@1x-50x24.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-5@1x-82x40.png 82w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-5@1x-696x340.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-5@1x-560x274.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-5@1x-840x411.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-5@1x-80x39.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-5@1x-48x23.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-5@1x.png 1440w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Create a new offering (e.g., “Web Win-back Offering”) that contains only the discounted monthly subscription. Then, create a &lt;strong&gt;Web Purchase Link&lt;/strong&gt; associated with this offering. The Web Paywall Link configuration defines what users see on the web page, including:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;A custom header and body text.&lt;/li&gt;



&lt;li&gt;Terms and conditions link.&lt;/li&gt;



&lt;li&gt;A success page after purchase.&lt;/li&gt;



&lt;li&gt;Instructions for redemption via a deep link if they’ve made a purchase.&lt;/li&gt;
&lt;/ul&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;574&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-18-at-18.08.37-1024x574.png&quot; alt=&quot;&quot; class=&quot;wp-image-46259&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-18-at-18.08.37-1024x574.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-18-at-18.08.37-300x168.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-18-at-18.08.37-768x431.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-18-at-18.08.37-1536x862.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-18-at-18.08.37-2048x1149.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-18-at-18.08.37-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-18-at-18.08.37-71x40.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-18-at-18.08.37-696x390.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-18-at-18.08.37-560x314.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-18-at-18.08.37-528x296.png 528w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-18-at-18.08.37-840x472.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-18-at-18.08.37-80x45.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Screenshot-2025-09-18-at-18.08.37-48x27.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Configure the Web Paywall Link to detect if a user already has an entitlement and redirect them accordingly.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-6-configure-redemption-links&quot;&gt;Step 6: Configure redemption links&lt;/h2&gt;



&lt;p&gt;Because users might not log in on the web, Redemption Links allow the RevenueCat system to link a web purchase to a mobile user account without explicit authentication.&lt;/p&gt;



&lt;p&gt;Inside your Web Billing app settings in RevenueCat:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Enable &lt;strong&gt;Redemption Links&lt;/strong&gt; (sandbox-only for testing).&lt;/li&gt;



&lt;li&gt;Set up a custom URL scheme inside your mobile app (e.g., pawplus://).&lt;br&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;501&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy@1x-1024x501.png&quot; alt=&quot;&quot; class=&quot;wp-image-46239&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy@1x-1024x501.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy@1x-300x147.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy@1x-768x375.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy@1x-50x24.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy@1x-82x40.png 82w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy@1x-696x340.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy@1x-560x274.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy@1x-840x411.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy@1x-80x39.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy@1x-48x23.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy@1x.png 1440w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;TK copy, In iOS, you need to define a custom URL schema. You can do this in Xcode, from your xcodeproj file, Info tab, URL Types section. Then add your custom scheme from Step 1 in the “URL Schemes” field. You can see a screenshot here, but remember to replace &amp;lt;YOUR_CUSTOM_SCHEME&amp;gt; with the one you configured.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;325&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-2@1x-1024x325.png&quot; alt=&quot;&quot; class=&quot;wp-image-46252&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-2@1x-1024x325.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-2@1x-300x95.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-2@1x-768x244.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-2@1x-50x16.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-2@1x-125x40.png 125w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-2@1x-696x221.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-2@1x-560x178.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-2@1x-840x267.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-2@1x-80x25.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-2@1x-48x15.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-2@1x.png 1440w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;This way, after completing a web purchase, users can redeem their subscription via a deep link, unlocking premium content in the app.&lt;/p&gt;



&lt;p&gt;In your iOS app add a &lt;code&gt;onWebPurchaseRedemptionAttempt&lt;/code&gt; modifier to listen for the redemption link and update the user’s subscription status after a successful link, in SwiftUI this can be accomplished with a modifier&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-BFtDo wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;YourContent()\n    .onWebPurchaseRedemptionAttempt { result in\n        switch result {\n        case .success(customerInfo):\n            \/\/ Redemption was successful and entitlements were granted to the user.\n            updateUI(customerInfo)\n        case let .error(error):\n            \/\/ Redemption failed due to an error.\n            displayError(error)\n        case .invalidToken:\n            \/\/ The redemption link is invalid.\n            displayInvalidLinkError()\n        case .purchaseBelongsToOtherUser:\n            \/\/ The purchase associated to the link belongs to a different user and it cannot be redeemed.\n            displayBelongsToOtherUserError()\n        case let .expired(obfuscatedEmail):\n            \/\/ The redemption link has expired. A new one has been sent to the user to the provided obfuscated email.\n            displayExpiredMessage(obfuscatedEmail)\n        }\n    }&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-7-build-the-email-automation-with-zapier&quot;&gt;Step 7: Build the Email Automation with Zapier&lt;/h2&gt;



&lt;p&gt;To send the win-back emails automatically, you’ll use RevenueCat webhooks combined with a Zapier automation (“Zap”).&lt;/p&gt;



&lt;p&gt;In RevenueCat:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Create a new &lt;strong&gt;Webhook&lt;/strong&gt; integration.&lt;/li&gt;



&lt;li&gt;Target only the &lt;strong&gt;subscription expired&lt;/strong&gt; event for your iOS app.&lt;/li&gt;



&lt;li&gt;Use the webhook URL provided by Zapier.&lt;/li&gt;
&lt;/ul&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;501&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium@1x-1024x501.png&quot; alt=&quot;Configuring webhook for win-back &quot; class=&quot;wp-image-46237&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium@1x-1024x501.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium@1x-300x147.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium@1x-768x375.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium@1x-50x24.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium@1x-82x40.png 82w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium@1x-696x340.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium@1x-560x274.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium@1x-840x411.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium@1x-80x39.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium@1x-48x23.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium@1x.png 1440w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;In Zapier:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Set the trigger to catch incoming webhooks.&lt;/li&gt;



&lt;li&gt;Use the customer’s email attribute from the RevenueCat event as the recipient address.&lt;/li&gt;



&lt;li&gt;Compose an email encouraging users to resubscribe at a discount.&lt;/li&gt;



&lt;li&gt;Include the Web Paywall Link inside the email.&lt;/li&gt;
&lt;/ul&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;438&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-7@1x-1024x438.png&quot; alt=&quot;&quot; class=&quot;wp-image-46269&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-7@1x-1024x438.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-7@1x-300x128.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-7@1x-768x329.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-7@1x-50x21.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-7@1x-94x40.png 94w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-7@1x-696x298.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-7@1x-560x240.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-7@1x-840x359.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-7@1x-80x34.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-7@1x-48x21.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/3-・-Medium-Copy-7@1x.png 1440w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;This will send users an automated email offering them a discounted subscription right after their original subscription expires.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-8-final-end-to-end-test&quot;&gt;Step 8: Final end-to-end test&lt;/h2&gt;



&lt;p&gt;After everything is set up you should test that your automation works through all the steps:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;A user starts a subscription in the mobile app.&lt;/li&gt;



&lt;li&gt;They cancel their subscription.&lt;/li&gt;



&lt;li&gt;After expiration, Zapier sends a discount email.&lt;/li&gt;



&lt;li&gt;The user clicks the link, subscribes via the Web Paywall Link.&lt;/li&gt;



&lt;li&gt;After purchase, they are given a redemption link that deep links into your app.&lt;/li&gt;



&lt;li&gt;The app links their new web subscription and unlocks premium features immediately.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Testing these steps should be done on a real device.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-conclusion&quot;&gt;Conclusion&lt;/h2&gt;



&lt;p&gt;By using RevenueCat Web Billing, Webhooks, and Zapier, you have now built a powerful win-back campaign without needing to code or manage your own website. The setup allows for offering steep discounts, better attribution, and seamless integration between web purchases and mobile app experiences. Check the resources below to learn more&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/web/web-billing/redemption-links&quot;&gt;Redemption links&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/integrations/webhooks&quot;&gt;Webhooks in RevenueCat&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;Another tutorial on using RevenueCat webhooks to build powerful automations, this time to power a &lt;a href=&quot;https://www.revenuecat.com/blog/engineering/how-to-build-a-blinkist-style-paywall-using-revenuecat-webhooks-and-zapier/&quot;&gt;Blinkist-style timeline paywall&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[LinkedIn’s approach to product testing and growth, with VP of Product Management Ora Levit]]></title><description><![CDATA[How a billion-user platform keeps growing by listening to its members]]></description><link>https://www.revenuecat.com/blog/growth/ora-levit-linkedin-sub-club-2025/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/ora-levit-linkedin-sub-club-2025/</guid><pubDate>Wed, 17 Sep 2025 14:10:57 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/ora-levit-linkedin-sub-club-2025.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;When you think of subscription apps, the professional social networking platform LinkedIn might not be your first thought. But maybe it should be! With over a billion active users and several billions of dollars in annual revenue, LinkedIn is one of the most successful subscription app businesses in the world.&lt;/p&gt;



&lt;p&gt;This week on the Sub Club podcast, we sat down with &lt;a href=&quot;https://www.linkedin.com/in/oralevit/&quot;&gt;Ora Levit&lt;/a&gt;, Vice President of Product Management at LinkedIn. We asked Ora about the product development and testing strategies that have helped her team grow LinkedIn into such a success and what other subscription app businesses can learn from it.&lt;/p&gt;



&lt;iframe loading=&quot;lazy&quot; width=&quot;100%&quot; height=&quot;180&quot; frameborder=&quot;no&quot; scrolling=&quot;no&quot; seamless=&quot;&quot; src=&quot;https://share.transistor.fm/e/39553414?color=FFFFFF&amp;amp;background=30343C&quot;&gt;&lt;/iframe&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;Value-Driven Growth: LinkedIn&apos;s Billion-Dollar Subscription Strategy — Ora Levit, LinkedIn&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/CdlajgDk_tw?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-value-add&quot;&gt;&lt;strong&gt;Value add&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Much of LinkedIn’s success can be attributed to the team’s focus on value-driven growth: a steadfast commitment to consistently adding valuable features to the app. It may sound obvious, but continually evolving an app to provide fresh value is one of the best ways to acquire and retain users and build long-term growth.&lt;/p&gt;



&lt;p&gt;This philosophy, along with LinkedIn’s mission to help job seekers and business owners achieve their goals, plays a central role in how Ora and her team approach product development. “First and foremost, LinkedIn’s mission is to provide an economic opportunity for every member of the global workforce …&amp;nbsp; so we prioritize our free experiences first,” Ora said. This means that LinkedIn is generally free to use but certain nice-to-have features — like marking a job as your top choice —&amp;nbsp;are only available to Premium subscribers. Members also have access to bundled benefits (such as access to &lt;a href=&quot;https://www.duolingo.com/&quot;&gt;Duolingo&lt;/a&gt; and &lt;a href=&quot;https://www.duolingo.com/&quot;&gt;Notion&lt;/a&gt;) that make a paid membership even more valuable.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-put-it-to-the-test&quot;&gt;&lt;strong&gt;Put it to the test&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Testing is a key part of any subscription business, and LinkedIn has it down to a science. LinkedIn runs an astonishing 1000+ A/B tests per year, which helps Ora and her team stay in step with what users want. “I don’t believe in sitting in the office by ourselves and figuring out what it should be because we have millions of members — they know better what works for them,” she said. “The more we can minimize time [spent discussing] internally and maximize the time where we learn and go to market and get that signal, the better we are at serving our customers.”&lt;/p&gt;



&lt;p&gt;This focus on testing helps the LinkedIn team iterate faster: quickly determining which features are resonating with users and which aren’t —&amp;nbsp;without guesswork.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-retain-and-regain&quot;&gt;&lt;strong&gt;Retain and regain&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;While LinkedIn has impressive user acquisition and retention stats, some amount of churn is inevitable. But Ora and her team understand that churn isn’t always the end of the story. When a former customer’s needs change (for example, they start a new business or re-enter the job market), they may become interested in signing up for LinkedIn Premium again.&lt;/p&gt;



&lt;p&gt;One way that LinkedIn wins back former subscribers is by offering multiple free trials. Most apps offer a single free trial and once a user has taken advantage, that’s it. But according to Ora, “Our offering changes over time, and as I mentioned, we believe in value-driven growth. We add a lot of value. And so the Premium that you’ve seen if you subscribed two years ago is not the Premium of today. It’s a very different product, and I want you to try it out.” By allowing users to experience the value of the new and improved premium tier, LinkedIn encourages former customers to “boomerang” back into paid subscribers.&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;p&gt;These are just a few of the topics we covered in our conversation with Ora. To hear more of LinkedIn’s story and what you can learn from it, check out &lt;a href=&quot;https://subclub.com/episode/value-driven-growth-linkedins-billion-dollar-subscription-strategy-ora-levit-linkedin&quot;&gt;this week’s episode of the Sub Club podcast&lt;/a&gt;.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Start here: a paywalls study guide]]></title><description><![CDATA[Get the download on everything you need to know about paywalls, all in one place]]></description><link>https://www.revenuecat.com/blog/growth/paywalls-study-guide/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/paywalls-study-guide/</guid><pubDate>Wed, 17 Sep 2025 09:46:03 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Paywalls.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Think of &lt;em&gt;Start here&lt;/em&gt; as your digital crash course to all-things app monetization and growth, ranging from paywalls to user retention. No fluff, no content hidden behind paywalls (ironically) — just expert content ready to &lt;strong&gt;get you up to speed, upskilled, and inspired&lt;/strong&gt;.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;So go ahead and browse, bookmark for later, or painstakingly digest each piece in all its glorious detail. We don’t much care what you do, we just hope it’s useful.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;For our first topic, where better to begin than paywalls?&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-paywalls-essential-reading&quot;&gt;&lt;strong&gt;Paywalls: essential reading&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;First up, this section covers the fundamentals of paywalls for subscription apps. If you’re new to the topic, or only have a few minutes, start here.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Link&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Format&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Includes&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/guide-to-mobile-paywalls-subscription-apps/&quot;&gt;The essential guide to paywalls for subscription apps&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Guide&lt;/td&gt;&lt;td&gt;Your handbook to paywalls: key types of paywall, optimization principles, compliance information, and paywall testing techniques&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://subclub.com/episode/how-to-build-more-successful-paywalls-sylvain-gauchet&quot;&gt;Sub Club: How to Build More Successful Paywalls&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Podcast &amp;amp; video&lt;/td&gt;&lt;td&gt;Top strategies for paywall optimization, particularly within user journeys&lt;br&gt;&lt;br&gt;&lt;strong&gt;&lt;em&gt;Note: &lt;/em&gt;&lt;/strong&gt;&lt;em&gt;If you’d rather watch than listen, &lt;/em&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=zza9ZIB8jyk&quot;&gt;&lt;em&gt;all Sub Club episodes are also available as video!&lt;/em&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-hard-vs-soft-paywalls&quot;&gt;&lt;strong&gt;Hard vs. soft paywalls&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Choose your fighter: hard or soft paywalls? Neither is better, the right choice depends on your audience and content. Explore the options, from freemium to fully-gated, below.&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Link&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Format&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Includes&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/hard-paywall-vs-soft-paywall/&quot;&gt;Hard paywall vs. soft paywall: How much of your app should be locked?&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Blog&lt;/td&gt;&lt;td&gt;Pros and cons of hard and soft paywalls, ft. case studies from apps like Headspace and Lose It!&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Subscription App Glossary:&lt;br&gt;&lt;a href=&quot;https://www.revenuecat.com/glossary/#paywall&quot;&gt;Paywall&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://www.revenuecat.com/glossary/#hard-paywall&quot;&gt;Hard paywall&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://www.revenuecat.com/glossary/#soft-paywall&quot;&gt;Soft paywall&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Definition&lt;/td&gt;&lt;td&gt;Quickfire definitions on key terms&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://subclub.com/episode/why-more-apps-need-to-be-more-than-just-apps-melissa-cash-felix-boudreau-pok-pok&quot;&gt;Sub Club: Why More Apps Need To Be More Than Just Apps&lt;/a&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;Podcast &amp;amp; video&lt;/td&gt;&lt;td&gt;Lessons and unexpected benefits from implementing a hard paywall at Pok Pok&lt;br&gt;&lt;br&gt;&lt;strong&gt;&lt;em&gt;Note: &lt;/em&gt;&lt;/strong&gt;&lt;em&gt;Jump to 27:06 for paywalls&lt;/em&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://subclub.com/episode/scaling-without-a-marketing-budget-mike-overell-classdojo&quot;&gt;Sub Club: Scaling Without a Marketing Budget&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Podcast &amp;amp; video&lt;/td&gt;&lt;td&gt;Advice from ClassDojo on setting up the right paywall for your app without impeding growth&amp;nbsp;&lt;br&gt;&lt;br&gt;&lt;strong&gt;&lt;em&gt;Note: &lt;/em&gt;&lt;/strong&gt;&lt;em&gt;Jump to 16:45 for paywalls&lt;/em&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-paywall-design-and-ui&quot;&gt;&lt;strong&gt;Paywall design and UI&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;It’s time to put down the moodboard and start designing. But what elements of paywall UI drive the most engagement?&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Link&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Format&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Includes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/paywall-redesigns-case-studies/&quot;&gt;How four paywall redesigns boosted conversions and revenue&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Blog&lt;/td&gt;&lt;td&gt;A breakdown of four apps, from food to fintech, who redesigned paywalls and saw a 20% increase in conversion&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/ugly-paywalls-conversion-testing/&quot;&gt;Dare to test an ugly paywall? Here’s why you should&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Blog&lt;/td&gt;&lt;td&gt;Why stripping back design elements can boost conversion&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/weird-paywalls-drive-subscription-growth/&quot;&gt;When paywalls get weird (and work)&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Blog&lt;/td&gt;&lt;td&gt;Real-world examples of quirky, rule-breaking paywalls that work (and why)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/engineering/server-driven-android/&quot;&gt;Server-driven UI SDK on Android: How RevenueCat enables remote paywalls without app updates&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Blog&lt;/td&gt;&lt;td&gt;Discover a server-driven approach to paywall UI for more control over your paywall’s appearance on Android&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=DiSWSxv5X-s&quot;&gt;Create auto-looping carousels with RevenueCat Paywalls&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Video tutorial&lt;/td&gt;&lt;td&gt;Walkthrough how to build carousels that capture and convert in RevenueCat Paywalls&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=h5KHK4dxwRQ&quot;&gt;Custom fonts for Paywalls&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Video tutorial&lt;/td&gt;&lt;td&gt;See how to install custom fonts in RevenueCat Paywalls&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=aJp7m4TYK7E&quot;&gt;How to create a timeline design with RevenueCat Paywalls&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Video tutorial&lt;/td&gt;&lt;td&gt;Learn how to create a timeline design in RevenueCat Paywalls&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-paywall-experimentation-and-optimization&quot;&gt;&lt;strong&gt;Paywall experimentation and optimization&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Now you’re into the thick of it: you’ve got the paywall, but how do you make it a success? Here’s our best expert advice for optimizing paywall performance.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Link&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Format&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Includes&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/paywall-conversion-boosters/&quot;&gt;5 overlooked paywall improvements that drive more conversions&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Blog&lt;/td&gt;&lt;td&gt;Tried-and-tested paywall optimization tactics for better conversion&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://subclub.com/episode/a-systematic-approach-to-paywall-optimization-live-at-app-promotion-summit-nyc&quot;&gt;Sub Club: A Systematic Approach to Paywall Optimization&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Podcast &amp;amp; video&lt;/td&gt;&lt;td&gt;Ways to optimize paywalls and boost revenue through improved UX&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/paywall-placement/&quot;&gt;Optimizing paywall placement: The key to unlocking more app subscribers&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Blog&lt;/td&gt;&lt;td&gt;Best practices for paywall placement, and key metrics to track success&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.revenuecat.com/webinars/paywall-optimization-best-practices/&quot;&gt;Webinar: Paywall optimization best practices&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Webinar&lt;/td&gt;&lt;td&gt;How to optimize your freemium strategy, paywall design and copy&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://subclub.com/episode/how-headspace-optimized-revenue-by-gating-content-shreya-oswal-and-keya-patel-headspace&quot;&gt;Sub Club: How Headspace optimized revenue by gating content&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Podcast &amp;amp; video&lt;/td&gt;&lt;td&gt;Case study exploring Headspace’s success with their freemium model and referral program&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/paywall-tests-grow-app-revenue/&quot;&gt;8 paywall test ideas to grow app revenue&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Blog&lt;/td&gt;&lt;td&gt;⬅️ Does what it says on the tin. Test away!&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://subclub.com/episode/growing-to-1m-mrr-with-paywall-and-pricing-experiments-francescu-santoni-mojo&quot;&gt;Sub Club: Growing to $1M MRR with Paywall and Pricing Experiments&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Podcast &amp;amp; video&lt;/td&gt;&lt;td&gt;How Mojo drove MMR sky-high by iterating paywall messaging, design, and pricing&lt;br&gt;&lt;br&gt;&lt;strong&gt;&lt;em&gt;Note: &lt;/em&gt;&lt;/strong&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=wlNbb4veyfM&quot;&gt;&lt;em&gt;Watch as a video here&lt;/em&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/how-to-use-maxdiff-to-test-your-paywalls-value-proposition/&quot;&gt;The MaxDiff method: A smarter way to test paywall value propositions&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Blog&lt;/td&gt;&lt;td&gt;A deep dive on best–worst scaling features, ft. a case study from Dogo&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/offering-customization-examples-targeting/&quot;&gt;24 ways to optimize pricing, packaging, and paywalls for custom audiences using Targeting&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Blog&lt;/td&gt;&lt;td&gt;Practical suggestions to tailor your monetization with RevenueCat’s Targeting feature&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-inspiration-and-success-stories&quot;&gt;&lt;strong&gt;Inspiration and success stories&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Wrap up your reading on paywalls with a stack of real-life examples of paywalls in action. Get out your notebook, bookmark your favorites, and hit the ground running.&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Link&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Format&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Includes&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;http://www.paywalls.com&quot;&gt;Paywalls.com&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Gallery&lt;/td&gt;&lt;td&gt;Browse real paywall screens; filter by UI element, app category, trending and top-growth paywalls&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/how-top-apps-approach-paywalls/&quot;&gt;What the best subscription apps get right about paywalls&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Blog&lt;/td&gt;&lt;td&gt;20+ examples of real apps nailing paywalls, with tactics you can try right away&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/engineering/how-i-successfully-migrated-my-indie-app-to-revenuecat-paywalls/&quot;&gt;How I successfully migrated my indie app to RevenueCat Paywalls&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Blog&lt;/td&gt;&lt;td&gt;Developer Advocate, Charlie Chapman, shows how he transitioned his iOS app to RevenueCat and implemented a paywall&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.youtube.com/playlist?list=PLsFOrkX_y0B5hfAswerllv8GZVkC5LblX&quot;&gt;Roast my paywall: Live!&amp;nbsp;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Video playlist&lt;/td&gt;&lt;td&gt;Webinar series where experts dissect the paywalls of real apps— discover what works, and what doesn’t&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-revenuecat-tutorials-and-implementation&quot;&gt;&lt;strong&gt;RevenueCat tutorials and implementation&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Whether you’re building for iOS or Android, these tutorials from the RC product knowledge base have you covered.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Link&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Format&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Includes&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=mPzCTxIlMXE&quot;&gt;How to use RevenueCat paywalls&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Video tutorial&lt;/td&gt;&lt;td&gt;Three minutes, countless features: take a whirlwind tour of RevenueCat Paywalls&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/tools/paywalls&quot;&gt;Build a paywall: implementation docs for RevenueCat Paywalls&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Developer documentation&lt;/td&gt;&lt;td&gt;Get into the weeds of Paywalls with detailed, technical implementation documentation&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/engineering/build-paywalls-compose/&quot;&gt;Turn your app into revenue: Building paywalls in Android with Jetpack Compose&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Blog&lt;/td&gt;&lt;td&gt;Learn how to seamlessly implement in-app subscriptions and paywall features with Jetpack Compose&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/engineering/storekit-views-guide-paywall-swift-ui/&quot;&gt;How to use StoreKit views to build a subscription app paywall with SwiftUI&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Blog&lt;/td&gt;&lt;td&gt;Build native app paywalls with this guide to Apple’s StoreView, ProductView, and SubscriptionStoreView APIs&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/engineering/how-to-build-a-blinkist-style-paywall-using-revenuecat-webhooks-and-zapier/&quot;&gt;How to build a Blinkist-style paywall using RevenueCat webhooks and Zapier&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Blog&lt;/td&gt;&lt;td&gt;No backend code required. Here’s how to recreate Blinkist’s trusted timeline paywall&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/growth/introducing-web-paywall-buttons/&quot;&gt;Meet the web purchase links (why and where you should test it, today)&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Blog&lt;/td&gt;&lt;td&gt;Say hello to the web purchase link to send users out to web purchases straight from your iOS app paywall&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-so-what-s-next&quot;&gt;So, what’s next?&lt;/h2&gt;



&lt;p&gt;How to build a paywall? ✅&lt;br&gt;How to choose the right kind of paywall? ✅&amp;nbsp;&lt;br&gt;How to optimize for success? ✅&lt;br&gt;How to implement RevenueCat paywalls to make all of the above easier? Also ✅&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Your paywall is one of the most important growth levers in your subscription app. The best teams don’t treat it as static; they test, experiment, and optimize relentlessly.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;With &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps-2025/&quot;&gt;82% of trials starting the same day a user installs an app&lt;/a&gt;, most apps don’t get a second chance at conversion. Every screen and every word counts.&lt;/p&gt;



&lt;p&gt;So whether you’re starting day one of building a new app, or trying to surpass $1M ARR, your next steps are simple:&amp;nbsp;&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Pick one experiment to pursue: &lt;/strong&gt;Test a new design, try shifting the placement of your paywall, or adjusting the trial period. Whatever you do, start small, move fast, and keep evolving.&amp;nbsp;&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Benchmark your metrics&lt;/strong&gt;: Not sure how to define success? Check how your app stacks up against industry data using the &lt;a href=&quot;https://www.revenuecat.com/healthscore/&quot;&gt;RevenueCat app health score&lt;/a&gt;.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Keep iterating: &lt;/strong&gt;Every change is a step forward (even when experiments don’t work out!). If something’s not working? Change it.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Now go forth, and start paywalling*. Good luck!&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;



&lt;p&gt;&lt;em&gt;*Not a real word, but we’re trying to make it a thing&lt;/em&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Mark your models as stable with the Compose runtime annotation library]]></title><description><![CDATA[In this article, we’ll look at how to address this issue using the new compose-runtime-annotation library.]]></description><link>https://www.revenuecat.com/blog/engineering/compose-runtime-annotation/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/compose-runtime-annotation/</guid><pubDate>Tue, 16 Sep 2025 23:46:56 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Compose-Runtime-Annotation.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;In Jetpack Compose, understanding stability is pretty important because it directly affects recomposition and overall UI performance. There are several strategies for making composable functions stable, and one of the most common is marking your classes with the stability annotations &lt;code&gt;@Immutable&lt;/code&gt; and &lt;code&gt;@Stable&lt;/code&gt;.&lt;/p&gt;



&lt;p&gt;However, there’s a catch: even if your model class is entirely composed of immutable properties, it will still be marked as unstable if it comes from a different package. This becomes especially problematic when building libraries, SDKs, or apps with a multi-module architecture, since all classes from external packages are treated as unstable, something you can’t control from the call site.&lt;/p&gt;



&lt;p&gt;In this article, we’ll look at how to address this issue using the new &lt;code&gt;compose-runtime-annotation&lt;/code&gt; library, with a real-world example of how the &lt;a href=&quot;https://github.com/RevenueCat/purchases-android&quot;&gt;RevenueCat’s Android SDK&lt;/a&gt; solved it in practice.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-stability-problem&quot;&gt;The stability problem&lt;/h2&gt;



&lt;p&gt;In Jetpack Compose, recomposition is triggered when state changes or new parameters are passed into a composable. The key factor the runtime uses to decide whether two objects are equivalent is &lt;strong&gt;stability&lt;/strong&gt;. Thanks to smart stability checks, even if state or parameters change, Compose can skip recomposition when it determines the objects are stable.&lt;/p&gt;



&lt;p&gt;However, even if you intend for a class to be stable, it will ultimately be considered unstable if it contains any unstable types. For example, consider the following model class, which might typically come from a network response:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1ccHJl wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;data class User(\n  val id: String,\n  val name: String,\n  val profiles: List&lt;String&gt;,\n)&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Since interface types are treated as unstable, the User class above ends up unstable because the profiles property is a List. In cases like this, you can explicitly mark the class with &lt;code&gt;@Immutable&lt;/code&gt; or &lt;code&gt;@Stable&lt;/code&gt; to inform the Compose compiler: &lt;em&gt;“I know this class is immutable, so please treat it as stable.”&lt;/em&gt;&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1ln1UN wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Immutable\ndata class User(\n  val id: String,\n  val name: String,\n  val profiles: List&lt;String&gt;,\n)&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;On the other hand, if your class contains only stable types, like in the example below, the Compose compiler will consider it stable by default:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZriLF5 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;data class User(\n  val id: String,\n  val name: String,\n  val address: String,\n)\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The problem, however, is that even if a class contains only stable types, it will still be treated as unstable if it originates from another package. For example, if the User class above comes from an open-source library, an SDK, or even another module in a multi-module architecture, the compiler will still consider it unstable.&lt;/p&gt;



&lt;p&gt;You could technically resolve this issue by adding the compose-runtime library and annotating those classes with stability annotations. However, it’s generally not a good idea to introduce a dependency on Compose in modules that are completely unrelated, such as a module containing only plain POJO models.&lt;/p&gt;



&lt;p&gt;Even if you add compose-runtime to other modules/libraries/SDKs, those modules then gain access to Compose runtime features like &lt;code&gt;SideEffect&lt;/code&gt;, &lt;code&gt;LaunchedEffect&lt;/code&gt;, &lt;code&gt;snapshotFlow&lt;/code&gt;, &lt;code&gt;StateFlow&amp;lt;T&amp;gt;.collectAsState()&lt;/code&gt;, and many more. These APIs will start appearing in your IDE’s autocomplete, which increases the risk of accidental or improper usage in places they don’t belong.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;compose-runtime-annotation-library&quot;&gt;Compose runtime annotation library&lt;/h2&gt;



&lt;p&gt;The idea, then, is: what if we could use “only” the stability annotations in our Compose-unrelated modules, such as pure JVM or core modules?&lt;/p&gt;



&lt;p&gt;To address this, the Jetpack Compose team recently released the &lt;code&gt;compose-runtime-annotation&lt;/code&gt; library, which contains only the stability annotations. It is designed for Kotlin Multiplatform (JVM, Android, iOS, etc.) and is available under the following package:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1eizo wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;compileOnly(\&amp;quot;androidx.compose.runtime:runtime-annotation:1.9.0\&amp;quot;)&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;And now, you’ll be able to import only the stability-related annotations, such as &lt;code&gt;@Immutable&lt;/code&gt;, &lt;code&gt;@Stable&lt;/code&gt;, and &lt;code&gt;@StableMarker&lt;/code&gt;, and mark your classes as stable with those annotations.&lt;/p&gt;



&lt;p&gt;The reason you can use &lt;code&gt;compileOnly&lt;/code&gt; instead of the &lt;code&gt;implementation&lt;/code&gt; method in the Gradle file is that the only requirement is to let the Compose compiler know your classes are stable. These annotations are only utilized at compile time rather than at runtime.&lt;/p&gt;



&lt;p&gt;One great real-world example is &lt;a href=&quot;https://github.com/RevenueCat/purchases-android&quot;&gt;RevenueCat’s Android SDK&lt;/a&gt;. It recently &lt;a href=&quot;https://github.com/RevenueCat/purchases-android/pull/2608&quot;&gt;adopted the compose-runtime-annotation library&lt;/a&gt; to mark classes in its core module as stable, improving overall UI performance. You can check out the PR to see how the library was introduced and applied.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;compose-stable-marker-library&quot;&gt;Compose stable marker library&lt;/h2&gt;



&lt;p&gt;Before the &lt;code&gt;compose-runtime-annotation&lt;/code&gt; library was released, there was the original &lt;a href=&quot;https://github.com/skydoves/compose-stable-marker&quot;&gt;Compose Stable Marker&lt;/a&gt; library, introduced about two years earlier, which behaves very similarly.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1G3Aor wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;compileOnly(\&amp;quot;com.github.skydoves:compose-stable-marker:1.0.2\&amp;quot;)&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Now that the official library is available, it’s generally best to use it, but there’s one caveat to keep in mind. The c&lt;code&gt;ompose-runtime-annotation&lt;/code&gt; library requires a &lt;code&gt;compileSdkVersion&lt;/code&gt; of at least 34. While the library itself supports older devices (the min SDK is down to API 21), building and verifying it correctly requires modern build tools (compile SDK 34 or higher).&lt;/p&gt;



&lt;p&gt;Most projects today are already targeting &lt;code&gt;compileSdkVersion&lt;/code&gt; 34 or higher, especially since &lt;a href=&quot;https://support.google.com/googleplay/android-developer/answer/11926878?hl=en&quot;&gt;Google Play is pushing developers to migrate to target SDK 35&lt;/a&gt;, but if you’re building libraries or SDKs that are still stuck below compile SDK 34, Compose Stable Marker remains a valid alternative.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;boosting-the-stability&quot;&gt;Boosting the stability&lt;/h2&gt;



&lt;p&gt;If you’re building an application consisting of several modules, there are two more ways to boost your Compose UI stabilities.&lt;/p&gt;



&lt;p&gt;1. &lt;a href=&quot;https://developer.android.com/develop/ui/compose/performance/stability/fix?utm_source=chatgpt.com#configuration-file&quot;&gt;Stability configuration file&lt;/a&gt;: Starting with Compose Compiler 1.5.5, you can provide a configuration file at compile time to mark specific classes as stable. This makes it possible to treat classes you don’t control, such as standard library types like &lt;code&gt;LocalDateTime&lt;/code&gt;, as stable.&lt;br&gt;2. &lt;a href=&quot;https://developer.android.com/develop/ui/compose/performance/stability/strongskipping?utm_source=chatgpt.com&quot;&gt;Strong skipping mode&lt;/a&gt;: When enabled, strong skipping makes all restartable composable functions skippable, even if they have unstable parameters. Non-restartable composable functions, however, remain unskippable. This is enabled by default in Kotlin 2.0.20.&lt;/p&gt;



&lt;p&gt;By using this, you may not always need stability annotations. However, if you’re building libraries or SDKs, you can’t assume that your users will handle every stability issue correctly. It’s still better to mark your classes as stable and provide explicit stability guarantees to ensure better performance.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;



&lt;p&gt;In this article, you explored why stability matters, the challenges of stability across different packages, and how to address these issues using the &lt;code&gt;compose-runtime-annotation &lt;/code&gt;and Compose Stable Marker libraries. With Strong Skipping mode and stability configuration files, it has become easier to make classes stable, but if you’re delivering libraries or SDKs, explicitly ensuring stability remains essential for achieving better performance.&lt;/p&gt;



&lt;p&gt;As always, happy coding!&lt;/p&gt;



&lt;p&gt;—&amp;nbsp;&lt;a href=&quot;https://github.com/skydoves&quot;&gt;Jaewoong&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[7 smart ways to monetize low-intent users]]></title><description><![CDATA[Practical strategies to turn an overlooked segment into meaningful revenue]]></description><link>https://www.revenuecat.com/blog/growth/revenue-strategies-low-intent-users/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/revenue-strategies-low-intent-users/</guid><pubDate>Tue, 16 Sep 2025 09:47:07 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/1.-How-to-monetize-low-intent-app-users-1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Not every user is going to convert to a recurring yearly subscriber, but that doesn’t mean they’re not worth having as a customer at all.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;It’s a spectrum:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;People who install the app, tap around for a minute or two, maybe come back once or twice, then churn&lt;/li&gt;



&lt;li&gt;High-frequency free users: people who never pay, but return regularly, sometimes for months or even years&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Both groups have low intention to subscribe, but they require very different strategies. And for some apps, &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps-2025/&quot;&gt;this group can make up 90% or more of total installs&lt;/a&gt;.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;It’s tempting to dismiss these users, but doing so means leaving revenue on the table. Let’s explore how to identify, engage, and derive value from these users — without resorting to aggressive tactics or compromising user trust.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-to-identify-low-intent-users-and-understand-what-s-holding-them-back&quot;&gt;&lt;strong&gt;How to identify low-intent users (and understand what’s holding them back)&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;But before you can engage and monetize these segments, you need to identify the right low-intent users to target.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Since &lt;a href=&quot;https://revx.io/best-practices-user-acquisition-retention-subscription-apps/&quot;&gt;80% of mobile subscriptions happen during onboarding&lt;/a&gt; (or the first session), we can already consider anyone who passes the onboarding paywall — without starting a trial or converting to subscription — as low-intent.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;You can also look for users who have:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;No account creation&lt;/li&gt;



&lt;li&gt;No core feature activation (e.g. no photo edits, no search, no first meditation)&lt;/li&gt;



&lt;li&gt;Long inactivity gaps&lt;/li&gt;



&lt;li&gt;Low interaction (e.g. scrolls without taps)&lt;/li&gt;



&lt;li&gt;Interact with low-converting features&lt;/li&gt;



&lt;li&gt;Have surpassed your app’s average-time-to-subscribe&lt;/li&gt;



&lt;li&gt;Have retained for more than 30 days, but on the free plan&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;First, think about &lt;em&gt;why&lt;/em&gt; these users remain in the low-intent bucket. Is it because &lt;strong&gt;the free experience already solves their core problem&lt;/strong&gt;, leaving them with no real incentive to upgrade? Consider whether &lt;strong&gt;they still bring value to your platform in other ways&lt;/strong&gt;, such as referring new users or contributing to a network effect.&lt;/p&gt;



&lt;p&gt;If it’s the latter, it may be worth exploring a &lt;a href=&quot;https://www.revenuecat.com/blog/growth/2025-app-monetization-trends/#h-trend-3-the-hybrid-monetization-boom&quot;&gt;hybrid monetization model&lt;/a&gt;. This could mean introducing ads or offering in-app purchases for one-off features or premium tools. Apps like MyFitnessPal and Duolingo have successfully used hybrid approaches to generate revenue from long-term free users.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;If it’s the former (users who get significant value from the free experience), consider adding light, well-timed friction that creates monetizable moments, without requiring a subscription. This might include one-time unlocks (e.g. exporting a file, accessing a detailed report), time-based passes, or even ad-supported flows at key points in the journey. The aim is to preserve the utility and trust of the free experience while introducing pathways to derive revenue from high-intent actions.&lt;/p&gt;



&lt;p&gt;Be sure to analyze the specific use cases of your low-intent users and compare them to those of your high-converting segment. In some categories, like dating apps, the majority of revenue may come disproportionately from one user group (for example, male users). This kind of imbalance can highlight opportunities to evolve your product experience and create more perceived value for other segments who currently see less benefit in paying.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-smart-ways-to-unlock-value-from-low-intent-users&quot;&gt;&lt;strong&gt;Smart ways to unlock value from low intent users&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Now you know who to target, here are seven strategies to appeal to low-intent users.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-one-time-unlocks-simple-value-no-strings-attached&quot;&gt;&lt;strong&gt;1. One-time unlocks: simple value, no strings attached&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;One of the simplest and most transparent ways to monetize low-intent users is through one-time feature unlocks. Rather than gating the entire product experience behind a recurring subscription, you can offer access to specific features or tools for a fixed price.&lt;/p&gt;



&lt;p&gt;This strategy works especially well for creative and utility apps where users may need just one or two functions. For example, a photo editing app might offer an AI background remover as a $2.99 add-on, while keeping basic editing tools free.&lt;/p&gt;



&lt;p&gt;Toca Boca, a suite of children’s creativity apps, uses this model effectively by allowing parents to purchase individual themed apps or bundles. Weather on the Way, a mobile app for forecasting weather along a travel route, charges a one-time fee for lifetime access.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;473&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-12-1024x473.png&quot; alt=&quot;&quot; class=&quot;wp-image-46084&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-12-1024x473.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-12-300x139.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-12-768x355.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-12-1536x709.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-12-50x23.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-12-87x40.png 87w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-12-696x321.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-12-560x259.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-12-840x388.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-12-80x37.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-12-48x22.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-12.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;An in-app purchase in Toca Boca that allows parents to unlock the “Mansion Pack,” adding extra content and features to the game.&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;Heavily gamified and community-based apps often monetize through virtual currency or tokens. Instead of unlocking features directly, users buy credits and then spend them within the app to perform certain actions, like sending a message, unlocking a new lesson, or boosting visibility.&lt;/p&gt;



&lt;p&gt;This model is often used in dating, language learning, and social platforms. For example, apps like Hinge and Tinder sell ‘Super Likes’ or ‘Boosts’ to increase match visibility. Language apps like Tandem allow users to pay for corrections or translations via credits.Many users appreciate the clarity and predictability of this kind of pricing, especially for apps they only use occasionally. By allowing users to pay only when they see value, the experience feels user-friendly and more trustworthy.These &lt;strong&gt;one-time purchases give users a sense of ownership&lt;/strong&gt;, &lt;strong&gt;reduce friction around commitment&lt;/strong&gt;, and can even &lt;strong&gt;serve as a lead-in to future subscription&lt;/strong&gt; offers.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;2-turn-hesitation-into-action-with-short-term-plans&quot;&gt;&lt;strong&gt;2. Turn hesitation into action with short-term plans&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;While annual and monthly subscriptions are the industry standard, they may not be the right entry point for low-intent users. &lt;a href=&quot;https://www.revenuecat.com/blog/growth/weekly-subscriptions/&quot;&gt;A weekly plan introduces a lower-stakes option&lt;/a&gt; that’s easier to say yes to, especially for users who are curious, but not yet convinced.&lt;/p&gt;



&lt;p&gt;This approach is ideal for apps with short-term use cases or seasonal spikes in engagement. A traveler using a weather or translation app for a week-long trip might be perfectly willing to pay $2.99 for a week of premium access, even if they have no interest in an ongoing subscription.&lt;/p&gt;



&lt;p&gt;If you’re considering testing a weekly plan, start with a segmented A/B test targeting non-converting users during onboarding or at key friction points. Monitor conversion rates, refund behavior, churn, and payback periods carefully. Weekly subscriptions can become a ‘revenue trap’ if they cannibalize longer-term subscriptions or lead to refund abuse.&lt;/p&gt;



&lt;p&gt;Done thoughtfully, however, weekly plans can bridge the gap between free and full commitment, and provide a much-needed monetization path for hesitant users.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;473&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-13-473x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-46086&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-13-473x1024.png 473w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-13-139x300.png 139w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-13-709x1536.png 709w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-13-23x50.png 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-13-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-13-214x464.png 214w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-13-696x1507.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-13-259x560.png 259w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-13-137x296.png 137w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-13-218x472.png 218w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-13-37x80.png 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-13-22x48.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-13.png 739w&quot; sizes=&quot;auto, (max-width: 473px) 100vw, 473px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Plant identifier app, PlantIn, offers a weekly subscription as an alternative to a one-off ‘Lifetime’ option.&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;3-let-users-experience-value-before-paying&quot;&gt;&lt;strong&gt;3. Let users experience value before paying&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Instead of offering a full subscription trial up front, some apps use reverse trials to let users explore a single feature or flow, and then invite them to pay to continue. Think of it as letting the user dip a toe in before diving in.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Lovable lets users &lt;a href=&quot;https://docs.lovable.dev/introduction/plans-and-credit-limits&quot;&gt;utilize daily free credits&lt;/a&gt; to build an app or website powered by AI, but once those credits are used, they prompt users to pay for continued access. Quizlet &lt;a href=&quot;https://help.quizlet.com/hc/en-us/articles/360030642972-Studying-with-Test&quot;&gt;offers access to Test Mode briefly&lt;/a&gt; before gating it with a premium offer.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;This model is particularly effective for users who may be skeptical of trials or unwilling to commit to recurring billing upfront. It aligns the paywall with a moment of value, increasing the likelihood of conversion without increasing perceived risk. And even if users don’t convert immediately, this approach can be used to collect valuable feedback or reviews that inform your roadmap and strengthen long-term retention.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;473&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-15-473x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-46090&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-15-473x1024.png 473w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-15-139x300.png 139w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-15-709x1536.png 709w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-15-23x50.png 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-15-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-15-214x464.png 214w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-15-696x1507.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-15-259x560.png 259w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-15-137x296.png 137w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-15-218x472.png 218w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-15-37x80.png 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-15-22x48.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-15.png 739w&quot; sizes=&quot;auto, (max-width: 473px) 100vw, 473px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Quizlet offers access to Test Mode briefly before gating it with a premium offer.&lt;/em&gt;&amp;nbsp;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;4-turn-attention-into-revenue-without-losing-trust&quot;&gt;&lt;strong&gt;4. Turn attention into revenue without losing trust&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Advertising often gets a bad reputation in mobile apps, but it doesn’t have to. With the right placement and pacing, Ads can deliver incremental revenue without compromising the user experience.&lt;/p&gt;



&lt;p&gt;Some products, like YouTube, monetize their free tier with skippable video ads. Users can choose to watch the full ad or wait a few seconds to skip, maintaining a sense of control. Spotify takes a similar approach, weaving ads naturally into the listening experience while gently nudging users toward its premium plan.&lt;/p&gt;



&lt;p&gt;The lesson here is: &lt;strong&gt;don’t fear ads, frame them.&lt;/strong&gt; Whether it’s rewarded videos in games, story-integrated audio ads, or Meta’s new ‘pay or see ads’ approach, the smartest apps are &lt;strong&gt;making advertising feel like a choice, not a disruption&lt;/strong&gt;. That’s how you drive revenue without alienating your free users.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;5-tips-welcome-a-kinder-monetization-model&quot;&gt;&lt;strong&gt;5. Tips welcome: a kinder monetization model&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;In creator-led or community-driven apps, some of your most loyal free users may be more than willing to contribute voluntarily, especially if they’ve come to value your content or mission over time.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Products like Wikipedia have popularized this approach with ‘supporter plans’ that allow users to tip or donate without unlocking any additional features. Platforms like Buy Me a Coffee or Patreon are often integrated for this purpose, particularly in smaller apps.&lt;/p&gt;



&lt;p&gt;This model isn’t about scale, it’s about affinity and mission. If your &lt;a href=&quot;https://www.revenuecat.com/blog/growth/solve-app-problems-emotionally/&quot;&gt;app builds a strong emotional connection&lt;/a&gt; with a niche audience, offering them a way to support you can drive steady contributions over time. It’s a quiet but powerful way to monetize without paywalls.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;576&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-14-1024x576.png&quot; alt=&quot;&quot; class=&quot;wp-image-46088&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-14-1024x576.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-14-300x169.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-14-768x432.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-14-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-14-71x40.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-14-696x392.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-14-560x315.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-14-526x296.png 526w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-14-840x472.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-14-80x45.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-14-48x27.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-14.png 1280w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Wikipedia routinely asks users to tip or donate in order to keep their service free and an independent source of information.&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;6-let-usage-build-the-case-for-upgrading&quot;&gt;&lt;strong&gt;6. Let usage build the case for upgrading&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;For many utility, productivity, and health apps, users can experience the full flow of a feature, but only up to a point. These apps provide generous access to the basics, but place subtle, meaningful limits on things like historical data (e.g. Slack), saved progress or long-term storage. This model respects free users’ need to get value early on, while creating natural breakpoints where upgrading starts to make sense.&lt;/p&gt;



&lt;p&gt;Notion is a good example. The app’s free tier includes access to virtually all core functionality; note-taking, file upload, database automations. But restricts advanced features like version history, private team spaces and workspace analytics. These restrictions are invisible at first, but as usage deepens — and you build the tool into your habits — they become more apparent. It’s a classic case of “free for now, but not forever”, and it works because users don’t feel pushed into upgrading &lt;em&gt;before&lt;/em&gt; the product becomes a key part of their toolstack.&lt;/p&gt;



&lt;p&gt;This kind of delayed restriction (data, storage, or accumulated progress) is particularly effective because &lt;strong&gt;it monetizes based on retained value, not initial access.&lt;/strong&gt; Users aren’t blocked from forming a habit, which often increases their likelihood of paying later. It’s a strategy that aligns well with long-term engagement: the more they use the app, the more valuable their data becomes — and the more motivated they are to unlock its full potential.&lt;/p&gt;



&lt;p&gt;Importantly, this tactic avoids the sharp friction of an upfront paywall. Instead of saying “you can’t use this,” it says “you &lt;em&gt;can&lt;/em&gt; use this, until you care enough to want more.” For low-intent users who do engage regularly but haven’t converted, this gentle escalation can be the nudge that finally tips them over the edge.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;7-the-friend-of-a-friend-revenue-model&quot;&gt;&lt;strong&gt;7. The friend-of-a-friend revenue model&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Sometimes, the most valuable thing a user can do isn’t converting, but referring to someone (or multiple people) who will.&lt;/p&gt;



&lt;p&gt;Low-intent users might not be ready to pay for your app, but that doesn’t mean they’re disengaged or unmotivated. Many are still willing to share an app they like. Especially if it helps others solve a problem, or if there’s a personal incentive in it for them. That’s where referral programs come in: they shift the value proposition away from individual monetization to focus on network-driven growth.&lt;/p&gt;



&lt;p&gt;In freemium apps, referrals can serve as a monetization multiplier. A free user may never spend a cent, but if they bring in three friends and one or two of those friends becomes a long-term subscriber, the original user has created meaningful downstream value. With the right tracking and attribution in place, you can design your referral program to reward the right behaviors. Not just installs, but quality referrals that lead to actual revenue.&lt;/p&gt;



&lt;p&gt;This works particularly well when referrals are:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Easy to share (e.g. built-in sharing via SMS, Whatsapp, Facebook)&lt;/li&gt;



&lt;li&gt;Aligned with user timing (after a successful session or helpful feature use)&lt;/li&gt;



&lt;li&gt;Incentivized fairly (e.g. “Get a free month when your friend subscribes”)&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Apps like &lt;a href=&quot;https://viral-loops.com/blog/dropbox-grew-3900-simple-referral-program/&quot;&gt;Dropbox&lt;/a&gt; and &lt;a href=&quot;https://referral-factory.com/learn/referral-program-saas&quot;&gt;Airtable&lt;/a&gt; built early growth through well-timed referral loops. Even Spotify &lt;a href=&quot;https://www.osiaffiliate.com/marketing/spotify-referral-program/&quot;&gt;has experimented with referral campaigns&lt;/a&gt; to accelerate premium growth among its free user base.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Gaming and language learning apps often reward both referrer and recipient with bonus time, credits, or extended trial access. For example, self-care app Finch gamifies offers exclusive in-game rewards you can only access through referrals. Most importantly, you only receive the reward when your referral successfully finishes onboarding — creating a loop of engaged users prompting new users to go back to the app again and again.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;473&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-16-473x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-46092&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-16-473x1024.png 473w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-16-139x300.png 139w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-16-709x1536.png 709w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-16-23x50.png 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-16-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-16-214x464.png 214w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-16-696x1507.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-16-259x560.png 259w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-16-137x296.png 137w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-16-218x472.png 218w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-16-37x80.png 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-16-22x48.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-16.png 739w&quot; sizes=&quot;auto, (max-width: 473px) 100vw, 473px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;The Finch app unlocks numerous rewards that scale as you invite more friends.&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;For low-intent users, a good referral program becomes a low-friction way to participate in the app’s success, without needing to pay directly. And for you, it’s an efficient way to acquire high-quality users who are more likely to convert, since they’re joining based on a trusted friend’s recommendation.&lt;/p&gt;



&lt;p&gt;Just remember: to make referral loops work, they need to feel organic. Don’t force it into your onboarding flow. Instead, surface it contextually. For example, after a successful feature use, during lifecycle emails, or when a user completes a milestone. This helps your low-intent users become advocates, not just participants — and gives them a meaningful role in your monetization strategy.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;473&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-17-473x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-46094&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-17-473x1024.png 473w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-17-139x300.png 139w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-17-709x1536.png 709w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-17-23x50.png 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-17-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-17-214x464.png 214w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-17-696x1507.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-17-259x560.png 259w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-17-137x296.png 137w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-17-218x472.png 218w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-17-37x80.png 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-17-22x48.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-17.png 739w&quot; sizes=&quot;auto, (max-width: 473px) 100vw, 473px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;ClassPass has a referral program embedded into its Home Screen experience.&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;low-intent-low-value&quot;&gt;&lt;strong&gt;Low-intent ≠ low value&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The subscription economy has matured, and so have user expectations. Not everyone will convert to a yearly plan, but that doesn’t mean you should leave them behind. Low-intent users often outnumber high-intent ones, and when engaged with care and creativity, they can become a significant source of revenue, referrals, and retention improvements.&lt;/p&gt;



&lt;p&gt;What this really comes down to is rethinking the binary of subscriber vs. churn. There’s a vast middle ground of users who aren’t ready to commit to a subscription, but who &lt;em&gt;will&lt;/em&gt; engage and pay in other ways if you meet them where they are.Combine smart segmentation with revenue tactics like one-time unlocks and re-trials, or ads, donations, and lightweight plans; there’s no shortage of monetization paths. Just remember to align your tactics with user intent and trust — don’t trade short-term gain for long-term loyalty&lt;em&gt;.&lt;/em&gt;&lt;strong&gt;The most successful apps design monetization with empathy, segmentation, and experimentation baked in.&lt;/strong&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[The creative volume trap in Meta ads]]></title><description><![CDATA[Why more Meta ads won't win you better results (and what to do instead)]]></description><link>https://www.revenuecat.com/blog/growth/creative-volume-meta-ad/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/creative-volume-meta-ad/</guid><pubDate>Fri, 12 Sep 2025 13:20:57 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Blog-cover.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Warning, this is perhaps slightly controversial for creative volume advocates: I’m about to go to war with Meta ads! The irony is that I run an agency producing an ungodly number of ad creatives for our clients.&lt;/p&gt;



&lt;p&gt;Just over six months back I spoke to an app founder who pushes 500 new ad creatives on Meta every single day. That’s ~15,000 ads tested per month!&lt;/p&gt;



&lt;p&gt;Since that day, I’ve spoken to dozens upon dozens of app founders, UA Managers and Heads of Performance who have all taken the same stance: “In order to take our Meta account to the next level, we need to test more ad creatives”.&lt;/p&gt;



&lt;p&gt;But I disagree. More volume isn’t always the answer.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-volume-is-overrated&quot;&gt;&lt;strong&gt;Volume is overrated&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;In short, a lot of teams are putting creative volume above everything else when it comes to Meta — at times setting a metric like &lt;em&gt;# of ads tested per month&lt;/em&gt; as the primary measure of input. But this is a slippery slope. Not only are there some harmful, unintended consequences to be aware of, but strategically this can position the entire team to sprint off in the wrong direction.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;The goal of creative testing is to find new winners.&lt;/strong&gt; It’s not about hitting an arbitrary number of creatives tested. We want to find ad creatives that enable us to scale spend, improve performance metrics and unlock new audiences in our ad accounts. Pumping out as many creatives as humanly possible isn’t the best way to go about that.&lt;/p&gt;



&lt;p&gt;Now I know what you’re thinking:&amp;nbsp;&lt;/p&gt;



&lt;p&gt;“But Nathan! The more creatives we test, the higher likelihood we’ll find new winners. And the faster we test, the faster we’ll find new winners.”&lt;/p&gt;



&lt;p&gt;Hmm.&lt;/p&gt;



&lt;p&gt;I get where that line of thinking comes from, and in theory… I agree. If all other variables remain constant this would be true 100% of the time. But in practice, these variables hardly ever remain constant, and when they do, there’s a ceiling to hit and negative returns to follow. Like so ⤵️&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;511&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Diminishing-returns-chart-1024x511.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-46170&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Diminishing-returns-chart-1024x511.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Diminishing-returns-chart-300x150.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Diminishing-returns-chart-768x383.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Diminishing-returns-chart-1536x766.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Diminishing-returns-chart-50x25.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Diminishing-returns-chart-80x40.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Diminishing-returns-chart-696x347.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Diminishing-returns-chart-560x279.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Diminishing-returns-chart-840x419.jpg 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Diminishing-returns-chart-48x24.jpg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Diminishing-returns-chart.jpg 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-volume-game-is-actually-a-trap&quot;&gt;&lt;strong&gt;The volume game is actually a trap&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Still with me? Okay, let’s dig into &lt;em&gt;why &lt;/em&gt;creative volume doesn’t = better.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-decreased-creative-diversity&quot;&gt;&lt;strong&gt;Decreased creative diversity&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;When sheer volume becomes the headline KPI, the quality of creative tests tends to drop. Every creative team naturally bends toward churning out ever-smaller tweaks. Five-pixel colour shifts, copy changes that barely register, trivial format flips — just to hit targets. Having to hit a high number of creatives&lt;strong&gt; makes you ration creativity.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;At that point, you’re not testing hypotheses or uncovering genuinely fresh insights; you’re playing a numbers game that makes big swings a thing of the past, scatters your learnings across a flood of low-impact variants, and ultimately erodes your chances of finding new winners.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-quick-case-study&quot;&gt;&lt;strong&gt;Quick case study&lt;/strong&gt;&lt;/h4&gt;



&lt;p&gt;We recently onboarded a new client at Perceptycs who ran into this exact problem with a previous creative agency: the agency was commissioned to deliver a certain number of creatives each month. At first, things were great. New concepts, some nice iterations and a healthy win rate. But overtime, the win rate started to decrease and the new concepts weren’t taking off like they used to. Why?&lt;/p&gt;



&lt;p&gt;The creative agency started delivering more and more iterations of historical winners, and fewer &lt;em&gt;new&lt;/em&gt; concepts. &lt;strong&gt;They started playing it safe.&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;At first, performance improved. Happy days. The iterations extended the life of winning concepts, the win rate &lt;em&gt;technically&lt;/em&gt; went up. Things looked healthy again. Until they didn’t. Inevitably, the concepts fatigued and no amount of iterating could bolster performance. The client was forced to scale back — now we’re helping them rebuild the right way.&lt;/p&gt;



&lt;p&gt;Honestly, it’s pretty easy to avoid something like that happening:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Cap the number of variants&lt;/li&gt;



&lt;li&gt;Add a quota for iterations of winners&lt;/li&gt;



&lt;li&gt;Ensure a high percentage of testing budget is pushed to new concepts&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Bear in mind: if &lt;em&gt;volume&lt;/em&gt; is still the focus, these measures will just open the door to even bigger problems…&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-creative-burnout&quot;&gt;&lt;strong&gt;Creative burnout&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Creative teams, whether in-house or agency side, don’t resort to banking on iterations because they’re lazy. At least not in most cases (I hope!). Often it’s because of creative burnout. Over time, not only does it become harder to come up with fresh creative concepts, angles, and formats, but teams have to do so at an increasing rate.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Sooner or later, win rate will start to drop, performance will get shaky, and that’s when the wheels come off. Finding genuine new winners becomes like drawing blood from a stone. Then:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Teams get demotivated&lt;/li&gt;



&lt;li&gt;Downward pressure increases as performance drops&lt;/li&gt;



&lt;li&gt;Everyone is back to playing it safe&lt;/li&gt;



&lt;li&gt;Everyone is burnt out&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Quotas or no quotas, when metrics are in the red month after month, most folk will take iterations over new concepts if it means stronger performance.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Circular-flow-chart-1024x1024.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-46173&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Circular-flow-chart-1024x1024.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Circular-flow-chart-300x300.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Circular-flow-chart-150x150.jpg 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Circular-flow-chart-768x768.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Circular-flow-chart-1536x1536.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Circular-flow-chart-50x50.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Circular-flow-chart-40x40.jpg 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Circular-flow-chart-464x464.jpg 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Circular-flow-chart-696x696.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Circular-flow-chart-560x560.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Circular-flow-chart-296x296.jpg 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Circular-flow-chart-472x472.jpg 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Circular-flow-chart-80x80.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Circular-flow-chart-48x48.jpg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Circular-flow-chart.jpg 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-poorer-experimentation-rigour&quot;&gt;&lt;strong&gt;Poorer experimentation rigour&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Perhaps one of the most harmful side effects of a volume-first approach to creative testing is the collapse of structured experimentation methodology.&lt;br&gt;&lt;br&gt;By this I mean:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Hypotheses development takes a back seat:&lt;/strong&gt; “There’s no time to waste” becomes, “how many corners can we cut and still push out enough ads?”. That means teams rush straight into creative production without first articulating clear, testable hypotheses — and end up tinkering, not learning.&lt;br&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Impact vs. effort prioritisation starts to erode:&lt;/strong&gt; It would be a flat out lie to say that high effort always equates to high impact. Often we see simple, ugly creatives that took minutes to produce outperform Spielberg-esque creatives. But when that’s the case, there’s now a performance justification for quick and easy. All of a sudden, we prioritise based on production speed as opposed to likelihood-to-succeed. Long-term, this just doesn’t work. &lt;strong&gt;We need creative diversity,&lt;/strong&gt; which means a mix of high-production and low-production creatives.&lt;br&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Corners are cut when it comes to post-test analysis:&lt;/strong&gt; When you’re staring at 200+ ad creatives, each with 20+ data points, and you have another 200 briefs to create this week… Trust me, you’re not feeling great about the task ahead! And that means more corners are cut. Placement analysis? Maybe next time. All of a sudden, you’re missing out on key insights, ignoring crucial learnings, and creative testing has become a matter of throwing stuff at the wall and seeing what sticks.&lt;/li&gt;
&lt;/ol&gt;



&lt;ol start=&quot;4&quot; class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Experiment documentation gets overlooked:&lt;/strong&gt; Let’s not forget the impact on your processes and documentation. You can forget keeping logs or writing up experiment docs. When there’s no capacity for testing, there’s no point in keeping documentation updated. “No one even looks at those anyway.”&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Maybe these things seem small. But when you’re scaling an account from five to six to seven figures in ad spend, you need some degree of structure and systematic process to consistently see success.&lt;/p&gt;



&lt;p&gt;Now. Am I saying that it’s impossible to run a high volume of creative tests and maintain a rigorous approach to experimentation?&lt;br&gt;&lt;br&gt;Of course not! But it’s a lot harder than if you adjust your volume.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-ad-account-chaos&quot;&gt;&lt;strong&gt;Ad account chaos&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;This is where the fun begins!&lt;/p&gt;



&lt;p&gt;Have you ever pushed 100+ creatives live in a single day?&lt;/p&gt;



&lt;p&gt;Scratch that. Have you ever tried structuring 300+ creatives per week, consistently, across different formats, concepts, angles, creators and languages for an iOS 14+ app where you have a limit of 18 campaigns each with five ad sets. Well?&lt;/p&gt;



&lt;p&gt;Trust me. It’s uncomfortably frustrating.&lt;/p&gt;



&lt;p&gt;Granted if you’re testing on Android first or leaning into web2app, these limitations aren’t an issue. But as Uncle Ben says, with great volume comes great structural complexity (or something like that).&lt;/p&gt;



&lt;p&gt;Sure, you could just throw 50 creatives into an advantage plus campaign and let the winners rise to the top. But you’re telling me that I overcame creative burnout, put together hundreds of briefs, &lt;em&gt;and&lt;/em&gt; forced myself to follow a rigorous experimentation process for the Meta gods to decide that 90% of ads shouldn’t get any spend?&lt;br&gt;&lt;br&gt;Uh uh! Nope.&lt;/p&gt;



&lt;p&gt;Assuming there is a hypothesis behind your creative or a reason you made that ad, you want to see it tested. When a creative gets spend and then fails, we should dig into why. We can look at on-platform metrics, dive into breakdowns, pay attention to placements etc.&lt;/p&gt;



&lt;p&gt;But when the creative &lt;em&gt;doesn’t&lt;/em&gt; get spend and we just say “Oh Meta didn’t push this creative because it’s not a winner and usually they’e right”, we now have 280+ losing ads and no indication of why they didn’t perform. Soon I’ll have thousands of losing ads, multiple failed concepts or formats, and zero data.&lt;/p&gt;



&lt;p&gt;It’s almost as if I should have just tested fewer ads…&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-should-you-focus-on-instead&quot;&gt;&lt;strong&gt;What should you focus on instead&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Okay Nathan, I hear you say, what &lt;em&gt;should &lt;/em&gt;I be doing?&amp;nbsp;&lt;/p&gt;



&lt;p&gt;I’m glad you asked!&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-set-the-right-north-star&quot;&gt;&lt;strong&gt;1. Set the right North Star&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;I’ll say it again: the point of creative testing is to find new winners! So that’s what we should be tracking:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;# of winning creatives in a given period&lt;/li&gt;



&lt;li&gt;Win rate (winning creatives ÷ total creatives tested) in the same period&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;If you can increase the absolute number of winners over time without your win rate collapsing, you’re doing high-volume testing the right way. I recommend plotting win rate against volume week-over-week (or month-over-month): when win rate starts to dip as volume climbs, you may be pushing things too far.&lt;br&gt;&lt;br&gt;The goal is to generate net-new winners with maximum efficiency.&lt;/p&gt;



&lt;p&gt;A key efficiency metric I like to track is &lt;strong&gt;Cost-per-winner (CPW)&lt;/strong&gt;:&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;(Total testing spend + total production costs) ÷ # winning creatives&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;This shows exactly how much you’re paying, on average, to uncover each new winner. If CPW drifts upward, you’re spending more to find less.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;563&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Cost-per-winner-efficiency-graph-1024x563.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-46175&quot; style=&quot;width:600px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Cost-per-winner-efficiency-graph-1024x563.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Cost-per-winner-efficiency-graph-300x165.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Cost-per-winner-efficiency-graph-768x422.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Cost-per-winner-efficiency-graph-1536x845.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Cost-per-winner-efficiency-graph-50x28.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Cost-per-winner-efficiency-graph-73x40.jpg 73w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Cost-per-winner-efficiency-graph-696x383.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Cost-per-winner-efficiency-graph-560x308.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Cost-per-winner-efficiency-graph-538x296.jpg 538w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Cost-per-winner-efficiency-graph-840x462.jpg 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Cost-per-winner-efficiency-graph-80x44.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Cost-per-winner-efficiency-graph-48x26.jpg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-creative-volume-trap-in-Meta-ads_Cost-per-winner-efficiency-graph.jpg 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;All of these metrics share the same North Star: more real winners, less wasted spend.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;If you see cost-per-winner climbing or win rate falling, it’s a signal to:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Dial back volume&lt;/li&gt;



&lt;li&gt;Revisit hypotheses and creative diversity&lt;/li&gt;



&lt;li&gt;Double-down on quality guardrails&lt;/li&gt;
&lt;/ol&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-focus-on-diversity-as-much-as-volume&quot;&gt;&lt;strong&gt;2. Focus on diversity as much as volume&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Not only does creative diversity prevent ad fatigue, but it unlocks new growth in your ad account too.&lt;/p&gt;



&lt;p&gt;By creative diversity, I mean:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Testing statics, videos, carousels.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Mixing it up with high production value and low production value creatives&lt;/li&gt;



&lt;li&gt;Pushing out different creative concepts and trends&lt;/li&gt;



&lt;li&gt;Working with different creators&lt;/li&gt;



&lt;li&gt;Trying out different editing styles&lt;/li&gt;



&lt;li&gt;Focusing on different angles and value propositions&lt;/li&gt;



&lt;li&gt;Experimenting with different AI creative formats&lt;/li&gt;



&lt;li&gt;Balancing new concepts with iterations&lt;/li&gt;



&lt;li&gt;Crafting scripts and briefs around different JTBD&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;I like to think of it like this:&amp;nbsp;&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;For every JTBD we’ve identified, we want multiple winners. For every placement we advertise in, we want multiple winners. For every demographic we deem as relevant, we want multiple winners.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;The only way to do that is to focus on creative diversity and ensure we document our hypotheses and learnings to make these connections.&lt;br&gt;&lt;br&gt;This also forces you to produce new concepts as opposed to iterating on historical winners.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;Tip: &lt;/em&gt;&lt;/strong&gt;&lt;em&gt;If you really want to be cautious, try adding quotas for iterations of historical winners and aim at least 60% of creative testing budget towards new concepts.&lt;/em&gt;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-reward-creativity-and-celebrate-big-swings-not-just-wins&quot;&gt;&lt;strong&gt;3. Reward creativity and celebrate big swings (not just wins)&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Earlier this year, Deeksha, our Growth Lead, came up with a killer creative concept. It was funny, engaging and all round a great ad. But the first variant didn’t do that well at all. In fact, it flopped. But the ad still made our creative hall of fame and got celebrated on Slack.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Now, on one hand, who cares? It flopped. After all, we want winners, right?&lt;/p&gt;



&lt;p&gt;But the concept was super smart, and it’s that type of thinking and creativity that enables us to find new winners. In fact, it was her creativity that eventually turned that concept into a winning creative.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Treasure that creativity and celebrate big swings.&lt;/strong&gt; No, they won’t all pay off. But if we don’t foster a culture where creativity can breathe, you just end up copying competitors off Ad Library 👀. That would make us a ‘not so Creative Agency’. And the same goes for you and your team!&amp;nbsp;&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-4-don-t-burnout-your-creative-strategists&quot;&gt;&lt;strong&gt;4. Don’t burnout your creative strategists&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Finally, make an active effort not to burn out your creative strategists!&lt;strong&gt; In a world where creative is the larger lever to pull, creative strategists are literally your engine.&lt;/strong&gt;&amp;nbsp;&lt;/p&gt;



&lt;p&gt;If you’re expecting one person or even a few individuals to come up with dozens and dozens of completely new concepts each month on their own, at an increasing rate, to greater success… You need to rethink your expectations.&lt;br&gt;&lt;br&gt;More and more frequently we’ve started supporting teams who already have strong in-house creative teams, but are looking to ensure diversity and increase volume without running into creative burnout. Bringing in an additional creative agency partner to buff up your creative efforts can enable you to reap all the rewards of high volume testing with very few of the drawbacks. (If that creative partner prioritises finding new winners and aren’t just playing a volume game, of course 😉).&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-have-i-convinced-you&quot;&gt;&lt;strong&gt;Have I convinced you?&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;High volume creative testing can work.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;But increasing volume isn’t always the answer to your performance plateau. There’s a million and one ways to tank your Meta ads performance by focusing too much on creative volume, without the proper guardrails.&lt;/p&gt;



&lt;p&gt;Instead, &lt;strong&gt;build a systematic creative testing strategy around a single North Star: new winners, delivered efficiently&lt;/strong&gt;. Track your win rate alongside volume, keep an eye on cost-per-winner, and double down on creative diversity with quotas and hypothesised JTBD.&lt;/p&gt;



&lt;p&gt;By swapping volume-chasing for insight-chasing, you’ll preserve your team’s creativity, maintain rigour in your experimentation and unlock real, sustainable lift in your Meta accounts.&amp;nbsp;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Don’t just solve a problem — solve it emotionally]]></title><description><![CDATA[Five levers to tap into your customer’s emotional motivators]]></description><link>https://www.revenuecat.com/blog/growth/solve-app-problems-emotionally/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/solve-app-problems-emotionally/</guid><pubDate>Tue, 09 Sep 2025 16:11:40 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Dont-just-solve-a-problem—solve-it-emotionally.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;For years now, I’ve been a dedicated subscriber to a bit of an unusual app: the F1 app. Yep, this is my truth.&lt;/p&gt;



&lt;p&gt;I originally started watching F1 for my partner, so we’d have a shared interest (he wasn’t about to give Netflix dating shows or ice baths a chance). But somewhere along the way, I became the bigger fan. I watch the practices, listen to the podcasts, catch the press conferences — the whole lot.&lt;/p&gt;



&lt;p&gt;Here’s the thing: if you think purely in terms of functionality, the F1 app lets me get the latest news and watch the races. But that’s not why I keep it.&lt;/p&gt;



&lt;p&gt;I find myself opening the app at the most random moments, craving a hit of F1 drama — which, let’s be honest, is an adrenaline junkie’s version of &lt;em&gt;Desperate Housewives&lt;/em&gt;. It’s a world that’s completely different from my day-to-day life as a growth consultant, or the races I usually train for (marathons and triathlons). It’s my escape. I love staying on top of the latest updates, feeling part of the F1 community, and nerding out over results and changes. One of my friends and I literally just send each other F1 Instagram Reels every week.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;520&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-11-520x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-46056&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-11-520x1024.png 520w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-11-152x300.png 152w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-11-768x1513.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-11-780x1536.png 780w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-11-25x50.png 25w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-11-20x40.png 20w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-11-235x464.png 235w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-11-696x1371.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-11-284x560.png 284w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-11-150x296.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-11-240x472.png 240w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-11-41x80.png 41w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-11-24x48.png 24w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-11.png 812w&quot; sizes=&quot;auto, (max-width: 520px) 100vw, 520px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;As much as we want to believe our apps are purely functional, most aren’t. They exist to satisfy an emotional need. And when you speak to your users’ feelings and emotions, that’s when you really retain them.&lt;/p&gt;



&lt;p&gt;So, how do you do that? Let’s start with the concept of a habit loop.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-habit-loop&quot;&gt;&lt;strong&gt;Habit loop&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;In his 2012 book &lt;em&gt;The Power of Habit&lt;/em&gt;, Charles Duhigg popularized the concept of the habit loop, namely the idea that every habit follows a three-step cycle:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;518&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-6-1024x518.png&quot; alt=&quot;&quot; class=&quot;wp-image-46046&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-6-1024x518.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-6-300x152.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-6-768x389.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-6-50x25.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-6-79x40.png 79w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-6-696x352.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-6-560x283.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-6-840x425.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-6-80x40.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-6-48x24.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-6.png 1235w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Charles Duhigg’s habit loop&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;This is the core of retention: a trigger prompts us to take action, and we’re rewarded. I get a push notification about the latest F1 news (trigger), I open the app to read it (action), and I enjoy discovering what’s happening (reward). &lt;strong&gt;The more someone moves through this loop with a positive emotional response, the more likely your app becomes part of their identity, rather than just a tool they use.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;A key part of this loop isn’t just a consistent reward — variation is key. If we don’t know &lt;em&gt;when&lt;/em&gt; and &lt;em&gt;if&lt;/em&gt; we will be rewarded, or if the reward changes, it keeps it exciting. As a result, it taps better into our emotional reaction.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Just a year after Charles started the craze for creating a habit loop, Nir Eyal released his book &lt;em&gt;Hooked&lt;/em&gt;. Here he expanded on the habit loop by adding a fourth step: investment.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;506&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-7-1024x506.png&quot; alt=&quot;&quot; class=&quot;wp-image-46048&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-7-1024x506.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-7-300x148.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-7-768x380.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-7-1536x759.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-7-50x25.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-7-81x40.png 81w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-7-696x344.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-7-560x277.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-7-840x415.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-7-80x40.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-7-48x24.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-7.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Nir Eyal’s habit loop&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;Investment is about putting time, effort, or data into an app — essentially giving it something that makes you more likely to stick around. It reduces the chances of switching and deepens your attachment to the platform.&lt;/p&gt;



&lt;p&gt;Now, the F1 app isn’t particularly personalized for me, I never took the time to set it up. But many F1 fans do invest heavily, especially through F1 Fantasy. Within the app, you can build your driver lineup based on a budget and compete for points. They even promote it on podcasts to encourage more fans to join in. That level of engagement makes you more invested and makes switching to another viewing platform (like a TV subscription with Sky) feel less appealing.&lt;/p&gt;



&lt;p&gt;Emotions play a role at every stage of this habit loop:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Emotional &lt;strong&gt;triggers&lt;/strong&gt; drive us to take action&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Actions&lt;/strong&gt; are often driven by feeling, not just logic&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Rewards&lt;/strong&gt; help us feel something (like joy, pride, or belonging)&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Investments&lt;/strong&gt; create an emotional connection and a sense of ownership&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;But before we can effectively tap into these emotions, we need to understand the emotional triggers that drive someone to use the app in the first place.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-creating-emotional-triggers&quot;&gt;Creating emotional triggers&lt;/h2&gt;



&lt;p&gt;I’ve actually already mentioned two types of triggers: the desire to escape and a push notification. One is an emotional, internal trigger; the other is an artificial, external one. External triggers — like notifications, emails, or social posts — are limited by opt-ins and channels. Internal triggers, on the other hand, are expansive, and incredibly powerful.&lt;/p&gt;



&lt;p&gt;The most famous examples are Instagram and TikTok. That addictive scroll we fall into when we’re bored? It’s driven by internal emotional cues. The other night I ended up in a rabbit hole of scrolling through Instagram reels. I just wanted one that would make me laugh.&lt;/p&gt;



&lt;p&gt;With most apps, you often start with external triggers (push, email, social media, etc.), but the goal is to eventually build a relationship strong enough that emotional, internal triggers take over.&lt;/p&gt;



&lt;p&gt;This might sound a little dark, but negative emotions make particularly strong internal triggers. In &lt;a href=&quot;https://medium.com/growthhackers/solving-retention-with-loops-93bdbbf3e3f9&quot;&gt;an article I co-authored with Thorsten Straus&lt;/a&gt; on solving retention with habit loops, we listed a few:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Fear&lt;/li&gt;



&lt;li&gt;Anger&lt;/li&gt;



&lt;li&gt;Disgust&lt;/li&gt;



&lt;li&gt;Sadness&lt;/li&gt;



&lt;li&gt;Rage&lt;/li&gt;



&lt;li&gt;Loneliness&lt;/li&gt;



&lt;li&gt;Melancholy&lt;/li&gt;



&lt;li&gt;Annoyance&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;However, we have to be conscious when we use them. For apps focused on change and progress, they can be incredibly effective. Take a fitness app like &lt;a href=&quot;https://www.joinladder.com/&quot;&gt;Ladder&lt;/a&gt;; they often showcase transformations, highlighting dissatisfaction or frustration (e.g., “I’m not seeing results”) as motivation.&lt;/p&gt;



&lt;p&gt;But for something like a meditation app, it’s important not to amplify the very emotions (anxiety, fear, stress etc.) that likely brought someone there in the first place.&lt;/p&gt;



&lt;p&gt;By creating emotional associations with our app, we can eventually ensure people associate the app with those emotions on their own. These emotional responses, however, are often driven by deeper desires — what Harvard Business School calls &lt;em&gt;emotional motivators&lt;/em&gt; in their study, &lt;a href=&quot;https://hbr.org/2015/11/the-new-science-of-customer-emotions&quot;&gt;&lt;em&gt;The New Science of Customer Emotions&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;They identified ten core emotional motivators that influence behavior. I like to think of them as &lt;em&gt;drivers&lt;/em&gt; (naturally, as an F1 fan). Certain drivers are more likely to resonate with specific types of apps.&lt;/p&gt;



&lt;p&gt;Here are the emotional motivators (or drivers, &lt;em&gt;wink wink&lt;/em&gt;), how they impact people, some words or phrases someone with that driver might use, and example app categories that often align with each one. These aren’t strict pairings, but a place to start when thinking about the emotional motivators behind your own product.&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Emotional Driver&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;What it allows individuals to achieve&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Words/phrases they might use&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Example app categories&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Stand out from the crowd&lt;/td&gt;&lt;td&gt;A unique social identifier&lt;/td&gt;&lt;td&gt;Different&lt;br&gt;Unique&lt;br&gt;Express myself&lt;br&gt;Feels like me&lt;/td&gt;&lt;td&gt;Social media apps, creative apps&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Have confidence in the future&lt;/td&gt;&lt;td&gt;Positive view of the future&lt;/td&gt;&lt;td&gt;Positive&lt;br&gt;Optimistic&lt;br&gt;Sense of direction&lt;br&gt;Get better&lt;/td&gt;&lt;td&gt;Gratitude / Manifestation apps&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Enjoy a sense of wellbeing&lt;/td&gt;&lt;td&gt;A life without stress&amp;nbsp;&lt;/td&gt;&lt;td&gt;Calm&amp;nbsp;&lt;br&gt;Balanced&lt;br&gt;Relaxed&lt;/td&gt;&lt;td&gt;Wellness / Sleep / Meditation apps&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Feel a sense of freedom&lt;/td&gt;&lt;td&gt;Empowerment to act independently&lt;/td&gt;&lt;td&gt;Independent&lt;br&gt;In control&lt;br&gt;Options&lt;/td&gt;&lt;td&gt;Travel apps, Productivity apps&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Feel a sense of thrill&lt;/td&gt;&lt;td&gt;Excitement and pleasure&amp;nbsp;&lt;/td&gt;&lt;td&gt;Excited&lt;br&gt;Feel a rush&lt;br&gt;Enjoy it&lt;/td&gt;&lt;td&gt;Gaming apps, Dating apps, Investment apps&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Feel a sense of belonging&lt;/td&gt;&lt;td&gt;Being a part of a community&lt;/td&gt;&lt;td&gt;Connected Understood&lt;br&gt;Supported&lt;br&gt;Part of something&lt;/td&gt;&lt;td&gt;Community / Social-Focused apps&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Protect the environment&lt;/td&gt;&lt;td&gt;Take care of their surroundings&lt;/td&gt;&lt;td&gt;Do my part&lt;br&gt;Reduce waste&lt;br&gt;Feel guilty&lt;br&gt;Future&lt;/td&gt;&lt;td&gt;Food reduction apps, Carbon tracking apps&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Be the person I want to be&lt;/td&gt;&lt;td&gt;Self-improve and live up to their ideal&lt;/td&gt;&lt;td&gt;Proud&lt;br&gt;Consistent&lt;br&gt;Progress&lt;br&gt;Getting better&lt;/td&gt;&lt;td&gt;Fitness apps, Education apps, Productivity apps&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Feel secure&lt;/td&gt;&lt;td&gt;To feel secure enough to follow their dreams&lt;/td&gt;&lt;td&gt;Secure&lt;br&gt;Safe&lt;br&gt;Peace of mind&lt;br&gt;Protected&lt;/td&gt;&lt;td&gt;Finance apps, Wellness apps&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Succeed in life&lt;/td&gt;&lt;td&gt;Live a meaningful life&lt;/td&gt;&lt;td&gt;Moving forward&lt;br&gt;Reach my goals&lt;br&gt;Motivated&lt;/td&gt;&lt;td&gt;Education apps,&amp;nbsp; Wellness apps&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;&lt;em&gt;Based originally on &lt;/em&gt;&lt;a href=&quot;https://hbr.org/2015/11/the-new-science-of-customer-emotions&quot;&gt;&lt;em&gt;The New Science of Customer Emotions&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;You’ve probably noticed that some categories can align with multiple emotional drivers, and that’s totally normal. But &lt;strong&gt;how do you move beyond the functional job your app does and get into your customer’s mindset to uncover their emotional triggers?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;We’ll start there, before diving into some of the most common emotional drivers behind subscription apps.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-understanding-your-emotional-motivators&quot;&gt;Understanding your emotional motivators&lt;/h2&gt;



&lt;p&gt;I’ve included a few words and phrases under each category, and you might recognize some from customer reviews or conversations. I’ve definitely seen reviews filled with phrases like “peace of mind,” “excited,” and similar expressions. These are helpful for identifying the &lt;em&gt;language&lt;/em&gt; your customers use, but reviews only scratch the surface. They rarely reveal the deeper emotional motivators at play.&lt;/p&gt;



&lt;p&gt;You guessed it… I’m going to talk about my favorite thing, aka Jobs to be Done (JTBD). It’ll come as no surprise that I advocate conducting JTBD interviews to understand these motivators.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Focus on your highest-spending, most loyal customers — those for whom &lt;a href=&quot;https://www.revenuecat.com/blog/growth/how-subscription-apps-can-become-painkillers/&quot;&gt;your app is a true &lt;em&gt;painkiller&lt;/em&gt;&lt;/a&gt;, not just a nice-to-have. The goal is to understand why.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;The most powerful thing you can do in these interviews is bring customers back to the moment they chose to switch to your app. What was going on in their life? What triggered the decision? For this purpose, I’d also suggest speaking with more recent customers who share similarities with those top-tier users.&lt;/p&gt;



&lt;p&gt;This helps you understand the emotions in that moment of acquisition, but I suggest taking it a step further and also talking to them about how they feel now when they use the app. When do they open your app? Why yours, and not another? This helps you see if what initially motivated them to try your app is still the same.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;For some apps, the motivators and emotions behind them transition over time. If we go back to the Ladder example, I might initially be driven to &lt;em&gt;be the person I want to be&lt;/em&gt;, but over time, as I’m happier with my strength, I might transition into using the app to &lt;em&gt;enjoy a sense of wellbeing&lt;/em&gt;. With these shifts in emotion, your language and visuals may change to adjust to where your app subscriber is in their journey.&lt;/p&gt;



&lt;p&gt;Today, we’ll spend less time on the acquisition phase and instead focus on how to use emotion to drive retention and loyalty. To do that, we’ll explore five powerful levers: &lt;strong&gt;Emotional storytelling, community, personalization, gamification, and rituals.&lt;/strong&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-1-emotional-storytelling&quot;&gt;1. Emotional storytelling&lt;/h2&gt;



&lt;p&gt;We use apps to solve a problem, but to feel that trust and connection, we want to feel a part of their story.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Like I mentioned earlier, F1 isn’t just about races. It’s a saga filled with rivalries, redemption arcs, and rising stars. I’m fully invested in the story of Hadjar, a young, emotional driver who crashed on the &lt;em&gt;formation lap&lt;/em&gt; of his first F1 race. The crowd felt for him, especially when Lewis Hamilton’s father gave him a hug and told him it was okay. From there, the app and podcast followed his growth, charting his journey from that crash to finishing 6th in Monaco, one of the hardest races on the calendar.&lt;/p&gt;



&lt;p&gt;We connect with people, and many apps play into that. Take &lt;em&gt;Headspace&lt;/em&gt;, for example. The meditation app uses Andy Puddicombe’s voice as one of its main narrators. His story of losing friends and loved ones is something many of us resonate with. If meditation helped him, it feels like it could help us too.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;387&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-8-1024x387.png&quot; alt=&quot;&quot; class=&quot;wp-image-46050&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-8-1024x387.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-8-300x113.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-8-768x290.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-8-1536x581.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-8-50x19.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-8-106x40.png 106w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-8-696x263.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-8-560x212.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-8-840x318.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-8-80x30.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-8-48x18.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-8.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Headspace has radio episodes sharing Andy’s story&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;For some subscription apps, having someone be the face of it doesn’t make sense, and that’s fine. &lt;a href=&quot;https://johnlivesay.com/winning-the-story-wars-with-jonah-sachs/&quot;&gt;Brand mythology&lt;/a&gt;, a phrase coined by Jonah Sachs, is about using visuals and copy to make your audience feel a part of your brand. Whether it’s that it reflects who they are, their identity, or gives them meaning, feeling part of a bigger story.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Emotional storytelling is the underlying lever that supports the next three levers:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Community: &lt;/strong&gt;Gives us a sense of belonging and shared purpose&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Personalization:&lt;/strong&gt; Helps them see themselves in the story&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Gamification:&lt;/strong&gt; Makes them feel like they’re on a journey, with progress and momentum&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;But here’s the catch: these techniques won’t land unless they’re backed by the right language and visuals. Without that emotional context, they fall flat.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-2-create-a-sense-of-community-nbsp&quot;&gt;2. Create a sense of community&amp;nbsp;&lt;/h2&gt;



&lt;p&gt;One of the most effective ways apps create emotional connection is by building a sense of community. They make users feel like they’re part of the app’s world and culture. F1 does this brilliantly by answering community questions both in-app and through the &lt;em&gt;F1 Explains&lt;/em&gt; podcast.&lt;/p&gt;



&lt;p&gt;Why does this work so well? It ties back to &lt;a href=&quot;https://www.britannica.com/topic/social-identity-theory&quot;&gt;&lt;em&gt;social identity theory&lt;/em&gt;&lt;/a&gt;, which tells us that when something aligns with our sense of belonging, we begin to feel like it’s part of &lt;em&gt;who we are&lt;/em&gt;. Realistically, I’ll probably never meet an F1 driver but I still feel part of the global F1 community reacting, debating, and celebrating every moment. And hey, a girl can dream.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Another favorite example of mine is Peloton. I resisted it for years. It just felt &lt;em&gt;too&lt;/em&gt; cultish; all those people swearing it was life-changing. “It’s an expensive stationary bike,” I told myself. Fast-forward a few years: I got a sweet deal from a friend… and now I’m in the cult. I love my Peloton. The workouts, the playlists — they’re incredible. I even virtually high-fived a few fellow riders the other day. I swear I could hear the whisper “One of us… One of us…” through the screen.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;882&quot; height=&quot;897&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Peloton-app-screens.png&quot; alt=&quot;&quot; class=&quot;wp-image-46060&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Peloton-app-screens.png 882w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Peloton-app-screens-295x300.png 295w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Peloton-app-screens-768x781.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Peloton-app-screens-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Peloton-app-screens-39x40.png 39w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Peloton-app-screens-456x464.png 456w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Peloton-app-screens-696x708.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Peloton-app-screens-551x560.png 551w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Peloton-app-screens-291x296.png 291w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Peloton-app-screens-464x472.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Peloton-app-screens-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Peloton-app-screens-48x48.png 48w&quot; sizes=&quot;auto, (max-width: 882px) 100vw, 882px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Peloton encourages you to connect with others and join communities&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;So, how do they do it, and how can you build something similar?&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Community events&lt;/strong&gt;: Peloton holds regular live workouts and invites members to ride in their studios, helping users feel part of something bigger&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Showcasing members&lt;/strong&gt;: They shout out individual achievements in live classes, and the leaderboard adds a competitive (and motivational) edge&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Creates sub-groups:&lt;/strong&gt; From #pelotonlondon to #pelotonmoms, users can find their niche and connect more deeply through micro-communities&amp;nbsp;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Sharing user feedback:&lt;/strong&gt; This is where update logs can shine. Don’t waste them on bug fixes. Use them to show users what’s changed based on their feedback. Take it further with in-app messages and emails to reinforce that their voices matter.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Connecting with other members:&lt;/strong&gt; Even if you aren’t comfortable virtually high-fiving a stranger, they also offer the option to connect with people you know, so you can follow your friends and families’ progress and workouts&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;em&gt;Peloton encourages you to connect with others and join communities&lt;/em&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-3-this-is-for-me-and-only-me&quot;&gt;3. This is for me and only me&lt;/h2&gt;



&lt;p&gt;As much as we love being part of a community, we also want to feel like individuals: unique, not just another cliché.&lt;/p&gt;



&lt;p&gt;With physical products, &lt;em&gt;personalization&lt;/em&gt; is often just segmentation in disguise: a few preset variations users can choose from. But with apps, personalization can be much more meaningful. It’s about creating a truly &lt;em&gt;individual&lt;/em&gt; experience—one that adapts to the user. From onboarding flows to content recommendations, personalization helps users feel like the app is made for &lt;em&gt;them&lt;/em&gt;. They feel ownership.&lt;/p&gt;



&lt;p&gt;This ties directly into &lt;a href=&quot;https://selfdeterminationtheory.org/theory/&quot;&gt;&lt;em&gt;Self-Determination Theory&lt;/em&gt;&lt;/a&gt;, which suggests people are more motivated—and feel more secure—when they believe they’re in control.&lt;/p&gt;



&lt;p&gt;And the good news? You don’t need millions of users or a complex system to start personalizing. Start small:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Ask for and use their name&lt;/li&gt;



&lt;li&gt;Reflect their choices back to them in later screens&lt;/li&gt;



&lt;li&gt;Let them set preferences or highlight what matters most to them&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;These small touches transform a generic app into &lt;em&gt;their&lt;/em&gt; app. That sense of ownership becomes a powerful emotional hook, especially if your audience is driven by a desire to feel confident about the future or secure in their choices.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-4-gamifying-the-experience&quot;&gt;4. Gamifying the experience&lt;/h2&gt;



&lt;p&gt;Now, I’m not just talking about an F1 fantasy league or your standard streaks and badges. I’m talking about the deeper, more thoughtful ways apps can gamify an experience to spark joy and build emotional connection. While gamification naturally aligns with the emotional driver &lt;em&gt;feel a sense of thrill&lt;/em&gt;, I’ve even seen financial apps use it effectively.&lt;/p&gt;



&lt;p&gt;The goal isn’t to gamify for the sake of it, but to create variable rewards that make the habit loop more enjoyable and engaging. In my &lt;a href=&quot;https://www.revenuecat.com/blog/growth/gamification-in-apps-complete-guide/&quot;&gt;gamification in apps&lt;/a&gt; guide, I broke down seven ways you can do this well:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Streaks&lt;/li&gt;



&lt;li&gt;Badges&lt;/li&gt;



&lt;li&gt;Internal currency and point-based rewards&lt;/li&gt;



&lt;li&gt;Leaderboards&lt;/li&gt;



&lt;li&gt;Challenges&lt;/li&gt;



&lt;li&gt;Guided progression&lt;/li&gt;



&lt;li&gt;Social interaction&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Look closely, and you’ll spot another powerful emotional motivator behind many of these: &lt;em&gt;be the person I want to be&lt;/em&gt;. The drive to grow, to improve, to become your ideal self, fuels countless fitness, education, and productivity apps. Gamification helps make that journey not only more fun, but also more manageable by breaking it into clear, bite-sized wins.&lt;/p&gt;



&lt;p&gt;In my recent &lt;a href=&quot;https://subclub.com/episode/boost-conversion-and-retention-with-jobs-to-be-done-daphne-tideman-growth-advisor&quot;&gt;SubClub podcast episode&lt;/a&gt;, I explored how the best apps bring the &lt;em&gt;aha!&lt;/em&gt; moment right into onboarding; giving users an immediate sense of progress in that very first session.&lt;/p&gt;



&lt;p&gt;I love the way &lt;a href=&quot;https://welltory.com/&quot;&gt;Welltory&lt;/a&gt;, a health tracking app, focuses onboarding on getting you to share your data, rather than overwhelming users with a list of features. When I tried this myself, I was amazed to see the insights it shared about my sleep and wellbeing. Potentially, I let out an audible ‘aha’.&lt;/p&gt;



&lt;p&gt;Gamification can amplify that feeling, turning a simple action into a mini-celebration. It allows you to bring fun and enjoyment into that &lt;em&gt;aha!&lt;/em&gt; moment, or push your users to take action.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-5-your-app-as-a-ritual&quot;&gt;5. Your app as a ritual&lt;/h2&gt;



&lt;p&gt;While this may not work for every app, the ideal scenario is that using your app becomes a &lt;em&gt;ritual &lt;/em&gt;— a natural, almost-automatic part of someone’s day. There’s a specific moment when they turn to your app, and they love it.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Time for another slightly embarrassing confession: I’m not just an F1 nerd but also a massive &lt;em&gt;Harry Potter&lt;/em&gt; fan. I literally can’t fall asleep without playing &lt;em&gt;Harry Potter&lt;/em&gt; on Audible. &lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;525&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Audible-Harry-Potter-app-screen-525x1024.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-46062&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Audible-Harry-Potter-app-screen-525x1024.jpg 525w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Audible-Harry-Potter-app-screen-154x300.jpg 154w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Audible-Harry-Potter-app-screen-768x1499.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Audible-Harry-Potter-app-screen-787x1536.jpg 787w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Audible-Harry-Potter-app-screen-26x50.jpg 26w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Audible-Harry-Potter-app-screen-21x40.jpg 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Audible-Harry-Potter-app-screen-238x464.jpg 238w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Audible-Harry-Potter-app-screen-696x1358.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Audible-Harry-Potter-app-screen-287x560.jpg 287w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Audible-Harry-Potter-app-screen-152x296.jpg 152w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Audible-Harry-Potter-app-screen-242x472.jpg 242w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Audible-Harry-Potter-app-screen-41x80.jpg 41w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Audible-Harry-Potter-app-screen-25x48.jpg 25w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Audible-Harry-Potter-app-screen.jpg 820w&quot; sizes=&quot;auto, (max-width: 525px) 100vw, 525px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;I’ve been subscribed to Audible for years because it serves two essential functions in my life: helping me fall asleep, and getting me through long runs. Just like someone might have a ritual around their morning coffee, your app can become part of that daily rhythm.&lt;/p&gt;



&lt;p&gt;If we go back to emotional drivers, this starts with identifying the &lt;em&gt;natural moments&lt;/em&gt; when users already turn to your app. Then, for new subscribers, you can guide them with push and email notifications to use your app during those moments. For instance, a journaling app might ask when you usually go to bed, and suggest setting a reminder just before that time to reflect and write. You begin with external triggers until internal triggers take over.&lt;/p&gt;



&lt;p&gt;How do you know your app has become a ritual, embedded in their life? When your users start saying things like &lt;em&gt;“I’m the kind of person who…”&lt;/em&gt;. That’s when your app becomes part of their identity. Rituals are especially powerful for emotional motivators like feeling secure, making progress, and belonging.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-from-functional-to-emotional-problem-solving&quot;&gt;From functional to emotional problem solving&lt;/h2&gt;



&lt;p&gt;Functional value might be what gets users through the door, but emotional connection is what keeps them coming back. When you tap into internal triggers, emotional motivators, and levers like community, personalization, gamification, and rituals — you move beyond being just a tool: &lt;strong&gt;you become a habit&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;The most loved apps aren’t just useful; they &lt;strong&gt;make people feel something&lt;/strong&gt;. Whether it’s a sense of belonging, progress, or security, emotion is what makes habits stick and strengthens the habit loop.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Solving a problem is essential, but when you make someone &lt;em&gt;feel&lt;/em&gt;, that’s when you build something they can’t imagine living without.&lt;/p&gt;



&lt;p&gt;In summary: emotion has a place in business, especially when it comes to apps.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[App portfolios vs. single-app focus: Which strategy drives long-term success?]]></title><description><![CDATA[Why some developers double down on one app while others spread their bets]]></description><link>https://www.revenuecat.com/blog/growth/app-portfolio-vs-single-app/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/app-portfolio-vs-single-app/</guid><pubDate>Tue, 09 Sep 2025 12:46:54 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/app-portfolio-vs-single-app.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;As RevenueCat’s &lt;em&gt;State of Subscription Apps 2025&lt;/em&gt; &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps-2025/#h-realized-ltv-per-payer&quot;&gt;shows&lt;/a&gt;, making a living from mobile apps is not for everyone — most who try never even reach $1,000 in monthly recurring revenue. This opens the eternal debate on whether it’s better to go all in on a single idea, or diversify into less polished ones to see what works best then double down.&lt;/p&gt;



&lt;p&gt;After five years, I’ve experienced both paths myself — and also worked alongside teams that chose one or the other. I’ll share those first-hand lessons so you can better weigh the benefits and risks, and decide which approach suits you.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-benefits-of-a-single-app-focus&quot;&gt;Benefits of a single-app focus&lt;/h2&gt;



&lt;p&gt;Before listing the benefits and advantages of putting all your time into one app, you should remember that software is a commodity.&lt;/p&gt;



&lt;p&gt;This means that if you are here to play the long-term, you must never forget that almost every single app developer team could replicate your product. Therefore, focusing on a single app eliminates the most crucial risk: being unable to stand out and nail the distribution game.&lt;/p&gt;



&lt;p&gt;But why?&lt;/p&gt;



&lt;p&gt;The main benefits of a single-app focus are not product improvement iterations but what will make your users say, “Oh, I should try this app”. In other words, it’s not about the software but what brings customers to the front door.&lt;/p&gt;



&lt;p&gt;Instead of giving a boring bullet point explaining why this could be a cool idea, below are three real cases I’ve lived that prove this approach is worth trying.&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Some years ago, a US-based indie developer focused on a single product in the health and fitness category. Today, this single app is doing more than $500K a month (most of it thanks to organic users coming into the app). What did he do to get here?
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Community building:&lt;/strong&gt; Grow its social media accounts to more than 1M followers, by focusing on not killing the product’s virality. He achieved this by not monetizing the product for the first few years. Who doesn’t like a great product for free? This is a clear example of playing the long game.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Name:&lt;/strong&gt; He nailed the app store positioning because the app’s name was the name of the entire category; therefore, the app ranks number one even after years. This means that he decided to allocate a lot of time and effort into app store optimization (which worked).&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Apple-friendly&lt;/strong&gt;: Bet on something that Apple will be proud of sharing for free with its user base in the App Store. His app has been app of the day, editor’s choice, and much more. He focused on creating relevant stories to pitch the Apple editorial team.&lt;br&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;



&lt;li&gt;I collaborated with two indie developers who scaled an app to +$100K ARR in two months without a clear idea of how even apps work. But they decided on one thing: to make one great product (with the secret catch that they bet on an idea forcing users to use the product daily). The result was a fantastic onboarding experience that resonated with their customers and a user experience focused on ease of use. But what were the benefits they discovered?
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Organic growth engine:&lt;/strong&gt; Created a small network of content creators, paid a fixed rate per 1,000 views, with an incentivized payout structure. This got them millions of organic impressions and almost free ideas to run paid ads. The organic purchases were “paying for the creators themselves”, and providing an extra cash flow to test-validated ad concepts.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;User obsession:&lt;/strong&gt; They built something they would use and did multiple user interviews weekly to identify the low-hanging fruit (low-effort features with high impact).&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Short payback period:&lt;/strong&gt; Ads were profitable since day one. They achieved this by removing the free trial and investing in validated ad ideas. Achieving this level of performance in a short period allowed them to scale fast while mitigating any financial risks.&lt;br&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;



&lt;li&gt;A close friend who had previously built a successful gaming company decided to go all-in on creating a new subscription apps studio. He chose the single-app approach. The result was that his first app today is doing +$700K in MRR, with the caveat that it took him more than one and a half years to get to the first $50K in MRR. These are things where he allocated his focus to make it work:
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;B2B distribution:&lt;/strong&gt; Instead of doing a simple B2C application, he built a more robust B2B product for users who depend on a specific service to do their work. He focused on promoting the app within niche communities of their user base, offering partnerships and referral programs. This is a tedious and lengthy process.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Exhaustive creative testing:&lt;/strong&gt; During the first 12 months of work, he never achieved a single ad that could make a cent in revenue. After more than 350 assets, he finally got a winning ad that later changed the course of his business. The idea came from asking users what videos they love seeing in their TikTok feed when bored.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Innovated product features:&lt;/strong&gt; Developed and optimized new ways of doing things that users already requested. Took the time to design, test, and deploy new product functionalities with a high level of detail. This created a strong word of mouth among its user base (product-led growth).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;With these stories, you’d conclude that by focusing on a single app, you’ll be able to maximize your chances of success by nailing:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Building an authentic organic community/engine&lt;/li&gt;



&lt;li&gt;App store optimization&lt;/li&gt;



&lt;li&gt;Product retention (focusing on high-frequency usage and disruptive features)&lt;/li&gt;



&lt;li&gt;No trial onboarding flow to get profitable ads from day zero&lt;/li&gt;
&lt;/ol&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-risk-of-focus&quot;&gt;The risk of focus&lt;/h2&gt;



&lt;p&gt;But what are the potential risks to focusing on one app? &lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.linkedin.com/in/vahebaghdasaryan/&quot;&gt;Vahe Bagdasaryan&lt;/a&gt;, Founder of &lt;a href=&quot;https://www.paywalls.design/&quot;&gt;paywalls.design&lt;/a&gt;, has led Growth, Monetization and Lifecycle Marketing at Flo Health. He shares the trade-off for single-app success:&lt;a href=&quot;https://www.linkedin.com/company/17930178/&quot;&gt;&lt;/a&gt;&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“When you focus on a single app, you get depth: tighter product loops, more brand equity, and the ability to run faster, compounding experiments. But you’re also putting all your revenue risk in one basket—an algorithm change or market shift can hit hard.”&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;I’ve personally experienced several lessons first hand after working at multiple companies focusing on a single app:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Slow (to none) responsiveness to new trends:&lt;/strong&gt; After years of working at a company that was mainly focused on improving what was already ‘working’, one learning was clear: they were not able to adapt to the new AI trend and ship high-quality products associated with what customers were looking for. It was a sad experience seeing other companies with 5% of the resources we had scale to millions in ARR in a matter of months, while we were focusing on trying to increase the revenue 5% YoY because the app was doing well. They tried to switch their approach two years later, but it was too late. The peak for the AI wave was left behind.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Complexity to identify the ceiling:&lt;/strong&gt; It is almost impossible to confidently say, “We won’t be able to grow our app anymore”. Because of this, companies are trapped in a loop where they keep trying even after seeing their metrics stabilize or shrink. It’s hard to say when it’s a good time to let it go and move on. The lack of certainty tends to freeze the decision-makers. It’s always safer to stick with what works (or used to work) than go all in on something new.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Emotional damage:&lt;/strong&gt; I’ve seen it before. Companies spend over two years on a single app, only to realize it was not the best bet. These situations devastate morale, creating a false impression of their skills and capabilities to ship great products. This all comes up to the human concept: “If I’m as smart as I think, then I won’t need to put too much effort into making this work”.&lt;/li&gt;
&lt;/ol&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-an-app-portfolio-approach-is-a-good-idea-nbsp&quot;&gt;Why an app-portfolio approach is a good idea&amp;nbsp;&lt;/h2&gt;



&lt;p&gt;After years in the app industry, I learnt there are two types of app-portfolios:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;One-code-fits-all&lt;/strong&gt;: When a company uses the same codebase to create new apps for different audiences and problems. Same code, different UI (theme/topic).&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Diversification&lt;/strong&gt;: Take as many different bets as possible to see what works. Implies building in various verticals, distinguished features, and new front/back infrastructure each time.&lt;/li&gt;
&lt;/ol&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“A portfolio spreads risk and gives you more shots at the goal, but the flip side is diluted attention and slower iteration per app.”&lt;/p&gt;
&lt;cite&gt;&lt;a href=&quot;https://www.linkedin.com/in/vahebaghdasaryan/&quot;&gt;Vahe Bagdasaryan&lt;/a&gt; – Founder of &lt;a href=&quot;https://www.paywalls.design/&quot;&gt;paywalls.design&lt;/a&gt;, ex-Flo&lt;/cite&gt;&lt;/blockquote&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-one-code-fits-all&quot;&gt;One-code-fits-all&lt;/h3&gt;



&lt;p&gt;Let’s start with the golden ticket: one-code-fits-all. Imagine for a second that your first app works out. Most app developers will start thinking about the next venture, but only a few will think about adapting the same codebase to a new product, and even fewer will know how to make that work.&lt;/p&gt;



&lt;p&gt;Here are some learnings and benefits of doubling down on one code fits all:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Low-code maintenance, and therefore the need for a massive team of developers, disappears. You can keep a lean infrastructure with just a few people — this helps to reduce operational costs and improve the gross profit.&lt;/li&gt;



&lt;li&gt;Tends to be a two-way door decision. If your next project does not work out, you can return to the previous state quickly without burning too much cash.&lt;/li&gt;



&lt;li&gt;Marketing and product-wise, it enables you to manage multiple apps at scale and with limited resources. If one feature works for one app, it will probably work for others. And the ad learning could be shared across apps.&lt;/li&gt;
&lt;/ol&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-diversification&quot;&gt;Diversification&lt;/h3&gt;



&lt;p&gt;When it comes to diversification, these are the main benefits I experienced first-hand:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Trend surfing allows flexibility and the ability to create different products quickly without worrying about the tech and maintenance.&lt;/li&gt;



&lt;li&gt;Reduces the risk of putting all your eggs in one basket. Betting in multiple verticals at the same time could ensure long-term success.&lt;/li&gt;



&lt;li&gt;Generate the opportunity to create entire new portfolios thanks to a huge success in a specific niche. I worked with a company that decided to create an app in the utility category, and encountered a massive success, so it allowed them to fund an entire team to only build utility apps.&lt;/li&gt;
&lt;/ol&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“What I’ve seen work best is building the infrastructure and playbooks (growth, monetization, lifecycle, etc.) that can scale across multiple apps — once you have that, the marginal cost of launching the second or third app is much lower, and you don’t lose as much focus.”&lt;/p&gt;
&lt;cite&gt;&lt;a href=&quot;https://www.linkedin.com/in/vahebaghdasaryan/&quot;&gt;Vahe Bagdasaryan&lt;/a&gt; – Founder of &lt;a href=&quot;https://www.paywalls.design/&quot;&gt;paywalls.design&lt;/a&gt;, ex-Flo&lt;/cite&gt;&lt;/blockquote&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-to-be-aware-of-when-managing-an-app-portfolio&quot;&gt;What to be aware of when managing an app portfolio&lt;/h2&gt;



&lt;p&gt;With industry growth fueled by AI, it’s faster and easier than ever to develop multiple apps. But that doesn’t mean it’s easy to make multiple &lt;strong&gt;successful &lt;/strong&gt;apps. As &lt;a href=&quot;https://www.linkedin.com/in/nathan--hudson/&quot;&gt;Nathan Hudson&lt;/a&gt;, Founder &amp;amp; CEO @ &lt;a href=&quot;https://www.perceptycs.com/&quot;&gt;Perceptycs&lt;/a&gt;, explains: &lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“There’s an awful lot that goes into scaling an app successfully: user acquisition, onboarding, optimization, ASO, improving retention, ongoing product development, bug fixes, etc. It’s not that simple to build a really solid, strong app.”&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Some of the risks of pursuing an app portfolio may be obvious, but when I started working with apps, it wasn’t clear to me just what could go wrong. (Plus, people don’t tend to share the bad news!)&lt;/p&gt;



&lt;p&gt;Below is a list, by order of importance, of the things you should consider:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;The amount of missing great opportunities is higher than what people think. Due to high iterations and low improvment cycles for a same product, a lot of companies end up throwing to the trash something that with more time could scale.&lt;/li&gt;



&lt;li&gt;Underestimate the difficulty of handling a lot of tech debt. Things break, users leave bad reviews and revenue does not grow.&lt;/li&gt;



&lt;li&gt;Focus in business is everything. As everyone says, doing a lot of things at the same time may led you to not doing anything good.&lt;/li&gt;



&lt;li&gt;Ignore the fact that other people with much more experience and knowledge than you are already building in a vertical you have almost no idea. Don’t be one of those people that say, “I can build something like this” and then expect to have the same revenue. That’s not the way it works.&lt;/li&gt;



&lt;li&gt;It’s hard to define how much time it’s worth allocating to an app, hence creating confusion on what success looks like.&lt;/li&gt;
&lt;/ol&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“The main bottleneck for many companies is no longer development time, it’s the growth strategy and execution itself, as well as ideation on the product side.”&lt;/p&gt;
&lt;cite&gt;&lt;a href=&quot;https://www.linkedin.com/in/nathan--hudson/&quot;&gt;Nathan Hudson&lt;/a&gt; – Founder &amp;amp; CEO @ &lt;a href=&quot;https://www.perceptycs.com/&quot;&gt;Perceptycs&lt;/a&gt;&lt;/cite&gt;&lt;/blockquote&gt;



&lt;p&gt;Whether you opt for one-code-fits-all or diversification, both approaches have their benefits. And if you can nail your resource management and risk expansion, an app portfolio can pay off. &lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-do-you-decide-between-single-app-focus-or-app-portfolios&quot;&gt;How do you decide between single-app focus or app portfolios?&lt;/h2&gt;



&lt;p&gt;Ultimately, there’s no one right path in mobile apps, just different opportunities to chase. &lt;/p&gt;



&lt;p&gt;After my own experiences and seeing others pursue portfolios, these are my main takeaways:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Pick a lane and double-down&lt;/strong&gt;: A single-app focus lets you pour all resources into one growth engine, community, ASO, sticky features, and ad funnels often driving faster organic traction and earlier profitability.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;But beware of tunnel vision&lt;/strong&gt;: The same single-app commitment can blind teams to new trends (e.g., AI), make it hard to spot a growth ceiling, and sink morale if the bet stalls.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Portfolios spread risk and learning&lt;/strong&gt;: Re-skinning one winning codebase or diversifying across verticals lets you ride new waves quickly, recycle features, and hedge against any one app’s decline.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Operational drag is real&lt;/strong&gt;: More apps mean more tech debt, fractured focus, and a higher chance of killing promising ideas too early success hinges on ruthless prioritization and shared infrastructure.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Success ≠ one formula&lt;/strong&gt;: Your best path depends on team strength, appetite for iteration, and cash runway. Choose the strategy that lets you move fastest while staying financially and emotionally resilient.&lt;/li&gt;
&lt;/ol&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“If you’ve built a money printer, I’d just focus on keeping it full of ink.”&lt;/p&gt;
&lt;cite&gt;&lt;a href=&quot;https://www.linkedin.com/in/nathan--hudson/&quot;&gt;Nathan Hudson&lt;/a&gt; – Founder &amp;amp; CEO @ &lt;a href=&quot;https://www.perceptycs.com/&quot;&gt;Perceptycs&lt;/a&gt;&lt;/cite&gt;&lt;/blockquote&gt;
</content:encoded></item><item><title><![CDATA[Why RevenueCat: The Essential Subscription Infrastructure for Growing App Businesses]]></title><description><![CDATA[RevenueCat is a cross-platform solution for leveraging in-app purchases and subscriptions. This article explains "Why RevenueCat"]]></description><link>https://www.revenuecat.com/blog/growth/essential-subscription-infra/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/essential-subscription-infra/</guid><pubDate>Mon, 08 Sep 2025 14:55:05 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/The-Essential-Subscription-Infrastructure-for-Growing-App-Businesses-A.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;As competition intensifies across the mobile app ecosystem, more developers and companies are turning to subscription models to create sustainable revenue and accelerate growth. In-app purchases and subscriptions are now core monetization strategies for many of the world’s leading mobile businesses.&lt;/p&gt;



&lt;p&gt;But managing subscriptions isn’t easy. Server-side receipt validation, cross-platform entitlements, centralizing data across app stores, setting up pricing experiments, tracking performance, all of this requires time, technical resources, and constant maintenance. That’s where RevenueCat comes in.&lt;/p&gt;



&lt;p&gt;RevenueCat is a cross-platform solution for leveraging in-app purchases and subscriptions. It provides versatile SDKs, scalable infrastructure, and a robust analytics and experimentation toolkit as a platform, so you can focus on building and growing your app, not wrangling with store APIs.&lt;/p&gt;



&lt;p&gt;Today, more than 75,000 apps across industries like gaming, health, education, and dating rely on RevenueCat, processing over $11 billion in annual subscription revenue. From indie developers to global companies like OpenAI, Notion, and Buffer, teams of every size use RevenueCat to simplify monetization and accelerate growth.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-do-global-companies-use-revenuecat&quot;&gt;Why do global companies use RevenueCat?&lt;/h2&gt;



&lt;p&gt;RevenueCat delivers distinct, but ultimately complementary, value to developers, growth marketers, and product managers.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;1-developer-perspective-cut-the-cost-and-time-of-building-subscription-infrastructure&quot;&gt;1) Developer perspective — Cut the Cost and time of building subscription infrastructure&lt;/h3&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Receipt validation &amp;amp; entitlements without a separate server: RevenueCat securely validates App Store / Google Play receipts on its servers and exposes results as simplified Entitlements. On the app side, you only need to check: &lt;em&gt;“Does this user have the &lt;/em&gt;&lt;em&gt;pro&lt;/em&gt;&lt;em&gt; entitlement?”&lt;/em&gt; No separate backend for payment verification required.&lt;br&gt;&lt;/li&gt;



&lt;li&gt;Cross-platform SDKs with a consistent model: RevenueCat abstracts platform differences so you work with the same concepts, customer, purchase, entitlement everywhere. Android’s Google Play Billing and iOS’s StoreKit evolve annually; migration and testing are costly. RevenueCat handles this, dramatically reducing maintenance across platforms.&lt;br&gt;&lt;/li&gt;



&lt;li&gt;Remote configuration with Offerings/Packages: Update price plans, display order, messaging, and trial availability from the dashboard, no code changes or redeploys. You can move faster on marketing and business strategy while developers focus on higher-value engineering work, and avoid constant back-and-forth for A/B tests.&lt;br&gt;&lt;/li&gt;



&lt;li&gt;Paywalls &amp;amp; Experiments: Non-developers can edit UI/copy/pricing for paywalls and offerwalls in a Figma-like web editor. You can assemble screens and run A/B tests in native Android/iOS without code changes, skipping the long cycle of code → release → review → user update. This is especially valuable on iOS, where reviews can take 1–2 weeks even for small copy tests.&lt;br&gt;&lt;/li&gt;



&lt;li&gt;Edge-case handling built in: Sandbox, refunds, upgrades/downgrades, restore purchases, subscription complexity often comes from exceptions. RevenueCat standardizes state transitions, so your team can focus on monetization and core business logic. For example, when a user buys on device A and logs into device B, restoring access is straightforward.&lt;br&gt;&lt;/li&gt;



&lt;li&gt;Reduced security/policy burden: RevenueCat addresses receipt tampering, changing store policies, and other sensitive compliance issues at the platform level, letting your team focus on your product.&lt;br&gt;&lt;/li&gt;



&lt;li&gt;One-click integrations with analytics/marketing: Easily send purchase/subscription events to Amplitude, Mixpanel, Segment, Braze, Adjust, AppsFlyer, GA4, and more. With Webhooks/ETL, loading data into your warehouse is simple, cutting time spent on data plumbing and boosting business insight.&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;2-growth-perspective-drive-monetization-with-experiments-segmentation-and-funnels&quot;&gt;2) Growth perspective — drive monetization with experiments, segmentation, and funnels&lt;/h3&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Optimize conversion with paywall/A/B tests: Test pricing (monthly/annual/lifetime), trial length, bundle combinations, and copy/design, then roll out changes without redeploying. Quickly find the best funnel for your target segments.&lt;br&gt;&lt;/li&gt;



&lt;li&gt;Segment-based targeting: Show different Offerings by country, device, acquisition channel, or behavior. Localize pricing and test country-specific plan preferences to run tailored strategies.&lt;br&gt;&lt;/li&gt;



&lt;li&gt;Funnel &amp;amp; cohort reports: Track trial start rate, trial → paid conversion, refund/churn, repurchase success, MRR/ARPPU/LTV, and other subscription KPIs directly in the dashboard.&lt;br&gt;&lt;/li&gt;



&lt;li&gt;Real-time marketing integrations: Implement trial-expiry reminders, failed-payment retries, and win-back campaigns through tools like Braze and OneSignal. Automate user engagement and improve retention.&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;3-revenue-perspective-lift-conversion-retention-and-ltv&quot;&gt;3) Revenue perspective — lift conversion, retention, and LTV&lt;/h3&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Maximize early conversion (trial starts / Day-0 purchases): Present clear value during onboarding and continuously test trial/price configurations to raise trial starts and Day-0 purchases.&lt;br&gt;&lt;/li&gt;



&lt;li&gt;Upsells and plan switches: Encourage monthly → annual upgrades, highlight premium packages, and bundle features to increase ARPPU and LTV, all easily A/B tested with Offerings.&lt;br&gt;&lt;/li&gt;



&lt;li&gt;Reduce involuntary churn: Handle payment retry and grace periods flexibly, and use reminder integrations to prevent churn and improve subscription retention.&lt;br&gt;&lt;/li&gt;



&lt;li&gt;Localized pricing and product mixes: Experiment with region-appropriate pricing and trial setups to optimize conversion and revenue across global markets.&lt;br&gt;&lt;/li&gt;



&lt;li&gt;Data-driven operations: Quickly compare performance by channel, country, and app version to allocate marketing budgets and prioritize your product roadmap.&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;state-of-subscription-apps-2025&quot;&gt;&lt;strong&gt;State of Subscription Apps 2025&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;RevenueCat’s mission is simple: “Help Developers Make More Money.”&lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps-2025/&quot;&gt;On the State of Subscription Apps 2025&lt;/a&gt; page, you’ll find ~260 pages of category-level analyses and benchmarks to guide your strategy this year.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;881&quot; height=&quot;461&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-5.png&quot; alt=&quot;&quot; class=&quot;wp-image-46027&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-5.png 881w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-5-300x157.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-5-768x402.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-5-50x26.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-5-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-5-696x364.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-5-560x293.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-5-840x440.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-5-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-5-48x25.png 48w&quot; sizes=&quot;auto, (max-width: 881px) 100vw, 881px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;conclusion&quot;&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;RevenueCat is a comprehensive solution to the technical, operational, and strategic challenges of in-app subscriptions and purchases. For developers, it reduces the costs of building and maintaining payment infrastructure while improving development velocity. For growth teams, it enables fast, data-driven experimentation and optimization. For product managers, it provides the tools to improve conversion, retention, and LTV, making RevenueCat a core piece of infrastructure for sustainable app growth.&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[How to hack your app store ratings]]></title><description><![CDATA[Hack your app store ratings by capturing happy users at the right moment.]]></description><link>https://www.revenuecat.com/blog/engineering/how-to-hack-your-app-store-ratings/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/how-to-hack-your-app-store-ratings/</guid><pubDate>Fri, 05 Sep 2025 10:42:33 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/How-to-improve-your-app-store-ratings-1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;One of the biggest things affecting conversion is your app’s App Store or Google Play Store rating. Many users see a good rating as a sign of trustworthiness, feature richness, and value. But that doesn’t mean good apps automatically have a good rating.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;The layman psychology behind app store ratings is that people are far more likely to publicly complain if something is wrong, than go out of their way to publicly praise something. Even for popular apps, negative reviews dominate over positive. Capturing those good reviews is crucial to unlock growth.&lt;/p&gt;



&lt;p&gt;One approach is by ethically hacking the system by building a ‘&lt;strong&gt;rating happiness engine&lt;/strong&gt;‘ that will prompt users to rate your app at the time they are most satisfied with it. First, let’s go through how app store ratings work, their benefits for user acquisition, and learn why good apps don’t necessarily have good ratings.&lt;/p&gt;



&lt;p&gt;&lt;em&gt;Note: When we say “app store”, we’re generalizing across the Apple App Store and Google Play Store, as well as other Android app distribution platforms like the Huawei App Gallery and Amazon Appstore. The ratings and reviews work in similar fashion across all of these.&amp;nbsp;&lt;/em&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-ratings-and-reviews&quot;&gt;Ratings and reviews&lt;/h2&gt;



&lt;p&gt;App stores use a combination of &lt;strong&gt;numerical ratings&lt;/strong&gt; and &lt;strong&gt;qualitative reviews&lt;/strong&gt; to provide users feedback on the value and user satisfaction of apps.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;From a growth perspective, ratings and reviews are critical. As explained in our&lt;a href=&quot;https://www.revenuecat.com/blog/growth/app-store-optimization-guide/&quot;&gt; App store optimization guide&lt;/a&gt;, ratings have a compounding effect: higher ratings improve conversion, which boosts organic visibility, drives more downloads, and generates more reviews.&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-how-app-ratings-works&quot;&gt;How app ratings works&lt;/h3&gt;



&lt;p&gt;There are two qualities to app store ratings:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Average rating:&lt;/strong&gt; an average of the ratings the app has received from users&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Rating count:&lt;/strong&gt; how many ratings the app has &lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Users rely on both metrics to evaluate the app’s perceived value: &lt;strong&gt;average rating tells a customer satisfaction story&lt;/strong&gt;, and the &lt;strong&gt;number of ratings provides validity&lt;/strong&gt; to that number.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Users can rate the app either in app stores or directly in the app. Apple gives a simple average of all ratings the app has received, while Google shows a weighted average placing heavier emphasis on more recent reviews. Both stores show the average rating in the app’s product page and search results. Apps with more reviews and higher average rating also rank higher in the app store’s search results.&lt;/p&gt;



&lt;p&gt;Users can rate your app on a scale of one to five. Individual ratings shape your app’s summary rating, which the product page and search results then display. This summary rating is specific to each territory on the App Store and you can reset it when you release a new version of your app.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-when-should-i-reset-my-app-s-ratings&quot;&gt;When should I reset my app’s ratings?&lt;/h3&gt;



&lt;p&gt;Only Apple allows developers to reset the ratings on their app, which you might consider if your app has been in the app store for years and has recently gone through a revamp, which would justify shaking off the baggage of old 1 star reviews. Google doesn’t allow developers to reset their ratings. Resetting ratings also doesn’t remove reviews, just the numerical rating.&lt;/p&gt;



&lt;p&gt;If your app has an average rating from thousands of reviews it’s preferable to keep them, as building that amount of reviews will take time—and even if you reset the rating number, the reviews will still speak volumes. Users can change their rating, so developers often achieve better results by improving the app and prompting users to rate it again, rather than resetting ratings.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-how-app-reviews-work&quot;&gt;How app reviews work&lt;/h3&gt;



&lt;p&gt;Similar to ratings, reviews are another factor that encourages users to evaluate if the app is worth downloading. Reviews that mention bugs, features, and pricing are what users often look at most often before downloading the app. The same as ratings, users can review apps in the app store itself, or directly in the app.&lt;/p&gt;



&lt;p&gt;The best way to turn bad user reviews into good user reviews is to answer all of the feedback users submit to app stores. For example, telling users that a bug they encountered has been fixed, a new feature has been released, or pricing has been adjusted. You can do this in the developer response section of the review, and it will often lead to previously-negative reviews turning positive. Users feel they they are being heard. Reviews with developer response are also shown in the app’s product page before the ones without, so it’s an ideal way of showing that you value user feedback.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://machinelearning.apple.com/research/app-store-review&quot;&gt;Starting this year&lt;/a&gt;, Apple began using an LLM (large-language-model) system to generate short summaries of App Store reviews, distilling thousands of user comments into concise highlights that surface the main themes of feedback. These AI-driven summaries help users quickly understand sentiment, but they don’t replace the importance of star ratings. &lt;strong&gt;Ratings remain the most visible trust signal&lt;/strong&gt; in search results and product pages.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-hacking-app-store-ratings&quot;&gt;Hacking app store ratings&lt;/h2&gt;



&lt;p&gt;The simplest hack for improving your ratings is to get users that are satisfied with your app to rate the app, and redirect the unsatisfied ones to give their feedback through another channel that you control.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;So, how do you tell these two types of users apart? &lt;strong&gt;Ask them.&lt;/strong&gt; &lt;/p&gt;



&lt;p&gt;This can be done as easily as an in-app notification that says “Are you enjoying [app name]?”, with simple yes and no answers. Answering ‘no’ will prompt the user to leave feedback through a custom form or similar, and answering ‘yes’ will ask the user if they want to leave review. This way, you still gather constructive critiques, and can address this, but you can also prioritize positive feedback showing on the app stores. &lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/How-to-improve-your-app-store-ratings-1-1024x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-46247&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/How-to-improve-your-app-store-ratings-1-1024x1024.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/How-to-improve-your-app-store-ratings-1-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/How-to-improve-your-app-store-ratings-1-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/How-to-improve-your-app-store-ratings-1-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/How-to-improve-your-app-store-ratings-1-1536x1536.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/How-to-improve-your-app-store-ratings-1-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/How-to-improve-your-app-store-ratings-1-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/How-to-improve-your-app-store-ratings-1-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/How-to-improve-your-app-store-ratings-1-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/How-to-improve-your-app-store-ratings-1-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/How-to-improve-your-app-store-ratings-1-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/How-to-improve-your-app-store-ratings-1-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/How-to-improve-your-app-store-ratings-1-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/How-to-improve-your-app-store-ratings-1-48x48.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/How-to-improve-your-app-store-ratings-1.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;This practice is commonly referred to as review gating, and it should generally be avoided because Apple’s App Store Review Guidelines prohibit steering only happy users toward leaving reviews while deflecting unhappy users elsewhere. If your Yes/No flow is explicitly tied to the App Store review process, you’re very likely to face rejection. That said, this pattern is allowed in certain contexts when it’s implemented for internal feedback collection rather than as a filter for App Store reviews. For example, if both “yes” and “no” responses give users an equal opportunity to leave a review, or if the answers are used only to trigger an in-app survey without influencing who gets asked to rate the app, then it can pass review. The key difference lies in whether the mechanism biases who ends up in the App Store.&lt;/p&gt;



&lt;p&gt;This hack works great for filtering satisfied and unsatisfied users, but it doesn’t solve how we capture the satisfied users. Let’s consider a more systematic approach.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-taking-things-further-building-the-customer-satisfaction-engine&quot;&gt;Taking things further – building the customer satisfaction engine&lt;/h3&gt;



&lt;p&gt;We could of course prompt the user to review the app every so often, but that would quickly frustrate users. Instead, we can be more systematic and focus on capturing users in the right moment.&lt;/p&gt;



&lt;p&gt;By building a customer satisfaction engine, you can monitor user interactions over time and decide when the positive occurs. One way to do this is assigning a score&amp;nbsp;to key user actions, for example:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Opening the app (1 point)&lt;/li&gt;



&lt;li&gt;Using a key feature (10 points)&lt;/li&gt;



&lt;li&gt;Subscribing (10 points)&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;When the cumulative score passes a threshold (e.g. 15 points), you can make the assumption that the user is enjoying using the app. This means prompting them now is likely to lead to a good review.&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/How-to-improve-your-app-store-ratings-2-1024x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-46244&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/How-to-improve-your-app-store-ratings-2-1024x1024.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/How-to-improve-your-app-store-ratings-2-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/How-to-improve-your-app-store-ratings-2-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/How-to-improve-your-app-store-ratings-2-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/How-to-improve-your-app-store-ratings-2-1536x1536.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/How-to-improve-your-app-store-ratings-2-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/How-to-improve-your-app-store-ratings-2-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/How-to-improve-your-app-store-ratings-2-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/How-to-improve-your-app-store-ratings-2-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/How-to-improve-your-app-store-ratings-2-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/How-to-improve-your-app-store-ratings-2-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/How-to-improve-your-app-store-ratings-2-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/How-to-improve-your-app-store-ratings-2-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/How-to-improve-your-app-store-ratings-2-48x48.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/How-to-improve-your-app-store-ratings-2.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;This approach aligns well with both Google Play’s&lt;a href=&quot;https://developer.android.com/guide/playcore/in-app-review#when-to-request&quot;&gt; in-app review guidelines&lt;/a&gt;, which recommend requesting reviews only after “meaningful user actions”, and Apple’s&lt;a href=&quot;https://developer.apple.com/design/human-interface-guidelines/ratings-and-reviews&quot;&gt; Human Interface Guidelines&lt;/a&gt;, which emphasize asking for reviews at “natural and happy moments.” This is the best principle for avoiding annoying your users.&lt;/p&gt;



&lt;p&gt;One more thing we should add in our happiness calculation is a method for decaying happiness events. One example might be if “app open” gives you 1 point, then that 1 point decays completely in one day. Opening the app multiple times a day increases the counter, but rarely opening the app does not count as engagement.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-building-the-happiness-engine-with-code&quot;&gt;Building the happiness engine with code&lt;/h3&gt;



&lt;p&gt;Three simple ideas form the foundation of the happiness engine.&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Record meaningful actions as “events”:&lt;/strong&gt; these are the things that usually signal user satisfaction—finishing a workout, subscribing, or completing a purchase. You decide which actions matter and how valuable each should be.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Calculate a score that decays over time&lt;/strong&gt;: each action gives points, but those points fade with time (exponential decay). That means frequent, recent engagement drives the score up, while old activity slowly stops mattering. &lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Show the review prompt at the right time: &lt;/strong&gt;when the score passes a threshold and a cooldown period has passed since the last prompt, try showing the in-app review dialog.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;The first step to building the engine is listing our events that we want to capture happiness points for.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1dWAOB wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;const config = {\n  actionConfigs: {\n    app_open: { basePoints: 1, halfLifeInDays: 1 },\n    use_feature_x: { basePoints: 5, halfLifeInDays: 2 },\n    subscribe_pro: { basePoints: 10, halfLifeInDays: 14 },\n  },\n  scoreThreshold: 16,\n};\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The engine itself will use these to keep track of the score and prompt the user to review once the score goes over the threshold:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-25m7Uu wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;type UserAction = &apos;app_open&apos; | &apos;use_feature_x&apos; | &apos;subscribe_pro&apos;;\n\ntype ActionConfig = {\n  basePoints: number;\n  halfLifeInDays: number; \/\/ how fast the points decay\n};\n\ntype Config = {\n  actionConfigs: Record&lt;UserAction, ActionConfig&gt;;\n  scoreThreshold: number;\n  promptCooldownInHours: number;\n  pruneAfterDays: number;\n};\n\ntype Event = { action: UserAction; timestamp: number };\n\nclass HappinessEngine {\n  private events: Event[] = [];\n  private lastPrompt: number = 0;\n\n  constructor(private config: Config) {}\n\n  \/\/ Record a new action\n  record(action: UserAction) {\n    this.events.push({ action, timestamp: Date.now() });\n  }\n\n  \/\/ Calculate the current happiness score\n  private calculateScore(): number {\n    const now = Date.now();\n    let score = 0;\n\n    for (const e of this.events) {\n      const { basePoints, halfLifeInDays } = this.config.actionConfigs[e.action];\n      const ageInDays = (now - e.timestamp) \/ (1000 * 60 * 60 * 24);\n\n      \/\/ exponential decay: each half-life cuts the value in half\n      const decay = Math.pow(0.5, ageInDays \/ halfLifeInDays);\n      score += basePoints * decay;\n    }\n    return score;\n  }\n\n  \/\/ Decide if we should show the prompt\n  shouldShowPrompt(): boolean {\n    const score = this.calculateScore();\n    const cooldownPassed =\n      Date.now() - this.lastPrompt &gt;= this.config.promptCooldownInHours * 3600 * 1000;\n\n    return score &gt;= this.config.scoreThreshold &amp;amp;&amp;amp; cooldownPassed;\n  }\n\n  \/\/ Try showing a prompt\n  maybeShowPrompt(): boolean {\n    if (!this.shouldShowPrompt()) return false;\n\n    console.log(&apos;\ud83d\udc49 Showing review prompt\u2026&apos;);\n    this.lastPrompt = Date.now();\n    return true;\n  }\n}\n\n\/\/ Example usage\nconst engine = new HappinessEngine({\n  actionConfigs: {\n    app_open: { basePoints: 1, halfLifeInDays: 1 },\n    use_feature_x: { basePoints: 5, halfLifeInDays: 2 },\n    subscribe_pro: { basePoints: 10, halfLifeInDays: 14 },\n  },\n  scoreThreshold: 16,\n  promptCooldownInHours: 336, \/\/ 14 days\n  pruneAfterDays: 120,\n});\n\nengine.record(&apos;app_open&apos;);\nengine.record(&apos;use_feature_x&apos;);\n\nif (engine.maybeShowPrompt()) {\n  \/\/ In a real app: call the iOS or Android in-app review API here\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;How this works:&lt;/strong&gt;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;App open&lt;/strong&gt; (1 point, fades in 1 day): Opening the app is a weak signal, but repeated openings in a short time show engagement&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Using a key feature&lt;/strong&gt; (5 points, fades in 2 days): Stronger proof that the user finds real value, so it counts more and decays more slowly&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Subscribing to Pro &lt;/strong&gt;(10 points, fades in 14 days): A clear sign of commitment and satisfaction, so it gives the highest points and stays relevant for weeks&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Score threshold (16 points):&lt;/strong&gt; Prevents a single action from triggering a prompt—the user needs a combination, e.g., multiple app opens + a feature use, or a subscription + some activity&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-react-native-example&quot;&gt;React Native example&lt;/h3&gt;



&lt;p&gt;At this point, we’ve covered the theory, the psychology behind ratings, and even walked through code you can adapt for your own app. But reading code in an article isn’t the same as actually experimenting with it. &lt;a href=&quot;https://github.com/plahteenlahti/HappinessEngine&quot;&gt;That’s why I built a small demo app where you can play around with the happiness engine yourself.&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;In the demo, you can click buttons to simulate actions like “use feature X,” or “subscribe to Pro.” Each event adds points that decay over time. Once the score passes the threshold, the engine tries to show the in-app review prompt. This makes it easy to see how different behaviors stack up and when the prompt would actually fire.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;576&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-4-1024x576.png&quot; alt=&quot;&quot; class=&quot;wp-image-45939&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-4-1024x576.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-4-300x169.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-4-768x432.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-4-1536x864.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-4-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-4-71x40.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-4-696x392.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-4-560x315.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-4-526x296.png 526w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-4-840x472.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-4-80x45.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-4-48x27.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-4.png 2048w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-ready-to-give-it-a-go&quot;&gt;Ready to give it a go?&lt;/h2&gt;



&lt;p&gt;App store ratings are one of the strongest levers you have for growth. They affect how many people trust your app, whether you rank higher in searches, and ultimately how many new users you win. The tricky part is that ratings don’t always reflect how good your app really is. Unhappy users are often more vocal than happy ones.&lt;/p&gt;



&lt;p&gt;That’s why it’s so important to &lt;strong&gt;deliberately capture the moments when your users are most satisfied&lt;/strong&gt;. By listening to feedback, responding to reviews, and prompting people at the right time, you can tilt the balance in your favor. The goal isn’t to trick the system, but to give your happiest customers the nudge they need to share their experience publicly.&lt;/p&gt;



&lt;p&gt;Do this well, and you’ll create a cycle: higher ratings lead to more downloads, which lead to more happy users, which lead to even higher ratings. In the long run, that steady compounding effect is one of the most powerful growth hacks you can put in place.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[How to win Shipaton part 4: pitching your app]]></title><description><![CDATA[How to win Shipaton: Turn your Devpost submission into a story judges remember.]]></description><link>https://www.revenuecat.com/blog/engineering/how-to-win-shipaton-part-4-pitching-your-app/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/how-to-win-shipaton-part-4-pitching-your-app/</guid><pubDate>Fri, 05 Sep 2025 06:00:27 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/cover.jpg" length="0" type="image/*"/><content:encoded>&lt;p&gt;Shipaton still has a few weeks left, so there’s plenty of time to ideate, build, and grow your app. In this final part of &lt;em&gt;How to win Shipaton&lt;/em&gt;, we’ll cover the practical side of submitting to Devpost — how to meet the requirements, tell a compelling story, and translate that story into both your written description and your video.&lt;/p&gt;



&lt;p&gt;Before we dive into all that, here are the submission basics you can’t miss:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;A clear text description of your app’s features and functionality.&lt;/li&gt;



&lt;li&gt;A demonstration video (max three minutes judges are reﬁquired to watch).&lt;/li&gt;



&lt;li&gt;The video must show the app working on the target device.&lt;/li&gt;



&lt;li&gt;Upload the video to a public platform (YouTube, Vimeo, etc.) and include the link in your submission.&lt;/li&gt;



&lt;li&gt;No copyrighted music, trademarks, or other protected material unless you have rights to use them.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;br&gt;Judges will only watch three minutes, so you need to hook them fast: show the problem your app solves, how it works, and why it matters. Beyond meeting the requirements, your goal is to make the video engaging, memorable, and different from the rest. If you’ve built something exciting, flaunt it. However, avoid the common pitfall of reducing your pitch to a feature list. That’s where storytelling comes in.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-why-you-need-storytelling&quot;&gt;Why you need storytelling&lt;/h3&gt;



&lt;p&gt;A Devpost submission isn’t just a checklist of features. It’s a pitch. Judges will see dozens of app submissions, and what makes yours stick in their memory is not the technology alone but the story behind it. Storytelling turns your app from “another project” into something relatable, valuable, and worth awarding.&lt;/p&gt;



&lt;p&gt;I’ve read a lot of screenplays and studied screenwriting as a hobby, and the same principles that make a movie or TV episode compelling can also make a hackathon pitch memorable. To show you how, we’ll borrow a storytelling method from screenwriting. First, we’ll cover the basics: how to frame the problem, how your app solves it, and how to express that in a way people remember. Then we’ll dive into a model called the Story Circle, created by Dan Harmon, and look at a simplified version you can actually use. Finally, we’ll show how to adapt this story structure to different formats, first a three-minute video and then the short logline you’ll need in your Devpost submission.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-to-tell-stories&quot;&gt;How to tell stories&lt;/h2&gt;



&lt;p&gt;Pitching, presenting, and selling are all just different forms of storytelling. To get better at them, you don’t need to become a brilliant writer or a polished speaker, although those skills do help. What really matters is understanding the structure of compelling stories. Once you see the common shapes that stories take, you can apply them to almost anything, including your app.&lt;/p&gt;



&lt;p&gt;At its core, storytelling is what makes information stick. People remember stories long after they forget bullet points. Think of ads: when they’re just product features, they disappear instantly. But when they tell a story (or have a very catchy jingle), they become memorable, shareable, and far more likely to leave an impression. And the story doesn’t need to be complicated. It just needs to feel like a story.&lt;/p&gt;



&lt;p&gt;In Western media, the most famous story model is the monomyth, more commonly known as the &lt;em&gt;Hero’s Journey&lt;/em&gt;. Its structure is simple:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;A main character, the hero&lt;/li&gt;



&lt;li&gt;..goes on a journey&lt;/li&gt;



&lt;li&gt;…faces and overcomes a decisive crisis&lt;/li&gt;



&lt;li&gt;..returns home transformed by the experience&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;This is powerful, but it’s not particularly formulaic. That makes it harder to apply directly when you’re pitching something like a mobile app. For our purposes, we need a model that’s more structured and repeatable. That’s where the Story Circle comes in, which we’ll look at next.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-story-circle&quot;&gt;The story circle&lt;/h3&gt;



&lt;p&gt;The Hero’s Journey is powerful, but for product pitches it often feels too abstract. What we need is something more concrete, repeatable, and easy to adapt. That’s where the Story Circle comes in.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;514&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/story-circle-1024x514.png&quot; alt=&quot;&quot; class=&quot;wp-image-45901&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/story-circle-1024x514.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/story-circle-300x150.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/story-circle-768x385.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/story-circle-1536x770.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/story-circle-50x25.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/story-circle-80x40.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/story-circle-696x349.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/story-circle-560x281.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/story-circle-840x421.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/story-circle-48x24.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/story-circle.png 1595w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The Story Circle was developed by Dan Harmon, the screenwriter behind shows like Community and Rick and Morty. Harmon wanted a model for writing stories that could be used again and again for episodic television. In refining the Hero’s Journey, he ended up with a simpler, more formulaic structure that still carries the emotional weight of a full story.&lt;/p&gt;



&lt;p&gt;Here’s how it works:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;1. &lt;strong&gt;Setup&lt;/strong&gt;: a character is in a zone of comfort or familiarity.&lt;/li&gt;



&lt;li&gt;2. &lt;strong&gt;Need&lt;/strong&gt;: they desire something.&lt;/li&gt;



&lt;li&gt;3. &lt;strong&gt;Go&lt;/strong&gt;: they enter an unfamiliar situation.&lt;/li&gt;



&lt;li&gt;4. &lt;strong&gt;Search&lt;/strong&gt;: they adapt to that situation.&lt;/li&gt;



&lt;li&gt;5. &lt;strong&gt;Find&lt;/strong&gt;: they get what they wanted.&lt;/li&gt;



&lt;li&gt;6. &lt;strong&gt;Take&lt;/strong&gt;: they pay a price for it.&lt;/li&gt;



&lt;li&gt;7. &lt;strong&gt;Return&lt;/strong&gt;: they come back to their familiar situation.&lt;/li&gt;



&lt;li&gt;8. &lt;strong&gt;Change&lt;/strong&gt;: they’ve transformed as a result of the journey.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;It’s straightforward, but that’s the point. Unlike the broad strokes of the Hero’s Journey, the Story Circle gives you a practical template you can follow without getting lost in theory. At its core, the circle is about moving from order into chaos and back again, with the character transformed by that journey. That’s what gives even a simple product pitch emotional weight.&lt;/p&gt;



&lt;p&gt;The question then becomes: how do you use this structure when pitching an app? In the next section, we’ll walk through a concrete example—first in a three-minute video, and then in a short written pitch.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-applying-storytelling-to-shipaton&quot;&gt;Applying storytelling to Shipaton&lt;/h2&gt;



&lt;p&gt;Let’s start with a simple, feature-based pitch. It might sound something like this:&lt;/p&gt;



&lt;p&gt;&lt;em&gt;“Fitness app X provides personalized workout plans, progress tracking, and reminders to help users stay consistent with their exercise routines. The app includes features such as logging workouts, viewing charts of progress, and receiving notifications to encourage regular activity. It is designed for people of all fitness levels who want a convenient way to manage their health and fitness from their phone.”&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;This is clear, but it’s also forgettable. It lists features without showing why they matter. To make it stick in the minds of judges (or potential users) we can reshape it using the Story Circle.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Step 1: The first half of the circle&lt;/strong&gt;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;1. Setup&lt;/strong&gt;&lt;br&gt;Introduce a relatable protagonist:&lt;br&gt;&lt;em&gt;“Meet Sarah. She’s busy, juggling work and family, and struggling to stay consistent with her workouts.”&lt;/em&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;2. Need (Problem)&lt;/strong&gt;&lt;br&gt;Show the frustration without your app:&lt;br&gt;&lt;em&gt;“She knows fitness is important, but the gym feels intimidating, and she keeps losing track of her progress.”&lt;/em&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;3. Go (Crossing the Threshold)&lt;/strong&gt;&lt;br&gt;Introduce your app as the tool that helps them take action:&lt;br&gt;&lt;em&gt;“That’s when she downloads X, her pocket fitness coach.”&lt;/em&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;4. Search (Struggle / Exploration)&lt;/strong&gt;&lt;br&gt;Show her trying the core features:&lt;br&gt;&lt;em&gt;“With personalized workout plans, real-time tracking, and progress reminders, Sarah starts building a routine that actually fits her life.”&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;At this point, you’ve already done more than list features. You’ve created empathy and given judges someone to root for.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Step 2: Completing the circle&lt;/strong&gt;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;5. Find (Discovery)&lt;/strong&gt;&lt;br&gt;Show momentum building:&lt;br&gt;“She discovers how easy it is to log her workouts and celebrate small wins.”&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;6. Take (Payoff / Transformation)&lt;/strong&gt;&lt;br&gt;Show the effort and the reward:&lt;br&gt;&lt;em&gt;“Some mornings are tough, but with clear progress charts and supportive reminders, Sarah pushes through.”&lt;/em&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;7. Return (Integration)&lt;br&gt;&lt;/strong&gt;Show the new normal:&lt;br&gt;&lt;em&gt;“Now, Sarah looks forward to her workouts, whether at home or at the gym, because she can see the difference it’s making.”&lt;/em&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;8.Change (Resolution)&lt;/strong&gt;&lt;br&gt;End with transformation and a call to action:&lt;br&gt;&lt;em&gt;“She feels stronger, more confident, and in control — and you can too. Start your journey with X today.”&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-why-this-works-for-shipaton&quot;&gt;Why this works for Shipaton&lt;/h3&gt;



&lt;p&gt;This version has two big advantages over the plain pitch. First, it’s a real story, not just a list of features, so it’s more likely to be remembered by judges who will watch dozens of submissions in a row. Second, it highlights value over features. Judges and users don’t care that your app has a chart, they care that it helps someone feel progress, stay motivated, or achieve a goal.&lt;/p&gt;



&lt;p&gt;Yes, the Sarah example is generic, because the app itself is generic. Your challenge at Shipaton is to apply this framework to your own unique project. If your app has a surprising use case, a quirky origin, or an unexpected benefit, lean into that. The more distinct and specific your story feels, the more likely it is to stand out in the competition.&lt;/p&gt;



&lt;p&gt;Now let’s take that same structure and see how it plays out in your three-minute video&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-using-the-story-circle-in-your-video&quot;&gt;Using the Story Circle in your video&lt;/h3&gt;



&lt;p&gt;A great Shipaton video is proof first, polish second. In the opening 15–20 seconds, start with &lt;strong&gt;Setup + Need&lt;/strong&gt;: introduce who you’re building for and the frustration they face. Keep it concrete—one or two moments that viewers will instantly recognize.&lt;/p&gt;



&lt;p&gt;Then move to &lt;strong&gt;Go + Search&lt;/strong&gt; by showing the app running on the actual device. Use simple screen captures or over-the-shoulder shots that clearly demonstrate taps and responses. Focus your narration on what the user is achieving, not just what the interface looks like.&lt;/p&gt;



&lt;p&gt;In the middle, highlight &lt;strong&gt;Find + Take&lt;/strong&gt;: the progress being made, the effort required, and why your solution works better than alternatives. If you have numbers—retention, completion, time saved—show them with a quick before-and-after.&lt;/p&gt;



&lt;p&gt;Close with &lt;strong&gt;Return + Change&lt;/strong&gt;. Show the new normal and wrap with a one-line transformation plus a clear call to action. Keep pacing tight: judges are only required to watch three minutes, so deliver your hook and proof in the first 60–90 seconds. Finally, double-check compliance—your footage must show the app working on the target device, avoid unlicensed music or third-party assets, and be uploaded publicly (YouTube, Vimeo, etc.) with the link in your submission.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-turn-that-video-into-a-clear-devpost-description&quot;&gt;Turn that video into a clear Devpost description&lt;/h3&gt;



&lt;p&gt;Your text should mirror the same beats, but in compact form. In screenwriting a short one sentence summary of a plot is called a logline. Start with a logline for your app that compresses Setup → Need → Change into one sentence, for example:&lt;/p&gt;



&lt;p&gt;“For [who], [App Name] helps [job to be done] by [distinct approach], so they can [valuable outcome].”&lt;/p&gt;



&lt;p&gt;Follow with two short paragraphs:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;The problem and why existing options fall short (Need).&lt;/li&gt;



&lt;li&gt;How your app works and why it’s different (Go → Search → Find). Keep it user-centric—focus on flows and outcomes, not just features.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Add a final paragraph with evidence (Take → Return → Change): traction, test results, or signals from early users. After the hook you can do a full feature list, and also tell the story of how you ended up building the app. You can even use the Story circle to make that captivating.&lt;/p&gt;



&lt;p&gt;Before publishing, run a compliance check: the description clearly explains functionality, the video link is public, the demo shows the app working on the device, and no copyrighted assets are used without permission.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-conclusion&quot;&gt;Conclusion&lt;/h2&gt;



&lt;p&gt;Storytelling isn’t decoration; it’s how you make judges care within strict time and attention limits. The Story Circle gives you a simple structure: start with a relatable problem, show your app solving it on the actual device, and end with the transformation it creates.&lt;/p&gt;



&lt;p&gt;In your video, focus on proof and clarity. In your description, compress the same beats into a logline and a few sharp paragraphs. Always emphasize outcomes over features. Judges and users want to know the value your app delivers, not just what buttons it has.&lt;/p&gt;



&lt;p&gt;If you build around these principles, your submission won’t just meet Devpost’s requirements — it will stand out. So don’t just list features. Tell a story worth remembering.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Consumer apps surpass gaming “for the first time” — the nuance behind the numbers]]></title><description><![CDATA[The crossover recently makes headlines, but the shift has been underway for some time]]></description><link>https://www.revenuecat.com/blog/growth/consumer-apps-revenue-surpass-gaming-2025/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/consumer-apps-revenue-surpass-gaming-2025/</guid><pubDate>Thu, 04 Sep 2025 11:33:23 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/consumer-apps-revenue-surpass-gaming-2025.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;This headline has recurred regularly over the last couple of years, as the few app intelligence companies adjusted their timeline. Most recently it resurfaced in a &lt;a href=&quot;https://www.businessofapps.com/news/app-revenue-surpasses-games-for-the-first-time-in-q2-2025/&quot;&gt;&lt;em&gt;Business of Apps&lt;/em&gt; piece&lt;/a&gt; claiming consumer app revenue surpassed gaming for the first time in Q2 2025 (see the cover image above). &lt;/p&gt;



&lt;p&gt;I wanted to offer further perspective on what those numbers actually reflect.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-non-gaming-growth-isn-t-new&quot;&gt;Non-gaming growth isn’t new&lt;/h2&gt;



&lt;p&gt;I’m not disputing the overall outcome: revenue from non-gaming has been outgrowing gaming for several years now. Especially post-Covid, as gaming revenue largely stalled while non-gaming keep soaring.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;680&quot; height=&quot;652&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/spend-vs-disposable-income.png&quot; alt=&quot;&quot; class=&quot;wp-image-45916&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/spend-vs-disposable-income.png 680w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/spend-vs-disposable-income-300x288.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/spend-vs-disposable-income-50x48.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/spend-vs-disposable-income-42x40.png 42w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/spend-vs-disposable-income-484x464.png 484w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/spend-vs-disposable-income-560x537.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/spend-vs-disposable-income-309x296.png 309w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/spend-vs-disposable-income-492x472.png 492w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/spend-vs-disposable-income-80x77.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/spend-vs-disposable-income-48x46.png 48w&quot; sizes=&quot;auto, (max-width: 680px) 100vw, 680px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;Post-Covid, gaming spend stalls while non-gaming continues to grow. Source: data.ai&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;This trend has been evidenced by the growing interest in subscription apps from actors historically focused on gaming, such as venture capitalists, ad networks, new tools, or exiting gaming founders launching app studios.&lt;/p&gt;



&lt;p&gt;Yet, there are many nuances to take into account behind the top line figures that I’d like to highlight.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-market-differences-matter&quot;&gt;Market differences matter&lt;/h2&gt;



&lt;p&gt;The split apps/games revenue is very dependent on countries. In the US or India, it’s been three years now that the headline applies.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;882&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/us-app-vs-games-spend-882x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-45925&quot; style=&quot;width:500px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/us-app-vs-games-spend-882x1024.png 882w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/us-app-vs-games-spend-258x300.png 258w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/us-app-vs-games-spend-768x891.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/us-app-vs-games-spend-43x50.png 43w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/us-app-vs-games-spend-34x40.png 34w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/us-app-vs-games-spend-400x464.png 400w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/us-app-vs-games-spend-696x808.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/us-app-vs-games-spend-483x560.png 483w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/us-app-vs-games-spend-255x296.png 255w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/us-app-vs-games-spend-407x472.png 407w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/us-app-vs-games-spend-69x80.png 69w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/us-app-vs-games-spend-41x48.png 41w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/us-app-vs-games-spend.png 1040w&quot; sizes=&quot;auto, (max-width: 882px) 100vw, 882px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;In the US, consumer app spend surpassed gaming in late-2022/2023. Source: Sensor Tower / &lt;a href=&quot;https://www.moloco.com/reports/performance-through-independence&quot;&gt;Moloco&lt;/a&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;While some other markets heavily skew towards gaming, like South Korea (73% gaming in 2024!), Japan (67%) or Germany.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-a-few-giants-dominate-non-gaming-revenue&quot;&gt;A few giants dominate non-gaming revenue&lt;/h2&gt;



&lt;p&gt;Aggregating all non-gaming revenue hides extreme power-law effects. The top 1% of publishers generate 90%+ of the stores revenue. The big revenue drivers are Social &amp;amp; Entertainment (Tiktok, HBO, Disney+, Youtube…). The overall revenue figure is more representative of the situation of a few big leaders than one of the hundreds of thousands of independent developers who read this news.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;593&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/top-publishers-most-revenue-1024x593.jpeg&quot; alt=&quot;&quot; class=&quot;wp-image-45922&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/top-publishers-most-revenue-1024x593.jpeg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/top-publishers-most-revenue-300x174.jpeg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/top-publishers-most-revenue-768x444.jpeg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/top-publishers-most-revenue-1536x889.jpeg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/top-publishers-most-revenue-50x29.jpeg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/top-publishers-most-revenue-69x40.jpeg 69w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/top-publishers-most-revenue-696x403.jpeg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/top-publishers-most-revenue-560x324.jpeg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/top-publishers-most-revenue-511x296.jpeg 511w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/top-publishers-most-revenue-816x472.jpeg 816w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/top-publishers-most-revenue-80x46.jpeg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/top-publishers-most-revenue-48x28.jpeg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/top-publishers-most-revenue.jpeg 1918w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;The top 1% of publishers drive the vast majority of app store revenue. Source: Sensor Tower&lt;/figcaption&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-where-do-we-draw-the-line-between-apps-and-games&quot;&gt;&lt;strong&gt;Where do we draw the line between apps and games?&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;What really defines a game versus a consumer app? There are many shades of grey between the category. I personally consider apps like Duolingo, Impulse, Toca Boca and Elevate to be games, miscategorized in “Education”.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-revenue-figures-have-big-blind-spots&quot;&gt;&lt;strong&gt;Revenue figures have big blind spots&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Keep in mind those revenue figures are:&lt;/p&gt;



&lt;p&gt;a) Estimates, not real. &lt;/p&gt;



&lt;p&gt;b) Only via in-app purchases (IAP) from the two main stores. This leaves aside a lot of apps &amp;amp; games revenue, especially in-app advertising (which I read was actually bigger than IAP, and is largely game driven) but also ecommerce, mobility/delivery, B2B, partnerships and more. &lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.apple.com/newsroom/2025/06/global-app-store-helps-developers-reach-new-heights/&quot;&gt;Apple shared two studies&lt;/a&gt; from the Analysis Group showing that more than 90% of the billings and sales from apps where going outside of IAP ($1 trillion+ from physical goods and services, $150 billion from in-app advertising, and $131 billion for digital goods and services – only the latter being reported in store revenue).&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;991&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/global-app-ecosystem-1024x991.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-45912&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/global-app-ecosystem-1024x991.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/global-app-ecosystem-300x290.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/global-app-ecosystem-768x743.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/global-app-ecosystem-50x48.jpg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/global-app-ecosystem-41x40.jpg 41w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/global-app-ecosystem-479x464.jpg 479w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/global-app-ecosystem-696x674.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/global-app-ecosystem-560x542.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/global-app-ecosystem-306x296.jpg 306w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/global-app-ecosystem-488x472.jpg 488w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/global-app-ecosystem-80x77.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/global-app-ecosystem-48x46.jpg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/global-app-ecosystem.jpg 1306w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;Credit: &lt;a href=&quot;https://www.apple.com/newsroom/2025/06/global-app-store-helps-developers-reach-new-heights/&quot;&gt;Apple&lt;/a&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-off-store-monetization-is-growing-fast&quot;&gt;Off-store monetization is growing fast&lt;/h2&gt;



&lt;p&gt;Last but not least, in the last few years, there has been a fast growing trend of monetizing partially off-store, both for games (web stores, especially for VIPs) and apps (CRM &amp;amp; web2app for quite a while, app2web more recently). This revenue isn’t accounted for in estimates, and it’s currently close to impossible to understand how much hidden app revenue is generated there. Some big apps make the bulk of their revenue outside the store. Think about Noom, Netflix, or Gmail, for entirely different reasons.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-a-shift-that-s-real-but-less-clear-cut-than-headlines-suggest&quot;&gt;A shift that’s real, but less clear-cut than headlines suggest&lt;/h2&gt;



&lt;p&gt;All in all, the tailwinds are strong for consumer apps (i.e. non-gaming), while mobile gaming is going through tougher times post-Covid. This shift is real, but it’s not exactly new. There is no precise way to determine at which moment the shift happened, if it even mattered at all, beyond serving as good engagement bait.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[The ultimate guide to price localization]]></title><description><![CDATA[Are Apple and Google’s price localizations helping or hurting your app?]]></description><link>https://www.revenuecat.com/blog/growth/price-localization-for-apps/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/price-localization-for-apps/</guid><pubDate>Thu, 04 Sep 2025 08:47:06 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/price-localization-for-apps.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Before you enter an airport, a bottle of water might cost $4. But once you walk through those scanners and shamefully get told off for the pair of nail scissors you forgot to remove, the same bottle of water will suddenly cost $12 and your first-born child. What gives? This, in its simplest form, is price localization (and capitalism) but I don’t have the energy to go into that today. Instead, we’re going to settle for discussing price localization for apps, a much more fairer approach you would expect.&lt;/p&gt;



&lt;p&gt;Now price localization seems simple enough. Apple and Google automatically localize pricing for you—amazing, right? Just let them do the heavy lifting while you sit back and relax. If it sounds too good to be true, it probably is, and nowhere is that more true than with pricing. There are plenty of seemingly simple solutions:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Trust Apple and Google&lt;/li&gt;



&lt;li&gt;Use the Netflix index (or the Big Mac Index or Spotify Index)&lt;/li&gt;



&lt;li&gt;Base it on competitor prices&lt;/li&gt;



&lt;li&gt;Base it on costs&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;I’ve already &lt;a href=&quot;https://www.revenuecat.com/blog/growth/guide-to-app-pricing-research-methods/&quot;&gt;explained why options three and four don’t tend to work&lt;/a&gt; when determining your overall price. But what about the first two? And if pricing isn’t easy, is it even worth the effort?&lt;/p&gt;



&lt;p&gt;Well, that is an easy answer: yes, it is so worth the effort. I’m not saying it makes sense for apps to localize, but &lt;strong&gt;every global app should take the time to consider if it’s worth improving price localization.&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;This is such a major opportunity for you to maximize your revenue and get more out of your app &lt;strong&gt;without having to build a single additional feature.&lt;/strong&gt; Does it sound too good to be true? Well, just this once, it’s &lt;em&gt;that&lt;/em&gt; good and &lt;em&gt;that&lt;/em&gt; true.&lt;/p&gt;



&lt;p&gt;And if you need more convincing, consider this: certain markets are seeing substantial growth right now. According to &lt;a href=&quot;https://www.revenuecat.com/blog/growth/is-localization-the-next-great-growth-opportunity-for-subscription-apps/&quot;&gt;data.ai’s insights on global app spend,&lt;/a&gt; Brazil was up &lt;strong&gt;31%&lt;/strong&gt;, Mexico &lt;strong&gt;26%&lt;/strong&gt;, and South Korea &lt;strong&gt;21%&lt;/strong&gt; in non-gaming app spend. There’s a huge opportunity to grow in these secondary markets.&lt;/p&gt;



&lt;p&gt;We’ve put together a complete guide to help you navigate this. It’s a big topic, so I’ve called in the big guns. First up: &lt;a href=&quot;https://www.linkedin.com/in/jacob-rushfinn/&quot;&gt;Jacob Rushfinn&lt;/a&gt;, author of &lt;a href=&quot;https://www.retention.blog/&quot;&gt;retention.blog&lt;/a&gt; and founder of Rushfinn Consulting. His &lt;a href=&quot;https://www.youtube.com/watch?v=2rV268J7anM&quot;&gt;excellent webinar on the subject&lt;/a&gt;, co-hosted with David Barnard, inspired much of this content, along with insights from his blog.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;We’ll start with the big question: &lt;em&gt;Should you localize your prices?&lt;/em&gt; Then we’ll look at why traditional pricing methodologies often fall short when it comes to localization. From there, we’ll walk through how to localize your pricing, covering approaches for both larger companies and startups. Finally, we’ll explore some alternatives to localization and a few edge cases worth considering.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-to-localize-or-not&quot;&gt;To localize or not?&lt;/h2&gt;



&lt;p&gt;I believe it was William Shakespeare who once wrote: “To localize or not to localize, that is the question.” I basically just told you that localizing is better than an Aperol Spritz on the first day of summer, so why am I now slamming on the brakes?&lt;/p&gt;



&lt;p&gt;As powerful as localized pricing can be, it’s not the right move for every app. Here are a few key factors to consider:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-do-you-have-international-traction&quot;&gt;1. Do you have international traction?&lt;/h3&gt;



&lt;p&gt;Let’s get the obvious out of the way: do you have international users? If you’re reading about price localization, I’ll assume you have some or are considering expanding. There is time and effort needed to localize so you need to ensure it’s worth the effort. People are quick to focus on expanding their audience to new markets versus getting the most out of their existing.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;If it is the right time to focus on those secondary markets, and you have some initial traction, the next question to ask is: are you converting in those regions? Are you retaining in those markets?&lt;/p&gt;



&lt;p&gt;You may find your conversion rates are lower internationally. That’s okay, but it’s important to have at least some indication of product-market fit, even if you haven’t yet achieved pricing-market fit.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-are-you-a-mass-market-app&quot;&gt;2. Are you a mass-market app?&lt;/h3&gt;



&lt;p&gt;For high-end or premium apps, audiences tend to be less price sensitive. In fact, lowering prices in certain regions could even harm your brand perception. Mass-market apps, on the other hand, often benefit more from significant price adjustments across markets. So your positioning impacts whether it makes sense to localize.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-are-there-signals-of-a-price-mismatch&quot;&gt;3. Are there signals of a price mismatch?&lt;/h3&gt;



&lt;p&gt;&lt;a href=&quot;https://www.linkedin.com/in/jacob-rushfinn/&quot;&gt;Jacob Rushfinn&lt;/a&gt; shares a &lt;a href=&quot;https://www.youtube.com/watch?v=2rV268J7anM&quot;&gt;smart method in his webinar&lt;/a&gt; for identifying pricing mismatches and opportunities for growth through localization:&lt;/p&gt;



&lt;p&gt;&lt;em&gt;“[Look at] how many free users are coming in. If your conversion rate in India is five times lower than in Canada, Australia, or US, well, there’s some mismatch, right?&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;&lt;em&gt;I think that can be an easy signal… If it’s the same as your best converting market, it’s unlikely you’re going to get a meaningfully higher conversion rate by lowering prices.”&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;A good starting point is to look at your top 10–20 markets by downloads. Compare download-to-purchase conversion rates and ARPU (Average Revenue Per User) across both Android and iOS.&lt;/p&gt;



&lt;p&gt;Keep in mind again: lower conversion might not always be a pricing issue. It could also mean you don’t yet have product-market fit in that region. To dig deeper, check engagement and retention rates—if they’re healthy, but conversions are low, pricing could be the culprit.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-4-can-you-afford-the-implementation-overhead&quot;&gt;4. Can you afford the implementation overhead?&lt;/h3&gt;



&lt;p&gt;Localized pricing does &lt;a href=&quot;https://www.revenuecat.com/blog/growth/the-pros-and-cons-of-web-to-app-funnels/&quot;&gt;come with some operational complexity&lt;/a&gt;. The biggest lift is upfront: researching, defining your pricing logic, and implementing it. If you’re supporting web-to-app flows, you’ll also need to manage payments and tax obligations across different markets, which can add another layer of complexity. People always see focusing on a new international market as a ‘quick hack’ and then are disappointed that it took more time and effort than they expected.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-traditional-methods-are-letting-you-down&quot;&gt;Traditional methods are letting you down&lt;/h2&gt;



&lt;p&gt;Let’s start with the default approach: letting Apple and Google handle localized pricing for you. At first glance, automatic localization sounds amazing; they do the heavy lifting, right?&lt;/p&gt;



&lt;p&gt;But once you dig into &lt;em&gt;how&lt;/em&gt; they set prices, the cracks start to show.&lt;/p&gt;



&lt;p&gt;Here’s how Google explains their pricing methodology:&lt;/p&gt;



&lt;p&gt;&lt;em&gt;“We use the price that you enter as the base for calculating market-specific prices. We’ll convert your price to the local currency, add tax in selected countries, and apply locally relevant pricing patterns and valid exchange rates for the date on which you set the price for your app. You can manually refresh the price to ensure that the local price reflects the latest exchange rate.” – Source: &lt;/em&gt;&lt;a href=&quot;https://support.google.com/googleplay/android-developer/answer/6334373?hl=en-GB#zippy=%2Cpaid-apps&quot;&gt;&lt;em&gt;Google Support&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Apple takes &lt;a href=&quot;https://www.apple.com/uk/newsroom/2022/12/apple-announces-biggest-upgrade-to-app-store-pricing-adding-700-new-price-points/#:~:text=Periodically%2C%20Apple%20updates%20prices%20in,stay%20equalised%20across%20all%20storefronts.&quot;&gt;a similar approach&lt;/a&gt;. Their suggested price points aren’t based on local spending power or perceived value, but are influenced by factors like taxes, exchange rates, and other market mechanics. For example, since taxes vary from country to country, the app stores adjust pricing to account for that.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Jacob gives a great example of the flaw in this logic in a &lt;a href=&quot;https://www.businessofapps.com/podcasts/cracking-international-app-pricing/&quot;&gt;podcast episode for Business of Apps&lt;/a&gt;, where he talks about Duolingo. Duolingo charges more in Spain and France than in the U.S. Why? Because users in those countries get &lt;em&gt;more&lt;/em&gt; value from the app. In the U.S., people often use Duolingo casually, to pick up a second language for travel. In Spain and France, it’s frequently used to improve English, which has a higher perceived value due to its importance in professional and academic contexts. The same terrifying green owl, but for a different price and a different level of dependency.&lt;/p&gt;



&lt;p&gt;So while these automatic adjustments might look good on paper—they aim to normalize take-home revenue per subscriber—they ignore a crucial factor: &lt;em&gt;value to the customer&lt;/em&gt;. If your pricing is too high for a specific region, you’ll likely see lower retention and a drop in overall lifetime value.&lt;/p&gt;



&lt;p&gt;Jacob dives into this in the webinar, noting that these default price points often aren’t optimal for conversion either. That means fewer subscribers, and ultimately, missed opportunities. A system that’s focused entirely on business mechanics, with no regard for customer value, was never going to succeed long-term.&lt;/p&gt;



&lt;p&gt;And yet, during the webinar, a poll showed that around &lt;strong&gt;40% of brands still rely on this ‘set it and forget it’ approach&lt;/strong&gt;. But how far off are these defaults, really? Surely Apple and Google, with all the data they have, can’t be &lt;em&gt;that&lt;/em&gt; wrong…right?&lt;/p&gt;



&lt;p&gt;Well, this is where Jacob’s data gets really interesting. He analyzed pricing across 10 apps, per country, focusing on apps with decent volume that appear optimized for localized pricing.&lt;/p&gt;



&lt;p&gt;Now, keep in mind these are general rules of thumb, especially if you don’t have much data to start with. Your category and audience matter—a lot. Some audiences are more price elastic than others. That said, when Jacob compared actual price points to Apple’s standard recommended pricing, the differences weren’t subtle; they were dramatic:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;585&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-2-1024x585.png&quot; alt=&quot;&quot; class=&quot;wp-image-45873&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-2-1024x585.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-2-300x171.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-2-768x439.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-2-1536x877.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-2-50x29.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-2-70x40.png 70w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-2-696x398.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-2-560x320.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-2-518x296.png 518w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-2-826x472.png 826w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-2-80x46.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-2-48x27.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-2.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Apple’s suggested prices vs what Jacob identified as the ideal price point based on the top ten apps&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;A few honorary mentions: India. Apple recommends pricing about 21% lower than the U.S., but most apps actually go 50–80% lower. That’s no small difference. For the UK, Apple suggests a 26% price increase (thanks a lot, Apple), while Jacob found most apps actually price about 10% lower.&lt;/p&gt;



&lt;p&gt;Hopefully, by now, you’re convinced that the default is… &lt;em&gt;defaulty&lt;/em&gt; bad. So what about indexes? Well, in Jacob’s experience, those don’t hold up too well either.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-three-indexes&quot;&gt;The three indexes&lt;/h3&gt;



&lt;p&gt;There are three major indexes often used for pricing: &lt;strong&gt;Netflix&lt;/strong&gt;, the &lt;strong&gt;Big Mac Index&lt;/strong&gt;, and &lt;strong&gt;Spotify&lt;/strong&gt;. Let’s start with the odd one out—the non-subscription product: a Big Mac. Warning: the author cannot be held accountable for your inexplicable craving for a burger by the end of this section.&lt;/p&gt;



&lt;p&gt;The Big Mac Index started out somewhat as a joke. And while I’m not a Big Mac fan (sorry, McDonald’s lovers), it’s been a useful tool for brands in general. That said, it doesn’t translate well to digital products. The costs involved are totally different, and regional variation in ingredient prices, like the cost of beef, heavily impacts a Big Mac’s price. As far as we know, there’s no meaningful correlation between the price of beef and the price of an app.&lt;/p&gt;



&lt;p&gt;Next up: Netflix. Probably the most famous example, but their pricing isn’t purely based on purchasing power. Anyone who’s experienced the mild panic of seeing their favorite show disappear while on holiday will understand why. (I’m literally writing this on a plane, terrified the season finale of my current show won’t be available in Crete.) Because &lt;a href=&quot;https://help.netflix.com/en/node/125345&quot;&gt;content availability varies by country due to licensing restrictions&lt;/a&gt;, Netflix adjusts pricing based on the value they’re actually able to deliver in each region, and that’s fair enough.&lt;/p&gt;



&lt;p&gt;That leaves one last hope: Spotify. At first glance, they seem like the best of the three, since their music library is available globally. But as Jacob fairly points out, Spotify is heavily focused on monthly subscriptions. They can get away with this because their retention is extremely strong, and they optimize around monthly pricing. This makes them less useful as a pricing benchmark for apps that rely on weekly or annual subscriptions, where pricing structures are quite different. Alas.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;449&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-1-1024x449.png&quot; alt=&quot;&quot; class=&quot;wp-image-45871&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-1-1024x449.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-1-300x131.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-1-768x336.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-1-1536x673.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-1-50x22.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-1-91x40.png 91w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-1-696x305.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-1-560x245.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-1-840x368.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-1-80x35.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-1-48x21.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-1.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;The three major indexes used for pricing and their flaws&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;Now that leaves us with competitor and cost-based pricing as the last of the “quick fix” options. Again I’ve been &lt;a href=&quot;https://www.revenuecat.com/blog/growth/guide-to-app-pricing-research-methods/&quot;&gt;pretty vocal about my issues with these&lt;/a&gt;. Competitor-based pricing assumes your competitors know what they’re doing (spoiler: they might not), and what they offer is often very different from your product anyway. As for cost-based pricing—well, your customers don’t care about your costs. They care about the value you deliver. I’ll stop myself there before I go into a complete rant, as I think you get the gist.&lt;/p&gt;



&lt;p&gt;For overall pricing strategy, &lt;a href=&quot;https://www.revenuecat.com/blog/growth/guide-to-app-pricing-research-methods/&quot;&gt;I generally recommend pricing research&lt;/a&gt;. However, I’ll admit that localization presents a challenge here. In many markets, your audience may be too small to conduct effective research, and doing individual studies for 10–20 countries is a heavy lift.&lt;/p&gt;



&lt;p&gt;So for this use case I will hold up my hands and admit competitor pricing will help guide you in the right direction, but it’s not enough to define your pricing strategy on its own.&lt;/p&gt;



&lt;p&gt;Let’s take a look at a better approach.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-optimising-your-localized-prices&quot;&gt;Optimising your localized prices&lt;/h2&gt;



&lt;p&gt;We’ve learned a lot from AI in the last year, including an inherent fear of em dashes and its skillset as a therapist. We also discovered that if you put garbage in, you’ll get garbage out. The same principle applies to pricing apps: if your initial price isn’t right or you look at the wrong competitor,s you’ll just create what are essentially more ‘bad’ prices.&lt;/p&gt;



&lt;p&gt;The starting point is having confidence in your initial pricing and making sure you’re working from the right foundation to build everything else on. That’s not to say your prices will perfectly match each market from the start, but stronger initial inputs mean better outcomes down the line. This is especially important if you’re a smaller company without enough users to run meaningful A/B tests in each market.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-optimize-your-biggest-market-s-price-first&quot;&gt;1. Optimize your biggest market’s price first&lt;/h3&gt;



&lt;p&gt;Start by deeply understanding price elasticity in your main market and optimizing there &lt;em&gt;before&lt;/em&gt; moving on to localization. For this, Jacob strongly recommends big swing tests. Don’t test $39 versus $43—go bold and try something like $39 versus $69.&lt;/p&gt;



&lt;p&gt;Now I’m very on board with this for multiple reasons:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Pricing tests take a long time:&lt;/strong&gt; You need to evaluate long-term monetization, not just short-term revenue bumps. It usually takes 3–6 months to understand the full impact on retention and LTV.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;You can’t endlessly test different price points:&lt;/strong&gt; Constantly changing your price creates confusion and can damage your brand. Don’t pingpong your pricing, ensure each test should be deliberate.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;It reduces the risk of a non-significant result:&lt;/strong&gt; There’s nothing worse than running a lengthy A/B test and ending up with no significant difference. Honestly, I’d rather see a drop in performance, as it at least gives you a clear signal. Often, no result means there wasn’t enough data to make the test worthwhile in the first place.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;I won’t get too deep into the statistics (we’ve got enough math already), but do make sure you calculate the &lt;a href=&quot;https://www.revenuecat.com/blog/growth/testing-strategies-for-low-traffic-apps/&quot;&gt;Minimum Detectable Effect&lt;/a&gt; before running a pricing A/B test.&lt;/p&gt;



&lt;p&gt;However, the reality is you may benefit from localized prices but not have enough users to properly A/B test different price points. In this case, I would politely ask you (read: &lt;em&gt;beg&lt;/em&gt;) to please at least invest some time into &lt;a href=&quot;https://www.revenuecat.com/blog/growth/guide-to-app-pricing-research-methods/&quot;&gt;pricing research&lt;/a&gt; for that initial market. Yes, it takes effort and no, it’s not perfect—but the quality of your initial price will shape every localized decision you make. Garbage in, garbage out.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-creating-your-own-pricing-index&quot;&gt;2. Creating your own pricing index&lt;/h3&gt;



&lt;p&gt;Once you’ve nailed down your base market pricing, the next step is to build your own pricing index using around ten relevant apps as benchmarks. Be thoughtful about which apps you include. Here’s what to look for:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Apps with proven global success&lt;/li&gt;



&lt;li&gt;Apps that use a similar business model (e.g., if you focus on annual subscriptions, choose others that prioritize annual plans)&lt;/li&gt;



&lt;li&gt;Apps within or adjacent to your category, since pricing dynamics vary by category&lt;/li&gt;



&lt;li&gt;App with a similar target audience&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;I also highly recommend checking out the &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps-2025/&quot;&gt;State of Subscription Apps 2025 Report&lt;/a&gt;. It includes multiple graphs that break down regional and category specific pricing. Keep in mind the data is at a regional level rather than per country, so it’s a great starting point, but not the whole picture.&lt;/p&gt;



&lt;p&gt;To go deeper, you can create a relative pricing table like the one Jacob showcased. According to Jacob, the most accurate method for checking prices across markets is to use a VPN to access local app stores directly. This ensures you’re seeing current rates rather than relying on price-spying tools, which may not always be up to date. &lt;a href=&quot;https://www.retention.blog/p/global-pricing-guidance&quot;&gt;Jacob has also reviewed many major apps and markets on his blog&lt;/a&gt;, which can save you time depending on your category.&lt;/p&gt;



&lt;p&gt;While it might be tempting to only look at big global competitors, make an effort to include local competitors too, even if that means your index looks a bit messier. Local apps may not have the same level of data as Netflix or Spotify, but they’re often much closer to the ground when it comes to understanding local spending power and willingness to pay in your space.&lt;/p&gt;



&lt;p&gt;This might mean reviewing a few more apps per market, but the additional insight will be well worth it, especially if you’re planning to expand into multiple countries.&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;App&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Your Main Market&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Market 2&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Market 3&amp;nbsp;&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Market 4&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;App 1&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;$79&lt;/td&gt;&lt;td&gt;11% cheaper&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;App 2&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;$89&lt;/td&gt;&lt;td&gt;5% cheaper&lt;/td&gt;&lt;td&gt;Same price&lt;/td&gt;&lt;td&gt;72% cheaper&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;App 3&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;$62&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;12% more expensive&lt;/td&gt;&lt;td&gt;64% cheaper&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;…&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;…&lt;/td&gt;&lt;td&gt;…&lt;/td&gt;&lt;td&gt;…&lt;/td&gt;&lt;td&gt;…&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Average&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;$84.32&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;6.80% cheaper&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;11.33% more expensive&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;54 % cheaper&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;&lt;em&gt;Comparison table per app.&amp;nbsp;&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;Feel free to also use Jacob’s guidance as another reference point:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;552&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-3-1024x552.png&quot; alt=&quot;&quot; class=&quot;wp-image-45875&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-3-1024x552.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-3-300x162.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-3-768x414.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-3-1536x828.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-3-50x27.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-3-74x40.png 74w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-3-696x375.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-3-560x302.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-3-549x296.png 549w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-3-840x453.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-3-80x43.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-3-48x26.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-3.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Jacob Rushfinn’s top rule of thumbs for pricing your app&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;I would also advise having up to three tables: iOS, Android, and Web-to-app, as each will have its own prices. I would also recommend creating a secondary table for the local competitors, where you have an overview of the subscription options they offer.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;App&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Your Main Market&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Market 2&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Market 3&amp;nbsp;&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Market 4&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;App 1&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Monthly, Annual&lt;/td&gt;&lt;td&gt;Monthly, Annual&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;App 2&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Annual&lt;/td&gt;&lt;td&gt;Annual&lt;/td&gt;&lt;td&gt;Annual&lt;/td&gt;&lt;td&gt;Weekly, Annua&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;App 3&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Annual, Lifetime&lt;/td&gt;&lt;td&gt;X&lt;/td&gt;&lt;td&gt;Annual, Lifetime&lt;/td&gt;&lt;td&gt;Annual&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;…&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;…&lt;/td&gt;&lt;td&gt;…&lt;/td&gt;&lt;td&gt;…&lt;/td&gt;&lt;td&gt;…&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;You may notice that for certain markets apps offer different options to reflect the purchasing power and behaviour there. I found this in my weekly subscriptions analysis too, in certain regions of the world weekly subscriptions may be more popular than in others.&lt;/p&gt;



&lt;p&gt;You may need to adjust your offering based on your findings. For example, Jacob noticed that &lt;a href=&quot;https://brainimpulse.me/fb_auto/g_initial_preland/store.html?one_link_id=220bb31c&quot;&gt;Impulse&lt;/a&gt;, the brain training app, generally offers weekly, annual, and lifetime subscriptions, but in Brazil, they’ve removed annual. With lower purchasing power, you may want cheaper options. For example, weekly subscriptions can provide almost a trial experience (if weekly is popular in your category and right for your brand).&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-consider-your-costs-nbsp&quot;&gt;3. Consider your costs&amp;nbsp;&lt;/h3&gt;



&lt;p&gt;I work with both apps and e-commerce brands, and one of the things I love most about apps is that, generally speaking, the costs are much lower. This is a huge advantage as it means you can often offer a lower price in a specific market and still maintain a healthy profit margin.&lt;/p&gt;



&lt;p&gt;Before you run off to start any old app, I have to issue a slight disclaimer—talk about a spoilsport, right? Of course, this doesn’t apply to every app, which is why it’s important to take a closer look at your cost structure to understand how much flexibility you actually have. Don’t just consider your app development and platform fees—also factor in local taxes and, crucially, marketing costs in each market.&lt;/p&gt;



&lt;p&gt;A great example of this comes from &lt;a href=&quot;https://flo.health/&quot;&gt;Flo, the period tracking app&lt;/a&gt;. They ran pricing experiments in Brazil, lowering their prices significantly. As &lt;a href=&quot;https://subclub.com/episode/how-to-maximize-revenue-with-regional-pricing-dmitry-gurski-flo&quot;&gt;co-founder Dmitri shared on the &lt;em&gt;Sub Club&lt;/em&gt; podcast&lt;/a&gt;, Brazil eventually became their third-largest market. Despite the lower prices, it was still highly profitable, partly because ad inventory in Brazil was also much cheaper for them at the time.&lt;/p&gt;



&lt;p&gt;This kind of context is key. Even if you’re charging less, your lower operating and acquisition costs in that market might still make it a worthwhile — and profitable — move.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-4-consider-value-for-the-market&quot;&gt;4. Consider value for the market&lt;/h3&gt;



&lt;p&gt;As we’ve seen with companies like Netflix and Duolingo, perceived value plays a big role in pricing, and the same applies to your app. Will users in every market you’re targeting get the same value from your product? If not, you may need to adjust your pricing up or down to reflect that.&lt;/p&gt;



&lt;p&gt;If you’re unsure, the &lt;a href=&quot;https://www.revenuecat.com/blog/growth/guide-to-app-pricing-research-methods/&quot;&gt;Van Westendorp Pricing Model&lt;/a&gt; is a great tool to help determine what price makes sense for each market. It works by asking your target audience four key questions to identify a range of acceptable price points:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;At what price would you consider the product so cheap that you’d question its quality?&lt;/li&gt;



&lt;li&gt;At what price would you consider the product a &lt;strong&gt;bargain&lt;/strong&gt; — a great buy for the money?&lt;/li&gt;



&lt;li&gt;At what price would you consider the product &lt;strong&gt;starting to get expensive&lt;/strong&gt;, but still worth it?&lt;/li&gt;



&lt;li&gt;At what price would you consider the product &lt;strong&gt;too expensive&lt;/strong&gt; to consider?&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;This gives you a clearer picture of what your users are actually willing to pay and helps ensure your prices align with perceived value, market by market.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;696&quot; height=&quot;348&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image.png&quot; alt=&quot;&quot; class=&quot;wp-image-45869&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-300x150.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-50x25.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-80x40.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-560x280.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/image-48x24.png 48w&quot; sizes=&quot;auto, (max-width: 696px) 100vw, 696px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Range of acceptable prices to charge&amp;nbsp;&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-5-experiment-with-adjusting-the-price&quot;&gt;5. Experiment with adjusting the price&lt;/h3&gt;



&lt;p&gt;From there, you’ll want to run tests on setting and adjusting the price in your new markets (assuming you have a large enough sample size). This can be incredibly impactful: &lt;a href=&quot;https://subclub.com/episode/how-to-maximize-revenue-with-regional-pricing-dmitry-gurski-flo&quot;&gt;Flo has focused a lot on optimizing their prices&lt;/a&gt; recently. The result? In the past year, they saw 45% overall growth, which came from 35% in English-speaking markets, and 80% in non-English-speaking markets.&lt;/p&gt;



&lt;p&gt;We’re not going to dive deep into the technical setup of these tests here, but Jacob shares a few important considerations to keep in mind:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Be mindful of &lt;/strong&gt;&lt;a href=&quot;https://support.apple.com/en-gb/109501&quot;&gt;&lt;strong&gt;Apple’s pricing rules&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;.&lt;/strong&gt; If your price increase exceeds their set thresholds, existing users will need to opt in again, which can lead to higher churn during tests.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Don’t stress too much about user backlash. &lt;/strong&gt;Most users don’t notice pricing tests as much as you might think. If you’re getting internal resistance, start with a low-risk country to prove the waters are calm before expanding tests to larger markets.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;What about legacy prices?&lt;/strong&gt; Jacob recommends keeping them in place for simplicity. In many cases, moving users to a new price point can trigger more churn than it’s worth. If you &lt;em&gt;do&lt;/em&gt; decide to migrate users, and it’s a significant price change, &lt;a href=&quot;https://www.revenuecat.com/blog/growth/how-to-raise-app-prices-effectively/&quot;&gt;invest time in clear, thoughtful communication to ease the transition.&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;When it comes to &lt;a href=&quot;https://www.revenuecat.com/blog/engineering/price-testing-for-mobile-apps/&quot;&gt;measuring the success of pricing experiments&lt;/a&gt;, take the long view. Make sure you’re evaluating the &lt;strong&gt;lifetime value (LTV)&lt;/strong&gt; impact of changes, not just conversion to paid. You’ll also want to track active, churned, and refunded subscribers. Tools like &lt;a href=&quot;http://www.revenuecat.com/feature/experiments&quot;&gt;RevenueCat Experiments&lt;/a&gt; can help make this possible.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-start-experimenting-with-localized-prices&quot;&gt;Start experimenting with localized prices&lt;/h2&gt;



&lt;p&gt;There you have it: the ultimate guide to price localization. A huge thanks to Jacob Rushfinn for his incredible webinar that inspired this article in the first place. If you’re ready to start optimizing your prices by market (whether you’re just starting to expand or improving your current setup), here’s your checklist:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Identify your top potential international market&lt;/li&gt;



&lt;li&gt;If you have the data, check where the conversion rate is lagging compared to your main market&lt;/li&gt;



&lt;li&gt;Ensure your main market’s price is optimized, as it’ll serve as your benchmark&lt;/li&gt;



&lt;li&gt;Research both international and local competitors to see how they’re pricing in those markets&lt;/li&gt;



&lt;li&gt;Explore package options per market to see if adjustments are needed (e.g., adding a weekly or monthly option for lower purchasing-power regions)&lt;/li&gt;



&lt;li&gt;Review costs per market, including marketing, to understand how much flexibility you have&lt;/li&gt;



&lt;li&gt;Assess perceived value in each market, and if needed, conduct pricing research to validate assumptions&lt;/li&gt;



&lt;li&gt;Test adjusting your prices and review the long-term impact, not just the immediate conversion lifts&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Price is such an impactful growth lever that it shouldn’t be underestimated. While it takes some upfront work to get it right, the payoff in scaling your app internationally can be significant, &lt;a href=&quot;https://www.revenuecat.com/blog/growth/is-localization-the-next-great-growth-opportunity-for-subscription-apps/&quot;&gt;especially as certain markets continue to grow rapidly&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;Now, when you get charged those $12 for a bottle of water in the airport, you’ll at least know this technique works in apps too!&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[The post-attribution playbook: Eric Seufert on fixing measurement and scaling growth]]></title><description><![CDATA[Why broken measurement hurts growth more than bad ads]]></description><link>https://www.revenuecat.com/blog/growth/eric-seufert-sub-club-podcast-2025/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/eric-seufert-sub-club-podcast-2025/</guid><pubDate>Wed, 03 Sep 2025 09:54:27 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/eric-seufert-sub-club-podcast-2025.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;&lt;em&gt;Don’t miss an episode: Subscribe to the podcast on &lt;a href=&quot;https://www.youtube.com/@SubClubPodcast?sub_confirmation=1&quot;&gt;YouTube&lt;/a&gt;, &lt;a href=&quot;https://podcasts.apple.com/us/podcast/sub-club-by-revenuecat/id1538057974&quot;&gt;Apple&lt;/a&gt;, and &lt;a href=&quot;https://open.spotify.com/show/6jmxautTyDTjwqRYyg9BXF&quot;&gt;Spotify&lt;/a&gt;. &lt;/em&gt;&lt;/p&gt;


&lt;div class=&quot;lazyblock-dd0db17b8671-Z1Xj5ur wp-block-lazyblock-dd0db17b8671&quot;&gt;&lt;blogpostpodcastcta title=&quot;Sub Club by RevenueCat&quot; description=&quot;Interviews and playbooks from the minds behind the world&apos;s biggest apps.&quot; links=&quot;[{&amp;quot;link-title&amp;quot;:&amp;quot;Apple Podcasts&amp;quot;,&amp;quot;link-url&amp;quot;:&amp;quot;https:\/\/podcasts.apple.com\/gb\/podcast\/sub-club-by-revenuecat\/id1538057974&amp;quot;,&amp;quot;link-image&amp;quot;:&amp;quot;apple-podcasts&amp;quot;},{&amp;quot;link-title&amp;quot;:&amp;quot;Spotify&amp;quot;,&amp;quot;link-url&amp;quot;:&amp;quot;https:\/\/open.spotify.com\/show\/6jmxautTyDTjwqRYyg9BXF?si=dac199d927a54ac6&amp;quot;,&amp;quot;link-image&amp;quot;:&amp;quot;spotify&amp;quot;},{&amp;quot;link-title&amp;quot;:&amp;quot;YouTube&amp;quot;,&amp;quot;link-url&amp;quot;:&amp;quot;https:\/\/www.youtube.com\/@SubClubPodcast?sub_confirmation=1&amp;quot;,&amp;quot;link-image&amp;quot;:&amp;quot;youtube&amp;quot;}]&quot;&gt;
&lt;/blogpostpodcastcta&gt;&lt;/div&gt;


&lt;p&gt;What’s the best way to optimize your ROAS when marketing your app? This is the perennial question in app marketing, and there’s no one right answer. But people like &lt;a href=&quot;https://www.linkedin.com/in/ericseufert/&quot;&gt;Eric Seufert&lt;/a&gt; can help you find the right approach for your app business.&lt;/p&gt;



&lt;p&gt;Eric is a quantitative marketer, media strategist, investor, and author who advises app businesses on the latest trends and tools in app marketing, helping teams optimize their ROAS and business growth. On this week’s episode of Sub Club, we asked Eric your burning questions about how to effectively measure ad performance, avoid common pitfalls in app marketing, and interpret the results of creative testing.&lt;/p&gt;



&lt;iframe loading=&quot;lazy&quot; width=&quot;100%&quot; height=&quot;180&quot; frameborder=&quot;no&quot; scrolling=&quot;no&quot; seamless=&quot;&quot; src=&quot;https://share.transistor.fm/e/25717daf?color=FFFFFF&amp;amp;background=30343C&quot;&gt;&lt;/iframe&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;The Post-Attribution Playbook for Growth — Eric Seufert, Mobile Dev Memo&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/0dZ-wwsNLWY?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-risky-is-it-to-put-80-of-ad-spend-into-meta-and-google&quot;&gt;&lt;strong&gt;How risky is it to put 80% of ad spend into Meta and Google?&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;You may think putting most of your ad spend into one or two big ad channels is risky, but according to Eric, diversity for diversity’s sake isn’t necessarily a good thing. “I think people feel compelled to diversify because they have this sort of abstract notion that being totally concentrated in one or two channels is a bad thing,” he said. “And yeah, there’s risk there, but the reality is that diversifying adds a lot of overhead.”&lt;/p&gt;



&lt;p&gt;Eric’s advice? If you want to diversify your ad spend, do so strategically. Don’t just optimize for ROAS, but for &lt;em&gt;spend-adjusted&lt;/em&gt; ROAS. And follow a waterfall method to allocate your ad spend:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Max out the biggest channel until it hits your ROAS threshold.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Max out the second-biggest channel (which has a smaller spend limit) until it hits your ROAS threshold.&lt;/li&gt;



&lt;li&gt;Max out the third-biggest channel (which has a smaller spend limit) until it hits your ROAS threshold.&lt;/li&gt;



&lt;li&gt;And so on.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;This approach minimizes overhead and complexity, while allowing you to diversify across ad channels with less risk.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-s-the-biggest-pitfall-you-see-across-growth-teams-right-now&quot;&gt;&lt;strong&gt;What’s the biggest pitfall you see across growth teams right now?&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;According to Eric, the biggest problem facing growth marketing teams today is what he calls &lt;em&gt;measurement disorganization&lt;/em&gt;. “The thing that I see most commonly is a very chaotic approach to measurement, just lacking any sort of coherency,” he said. “I see people using competing tools, essentially not really knowing which one to trust or how to interpret the output of one relative to the other, [or people] having a bunch of tools that aren’t working in concert — they’re just a couple different data points, I don’t know how to interpret them as an ensemble.” &lt;/p&gt;



&lt;p&gt;Unfortunately, the solution for this problem isn’t an easy one: it involves sitting down with stakeholders and coming up with a measurement plan that satisfies everyone. As Eric puts it, “Your measurement system is essentially the heartbeat of the company — everything flows from that, and you really need to be doing it correctly and in a way that … everyone understands and appreciates.”&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-do-you-balance-speed-versus-accuracy-and-make-confident-decisions-with-incomplete-data&quot;&gt;&lt;strong&gt;How do you balance speed versus accuracy and make confident decisions with incomplete data?&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Eric’s advice on this one is pretty straightforward: “The way I approach creative testing is trying to identify losers as quickly as possible. The winners take time to prove out, but the losers are pretty quick to prove out,” he said. So what does that look like? &lt;/p&gt;



&lt;p&gt;Especially in the early days after launching an app, it’s impossible to know terminal LTV or incrementality — so the best approach is to slowly, methodically increase your ad spend in the right places as you gather more data. If a certain creative is obviously not a winner, kill it immediately (at best, it will perform at the average, but it won’t grow your ad spend), and let the apparent winners age to see how they perform over time. Track ROAS for each cohort at day 20, 30, 50, and so on, and increase your budget frontier as it makes sense. This data-driven approach takes the guesswork out of ad spend decision-making and lets teams iterate quickly on what works.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-conclusion&quot;&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;These are just a few of the great questions listeners submitted. To hear our full conversation with Eric, &lt;a href=&quot;https://subclub.com/episode/the-post-attribution-playbook-for-growth-eric-seufert-mobile-dev-memo&quot;&gt;listen to the full episode&lt;/a&gt; wherever you get your podcasts.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Introducing RevenueCat MCP]]></title><description><![CDATA[Manage subscriptions through AI with RevenueCat’s new MCP server.]]></description><link>https://www.revenuecat.com/blog/company/introducing-revenuecat-mcp/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/company/introducing-revenuecat-mcp/</guid><pubDate>Mon, 01 Sep 2025 09:42:45 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Blog_Cover_RevenueCat-MCP.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Today, we’re launching the &lt;strong&gt;RevenueCat MCP Server&lt;/strong&gt;, now in public beta. For the first time, you can create and manage your subscription configurations directly through your AI assistant using natural language, no dashboard navigation required.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-is-the-revenuecat-mcp-server&quot;&gt;What is the RevenueCat MCP server?&lt;/h2&gt;



&lt;p&gt;The RevenueCat MCP Server is built on the &lt;a href=&quot;https://modelcontextprotocol.io/&quot;&gt;Model Context Protocol (MCP)&lt;/a&gt;, an open standard that enables AI assistants to securely interact with external tools and services. MCP has quickly become the gold standard for AI integrations, with platforms like Supabase, Linear, and Vercel already shipping their own MCP servers.&lt;/p&gt;



&lt;p&gt;RevenueCat’s implementation makes us the first subscription management platform to offer AI-native configuration, letting developers and product teams manage subscription setups through simple conversations with their preferred AI assistant.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-build-an-mcp-server&quot;&gt;Why build an MCP server?&lt;/h2&gt;



&lt;p&gt;As AI tools like Claude Code, Cursor, and GitHub Copilot become essential to development workflows, we noticed developers constantly switching between their AI assistants and the RevenueCat dashboard to configure subscription products, set up entitlements, and manage offerings across multiple platforms.&lt;/p&gt;



&lt;p&gt;With our MCP server, that context-switching disappears. Your AI assistant can now:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Create subscription products in RevenueCat across iOS, Android, Amazon, Stripe, and Roku&lt;/li&gt;



&lt;li&gt;Configure entitlements and link them to products&lt;/li&gt;



&lt;li&gt;Set up complex offering hierarchies with standardized naming&lt;/li&gt;



&lt;li&gt;Manage cross-platform subscription configurations&lt;/li&gt;



&lt;li&gt;Generate paywalls &lt;/li&gt;



&lt;li&gt;All through natural language, all within your existing AI workflow&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Imagine setting up a complete subscription hierarchy, from app creation to paywall generation, just by describing what you want to your AI assistant.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-you-can-do-with-revenuecat-mcp&quot;&gt;What you can do with RevenueCat MCP&lt;/h2&gt;



&lt;figure class=&quot;wp-block-embed is-type-wp-embed is-provider-wistia-inc wp-block-embed-wistia-inc&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; class=&quot;wp-embedded-content&quot; sandbox=&quot;allow-scripts&quot; security=&quot;restricted&quot; title=&quot;MCP-Web Video&quot; src=&quot;https://fast.wistia.net/embed/iframe/q2na8mwo8e?dnt=1#?secret=zBIuqbvu49&quot; data-secret=&quot;zBIuqbvu49&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; width=&quot;500&quot; height=&quot;310&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;With RevenueCat MCP, your AI assistant can:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Create products&lt;/strong&gt; — “Create a premium monthly subscription for iOS and Android.”&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Manage entitlements&lt;/strong&gt; — “Attach &lt;code&gt;premium_monthly&lt;/code&gt; to the &lt;code&gt;premium_features&lt;/code&gt; entitlement.”&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Configure offerings&lt;/strong&gt; — “Set up &lt;code&gt;main_offering&lt;/code&gt; with &lt;code&gt;$rc_monthly&lt;/code&gt; and &lt;code&gt;$rc_annual&lt;/code&gt; packages.”&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Generate paywalls&lt;/strong&gt; — “Create a paywall for &lt;code&gt;main_offering&lt;/code&gt;.”&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Run multi-step setups&lt;/strong&gt; — “Create an app, add products, and attach them to entitlements, one command.”&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Everything happens in real time, within your AI tool, with no need to navigate the RevenueCat dashboard.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-to-connect-to-revenuecat-mcp&quot;&gt;How to connect to RevenueCat MCP&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;640&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Blog-Visual_RevenueCat-MCP-1024x640.png&quot; alt=&quot;&quot; class=&quot;wp-image-45821&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Blog-Visual_RevenueCat-MCP-1024x640.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Blog-Visual_RevenueCat-MCP-300x188.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Blog-Visual_RevenueCat-MCP-768x480.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Blog-Visual_RevenueCat-MCP-1536x961.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Blog-Visual_RevenueCat-MCP-2048x1281.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Blog-Visual_RevenueCat-MCP-50x31.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Blog-Visual_RevenueCat-MCP-64x40.png 64w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Blog-Visual_RevenueCat-MCP-696x435.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Blog-Visual_RevenueCat-MCP-560x350.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Blog-Visual_RevenueCat-MCP-473x296.png 473w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Blog-Visual_RevenueCat-MCP-755x472.png 755w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Blog-Visual_RevenueCat-MCP-80x50.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/09/Blog-Visual_RevenueCat-MCP-48x30.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Setting up RevenueCat’s MCP server takes just seconds. Here’s how to connect it to popular AI clients:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-cloud-mcp-server-recommended&quot;&gt;Cloud MCP server (recommended)&lt;/h3&gt;



&lt;p&gt;Endpoint: &lt;code&gt;https://mcp.revenuecat.ai/mcp&lt;/code&gt;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Example: Claude Code&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Simply add the server via the &lt;code&gt;claude&lt;/code&gt; CLI command:&lt;/p&gt;



&lt;pre class=&quot;wp-block-code&quot;&gt;&lt;code&gt;claude mcp add --transport http revenuecat https://mcp.revenuecat.ai/mcp --header &quot;Authorization: Bearer YOUR_API_V2_SECRET_KEY&quot;&lt;/code&gt;&lt;/pre&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;using-with-cursor&quot;&gt;Using with Cursor&lt;/h3&gt;



&lt;p&gt;You can add the MCP server to Cursor with a single click:&lt;/p&gt;



&lt;div class=&quot;wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex&quot;&gt;
&lt;div class=&quot;wp-block-button&quot;&gt;&lt;a class=&quot;wp-block-button__link wp-element-button&quot; href=&quot;https://cursor.com/en/install-mcp?name=revenuecat&amp;amp;config=eyJ1cmwiOiJodHRwczovL21jcC5yZXZlbnVlY2F0LmFpL21jcCJ9&quot;&gt;Add to Cursor&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;That’s it, no CLI or manual configuration required. Just click, connect, and start creating subscriptions directly from Cursor. For more examples (Claude, VS Code, and other MCP-compatible clients), check out our &lt;a href=&quot;https://www.revenuecat.com/docs/tools/mcp/overview?utm_source=chatgpt.com&quot;&gt;documentation&lt;/a&gt;.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;authentication-options&quot;&gt;Authentication Options&lt;/h3&gt;



&lt;p&gt;RevenueCat MCP Server supports two authentication methods:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;API v2 Secret Key:&lt;/strong&gt; Use a scoped key (read-only or write-enabled) with Bearer authentication.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;OAuth:&lt;/strong&gt; For supported clients, connect without managing keys directly.&lt;/li&gt;
&lt;/ul&gt;



&lt;h4 class=&quot;wp-block-heading&quot;&gt;&lt;strong&gt;OAuth Authentication Support&lt;/strong&gt;&lt;/h4&gt;



&lt;p&gt;RevenueCat MCP Server also supports OAuth authentication for supported clients.&lt;/p&gt;



&lt;p&gt;Currently supported:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Visual Studio Code&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Cursor&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Claude Code&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;🔧 &lt;strong&gt;Third-Party Integration:&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;If you’d like to integrate your service with RevenueCat MCP Server using OAuth, please contact &lt;a href=&quot;mailto:support@revenuecat.com&quot;&gt;RevenueCat Support&lt;/a&gt; as well as &lt;a href=&quot;mailto:partnerships@revenuecat.com&quot;&gt;Partnerships&lt;/a&gt; so we can set up OAuth clients for your application.&lt;/p&gt;



&lt;p&gt;For examples of both OAuth and secret key authentication across different AI clients, see our &lt;a href=&quot;https://www.revenuecat.com/docs/tools/mcp/overview?utm_source=chatgpt.com&quot;&gt;documentation&lt;/a&gt;.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;built-for-security-and-collaboration&quot;&gt;Built for security and collaboration&lt;/h2&gt;



&lt;p&gt;RevenueCat MCP follows protocol best practices:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Scoped API v2 keys&lt;/strong&gt; — read-only or write-enabled as needed&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;HTTPS + Bearer authentication&lt;/strong&gt; for all requests&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Audit logging&lt;/strong&gt; for every change&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Separate keys per environment&lt;/strong&gt; and rotate regularly&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Remember: connecting an AI client to RevenueCat MCP grants it the same API access as your key. Only use trusted clients and review permissions before approving connections.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;current-beta-limitations&quot;&gt;Current beta limitations&lt;/h2&gt;



&lt;p&gt;RevenueCat MCP lets you create products in your RevenueCat project configuration only.&lt;/p&gt;



&lt;p&gt;It does &lt;em&gt;not&lt;/em&gt; currently create products directly in App Store Connect, Google Play Console, or other external stores:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;iOS:&lt;/strong&gt; You can export configurations to App Store Connect, but pricing setup isn’t yet supported.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Android:&lt;/strong&gt; Export is not yet available.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Other platforms (Amazon, Roku, Stripe):&lt;/strong&gt; Configuration is supported in RevenueCat only.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;We’re actively working on tighter store integrations, but we want to be clear: today’s MCP release is about configuring your RevenueCat project, not directly publishing to app stores.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;start-using-revenuecat-mcp&quot;&gt;Start using RevenueCat MCP&lt;/h2&gt;



&lt;p&gt;Start using RevenueCat MCP today and bring subscription management directly into your AI-powered workflow. Build faster and ship with fewer clicks. Here’s how to get started:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Generate API v2 Key&lt;/strong&gt;: Create a new API v2 secret key in your RevenueCat dashboard&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Configure your AI&lt;/strong&gt;: Add our MCP server to Claude, VS Code, Cursor, or any MCP-compatible client&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Start creating&lt;/strong&gt;: Tell your AI what subscription setup you need and watch the magic happen&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;&lt;strong&gt;Quick Links:&lt;/strong&gt;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Documentation&lt;/strong&gt;: &lt;a href=&quot;https://www.revenuecat.com/docs/tools/mcp/overview&quot;&gt;https://www.revenuecat.com/docs/tools/mcp/overview&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;MCP Server URL&lt;/strong&gt;: &lt;code&gt;https://mcp.revenuecat.ai/mcp&lt;/code&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Community Support&lt;/strong&gt;: &lt;a href=&quot;https://community.revenuecat.com/&quot;&gt;community.revenuecat.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;strong&gt;Join the Beta:&lt;/strong&gt; Have feedback or feature requests? We’d love to hear from you through our community forums or direct support channels.&lt;/p&gt;



&lt;p&gt;Ready to manage subscriptions through AI? &lt;a href=&quot;https://www.revenuecat.com/docs/tools/mcp/overview&quot;&gt;Get started with RevenueCat MCP →&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Here’s the full lineup for App Growth Annual 2025]]></title><description><![CDATA[Three keynotes, four talks, 24 workshops, competitions, prizes, and more besides. Are you signed up?]]></description><link>https://www.revenuecat.com/blog/company/app-growth-annual-2025-lineup/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/company/app-growth-annual-2025-lineup/</guid><pubDate>Fri, 29 Aug 2025 13:05:01 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/raga-25-lineup-all.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;App Growth Annual returns on &lt;strong&gt;October 14, 2025&lt;/strong&gt;, at &lt;strong&gt;&lt;a href=&quot;https://www.theglasshouses.com/&quot;&gt;The Glasshouse&lt;/a&gt;, New York City&lt;/strong&gt; (with a global virtual audience), and the lineup is stacked.&lt;/p&gt;



&lt;p&gt;This year’s lineup spans headline keynotes, tactical talks, indie founder stories, and more than 20 workshops led by practitioners who’ve scaled top apps. Expect actionable tactics on paywalls, pricing, user acquisition, retention, and growth — plus the chance to connect with peers building the next generation of subscription businesses.&lt;/p&gt;



&lt;p&gt;And there’s plenty more beyond the sessions, and even beyond the day itself. App Growth Annual also brings back the &lt;strong&gt;Shippies × Shipaton Awards&lt;/strong&gt;, the &lt;strong&gt;World Paywall Speed-Building Championship&lt;/strong&gt; finals, and the launch of &lt;strong&gt;New York App Week&lt;/strong&gt;: a citywide run of meetups, dinners, and micro-events. If you’re planning to be there in person, think of it as a &lt;em&gt;whole week&lt;/em&gt; of good times.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://rev.cat/raga-reg&quot;&gt;&lt;strong&gt;Apply for in-person tickets&lt;/strong&gt;&lt;/a&gt; (spaces limited) | &lt;a href=&quot;https://rev.cat/ragavirtual-reg&quot;&gt;&lt;strong&gt;Register for virtual (free)&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-highlights-beyond-the-stage&quot;&gt;&lt;strong&gt;Highlights beyond the stage&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Let’s start here, because App Growth Annual isn’t just about talks and workshops. This year, we’re bringing back — and leveling up — the other events that make it such a unique gathering.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-shippies-shipaton-awards&quot;&gt;The Shippies × Shipaton Awards&lt;/h3&gt;



&lt;p&gt;&lt;a href=&quot;/blog/company/shippies-2025-app-growth-awards/&quot;&gt;The Shippies are back&lt;/a&gt; — our awards for the most impactful subscription apps. Last year we celebrated winners like Inkitt, Arnold Schwarzenegger’s The Pump, Lose It!, Zumba, HER, and Shotsy. &lt;/p&gt;



&lt;p&gt;For 2025 we’re going bigger:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Winners announced live on stage in New York, October 14&lt;/li&gt;



&lt;li&gt;Every winning app featured on a &lt;strong&gt;Times Square billboard&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;Spotlights across RevenueCat’s channels&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;And this year’s award show will be hosted by &lt;a href=&quot;https://www.revenuecat.com/blog/author/hannah-parvaz/&quot;&gt;Hannah Parvaz&lt;/a&gt;! Founder of Aperture, multi-award-winning marketer, coach and mentor, and 2019 App Marketer of the Year.&lt;/p&gt;



&lt;p&gt;Award categories include best onboarding, best paywall, best churn reduction, best monetization, best new app, and best solo indie app. &lt;a href=&quot;https://form.typeform.com/to/wffvBJvx?typeform-source=lnkd.in&quot;&gt;&lt;strong&gt;Apply by September 15&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-new-york-app-week-oct-13-16&quot;&gt;New York App Week (Oct 13–16)&lt;/h3&gt;



&lt;p&gt;For four days, New York City becomes the hub for app growth. Alongside App Growth Annual you’ll find meetups, dinners, parties, and micro-events — each tight, useful, and designed to give builders one tangible takeaway.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;Highlights already confirmed include an &lt;strong&gt;early morning run&lt;/strong&gt; with fellow app builders and a &lt;strong&gt;dinner connecting app sellers and buyers&lt;/strong&gt; (hosted by &lt;a href=&quot;https://www.linkedin.com/in/evelinherrera/&quot;&gt;Evelin Herrera&lt;/a&gt;). More events will be announced soon.&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Want to host or co-host? We’ll fund selected events with micro-grants and promote them to our 150K+ audience and 300 in-person attendees. &lt;a href=&quot;http://appweek.events/&quot;&gt;&lt;strong&gt;Pitch your event here&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-world-paywall-speed-building-championship-2025&quot;&gt;World Paywall Speed-Building Championship 2025&lt;/h3&gt;



&lt;p&gt;Equal parts hackathon, e-sports, and WWE spectacle, the &lt;strong&gt;&lt;a href=&quot;https://revenuecatpaywallsworldchamps.devpost.com/&quot;&gt;World Paywall Speed-Building Championship&lt;/a&gt;&lt;/strong&gt; pits the fastest, most precise builders against each other using RevenueCat Paywalls.&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Qualifiers run online — the top five finalists get an &lt;strong&gt;all-expenses-paid trip to NYC&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;The grand finals take place live on stage at App Growth Annual&lt;/li&gt;



&lt;li&gt;The winner takes home &lt;strong&gt;$5,000 USD, a custom title belt, and a Times Square billboard spotlight&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Come for the chaos. Stay for the cash.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-keynotes&quot;&gt;Keynotes&lt;/h2&gt;



&lt;p&gt;Now onto the main event! And for those joining us virtually: all of our keynotes and main stage talks will be livestreamed. &lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-natalia-castillejo&quot;&gt;Natalia Castillejo&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;&lt;strong&gt;From free to paid: Lessons in value creation at Duolingo&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Castillejo-raga-1024x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-45813&quot; style=&quot;width:414px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Castillejo-raga-1024x1024.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Castillejo-raga-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Castillejo-raga-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Castillejo-raga-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Castillejo-raga-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Castillejo-raga-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Castillejo-raga-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Castillejo-raga-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Castillejo-raga-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Castillejo-raga-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Castillejo-raga-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Castillejo-raga-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Castillejo-raga-48x48.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Castillejo-raga.png 1080w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;a href=&quot;https://www.linkedin.com/in/natic/&quot;&gt;Natalia Castillejo&lt;/a&gt;, Director of Product at Duolingo, will be leading our keynote lineup.&lt;/p&gt;



&lt;p&gt;How do you build a product that millions use for free and still create a subscription people choose to pay for? In this talk, Duolingo’s Natalia Castillejo shares how the team built 0→1 learning features, launched Duolingo Max (the newest premium tier), and balanced business growth with real learner value—offering practical lessons for anyone building freemium products.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;greg-stewart&quot;&gt;Greg Stewart&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;Standing out in a crowded space — How Ladder became the #1 grossing fitness app in the US&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1080&quot; height=&quot;1080&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/greg-raga.png&quot; alt=&quot;&quot; class=&quot;wp-image-45697&quot; style=&quot;width:414px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/greg-raga.png 1080w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/greg-raga-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/greg-raga-1024x1024.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/greg-raga-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/greg-raga-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/greg-raga-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/greg-raga-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/greg-raga-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/greg-raga-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/greg-raga-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/greg-raga-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/greg-raga-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/greg-raga-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/greg-raga-48x48.png 48w&quot; sizes=&quot;auto, (max-width: 1080px) 100vw, 1080px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;In one of mobile’s most competitive markets, Ladder has done what seemed impossible: climbing to #1 on the US App Store’s top grossing fitness charts. In this keynote, CEO &lt;a href=&quot;https://www.linkedin.com/in/gregoryfstewart/&quot;&gt;Greg Stewart&lt;/a&gt; shares a series of stories and strategies behind that growth, from product decisions that drive retention to marketing plays that cut through the noise. You’ll leave with practical lessons on differentiation, growth, and brand-building you can apply to your own app, no matter the category.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;michael-ribero&quot;&gt;Michael Ribero&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;Beyond the paywall — bundling, pricing, and post-purchase upsells (Sub Club podcast live)&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ribero-raga-1024x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-45702&quot; style=&quot;width:414px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ribero-raga-1024x1024.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ribero-raga-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ribero-raga-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ribero-raga-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ribero-raga-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ribero-raga-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ribero-raga-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ribero-raga-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ribero-raga-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ribero-raga-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ribero-raga-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ribero-raga-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ribero-raga-48x48.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ribero-raga.png 1080w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Traditional media seems like the last place to look for app growth insights, but &lt;a href=&quot;https://www.linkedin.com/in/michael-ribero/&quot;&gt;Michael Ribero&lt;/a&gt; helped turn The Washington Post, Vogue, and The New Yorker into digital subscription powerhouses using tactics any app can steal. Join Michael and Sub Club host David Barnard for a conversation about maximizing LTV with post-purchase upsells, the bundle/unbundle/re-bundle playbook, replacing search traffic, and so much more.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-jacob-eiting&quot;&gt;Jacob Eiting&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;RevenueCat product keynote&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;I’ll wrap up the day by connecting the themes from across App Growth Annual back to RevenueCat’s mission: helping developers make more money. Expect a mix of reflections on the state of subscription apps, a look at where growth opportunities really lie, and a preview of what we’re building next. From new product reveals and live demos to behind-the-scenes context, I’ll share how we’re continuing to support developers with the tools, data, and infrastructure to build sustainable businesses.&lt;/p&gt;



&lt;p&gt;Get a taste by checking out my closing keynote from last year’s event, which included our &lt;a href=&quot;/blog/company/dipsea-acquisition-announcement/&quot;&gt;spicy acquisition news&lt;/a&gt;:&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;Closing keynote: RevenueCat’s mission, future roadmap, and our spicy new acquisition&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/nRu6giYYbDQ?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-main-stage-talks&quot;&gt;Main stage talks&lt;/h2&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;steve-p-young&quot;&gt;Steve P. Young&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;Growth hack or black hat? Shedding light on questionable app growth strategies&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/steve-young-raga-1024x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-45704&quot; style=&quot;width:414px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/steve-young-raga-1024x1024.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/steve-young-raga-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/steve-young-raga-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/steve-young-raga-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/steve-young-raga-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/steve-young-raga-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/steve-young-raga-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/steve-young-raga-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/steve-young-raga-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/steve-young-raga-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/steve-young-raga-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/steve-young-raga-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/steve-young-raga-48x48.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/steve-young-raga.png 1080w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Are you willing to break the rules to succeed? In this talk, &lt;a href=&quot;https://www.linkedin.com/in/stevepyoung/&quot;&gt;Steve P. Young&lt;/a&gt; — founder of App Masters — exposes the hidden black hat strategies top apps use to climb the charts, revealing the controversial growth tactics big companies don’t want you to know. You’ll leave seeing app marketing in a whole new light.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;danielle-goryl&quot;&gt;Danielle Goryl&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;The risks and rewards of paywalling a previously free feature — lessons from Lose It!&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/goryl-raga-1024x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-45706&quot; style=&quot;width:414px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/goryl-raga-1024x1024.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/goryl-raga-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/goryl-raga-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/goryl-raga-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/goryl-raga-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/goryl-raga-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/goryl-raga-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/goryl-raga-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/goryl-raga-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/goryl-raga-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/goryl-raga-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/goryl-raga-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/goryl-raga-48x48.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/goryl-raga.png 1080w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;What happens when a monetization experiment shows early promise but creates unexpected challenges over time? Join &lt;a href=&quot;https://www.linkedin.com/in/danielle-goryl-3324a8b/&quot;&gt;Danielle Goryl&lt;/a&gt;, VP of Growth Marketing at Lose It!, as she shares what happened when moving a key feature behind the paywall delivered positive results on iOS but longer-term issues on Android. Learn how Lose It! moved away from platform parity, experimented with new approaches to find the right solution, and addressed the ratings impact from the original decision. This candid session offers practical insights into adapting strategy across platforms and finding the balance between monetization and user experience.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-indie-stage-talks&quot;&gt;Indie stage talks&lt;/h2&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;emmanuel-crouvisier&quot;&gt;Emmanuel Crouvisier&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;Rev-share partnerships — how to grow with creators and communities&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/emmanuel-raga-1024x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-45708&quot; style=&quot;width:414px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/emmanuel-raga-1024x1024.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/emmanuel-raga-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/emmanuel-raga-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/emmanuel-raga-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/emmanuel-raga-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/emmanuel-raga-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/emmanuel-raga-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/emmanuel-raga-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/emmanuel-raga-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/emmanuel-raga-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/emmanuel-raga-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/emmanuel-raga-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/emmanuel-raga-48x48.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/emmanuel-raga.png 1080w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The online world has shifted, with users turning to creators and communities for advice and buying decisions. That makes them the perfect place to share your app — but how do you do it without it feeling like an ad or “selling out”? &lt;a href=&quot;https://www.linkedin.com/in/emcro/&quot;&gt;Emmanuel Crouvisier&lt;/a&gt;, founder of CardPointers, will share how he’s used rev-share partnerships to build win-win relationships with creators and communities, turning them into a powerful growth channel.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;aja-beckett&quot;&gt;Aja Beckett&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;From indie side project to $2M in funding — lessons from growing Shotsy&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/aja-raga-1024x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-45710&quot; style=&quot;width:414px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/aja-raga-1024x1024.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/aja-raga-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/aja-raga-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/aja-raga-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/aja-raga-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/aja-raga-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/aja-raga-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/aja-raga-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/aja-raga-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/aja-raga-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/aja-raga-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/aja-raga-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/aja-raga-48x48.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/aja-raga.png 1080w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;What does it take to go from tinkering on a side project to building the most-trusted health tracking app for people GLP-1 medications like Ozempic and Mounjaro… and then raising $2M in venture funding? In this talk, Aja Beckett shares lessons from her journey: the scrappy indie years, deciding when (and why) to raise capital, and what VCs really look for. She’ll cover the pros and cons of staying indie vs. raising, what changed once Shotsy had funding, and the unexpected lessons along the way. Perfect for indie founders wondering if they should take the leap.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-workshops&quot;&gt;Workshops&lt;/h2&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;eric-crowley&quot;&gt;Eric Crowley&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;From investment to exit — tactics for raising capital and selling your app&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/crowley-raga-1024x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-45712&quot; style=&quot;width:414px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/crowley-raga-1024x1024.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/crowley-raga-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/crowley-raga-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/crowley-raga-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/crowley-raga-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/crowley-raga-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/crowley-raga-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/crowley-raga-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/crowley-raga-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/crowley-raga-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/crowley-raga-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/crowley-raga-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/crowley-raga-48x48.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/crowley-raga.png 1080w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Thinking about raising capital or preparing your app for acquisition? In this workshop, &lt;a href=&quot;https://www.linkedin.com/in/crowleyeric/&quot;&gt;Eric Crowley&lt;/a&gt; — partner at GP Bullhound and head of the Consumer Subscription Software practice — shares the playbook he’s used advising companies like Runna (sold to Strava) and Flo (secured a $225M investment at a $1B+ valuation). You’ll learn how to position your business for investors and buyers, track the metrics that matter, and run financial diligence with confidence. You’ll leave ready to navigate your next fundraising round or exit.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;vahe-bagdasaryan&quot;&gt;Vahe Bagdasaryan&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;Roast my paywall — quick wins to boost conversions&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vahe-raga-1024x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-45742&quot; style=&quot;width:414px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vahe-raga-1024x1024.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vahe-raga-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vahe-raga-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vahe-raga-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vahe-raga-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vahe-raga-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vahe-raga-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vahe-raga-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vahe-raga-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vahe-raga-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vahe-raga-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vahe-raga-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vahe-raga-48x48.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vahe-raga.png 1080w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;See what’s holding your paywall back and how to fix it. In this workshop, &lt;a href=&quot;https://www.linkedin.com/in/vahebaghdasaryan/&quot;&gt;Vahe Bagdasaryan&lt;/a&gt;, founder of Paywalls Design, shares the data-backed tweaks he’s learned from testing hundreds of paywalls each month for apps like Cal AI, NGL, and ReciMe. You’ll get practical insights on pricing, layout, and copy that have helped apps generate seven-figure revenue in months — and leave ready to apply them to your own paywall.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;marcus-burke&quot;&gt;Marcus Burke&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;Unifying Meta, ASO &amp;amp; onboarding for scale&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/marcus-raga-1024x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-45744&quot; style=&quot;width:414px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/marcus-raga-1024x1024.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/marcus-raga-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/marcus-raga-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/marcus-raga-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/marcus-raga-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/marcus-raga-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/marcus-raga-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/marcus-raga-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/marcus-raga-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/marcus-raga-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/marcus-raga-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/marcus-raga-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/marcus-raga-48x48.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/marcus-raga.png 1080w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Discover the latest full-funnel tactics for scaling your app on Meta. In this hands-on workshop, Marcus Burke, an independent consultant with 13+ years of experience helping apps like Blinkist, Moongate and Cal AI, will help you leverage Meta’s algorithm,&amp;nbsp;crack creative at scale, unlock organic and&amp;nbsp;boost conversion. Bring your questions and leave with practical tactics you can apply immediately to drive sustainable growth.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;olga-berezovsky&quot;&gt;Olga Berezovsky&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;How to test subscription prices without losing customers&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/olga-raga-1024x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-45746&quot; style=&quot;width:414px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/olga-raga-1024x1024.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/olga-raga-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/olga-raga-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/olga-raga-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/olga-raga-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/olga-raga-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/olga-raga-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/olga-raga-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/olga-raga-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/olga-raga-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/olga-raga-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/olga-raga-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/olga-raga-48x48.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/olga-raga.png 1080w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Pricing experiments are among the most complex tests you can run, especially when longer-term plans delay results for months. In this workshop, &lt;a href=&quot;https://www.linkedin.com/in/olgaberezovsky/&quot;&gt;Olga Berezovsky&lt;/a&gt; – author of the Data Analysis Journal, data scientist and analyst-in-residence for over 20 fast-growing products – shares her framework for modeling revenue improvements early. You’ll learn to pinpoint acceptable drops in Install-to-Trial and Trial-to-Paid conversions, and calculate how many you can “sacrifice” to raise MRR, ARPU, or LTV — leaving you ready to run price tests with confidence.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;nathan-hudson&quot;&gt;Nathan Hudson&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;How to scale Meta with dozens of AI agents&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/hudson-raga-1024x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-45714&quot; style=&quot;width:414px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/hudson-raga-1024x1024.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/hudson-raga-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/hudson-raga-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/hudson-raga-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/hudson-raga-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/hudson-raga-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/hudson-raga-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/hudson-raga-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/hudson-raga-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/hudson-raga-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/hudson-raga-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/hudson-raga-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/hudson-raga-48x48.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/hudson-raga.png 1080w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;AI is everywhere, but this session focuses only on what actually works. In this workshop, &lt;a href=&quot;https://www.linkedin.com/in/nathan--hudson/&quot;&gt;Nathan Hudson&lt;/a&gt;, App Marketer of the Year and founder of creative performance agency Perceptycs, shares how his team built dozens of AI agents to scale Meta acquisition for leading subscription apps. From creative strategy and production to campaign optimization, you’ll learn what works, what doesn’t, and leave with clear steps to harness AI agents to grow your Meta acquisition.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;thomas-petit&quot;&gt;Thomas Petit&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;Signal engineering bootcamp — optimize ad spend with smarter events&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/thomas-raga-1024x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-45716&quot; style=&quot;width:414px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/thomas-raga-1024x1024.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/thomas-raga-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/thomas-raga-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/thomas-raga-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/thomas-raga-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/thomas-raga-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/thomas-raga-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/thomas-raga-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/thomas-raga-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/thomas-raga-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/thomas-raga-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/thomas-raga-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/thomas-raga-48x48.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/thomas-raga.png 1080w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Most subscription apps send the wrong signals to ad networks and waste ad spend in the process. In this workshop, &lt;a href=&quot;https://www.linkedin.com/in/thomasbcn/&quot;&gt;Thomas Petit&lt;/a&gt;, independent app growth advisor with 10+ years in mobile subscriptions, shows how to design and refine the events you send to Meta, Google, and TikTok so their algorithms find higher-value users. You’ll learn which signals matter, how to filter for quality, and when to prioritize speed over accuracy — leaving with a blueprint for better ROAS.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;eli-winderbaum&quot;&gt;Eli Winderbaum&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;The AI powered support playbook — scale support while delighting users&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/eli-raga-1024x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-45748&quot; style=&quot;width:414px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/eli-raga-1024x1024.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/eli-raga-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/eli-raga-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/eli-raga-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/eli-raga-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/eli-raga-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/eli-raga-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/eli-raga-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/eli-raga-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/eli-raga-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/eli-raga-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/eli-raga-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/eli-raga-48x48.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/eli-raga.png 1080w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The customer support team of the future is AI-first and that future is here. In this workshop, &lt;a href=&quot;https://www.linkedin.com/in/eliwinderbaum/&quot;&gt;Eli Winderbaum&lt;/a&gt;, Head of Customer Experience at Captions, shares how AI agents resolve over 70% of inbound inquiries instantly while increasing customer satisfaction. You’ll learn when to deploy AI vs. humans, how to keep AI knowledge fresh, and how support can fuel growth. Leave with strategies to deliver world-class, 24/7 support — from solo indie to fast-growing app team.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;ariel-michaeli&quot;&gt;Ariel Michaeli&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;Live ASO teardown — secrets you’re missing (and how to fix them)&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ariel-raga-1024x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-45750&quot; style=&quot;width:414px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ariel-raga-1024x1024.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ariel-raga-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ariel-raga-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ariel-raga-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ariel-raga-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ariel-raga-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ariel-raga-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ariel-raga-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ariel-raga-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ariel-raga-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ariel-raga-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ariel-raga-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ariel-raga-48x48.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ariel-raga.png 1080w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;App Store Optimization can make the difference between an app that’s buried in search results and one downloaded by thousands of new users daily. Yet most developers either ignore it or rely on outdated tactics. In this live teardown, &lt;a href=&quot;https://www.linkedin.com/in/arielmichaeli/&quot;&gt;Ariel Michaeli&lt;/a&gt; — CEO of Appfigures — will analyze real apps to show exactly what works, what doesn’t, and how to improve. You’ll leave with blunt feedback, practical ASO tactics, and at least one “do this now” moment to boost visibility and conversions.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;daphne-tideman&quot;&gt;Daphne Tideman&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;How to use jobs to be done to build what users really need&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/daphne-raga-1024x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-45752&quot; style=&quot;width:414px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/daphne-raga-1024x1024.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/daphne-raga-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/daphne-raga-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/daphne-raga-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/daphne-raga-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/daphne-raga-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/daphne-raga-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/daphne-raga-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/daphne-raga-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/daphne-raga-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/daphne-raga-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/daphne-raga-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/daphne-raga-48x48.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/daphne-raga.png 1080w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The most successful apps don’t just add features, they solve the real jobs their users are trying to accomplish. In this workshop, &lt;a href=&quot;https://www.linkedin.com/in/daphnetideman/&quot;&gt;Daphne Tideman&lt;/a&gt;, growth consultant and former Head of Growth at Heights (where she scaled revenue from £28K to £343K MRR in 18 months), shows you how to uncover, prioritize, and apply jobs to be done to your app’s marketing, product, and retention strategies. You’ll leave with a framework, examples, and steps to align your app with what users truly need.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;phil-carter&quot;&gt;Phil Carter&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;How to optimize pricing and packaging for your subscription app&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/phil-raga-1024x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-45718&quot; style=&quot;width:414px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/phil-raga-1024x1024.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/phil-raga-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/phil-raga-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/phil-raga-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/phil-raga-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/phil-raga-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/phil-raga-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/phil-raga-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/phil-raga-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/phil-raga-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/phil-raga-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/phil-raga-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/phil-raga-48x48.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/phil-raga.png 1080w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Pricing and packaging decisions can make or break your subscription business. In this workshop, &lt;a href=&quot;https://www.linkedin.com/in/philgcarter/&quot;&gt;Phil Carter&lt;/a&gt; — growth advisor to category-leading apps like &lt;a href=&quot;https://www.perplexity.ai/&quot;&gt;Perplexity&lt;/a&gt;, &lt;a href=&quot;https://gamma.app/&quot;&gt;Gamma&lt;/a&gt;, &lt;a href=&quot;http://chess.com/&quot;&gt;Chess.com&lt;/a&gt;, and &lt;a href=&quot;https://imprintapp.com/&quot;&gt;Imprint&lt;/a&gt; — shares proven tools for optimizing subscription price points, plan structures, and premium feature bundles to maximize subscriber conversion, retention, and LTV. You’ll learn how to go beyond A/B testing with techniques like Van Westendorp, Gabor-Granger, MaxDiff, and Conjoint analysis to maximize your company’s subscription revenue growth. Leave with a proven toolkit for improving monetization without sacrificing subscriber loyalty.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;ashley-black&quot;&gt;Ashley Black&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;How to launch, test, and scale Google Ads for your app&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ashley-raga-1024x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-45720&quot; style=&quot;width:414px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ashley-raga-1024x1024.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ashley-raga-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ashley-raga-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ashley-raga-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ashley-raga-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ashley-raga-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ashley-raga-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ashley-raga-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ashley-raga-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ashley-raga-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ashley-raga-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ashley-raga-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ashley-raga-48x48.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ashley-raga.png 1080w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Google’s App Campaigns may be automated, but they’re far from hands-off. In this workshop, &lt;a href=&quot;https://www.linkedin.com/in/ashleym-black/&quot;&gt;Ashley Black&lt;/a&gt; — former Head of App Ad Sales at Google and now founder of Candid Consulting — shares how subscription apps can strategically unlock performance on the world’s largest app network.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;benjamin-burgess&quot;&gt;Benjamin Burgess&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;Subscriber-ready acquisition: Event-optimized UA that balances scale and quality&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/burgess-raga-1024x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-45722&quot; style=&quot;width:414px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/burgess-raga-1024x1024.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/burgess-raga-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/burgess-raga-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/burgess-raga-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/burgess-raga-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/burgess-raga-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/burgess-raga-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/burgess-raga-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/burgess-raga-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/burgess-raga-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/burgess-raga-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/burgess-raga-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/burgess-raga-48x48.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/burgess-raga.png 1080w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Freemium unlocks massive growth potential, but it complicates everything about paid acquisition — from which events to optimize for to how you measure success. In this workshop, &lt;a href=&quot;https://www.linkedin.com/in/burgess-benjamin/&quot;&gt;Benjamin Burgess&lt;/a&gt;, former growth lead at Life360 and AccuWeather, shares how to effectively shift paid acquisition focus from installs to revenue. You’ll leave with practical ways to balance volume with LTV and to align creative and landing pages so intent carries through, along with examples you can adapt to your own funnel.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;tammy-taw&quot;&gt;Tammy Taw&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;Making more from your Android app — monetization strategies that work&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/tammy-raga-1024x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-45724&quot; style=&quot;width:414px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/tammy-raga-1024x1024.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/tammy-raga-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/tammy-raga-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/tammy-raga-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/tammy-raga-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/tammy-raga-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/tammy-raga-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/tammy-raga-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/tammy-raga-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/tammy-raga-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/tammy-raga-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/tammy-raga-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/tammy-raga-48x48.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/tammy-raga.png 1080w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Subscriptions aren’t your only path to growth. In this workshop, &lt;a href=&quot;https://www.linkedin.com/in/tammytaw/&quot;&gt;Tammy Taw&lt;/a&gt; — monetization strategist at Google Play with 20 years’ experience across brands like Disney, EA, and Google — shares how to diversify your Android app revenue through hybrid models. You’ll learn how to expand your SKU mix, introduce one-time purchases or microtransactions, and tailor offers to specific buyer cohorts.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;gab-ferree&quot;&gt;Gab Ferree&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;Own the narrative — a communications playbook for subscription apps&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/gab-raga-1024x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-45754&quot; style=&quot;width:414px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/gab-raga-1024x1024.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/gab-raga-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/gab-raga-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/gab-raga-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/gab-raga-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/gab-raga-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/gab-raga-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/gab-raga-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/gab-raga-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/gab-raga-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/gab-raga-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/gab-raga-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/gab-raga-48x48.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/gab-raga.png 1080w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;In high-stakes moments, how you communicate can define your brand. &lt;a href=&quot;https://www.linkedin.com/in/gabferree/&quot;&gt;Gab Ferree&lt;/a&gt; — former Head of Comms at Bumble &amp;amp; Slack — shares proven strategies to craft the right message at the right time. Learn how to frame pricing changes, respond to negative press or reviews, and turn product updates into stories that convert. Leave with practical tools to manage crises, build trust, and drive the narrative in your favor.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;felix-boudreau&quot;&gt;Félix Boudreau&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;Stop gambling — a data-driven playbook for influencer marketing&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/felix-raga-1024x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-45756&quot; style=&quot;width:414px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/felix-raga-1024x1024.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/felix-raga-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/felix-raga-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/felix-raga-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/felix-raga-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/felix-raga-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/felix-raga-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/felix-raga-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/felix-raga-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/felix-raga-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/felix-raga-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/felix-raga-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/felix-raga-48x48.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/felix-raga.png 1080w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Influencer marketing is powerful but risky — one bad partnership can blow a budget. In this workshop, &lt;a href=&quot;https://www.linkedin.com/in/felixboudreau/&quot;&gt;Félix Boudreau&lt;/a&gt;, VP, Growth &amp;amp; Marketing at Pok Pok and former marketing lead at BetterSleep, shares how he built a top-grossing kids’ app by turning influencers into a reliable, ROI-positive channel. You’ll learn how to attribute performance, forecast campaign success, and apply proven techniques to make influencer marketing a predictable growth engine for your app.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;ron-schneidermann&quot;&gt;Ron Schneidermann&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;The executive roundtable — networking and problem solving with fellow leaders at scaled apps&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ron-raga-1024x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-45726&quot; style=&quot;width:414px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ron-raga-1024x1024.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ron-raga-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ron-raga-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ron-raga-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ron-raga-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ron-raga-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ron-raga-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ron-raga-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ron-raga-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ron-raga-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ron-raga-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ron-raga-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ron-raga-48x48.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ron-raga.png 1080w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Join &lt;a href=&quot;https://www.linkedin.com/in/schneidermann/&quot;&gt;Ron Schneidermann&lt;/a&gt;, former CEO of AllTrails, and a small group of fellow app executives for something different: no agenda, no slides — just candid discussion and problem solving. Ron will kick things off with lessons from scaling AllTrails to millions of subscribers, then open the floor for conversation. Bring your questions on team building, product decisions, and growth challenges — and leave with fresh perspectives from peers who’ve been there too.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;ethan-garr&quot;&gt;Ethan Garr&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;Perfect customer loops — retention built on core value&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ethan-raga-1024x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-45758&quot; style=&quot;width:414px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ethan-raga-1024x1024.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ethan-raga-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ethan-raga-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ethan-raga-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ethan-raga-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ethan-raga-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ethan-raga-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ethan-raga-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ethan-raga-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ethan-raga-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ethan-raga-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ethan-raga-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ethan-raga-48x48.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/ethan-raga.png 1080w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Nobody comes back for a second experience without a great first one. In this session, &lt;a href=&quot;https://www.linkedin.com/in/ethan-garr/&quot;&gt;Ethan Garr&lt;/a&gt; — co-inventor of RoboKiller and co-host of &lt;em&gt;The Breakout Growth Podcast&lt;/em&gt; — reframes retention around your users’ path to core value, and the loops that keep them consistently engaged. You’ll learn how to treat win-backs as signals of broken value, diagnose why users churn, and build a test-driven strategy to deliver meaningful value across the entire journey. Leave ready to move beyond “we miss you” messages and create customer loops that keep users coming back for more.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;patrick-falzon&quot;&gt;Patrick Falzon&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;How to scale with TV, PR, radio, and other non-digital channels&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/falzon-raga-1024x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-45728&quot; style=&quot;width:414px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/falzon-raga-1024x1024.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/falzon-raga-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/falzon-raga-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/falzon-raga-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/falzon-raga-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/falzon-raga-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/falzon-raga-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/falzon-raga-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/falzon-raga-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/falzon-raga-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/falzon-raga-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/falzon-raga-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/falzon-raga-48x48.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/falzon-raga.png 1080w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Most app teams master Meta, Google, and ASA — then stall. In this workshop, &lt;a href=&quot;https://www.linkedin.com/in/patrickfalzon/&quot;&gt;Patrick Falzon&lt;/a&gt;, CEO of The App Shop and former executive at The Mosaic Group, shares how to expand into non-digital channels like TV, CTV, radio, print, and PR without lighting money on fire. You’ll learn how each channel really works, how to buy and manage them, and what creative and tracking you need in place. Walk away with a practical framework for budgets, CAC ranges, and a test-to-scale playbook you can run next quarter.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;guillaume-de-sa&quot;&gt;Guillaume De Sá&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;Stealth marketing — how to scale with TikTok and Instagram UGC networks&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/guillaume-raga-1024x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-45730&quot; style=&quot;width:414px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/guillaume-raga-1024x1024.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/guillaume-raga-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/guillaume-raga-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/guillaume-raga-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/guillaume-raga-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/guillaume-raga-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/guillaume-raga-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/guillaume-raga-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/guillaume-raga-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/guillaume-raga-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/guillaume-raga-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/guillaume-raga-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/guillaume-raga-48x48.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/guillaume-raga.png 1080w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;a href=&quot;https://www.linkedin.com/in/guillaume-s%C3%A0/&quot;&gt;Guillaume De Sá’s&lt;/a&gt; never spent a dollar on paid ads. Guillaume runs a portfolio company that includes Social Growth Engineers, Shortimize, FindMeCreators, and several single-feature mobile apps. Today, he manages more than 300 creator accounts on TikTok and Instagram, posting nearly 500 unique, human-made videos a day. In this session, he’ll share how to manage creators, design winning hooks and formats, and build an organic acquisition machine at scale — with practical lessons you can apply to your own growth strategy.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;steve-moy&quot;&gt;Steve Moy&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;Gamification beyond the checkbox — proven metagame mechanics that drive impact&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/moy-raga-1024x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-45732&quot; style=&quot;width:414px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/moy-raga-1024x1024.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/moy-raga-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/moy-raga-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/moy-raga-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/moy-raga-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/moy-raga-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/moy-raga-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/moy-raga-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/moy-raga-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/moy-raga-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/moy-raga-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/moy-raga-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/moy-raga-48x48.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/moy-raga.png 1080w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Gamification can do more than streaks, badges, and points — built on the right metagame, it drives real engagement and revenue. In this session, &lt;a href=&quot;https://www.linkedin.com/in/stevemoy/&quot;&gt;Steven Moy&lt;/a&gt;, Chief Product Officer at Sweatcoin, draws on two decades in games (Rock Band, Dungeons &amp;amp; Dragons Online, Lightning Link Casino) and time leading revenue features at Bumble and Badoo. He’ll share how to design game loops and economies that keep users coming back, plus recent trends across PC, console, and mobile.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;bohdan-lopatiy&quot;&gt;Bohdan Lopatiy&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;Roast my onboarding — live teardown with Flo&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/bohdan-raga-1024x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-45734&quot; style=&quot;width:414px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/bohdan-raga-1024x1024.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/bohdan-raga-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/bohdan-raga-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/bohdan-raga-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/bohdan-raga-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/bohdan-raga-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/bohdan-raga-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/bohdan-raga-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/bohdan-raga-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/bohdan-raga-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/bohdan-raga-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/bohdan-raga-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/bohdan-raga-48x48.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/bohdan-raga.png 1080w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;From crafting user onboarding at Flo and leading the monetization and activation team, &lt;a href=&quot;https://www.linkedin.com/in/lopatiyb/&quot;&gt;Bohdan Lopatiy&lt;/a&gt; has seen what works (and what doesn’t). In this live session, he’ll critique real onboarding flows and show how to design experiences that both convert and retain. You’ll leave with practical takeaways to make your own onboarding more effective.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;gessica-bicego&quot;&gt;Gessica Bicego&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;Cracking web2app — choosing the right funnel for your app&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/bicego-raga-1024x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-45736&quot; style=&quot;width:414px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/bicego-raga-1024x1024.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/bicego-raga-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/bicego-raga-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/bicego-raga-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/bicego-raga-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/bicego-raga-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/bicego-raga-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/bicego-raga-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/bicego-raga-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/bicego-raga-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/bicego-raga-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/bicego-raga-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/bicego-raga-48x48.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/bicego-raga.png 1080w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Web-to-app is no longer experimental; it’s a core acquisition strategy. But with so many options — from mini landing pages to web onboarding flows — how do you know which approach is right for your app? In this workshop, &lt;a href=&quot;https://www.linkedin.com/in/gessicabicego/&quot;&gt;Gessica Bicego&lt;/a&gt;, Independent Consultant (ex-Blinkist, Paired), shares the key decisions that make web-to-app funnels profitable, not just functional. You’ll see what works across different verticals, learn when to go lean vs. custom, and leave with a clear plan to build or scale your own funnel.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;david-vargas&quot;&gt;David Vargas&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;The TikTok ads playbook: AMA on creatives, offers, and scaling UA&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vargas-raga-1024x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-45738&quot; style=&quot;width:414px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vargas-raga-1024x1024.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vargas-raga-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vargas-raga-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vargas-raga-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vargas-raga-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vargas-raga-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vargas-raga-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vargas-raga-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vargas-raga-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vargas-raga-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vargas-raga-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vargas-raga-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vargas-raga-48x48.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vargas-raga.png 1080w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;TikTok has become one of the most powerful channels for subscription app growth, with unmatched reach, the highest engagement rates in social, and a billion users with real purchase power. But it’s also volatile: winning creatives can collapse in 24 hours, and scaling without the right testing framework quickly burns cash. In this workshop, &lt;a href=&quot;https://www.linkedin.com/in/davidvargasmontiel/&quot;&gt;David Vargas&lt;/a&gt;, UA and ASO Manager at SplitMetrics, shares lessons from managing strategies for 100+ apps — showing how creative velocity, smart offer design, and structured experiments can turn TikTok into a profitable growth engine. After a short case study, the session opens into an AMA, where David will tackle your toughest UA questions live. You’ll leave with experiments you can run right away to lower CAC, fight fatigue, and scale paid campaigns with confidence.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;peter-woohyeok-choi&quot;&gt;Peter (Woohyeok) Choi&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;Unlocking Japan and Korea — essential insights for breaking into the world’s 3rd and 4th largest app markets&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large is-resized&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/choi-raga-1024x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-45740&quot; style=&quot;width:414px&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/choi-raga-1024x1024.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/choi-raga-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/choi-raga-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/choi-raga-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/choi-raga-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/choi-raga-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/choi-raga-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/choi-raga-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/choi-raga-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/choi-raga-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/choi-raga-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/choi-raga-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/choi-raga-48x48.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/choi-raga.png 1080w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Breaking into Japan and Korea’s app markets is challenging, but with the right approach it’s a massive opportunity. In this workshop, &lt;a href=&quot;https://www.linkedin.com/in/woohyeok-choi-/&quot;&gt;Peter Choi&lt;/a&gt; — CEO Staff at Delightroom (maker of the globally successful Alarmy app) and Product Owner of Between, the Korea- and Japan-based couple app — shares why common growth strategies often fall short in these regions. You’ll learn how to fine-tune monetization, engagement models, and onboarding flows to resonate with local users, and leave with practical strategies to grow in two of the world’s top app markets.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-don-t-miss-app-growth-annual-2025&quot;&gt;Don’t miss App Growth Annual 2025&lt;/h2&gt;



&lt;p&gt;We built App Growth Annual to be the day the subscription app community gets together — to learn what’s working, share what’s not, and celebrate the wins along the way. Expect practical insights, open debates, and a few surprises (including on stage).&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://rev.cat/raga-reg&quot;&gt;&lt;strong&gt;Apply for in-person tickets&lt;/strong&gt;&lt;/a&gt; | &lt;a href=&quot;https://rev.cat/ragavirtual-reg&quot;&gt;&lt;strong&gt;Register for virtual (free)&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;&lt;/p&gt;



&lt;p&gt;&lt;br&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[5 quick fixes for bad default global pricing on app stores]]></title><description><![CDATA[Why regional pricing outperforms features, funnels, and ad spend]]></description><link>https://www.revenuecat.com/blog/growth/5-quick-fixes-for-bad-default-global-pricing-on-app-stores/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/5-quick-fixes-for-bad-default-global-pricing-on-app-stores/</guid><pubDate>Fri, 29 Aug 2025 09:27:48 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/5-quick-fixes-for-bad-default-global-pricing-on-app-stores.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Let me be blunt: if your entire monetization strategy boils down to “build new features” or “buy more traffic,” you’re playing on hard mode. I’ve been there. I’ve spent thousands on paid installs. I’ve obsessively A/B tested onboarding screens. But the biggest revenue unlock we ever hit in one of our apps didn’t come from any of that.&lt;/p&gt;



&lt;p&gt;It came from changing the price. Not the product. Not the brand. Just the price — specifically, making it &lt;em&gt;fair&lt;/em&gt; for users around the world.&lt;/p&gt;



&lt;p&gt;And that’s the part most devs overlook.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-global-pricing-is-broken-by-default&quot;&gt;Why global pricing is broken by default&lt;/h2&gt;



&lt;p&gt;Let’s say you charge &lt;strong&gt;$49.99/year&lt;/strong&gt;. In the U.S., that’s a no-brainer for a useful tool — less than a cup of coffee a month. But in &lt;strong&gt;India or Brazil&lt;/strong&gt;, it’s a much bigger ask. I once had a user DM me saying: &lt;em&gt;“This costs more than my Netflix and Spotify combined. I love your app, but I just can’t.”&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;That’s when it hit me: value isn’t universal&lt;strong&gt; &lt;/strong&gt;—&lt;strong&gt; it’s relative&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;You’re not just competing with other apps, you’re competing with the local economy.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-so-what-works-instead&quot;&gt;&lt;strong&gt;So what works instead?&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;&lt;strong&gt;Purchasing Power Parity (PPP)&lt;/strong&gt; is your friend here. Think of it as adjusting your price so that $1 feels like $1, no matter the country. And it works.&lt;/p&gt;



&lt;p&gt;When we started testing regional pricing with early Mirava users, here’s what we saw:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;A meditation app doubled subscriptions in Latin America in &lt;strong&gt;14 days&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;A wellness tracker got a &lt;strong&gt;38% lift in conversions&lt;/strong&gt; in Southeast Asia&lt;/li&gt;



&lt;li&gt;One app cut prices by 60% and got &lt;strong&gt;3x more paying users&lt;/strong&gt; in return&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Let that sink in: you halve the price and &lt;em&gt;triple&lt;/em&gt; the conversions.&lt;/p&gt;



&lt;p&gt;It’s not about discounting — it’s about &lt;strong&gt;fair pricing&lt;/strong&gt;.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-5-quick-fixes-to-unlock-more-revenue-through-regional-pricing&quot;&gt;5 quick fixes to unlock more revenue through regional pricing&lt;/h2&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-cut-prices-where-it-hurts-most&quot;&gt;1. Cut prices where it hurts most&lt;/h3&gt;



&lt;p&gt;Look at Southeast Asia, Latin America, parts of Eastern Europe. These are markets with high mobile penetration, but low average income. In these markets, a 60–80% price drop is what makes access possible.&lt;/p&gt;



&lt;p&gt;&lt;em&gt;Tip: I’ve personally used a 70% cut in India and 60% in the Philippines with great results.&lt;/em&gt;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-use-local-price-psychology&quot;&gt;2. Use local price psychology&lt;/h3&gt;



&lt;p&gt;Nobody wants to pay ₱202.33 or ₹376.19. It looks lazy. Round to prices that feel local: ₱199, ₹349, R$49.&lt;/p&gt;



&lt;p&gt;&lt;em&gt;Your app should feel made for them, not exported to them.&lt;/em&gt;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-map-to-native-price-tiers&quot;&gt;&lt;strong&gt;3. Map to native price tiers&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Apple and Google both have native price tier suggestions. Use them as starting points. Their tiers are optimized for each region’s psychology and economy.&lt;/p&gt;



&lt;p&gt;&lt;em&gt;Tip: Don’t use the same tier on both platforms — Google’s and Apple’s markets behave differently.&lt;/em&gt;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-4-watch-competitors-in-local-stores&quot;&gt;4. Watch competitors in local stores&lt;/h3&gt;



&lt;p&gt;Your U.S. price might look premium… but in Brazil, you might be charging 5x more than your competitor. Look up the top 5 apps in your niche in local app stores. What do they charge?&lt;/p&gt;



&lt;p&gt;&lt;em&gt;We found a 2x price mismatch in LATAM vs. local competitors for one app, which explained months of churn.&lt;/em&gt;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-5-automate-or-you-ll-never-do-it&quot;&gt;5. Automate or you’ll never do it&lt;/h3&gt;



&lt;p&gt;I get it. Managing 175+ prices across three platforms is a nightmare. I tried the spreadsheets, I built a Zapier pipeline… It broke constantly.&lt;/p&gt;



&lt;p&gt;That’s why we built &lt;strong&gt;Mirava&lt;/strong&gt;, because nobody should be doing this by hand in 2025.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-teams-procrastinate-and-why-you-can-t-afford-to&quot;&gt;Why teams procrastinate and why you can’t afford to&lt;/h2&gt;



&lt;p&gt;Most teams ignore pricing updates because:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Apple, Google, and Stripe all do it differently&lt;/li&gt;



&lt;li&gt;You have to update for each platform separately&lt;/li&gt;



&lt;li&gt;You &lt;em&gt;might&lt;/em&gt; break something&lt;/li&gt;



&lt;li&gt;It’s not sexy, like a redesign or new feature&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;But you need to remember that &lt;strong&gt;you’re&lt;/strong&gt; &lt;strong&gt;losing money every single day you delay.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;You don’t need to boil the ocean: start with your top three regions outside your home market. Just doing &lt;em&gt;that&lt;/em&gt; can boost revenue by double digits.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-tl-dr-make-pricing-your-growth-lever-not-an-afterthought&quot;&gt;&lt;strong&gt;TL;DR — make pricing your growth lever, not an afterthought&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;In 2025, most apps are fighting churn, burning ad budgets, and hoping their next feature moves the needle. But the smartest teams I know are optimizing their pricing.&lt;/p&gt;



&lt;p&gt;And regional pricing is one of the &lt;strong&gt;fastest, highest-ROI&lt;/strong&gt; growth moves available today. You don’t need a new feature — you need better economics.&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;p&gt;&lt;strong&gt;Want help without spreadsheets?&lt;br&gt;&lt;/strong&gt;&lt;a href=&quot;http://www.mirava.io&quot;&gt;Mirava&lt;/a&gt; automates regional pricing for mobile apps. Cross-platform. PPP-based. Built by people who’ve felt this pain (and fixed it). Now in public beta.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Applications are now open for The Shippies 2025 🏆]]></title><description><![CDATA[Announcing The Shippies 2025: Celebrating App Growth Excellence 🚢]]></description><link>https://www.revenuecat.com/blog/company/shippies-2025-app-growth-awards/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/company/shippies-2025-app-growth-awards/</guid><pubDate>Tue, 26 Aug 2025 10:56:01 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/RevenueCat-App-Growth-2024-0060-1-Large.jpeg" length="0" type="image/*"/><content:encoded>&lt;p&gt;Last year at App Growth Annual, we tried something new: handing out a set of trophies to recognize the best subscription apps in the world. We called them &lt;em&gt;The Shippies&lt;/em&gt;, a not-so-subtle nod to “shipping” (which we think is worth celebrating in itself)&lt;/p&gt;



&lt;p&gt;It was a hit. We had incredible entries, tough judging decisions, and &lt;a href=&quot;https://www.revenuecat.com/blog/growth/shippies-winners-2024/&quot;&gt;six winners&lt;/a&gt; who set the standard for what “app growth excellence” looks like:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Smooth Sailor (Best Onboarding Experience):&lt;/strong&gt; &lt;em&gt;Arnold Schwarzenegger’s The Pump&lt;/em&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Port of Entry (Most Effective Use of Paywalls):&lt;/strong&gt; &lt;em&gt;Lose It!&lt;/em&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Life Preserver (Best Churn Reduction Initiative):&lt;/strong&gt; &lt;em&gt;HER&lt;/em&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Treasure Chest (Best Monetization Strategy):&lt;/strong&gt; &lt;em&gt;Zumba&lt;/em&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Anchor’s Away (Best New App Launch):&lt;/strong&gt; &lt;em&gt;Galatea by Inkitt&lt;/em&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Lone Skipper (Best Solo Developer Build):&lt;/strong&gt; &lt;em&gt;Shotsy&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;figure class=&quot;wp-block-embed is-type-rich is-provider-twitter wp-block-embed-twitter&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;blockquote class=&quot;twitter-tweet&quot; data-width=&quot;500&quot; data-dnt=&quot;true&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;The Pump is now an award-winning app! I want to thank my whole team for working their asses off, and all of our members for making it the positive corner of the internet.&lt;a href=&quot;https://t.co/Ny6ByM3yYg&quot;&gt;https://t.co/Ny6ByM3yYg&lt;/a&gt; &lt;a href=&quot;https://t.co/5SIzCAv6A7&quot;&gt;https://t.co/5SIzCAv6A7&lt;/a&gt;&lt;/p&gt;— Arnold (@Schwarzenegger) &lt;a href=&quot;https://twitter.com/Schwarzenegger/status/1842231857959890972?ref_src=twsrc%5Etfw&quot;&gt;October 4, 2024&lt;/a&gt;&lt;/blockquote&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;We didn’t just hand them a trophy. We gave them the spotlight, literally. Their apps lit up over 150 billboards across San Francisco, turning Market Street into a celebration of subscription success&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;768&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/IMG_2125-Large-1024x768.jpeg&quot; alt=&quot;&quot; class=&quot;wp-image-45672&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/IMG_2125-Large-1024x768.jpeg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/IMG_2125-Large-300x225.jpeg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/IMG_2125-Large-768x576.jpeg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/IMG_2125-Large-50x38.jpeg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/IMG_2125-Large-53x40.jpeg 53w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/IMG_2125-Large-619x464.jpeg 619w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/IMG_2125-Large-696x522.jpeg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/IMG_2125-Large-560x420.jpeg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/IMG_2125-Large-395x296.jpeg 395w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/IMG_2125-Large-629x472.jpeg 629w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/IMG_2125-Large-80x60.jpeg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/IMG_2125-Large-48x36.jpeg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/IMG_2125-Large.jpeg 1280w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;This year, we’re taking it even bigger&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-shippies-2025&quot;&gt;&lt;strong&gt;The Shippies 2025 🚢&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;&lt;a href=&quot;https://form.typeform.com/to/wffvBJvx&quot;&gt;Applications&lt;/a&gt; are now open for the second edition of &lt;em&gt;The Shippies&lt;/em&gt;. Six categories. Six winners. Endless bragging rights&lt;/p&gt;



&lt;p&gt;Here’s what’s up for grabs:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;A shiny Shippy trophy (in a brand new design!)&lt;/li&gt;



&lt;li&gt;A feature across RevenueCat channels&lt;/li&gt;



&lt;li&gt;Your app &lt;strong&gt;on a Times Square billboard&lt;/strong&gt; during New York App Week (October 13-16) and App Growth Annual in New York&lt;/li&gt;
&lt;/ul&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;966&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-54-966x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-45674&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-54-966x1024.png 966w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-54-283x300.png 283w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-54-768x814.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-54-47x50.png 47w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-54-38x40.png 38w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-54-438x464.png 438w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-54-696x737.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-54-529x560.png 529w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-54-279x296.png 279w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-54-445x472.png 445w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-54-76x80.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-54-45x48.png 45w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-54.png 1024w&quot; sizes=&quot;auto, (max-width: 966px) 100vw, 966px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;If you can’t make it to New York on October 14, we’ll &lt;em&gt;ship&lt;/em&gt; you your Shippy. But the billboard? That’s happening no matter what&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;categories&quot;&gt;&lt;strong&gt;Categories&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Same as last year, there are six categories and you can pick any two to apply for:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Smooth Sailor&lt;/strong&gt; – Best onboarding experience&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Port of Entry&lt;/strong&gt; – Most effective use of paywalls&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Life Preserver&lt;/strong&gt; – Best churn reduction initiative&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Treasure Chest&lt;/strong&gt; – Best overall monetization strategy&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Anchor’s Away&lt;/strong&gt; – Best new app launch&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Lone Skipper&lt;/strong&gt; – Best new app built by a solo developer&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-to-apply-for-the-2025-shippies&quot;&gt;&lt;strong&gt;How to Apply&lt;/strong&gt; for the 2025 Shippies&lt;/h2&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Fill out &lt;a href=&quot;https://form.typeform.com/to/wffvBJvx&quot;&gt;this application form&lt;/a&gt; by &lt;strong&gt;September 15, 2025&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;You can apply in up to two categories&lt;/li&gt;



&lt;li&gt;Winners will be announced on stage at &lt;strong&gt;App Growth Annual NYC, October 14, 2025&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;why-apply&quot;&gt;&lt;strong&gt;Why Apply?&lt;/strong&gt;&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;640&quot; height=&quot;849&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/9c612406b33b55a341b387200b5fa9fd47fb3aaa-856x1136-1.jpeg&quot; alt=&quot;&quot; class=&quot;wp-image-45682&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/9c612406b33b55a341b387200b5fa9fd47fb3aaa-856x1136-1.jpeg 640w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/9c612406b33b55a341b387200b5fa9fd47fb3aaa-856x1136-1-226x300.jpeg 226w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/9c612406b33b55a341b387200b5fa9fd47fb3aaa-856x1136-1-38x50.jpeg 38w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/9c612406b33b55a341b387200b5fa9fd47fb3aaa-856x1136-1-30x40.jpeg 30w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/9c612406b33b55a341b387200b5fa9fd47fb3aaa-856x1136-1-350x464.jpeg 350w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/9c612406b33b55a341b387200b5fa9fd47fb3aaa-856x1136-1-422x560.jpeg 422w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/9c612406b33b55a341b387200b5fa9fd47fb3aaa-856x1136-1-223x296.jpeg 223w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/9c612406b33b55a341b387200b5fa9fd47fb3aaa-856x1136-1-356x472.jpeg 356w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/9c612406b33b55a341b387200b5fa9fd47fb3aaa-856x1136-1-60x80.jpeg 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/9c612406b33b55a341b387200b5fa9fd47fb3aaa-856x1136-1-36x48.jpeg 36w&quot; sizes=&quot;auto, (max-width: 640px) 100vw, 640px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Beyond the trophy and the Times Square flex, The Shippies are about shining a light on the work that usually doesn’t get a spotlight. Onboarding flows. Churn experiments. Pricing strategies. Launches that worked&lt;/p&gt;



&lt;p&gt;If you’ve been shipping hard, we want to celebrate you&lt;/p&gt;



&lt;div class=&quot;wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex&quot;&gt;
&lt;div class=&quot;wp-block-button has-custom-width wp-block-button__width-50 is-style-fill&quot;&gt;&lt;a class=&quot;wp-block-button__link has-vivid-red-background-color has-background has-medium-font-size has-custom-font-size wp-element-button&quot; href=&quot;https://form.typeform.com/to/wffvBJvx&quot; style=&quot;border-radius:15px&quot;&gt;Submit your app for a Shippy&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;&lt;br&gt;We can’t wait to see the entries this year and we’ll see you (and your app, fifty feet high in Times Square) in October!&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[How Shipaton turned Mansour Mahamat’s hobby app in to a business]]></title><description><![CDATA[How a Jiu-Jitsu black belt used Shipaton to turn a coding experiment into a subscription app used worldwide]]></description><link>https://www.revenuecat.com/blog/engineering/how-shipaton-turned-mansour-mahamats-hobby-app-in-to-a-business/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/how-shipaton-turned-mansour-mahamats-hobby-app-in-to-a-business/</guid><pubDate>Fri, 22 Aug 2025 13:16:45 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/cover.jpg" length="0" type="image/*"/><content:encoded>&lt;p&gt;&lt;br&gt;&lt;em&gt;As part of this year’s Shipaton, we’re highlighting stories from past participants to show what’s possible when you commit to building in public. Whether you’re aiming to sharpen your skills, launch your first product, or maybe even win, these interviews are meant to spark ideas, share learnings, and inspire you to take part in Shipaton.&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;&lt;em&gt;We’re also including their tips on how to get the most out of Shipaton, from choosing the right idea to managing your time to pushing through the inevitable bugs and blockers.&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;Concluding our Shipaton interview series: &lt;strong&gt;Mansour Mahamat&lt;/strong&gt;, a frontend developer from France living in Sweden. He first started coding in 2019 and has over the years worked on a variety of web apps and projects. Last year however, he came across Shipaton and decided that it posed the perfect opportunity to branch out into mobile development. Before he had only done simple tutorials, but he was missing the notch of building a full mobile app.&lt;/p&gt;



&lt;p&gt;So as Shipaton kicked off last year, Mansour Mahamat opened the SwiftUI documentation and started building and learning more about the technology by doing that. It wasn’t long before he was also documenting his progress in TikTok, one of the only participants to do that last year. Originally he had a simple goal of learning English by talking about his app, and building a mobile app, but what he ended up building was an actual business around his app idea.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-building-the-app&quot;&gt;Building the app&lt;/h2&gt;



&lt;p&gt;Mansour has been practicing Brazilian jiu-jitsu for years and has a black belt from it. So when it came to coming up with an idea he didn’t have to think for long and decided to combine two of his passions. His idea actually came to him while after a training session:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;The idea struck me after a particularly intense rolling session. I was lying on the mat, exhausted but exhilarated, wishing I could capture this moment and track my progress over time. That’s when it hit me — why not create an app that could do just that?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;His idea was to build an app to log techniques and progress while going Brazilian jiu-jitsu training. Originally it was supposed to be a personal tool, with the MVP having two core features: logging training sessions and visualizing the progress from those.&lt;/p&gt;



&lt;p&gt;However the app started growing as he shared it with his BJJ gym mates, who provided valuable feedback and suggested new features. He ended up building for example AI coaches and community leaderboards, which further boosted the adoption. The last days of Shipaton he spent on polishing the UI and improving the user experience and performance of the app.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-from-swift-to-react-native&quot;&gt;From Swift to React Native&lt;/h3&gt;



&lt;p&gt;Mansour decided to build the first version of BJJ Evolve using SwiftUI, as a learning experience. Although he found working with SwiftUI pleasant and fast, he decided to rebuild the app in React Native after Shipaton. He wanted to be able to iterate new versions of the app faster and also build an Android version. Maintaining two apps in different programming languages would have been too much work.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-building-in-public-morning-shift-edition&quot;&gt;Building in public: morning shift edition&lt;/h2&gt;



&lt;p&gt;For Mansour, consistency was everything. He carved out time by waking up at 5 a.m. every day before work, giving himself two uninterrupted hours to learn, build, and push his project forward. That routine carried him through the most intense parts of Shipaton, helping him hit milestones without burning out.&lt;/p&gt;



&lt;p&gt;But building was only half the story. To find users, Mansour didn’t just rely on the app store. Before even shipping, he created a waitlist that grew to 300 people in just two weeks. His secret weapon? TikTok.&lt;/p&gt;



&lt;p&gt;By posting daily videos about his progress and mixing in snippets of his training as a black belt, he quickly built authority and trust. What began as a way to practice English became his breakout marketing channel. Soon, gym peers, competitors, and even strangers online were downloading his app.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“Building something is easy. Finding users is hard. TikTok made people see me not only as a developer but also as a black belt who understands the sport. That made them trust the app immediately.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-post-shipaton-side-project-into-a-business&quot;&gt;Post-Shipaton: side project into a business&lt;/h2&gt;



&lt;p&gt;In addition to converting the app from SwiftUI to React Native, Mansour also added multilingual support — first French, then Spanish — after seeing downloads spread across the world.&lt;/p&gt;



&lt;p&gt;Continuing to work on the app has paid dividends. Today, 5–6 gyms actively use the app, supported by a companion web platform for coaches. The system allows managing students, handling subscriptions, and publishing schedules, while athletes track progress from their phones. What started as “just a Shipaton project” has become a real business with daily new downloads.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-advice-for-shipaton-participants&quot;&gt;Advice for Shipaton participants&lt;/h2&gt;



&lt;p&gt;When asked what advice Mansour would give Shipaton 2025 participants, he emphasized passion, consistency, and community: pick something you’re passionate about&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“You need to love the problem you’re solving. Otherwise, you’ll get bored after two weeks. I’ve been working on this project for over a year, and I’m still motivated.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;He also tells shippers to focus on being consistent and sticking to it.His 5 a.m. routine and regular updates kept momentum alive. Many others started building in public but stopped after 10 days. He advises posting updates on whichever platforms your community uses, whether Reddit, Facebook, LinkedIn, or TikTok.&amp;nbsp;&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“You can build the best app, but if no one sees it, you’ll struggle.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-plans-for-this-year-s-shipaton&quot;&gt;Plans for this year’s Shipaton&lt;/h2&gt;



&lt;p&gt;For this year’s Shipaton, Mansour is shifting gears. While he had initially planned to build a boxing app powered by AI, the demand from his Brazilian Jiu-Jitsu community changed his direction. Over the past months, gyms reached out asking for a more customizable solution — one built specifically for coaches and their students.&lt;/p&gt;



&lt;p&gt;That feedback sparked a new project: a B2B version of BJJ Evolve designed for gyms. Unlike the original app, which was consumer-focused, this new version centers on coaches. It includes a social-style feed (similar to Facebook) where trainers can post updates, share schedules, or communicate with their athletes. Students receive push notifications directly in the app, keeping everyone connected in one place. To support subscriptions and gym-specific monetization, Mansour is also integrating RevenueCat.&lt;/p&gt;



&lt;p&gt;He’s documenting the journey on &lt;a href=&quot;https://www.youtube.com/@manstechlife&quot;&gt;YouTube&lt;/a&gt;, bringing the same build-in-public approach that fueled his BJJ app’s growth. His goal: replicate the power of consistency and community, while evolving the product into a more professional, gym-first tool.&lt;/p&gt;



&lt;p&gt;Reflecting on this evolution, Mansour sees it as a natural progression:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“Shipaton opened the door for me last year when I built a personal app. A year later, it became professional. Gyms are using it, and now I’m taking it even further with a dedicated B2B product.”&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[How to win Shipaton part 3: growing your app]]></title><description><![CDATA[Tactics to get your first 100 users and show real momentum during Shipaton]]></description><link>https://www.revenuecat.com/blog/engineering/how-to-win-shipaton-part-3-growing-your-app/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/how-to-win-shipaton-part-3-growing-your-app/</guid><pubDate>Fri, 22 Aug 2025 06:55:03 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Slice.jpg" length="0" type="image/*"/><content:encoded>&lt;p&gt;You’ve come up with an app idea, you’ve built it, and now you need users to prove your app is growing. That’s how you win Shipaton. In this third, and second-to-last, installment of our “How to Win Shipaton” series, we’re diving into growth.&lt;/p&gt;



&lt;p&gt;So far, we’ve covered how to generate an idea and turn it into a minimum lovable product without wasting time. By now, your app should be in the hands of users. Maybe it’s just TestFlight testers, or perhaps you’ve already launched on the App Store and gathered a small but loyal group giving feedback. Wherever you are, the next challenge is clear: it’s time to grow your user base.&lt;/p&gt;



&lt;p&gt;In this guide, we’ll frame growth as momentum. Momentum builds as you listen to your users and strengthen your app’s presence. The milestone to aim for is 100 paying customers during Shipaton. It’s ambitious but realistic, and it doesn’t require gimmicky growth hacks to achieve.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-1-acquire-new-users&quot;&gt;Step 1: Acquire new users&lt;/h2&gt;



&lt;p&gt;The first step to growing your app is acquiring users. Your earliest users are usually the same people you spoke with when validating your idea — friends, family, or folks with the specific pain point you’re solving, like teachers. Now is the time to lean on those networks. Announce your app with a LinkedIn or Twitter post that clearly explains the problem you solve and why it matters. As you bring users in, keep track of who they are. You’ll want this list later when you start iterating or announcing updates.&lt;/p&gt;



&lt;p&gt;The next step, once you’ve tapped your immediate circle, is finding new ones. Seek out niche communities on Reddit, Discord, or specialized forums where your potential users already gather. Don’t overlook small-scale influencers in your niche either. A micro-influencer with a few hundred engaged followers can often drive more adoption than a big account with a broad, unfocused audience. Offering them free access to your app in exchange for a shout-out can be a simple, low-cost win.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-shipaton-is-here-to-help&quot;&gt;Shipaton is here to help&lt;/h3&gt;



&lt;p&gt;Shipaton itself is a powerful growth tool. Use the Shipaton Discord to showcase your app, gather feedback, and connect with other builders. Consider teaming up with fellow participants to cross-promote each other’s apps. Collaboration during Shipaton not only gets you more users, it also makes the experience more fun. Join &lt;a href=&quot;https://app.getriver.io/shipaton&quot;&gt;IRL Shipaton events&lt;/a&gt; and ask people there to try your app.&lt;/p&gt;



&lt;p&gt;Finally, make your first users feel like VIPs. Let them know how important they are to your app’s journey. You might offer an early-bird discount, unlock a custom “founding user” app icon, or create a playful Easter egg that only early adopters can access. These small touches not only reward loyalty but also turn users into advocates who bring in the next wave.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-2-improve-your-discoverability&quot;&gt;Step 2: Improve your discoverability&lt;/h2&gt;



&lt;p&gt;Every potential user passes through your App Store or Play Store product page. Making that page as strong and discoverable as possible is one of the clearest growth levers you have. With each release, revisit your title and description to make sure they include the keywords people actually use to search for apps like yours. This practice, App Store Optimization (ASO), can have a huge impact, and &lt;a href=&quot;https://www.revenuecat.com/blog/growth/app-store-optimization-guide/&quot;&gt;we’ve even put together a handy guide to help you get started&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;Strong copy matters. Write an app description that clearly communicates your main features and, more importantly, the benefits users will get. Reinforce these benefits visually with well-designed screenshots and a short demo video that shows your app in action.&lt;/p&gt;



&lt;p&gt;Ratings and reviews are another critical driver of visibility and conversion. Tap into that email list of early users and ask them directly for reviews. Make the ask personal and transparent: let them know honest feedback helps other people discover the app. Both Apple and Google reward well-rated apps by ranking them higher in search results and users will use it to determine if the app is worth trying.&lt;/p&gt;



&lt;p&gt;Finally, keep your app fresh. Frequent small updates not only improve the product, they signal to the stores (and your users) that the app is actively maintained. And when you ship, be specific. Don’t do the generic “Bug fixes and performance improvements” update text. Instead, highlight the actual changes you’ve made, whether it’s new features, UI tweaks, or even minor improvements. This shows momentum and helps users see the progress you’re making.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-3-keep-existing-users&quot;&gt;Step 3: Keep existing users&lt;/h2&gt;



&lt;p&gt;Getting new users is important, but keeping the ones you already have is even more critical. In product development this is called retention, and it is where your app truly proves its value.&lt;/p&gt;



&lt;p&gt;Start by responding to feedback quickly. If a user reports a bug or suggests an improvement, act on it and let them know as soon as you’ve made the change. This shows you’re listening and builds trust early. If they gave your app a bad rating in the app store because of a bug or missing feature, nudge them to try the new version where it’s fixed. It’s more than likely that they will fix their rating once they feel heard.&lt;/p&gt;



&lt;p&gt;Show momentum by iterating visibly. Use your changelog and “What’s New” notes in the stores to highlight improvements, not just bug fixes. Small but frequent updates reassure users that the app is alive and getting better with every release.&lt;/p&gt;



&lt;p&gt;Finally, engage on a personal level. A short direct message or email thanking early adopters can go a long way. When users feel recognized and valued, they’re more likely to stick around. It might make them also more likely to tell their friends about it.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-4-build-a-feedback-loop&quot;&gt;Step 4: Build a feedback loop&lt;/h2&gt;



&lt;p&gt;Growth isn’t just about adding users, it’s about learning from the ones you already have. A strong feedback loop helps you figure out what’s working, what’s broken, and what to build next.&lt;/p&gt;



&lt;p&gt;Start simple with lightweight questions. A quick “Was this feature useful?” or “How’s your experience so far?” can give you directional insights without overwhelming users. You can either do this by asking your users directly, or if you have time, implement a simple feedback feature in your app.&lt;/p&gt;



&lt;p&gt;For more in depth conversations, set up channels outside the app. A short survey, or even better, a dedicated Discord or Slack group, gives your users a place to share thoughts, requests, and bugs in more detail. This kind of space also helps users feel closer to the product and the team behind it. Apps that have a strong user community around them are often some of the best monetizing apps.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-conclusion&quot;&gt;Conclusion&lt;/h2&gt;



&lt;p&gt;Winning Shipaton isn’t just about hitting the biggest numbers. It’s about showing clear signs of growth and proving that you’ve hustled to get your app into more hands. Even small improvements, such a few new daily active users, a handful of signups, or the first batch of reviews, are what builds momentum. Track that progress, however modest it may be. The early metrics tell the story of an app that’s alive, growing, and moving in the right direction.&lt;/p&gt;



&lt;p&gt;In the final part of this series, we’ll look at how to make your submission stand out. Beyond growth, it’s about telling your story in a way that shows the journey, the effort, and the vision behind your app. When we write that story into a Devpost submission we are going to use the growth methods you ended up using as story points.&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Introductory offers for RevenueCat Web Billing: convert more users with the right first price]]></title><description><![CDATA[Create flexible, intro-period pricing to boost acquisition. Give your customers a reason to subscribe sooner with Introductory Offers now available for RevenueCat Web Billing.]]></description><link>https://www.revenuecat.com/blog/company/introductory-offers-for-revenuecat-web-billing/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/company/introductory-offers-for-revenuecat-web-billing/</guid><pubDate>Thu, 21 Aug 2025 08:51:47 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Blog_Cover_Introductory-Offer-for-Web-1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;For subscription businesses, the very first price a potential customer sees is one of the most powerful levers for conversion. In fact, &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps-2025/#h-time-to-trial&quot;&gt;82% of trial starts happen on the first day a user downloads an app&lt;/a&gt;. On web, the same principle applies: when a visitor lands on your paywall, their decision often hinges on the very first number they see.&lt;/p&gt;



&lt;p&gt;On mobile, the App Store and Play Store have long equipped developers with flexible pricing tools like free trials, introductory discounts, seasonal promos. But on the web, subscription companies often face a gap. Without dedicated infrastructure, they end up:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Building custom checkout logic for discounts.&lt;/li&gt;



&lt;li&gt;Running promotions manually with codes.&lt;/li&gt;



&lt;li&gt;Risking inconsistent experiences across platforms.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/web/web-billing/overview&quot;&gt;RevenueCat Web Billing&lt;/a&gt; closes this gap. It gives you app-store grade subscription infrastructure directly on the web, so your pricing strategy is consistent, scalable, and easy to manage. And now, with Introductory Offers, you can use the same proven tactics that drive conversions on mobile to win more subscribers on the web.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-are-introductory-offers&quot;&gt;What are Introductory Offers?&lt;/h2&gt;



&lt;p&gt;Introductory Offers let you set a special price for a specified period of a subscription on &lt;a href=&quot;https://www.revenuecat.com/docs/web/web-billing/overview&quot;&gt;RevenueCat Web Billing&lt;/a&gt;. The system automatically applies the discount for all eligible new subscribers, then rolls them into your regular price without any manual intervention.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt;&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Set up the product in your RevenueCat dashboard.&lt;/li&gt;



&lt;li&gt;Choose the length of the intro period (e.g., 1 week, 3 months).&lt;/li&gt;



&lt;li&gt;Set the intro price.&lt;/li&gt;



&lt;li&gt;Save, publish, and promote.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;After the intro period ends, RevenueCat seamlessly transitions subscribers to your standard price to reduce churn from manual upgrades.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-wp-embed is-provider-wistia-inc wp-block-embed-wistia-inc&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; class=&quot;wp-embedded-content&quot; sandbox=&quot;allow-scripts&quot; security=&quot;restricted&quot; title=&quot;Intro Offers - Web Video&quot; src=&quot;https://fast.wistia.net/embed/iframe/d2ml6cs5bz?dnt=1#?secret=bMfUFevDTo&quot; data-secret=&quot;bMfUFevDTo&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; width=&quot;500&quot; height=&quot;310&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;why-this-matters-for-subscription-apps&quot;&gt;Why this matters for subscription apps&lt;/h2&gt;



&lt;p&gt;If you landed here searching for “introductory pricing for web subscriptions” or “how to add intro offers to SaaS billing,” you’re likely trying to solve one of these challenges:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Boosting signups without deep discounts&lt;/strong&gt; &lt;br&gt;Intro pricing lowers the barrier to entry without permanently reducing your standard price.&lt;br&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Reducing failed trials&lt;/strong&gt; &lt;br&gt;Free trials can create noise: payment failures, disengaged users, or mismatched intent. Intro Offers bring in subscribers who are willing to commit, even if only a little.&lt;br&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Simplifying campaign management&lt;/strong&gt; &lt;br&gt;Running seasonal or regional promotions often means juggling codes, eligibility scripts, and custom checkout flows. Intro Offers let you run everything natively in RevenueCat.&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;designed-for-every-growth-strategy&quot;&gt;Designed for every growth strategy&lt;/h2&gt;



&lt;p&gt;&lt;strong&gt;1. Drive more signups, instantly&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Lower the barrier to entry with a first-month discount. Users are more likely to try your product when the cost feels small and the commitment minimal.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;2. Perfect for campaigns&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Tie an intro offer to a seasonal push, like a back-to-school special or holiday promotion. Every eligible new user gets the same clear, consistent discount at checkout.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;3. Smarter than free trials&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Free trials can attract the wrong audience or lead to failed charges. A low introductory price validates payment details and engages more serious users.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;4. Keep analytics clean&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Your metrics remain accurate because the intro period and regular subscription are tracked as a single lifecycle so LTV, retention, and cohort data stay intact.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;640&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Blog-Visual_Introductory-Offer-for-Web_Customer-journey-diagram-1-1024x640.png&quot; alt=&quot;&quot; class=&quot;wp-image-45601&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Blog-Visual_Introductory-Offer-for-Web_Customer-journey-diagram-1-1024x640.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Blog-Visual_Introductory-Offer-for-Web_Customer-journey-diagram-1-300x188.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Blog-Visual_Introductory-Offer-for-Web_Customer-journey-diagram-1-768x480.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Blog-Visual_Introductory-Offer-for-Web_Customer-journey-diagram-1-1536x960.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Blog-Visual_Introductory-Offer-for-Web_Customer-journey-diagram-1-2048x1280.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Blog-Visual_Introductory-Offer-for-Web_Customer-journey-diagram-1-50x31.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Blog-Visual_Introductory-Offer-for-Web_Customer-journey-diagram-1-64x40.png 64w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Blog-Visual_Introductory-Offer-for-Web_Customer-journey-diagram-1-696x435.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Blog-Visual_Introductory-Offer-for-Web_Customer-journey-diagram-1-560x350.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Blog-Visual_Introductory-Offer-for-Web_Customer-journey-diagram-1-474x296.png 474w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Blog-Visual_Introductory-Offer-for-Web_Customer-journey-diagram-1-755x472.png 755w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Blog-Visual_Introductory-Offer-for-Web_Customer-journey-diagram-1-80x50.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Blog-Visual_Introductory-Offer-for-Web_Customer-journey-diagram-1-48x30.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;best-practices-for-introductory-offers&quot;&gt;Best practices for Introductory Offers&lt;/h2&gt;



&lt;p&gt;Introductory Offers are powerful, but the way you design them determines their impact. Here are strategies we’ve seen succeed across subscription apps:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Match pricing to intent&lt;/strong&gt;&lt;br&gt;Shorter intro periods (like 1 week or 1 month) create urgency and higher upfront revenue. Longer periods (e.g., 3 months) can work for seasonal campaigns or higher-consideration products.&lt;br&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Test vs. free trials&lt;/strong&gt;&lt;br&gt;Many apps find that a $0 trial attracts users who never convert, while a low intro price brings in more committed subscribers. Run A/B tests to see which model produces better retention.&lt;br&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Align web and mobile&lt;/strong&gt;&lt;br&gt;Users expect consistency. If you’re running an App Store intro offer, consider mirroring it on web. Or, create complementary offers that make sense for different acquisition channels.&lt;br&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Use scarcity strategically&lt;/strong&gt;&lt;br&gt;Limited-time offers (e.g., “first month $1 for back-to-school”) can boost urgency, but overuse reduces credibility. Balance evergreen offers with campaign-specific ones.&lt;br&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Track beyond conversion&lt;/strong&gt;&lt;br&gt;Intro Offers can inflate early signups. Measure whether users acquired this way retain longer and spend more over time.&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;how-revenuecat-introductory-offers-stand-out&quot;&gt;How RevenueCat Introductory Offers stand out&lt;/h2&gt;



&lt;p&gt;With RevenueCat Introductory Offers, every eligible new subscriber receives the discount automatically, no promo codes to manage, no custom eligibility scripts to maintain. The system handles it for you, so every checkout feels seamless for the user and maintenance-free for your team.&lt;/p&gt;



&lt;p&gt;All of your offers are managed in one central place, right inside the RevenueCat dashboard. You can create, edit, and monitor offers without touching code or juggling multiple tools, giving you full control over pricing strategies.&lt;/p&gt;



&lt;p&gt;Introductory Offers also work in harmony with your mobile store setups. You can match App Store or Play Store promotions to keep the experience consistent across platforms, or design complementary web offers that give you more flexibility in how you acquire and convert different audiences.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;why-introductory-offers-matter&quot;&gt;Why Introductory Offers matter&lt;/h2&gt;



&lt;p&gt;Introductory pricing works because it lowers the barrier to entry without committing you to a permanent discount, and because it sets clear expectations for what happens next. The same approach now applies on web, fully integrated, automatically applied, and tracked just like any other subscription in RevenueCat.&lt;/p&gt;



&lt;p&gt;You can use it to run seasonal promos, experiment with onboarding flows, or create pricing that resonates in specific markets. The setup takes minutes, but the impact can last through the entire subscriber lifecycle.&lt;/p&gt;



&lt;p&gt;If you want to dig into the strategy behind effective intro pricing, David Vargas has broken down the mechanics, psychology, and data in &lt;a href=&quot;https://www.revenuecat.com/blog/growth/introductory-offers-apps/&quot;&gt;Introductory Offers: What They Are and How to Use Them to Grow Your App&lt;/a&gt;.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-get-started-today&quot;&gt;Get started today&lt;/h2&gt;



&lt;p&gt;Introductory Offers are live now for all &lt;a href=&quot;https://www.revenuecat.com/docs/web/web-billing/overview&quot;&gt;RevenueCat Web Billing&lt;/a&gt; customers. Whether you’re aiming to boost campaign performance, refine onboarding, or keep your analytics cleaner, this feature is ready to work for you.&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/web/web-billing/product-setup#introductory-period&quot;&gt;Read the documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Make your first impression count. Turn web visitors into customers with RevenueCat Introductory Offers.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[When paywalls get weird (and work)]]></title><description><![CDATA[How breaking UX rules can drive surprising subscription lifts]]></description><link>https://www.revenuecat.com/blog/growth/weird-paywalls-drive-subscription-growth/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/weird-paywalls-drive-subscription-growth/</guid><pubDate>Tue, 19 Aug 2025 09:34:07 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/weird-paywalls-drive-subscription-growth-v1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;I’m going to out myself as a non-native Londoner here and admit that I like riding the tube. I know, I know, it’s sweaty, loud, and crowded. But hear me out: I love looking at all the ads. They’re plastered all over the stations and trains themselves.&lt;/p&gt;



&lt;p&gt;In fact, there aren’t many places in a city where you won’t see ads. In &lt;em&gt;Love Actually&lt;/em&gt;, they say love is all around us. But dare I say that &lt;em&gt;ads&lt;/em&gt; are all around us?&lt;/p&gt;



&lt;p&gt;The reason I love them so much is the creativity. In the vicious fight for attention, marketers are pulling all guns out and going in blazing. From Surreal, the &lt;a href=&quot;https://fastuna.com/blog/unpacking-surreal-ad-campaign&quot;&gt;breakfast cereal using ‘fake’ celebrities&lt;/a&gt; to endorse their cereals to… Duolingo is announcing that the owl we simultaneously love and fear is dead—false alarm. Go do your daily lesson already.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;858&quot; height=&quot;709&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Surreals-‘celebrity-campaign.png&quot; alt=&quot;&quot; class=&quot;wp-image-45405&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Surreals-‘celebrity-campaign.png 858w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Surreals-‘celebrity-campaign-300x248.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Surreals-‘celebrity-campaign-768x635.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Surreals-‘celebrity-campaign-50x41.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Surreals-‘celebrity-campaign-48x40.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Surreals-‘celebrity-campaign-562x464.png 562w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Surreals-‘celebrity-campaign-696x575.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Surreals-‘celebrity-campaign-560x463.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Surreals-‘celebrity-campaign-358x296.png 358w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Surreals-‘celebrity-campaign-571x472.png 571w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Surreals-‘celebrity-campaign-80x66.png 80w&quot; sizes=&quot;auto, (max-width: 858px) 100vw, 858px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Credit: Surreals ‘celebrity’ campaign&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;962&quot; height=&quot;654&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Duolingo-Duo-or-Die.png&quot; alt=&quot;&quot; class=&quot;wp-image-45407&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Duolingo-Duo-or-Die.png 962w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Duolingo-Duo-or-Die-300x204.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Duolingo-Duo-or-Die-768x522.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Duolingo-Duo-or-Die-50x34.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Duolingo-Duo-or-Die-59x40.png 59w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Duolingo-Duo-or-Die-683x464.png 683w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Duolingo-Duo-or-Die-696x473.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Duolingo-Duo-or-Die-560x381.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Duolingo-Duo-or-Die-435x296.png 435w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Duolingo-Duo-or-Die-694x472.png 694w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Duolingo-Duo-or-Die-80x54.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Duolingo-Duo-or-Die-48x33.png 48w&quot; sizes=&quot;auto, (max-width: 962px) 100vw, 962px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Credit: Duolingo, Duo or Die&amp;nbsp;&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;Then I look at app paywalls and just feel… underwhelmed, the most important moment falls flat. It’s always the same setup, with the same few variations… to add benefits or not? Social proof or no social proof?&amp;nbsp;&lt;/p&gt;



&lt;p&gt;It’s like all the creative steam ran out by the time they got to that part of the journey. Which is such a shame, especially now that tools like &lt;a href=&quot;https://www.revenuecat.com/feature/paywalls/&quot;&gt;RevenueCat Paywalls&lt;/a&gt; make it easier than ever to test and tweak paywalls.&lt;/p&gt;



&lt;p&gt;To be fair, you’re asking someone to pay for your app, so of course, you want to come across as professional. But is that all we can do? Maybe it’s time to get a little &lt;em&gt;weird&lt;/em&gt;.&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-1bQwLV wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Find inspiration with real paywall examples on Paywalls.com&quot; text=&quot;&lt;p&gt;Browse real examples at &lt;a href=&amp;quot;https://www.paywalls.com/&amp;quot; target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noopener&amp;quot;&gt;Paywalls.com&lt;/a&gt;: filter paywall screens by different UI elements, app category, and trending and top-growth paywalls.&lt;/p&gt;&quot; icon=&quot;sparks&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-santa-claus-is-coming-to-apps&quot;&gt;Santa Claus is coming to apps&lt;/h2&gt;



&lt;p&gt;Before you panic, it’s not December. Don’t worry, 2025 is going fast, but not &lt;em&gt;that&lt;/em&gt; fast. And yet, Santa Claus is coming to apps. At least, according to &lt;a href=&quot;https://coinstats.app/&quot;&gt;CoinStats&lt;/a&gt;, a cryptocurrency app. When they presented their &lt;a href=&quot;https://youtu.be/MlFKOeSUgQY?si=jxX0T5o44IZ2w38W&quot;&gt;paywall experiments at the App Promotion Summit&lt;/a&gt; in London in May, I was expecting the usual suspects: an honest paywall, a bit more personalization, maybe a slicker design.&lt;/p&gt;



&lt;p&gt;Instead, &lt;a href=&quot;https://www.linkedin.com/in/ACoAAATBG6oBN7V8xaFoYAfTTcmVLUtA23HNgyg/&quot;&gt;Tigran Mkrtchyan&lt;/a&gt;, their Head of Digital Marketing, unveiled an animated frog, a funky Santa Claus, and a creepy spider… wait, what? Rather than letting the paywall simply appear, they turned it into a full-blown animation that gradually revealed the screen. I won’t lie, I laughed out loud.&lt;/p&gt;



&lt;p&gt;This wasn’t your average Santa either. This was &lt;em&gt;Giga Chad&lt;/em&gt; Santa Claus. Maybe I live under a rock (okay, I probably do, I regularly need my Gen Z sister to decode TikTok trends for me), but I had no idea who Giga Chad was. Is it just me?!&lt;/p&gt;



&lt;p&gt;Turns out, this hyper-masculine meme version of Santa was a hit in the crypto community. They love the guy.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-wp-embed is-provider-wistia-inc wp-block-embed-wistia-inc&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; class=&quot;wp-embedded-content&quot; sandbox=&quot;allow-scripts&quot; security=&quot;restricted&quot; title=&quot;CoinStats - New Year 2025 Giga Chad Video&quot; src=&quot;https://fast.wistia.net/embed/iframe/6of553r0q6?dnt=1#?secret=MZpg7V09gH&quot; data-secret=&quot;MZpg7V09gH&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; width=&quot;500&quot; height=&quot;281&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;So with their weird paywall, CoinStats managed to hit a triple whammy:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;It nailed &lt;a href=&quot;https://lectera.com/info/articles/situational-marketing&quot;&gt;situational marketing&lt;/a&gt; by tapping into a trending meme&lt;/li&gt;



&lt;li&gt;It was seasonally relevant, tying in with Christmas&lt;/li&gt;



&lt;li&gt;And it broke the expected pattern, making the experience memorable and attention-grabbing&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;The first two points are especially powerful because so often, people see offers and think, &lt;em&gt;“It’ll probably still be there later.”&lt;/em&gt; If we can wait to do something, we will.&lt;/p&gt;



&lt;p&gt;We’re bombarded with discounts every day. I can’t be the only one who’s skeptical of &lt;a href=&quot;https://www.revenuecat.com/blog/growth/subscription-pricing-psychology-how-to-influence-purchasing-decisions/&quot;&gt;countdown timers&lt;/a&gt; (though I’ll admit…I still fall for them now and then). But by linking the offer to a trending moment &lt;em&gt;and&lt;/em&gt; the time of year, it feels more real. You believe that not only is Santa Claus coming to town just once, but so is that 60% off deal. It also makes it feel more relevant to you, referring to what is essentially an ‘inside joke’.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;535&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/CoinStats-Playing-into-the-fact-that-it-was-a-good-time-to-invest-535x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-45434&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/CoinStats-Playing-into-the-fact-that-it-was-a-good-time-to-invest-535x1024.png 535w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/CoinStats-Playing-into-the-fact-that-it-was-a-good-time-to-invest-157x300.png 157w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/CoinStats-Playing-into-the-fact-that-it-was-a-good-time-to-invest-26x50.png 26w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/CoinStats-Playing-into-the-fact-that-it-was-a-good-time-to-invest-21x40.png 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/CoinStats-Playing-into-the-fact-that-it-was-a-good-time-to-invest-243x464.png 243w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/CoinStats-Playing-into-the-fact-that-it-was-a-good-time-to-invest-696x1331.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/CoinStats-Playing-into-the-fact-that-it-was-a-good-time-to-invest-293x560.png 293w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/CoinStats-Playing-into-the-fact-that-it-was-a-good-time-to-invest-155x296.png 155w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/CoinStats-Playing-into-the-fact-that-it-was-a-good-time-to-invest-247x472.png 247w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/CoinStats-Playing-into-the-fact-that-it-was-a-good-time-to-invest-42x80.png 42w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/CoinStats-Playing-into-the-fact-that-it-was-a-good-time-to-invest-25x48.png 25w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/CoinStats-Playing-into-the-fact-that-it-was-a-good-time-to-invest.png 754w&quot; sizes=&quot;auto, (max-width: 535px) 100vw, 535px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Credit: CoinStats: Playing into the fact that it was a good time to invest&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;In reality, this wasn’t a once-a-year offer, but part of an ongoing strategy. CoinStats continued to tweak and roll out different versions throughout the year. The Giga Chad Santa paywall was actually a follow-up to a successful Halloween version, where they tested a similar offer with a bitcoin-inspired spider:&amp;nbsp;&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;819&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/The-spider-paywall-819x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-45436&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/The-spider-paywall-819x1024.png 819w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/The-spider-paywall-240x300.png 240w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/The-spider-paywall-768x960.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/The-spider-paywall-40x50.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/The-spider-paywall-32x40.png 32w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/The-spider-paywall-371x464.png 371w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/The-spider-paywall-696x870.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/The-spider-paywall-448x560.png 448w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/The-spider-paywall-237x296.png 237w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/The-spider-paywall-378x472.png 378w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/The-spider-paywall-64x80.png 64w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/The-spider-paywall-38x48.png 38w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/The-spider-paywall.png 1080w&quot; sizes=&quot;auto, (max-width: 819px) 100vw, 819px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Credit: CoinStats: The spider paywall&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;But do all these quirky, animated paywalls actually perform? Tigran shared the results from their original froggy campaign that came before Santa Claus, and they were incredible. The early performance was so strong that it paved the way for further experiments.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;576&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Results-of-the-initial-paywall-test-1024x576.png&quot; alt=&quot;&quot; class=&quot;wp-image-45440&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Results-of-the-initial-paywall-test-1024x576.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Results-of-the-initial-paywall-test-300x169.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Results-of-the-initial-paywall-test-768x432.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Results-of-the-initial-paywall-test-1536x864.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Results-of-the-initial-paywall-test-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Results-of-the-initial-paywall-test-71x40.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Results-of-the-initial-paywall-test-696x392.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Results-of-the-initial-paywall-test-560x315.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Results-of-the-initial-paywall-test-526x296.png 526w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Results-of-the-initial-paywall-test-840x472.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Results-of-the-initial-paywall-test-80x45.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Results-of-the-initial-paywall-test-48x27.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Results-of-the-initial-paywall-test.png 2000w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;From the results we saw that the conversion rate improved significantly for both Android and iOS resulting in an average lift of 2.9x.&lt;/p&gt;



&lt;p&gt;Why else does this kind of paywall actually perform so well? Tigran believes it’s not just about surprise or standing out, it’s also about encouraging an &lt;a href=&quot;https://www.businessofapps.com/insights/paywall-optimization-reimagined/&quot;&gt;emotional connection&lt;/a&gt; by relating to memes and well-known icons. CoinStats had already seen this work well in &lt;a href=&quot;https://tigranmk.substack.com/p/bear-marketing&quot;&gt;another case study&lt;/a&gt; where they changed the Bitcoin icon to Bobo the Bear—a meme symbol for market downturns—when Bitcoin hit an all-time high. It got people talking, smiling, and most importantly, &lt;em&gt;engaging&lt;/em&gt;.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;721&quot; height=&quot;362&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Tigranmk-Substack.png&quot; alt=&quot;&quot; class=&quot;wp-image-45442&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Tigranmk-Substack.png 721w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Tigranmk-Substack-300x151.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Tigranmk-Substack-50x25.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Tigranmk-Substack-80x40.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Tigranmk-Substack-696x349.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Tigranmk-Substack-560x281.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Tigranmk-Substack-48x24.png 48w&quot; sizes=&quot;auto, (max-width: 721px) 100vw, 721px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Credit: Tigranmk Substack&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;In case you’re as confused as I was to meet Giga Chad Santa Claus, let me break it down for you. A bear market = a downturn, while a bull market (what was referenced in the Christmas paywall) = an upturn. So why show a bear when things are going well? Because poor Bobo (a beloved meme in crypto culture) is sad that it’s not a bull market. The emotional twist struck a chord.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;It generated a wave of tweets from large Crypto accounts about the bear, and they saw the highest Google Search traffic of the last 16 months, along with the second-highest amount of App Store downloads in the last year. All because of a sad bear. This is the secondary benefit from getting weird, it can accidentally also increase your word of mouth (if you get weird enough).&lt;/p&gt;



&lt;p&gt;While that isn’t quite a paywall, it highlights another example of how breaking the mold gets you standing out and people talking about you.&lt;br&gt;&lt;br&gt;However, I also appreciate that this may not be the way forward for everyone, so let’s look at some more weird approaches to paywalls you could consider that are a bit tamer.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-a-llama-full-of-water&quot;&gt;A llama full of water&lt;/h2&gt;



&lt;p&gt;&lt;a href=&quot;https://waterllama.com/&quot;&gt;Waterllama&lt;/a&gt; is a water tracker app that helps you build a sustainable hydration habit. This may sound like an obvious thing, but I live with a man who regularly exists on one glass of water a day, usually forced on him by me. Their app shows the animal water tracker getting filled up on the paywall; the llama is thirsty, too.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-wp-embed is-provider-wistia-inc wp-block-embed-wistia-inc&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; class=&quot;wp-embedded-content&quot; sandbox=&quot;allow-scripts&quot; security=&quot;restricted&quot; title=&quot;WaterLlama - Animated Carousel Video&quot; src=&quot;https://fast.wistia.net/embed/iframe/lzt89hmqpb?dnt=1#?secret=cMlZBYZjYN&quot; data-secret=&quot;cMlZBYZjYN&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; width=&quot;346&quot; height=&quot;750&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;The llama isn’t just for entertainment value; it’s part of a broader carousel that highlights the different features at the top of the screen. They get even more quirky with the llama I realised as I continued to test the app. I got offered to hit (aka tap) a llama pinata to open a special lifetime deal and at the top of that deal there is a very excited llama in a bucket hat (definitely a phrase I never thought I’d say).&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;473&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Tap-the-llama-pinata-to-unlock-a-special-offer-473x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-45445&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Tap-the-llama-pinata-to-unlock-a-special-offer-473x1024.png 473w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Tap-the-llama-pinata-to-unlock-a-special-offer-139x300.png 139w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Tap-the-llama-pinata-to-unlock-a-special-offer-768x1663.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Tap-the-llama-pinata-to-unlock-a-special-offer-709x1536.png 709w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Tap-the-llama-pinata-to-unlock-a-special-offer-23x50.png 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Tap-the-llama-pinata-to-unlock-a-special-offer-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Tap-the-llama-pinata-to-unlock-a-special-offer-214x464.png 214w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Tap-the-llama-pinata-to-unlock-a-special-offer-696x1507.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Tap-the-llama-pinata-to-unlock-a-special-offer-259x560.png 259w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Tap-the-llama-pinata-to-unlock-a-special-offer-137x296.png 137w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Tap-the-llama-pinata-to-unlock-a-special-offer-218x472.png 218w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Tap-the-llama-pinata-to-unlock-a-special-offer-37x80.png 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Tap-the-llama-pinata-to-unlock-a-special-offer-22x48.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Tap-the-llama-pinata-to-unlock-a-special-offer.png 923w&quot; sizes=&quot;auto, (max-width: 473px) 100vw, 473px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Tap the llama pinata to unlock a special offer&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;473&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/An-excited-llama-about-a-lifetime-offer-473x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-45447&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/An-excited-llama-about-a-lifetime-offer-473x1024.png 473w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/An-excited-llama-about-a-lifetime-offer-139x300.png 139w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/An-excited-llama-about-a-lifetime-offer-768x1663.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/An-excited-llama-about-a-lifetime-offer-709x1536.png 709w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/An-excited-llama-about-a-lifetime-offer-23x50.png 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/An-excited-llama-about-a-lifetime-offer-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/An-excited-llama-about-a-lifetime-offer-214x464.png 214w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/An-excited-llama-about-a-lifetime-offer-696x1507.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/An-excited-llama-about-a-lifetime-offer-259x560.png 259w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/An-excited-llama-about-a-lifetime-offer-137x296.png 137w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/An-excited-llama-about-a-lifetime-offer-218x472.png 218w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/An-excited-llama-about-a-lifetime-offer-37x80.png 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/An-excited-llama-about-a-lifetime-offer-22x48.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/An-excited-llama-about-a-lifetime-offer.png 923w&quot; sizes=&quot;auto, (max-width: 473px) 100vw, 473px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;With paywalls often consisting of a single screen, it’s easy to miss a small feature callout. Waterllama manages to pack a lot by showing a small animation per feature that brings its relatively standard first screen of a paywall to life:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;473&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/WaterLlama-Paywall-on-iPhone-473x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-45449&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/WaterLlama-Paywall-on-iPhone-473x1024.png 473w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/WaterLlama-Paywall-on-iPhone-139x300.png 139w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/WaterLlama-Paywall-on-iPhone-768x1663.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/WaterLlama-Paywall-on-iPhone-709x1536.png 709w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/WaterLlama-Paywall-on-iPhone-23x50.png 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/WaterLlama-Paywall-on-iPhone-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/WaterLlama-Paywall-on-iPhone-214x464.png 214w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/WaterLlama-Paywall-on-iPhone-696x1507.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/WaterLlama-Paywall-on-iPhone-259x560.png 259w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/WaterLlama-Paywall-on-iPhone-137x296.png 137w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/WaterLlama-Paywall-on-iPhone-218x472.png 218w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/WaterLlama-Paywall-on-iPhone-37x80.png 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/WaterLlama-Paywall-on-iPhone-22x48.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/WaterLlama-Paywall-on-iPhone.png 923w&quot; sizes=&quot;auto, (max-width: 473px) 100vw, 473px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Credit: WaterLlama Paywall on iPhone&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;Interestingly, they also offer a landing page-style scroll, where you can scroll further through the various features and social proof. The reviews can be found lower on the page.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;This is also referred to as long-form/conversion-focused paywalls (though which paywall isn’t conversion focused?) and allows you to add far more content into your landing page for those not yet convinced to upgrade.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Here’s how they structure the rest of the paywall:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Awards they’ve won for their app&lt;/li&gt;



&lt;li&gt;A bigger breakdown of each feature&lt;/li&gt;



&lt;li&gt;A review block of the app&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Throughout the page, there is a sticky CTA to keep you focused on the upgrade.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-wp-embed is-provider-wistia-inc wp-block-embed-wistia-inc&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; class=&quot;wp-embedded-content&quot; sandbox=&quot;allow-scripts&quot; security=&quot;restricted&quot; title=&quot;WaterLlama - Scrollable Paywall Video&quot; src=&quot;https://fast.wistia.net/embed/iframe/4acz9jkfif?dnt=1#?secret=B5tVacPtfz&quot; data-secret=&quot;B5tVacPtfz&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; width=&quot;346&quot; height=&quot;750&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;My theory is that because the paywall appears so quickly after downloading the app, they want to make sure that if you’re not convinced yet, you’ll be curious enough to look a little closer.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-away-from-the-paywall&quot;&gt;Step away from the paywall&lt;/h2&gt;



&lt;p&gt;&lt;a href=&quot;https://www.capcut.com/&quot;&gt;CapCut&lt;/a&gt;, an AI-powered video and image editor owned by ByteDance (TikTok’s parent company), takes this concept a step further with their paywall. Instead of simply listing features, their paywall lets you click through examples of all the features on both their standard and pro plans. These features are automatically displayed one by one, with animations that demonstrate how they work. For such a visual app, this is a fantastic way of showing, rather than just telling, what the app can do. It’s interactive and gives users a hands-on preview of what they’re getting, making the paywall feel like part of the experience rather than an obstacle.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-wp-embed is-provider-wistia-inc wp-block-embed-wistia-inc&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; class=&quot;wp-embedded-content&quot; sandbox=&quot;allow-scripts&quot; security=&quot;restricted&quot; title=&quot;CapCut - Animated Header Video&quot; src=&quot;https://fast.wistia.net/embed/iframe/hdeij65t40?dnt=1#?secret=Ct1WPAoXr1&quot; data-secret=&quot;Ct1WPAoXr1&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; width=&quot;346&quot; height=&quot;750&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;The paywall is also a landing page. Now, CapCut breaks two classic ‘rules’ of web landing pages:&amp;nbsp;&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;It uses a carousel at the top of the page&lt;/li&gt;



&lt;li&gt;Each feature further down the page can be clicked, meaning you’d leave the paywall.&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Cleverly, though, each feature you can click through to has a clear upgrade button at the bottom, making it feel part of the paywall. Given they were estimated to have made &lt;a href=&quot;https://appfigures.com/resources/insights/20240426?f=5&quot;&gt;$59 million in a quarter last year&lt;/a&gt;, I’m assuming they’ve tested this and found it works. CapCut isn’t afraid to color outside the lines, and that clearly works in their favor.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-wp-embed is-provider-wistia-inc wp-block-embed-wistia-inc&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; class=&quot;wp-embedded-content&quot; sandbox=&quot;allow-scripts&quot; security=&quot;restricted&quot; title=&quot;CapCut - Sub landingpages Video&quot; src=&quot;https://fast.wistia.net/embed/iframe/19uofc8zd5?dnt=1#?secret=Hy6j5yszRM&quot; data-secret=&quot;Hy6j5yszRM&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; width=&quot;346&quot; height=&quot;750&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;Most paywalls don’t allow scrolling (let alone secondary pages), but it’s an interesting way to show more and convince your audience of your app’s value.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-don-t-leave-me-hanging-what-s-the-offer&quot;&gt;Don’t leave me hanging, what’s the offer?&lt;/h2&gt;



&lt;p&gt;A paywall that teases you to find out your discount? The cheek, the nerve, the &lt;em&gt;brilliance&lt;/em&gt; of it. In my research into funky paywalls, I came across a great newsletter on &lt;a href=&quot;https://www.retention.blog/&quot;&gt;Retention.blog&lt;/a&gt; by Jacob Rushkinn. I’ve never met Jacob, but it turns out we were both pondering the same thing, albeit on different sides of the Atlantic: Why are paywalls so incredibly boring?&lt;/p&gt;



&lt;p&gt;While I don’t have the perfect answer to that question either, I loved the example Jacob shared of how Flo, a period and health tracking app, uses an Instagram story-style paywall. It’s not just a straightforward ask for money; it’s interactive. Users are prompted to “swipe to reveal your discount.” It’s playful, engaging, and adds an element of curiosity and excitement to an otherwise mundane part of the app journey. A small tweak like this makes a huge difference in breaking up the monotony of typical paywalls.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;576&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Is-your-paywall-boring-2-1024x576.png&quot; alt=&quot;&quot; class=&quot;wp-image-45424&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Is-your-paywall-boring-2-1024x576.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Is-your-paywall-boring-2-300x169.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Is-your-paywall-boring-2-768x432.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Is-your-paywall-boring-2-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Is-your-paywall-boring-2-71x40.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Is-your-paywall-boring-2-696x392.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Is-your-paywall-boring-2-560x315.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Is-your-paywall-boring-2-526x296.png 526w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Is-your-paywall-boring-2-840x472.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Is-your-paywall-boring-2-80x45.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Is-your-paywall-boring-2-48x27.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Is-your-paywall-boring-2.png 1456w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Credit: Jacob Rushkinn newsletter “🥱 Is your paywall boring?”&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;It brings excitement and suspense into the paywall—what will it be?! A quick swipe up revealed a whopping &lt;em&gt;86% off for lifetime&lt;/em&gt;, meaning users could get Flo at just $24.99. And if you decided, “Nah, I’m good,” they hit you with the ultimate emotional manipulation: a crying teddy bear, talk about a guilt trip.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;1000&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Is-your-paywall-boring.png&quot; alt=&quot;&quot; class=&quot;wp-image-45422&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Is-your-paywall-boring.png 1000w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Is-your-paywall-boring-300x300.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Is-your-paywall-boring-150x150.png 150w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Is-your-paywall-boring-768x768.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Is-your-paywall-boring-50x50.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Is-your-paywall-boring-40x40.png 40w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Is-your-paywall-boring-464x464.png 464w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Is-your-paywall-boring-696x696.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Is-your-paywall-boring-560x560.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Is-your-paywall-boring-296x296.png 296w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Is-your-paywall-boring-472x472.png 472w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Is-your-paywall-boring-80x80.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Is-your-paywall-boring-48x48.png 48w&quot; sizes=&quot;auto, (max-width: 1000px) 100vw, 1000px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Credit: Jacob Rushkinn newsletter “🥱 Is your paywall boring?”&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;I’m not about to recommend offering 86% off, or relying on high discount offers in general, but I have to admit that this is a great example. I think the format of teasing a discount is unique, or even building in a fun Instagram feel to your paywall, with each story introducing a benefit and value of the app before getting to the paywall. Alternatively it could be a series of transformations of how the app helped individuals achieve their goals before going to a paywall.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-testing-out-your-weird-paywall&quot;&gt;Testing out your weird paywall&lt;/h2&gt;



&lt;p&gt;We’ve covered some wonderfully weird animals—from a bitcoin spider to a water-filled llama to a tearful bear—but weird paywalls aren’t really about the animals. I know, it’s shocking. They’re about breaking the mold, getting creative, and daring to try something different instead of defaulting to the standard copy-and-paste approach.&lt;/p&gt;



&lt;p&gt;So here’s a challenge: sit down with your team for a creative brainstorm. Use these examples not as templates, but as inspiration for how you might get a little weird in your own way. &lt;/p&gt;



&lt;p&gt;A few ideas to kick things off:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Animate your paywall entrance&lt;/li&gt;



&lt;li&gt;Tap into a timely or cultural reference&lt;/li&gt;



&lt;li&gt;Add relevant animations to &lt;em&gt;show&lt;/em&gt; how features work&lt;/li&gt;



&lt;li&gt;Turn your paywall into an engaging landing page&lt;/li&gt;



&lt;li&gt;Create in-depth pages to explain value, not just list features&lt;/li&gt;



&lt;li&gt;Try a swipeable, story-style paywall&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;strong&gt;The point isn’t to replicate, it’s to reimagine.&lt;/strong&gt; I’m not saying that you need to slap buff Santa all over your paywall, as tempting as that might be. Find your own version of buff Santa. Bring in your marketing team, your designers, and especially your social media person. You never know who’s got the perfect quirky idea up their sleeve. Throw out the textbook and think out of the box, as laughing could be the key to opening up your customers’ wallets.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[5 app monetization trends you can’t ignore in 2025]]></title><description><![CDATA[11 experts break down the top 5 monetization trends shaping the year.]]></description><link>https://www.revenuecat.com/blog/growth/2025-app-monetization-trends/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/2025-app-monetization-trends/</guid><pubDate>Fri, 15 Aug 2025 08:18:34 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/hackathon-blog-header-blue.webp" length="0" type="image/*"/><content:encoded>&lt;p&gt;2025 already feels like a fascinating year for app monetization. In just the first half of the year, we’ve seen:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;AI reshaping cost structures&lt;/li&gt;



&lt;li&gt;Competition intensifying as building apps becomes increasingly easy — perhaps too easy, but that’s a topic for another day&lt;/li&gt;



&lt;li&gt;The battle between native IAP and web checkout heating up, joined by a &lt;a href=&quot;https://www.revenuecat.com/blog/growth/external-ios-payments-pros-cons-gotchas/&quot;&gt;new potential contender of app-to-web&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;Paywalls becoming &lt;a href=&quot;https://www.revenuecat.com/blog/growth/announcing-revenuecat-paywalls-v2/&quot;&gt;easier than ever to build in RevenueCat&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;And we are only halfway through the year.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;There’s so much happening in monetization right now that I honestly couldn’t keep up, so I called in some of the best minds in the space. Think of them as the Glastonbury headliners of the app world: the ones everyone stops to watch, no matter what stage they’re on.&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;a href=&quot;/blog/post_author/alice-muir-kocourkova/&quot;&gt;Alice Muir Kocourková&lt;/a&gt; – Growth Lead at Phiture&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.linkedin.com/in/andycarvell/&quot;&gt;Andy Carvell&lt;/a&gt; – Co-Founder &amp;amp; CEO at Phiture&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.linkedin.com/in/cristianrotari/&quot;&gt;Cristian Rotari&lt;/a&gt; – Senior Product Manager at Zing Coach&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.linkedin.com/in/ekaterina-shpadareva-gamsriegler/&quot;&gt;Ekaterina Gamsriegler&lt;/a&gt; – Head of Marketing &amp;amp; Growth at MyGroove&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/author/hannah-parvaz/&quot;&gt;Hannah Parvaz&lt;/a&gt; – Founder of Aperture&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/author/nathan-hudson/&quot;&gt;Nathan Hudson&lt;/a&gt; – Founder of Perceptycs&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.linkedin.com/in/lea-samrani/&quot;&gt;Léa Samrani&lt;/a&gt; – VP Growth at Passion.io&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.linkedin.com/in/rosie-hoggmascall/&quot;&gt;Rosie Hoggmascall&lt;/a&gt; – Product Growth Expert&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.linkedin.com/in/sylvaingauchet/&quot;&gt;Sylvain Gauchet&lt;/a&gt; – Growth Consultant &amp;amp; Advisor&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/author/thomas-petit/&quot;&gt;Thomas Petit&lt;/a&gt; – &lt;a href=&quot;https://x.com/Thomasbcn&quot;&gt;@thomasbcn&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.revenuecat.com/blog/author/vahe-baghdasaryan/&quot;&gt;Vahe Baghdasaryan&lt;/a&gt; – Founder at paywalls.design&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Okay, so I didn’t hit the full Glastonbury setlist, but this top 11 lineup is still something I’m pretty proud of. Step aside, Ed Sheeran.&lt;/p&gt;



&lt;p&gt;Some of these insights came directly from conversations, others were pulled from the &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps-2025/&quot;&gt;&lt;em&gt;State of Subscription Apps (SOSA) Report 2025&lt;/em&gt;&lt;/a&gt; or past discussions. I asked what they’ve seen so far this year and what they expect to unfold in the months ahead.&lt;/p&gt;



&lt;p&gt;The result? A fascinating mix of sharp takes, surprising trends, and thoughtful predictions. I learned a lot, and I think you will too.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-trend-1-premium-pricing-is-the-new-norm&quot;&gt;Trend 1: Premium pricing is the new norm&lt;/h2&gt;



&lt;p&gt;If you’ve overanalyzed the &lt;em&gt;State of Subscription Apps Report&lt;/em&gt; like I have, you may have noticed something interesting about pricing changes this year vs last:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;557&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-3-1024x557.png&quot; alt=&quot;&quot; class=&quot;wp-image-45558&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-3-1024x557.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-3-300x163.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-3-768x418.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-3-50x27.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-3-73x40.png 73w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-3-696x379.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-3-560x305.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-3-544x296.png 544w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-3-840x457.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-3-80x44.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-3-48x26.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-3.png 1319w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Average app prices this year vs the previous year&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;It’s a fun game of spot the difference: the median and bottom quartile prices haven’t really moved, but look closely at the upper quartile and P90, especially for annual plans, and there’s a small but noticeable uptick of around 5%.&lt;/p&gt;



&lt;p&gt;That might’ve been our first signal of a trend I’ve now heard two experts call out: the best are pricing higher. Rosie Hoggmascall, a Product Growth expert focused on PLG, UX, and monetization (and author of &lt;a href=&quot;https://growthdives.com/&quot;&gt;&lt;em&gt;Growth Dives&lt;/em&gt;&lt;/a&gt;), once told me:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“You’re either pricing to be the best in your category or to be the cheapest; most apps are choosing one or the other”.&amp;nbsp;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;So when Léa Samrani, VP Growth at &lt;a href=&quot;http://passion.io&quot;&gt;Passion.io&lt;/a&gt;, shared the following, it really clicked:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“I’ve seen a rise of the extremes in pricing, maybe I’m a bit biased as I work for Passion.io as VP Growth, and passion apps are often high tickets, but it seems to me that products are positioning themselves&lt;/em&gt;&lt;strong&gt;&lt;em&gt; more clearly in either the affordable category or in high tickets, and I am seeing less middle ground pricing.&lt;/em&gt;&lt;/strong&gt;&lt;em&gt; For example, the new &lt;/em&gt;&lt;a href=&quot;https://go.tonyrobbins.com/tony-ai#:~:text=Available%2024%2F7%20in,Billed%20monthly%2C%20cancel%20anytime.&quot;&gt;&lt;em&gt;Tony Robbins AI app&lt;/em&gt;&lt;/a&gt;&lt;em&gt; is priced at $99/month.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Eek, that is steep if I do say so myself, though they do interestingly enough offer the first 14 days for $1:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;575&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-4-1024x575.png&quot; alt=&quot;&quot; class=&quot;wp-image-45560&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-4-1024x575.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-4-300x168.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-4-768x431.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-4-1536x862.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-4-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-4-71x40.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-4-696x391.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-4-560x314.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-4-527x296.png 527w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-4-840x472.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-4-80x45.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-4-48x27.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-4.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Tony Robbins AI app&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;It feels like premium pricing is getting bolder. Maybe it’s no longer just about being “the best” in your category, and instead, as Léa points out, users no longer expect apps to live in the £5–10/month range.&lt;/p&gt;



&lt;p&gt;So, where is this shift happening the most? Here’s what Léa said:&lt;/p&gt;



&lt;p&gt;&lt;em&gt;“I’ve worked with a handful of creator-led apps this year (mainly in the fitness category), and I see similar things with higher-tier pricing. I see this as apps understanding their category better and being less afraid of higher price positioning when the value and brand strength are strong.”&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;That tracks, especially for someone who pays for far too many of those apps. Fitness and creator-led apps often trade on personal transformation and perceived expertise, making high prices easier to justify. We expect education, self-development, and broader health apps to follow suit.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Our prediction?&lt;/strong&gt; The trend will continue into the second half of 2025. As more high-priced apps succeed, the middle will continue to shrink. Apps will increasingly pick a side: luxury or low cost.&lt;/p&gt;



&lt;p&gt;But with higher prices comes higher expectations—something that leads us into the next trend.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-trend-2-pricing-amp-packaging-get-smarter&quot;&gt;Trend 2: Pricing &amp;amp; packaging get smarter&lt;/h2&gt;



&lt;p&gt;Despite the rise of pricing extremes, or maybe because of them, one thing is clear: &lt;strong&gt;flexibility is everything&lt;/strong&gt;. Alice Muir, Growth Lead at &lt;a href=&quot;https://phiture.com/&quot;&gt;Phiture&lt;/a&gt;, put it well:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“With economic uncertainty and recession concerns hitting multiple markets in 2025, I’ve seen developers become much more flexible in how they price and package subscriptions.&amp;nbsp;The one-size-fits-all model is breaking down; users are &lt;/em&gt;&lt;strong&gt;&lt;em&gt;more price-sensitive, and expectations around value are rising&lt;/em&gt;&lt;/strong&gt;&lt;em&gt;.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;A higher price can work, but only if users understand &lt;em&gt;why&lt;/em&gt; they’re paying more and feel they have options. As Alice explained:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“Successful apps are responding with granular tiers—usage-based plans, one-off purchases, regional pricing, seasonal discounts, or even pause options.&amp;nbsp;In this climate, rigidity will kill growth. Developers need to treat pricing as a dynamic tool, not a fixed decision. The &lt;/em&gt;&lt;strong&gt;&lt;em&gt;most resilient apps are those iterating quickly and aligning monetization with user behavior and regional context&lt;/em&gt;&lt;/strong&gt;&lt;em&gt;, especially outside the U.S., where willingness to pay varies dramatically.”&amp;nbsp;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;To stay indispensable, apps may need to evolve what they offer altogether. Alice pointed to ClassPass (a fitness, wellness, and beauty app) as a prime example:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“The most competitive ones are going a step further, expanding their value proposition entirely—like ClassPass, which now bundles coworking, healthy food, and beauty treatments into what was once just a fitness pass. Staying relevant means evolving with your users, not just pricing for them.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;906&quot; height=&quot;740&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-5.png&quot; alt=&quot;&quot; class=&quot;wp-image-45562&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-5.png 906w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-5-300x245.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-5-768x627.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-5-50x41.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-5-49x40.png 49w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-5-568x464.png 568w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-5-696x568.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-5-560x457.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-5-362x296.png 362w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-5-578x472.png 578w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-5-80x65.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-5-48x39.png 48w&quot; sizes=&quot;auto, (max-width: 906px) 100vw, 906px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;ClassPass used to only offer Fitness, but now offers multiple options depending on the city&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;Cristian Rotari, Senior Product Manager at &lt;a href=&quot;https://www.zing.coach/&quot;&gt;Zing Coach&lt;/a&gt;, sees this flexibility becoming the norm:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“Dynamic pricing and packaging are bound to become more mainstream. Not many apps are doing this well today, mostly because the infrastructure used to be expensive and hard to build. But that’s changing. With the rise of more accessible SDKs and smarter tooling, more teams will start experimenting.&amp;nbsp;&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;&lt;em&gt;The opportunity lies in &lt;/em&gt;&lt;strong&gt;&lt;em&gt;using context that’s already available: onboarding answers, location, or even something like battery level. &lt;/em&gt;&lt;/strong&gt;&lt;em&gt;These signals help tailor not just pricing, but how and when you present it, and help monetization feel less pushy.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Ekaterina Gamsriegler, Head of Growth and Marketing at &lt;a href=&quot;https://mygroove.app/&quot;&gt;MyGroove&lt;/a&gt; and creator of a &lt;a href=&quot;https://maven.com/mathemarketing/growing-mobile-subscription-apps&quot;&gt;top course on Maven on app growth&lt;/a&gt;, sees a similar shift toward monetization flexibility, though often with a sharper edge:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“I have a feeling that many apps are monetizing more aggressively than before, with&lt;/em&gt; a) &lt;em&gt;Bigger discounts, offered earlier (sometimes right after the first paywall skip)&lt;/em&gt; and b) &lt;em&gt;Heavier reliance on onboarding offers to drive conversions. So more apps might be feeling a push for strong short-term revenue to fuel their UA efforts and defend market share, especially in verticals that become more competitive with an influx of AI apps.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;This trend isn’t just about offering more pricing options, but also about finding ways to push monetization earlier and seize high-intent moments quickly, especially in categories where competition is intensifying.&lt;/p&gt;



&lt;p&gt;While you need to be conscious of how you adjust pricing, there is so much potential here, not just to get smarter in terms of price localization, but basically context localization. If you know someone’s battery is about to die, why not offer them a deal they can’t refuse? Don’t give them time to overthink it—because you might lose them for good.&lt;/p&gt;



&lt;p&gt;With the rise of pricing flexibility, we’re seeing smart approaches like:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;More granular tiers&lt;/li&gt;



&lt;li&gt;Localized and contextual pricing (even down to battery level!)&lt;/li&gt;



&lt;li&gt;Value bundling (ClassPass is leading the way)&lt;/li&gt;



&lt;li&gt;Bigger offers, often offered earlier in the user journey&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;In short, pricing is becoming one of the biggest levers for growth, especially in an era of hybrid monetization.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-trend-3-the-hybrid-monetization-boom&quot;&gt;Trend 3: The hybrid monetization boom&lt;/h2&gt;



&lt;p&gt;For a long time, subscriptions were &lt;em&gt;the&lt;/em&gt; go-to monetization model for most apps. The SOSA 2025 report showed that in nearly every industry (except gaming), over 50% of apps offered subscriptions &lt;em&gt;only&lt;/em&gt;.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;543&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-6-1024x543.png&quot; alt=&quot;&quot; class=&quot;wp-image-45564&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-6-1024x543.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-6-300x159.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-6-768x407.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-6-50x27.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-6-75x40.png 75w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-6-696x369.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-6-560x297.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-6-558x296.png 558w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-6-840x445.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-6-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-6-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-6.png 1328w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;But in 2025, that’s starting to shift.&amp;nbsp; More and more apps are mixing models.&lt;/p&gt;



&lt;p&gt;Vahe Baghdasaryan, Founder at &lt;a href=&quot;https://www.paywalls.design/&quot;&gt;paywalls.design&lt;/a&gt;&lt;a href=&quot;https://flo.health/&quot;&gt;,&lt;/a&gt; put it like this in the &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps-2025/&quot;&gt;SOSA 2025 report&lt;/a&gt;:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“Based on the data, gaming apps have a strong mix of both subscriptions and consumables, demonstrating how this model can work effectively. However, most non-gaming categories&lt;/em&gt; &lt;em&gt;remain heavily reliant on subscriptions alone, missing out on additional revenue streams.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;So while subscriptions still dominate, I can’t help but wonder how different that graph will look in next year’s report.&lt;/p&gt;



&lt;p&gt;The experts I spoke to definitely see hybrid monetization on the rise, and if there was one thing my Glastonbury lineup seemed to agree on, it was this. Nearly everyone mentioned seeing more hybrid models emerge.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-subscriptions-in-app-purchases-iaps-nbsp&quot;&gt;Subscriptions + in-app purchases (IAPs)&amp;nbsp;&lt;/h3&gt;



&lt;p&gt;Let’s go back to Cristian Rotari for his thoughts on this increasingly popular strategy:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“A strategy that more and more apps are adopting is hybrid monetization, specifically subscription + IAPs. This approach &lt;/em&gt;&lt;strong&gt;&lt;em&gt;allows apps to upsell without disrupting the main paywall, either on app or web flows.&amp;nbsp;&lt;/em&gt;&lt;/strong&gt;&lt;em&gt;If you have a compelling core offering, you can generate minimal friction and still boost ARPU and ROAS while generating value for the users.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;In other words, one of the most common hybrid models we’re seeing is layering additional in-app purchases on top of a subscription. What does this look like in practice? Cristian shared some examples:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“If you’re a fitness app, you can offer supplements or a nutrition guide. If you’re an app for kids, you could provide printables with it. Fake door experiments are a great way to assess willingness to pay from users, and if the math works, execute.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;The trend is clear: apps are building upsell opportunities into the experience without interfering with the main subscription journey. It’s monetization that adds value, not friction.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-subscriptions-physical-products&quot;&gt;Subscriptions + physical products&lt;/h3&gt;



&lt;p&gt;I can’t help but wonder if Cristian listened to that great &lt;a href=&quot;https://subclub.com/episode/what-readingcom-learned-testing-prices-and-funnels-tim-dikun-teachingcom&quot;&gt;Sub Club podcast episode&lt;/a&gt; with Tim Dikum from &lt;a href=&quot;http://teaching.com&quot;&gt;Teaching.com&lt;/a&gt;—because they’re doing exactly this with &lt;a href=&quot;http://reading.com&quot;&gt;Reading.com&lt;/a&gt;, their app that helps kids learn to read. Not only are they offering printables as an upsell, but they’re also working on launching physical books.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;I’ve also seen BetterMe, the wellness app, take a similar approach by bundling their subscription with a Pilates Essentials Kit to enhance the user’s experience.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;478&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-7-1024x478.png&quot; alt=&quot;&quot; class=&quot;wp-image-45568&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-7-1024x478.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-7-300x140.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-7-768x359.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-7-50x23.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-7-86x40.png 86w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-7-696x325.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-7-560x262.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-7-840x392.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-7-80x37.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-7-48x22.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/image-7.png 1246w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Example of BetterMe combining subscription with physical products&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;Hybrid monetization isn’t just digital anymore. Physical products are becoming part of the mix, helping increase both LTV and perceived value.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-subscriptions-ads&quot;&gt;Subscriptions + ads&lt;/h3&gt;



&lt;p&gt;Thomas Petit, also flagged this trend, highlighting a format that’s making a comeback: ads.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“Hybrid models (subs + ads, subs + IAP, and subs + ecomm) are on the rise. They’re primarily driven by AI, which has variable costs, unlike the previous wave of subs. Full subscription doesn’t fit anymore.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;This shift is especially relevant for apps with freemium models or those operating in markets with lower willingness to pay. And it’s not just ads joining the mix, as Thomas pointed to another emerging hybrid format as well.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-subscriptions-ai-usage-features&quot;&gt;Subscriptions + AI-usage features&lt;/h3&gt;



&lt;p&gt;AI is shifting the economics of monetization. Sylvain Gauchet, Growth Consultant &amp;amp; Advisor and author of the &lt;a href=&quot;https://growthgems.substack.com/&quot;&gt;Growth Gems newsletter&lt;/a&gt;, spoke to this when I asked what trends he’s been seeing:&lt;/p&gt;



&lt;p&gt;&lt;em&gt;“As apps with AI at their core realize that the cost of LLM calls and Gen AI eats too much into their margins, they’re breaking out of the subscription model’s ‘LTV ceiling’, either by:&lt;/em&gt;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;em&gt;Adding usage-based pricing via in-app purchases (giving additional credits). Example: Lensa AI with their Magic Avatars packs.&lt;/em&gt;&lt;/li&gt;



&lt;li&gt;&lt;em&gt;Offering multiple tiers, each including a different number of credits. Example: VSCO with their Plus plan (250 monthly credits) and Premium plan (500 monthly credits).”&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;With AI, user activity directly impacts your costs. So while we’re seeing more pricing flexibility in the name of value, it’s also a response to rising infrastructure costs. That shift is creating new pricing logic.&lt;/p&gt;



&lt;p&gt;Léa Samrani predicts this will evolve further with in-app currencies:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“Another trend I expect to see more of is more credit/coins IAP-based pricing. It’s been booming in SaaS, and with the way AI scales in terms of cost, it will make sense to start seeing more usage-based pricing in D2C/Apps too.&amp;nbsp;I think this will be interesting as a subscription app with a 1+ year subscription length, and low usage/retention will, as a result, be a lot less competitive in terms of fees. Why would you pay an annual subscription when you can pay with low commitment and clear value/cost defined?”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;So, especially for AI-driven apps, expect usage-based monetization—whether through credits, coins, or capped tiers—to become a more dominant part of the playbook.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-what-is-leading-this-rise-in-hybrid-monetization&quot;&gt;What is leading this rise in hybrid monetization?&lt;/h3&gt;



&lt;p&gt;While subscriptions are definitely here to stay, hybrid models are proving to be smarter and more dynamic ways to monetize. As Vahe Baghdasaryan put it in the SOSA 2025 report:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“By integrating consumables—such as one-time purchases for premium content, AI-generated insights, or feature unlocks—subscription apps can better capture user demand and increase overall LTV. Users who may not commit to a full subscription might still be willing to make smaller purchases, providing an additional revenue layer.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;In other words, hybrid models help apps monetize across the spectrum of user intent. Subscriptions aren’t disappearing—but they’re becoming just one piece of a larger monetization puzzle.&lt;/p&gt;



&lt;p&gt;Is it me, or is monetization getting a bit spicy? So let’s keep the heat going and jump into one of the buzziest topics of 2025 so far: app-to-web.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-trend-4-app-to-web-checkout-divide-and-conquer&quot;&gt;Trend 4: App-to-web checkout: divide and conquer&lt;/h2&gt;



&lt;p&gt;App-to-web checkout is having a &lt;em&gt;moment&lt;/em&gt; for sure, as Andy Carvell, Co-founder and CEO of &lt;a href=&quot;https://phiture.com/&quot;&gt;Phiture&lt;/a&gt; explains:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“Regulatory shifts in the app store model, from the Epic v. Apple ruling in the US to Europe’s DMA enforcement, have finally allowed developers to explore real alternatives, albeit with significant complexity involved (especially in the EU).”&amp;nbsp;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;This has led to apps testing more about web-based subscription for sure, combined with some of the trends we’ve discussed before. Andy continues:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“We’re seeing some leading apps cautiously testing web-based subscription flows and creative pricing moves: things like discounted web-only offers, multi-product bundles, and new premium tiers.&amp;nbsp;Early results inspire optimism: companies are recapturing a bigger share of revenue and finding new audiences and levers for growth, but they’re also discovering pitfalls including conversion/retention drop-offs and increased operational overhead.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-web-advocates&quot;&gt;Web advocates&lt;/h3&gt;



&lt;p&gt;Nathan Hudson, Founder and CEO of &lt;a href=&quot;https://www.perceptycs.com/&quot;&gt;Perceptycs&lt;/a&gt; has also seen positive results for his clients:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“While they haven’t been a game changer for everyone, some of our clients are now generating over 80% of new revenue through web payments, seeing record-low CPAs from improved trial conversion, and predicting higher LTVs from web renewals. As users encounter these external payment flows more frequently and become more comfortable converting via web checkouts.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;And Hannah Parvaz, founder of &lt;a href=&quot;https://www.aperture.london/&quot;&gt;Aperture&lt;/a&gt; and a &lt;a href=&quot;https://hannahparvaz.substack.com/&quot;&gt;weekly app growth newsletter&lt;/a&gt;, is also a fan. She has seen web funnel adoption accelerate across all her clients this year:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“Web funnel adoption is scaling rapidly. I’ve been building web flows since 2014 and it’s sooo good to see them finally getting the spotlight. &lt;/em&gt;&lt;strong&gt;&lt;em&gt;More and more teams are skipping the direct-to-App Store approach and going web-first, because it just works.&lt;/em&gt;&lt;/strong&gt;&lt;em&gt;&amp;nbsp;Our most successful accounts are scaling on web. You get better tracking, lower fees, full control over messaging, and a funnel you can actually optimise. Ads now land on high-converting web pages that educate and convert before deep linking into the app (if at all) with clean event tracking the whole way through.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;But she does note the why behind the movement, with platforms underreporting more than ever before:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“Performance looks dead in-platform… then backend revenue says otherwise. Why? Probabilistic isn’t reality. Teams are hacking it by sending app events as web events, rebuilding flows from web to app so attribution actually works. It’s a full-on shift in how people structure their funnels to see the growth that’s already happening.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-web-won-t-work-for-everyone&quot;&gt;Web won’t work for everyone&lt;/h3&gt;



&lt;p&gt;But it’s by no means a guaranteed win for all. As Cristian Rotari put it:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“It seems like the &lt;/em&gt;&lt;strong&gt;&lt;em&gt;growth world is divided around it, &lt;/em&gt;&lt;/strong&gt;&lt;em&gt;and so are the results we keep seeing from different apps. The key here is to experiment and see for yourself. One insight I got is that &lt;/em&gt;&lt;strong&gt;&lt;em&gt;the less tech-savvy your user base, the better.&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;For example, if your users are a bunch of 20-year-olds who have grown up with apps, taking them outside of the native IAP purchase flow might feel like a scam. It’s different for those who are not so familiar with how these systems work.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;In other words, pulling younger users into a web checkout flow might feel scammy to them. For older or more niche audiences, the trust gap is smaller. Ekaterina Gamsriegler adds to this with her experience:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“So far, the results have been more mixed than expected. Some apps (like Spotify) reported increased purchase rates and revenue. Others saw only marginal improvements (3–6% lift), or even lower ARPPU compared to native IAPs.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Ekaterina quick to point out that success hinges on many variables:&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;“&lt;/em&gt;&lt;/strong&gt;&lt;em&gt;As with most things in Growth, it’s clear that there are many variables at play that need to be figured out to make it work:&lt;/em&gt;&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;UX and Messaging. &lt;/em&gt;&lt;/strong&gt;&lt;em&gt;How much more friction does the alternative flow have? Is it clear to a user what happens next?&lt;/em&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;&lt;em&gt;Offer.&lt;/em&gt;&lt;/strong&gt;&lt;em&gt; Is the price lower?&lt;/em&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;&lt;em&gt;Brand trust.&lt;/em&gt;&lt;/strong&gt;&lt;em&gt; Will users feel secure entering their payment information? They probably do with Spotify, but will it work for your app?&lt;/em&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;&lt;em&gt;Trialist and Subscriber churn. &lt;/em&gt;&lt;/strong&gt;&lt;em&gt;Web subscriptions are known for being harder to cancel, potentially compensating for the first three points.&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;&lt;em&gt;For now, I see apps testing and iterating. In the meantime, the “web2web checkout” hype continues and shows no sign of slowing down.”&lt;/em&gt;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-how-to-make-it-work-for-you&quot;&gt;How to make it work for you&lt;/h3&gt;



&lt;p&gt;As Hannah and others have noted, web flows aren’t just about cost-saving, they give you control. Control over the funnel, the messaging, the offer, and the attribution.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;That being said we need to proceed with caution. Sylvain Gauchet does expect that Apple will combat this push on app-to-web, though, leading to a more nuanced approach to the usage of app-to-web:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“After a “Wild Wild West” period where developers pushed the limits of their app-to-web implementations in order to avoid app store fees, Apple will crack down (or penalize) the adventurous ones.&amp;nbsp;What we will see next is &lt;/em&gt;&lt;strong&gt;&lt;em&gt;apps using smart segmentation to only surface web payments for high-intent segments of users and/or specific parts of the journey&lt;/em&gt;&lt;/strong&gt;&lt;em&gt; (e.g., past the first paywall, for promos, etc.).”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Thomas Petit agrees that the future of app-to-web will be fragmented. He expects to see more parallel systems running—direct-to-store, web2app, and web2web—all being tested side by side. But lower platform fees don’t always equal higher take-home revenue, as shown by &lt;a href=&quot;https://www.revenuecat.com/blog/growth/iap-vs-web-purchases-conversion-test/&quot;&gt;RevenueCat’s own experiments comparing web vs. native IAPs&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;Cristian sums it up best: web checkout works when you know your audience and have the volume or LTV to justify the added complexity.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“If you have the luxury of a larger user base where you can individually look at these segments, I encourage you to do so.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;So: this isn’t a silver bullet. However, when done correctly, app-to-web opens up optimization opportunities that you simply don’t get in-platform. As Cristian noted, it works especially well for more premium audiences or larger user bases where you can afford to segment, experiment, and personalize.&lt;/p&gt;



&lt;p&gt;And all this experimentation with web flows sets the stage for our final trend…&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-trend-5-the-money-back-guarantee-era-begins&quot;&gt;Trend 5: The money-back guarantee era begins&lt;/h2&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;&lt;/blockquote&gt;



&lt;p&gt;This one came from Nathan Hudson and it immediately piqued my interest: money-back guarantees as an alternative to free trials.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“One trend I’m keeping a close eye on is money-back guarantees, and how prevalently they might be adopted in place of free trials. This couldn’t be done outside of web2app, before external payment flows were introduced. But having seen them work pretty well so far, I expect they’ll become more popular.“&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;It’s an interesting one, as I can imagine that if users respond well to it, it could reduce the drop-off in free trials and also encourage users to commit to testing the app. While conversion rates might drop a bit, the amount you lose by claiming the guarantee versus canceling a trial, I would expect to be less.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Which apps should try this out? Nathan shares the following:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“I’d particularly recommend trying them out if you’re focused on scaling paid UA and looking to maximise signal quality. By pushing a hard paywall with a money-back guarantee, you can optimise your Meta and TikTok campaigns for&lt;/em&gt;&lt;strong&gt;&lt;em&gt; the direct purchase event, removing the complexity and opacity of dealing with trial conversions.&lt;/em&gt;&lt;/strong&gt;&lt;em&gt;”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;You’re getting a more honest conversion event—one that platforms like Meta and TikTok can optimize against with far less ambiguity than a trial start.&lt;/p&gt;



&lt;p&gt;Hannah Parvaz noted that this kind of shift also reflects something broader: a redefinition of what success looks like. It’s no longer about install-to-trial—it’s about &lt;em&gt;post-onboarding&lt;/em&gt; behavior and actual long-term value:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“CAC targets will shift to post-trial or post-onboarding behaviour, not just install. MMM will keep growing, especially as people get more comfortable making directional budget calls without needing “perfect” data.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;So while this might look like a monetization tactic on the surface, it’s really about &lt;strong&gt;better measurement&lt;/strong&gt;. Just like web flows allow for cleaner attribution and more flexible funnels, money-back guarantees give growth teams clearer, more actionable signals for performance—and potentially, more committed users too.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-monetization-is-getting-smarter-and-spicier&quot;&gt;Monetization is getting smarter and spicier&lt;/h2&gt;



&lt;p&gt;If there’s one thing I’ve taken away from speaking to this Glastonbury star lineup, it’s that monetization in 2025 is no longer a “set it and forget it” game. Pricing, packaging, platforms—even the &lt;em&gt;moment&lt;/em&gt; of purchase—is being rethought from the ground up.&lt;/p&gt;



&lt;p&gt;Here are the most significant shifts I’m watching:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Apps are charging more and owning it.&lt;/strong&gt; There’s no shame in being premium when the value is clear.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Static pricing is dying.&lt;/strong&gt; Flexibility wins, whether that’s through dynamic tiers, localized offers, or smart timing.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Subscription-only is outdated.&lt;/strong&gt; Hybrid monetization is becoming the new standard, especially in AI-heavy or usage-based models.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Web flows unlock new tactics.&lt;/strong&gt; From money-back guarantees to smarter user segmentation, app-to-web opens a world of new plays.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;But none of this is plug-and-play. What works for one app might flop for another. The real winners? The ones who test, adapt, listen to their users, and keep evolving.&lt;/p&gt;



&lt;p&gt;Because if 2024 was about survival, 2025 is about &lt;em&gt;sophistication&lt;/em&gt;.&lt;/p&gt;



&lt;p&gt;As Hannah Parvaz put it:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“Feels like the second half of the year is less about chasing channels and more about building smarter systems, and I’m very here for it. More budgets are going into CRM, onboarding, and even cancellation flows. The teams that invest in it early are converting better, retaining more users, and giving their paid campaigns a much better shot at success.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Which brings us to the final truth about modern monetization: &lt;strong&gt;it doesn’t work in isolation&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;It’s part of a broader growth system. Andy Carvell echoes this sentiment:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“Winners in subscriptions in 2025 will be those who innovate boldly, execute carefully and pay attention to what the data is telling them about retention, not just short-term conversion rates.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;If you’re not integrating these pricing and payment tests into your onboarding, retention, CRM, and UA strategy, you’re only doing half the job. The future belongs to the teams that treat monetization as a system, not a silo. Now it’s time to go watch some actual Glastonbury performances, excuse me.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[From user interviews to winning ad creatives]]></title><description><![CDATA[How building informed empathy will make you a better creative strategist]]></description><link>https://www.revenuecat.com/blog/growth/informed-empathy-user-interviews-ad-creatives/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/informed-empathy-user-interviews-ad-creatives/</guid><pubDate>Thu, 14 Aug 2025 08:41:36 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/informed-empathy-user-interviews-ad-creatives.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Everyone tells you to “talk to your customers.” Yet so many subscription apps still flop, even when they’re drowning in user interviews. The secret isn’t just &lt;em&gt;talking&lt;/em&gt;. It’s about &lt;em&gt;how&lt;/em&gt; you listen and build what I call informed empathy.&lt;/p&gt;



&lt;p&gt;The problem is that it’s easy to reduce “Speak to customers” down to “Ask your customers what benefit they’re looking for.”&lt;br&gt;&lt;br&gt;The worst part is that it feels like you’re doing the right thing!&lt;br&gt;&lt;br&gt;I mean, you’re not asking them what features to build. You’re focusing on the transformation. You’re kind of building a &lt;a href=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/01/what-drives-users-to-pay-jobs-to-be-done-1.png&quot;&gt;jobs-to-be-done&lt;/a&gt; statement… Right?&lt;/p&gt;



&lt;p&gt;Yes. But no.&lt;/p&gt;



&lt;p&gt;The reality is that customers will tell you about their pain points and desired outcomes if you ask them. And this is good. But there’s so much more they can tell you if you ask the right questions.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-depth-conquers-all&quot;&gt;Depth conquers all&lt;/h2&gt;



&lt;p&gt;We don’t just want to learn about their pain point and desired outcome. We want to become the domain expert on our customers. We want to understand the context, motivations, feelings, drivers, nuances and lived experiences around those paint points and desired outcomes.&lt;br&gt;&lt;br&gt;And the only way to do that is to ask deeper questions.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Questions that draw out:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;The language they use to describe their problem&lt;/li&gt;



&lt;li&gt;How that problem makes them feel&lt;/li&gt;



&lt;li&gt;Who that problem impacts beyond them&lt;/li&gt;



&lt;li&gt;Why that matters to them&lt;/li&gt;



&lt;li&gt;Their current context and when that problem is top of mind&lt;/li&gt;



&lt;li&gt;How they feel about their current context&lt;/li&gt;



&lt;li&gt;Why they feel that way&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Doing this helps build what I like to call “informed empathy”.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-is-informed-empathy&quot;&gt;What is informed empathy?&lt;/h2&gt;



&lt;p&gt;Informed empathy is the ability to understand and share another person’s feelings or experiences based not just on emotional intuition, but on factual knowledge about their context, background, and circumstances.&lt;/p&gt;



&lt;p&gt;We don’t just want to know their feelings or desires, we want to know the experiences that led to those.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;And unlike desired outcomes or pain points –&amp;nbsp; there’s not a one size fits all answer. In fact, it’s not even close. Every user carries a unique mix of motivations and drivers. And whilst some will be shared across users, in every case, there’s variation.&lt;/p&gt;



&lt;p&gt;Ultimately, our task is uncover these facts so that we can connect with users on a deeper level. This is the key to crafting winning ad creatives that resonate with the target audience.&lt;/p&gt;



&lt;p&gt;User-generated content (UGC) scripts that feel more relatable, storyboards that are less shallow and creative concepts that are more thought out.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-drivers-to-probe-around-to-build-informed-empathy&quot;&gt;Drivers to probe around to build informed empathy&lt;/h2&gt;



&lt;p&gt;So how exactly do we build informed empathy?&lt;/p&gt;



&lt;p&gt;One of the biggest breakthroughs I had was when I stopped turning up to user interviews with pre-written questions and instead started turning up with a list of drivers that I wanted to probe around.&lt;br&gt;&lt;br&gt;I stopped chasing answers and started chasing context.&lt;br&gt;&lt;br&gt;And these five drivers are the ones I find myself probing around most often to build informed empathy from user interviews:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-functional-drivers&quot;&gt;&lt;strong&gt;1. Functional drivers&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Up to this point, I’ve been pretty bullish about the fact that we don’t want to solely focus on functional drivers. However, they are a strong starting point!&lt;br&gt;&lt;br&gt;By functional drivers I mean the tangible, real world outcomes a user is chasing, and the pain point they are running away from. It’s the before and after. The transformation. The specific job they are trying to fulfil. (whether big or small).&lt;br&gt;&lt;br&gt;We want to identify this before (pain point) and after (desired outcome) so that we can begin to paint a clear picture for prospects:&lt;/p&gt;



&lt;p&gt;Life without our product vs life with our product.&lt;br&gt;&lt;br&gt;But once we identify that driver, we don’t stop. We probe.&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Why does that even matter?&lt;/li&gt;



&lt;li&gt;When did they start caring about this?&lt;/li&gt;



&lt;li&gt;What is the context around that functional driver&lt;/li&gt;



&lt;li&gt;What will be different when they achieve that outcome?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Because life with our product is about more than the functional job that it will accomplish.&lt;br&gt;&lt;br&gt;For this reason, I like to use functional drivers as the entry point into the other drivers.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-emotional-drivers&quot;&gt;&lt;strong&gt;2. Emotional drivers&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Whilst users are looking for functional outcomes, it’s emotions that drive purchase decisions. Very often the functional driver sits on top of an emotional driver. If we can get users to relive their purchase decision and the feelings that sealed the deal, we can focus on recreating those moments for a broader audience and become better storytellers.&lt;br&gt;&lt;br&gt;Specifically I’m looking to dive into:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;How they feel about the pain point(s) that were are trying to solve with our product&amp;nbsp;&lt;/li&gt;



&lt;li&gt;How they were feeling at the moment they decided to give our product a go&lt;/li&gt;



&lt;li&gt;Why they think they felt that way&lt;/li&gt;



&lt;li&gt;How they think they’ll feel when that pain point is relieved&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Once we uncover their emotional triggers – relief, excitement, FOMO, we can proactively try and elicit those feelings through our ad creatives and marketing efforts. It’s about tapping into their emotions, not just their logic.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-contextual-drivers&quot;&gt;&lt;strong&gt;3. Contextual drivers&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Next we have contextual drivers. These are typically the &lt;em&gt;moments or environments that push users to turn to our app?&lt;/em&gt; But they could equally be the moments or environments that highlight the pain point or desired outcome in our user’s / prospect’s life.&lt;br&gt;&lt;br&gt;Here’s a personal example!&lt;br&gt;&lt;br&gt;I love tennis! I’m not that good. But I do love to play…&lt;br&gt;&lt;br&gt;And I especially love to play when I’m watching Wimbledon on TV each Summer.&lt;/p&gt;



&lt;p&gt;Personally I find these drivers helpful for generating a bucket of ideas for UGC scripts and creative concepts to test. It’s about understanding how your product does or might fit into their daily life.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Bonus tip&lt;/strong&gt;: Try to dig into contextual drivers to see which emotional / functional drivers they are closely tied to. Is it that specific contexts evoke certain emotions? Or do they remind them about a specific outcome that is missing in their life?&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-4-social-drivers&quot;&gt;&lt;strong&gt;4. Social drivers&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Social drivers are often overlooked but can be incredibly powerful. And they often sit beneath functional or emotional drivers.&lt;br&gt;&lt;br&gt;For example – I want to get in shape this summer, so that I don’t feel self conscious when I’m at the beach with my friends when we go on holiday.&lt;br&gt;&lt;br&gt;There is a functional driver – Getting in shape.&lt;br&gt;There’s an emotional driver – Not feeling self conscious&lt;br&gt;There’s a contextual driver – Being at the beach&lt;br&gt;But there’s a social driver that underpins all of these – How my friends perceive me.&lt;br&gt;&lt;br&gt;This is why it’s so important to keep digging, even when you think you’ve gotten your answer. We could stop at getting shape. But that’s not enough!&lt;br&gt;&lt;br&gt;When probing for social drivers it can be useful to separate them into two types:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;The impact of other people on our user&lt;/li&gt;



&lt;li&gt;The impact of our user on other people&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;It’s an important distinction to make since social dynamics can be so complex.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-5-identity-drivers&quot;&gt;&lt;strong&gt;5. Identity drivers&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Finally we have identity drivers. We want to understand how the user perceives themselves and who they aspire to be. And going beyond this, we want to probe at how that impacts the decisions they make and have made in relation to our product and the pain point we are solving.&lt;/p&gt;



&lt;p&gt;We’re looking to identify the personal values that the user believes are theirs intrinsically.&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Who are they trying to be?&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;When they tell people they use this app, what does that say about them?&lt;br&gt;&lt;/li&gt;



&lt;li&gt;What are their personal values? E.g. health, creativity, sustainability. And which of these are bolstered by subscribing to our app?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;That way we can paint that picture for them with our product being the hero of the story.&lt;/p&gt;



&lt;p&gt;We can lean on these personal narratives and value hooks when producing ad creatives. It’s about positioning our app as more than a functional piece of software but an integral part of them becoming the person they want to be and living the life they want to live.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-putting-it-into-practice&quot;&gt;Putting it into practice&lt;/h2&gt;



&lt;p&gt;“Talking to customers” alone won’t help you create winning ad creatives. But building informed empathy and layering creativity on top of core drivers is what brings breakthroughs on the acquisition side.&lt;br&gt;&lt;br&gt;The next time you conduct a series of customer interviews, try this:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Before the call&lt;/strong&gt;: Try not preparing any more than 3 questions max. These questions should focus on getting users to open up around the drivers we want to unpack.&lt;br&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;During the call&lt;/strong&gt;: Force yourself to probe for more details every time they answer a question. Even if you think you have your answer, keep asking why in different ways until you stop getting new insights.&lt;br&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;After the call&lt;/strong&gt;: Thematise quotes by driver and look for any motivations that seem to be more central to the user’s story. Themes / situations / drivers they keep coming back to.&lt;br&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;After this you’ll be in a great position to kick off a brainstorm with your creative strategy team and start coming up with stronger creative concepts and angles to test.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[How to win Shipaton part 2: building fast]]></title><description><![CDATA[A time-boxed framework to build, test, and ship your Shipaton app before the clock runs out.]]></description><link>https://www.revenuecat.com/blog/engineering/how-to-win-shipaton-part-2-building-fast/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/how-to-win-shipaton-part-2-building-fast/</guid><pubDate>Wed, 13 Aug 2025 12:27:26 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/cover-how-to-build-fast.jpg" length="0" type="image/*"/><content:encoded>&lt;p&gt;Shipaton is in full swing with 49 days still on the clock. That’s plenty of time to come up with an idea, build it, ship it, and turn it into something big. This week’s guide focuses on execution: how to build efficiently, avoid wasted effort, and get your app into users’ hands as quickly as possible.&lt;/p&gt;



&lt;p&gt;The key to managing your time is starting small but lovable. Aim for a minimum lovable product (MLP) that delivers the core experience people will enjoy right away. Then grow it based on real feedback. &lt;a href=&quot;https://www.revenuecat.com/blog/engineering/how-to-win-shipaton-part-1-coming-up-with-an-idea/&quot;&gt;If you missed last week’s guide on finding your idea&lt;/a&gt;, narrowing your focus, and iterating with users, read that first. Once you’re clear on the “what,” this article will help you nail the “how.”&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-set-a-timeline-and-stick-to-it&quot;&gt;Set a timeline, and stick to it&lt;/h2&gt;



&lt;p&gt;Deadlines are what turn ideas into finished products. App development is no different. Your first goal is to build something you can put in front of potential users as quickly as possible. The longer you spend building in isolation, the greater the risk of creating something no one needs — or will pay for.&lt;/p&gt;



&lt;p&gt;One way to keep yourself on track is with what I call the 4-8-24 approach. I first used this while working on proof-of-concepts and prototypes at a previous company. At the time we applied it instinctively, but later I shaped it into a repeatable framework I’ve used for app development, project management, and even to keep my easily distracted brain focused on a single task.&lt;/p&gt;



&lt;p&gt;The idea is simple:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;4 hours to build the first version.&lt;/li&gt;



&lt;li&gt;8 hours to polish it enough to show real users.&lt;/li&gt;



&lt;li&gt;24 hours (spread over three days) to refine, package, and release.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Each stage has a clear purpose and a strict time limit — both are essential for moving fast without losing direction.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-build-in-4-hours&quot;&gt;Build in 4 hours&lt;/h3&gt;



&lt;p&gt;The first four hours are about proving to yourself that the concept works, and that it’s worth continuing. The time limit is artificial, but it’s important. At this point you don’t need to show the app to anyone, but it should instantly communicate what it does. Ideally, it even delivers the core feature in some form.&lt;/p&gt;



&lt;p&gt;It doesn’t have to be perfect. If there’s an API you need to call, mock it for now and build the app as if the response were real. You can even use the Wizard of Oz method: a polished-looking UI with someone manually “pulling the levers” behind the scenes to make things work.&lt;/p&gt;



&lt;p&gt;The goal here is to validate the idea and create the first prototype. By the end of four hours, you should feel confident in the project and excited to build more. If you don’t, something’s off. In case it looks like the app would require massive extra work just to be viable, be ruthless and kill it. If you think it could work but not in its current form, spend another four hours creating a different prototype.&lt;/p&gt;



&lt;p&gt;In shorter hackathons, like 24-hour sprints, I often showed this four-hour version to potential users — but never let them use it directly. At this stage I only wanted to see if the prototype piqued their interest. You can also ask what features they consider essential, then focus on those in the next eight-hour build.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-build-in-8-hours&quot;&gt;Build in 8 hours&lt;/h3&gt;



&lt;p&gt;Once you have your four-hour prototype, it’s time to build the eight-hour version that you’ll show to users. This build should focus on three things:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Main features you can reasonably create in this time.&lt;/li&gt;



&lt;li&gt;A polished UI that makes users want to interact with it.&lt;/li&gt;



&lt;li&gt;Barely functional internals, enough to demo, but not for public release.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;That last point is the most surprising, but it’s deliberate. You’re not building this version for the App Store yet. It just needs to work well enough for people to try it on your phone and decide if they’d want to download it, use it, and pay for it. The more “duct tape” holding it together, the better, as long as the cracks don’t show to the user.&lt;/p&gt;



&lt;p&gt;You shouldn’t be proud of this version yet. In fact, that’s a good sign. This should be a convincing fake, something that looks ready but is still quick and dirty underneath. It’s your chance to see genuine reactions before you commit serious time and resources to the build.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-build-in-24-hours&quot;&gt;Build in 24 hours&lt;/h3&gt;



&lt;p&gt;The last stop before releasing your app is to work on it for three days (8 hours per day = 24 hours), focusing mainly on polishing. If you’ve done things correctly, 80% of your MLP version of your app is already complete, and now you’re going to spend roughly 80% of the remaining time polishing the final 20%.&lt;/p&gt;



&lt;p&gt;During this stage, you should also create your App Store pages, prepare the app for either beta testing or full release (depending on your launch strategy), and get all supporting materials ready, such as app icons and screenshots. It’s also a good idea to tweet or otherwise let people know your app is coming soon.&lt;/p&gt;



&lt;p&gt;Your goal should be to wrap up the first version of your app within this timeframe. If it feels too short, be strict and strip out features that take too much development time. It’s okay to be embarrassed about the version you’re going to launch. If you’re not, you’re probably launching too late.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-ship-as-often-as-you-humanly-can&quot;&gt;Ship as often as you humanly can&lt;/h2&gt;



&lt;p&gt;Your app is out now. Maybe users are flocking to it and your MRR keeps rising. More likely, the reality is different: you have a few dedicated users sending feedback, some of them even paying, but most people download the app, try it once, and then drop off. That is to be expected. You deliberately released an app that might not have everything so you could learn from your users what to build next.&lt;/p&gt;



&lt;p&gt;To do that, you need to pay close attention to what your users are saying, identify the features most of them are asking for, and ship those. The more aggressively you ship, the better your results will be. Early on, releasing new features once a month is far too slow. Aim for weekly updates. After you have shipped almost every week for a few months, you can slow the pace if it makes sense.&lt;/p&gt;



&lt;p&gt;What should you ship this often? Bug fixes and features. Your app is still far from complete, so bugs will probably take most of your time. Focus on fixing them. If you can add a new feature in every few releases, do it, but spend the majority of your output on polishing the app.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-general-guidelines&quot;&gt;General guidelines&lt;/h3&gt;



&lt;p&gt;Let’s look at some general guidelines for building things better as well. These can be employed at every stage of building your app&amp;nbsp;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Make use of testers. Early testers are your shortcut to spotting what’s broken, what’s confusing, and what’s worth doubling down on. Keep your feedback loop short&lt;/li&gt;



&lt;li&gt;Use AI to make things fast, then improve on it. AI can help you scaffold UI, generate boilerplate code, or even mock up marketing copy in minutes. The trick is not to ship AI output untouched, it’s to treat it as the rough draft.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Go back and polish. Shipaton rewards speed, but speed without polish is just a race to mediocrity. Small, continuous polish keeps users engaged, reduces churn, and makes your next big feature release look even better by comparison.&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-conclusion&quot;&gt;Conclusion&lt;/h2&gt;



&lt;p&gt;Building fast doesn’t mean cutting corners — it means focusing on what matters most right now and letting the rest wait. The 4-8-24 method gives you a structure to go from “idea in your head” to “app in users’ hands” without drowning in scope creep. Pair that with relentless beta testing, smart use of AI, and regular polish, and you’ll keep momentum without sacrificing quality. This is how you win Shipaton.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[remember vs rememberSaveable: deep dive into state management and recomposition in Jetpack Compose]]></title><description><![CDATA[Understanding the differences between remember and rememberSaveable by exploring their internal mechanisms, and how they relate to state and recomposition.]]></description><link>https://www.revenuecat.com/blog/engineering/remember-vs-remembersaveable/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/remember-vs-remembersaveable/</guid><pubDate>Fri, 08 Aug 2025 09:46:48 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/remember-vs-rememberSaveable.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Jetpack Compose enables you to design and build UI components and screens in a declarative way, and this approach is powered by several key concepts. One of the most important is idempotence, the idea that a composable function will always produce the same UI output given the same input parameters. This ensures consistent rendering and helps Compose efficiently manage recompositions and UI updates.&lt;/p&gt;



&lt;p&gt;In this article, you’ll explore the concept of recomposition in Jetpack Compose, dive into the internal workings of remember versus rememberSaveable, and learn how these APIs are used in real-world scenarios through examples from &lt;a href=&quot;https://www.revenuecat.com/docs/getting-started/installation/android&quot;&gt;RevenueCat’s Android SDK&lt;/a&gt;.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-compose-phases-and-recomposition&quot;&gt;Compose Phases and Recomposition&lt;/h2&gt;



&lt;p&gt;Before we dig into how &lt;code&gt;remember&lt;/code&gt; and &lt;code&gt;rememberSaveable&lt;/code&gt; work under the hood, let’s first understand why they’re needed in the first place, and what they actually do in Jetpack Compose.&lt;/p&gt;



&lt;p&gt;The Jetpack Compose rendering pipeline is built around &lt;a href=&quot;https://developer.android.com/develop/ui/compose/phases&quot;&gt;three core phases&lt;/a&gt; that define how UI is constructed and updated: &lt;strong&gt;Composition&lt;/strong&gt;, &lt;strong&gt;Layout&lt;/strong&gt;, and &lt;strong&gt;Drawing&lt;/strong&gt;. These phases work together to form a unidirectional data flow, starting from the UI description and ending with pixels on the screen.&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Composition&lt;/strong&gt; – &lt;em&gt;What&lt;/em&gt; to show: Composable functions are executed to generate a UI tree that describes the current screen state.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Layout&lt;/strong&gt; – &lt;em&gt;Where&lt;/em&gt; to show it: Each element in the tree is measured and positioned within a 2D space, considering constraints and child elements.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Drawing&lt;/strong&gt; – &lt;em&gt;How&lt;/em&gt; to render it: The positioned elements are drawn onto a Canvas, typically mapped to the device screen.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Understanding this three-phase pipeline is key to writing a performant and maintainable UI in Compose, especially because these phases are tightly coupled with recomposition. As the name implies, recomposition restarts the pipeline from the composition phase, re-running your composable functions in response to state changes.&lt;/p&gt;



&lt;p&gt;This means composable functions are re-invokable at any time, and you should write them assuming that they will be. However, without explicit state-handling mechanisms, every local variable inside a composable will be re-initialized on each recomposition, often leading to unexpected behavior.&lt;/p&gt;



&lt;p&gt;That’s why the Compose Runtime introduces State to provide a way for values to survive recomposition and keep your UI in sync with the underlying data model.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-understanding-state&quot;&gt;Understanding State&lt;/h2&gt;



&lt;p&gt;Now, let’s take a moment to understand the nature of State in Jetpack Compose.&lt;/p&gt;



&lt;p&gt;For example, consider the following simple function:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-pJdYp wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Composable\nfun Counter() {\n    var counter = 0\n\n    Button(\n        onClick = { counter++ }\n    ) {\n        Text(text = \&amp;quot;Count: $counter\&amp;quot;)\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;When you click the button, the &lt;code&gt;counter&lt;/code&gt; variable should increase by 1, and the &lt;code&gt;Counter&lt;/code&gt; composable function should re-render to reflect the updated state. However, it won’t behave as expected. That’s because Compose doesn’t automatically track regular variables, it relies on a special mechanism to detect changes and trigger recomposition.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;state&quot;&gt;State&lt;/h3&gt;



&lt;p&gt;To handle this properly, Compose provides a built-in mechanism called State. State allows the Compose runtime to observe value changes and automatically re-run the associated composable functions when needed. Once a state value changes, Compose will intelligently recompose only the affected parts of the UI.&lt;/p&gt;



&lt;p&gt;Let’s update the function to use State below:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z12xSkr wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Composable\nfun Counter() {\n    var counter by mutableStateOf(0)\n\n    Button(\n        onClick = { counter++ }\n    ) {\n        Text(text = \&amp;quot;Count: $counter\&amp;quot;)\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;It looks like it should work, but you’ll notice a red underline under &lt;code&gt;mutableStateOf&lt;/code&gt;, with an error saying: “Creating a state object during composition without using remember.”&lt;/p&gt;



&lt;p&gt;So what’s the issue? Let’s break it down.&lt;/p&gt;



&lt;p&gt;A function is an independently executable block of code, and in Jetpack Compose, a composable function can be re-executed at any time due to state changes (i.e. recomposition). That means the &lt;code&gt;counter&lt;/code&gt; variable is re-initialized to &lt;code&gt;0&lt;/code&gt; every time &lt;code&gt;Counter()&lt;/code&gt; is recomposed.&lt;/p&gt;



&lt;p&gt;To persist the value across recompositions, you need to tell Compose to retain it in memory, and that’s exactly what &lt;code&gt;remember&lt;/code&gt; is for.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;remember-vs-remembersaveable&quot;&gt;remember vs. rememberSaveable&lt;/h2&gt;



&lt;p&gt;To persist state across recompositions, Jetpack Compose provides two essential tools: &lt;code&gt;remember&lt;/code&gt; and &lt;code&gt;rememberSaveable&lt;/code&gt;. These APIs allow you to retain values even as your composable functions are re-executed, ensuring the UI remains consistent with user interactions.&lt;/p&gt;



&lt;p&gt;Let’s revise the earlier example using &lt;code&gt;remember&lt;/code&gt; to preserve the counter value:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-2rt2AM wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Composable\nfun Counter() {\n    var counter by remember { mutableStateOf(0) }\n\n    Button(onClick = { counter++ }) {\n        Text(text = \&amp;quot;Count: $counter\&amp;quot;)\n    }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;In this case, every time the &lt;code&gt;Counter&lt;/code&gt; composable is recomposed, for example, after a state update, the current &lt;code&gt;counter&lt;/code&gt; value is preserved in memory instead of being reinitialized.&lt;/p&gt;



&lt;p&gt;Both &lt;code&gt;remember&lt;/code&gt; and &lt;code&gt;rememberSaveable&lt;/code&gt; serve a similar purpose: they cache values in the Compose runtime memory, giving the illusion of persistence within an otherwise stateless function. However, while they may appear similar on the surface, their behaviors diverge significantly behind the scenes.&lt;/p&gt;



&lt;p&gt;In short, &lt;code&gt;remember&lt;/code&gt; stores values in memory only as long as the process remains alive. If the app process is killed (e.g., backgrounded and reclaimed by the system), the state is lost. On the other hand, &lt;code&gt;rememberSaveable&lt;/code&gt; serializes and stores the state in a &lt;code&gt;Bundle&lt;/code&gt;, allowing it to survive configuration changes and process death, making it a better choice for preserving UI state across a wider range of lifecycle events.&lt;/p&gt;



&lt;p&gt;We’ll explore those differences in more detail next.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;remember&quot;&gt;remember&lt;/h3&gt;



&lt;p&gt;If you look into the internal implementation of &lt;code&gt;remember&lt;/code&gt;, you’ll see it’s quite straightforward something like this:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1ggWsD wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Composable\ninline fun &lt;T&gt; remember(\n    key1: Any?,\n    crossinline calculation: @DisallowComposableCalls () -&gt; T\n): T {\n    return currentComposer.cache(currentComposer.changed(key1), calculation)\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;remember&lt;/code&gt; function uses the &lt;strong&gt;Composer&lt;/strong&gt; to cache a value in memory. This cached value is preserved across recompositions unless the provided &lt;code&gt;key&lt;/code&gt; changes, which is how &lt;code&gt;remember&lt;/code&gt; knows when to invalidate and recreate the value.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;remembersaveable&quot;&gt;rememberSaveable&lt;/h3&gt;



&lt;p&gt;In Jetpack Compose, &lt;code&gt;remember&lt;/code&gt; is an API for maintaining state across recompositions. However, its memory is ephemeral; it does not survive configuration changes or, more critically, system-initiated process death. This is where &lt;code&gt;rememberSaveable&lt;/code&gt; steps in. It builds upon the foundation of &lt;code&gt;remember&lt;/code&gt; but adds a crucial layer of persistence, ensuring that UI state can be saved to and restored from a &lt;code&gt;Bundle&lt;/code&gt;, the standard Android mechanism for instance state.&lt;/p&gt;



&lt;p&gt;A detailed analysis of its internal implementation reveals an internal mechanism that interacts with a &lt;code&gt;SaveableStateRegistry&lt;/code&gt;, uses a &lt;code&gt;Saver&lt;/code&gt; to convert objects into bundle-able types, and leverages the &lt;code&gt;RememberObserver&lt;/code&gt; lifecycle to manage its registration. Let’s dissect the code to understand how it achieves this resilience.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZIa0PP wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Composable\nfun &lt;T : Any&gt; rememberSaveable(\n    vararg inputs: Any?,\n    saver: Saver&lt;T, out Any&gt; = autoSaver(),\n    key: String? = null,\n    init: () -&gt; T\n): T {\n    \/\/ 1. Determine a Unique Key\n    val compositeKey = currentCompositeKeyHash\n    val finalKey = if (!key.isNullOrEmpty()) {\n        key\n    } else {\n        compositeKey.toString(MaxSupportedRadix)\n    }\n\n    \/\/ 2. Access the Registry\n    val registry = LocalSaveableStateRegistry.current\n\n    \/\/ 3. Remember the Holder Object\n    val holder = remember {\n        val restored = registry?.consumeRestored(finalKey)?.let { saver.restore(it) }\n        val finalValue = restored ?: init()\n        SaveableHolder(saver, registry, finalKey, finalValue, inputs)\n    }\n\n    \/\/ 4. Value and SideEffect for Updates\n    val value = holder.getValueIfInputsDidntChange(inputs) ?: init()\n    SideEffect { holder.update(saver, registry, finalKey, value, inputs) }\n\n    return value\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Let’s break down this orchestration step by step:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Determining a Unique Key:&lt;/strong&gt; The first and most critical step is establishing a unique key for the state being saved. This key is used to store and retrieve the value from the &lt;code&gt;Bundle&lt;/code&gt;. The function prioritizes a developer-provided &lt;code&gt;key&lt;/code&gt;. If none is given, it falls back to using the &lt;code&gt;currentCompositeKeyHash&lt;/code&gt;, a value automatically generated by the Compose compiler based on the composable’s position in the UI tree. This ensures that the state is uniquely identified within its parent.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Accessing the Registry:&lt;/strong&gt; It then looks up the &lt;code&gt;SaveableStateRegistry&lt;/code&gt; from a &lt;code&gt;CompositionLocal&lt;/code&gt;. This registry is the central authority responsible for the entire save/restore process. It’s the component that actually interacts with the Android framework’s &lt;code&gt;SavedStateHandle&lt;/code&gt; or &lt;code&gt;Activity.onSaveInstanceState&lt;/code&gt;.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Remembering the &lt;code&gt;SaveableHolder&lt;/code&gt;:&lt;/strong&gt; This is the core of the implementation. Instead of just remembering the value itself, it remembers an instance of a private helper class, &lt;code&gt;SaveableHolder&lt;/code&gt;. This holder is where all the complex logic resides. During its initial creation inside &lt;code&gt;remember&lt;/code&gt;, it attempts to restore a value. It asks the &lt;code&gt;registry&lt;/code&gt; if it has a previously saved value for the &lt;code&gt;finalKey&lt;/code&gt; (&lt;code&gt;consumeRestored&lt;/code&gt;). If it does, it uses the provided &lt;code&gt;saver&lt;/code&gt; object to convert the stored data back into its original type &lt;code&gt;T&lt;/code&gt; (&lt;code&gt;saver.restore(it)&lt;/code&gt;). If no restored value is found (e.g., on first launch), it uses the &lt;code&gt;init&lt;/code&gt; lambda to create the initial value. This &lt;code&gt;SaveableHolder&lt;/code&gt; is then stored in the composition’s memory.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Handling Inputs and Updates:&lt;/strong&gt; The &lt;code&gt;vararg inputs&lt;/code&gt; parameter behaves similarly to the keys in &lt;code&gt;LaunchedEffect&lt;/code&gt;. If the inputs change on a subsequent recomposition, it signals that the state should be reset. The line &lt;code&gt;holder.getValueIfInputsDidntChange(inputs) ?: init()&lt;/code&gt; enforces this. The &lt;code&gt;SideEffect&lt;/code&gt; ensures that any changes to the parameters (&lt;code&gt;saver&lt;/code&gt;, &lt;code&gt;registry&lt;/code&gt;, &lt;code&gt;key&lt;/code&gt;, &lt;code&gt;value&lt;/code&gt;, &lt;code&gt;inputs&lt;/code&gt;) are communicated to the &lt;code&gt;holder&lt;/code&gt; after every successful recomposition.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;&lt;code&gt;rememberSaveable&lt;/code&gt; is not a simple function but an intricate system designed to bridge the declarative, in-memory world of Compose with the persistent, lifecycle-aware world of the Android framework. It uses a unique &lt;strong&gt;key&lt;/strong&gt; to identify state and a &lt;strong&gt;&lt;code&gt;SaveableStateRegistry&lt;/code&gt;&lt;/strong&gt; to manage the actual saving process.&lt;/p&gt;



&lt;p&gt;The core logic is encapsulated within a &lt;strong&gt;&lt;code&gt;SaveableHolder&lt;/code&gt;&lt;/strong&gt; object, which is stored in the composition via &lt;code&gt;remember&lt;/code&gt;. This holder acts as a &lt;code&gt;RememberObserver&lt;/code&gt;, using &lt;code&gt;onRemembered&lt;/code&gt; to &lt;strong&gt;register a value provider&lt;/strong&gt; with the registry and &lt;code&gt;onForgotten&lt;/code&gt; to &lt;strong&gt;unregister&lt;/strong&gt; it, thus perfectly synchronizing the persistence lifecycle with the composition lifecycle. By also tracking &lt;code&gt;inputs&lt;/code&gt;, it provides a powerful mechanism to not only survive process death but also to control when state should be reset based on external dependencies.&lt;/p&gt;



&lt;p&gt;Now let’s explore &lt;code&gt;SaveableHolder&lt;/code&gt; .&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-saveableholder-the-internal-workhorse&quot;&gt;The SaveableHolder: The Internal Workhorse&lt;/h3&gt;



&lt;p&gt;The &lt;code&gt;SaveableHolder&lt;/code&gt; class is a private implementation detail that encapsulates all the logic for interacting with the &lt;code&gt;SaveableStateRegistry&lt;/code&gt;. It implements &lt;code&gt;RememberObserver&lt;/code&gt; to hook into the composition lifecycle.&lt;/p&gt;



&lt;p&gt;Let’s analyze its key responsibilities:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z27Mnqj wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;private class SaveableHolder&lt;T&gt;(\n    \/\/ ... constructor properties ...\n) : SaverScope, RememberObserver {\n    private var entry: SaveableStateRegistry.Entry? = null\n    private val valueProvider = { \/* saves the value *\/ }\n\n    \/\/ ... update function ...\n    fun update(\n        saver: Saver&lt;T, Any&gt;,\n        registry: SaveableStateRegistry?,\n        key: String,\n        value: T,\n        inputs: Array&lt;out Any?&gt;\n    ) {\n     ..\n    }\n\n    private fun register() {\n        \/\/ ... registers the valueProvider with the registry ...\n    }\n\n    override fun onRemembered() {\n        register()\n    }\n\n    override fun onForgotten() {\n        entry?.unregister()\n    }\n\n    \/\/ ... other functions ...\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Registration with the Registry (&lt;code&gt;register&lt;/code&gt; and &lt;code&gt;onRemembered&lt;/code&gt;):&lt;/strong&gt; The &lt;code&gt;SaveableHolder&lt;/code&gt;‘s most important job is to register itself with the &lt;code&gt;SaveableStateRegistry&lt;/code&gt;. When the holder is first “remembered” by the composition, its &lt;code&gt;onRemembered()&lt;/code&gt; lifecycle callback is invoked. This, in turn, calls the private &lt;code&gt;register()&lt;/code&gt; function. Inside &lt;code&gt;register()&lt;/code&gt;, it doesn’t pass its value directly to the registry. Instead, it provides a lambda, &lt;code&gt;valueProvider&lt;/code&gt;. This provider, when called by the registry during the &lt;code&gt;onSaveInstanceState&lt;/code&gt; event, will execute the &lt;code&gt;saver&lt;/code&gt; logic to convert the current value into a &lt;code&gt;Bundle&lt;/code&gt;compatible format. The registry returns an &lt;code&gt;Entry&lt;/code&gt; object, which is a handle that can be used later to unregister.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Unregistering (&lt;code&gt;onForgotten&lt;/code&gt;):&lt;/strong&gt; When the composable leaves the composition (or its &lt;code&gt;rememberSaveable&lt;/code&gt; keys change), the &lt;code&gt;onForgotten()&lt;/code&gt; callback is triggered. This is the cleanup phase. The holder calls &lt;code&gt;entry?.unregister()&lt;/code&gt;, telling the &lt;code&gt;SaveableStateRegistry&lt;/code&gt; that it no longer needs to save this piece of state. This prevents memory leaks and ensures that state from disposed UI is not saved unnecessarily.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Updating State (&lt;code&gt;update&lt;/code&gt;):&lt;/strong&gt; The &lt;code&gt;update&lt;/code&gt; function is called within the &lt;code&gt;SideEffect&lt;/code&gt; block. Its job is to keep the holder’s internal properties (like the current &lt;code&gt;value&lt;/code&gt;, the &lt;code&gt;saver&lt;/code&gt;, and the &lt;code&gt;key&lt;/code&gt;) synchronized with the latest values from the composable function. If critical properties like the &lt;code&gt;key&lt;/code&gt; or the &lt;code&gt;registry&lt;/code&gt; itself change, it knows that its current registration is invalid, so it unregisters and re-registers itself to ensure correctness.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Handling Input Changes (&lt;code&gt;getValueIfInputsDidntChange&lt;/code&gt;):&lt;/strong&gt; This function is a simple but effective check. Before returning its stored value, it compares the current &lt;code&gt;inputs&lt;/code&gt; from the recomposition with the &lt;code&gt;inputs&lt;/code&gt; it stored from the previous composition. If they don’t match, it returns &lt;code&gt;null&lt;/code&gt;, signaling to the &lt;code&gt;rememberSaveable&lt;/code&gt; composable that the state should be reset to its &lt;code&gt;init&lt;/code&gt; value. This is how &lt;code&gt;rememberSaveable&lt;/code&gt; achieves the behavior of re-initializing when its keys change.&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;use-cases&quot;&gt;Use-cases&lt;/h2&gt;



&lt;p&gt;Now that you’ve explored the internals of &lt;code&gt;remember&lt;/code&gt;, &lt;code&gt;rememberSaveable&lt;/code&gt;, and their supporting components like &lt;code&gt;SaveableStateRegistry&lt;/code&gt; and &lt;code&gt;SaveableHolder&lt;/code&gt;, the next question is: &lt;strong&gt;When should you actually use each one?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;At first glance, &lt;code&gt;rememberSaveable&lt;/code&gt; might seem like the better option, it can persist across both recompositions &lt;em&gt;and&lt;/em&gt; process death. So should you just use it everywhere instead of &lt;code&gt;remember&lt;/code&gt;?&lt;/p&gt;



&lt;p&gt;Let’s walk through some practical use cases from RevenueCat’s Android SDK to understand when each API is appropriate, and why picking the right one matters for both performance and user experience.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;remember-2&quot;&gt;remember&lt;/h3&gt;



&lt;p&gt;As discussed earlier, &lt;code&gt;remember&lt;/code&gt; preserves state across recompositions, but it does not restore values after configuration changes (e.g., rotations or process death). In &lt;a href=&quot;https://github.com/RevenueCat/purchases-android&quot;&gt;RevenueCat’s Android SDK&lt;/a&gt; demo, we use &lt;code&gt;remember&lt;/code&gt; with &lt;code&gt;mutableStateOf&lt;/code&gt; to hold UI state during recomposition, like this:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1CYsrF wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;var isDebugBottomSheetVisible by remember { mutableStateOf(false) }\nvar showLogInDialog by remember { mutableStateOf(false) }\nvar showApiKeyDialog by remember { mutableStateOf(false) }&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;So those values will be re-initialized to &lt;code&gt;false&lt;/code&gt; if a configuration change occurs, such as rotating the screen, switching to dark mode, or adjusting the system font size.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;remembersaveable-2&quot;&gt;rememberSaveable&lt;/h3&gt;



&lt;p&gt;On the other hand, the RevenueCat SDK uses &lt;code&gt;rememberSaveable&lt;/code&gt; to persist specific state not only across recompositions, but also through configuration changes, as seen in the &lt;code&gt;PaywallDialog&lt;/code&gt; example.&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1cCp28 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;kotlin&quot; content=&quot;&amp;quot;@Composable\nfun PaywallDialog(\n    paywallDialogOptions: PaywallDialogOptions,\n) {\n    val shouldDisplayBlock = paywallDialogOptions.shouldDisplayBlock\n    var shouldDisplayDialog by rememberSaveable { mutableStateOf(shouldDisplayBlock == null) }\n    if (shouldDisplayBlock != null) {\n        LaunchedEffect(paywallDialogOptions) {\n            launch {\n                shouldDisplayDialog = shouldDisplayPaywall(shouldDisplayBlock)\n            }\n        }\n    }&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;In this case, the paywall dialog should remain visible if the user isn’t entitled to access premium features, even after a configuration change. If you used &lt;code&gt;remember&lt;/code&gt; instead of &lt;code&gt;rememberSaveable&lt;/code&gt;, the &lt;code&gt;shouldDisplayDialog&lt;/code&gt; state could be reset to &lt;code&gt;false&lt;/code&gt; during such changes, like screen rotation, dark mode toggling, or font size adjustments, which might lead to unintended behavior, such as granting access to premium features without proper entitlement.&lt;/p&gt;



&lt;p&gt;So for the same use cases of state to display a dialog, which one you should use can be very different on the situation. Then, does using &lt;code&gt;rememberSaveable&lt;/code&gt; everywhere instead of &lt;code&gt;remember&lt;/code&gt; is better since it has more features and retain better? The answer is no.&lt;/p&gt;



&lt;p&gt;Retaining all states in every scenario can also cause unintended behavior, and as you’ve seen in the internal implementation, &lt;code&gt;rememberSaveable&lt;/code&gt; carries more overhead than &lt;code&gt;remember&lt;/code&gt;. That’s why it’s important to carefully choose the right API based on your specific requirements, balancing persistence needs against performance considerations.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;



&lt;p&gt;In this article, you’ve covered the core concepts of Compose phases, recomposition, state, and the internal workings of &lt;code&gt;remember&lt;/code&gt; and &lt;code&gt;rememberSaveable&lt;/code&gt; along with guidance on selecting the right API for your needs. Together, these concepts form the cornerstone of the Compose Runtime, enabling Jetpack Compose to deliver a truly declarative UI experience.&lt;/p&gt;



&lt;p&gt;As always, happy coding!&lt;br&gt;&lt;br&gt;—&amp;nbsp;&lt;a href=&quot;https://github.com/skydoves&quot;&gt;Jaewoong&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[The experiments that grew Zumba’s LTV by 17%]]></title><description><![CDATA[Why the world’s biggest dance brand waited 24 years to launch an app and what happened next]]></description><link>https://www.revenuecat.com/blog/growth/how-zumba-grew-ltv-by-17-with-relentless-user-feedback-sub-club/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/how-zumba-grew-ltv-by-17-with-relentless-user-feedback-sub-club/</guid><pubDate>Thu, 07 Aug 2025 11:55:39 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/Nicole-Page-Lucy-Levy-Sub-Club-Blog-1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;What does it take for a legacy brand to compete with, and beat, the new wave of fitness apps? For Zumba, the answer wasn’t simply to launch an app as fast as possible. Instead, they took the long road: 24 years of relentless customer research, iteration, and community-building, all leading up to the release of their first direct-to-consumer app in 2024.&lt;/p&gt;



&lt;p&gt;While many brands rush into the app store with flashy features or giant content libraries, Zumba did things differently. They spent years learning from instructors, studios, and everyday users around the world, ultimately building an app experience that’s less about technology and more about helping people feel welcome and succeed, especially beginners. In a crowded market dominated by free YouTube videos and digital fitness startups, Zumba’s app is now outperforming peers where it matters most: retention and lifetime value.&lt;/p&gt;



&lt;p&gt;On this episode of Sub Club, Zumba’s &lt;a class=&quot;&quot; href=&quot;https://www.linkedin.com/in/lucy-levy-827b8213/&quot;&gt;Lucy Levy&lt;/a&gt; (Chief Consumer Officer) and &lt;a class=&quot;&quot; href=&quot;https://www.linkedin.com/in/nicoleraesalzman/&quot;&gt;Nicole Page&lt;/a&gt; (Senior Product Manager) share the experiments, data, and hard-won lessons behind their breakout success and what every subscription app can learn from Zumba’s approach.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Key takeaways:&lt;/strong&gt;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Customer feedback trumps assumptions:&lt;/strong&gt; Every feature, from VHS tapes to app onboarding, started with real user conversations.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Beginners are your growth engine:&lt;/strong&gt; 70% of users are new to Zumba, so onboarding is designed to move them quickly to early wins, driving a 60% annual-plan opt-in rate.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Programs &amp;gt; content libraries:&lt;/strong&gt; Users will pay for curated, guided journeys. Those in programs watched 2x as many videos and had double the retention.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Web checkout boosts LTV:&lt;/strong&gt; Zumba’s shift to web billing (with Apple/Google Pay) dropped instant conversions by 25%, but annual plans and retention soared, growing LTV 17%.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Test everything, move fast:&lt;/strong&gt; The Zumba team pivots daily based on metrics — speed of iteration beats legacy playbooks.&lt;/li&gt;
&lt;/ul&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;Optimizing Funnels, Pricing, and Retention at Zumba — Nicole Page &amp;amp; Lucy Levy, Zumba&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/-GHpDJm8MgY?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;iframe loading=&quot;lazy&quot; width=&quot;100%&quot; height=&quot;180&quot; frameborder=&quot;no&quot; scrolling=&quot;no&quot; seamless=&quot;&quot; src=&quot;https://share.transistor.fm/e/8767108b?color=FFFFFF&amp;amp;background=30343C&quot;&gt;&lt;/iframe&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-zumba-s-app-turned-user-feedback-into-a-retention-machine&quot;&gt;How Zumba’s app turned user feedback into a retention machine&lt;/h2&gt;



&lt;p&gt;Most fitness brands chase trends. Zumba spent 24 years listening: on the phone, in studios, and now in-app. Every product evolution, from instructor certifications to today’s digital experience, was sparked by user insight, not top-down decisions. With over 70% of new users identifying as beginners, Zumba built onboarding and programs to lower the intimidation factor and help people reach that crucial “three class” milestone, proven to unlock long-term retention.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-structure-wins-the-value-of-guided-programs&quot;&gt;&lt;strong&gt;Why structure wins: The value of guided programs&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;The digital fitness space is flooded with free content (hello, YouTube). Zumba’s insight: people are overwhelmed by choice, not lacking for options. By offering goal-based, beginner-friendly programs instead of endless video libraries, subscribers watched twice as many classes and stuck around longer. As confirmed in &lt;a class=&quot;&quot; href=&quot;https://www.revenuecat.com/state-of-subscription-apps-2025/&quot;&gt;State of Subscription Apps 2025&lt;/a&gt;, habit-building features and onboarding milestones are among the strongest levers for retention in Health &amp;amp; Fitness apps.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-web-checkout-lower-conversions-higher-ltv&quot;&gt;&lt;strong&gt;Web checkout: Lower conversions, higher LTV&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Facing new App Store policy changes, Zumba experimented with routing users to a streamlined Stripe-powered web checkout. Apple Pay and Google Pay were preselected to reduce friction. The result? Immediate conversions dropped by 25% but annual plans, retention, and LTV all jumped. Overall, Zumba saw a &lt;strong&gt;17% lift in LTV&lt;/strong&gt;.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-bottom-line-test-listen-and-move-faster-than-legacy-brands&quot;&gt;&lt;strong&gt;The bottom line: Test, listen, and move faster than legacy brands&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Zumba’s launch wasn’t “late” — it was intentional. Through hundreds of rapid experiments, listening to their most dedicated (and most beginner) users, and putting LTV over quick wins, Zumba’s team proved that even the biggest legacy brands can out-iterate the competition. &lt;br&gt;&lt;br&gt;The lesson: Community-powered innovation, not just content, drives outsized growth.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[App Growth Annual 2025: Registration now open for NYC (and online)]]></title><description><![CDATA[We're back! New city, twice the workshops, same amazing vibes. ]]></description><link>https://www.revenuecat.com/blog/company/app-growth-annual-2025-announcement/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/company/app-growth-annual-2025-announcement/</guid><pubDate>Wed, 06 Aug 2025 13:18:19 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/app-growth-annual-2025-announcement.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;App Growth Annual is back, and after packing out San Francisco last year, we’re taking it up a notch in New York City.&lt;/p&gt;



&lt;p&gt;This is the one event that brings together the builders, founders, and growth leaders powering the future of subscription apps. Whether you’re scaling to millions in ARR or launching your next big thing, you’ll get direct access to the sharpest tactics, live industry debates, and the kind of connections that spark your next breakthrough.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Registration is open for both &lt;/strong&gt;&lt;a href=&quot;https://appgrowthannual.com/invite&quot;&gt;&lt;strong&gt;in-person&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt; and &lt;/strong&gt;&lt;a href=&quot;https://appgrowthannual.com/virtual&quot;&gt;&lt;strong&gt;virtual&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt; attendance.&lt;/strong&gt; Early interest is high — &lt;strong&gt;we recommend applying for in-person tickets soon.&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
https://youtu.be/5NgImDYUDGo
&lt;/div&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-s-coming-in-2025&quot;&gt;What’s coming in 2025&lt;/h2&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Expanded workshops &amp;amp; tracks:&lt;/strong&gt; Two blocks of hands-on sessions, plus dedicated indie and growth leader programming.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Jacob’s product keynote:&lt;/strong&gt; Get an inside look at the RevenueCat roadmap, with live demos and exclusive reveals.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Shippies × Shipaton Awards:&lt;/strong&gt; One combined show honoring the best in subscription app growth.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;World Paywall Speed-Building Championship finals:&lt;/strong&gt; Watch the industry’s fastest builders compete for $5,000, a custom belt, and a spot on a Times Square billboard… live on stage!&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Legendary afterparty:&lt;/strong&gt; Celebrate with fellow attendees and a special guest (to be announced).&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-event-details&quot;&gt;Event details&lt;/h2&gt;



&lt;p&gt;&lt;strong&gt;When:&lt;/strong&gt; October 14, 2025&lt;br&gt;&lt;strong&gt;Where:&lt;/strong&gt; &lt;a href=&quot;https://www.theglasshouses.com/&quot;&gt;The Glasshouse&lt;/a&gt;, 660 12th Ave, New York, NY 10019 / Online&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-to-register&quot;&gt;How to register&lt;/h2&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://appgrowthannual.com/invite&quot;&gt;&lt;strong&gt;Apply for in-person tickets&lt;/strong&gt;&lt;/a&gt; (spaces are limited)&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://appgrowthannual.com/virtual&quot;&gt;&lt;strong&gt;Register for the virtual event&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Both formats include live-streamed sessions and a front-row seat to the Paywall Championship finals.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-a-look-back-highlights-from-2024&quot;&gt;A look back: Highlights from 2024&lt;/h2&gt;



&lt;p&gt;Last year’s inaugural App Growth Annual proved there’s nothing quite like bringing the subscription app world together under one roof.&lt;/p&gt;



&lt;p&gt;Standout sessions featured everything from growth frameworks and retention tactics to the live Sub Club podcast and a first-of-its-kind Shippies awards show. Feedback poured in about the “unmatched energy,” honest insights, and actionable ideas that teams started applying right away.&lt;/p&gt;



&lt;p&gt;Relive four of our keynotes on YouTube:&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;App Growth Annual 2024&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/videoseries?list=PLsFOrkX_y0B5zndnf4m7idPnZWpzboMCv&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;p&gt;See the full 2024 highlight roundup: &lt;a href=&quot;https://www.linkedin.com/posts/sylvaingauchet_growthgems-activity-7246858721753014272-Vhqt&quot;&gt;Download 120+ takeaways from Growth Gems&lt;/a&gt;&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;p&gt;&lt;strong&gt;See you in New York or online!&lt;/strong&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[How to monetize your AI app with virtual currencies]]></title><description><![CDATA[Learn how yo utilize RevenueCat's virtual currencies to power your in-app economies]]></description><link>https://www.revenuecat.com/blog/engineering/how-to-monetize-your-ai-app-with-virtual-currencies/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/how-to-monetize-your-ai-app-with-virtual-currencies/</guid><pubDate>Tue, 05 Aug 2025 14:19:44 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/How-to-monetize-your-AI-app-with-virtual-currencies.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Virtual currencies let you monetize AI-powered features, such as generating images or unlocking large language model (LLM) responses. They power in-app economies that boost retention and add flexible monetization options beyond subscriptions or one-time purchases.&lt;/p&gt;



&lt;p&gt;In this guide, we’ll help you set up and integrate RevenueCat virtual currencies in your app. Here’s what we’ll cover:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Creating virtual currencies in RevenueCat&lt;/li&gt;



&lt;li&gt;Associating products to sell currency&lt;/li&gt;



&lt;li&gt;Reading user balances from the SDK or backend&lt;/li&gt;



&lt;li&gt;Depositing and spending currency via your backend&lt;/li&gt;



&lt;li&gt;Security best practices for building trusted virtual economies&lt;/li&gt;
&lt;/ul&gt;



&lt;figure class=&quot;wp-block-video&quot;&gt;&lt;video height=&quot;1080&quot; style=&quot;aspect-ratio: 1920 / 1080;&quot; width=&quot;1920&quot; controls=&quot;&quot; loop=&quot;&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/virtual-currencies.mov&quot;&gt;&lt;/video&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-prerequisites&quot;&gt;Prerequisites&lt;/h2&gt;



&lt;p&gt;Before starting, make sure:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;You have a RevenueCat account with a project created&lt;/li&gt;



&lt;li&gt;Your in-app purchases are set up and working in RevenueCat&lt;/li&gt;



&lt;li&gt;You are using:
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;react-native-purchases 9.1.0 or higher &lt;/li&gt;



&lt;li&gt;react-native-purchases-ui 9.1.0 or higher &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;In this project we are going to use React Native, but virtual currencies are supported in all RevenueCat SDKs. Code samples are kept simple to make it possible to implement the shown examples in Swift, Flutter, and Kotlin when needed. &lt;a href=&quot;https://github.com/plahteenlahti/rc-virtual-currencies&quot;&gt;The example project is forkable from this repository.&lt;/a&gt; The demo is a React Native app with Expo that generates cat themed bed time stories using Open AI’s API. Every generated story will cost one coin, and logic for calling both RevenueCat’s and Open AI’s APIs will be located in a custom function using Expo’s &lt;a href=&quot;https://docs.expo.dev/router/reference/api-routes/&quot;&gt;API routes&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;If you’re using platforms other than React Native (such as Flutter, Unity, Web, or iOS/Android natively), make sure your app is using the minimum supported SDK versions listed in the Virtual Currency documentation. SDK capabilities and supported methods can differ slightly between platforms.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-1-set-up-virtual-currencies-in-revenuecat&quot;&gt;Step 1: Set up virtual currencies in RevenueCat&lt;/h2&gt;



&lt;p&gt;The first step is to set up virtual currencies in the RevenueCat dashboard. Navigate to your project and go to the &lt;strong&gt;Product Catalog&lt;/strong&gt; → &lt;strong&gt;Virtual Currencies.&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image&quot;&gt;&lt;img decoding=&quot;async&quot; src=&quot;https://lh7-rt.googleusercontent.com/docsz/AD_4nXdtY7f4HkPmR4F9bG-oFQC2J1_s0D4VUMMF_yTLGM0DsEr0FS-qDHofbIqDudVnQSXRc2yLg4gAlmsngkhl7emPjWinFhPlMAh7u0qZBli_SBhl1msMJf7aiTdKUI8tWy65b5yhjQ?key=YfqjIZAtZI_9jsMGFGsxlQ&quot; alt=&quot;&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-create-a-new-product&quot;&gt;Create a new product&lt;/h3&gt;



&lt;p&gt;Virtual currencies need to be associated with products that exist in App Store Connect and Play Store. Virtual currencies can be associated with both in-app purchases and subscriptions. For example you can make a consumable purchase which when bought gives the user 500 credits, or a subscription recurring monthly that gives 500 credits every month. In this tutorial we are going to use a consumable purchase for our single pack of 100 coins.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;You can create products in App Store Connect through the RevenueCat dashboard. Navigate to &lt;strong&gt;Product catalog&lt;/strong&gt; and select the &lt;strong&gt;Products&lt;/strong&gt; tab. Click &lt;strong&gt;New product&lt;/strong&gt;, and select your app. Give 100_coin_pack as the identifier, and 100 coins as the name, Product type should be Consumable. Once done click Create product.&lt;br&gt;&lt;br&gt;RevenueCat has now created the product. You should see a prompt to create the product in App Store Connect. Click that, ensure that everything looks correct and click Create Product to create the product in App Store Connect.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image&quot;&gt;&lt;img decoding=&quot;async&quot; src=&quot;https://lh7-rt.googleusercontent.com/docsz/AD_4nXfGHo2P05J0cwfgDjQVR7LXwA4T9mPs_VfIyxavqbszE1yLEz4DFyd-Q8KvJN3loZ_CNdQQdk8yNqvl4fe6leHXe1Zv69Lwsf0HMricay2yaoUJqsnwTq0WsOvBITF8Kyg1hu1M?key=YfqjIZAtZI_9jsMGFGsxlQ&quot; alt=&quot;&quot;&gt;&lt;/figure&gt;



&lt;p&gt;You now have one consumable product to use with virtual currencies.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-create-a-new-currency&quot;&gt;Create a new currency&lt;/h3&gt;



&lt;p&gt;Click + New virtual currency, and define:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Code&lt;/strong&gt;: COINS&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Name&lt;/strong&gt;: Coins&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Description&lt;/strong&gt;: Used to generate AI responses&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Icon&lt;/strong&gt;: Optional&lt;/li&gt;
&lt;/ul&gt;



&lt;figure class=&quot;wp-block-image&quot;&gt;&lt;img decoding=&quot;async&quot; src=&quot;https://lh7-rt.googleusercontent.com/docsz/AD_4nXeSD-dVnOjI_DPKOXd9fM6gFm3R1YF4G12jP5QFUtxc8IWE8bNp0tR98jSyRU1wIuhobbEm9G10lSWyT2zTAvOa_pBHR81BxWlBQfs1_vGFE_TMVHQ1isQNDpxJpu69NUfIP7HD?key=YfqjIZAtZI_9jsMGFGsxlQ&quot; alt=&quot;&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;br&gt;After adding all the details associate the product we created in the previous section. This is the only configuration we need to do in RevenueCat’s dashboard to start working with Virtual currencies&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-using-virtual-currency-with-subscriptions&quot;&gt;Using virtual currency with subscriptions&lt;/h3&gt;



&lt;p&gt;Virtual currencies can also be granted on a recurring basis through subscriptions. RevenueCat handles renewals, free trials, proration, and upgrades/downgrades automatically. If your subscription includes a virtual currency grant, a customer will receive the amount at the beginning of each billing period.&lt;br&gt;For full details on how grants behave across plan switches and trials, see &lt;a href=&quot;https://www.revenuecat.com/docs/offerings/virtual-currency/subscriptions&quot;&gt;the subscription section of the official documentation.&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-2-purchase-virtual-currency-in-app&quot;&gt;Step 2: Purchase virtual currency in app&lt;/h2&gt;



&lt;p&gt;To have functional virtual currencies we need to have both a mobile app that has RevenueCat SDK, and a backend to call which will handle deducting virtual currencies when a user makes a request to generate a new story.In this example, the backend is a simple Expo API route using Expo Router. We will be building both of these in this tutorial, starting with the app.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-add-a-paywall-and-check-virtual-currency-balance&quot;&gt;Add a paywall and check virtual currency balance&lt;/h3&gt;



&lt;p&gt;The first step is to configure the app to initialize RevenueCat, show the current balance of virtual currencies, and provide a paywall to purchase virtual currencies. Add the following changes to to your app, in the example project these are down on the first screen, index.tsx&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z12k1jh wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;import { useEffect, useState } from \&amp;quot;react\&amp;quot;;\nimport { View, Text, TouchableOpacity, SafeAreaView } from \&amp;quot;react-native\&amp;quot;;\nimport Purchases from &apos;react-native-purchases&apos;;\nimport Paywall from &apos;react-native-purchases-ui&apos;;\n\nexport default function Index() {\n  const [coins, setCoins] = useState&lt;number&gt;(0);\n  const [error, setError] = useState&lt;string&gt;(\&amp;quot;\&amp;quot;);\n\n  const fetchCoins = async () =&gt; {\n    try {\n      await Purchases.invalidateVirtualCurrenciesCache();\n      const currencies = await Purchases.getVirtualCurrencies();\n      setCoins(currencies.all[&apos;COINS&apos;].balance);\n    } catch {\n      setError(\&amp;quot;Could not load coin balance\&amp;quot;);\n    }\n  };\n\n  useEffect(() =&gt; {\n    Purchases.setLogLevel(Purchases.LOG_LEVEL.DEBUG);\n    Purchases.configure({\n      apiKey: process.env.EXPO_PUBLIC_RC_SDK_KEY_IOS\n    });\n    fetchCoins();\n  }, []);\n\n  const handleBuyCoins = async () =&gt; {\n    const result = await Paywall.presentPaywall();\n    if (result === Paywall.PAYWALL_RESULT.PURCHASED) {\n      fetchCoins();\n    }\n  };\n\n  return (\n    &lt;SafeAreaView style={{ flex: 1, justifyContent: &apos;center&apos;, alignItems: &apos;center&apos; }}&gt;\n      &lt;Text style={{ fontSize: 24 }}&gt;Coins: {coins}&lt;\/Text&gt;\n      {error ? &lt;Text style={{ color: &apos;red&apos; }}&gt;{error}&lt;\/Text&gt; : null}\n      &lt;TouchableOpacity onPress={handleBuyCoins} style={{ marginTop: 20 }}&gt;\n        &lt;Text style={{ color: &apos;#576cdb&apos;, fontSize: 18 }}&gt;Buy Coins&lt;\/Text&gt;\n      &lt;\/TouchableOpacity&gt;\n    &lt;\/SafeAreaView&gt;\n  );\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This code initializes purchases in the useEffect so the SDK is ready to fetch the user’s virtual currency balance. Every time a user successfully completes the paywall the virtual currencies are refetched to update the cached amount of virtual currencies.&lt;/p&gt;



&lt;p&gt;You also need to add .env file with the following keys:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Zx486i wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;RC_PROJECT_ID=\nEXPO_PUBLIC_RC_SDK_KEY_IOS=\nRC_API_SECRET_KEY=\nOPENAI_API_KEY=&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;You can find &lt;code&gt;RC_PROJECT_ID&lt;/code&gt; from RevenueCat’s dashboard:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image&quot;&gt;&lt;img decoding=&quot;async&quot; src=&quot;https://lh7-rt.googleusercontent.com/docsz/AD_4nXfUIFknos2QAlzINrIquN_jQgO6zot7vROxYXvpAq23pHJkIj1xhMxK2u0vdAkCl9x9EQYCpstFC7UygAZmC6D7oHYNJxZZ5OemlSfF1vICaCiP2KW-VY2EPtfnkbBVq8yLXmELSw?key=YfqjIZAtZI_9jsMGFGsxlQ&quot; alt=&quot;&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;code&gt;EXPO_PUBLIC_RC_SDK_KEY_IOS&lt;/code&gt; is similar in the RevenueCat SDK. The &lt;code&gt;EXPO_PUBLIC&lt;/code&gt; part means that the key will be bundled with the app and therefore not a secret key that we have to be careful about leaking. However the other keys are secret and should never be visible in a code that someone could access for example by unbundling the app bundle.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;The &lt;code&gt;RC_API_SECRET_KEY&lt;/code&gt; will come into use in the next section when we build the backend parts of this example. You have to generate it in the RevenueCat dashboard:&lt;br&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image&quot;&gt;&lt;img decoding=&quot;async&quot; src=&quot;https://lh7-rt.googleusercontent.com/docsz/AD_4nXdmNrYJeyaydMh9E0z3fRvFfqyfOyyqr_sdYPANtc0voU9dHYx53vYLM1Wa0nwHrv9VMgi4HcgYNhU5Riktd5_wHnMjTxZkkKnot3Hvpd3CZ3B90ghNgRzTPc44DI4ss8zCseo0yA?key=YfqjIZAtZI_9jsMGFGsxlQ&quot; alt=&quot;&quot;&gt;&lt;/figure&gt;



&lt;p&gt;In this project we are using Open AI for generating bedtime stories. You can of course use any API you want or modify the following backend code to do as you wish. If you’re using Open AI, generate a new key in the Open AI API dashboard, and add it in the env for future use.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-call-backend-to-generate-a-story&quot;&gt;Call backend to generate a story&lt;/h3&gt;



&lt;p&gt;As a final step for the app itself we need to add a button for calling our backend to generate a story, and a Text element that will get populated with the generated story. When running locally the endpoint to call can be just &lt;code&gt;/generate&lt;/code&gt; and it will be called with a POST request that contains the customerID from RevenueCat’s SDK. Make the following changes to &lt;code&gt;index.tsx&lt;/code&gt;:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZMJGBP wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;import { useEffect, useState } from \&amp;quot;react\&amp;quot;;\nimport { View, Text, TouchableOpacity, SafeAreaView } from \&amp;quot;react-native\&amp;quot;;\nimport Purchases from &apos;react-native-purchases&apos;;\nimport Paywall from &apos;react-native-purchases-ui&apos;;\n\nexport default function Index() {\n  const [coins, setCoins] = useState&lt;number&gt;(0);\n  const [error, setError] = useState&lt;string&gt;(\&amp;quot;\&amp;quot;);\n\n  const fetchCoins = async () =&gt; {\n    try {\n      await Purchases.invalidateVirtualCurrenciesCache();\n      const currencies = await Purchases.getVirtualCurrencies();\n      setCoins(currencies.all[&apos;COINS&apos;].balance);\n    } catch {\n      setError(\&amp;quot;Could not load coin balance\&amp;quot;);\n    }\n  };\n\n  useEffect(() =&gt; {\n    Purchases.setLogLevel(Purchases.LOG_LEVEL.DEBUG);\n    Purchases.configure({\n      apiKey: process.env.EXPO_PUBLIC_RC_SDK_KEY_IOS\n    });\n    fetchCoins();\n  }, []);\n\n  const handleBuyCoins = async () =&gt; {\n    const result = await Paywall.presentPaywall();\n    if (result === Paywall.PAYWALL_RESULT.PURCHASED) {\n      fetchCoins();\n    }\n  };\n\n  return (\n    &lt;SafeAreaView style={{ flex: 1, justifyContent: &apos;center&apos;, alignItems: &apos;center&apos; }}&gt;\n      &lt;Text style={{ fontSize: 24 }}&gt;Coins: {coins}&lt;\/Text&gt;\n      {error ? &lt;Text style={{ color: &apos;red&apos; }}&gt;{error}&lt;\/Text&gt; : null}\n      &lt;TouchableOpacity onPress={handleBuyCoins} style={{ marginTop: 20 }}&gt;\n        &lt;Text style={{ color: &apos;#576cdb&apos;, fontSize: 18 }}&gt;Buy Coins&lt;\/Text&gt;\n      &lt;\/TouchableOpacity&gt;\n    &lt;\/SafeAreaView&gt;\n  );\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-3-handle-virtual-currencies-in-the-backend&quot;&gt;Step 3: Handle virtual currencies in the backend&lt;/h2&gt;



&lt;p&gt;Since virtual currencies are tied to users, we want the backend to handle monitoring the amount of virtual currencies the user has, and deducting them when a successful API call is done. This also improves the security as the user can’t just spoof the amount of virtual currencies and call the API with fake virtual currency amount.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Virtual currencies are non-transferable and permanently tied to the Customer ID that receives them. Merging accounts, transferring balances, or moving currencies between users is not currently supported. If your app requires account linking or switching, ensure your identity logic is stable before granting any currency.&lt;/p&gt;



&lt;p&gt;In this case our “backend” is just an Expo API route, functionality that Expo router provides out of the box. Create a new API route by naming your file like generate+api.ts. Expo Router uses this convention to define API endpoints:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZTz9R0 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;import OpenAI from \&amp;quot;openai\&amp;quot;;\n\nexport async function POST(request: Request) {\n  const { customerId, currencyCode = &apos;COINS&apos; } = await request.json();\n\n  if (!customerId) {\n    return Response.json({ error: &apos;Missing customerId&apos; }, { status: 400 });\n  }\n\n  const balance = await getBalance(customerId, currencyCode);\n  if (balance &lt; 1) {\n    return Response.json({ error: &apos;Not enough coins&apos; }, { status: 402 });\n  }\n\n  const story = await generateStory();\n  await deductCoin(customerId, currencyCode, 1);\n\n  const remaining = await getBalance(customerId, currencyCode);\n  return Response.json({ story, remainingBalance: remaining });\n}\n\nasync function getBalance(customerId: string, currency: string): Promise&lt;number&gt; {\n  const res = await fetch(\n    `https:\/\/api.revenuecat.com\/v2\/projects\/${process.env.RC_PROJECT_ID}\/customers\/${encodeURIComponent(customerId)}\/virtual_currencies`,\n    {\n      headers: {\n        Authorization: `Bearer ${process.env.RC_API_SECRET_KEY}`,\n        &apos;Content-Type&apos;: &apos;application\/json&apos;,\n      }\n    }\n  );\n  const data = await res.json();\n  return data.items.find((item: any) =&gt; item.currency_code === currency)?.balance || 0;\n}\n\nasync function deductCoin(customerId: string, currency: string, amount: number) {\n  await fetch(\n    `https:\/\/api.revenuecat.com\/v2\/projects\/${process.env.RC_PROJECT_ID}\/customers\/${encodeURIComponent(customerId)}\/virtual_currencies\/transactions`,\n    {\n      method: &apos;POST&apos;,\n      headers: {\n        Authorization: `Bearer ${process.env.RC_API_SECRET_KEY}`,\n        &apos;Content-Type&apos;: &apos;application\/json&apos;,\n      },\n      body: JSON.stringify({ adjustments: { [currency]: -amount } }),\n    }\n  );\n}\n\nasync function generateStory(): Promise&lt;string&gt; {\n  const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY! });\n\n  const res = await client.chat.completions.create({\n    model: \&amp;quot;gpt-4.1-nano\&amp;quot;,\n    messages: [\n      { role: \&amp;quot;system\&amp;quot;, content: \&amp;quot;You&apos;re a calming cat storyteller.\&amp;quot; },\n      { role: \&amp;quot;user\&amp;quot;, content: \&amp;quot;Tell me a gentle cat bedtime story.\&amp;quot; }\n    ],\n    max_tokens: 500,\n    temperature: 0.7,\n  });\n\n  return res.choices[0]?.message?.content || &apos;No story available&apos;;\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-deducting-virtual-currencies-in-the-backend&quot;&gt;Deducting virtual currencies in the backend&lt;/h3&gt;



&lt;p&gt;Let’s go through what the code does. After validating the customerId in the incoming POST request, we check the user’s virtual currency balance using the getBalance function. RevenueCat’s Web API can check the balance using the productID and customerID. The API returns a list of all virtual currency types the user holds, and we extract the balance for the specific currency. If the user doesn’t have at least one coin, we immediately respond with an HTTP 402 status, indicating that the request can’t be fulfilled due to insufficient balance.&lt;/p&gt;



&lt;p&gt;If the user does have enough balance, we then proceed to generate a story by calling the generateStory function. This function uses the OpenAI SDK to create a short bedtime story about cats. We configure the model with a friendly system prompt that sets the tone, and a simple user prompt that asks for a gentle cat story. We extract the generated story from the response. You could also stream the response, but for the simplicity we just return the full response.&lt;/p&gt;



&lt;p&gt;After generating the story, we deduct one coin from the user’s balance using the deductCoin function. Like the balance check, this also makes a call to RevenueCat’s REST API. This time, however, we send a POST request to the &lt;code&gt;/virtual_currencies/transactions&lt;/code&gt; endpoint with a negative adjustment for the COINS currency. This way we ensure the user is charged exactly one coin for this action, and keep all transactions secure and server-side.&lt;/p&gt;



&lt;p&gt;Finally, we re-fetch the updated balance to reflect the user’s remaining coins, and return both the generated story and the remaining balance in the response. This allows the frontend to update the story display and refresh the coin count without having to make an additional balance check on its own. Alternatively we can invalidate the virtual currency cache on the device with every call.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-step-4-test-your-virtual-currency-flow&quot;&gt;Step 4: Test your virtual currency flow&lt;/h2&gt;



&lt;p&gt;Before you ship your app, you want to be confident that every sandbox purchase turns into the right number of coins, and that spending coins actually gates access to your AI features. &lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;1-configure-sandbox-behavior-in-revenuecat&quot;&gt;1. Configure sandbox behavior in RevenueCat&lt;/h3&gt;



&lt;p&gt;In your RevenueCat project settings (Project settings → General), you’ll find &lt;strong&gt;Sandbox Testing Access&lt;/strong&gt;. This controls whether test purchases (RevenueCat Test Store and platform sandboxes like Apple / Google) actually grant entitlements and virtual currency.&lt;/p&gt;



&lt;p&gt;You can choose between:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Anybody (default)&lt;/strong&gt; – All sandbox purchases grant entitlements and add virtual currency as configured. This is perfect for early development when you’re iterating quickly.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Allowed App User IDs only&lt;/strong&gt; – Only specific app user IDs you add to the allowlist will get entitlements and coins from sandbox purchases. Use this when you want to limit testing to a small set of QA accounts.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Nobody&lt;/strong&gt; – Sandbox purchases are still recorded, but they no longer grant entitlements or virtual currency. This is handy if you want to test purchase flows without constantly polluting balances.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;If you tighten this setting (for example, switching from “Anybody” to “Allowed App User IDs only”), any entitlements granted by sandbox purchases to users who no longer qualify will be removed automatically. Virtual currency already granted will stay on the account, which is useful to remember if you’re doing lots of iterative tests against the same app user IDs.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;2-run-an-end-to-end-purchase-test&quot;&gt;2. Run an end-to-end purchase test&lt;/h3&gt;



&lt;p&gt;With sandbox access configured:&lt;/p&gt;



&lt;ol start=&quot;1&quot; class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Create a fresh test account&lt;/strong&gt; in the platform sandbox (Apple / Google, etc.).&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Log into your app&lt;/strong&gt; with a dedicated app user ID (or an anonymous user if that’s your setup).&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Make a test purchase&lt;/strong&gt; of your coin pack in the sandbox.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Verify the balance&lt;/strong&gt;:
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;In your app, call Purchases.virtualCurrencies() and confirm the balance matches what you expect.&lt;/li&gt;



&lt;li&gt;In the RevenueCat dashboard, open the customer and check the virtual currency section to confirm the same balance.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;If the purchase succeeded but the balance didn’t change, double-check:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;The product is associated with the correct virtual currency in the RevenueCat dashboard.&lt;/li&gt;



&lt;li&gt;You’re looking at the correct app user ID in the dashboard.&lt;/li&gt;



&lt;li&gt;Sandbox Testing Access isn’t set to “Nobody”.&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;3-test-spending-and-edge-cases&quot;&gt;3. Test spending and edge cases&lt;/h3&gt;



&lt;p&gt;Next, exercise the “spend coins” path:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Use your &lt;strong&gt;backend endpoint&lt;/strong&gt; to deduct coins for a real action (e.g. “Generate 1 bed time story”), and confirm the balance decreases both in the app and the dashboard.&lt;/li&gt;



&lt;li&gt;Try to &lt;strong&gt;spend more coins than you have&lt;/strong&gt;, and ensure your backend correctly refuses the action and your UI shows an appropriate message.&lt;/li&gt;



&lt;li&gt;Simulate &lt;strong&gt;network failures&lt;/strong&gt; between your app and backend, and confirm you don’t double-charge or double-grant currency if the user retries.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Once you’re happy with the flow, consider switching Sandbox Testing Access from &lt;strong&gt;Anybody&lt;/strong&gt; to &lt;strong&gt;Allowed App User IDs only&lt;/strong&gt; so only your test accounts can keep manipulating balances in sandbox, while you continue building and demoing the app.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-conclusion&quot;&gt;Conclusion&lt;/h2&gt;



&lt;p&gt;With just a few pieces of configuration and some simple backend logic, you’ve now integrated a complete virtual currency flow into your AI-powered app. Users can purchase coins through a paywall, track their balance in real time, and spend them on in-app actions like generating bedtime stories. By offloading the balance checks and deductions to the backend, you’ve also ensured that your virtual economy is secure.&lt;/p&gt;



&lt;p&gt;Virtual currencies unlock a flexible and scalable way to monetize AI use cases, from story generation and chatbots to custom image creation and beyond. Whether you’re building a playful hobby app or scaling a serious product, RevenueCat’s virtual currencies give you the tools to engage users and drive revenue without the friction of traditional payment models. Now that you’ve seen how it all fits together, you’re ready to start experimenting, customizing, and building richer experiences around virtual currencies.&lt;/p&gt;



&lt;p&gt;If you run in to any problems, or you have an interesting way to to use Virtual Currencies, &lt;a href=&quot;https://perttu.dev/about&quot;&gt;please let me know&lt;/a&gt;! I plan on updating this post from time to time as we keep developing Virtual Currencies and adding new features. &lt;/p&gt;



&lt;p&gt;Learn more about virtual currencies:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/plahteenlahti/rc-virtual-currencies&quot;&gt;Example repository&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/offerings/virtual-currency&quot;&gt;Virtual currencies documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Announcing RevenueCat virtual currency – monetize beyond subscriptions]]></title><description><![CDATA[Launch your own coin or credit system in minutes. With RevenueCat virtual currency, you can sell packs, grant bonuses, and manage balances across iOS, Android, and web]]></description><link>https://www.revenuecat.com/blog/company/revenuecat-virtual-currency/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/company/revenuecat-virtual-currency/</guid><pubDate>Tue, 05 Aug 2025 12:51:08 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/gamification-in-apps-complete-guide.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Today, we’re excited to announce that &lt;a href=&quot;https://www.revenuecat.com/docs/offerings/virtual-currency&quot;&gt;&lt;strong&gt;virtual currency&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt; support&lt;/strong&gt; is now live for all RevenueCat users&lt;/p&gt;



&lt;p&gt;No, we’re not pivoting into crypto (no CatCoins yet), but rather launched support for in-app currencies like coins, credits, or tokens users can buy and spend in your app&lt;/p&gt;



&lt;p&gt;After months in closed beta with feedback from games, AI-apps, and more, we’ve refined this feature to be &lt;strong&gt;ready for prime time&lt;/strong&gt;. In fact, despite being in “beta”, many big apps are already using virtual currency in production to boost revenue and engagement&lt;/p&gt;



&lt;p&gt;In-app coins or currency support in RevenueCat opens up monetization options beyond traditional subscriptions or consumables, letting you track user currency balances, sell packs of coins or credits, grant bonus currency via subscriptions, and much more. If you’ve ever wanted to add an in-app currency (think coins, gems, tokens) to your app’s economy, we now have you covered across iOS, Android, and web, all fully integrated into our dashboard and APIs&lt;/p&gt;



&lt;p&gt;Want the full technical breakdown?&lt;a href=&quot;https://www.revenuecat.com/docs/offerings/virtual-currency&quot;&gt; See the docs for Virtual Currency implementation steps, code examples, and more&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Virtual currencies are supported in the following SDK versions:&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;SDK&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Supported Versions&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;iOS&amp;nbsp;&lt;/td&gt;&lt;td&gt;5.32.0+&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Android&amp;nbsp;&lt;/td&gt;&lt;td&gt;9.1.0+&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;React Native&amp;nbsp;&lt;/td&gt;&lt;td&gt;9.1.0+&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Flutter&amp;nbsp;&lt;/td&gt;&lt;td&gt;9.1.0+&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Capacitor&amp;nbsp;&lt;/td&gt;&lt;td&gt;11.1.0+&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Unity&lt;/td&gt;&lt;td&gt;8.1.0+&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-can-you-do-with-virtual-currencies-in-modern-apps&quot;&gt;&lt;strong&gt;What can you do with virtual currencies in modern apps?&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Virtual currencies unlock &lt;strong&gt;flexible pricing and new purchase experiences&lt;/strong&gt; that weren’t possible with subscriptions alone. Here are a few ways you could use this feature:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-ai-apps-and-usage-based-pricing&quot;&gt;AI apps and usage-based pricing&lt;/h3&gt;



&lt;p&gt;If your app uses AI or other pay-per-use features, virtual currency lets you charge power users for exactly what they consume&lt;/p&gt;



&lt;p&gt;For example, an AI image generator might give free users some credits each day and sell packs of credits for heavy users. This usage-based model ensures your biggest fans can pay for more output without committing to a high recurring fee&lt;/p&gt;



&lt;p&gt;It’s a perfect complement to subscriptions or can even replace them in regions where recurring payments are tricky (for instance, parts of Asia where subscription regulations favor consumables)&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-content-apps-with-pay-per-item&quot;&gt;Content apps with pay-per-item&lt;/h3&gt;



&lt;p&gt;Apps for books, stories, music, or videos can use a coin system to monetize individual pieces of content&lt;/p&gt;



&lt;p&gt;Instead of locking everything behind a subscription, you could let users &lt;strong&gt;unlock chapters, songs, or articles&lt;/strong&gt; with a few coins. This creates a low-friction purchase for casual users (who might balk at a full subscription) while still generating revenue on a per-item basis. Many reading apps and episodic story games already use this model, and now you can implement it without building a custom currency backend&lt;/p&gt;



&lt;p&gt;Virtual currencies are &lt;strong&gt;extremely popular in content and e-learning apps&lt;/strong&gt; for exactly this reason: they drop the barrier to entry for spending&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-raise-the-ceiling-drop-the-floor-nbsp&quot;&gt;Raise the ceiling, drop the floor&amp;nbsp;&lt;/h3&gt;



&lt;p&gt;Virtual currency lets you &lt;strong&gt;raise your revenue ceiling and lower the floor&lt;/strong&gt; of entry&lt;/p&gt;



&lt;p&gt;High spenders can keep buying more currency packs on top of a subscription, no longer limited to a fixed monthly price. At the same time, more price-sensitive users can spend just $0.99 on a small pack of coins when they feel like it, rather than committing to a larger purchase. In other words, you can capture value from every segment of users&lt;/p&gt;



&lt;p&gt;Combining subscriptions with one-off consumable purchases diversifies your revenue stream and maximizes retention, allowing your app to cater to everyone from casual tippers to superfans willing to spend big&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-games-and-other-creative-uses&quot;&gt;Games (and other creative uses)&lt;/h3&gt;



&lt;p&gt;Of course, &lt;strong&gt;mobile games&lt;/strong&gt; are a classic use case – from buying gems to unlock levels, to coins for cosmetic items, a virtual currency is the lifeblood of many game economies&amp;nbsp;&lt;/p&gt;



&lt;p&gt;With RevenueCat, even game developers can now avoid building their own backend for currency management. But it doesn’t stop at games: we’re excited to see &lt;strong&gt;creative applications&lt;/strong&gt; beyond the usual suspects. Maybe you’ll use a token system to reward educational progress, or a point system to incentivize content creation in a social app&lt;/p&gt;



&lt;p&gt;The possibilities are endless, and &lt;strong&gt;if your app can benefit from an in-app economy, we’ve got the infrastructure to support it&lt;/strong&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-to-implement-virtual-currencies-in-your-app&quot;&gt;&lt;strong&gt;How to implement virtual currencies in your app&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;One of our goals was to make virtual currencies &lt;strong&gt;as easy to implement as subscriptions&lt;/strong&gt;. We designed RevenueCat’s virtual currency support to handle a wide range of scenarios out-of-the-box, from simple coin packs to complex hybrid models. Here are a few common implementation patterns and how RevenueCat supports them&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-direct-purchase-of-currency-consumables-nbsp&quot;&gt;Direct purchase of currency (consumables)&amp;nbsp;&lt;/h3&gt;



&lt;p&gt;Sell packs of coins or credits just like any other in-app purchase&lt;/p&gt;



&lt;p&gt;You can define a consumable product in App Store/Play Store (for example, “100 Coins for $4.99”) and associate it with your RevenueCat virtual currency. We will automatically add the specified amount to your user’s balance when the purchase is made&lt;/p&gt;



&lt;p&gt;No more building custom receipt validation or balance tracking. We handle the secure &lt;strong&gt;account balance management&lt;/strong&gt; for you behind the scenes&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-subscriptions-that-grant-currency-nbsp&quot;&gt;Subscriptions that grant currency&amp;nbsp;&lt;/h3&gt;



&lt;p&gt;You can also use subscriptions to &lt;strong&gt;add currency on a regular basis&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;For example, a monthly subscription might give the user 100 credits each month as part of a premium plan. RevenueCat supports this natively: when you associate a subscription product with a virtual currency, the user’s balance will increase on each subscription renewal (and you can even choose to grant the currency immediately when a free trial starts)&lt;/p&gt;



&lt;p&gt;This effectively lets you create subscription bundles (e.g. “Pro Plan: $9.99/month and get 500 coins monthly”) with minimal effort. It’s a great way to mix the predictability of subscriptions with the flexibility of consumables&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-subscriber-exclusive-discounts-or-bonuses&quot;&gt;Subscriber-exclusive discounts or bonuses&lt;/h3&gt;



&lt;p&gt;Want to reward your subscribers with better deals on currency? With a bit of configuration, you can do that too&lt;/p&gt;



&lt;p&gt;For instance, you might offer a “double coins” pack that only appears for active subscribers (for example, subscribers pay $4.99 and get 200 coins instead of the usual 100). Using our Targeting feature and by defining a custom offering for specific subscription tiers, it’s straightforward to show special currency products or pricing to certain user segments (like subscribers). You could also implement bonuses via server logic — for example, grant a bonus batch of coins whenever a subscribed user buys a consumable pack&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;The virtual currency system is flexible&lt;/strong&gt;: it works alongside entitlements, experiments, and webhooks, so you can get as creative as you want with promotions and perks&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;643&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vc-setup-47f6782d389a25022ae3c69cd903f98b-1024x643.png&quot; alt=&quot;“Create new currency” view when adding a new virtual currency in the RevenueCat dashboard&quot; class=&quot;wp-image-45428&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vc-setup-47f6782d389a25022ae3c69cd903f98b-1024x643.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vc-setup-47f6782d389a25022ae3c69cd903f98b-300x188.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vc-setup-47f6782d389a25022ae3c69cd903f98b-768x482.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vc-setup-47f6782d389a25022ae3c69cd903f98b-50x31.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vc-setup-47f6782d389a25022ae3c69cd903f98b-64x40.png 64w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vc-setup-47f6782d389a25022ae3c69cd903f98b-696x437.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vc-setup-47f6782d389a25022ae3c69cd903f98b-560x352.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vc-setup-47f6782d389a25022ae3c69cd903f98b-471x296.png 471w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vc-setup-47f6782d389a25022ae3c69cd903f98b-752x472.png 752w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vc-setup-47f6782d389a25022ae3c69cd903f98b-80x50.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vc-setup-47f6782d389a25022ae3c69cd903f98b-48x30.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vc-setup-47f6782d389a25022ae3c69cd903f98b.png 1494w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;em&gt;Above: Configuring a new virtual currency in the RevenueCat dashboard is simple. You can define a &lt;/em&gt;&lt;strong&gt;&lt;em&gt;currency code&lt;/em&gt;&lt;/strong&gt;&lt;em&gt;, name, icon, and description for up to 100 different virtual currencies per project . In this example, we’re adding a currency called “Gold” — it took just a few seconds to set up&lt;/em&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;455&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vc-products-2db62641c64d899c2dafb0f83eac2c85-1024x455.png&quot; alt=&quot;The product-to‑currency mapping UI for virtual currency as shown in the RevenueCat dashboard
&quot; class=&quot;wp-image-45430&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vc-products-2db62641c64d899c2dafb0f83eac2c85-1024x455.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vc-products-2db62641c64d899c2dafb0f83eac2c85-300x133.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vc-products-2db62641c64d899c2dafb0f83eac2c85-768x341.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vc-products-2db62641c64d899c2dafb0f83eac2c85-50x22.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vc-products-2db62641c64d899c2dafb0f83eac2c85-90x40.png 90w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vc-products-2db62641c64d899c2dafb0f83eac2c85-696x309.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vc-products-2db62641c64d899c2dafb0f83eac2c85-560x249.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vc-products-2db62641c64d899c2dafb0f83eac2c85-840x373.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vc-products-2db62641c64d899c2dafb0f83eac2c85-80x36.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vc-products-2db62641c64d899c2dafb0f83eac2c85-48x21.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/vc-products-2db62641c64d899c2dafb0f83eac2c85.png 1490w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;em&gt;Above: Associating in-app products with your virtual currency. Here, a product (subscription or one-time purchase) is linked to &lt;/em&gt;&lt;strong&gt;&lt;em&gt;deposit 50 Gold&lt;/em&gt;&lt;/strong&gt;&lt;em&gt; into the user’s balance whenever the purchase occurs. RevenueCat even lets you toggle whether a subscription should grant the currency &lt;/em&gt;&lt;strong&gt;&lt;em&gt;when a free trial starts&lt;/em&gt;&lt;/strong&gt;&lt;em&gt; (as seen in the checkbox) or only on paid renewals. All of this happens automatically. Once configured, every purchase of that product will increase the customer’s currency balance, which you can view in the dashboard or retrieve via API. Secure balance updates are handled for you, so you can focus on designing great monetization, not ledger management&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;It’s worth noting that virtual currency support is part of &lt;strong&gt;RevenueCat’s standard feature set&lt;/strong&gt; for all plans. Just like our other features (Experiments, Paywalls, etc.), it’s included at no extra cost, meaning you &lt;strong&gt;start for free and only pay when your app is earning over $2.5k per month&lt;/strong&gt;. So whether you’re a hobby dev or running a top-100 app, you can start experimenting with in-app currency right away&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-one-more-thing-the-shipaton-2025-hamm-award&quot;&gt;&lt;strong&gt;One more thing… The Shipaton 2025 HAMM Award&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;RevenueCat’s global hackathon, &lt;a href=&quot;https://www.shipaton.com/&quot;&gt;&lt;strong&gt;Shipaton 2025&lt;/strong&gt;&lt;/a&gt;, is happening now and we’re offering some serious incentives for creative app builders&lt;/p&gt;



&lt;p&gt;There’s over $350,000 in prizes up for grabs, including trips to New York and getting your app featured on a giant Times Square billboard! In line with our mission to help you make more money, we’ve introduced a new &lt;strong&gt;HAMM Award&lt;/strong&gt; (Help Apps Make Money) to honor the project with the most &lt;strong&gt;creative monetization strategy&lt;/strong&gt; mixing subscriptions, virtual currency, or other revenue streams&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;918&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/shipaton-categories-9-1024x918.png&quot; alt=&quot;The categories for Shipaton 2025, with the HAMM award highlighted, showing it as a good fit for virtual currency enabled apps&quot; class=&quot;wp-image-45432&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/shipaton-categories-9-1024x918.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/shipaton-categories-9-300x269.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/shipaton-categories-9-768x688.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/shipaton-categories-9-50x45.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/shipaton-categories-9-45x40.png 45w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/shipaton-categories-9-518x464.png 518w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/shipaton-categories-9-696x624.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/shipaton-categories-9-560x502.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/shipaton-categories-9-330x296.png 330w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/shipaton-categories-9-527x472.png 527w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/shipaton-categories-9-80x72.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/shipaton-categories-9-48x43.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/08/shipaton-categories-9.png 1040w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;This is your chance to show off an inventive use of virtual currency (or any monetization model) and get rewarded for it. Whether or not you’re participating in Shipaton, we find it inspiring to see developers push the boundaries of how apps can make money&amp;nbsp; and we can’t wait to see what you come up with&lt;/p&gt;



&lt;hr class=&quot;wp-block-separator has-alpha-channel-opacity&quot;&gt;



&lt;p&gt;&lt;strong&gt;Ready to get started?&lt;/strong&gt; Virtual currency support is live in the RevenueCat dashboard. After you’ve set up your currencies, you can fetch currency balances through our Developer API 2.0.0, or in your app via the SDK. Need some technical support? Check out &lt;a href=&quot;https://www.revenuecat.com/docs/offerings/virtual-currency&quot;&gt;the virtual currency docs&lt;/a&gt;, or reach out&lt;/p&gt;



&lt;p&gt;We’re eager for you to try it out, start monetizing better, and &lt;strong&gt;let us know what you think&lt;/strong&gt;. Our team is listening closely to your feedback to help shape where we take this feature next&lt;/p&gt;



&lt;p&gt;The era of &lt;em&gt;coins and credits&lt;/em&gt; in RevenueCat has begun, and you’re invited to build the next big thing with it. Happy monetizing, and happy building!&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[How to win Shipaton, part 1: coming up with an idea]]></title><description><![CDATA[Don’t know what to build for Shipaton? A 45x hackathon winner breaks down how to find and validate app ideas that solve real problems—and have a shot at winning.]]></description><link>https://www.revenuecat.com/blog/engineering/how-to-win-shipaton-part-1-coming-up-with-an-idea/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/how-to-win-shipaton-part-1-coming-up-with-an-idea/</guid><pubDate>Mon, 04 Aug 2025 08:41:05 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/1.-How-to-come-up-with-an-app-idea-for-Shipaton.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Shipaton just kicked off. Developers are starting to build their apps (if they aren’t already). You’re interested in participating, but you don’t know where to start. Worst of all, you don’t even know what to build.&lt;/p&gt;



&lt;p&gt;I’ve been there. In my past life, I competed in over 70 hackathons and ended up winning 45 of them. If you’re unfamiliar, hackathons are fast-paced, 24–48-hour sprints to build something cool, useful, or delightful. Shipaton is essentially a mobile hackathon with a slightly longer timeframe.&lt;/p&gt;



&lt;p&gt;The keys to winning a hackathon—whether it lasts two months or 24 hours—are the same:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Solve a real problem&lt;/li&gt;



&lt;li&gt;For real people&lt;/li&gt;



&lt;li&gt;In a way that delivers delight or an “aha” moment&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;I’m going to explain how to hit those three points and how they’ll help you win Shipaton. This article is the first in a series focused on ideating, building, and growing a mobile app with a shot at winning. By the end of this guide, you’ll have a concrete idea to build, a way to validate it, and confidence that your app solves a real problem.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-come-up-with-a-killer-idea&quot;&gt;Come up with a killer idea&lt;/h2&gt;



&lt;p&gt;The first step, before designing or building anything, is to come up with an idea—not just something you &lt;em&gt;want&lt;/em&gt; to build, but something you &lt;em&gt;need&lt;/em&gt; to build. That difference is crucial. Once the initial motivation fades, what you wanted to build becomes something you’ll “work on later when you have more time.” But the feeling of &lt;em&gt;needing&lt;/em&gt; to build something is much stronger. It gets you through the bugs, the burnout, and even the users who hate your idea.&lt;/p&gt;



&lt;p&gt;Your mission statement should be:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;I need to build this, because I’m the only one who can get it right.&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Getting to that point requires working on a problem that’s tangible, challenging, and shared by more than just you.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-discover-a-real-problem&quot;&gt;Discover a real problem&lt;/h3&gt;



&lt;p&gt;A real problem is one that exists for more than one person. A common mistake is building something for yourself and assuming others share your pain. More often than not, the problem isn’t as serious as you think—or it’s already been solved.&lt;/p&gt;



&lt;p&gt;Here’s an example. I worked on a mobile app where the company had top-tier talent: successful founders, strong product leads, and a bold vision. The idea was to rival Twitch by letting viewers bet on what the streamer would do next. The thinking was that this would drive engagement, which would attract more streamers, and in turn, more viewers.&lt;/p&gt;



&lt;p&gt;It worked at first. But after launch, users didn’t return. The team overlooked a key insight: most people watch game streams passively. They put them on in the background. They aren’t looking to engage more deeply.&lt;/p&gt;



&lt;p&gt;The company started with a solution and went looking for a problem. Always start the other way around.&lt;/p&gt;



&lt;p&gt;A real problem comes from real people with real pain or unmet needs. Discovering that is the first step to building something that matters.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-talk-to-people&quot;&gt;Talk to people&lt;/h3&gt;



&lt;p&gt;The best way to find real problems is to talk to people. Not to pitch your idea—just to listen. Ask open-ended questions. Pose hypotheticals. Get them to imagine a perfect world.&lt;/p&gt;



&lt;p&gt;Talking to users could’ve saved that Twitch competitor. A few honest conversations might’ve revealed that engagement wasn’t the issue.&lt;/p&gt;



&lt;p&gt;It’s not always easy to start these conversations, especially if you’re unclear on the problem space. Narrowing your focus helps. Start with a domain you know. Maybe you once worked in a research lab and remember how tedious it was to recruit student test subjects.&lt;/p&gt;



&lt;p&gt;There’s your starting point. Reach out to a few research groups. Ask if they struggle with recruitment. Offer to chat. Show up with curiosity and ask open questions. You may find your original assumption was wrong, but you might also uncover something real.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-start-with-a-single-problem&quot;&gt;Start with a single problem&lt;/h3&gt;



&lt;p&gt;Things can still go sideways even if you’ve identified a real problem—especially if you try to solve too many problems at once, or your initial solution becomes too complex.&lt;/p&gt;



&lt;p&gt;Let’s look at an example.&lt;/p&gt;



&lt;p&gt;You’ve decided to build something for barbers to manage bookings. You create a solid mobile app that allows barbers to mark when they have free slots, and lets customers book those slots. Then, one of the barbers mentions they also struggle with payments and estimating profitability.&lt;/p&gt;



&lt;p&gt;Instead of launching with the booking system, you decide to keep building—adding billing functionality and advanced charting features. What was meant to take two months turns into six. In that time, some customers may have found alternative solutions. And the new features? They may not even add much value beyond that one barber’s specific case.&lt;/p&gt;



&lt;p&gt;This is why speed matters. And why narrowing down your scope is critical in the beginning. Your goal should be to validate your idea with the bare minimum set of features. Don’t try to build a full menu—just focus on getting one dish right.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-validate-your-idea&quot;&gt;Validate your idea&lt;/h2&gt;



&lt;p&gt;We have already talked about validating your idea in the previous part but product development in essence is constant validation of ideas. It doesn’t stop after validating the initial idea. Shipaton takes two months. If you truly want to win, you should be validating your product until the very last day. This means that validating ideas does not stop after you’ve built your prototype, it doesn’t stop after you have launched your product, and it doesn’t stop after you made some dollars from your idea. Building products is a continuous process of learning and discovery.&amp;nbsp;&lt;br&gt;&lt;/p&gt;



&lt;p&gt;In order to constantly validate your idea you need to gather feedback from users in a continuous way. When you’re first starting building your product, aim to release when your product has the feature your users asked for, but when you’re still slightly embarrassed about the state of your product. Embarrassment is the only way to know that you’re not spending time on something that might end up being useless in the end. If that feels hard here is how to validate your idea at every step:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;If you only have a rough idea of your app, make a paper or figma prototype. Send the link to users and ask them to test it out over a video call and narrate as they use the prototype&lt;/li&gt;



&lt;li&gt;If you app is only on your phone, give them your phone and ask them to use it&lt;/li&gt;



&lt;li&gt;If you have built a version of your app that can be distributed, let users install the app on their phone and schedule a call with them after they have tested it&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;In the beginning it is not about the amount of feedback, but the quality of it. Don’t implement analytics in your app, it doesn’t provide any benefit at this level. Instead aim to ask open ended questions, prompt users to provide suggestions, evaluate the given suggestions critically and build the features that make the cut. Launch your product as many times as it takes:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image&quot;&gt;&lt;img decoding=&quot;async&quot; src=&quot;https://lh7-rt.googleusercontent.com/docsz/AD_4nXeQHaOJl9EcU0edfMy0F-8LSLmball3yYOPfSfyCsFf8o1MdyQre0HyutpkKlLaIKPBEL6nplw6ZG3dLFrGycaYzEz8ZCisgvtAlVXt79wZdWR0TO5PEnwNto_PqFNBM1o5w0M4?key=up-RMgN7wRVuDj9hrroF3w&quot; alt=&quot;&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Eventually your idea will take shape into something that users would be interested in using, at which point, preferably earlier already, you should start asking how much they would be willing to pay for it. How much people are willing to pay for something is the best estimate of how much value they give to it. Your users hopefully want to pay some amount of money for the product, even if you ended up monetizing it with ads. Monetizing is also one of the requirements of Shipaton.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;get-ready-to-throw-it-all-away&quot;&gt;Get ready to throw it all away&lt;/h3&gt;



&lt;p&gt;Gathering feedback has now been mentioned a few times, and you probably have an idea what to do with feedback to improve your product. But what if it turns out that the thing you’ve built doesn’t solve a single problem for the user, they’re not willing to pay any money for it, or they just don’t find it useful. What do you do then?&lt;/p&gt;



&lt;p&gt;The answer is simple but cruel: you throw it all away and start from scratch.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;This is also the core of a successful product development feedback loop. The faster you can build out your idea, the faster you can validate if the idea is worth it to the users in the way you thought. Spending a lot of resources on development in the beginning might be a wasted effort, so love your idea but also plan for abandonment from the beginning. Hopefully you only end up scrapping ideas and features, not completed products.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;determine-metrics&quot;&gt;Determine metrics&lt;/h3&gt;



&lt;p&gt;A systemic approach to making informed decisions about whether it is worth it to persevere with an idea is to determine metrics for tracking success from the start. These are your benchmarks that tell you whether the thing you’re building is actually resonating with users. Without metrics, you’re flying blind.&lt;/p&gt;



&lt;p&gt;Metrics don’t have to be complicated. In fact, they should be so simple that you can answer them in a sentence or two after talking to just a few users. Here are a few examples:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Activation&lt;/strong&gt;: How many people got to the core value of the app on first try?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Retention&lt;/strong&gt;: Did they come back the next day or the next week?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Referral&lt;/strong&gt;: Did they tell anyone else about it?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Monetization&lt;/strong&gt;: Did they say they’d pay for it?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;You don’t need to track everything. Pick one primary metric that reflects whether your idea is working, and use that to guide what you do next. If you’re improving that one thing, chances are you’re heading in the right direction.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;the-minimum-lovable-product&quot;&gt;The Minimum Lovable Product&lt;/h3&gt;



&lt;p&gt;You may have heard of the Minimum Viable Product (MVP), a product that accomplishes the main use case but nothing else.&amp;nbsp; For Shipaton however you should aim for building something people truly love: a Minimum Lovable Product (MLP). Both minimum viable and minimum lovable products accomplish their purpose, but the latter does it in a way that delights the user and makes them come back. This can be for example by introducing a novel approach solution of an existing problem, such as a todo where accomplishing a task requires taking a selfie. In hackathons, your idea can be something that someone already comes up with, but with some novelty and love, you can still end up winning.&lt;/p&gt;



&lt;p&gt;When I used to compete in hackathons I would spend most of my time discovering a problem and understanding it. Solutions usually came after that almost without thinking. All my other time (not counting actually coding the hackathon project) would go into finding a unique approach, novel technology, or delightful interaction. Sometimes this meant writing code for drones to follow a construction crane to give better visibility to the crane handler, building an RPG inspired mobile app for study planning, or mobile hospital app with indoor positioning with beautiful UI. In other words, aiming for MLP. Often it brought the main prize.&lt;/p&gt;



&lt;p&gt;An MLP does not mean cutting corners. It means ruthlessly cutting scope, while preserving the delight. It means identifying the absolute smallest surface area that communicates your product’s value — and then making sure that piece feels magical. The MLP should give your user a small, delightful win.&lt;/p&gt;



&lt;p&gt;Ask yourself:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;What is the smallest thing I can build that still solves the problem?&lt;/li&gt;



&lt;li&gt;What makes this feel personal, intentional, or unique?&lt;/li&gt;



&lt;li&gt;What can I polish just enough that someone says “wow, I didn’t expect that”?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;You’re not building a castle. You’re building a tiny hut, but one with charm. Something your user wants to return to, not because it has everything, but because what it does, it does well.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;



&lt;p&gt;At the start, building an app can feel overwhelming, especially when you don’t even know what to build. But the truth is, you don’t need a groundbreaking idea. You just need a real problem, a focused solution, and the willingness to listen and adapt along the way. When you talk to people, narrow in on what matters, and build something small but thoughtful, things start clicking. You get that feeling of momentum. Suddenly, you’re not just hacking on an app — you’re building something that could actually matter to someone.&lt;/p&gt;



&lt;p&gt;Shipaton gives you two months and a big stage. That’s more than enough time to go from zero to something you’re genuinely proud of. Don’t wait for the perfect idea or the perfect plan. Start small, stay lean, and let your users guide what you build. The best apps don’t come from perfect strategy — they come from people who are curious, willing to listen, and stubborn enough to keep going.&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[How Rudrank Riyam won Shipaton’s Build in Public Award by sharing every step]]></title><description><![CDATA[Behind the scenes of a Shipaton-winning launch — from prototype to community-powered release.]]></description><link>https://www.revenuecat.com/blog/company/shipaton-interview-with-rudrank-riyam/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/company/shipaton-interview-with-rudrank-riyam/</guid><pubDate>Thu, 31 Jul 2025 10:29:37 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/4.-Shipaton-interviews_-Rudrank-Riyam-–-How-to-win-build-in-public.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;&lt;em&gt;As part of this year’s Shipaton, we’re highlighting stories from past participants to show what’s possible when you commit to building in public. Whether you’re aiming to sharpen your skills, launch your first product, or maybe even win, these interviews are meant to spark ideas, share learnings, and inspire you to take part in Shipaton.&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;&lt;em&gt;We’re also including their tips on how to get the most out of Shipaton, from choosing the right idea to managing your time to pushing through the inevitable bugs and blockers.&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;Next up: &lt;strong&gt;Rudrank Riyam&lt;/strong&gt;, an independent iOS developer from India, whose journey in mobile development began in 2019, after winning the coveted WWDC scholarship and interning at Apple. When he saw last year’s Shipaton announcement he immediately knew he had to take part in it, especially for the Build in Public award.&lt;/p&gt;



&lt;p&gt;&lt;em&gt;I only participated to win. It wasn’t about the second or the third prize. I wanted the first prize. I also knew this was the push I needed to get the gradient app I was working on out to users.&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;At the time Rudrank was in between jobs and had ample time to dedicate to building a project for Shipaton. Rudrank’s sister encouraged him to also try something new for the Build in Public part: start a YouTube channel and document the process of building and growing the app there.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“I saw the Built in Public award and thought, that’s the one I can win. I’ve been building in public since 2019 and I have like 30,000 tweets. It just comes naturally to me.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-building-meshing-app-and-talking-about-it&quot;&gt;Building Meshing app and talking about it&lt;/h2&gt;



&lt;p&gt;When asked how he came up with the idea for the Meshing app, an app for creating beautiful mesh gradients in your iPhone, was inspired by Apple Music’s visualizations and from how long it took to display a preview of a mesh gradient in SwiftUI.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“The previews kept loading…and loading…and loading. It felt like an eternity. During those moments, my only thought was: ‘Ah, I wish I had an app that could visualise these mesh gradients easily.’”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Rudrank originally built Meshing as a macOS-only app, with no plans to release it publicly, but after the Shipaton announcement he decided to pivot to building a mobile app and monetizing it with RevenueCat. “I had to essentially rebuild the whole app”, he said.&lt;/p&gt;



&lt;p&gt;During the build process he used AI for building the app, feeding Claude documentation on SwiftUI and modifying the code it created (you can actually see some of the prompts in Rudrank’s &lt;a href=&quot;https://devpost.com/software/meshing&quot;&gt;Devpost submission&lt;/a&gt;). This approach came in handy, as, in his own words, his coding skills were rusty. Allowing AI to work on the code gave him the time to dive deep into the fundamentals of mesh gradients and bezier curves.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-monetizing-with-revenuecat&quot;&gt;Monetizing with RevenueCat&lt;/h3&gt;



&lt;p&gt;One of the goals of Shipaton is to get people monetizing their apps, and in Rudrank’s case he had already been burned by hand coding subscriptions in one his apps:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“In 2020, it was a nightmare. I was on the verge of crying because I messed up something and people were getting subscriptions for free”&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;That experience led him to adopt RevenueCat, which he described as a turning point: “After that I integrated RevenueCat and then I really liked it. I started advocating it to clients. I was taking consulting calls and just saying, ‘Just use RevenueCat.&apos;”&amp;nbsp;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;For Meshing, he opted for a straightforward model: the app was free to use, but exporting a gradient as a wallpaper triggered a paywall. This allowed users to experience the full creative process before being prompted to pay, aligning with his goals of making an app that allows you to explore its main feature for free.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-building-in-public&quot;&gt;Building in public&lt;/h2&gt;



&lt;p&gt;Rudrank aimed from the beginning to win the build in public award, where the goal is to share the progress of building and growing the app in social media. In Rudrank’s case, since he was already very active on X, tweeting regularly, but also resurrecting the YouTube channel he had created years earlier.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-it-feels-to-win-shipaton&quot;&gt;How it feels to win Shipaton&lt;/h2&gt;



&lt;p&gt;On the final stretch of Shipaton, Rudrank had a strong feeling that he was on the track to win. “By day 40, I kind of knew that I would win the first prize because the others I thought were my competition — he had given up,” he said. Still, he didn’t slow down on tweeting or posting videos.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;That determination paid off. When he saw his name among the winners, it hit hard. “I could feel the goosebumps,” he recalled.&lt;/p&gt;



&lt;p&gt;But the victory wasn’t just about recognition or prize money. What got him most excited was discovering that RevenueCat would present the awards in person. “I got to know that the Shippies award will be given in San Francisco. So at 2:00 p.m. I decided to buy the plane ticket. The flight was at 2:00 a.m.” He booked it impulsively, using the prize money to fund the trip. That spontaneous flight marked more than a celebration, it was like closing a loop for a project built from uncertainty, vulnerability, and relentless sharing in public.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;682&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_8356-1024x682.jpeg&quot; alt=&quot;Rudrank receiving the Build in Public award at 2024 RevenueCat App Growth Annual&quot; class=&quot;wp-image-45050&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_8356-1024x682.jpeg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_8356-300x200.jpeg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_8356-768x512.jpeg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_8356-50x33.jpeg 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_8356-60x40.jpeg 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_8356-696x464.jpeg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_8356-560x373.jpeg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_8356-444x296.jpeg 444w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_8356-708x472.jpeg 708w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_8356-80x53.jpeg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_8356-48x32.jpeg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_8356.jpeg 1280w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-plans-for-this-year-s-shipaton&quot;&gt;Plans for this year’s Shipaton&lt;/h2&gt;



&lt;p&gt;This year Rudrank has even bigger goals: going for two released apps instead of one. The first one is going to be a fitness app that tracks workouts, sleep and macros. Second one is a journaling app, resurrecting a previous idea he had to abandon. Originally he planned on entering each app in different categories (Grand Prize and Build in Public), but now he’s aiming high, and said “Why not both apps for both prizes?”&lt;/p&gt;



&lt;p&gt;Unlike Meshing, which he built more for fun, this year’s apps address his personal pain points.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“When Shipathon was announced, I started a new hashtag — it’s called &lt;/em&gt;&lt;strong&gt;&lt;em&gt;#burnaton&lt;/em&gt;&lt;/strong&gt;&lt;em&gt;. Every day I’m posting that I’m burning this many active calories and this was my workout routine. &lt;/em&gt;&lt;em&gt;It keeps me accountable on making the app better, and then the folks can tell me what to do. And second, I’m burning a lot of calories and it’s helping me get fitter&lt;/em&gt;&lt;em&gt;”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Rudrank is going to build in public this time as well, but with a healthier mindset. He will still be posting daily, but this time aiming to do it in a more sustainable, self-growth way, rather than chasing validation. He’s still going all in with plans to support other Shipaton participants to ship their apps, despite them being his competition. He has also cleared his calendar for the period of Shipaton.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“Burn the boats mentality: no backup plan, full focus”&lt;/em&gt;&amp;nbsp;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-advice-for-shipaton-participants&quot;&gt;Advice for Shipaton participants&lt;/h2&gt;



&lt;p&gt;For Rudrank, success at Shipathon wasn’t about beating others, it was about beating who he was yesterday. While some participants might fear they can’t compete with his daily videos, tweets, and articles, Rudrank had a different perspective: the real competition is internal.&lt;/p&gt;



&lt;p&gt;When it comes to advice to new builders, Rudrank’s advice is simple but achievable: “Ship a ton.” Don’t obsess over perfection. Don’t wait for the big breakthrough moment. Just keep building. “If you see my first video and then the last few videos, the way I speak and how natural I sound — that’s what improved and what really matters..”&lt;/p&gt;



&lt;p&gt;Rudrank also encourages participants to solve problems that matter to them. Last year, he built Meshing because it looked cool. This year, he’s building apps tied directly to his personal health and wellness.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Finally, Rudrank reminds everyone that the biggest prize isn’t cash or visibility. It’s the community. “The real Shipathon win is the friends you make along the way,” Rudrank says with a laugh, fully aware that it sounds like a cliché. For him, it’s undeniably true. From late-night encouragements to unexpected DMs from fellow builders, the relationships he formed during the competition became just as meaningful as the app he shipped. “Even though some of them were technically my competitors, I didn’t see it that way,” he adds. “I just wanted to help others get to the finish line, too.”&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Stop focusing on LTV to CAC: It’s a terrible metric for subscription apps]]></title><description><![CDATA[Why LTV:CAC falls short and what subscription apps should measure instead]]></description><link>https://www.revenuecat.com/blog/growth/ltv-cac-subscription-apps-alternatives/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/ltv-cac-subscription-apps-alternatives/</guid><pubDate>Tue, 29 Jul 2025 09:20:22 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/ltv-cac-subscription-apps-alternatives.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Let me start by telling a story.&lt;br&gt;&lt;br&gt;A few years ago, I had a client, a VC-backed subscription app who were gearing up for their next fundraise. And there was one set of investors that seemed particularly interested in these three questions:&lt;br&gt;&lt;br&gt;1) How long do paying customers keep paying (Customer Lifetime, CLT)&lt;/p&gt;



&lt;p&gt;2) How much do they pay you before they churn (&lt;a href=&quot;/blog/growth/what-is-lifetime-value-ltv-apps/&quot;&gt;Lifetime Value, LTV&lt;/a&gt;)&lt;/p&gt;



&lt;p&gt;3) How much does it cost you to acquire those customers (CAC)&lt;br&gt;&lt;br&gt;Ultimately the investors wanted to dive into the business’s unit economics. But the pitch deck focused on unpacking one metric — LTV:CAC. Whilst these are related, they are not the same thing.&lt;br&gt;&lt;br&gt;And I’ll just say it: I think &lt;strong&gt;focusing on LTV to CAC is a terrible way of measuring the success of most consumer subscription app businesses.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;But since that day, I’ve worked with dozens of consumer subscription apps and spoken to countless teams who still stress the importance of LTV to CAC.&lt;/p&gt;



&lt;p&gt;Let’s break down &lt;strong&gt;each of the metrics’s components&lt;/strong&gt; to see why LTV:CAC isn’t a great fit for sub apps, and talk about &lt;strong&gt;the metrics I prefer to track&lt;/strong&gt; instead.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-i-m-not-a-fan-of-these-metrics&quot;&gt;Why I’m not a fan of these metrics&lt;/h2&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-chaos-of-tracking-customer-lifetime-amp-lifetime-value&quot;&gt;The chaos of tracking Customer Lifetime &amp;amp; Lifetime Value&lt;/h3&gt;



&lt;p&gt;Starting with Customer Lifetime. How long do paying customers keep paying you?&lt;br&gt;&lt;br&gt;This is a beautiful concept, but in the subscription app world, it’s sort of just that. A concept.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;It’s not actually that easy to definitively pinpoint Customer Lifetime. Firstly it can only be done retrospectively, after a user has churned. If a customer keeps paying month after month, year after year; you can’t say for certain what their lifetime is.&lt;/p&gt;



&lt;p&gt;To add another layer of complexity, if your app is particularly seasonal, users may sign up every year between particular months then cancel their subscription and then come back the following year. So that churn we thought was churn actually wasn’t churn!&lt;br&gt;&lt;br&gt;Even if your app isn’t seasonal, users may decide to pause their subscription for a whole host of reasons only to come back later. Trying out a competitor, cutting back on frivolous costs, not relating the need your app solves at that point in time. The list goes on.&lt;br&gt;&lt;br&gt;All of this makes tracking Customer Lifetime incredibly difficult.&lt;/p&gt;



&lt;p&gt;And if we don’t know what the Customer Lifetime is, how can we possibly state what our customers’ lifetime value is? We can’t.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-beauty-of-customer-lifetime-amp-lifetime-value&quot;&gt;The beauty of Customer Lifetime &amp;amp; Lifetime Value&lt;/h3&gt;



&lt;p&gt;Ironically, part of the beauty of consumer subscription apps is this complex and almost toxic relationship between the customer, the cancel button and the resubscribe button.&lt;/p&gt;



&lt;p&gt;You can have users who keep paying for years on end and are incredibly valuable to your business. These customers bring up the value of any given cohort and ultimately increase the perceived lifetime value.&lt;/p&gt;



&lt;p&gt;On the flip side you have users who cancel after just one month or even one week. These customers bring down the lifetime of any given cohort and decrease the perceived lifetime value.&lt;/p&gt;



&lt;p&gt;So how can we monitor unit economics over time and assess the efficiency of our marketing budget without going against the natural dynamics of subscription app retention curves.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Well, here’s what I do.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-metrics-i-prefer-instead&quot;&gt;The metrics I prefer instead&lt;/h2&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-periodic-arppu-snapshots&quot;&gt;Periodic ARPPU Snapshots&lt;/h3&gt;



&lt;p&gt;Rather than setting off on a wild goose chase to calculate customer LTV, I prefer to take snapshots of the revenue generated from individual customers and cohorts at specific times.&lt;br&gt;&lt;br&gt;I like to call these periodic ARPPU snapshots.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Others call this realized LTV.&lt;/p&gt;



&lt;p&gt;Typically I’d want to take these snapshots in a way that lines up with core conversion and renewal periods. Although, these can be taken as frequently as you like.&lt;br&gt;&lt;br&gt;This might look like:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Day 0 (Trial Start / Initial Conversion)&lt;/li&gt;



&lt;li&gt;Day 7 (Trial Conversion)&lt;/li&gt;



&lt;li&gt;Day 30 (Monthly renewal&lt;/li&gt;



&lt;li&gt;Day 90 (Quarterly Renewal)&lt;/li&gt;



&lt;li&gt;Day 365 (Annual Renewal)&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Alongside these core periods, I find it helpful to look at ARPPU monthly when doing more granular analyses.&lt;/p&gt;



&lt;p&gt;In RevenueCat, this can be done really easily by filtering by Realized Customer LTV (which is the same as ARPPU) in the &lt;a href=&quot;https://www.revenuecat.com/docs/dashboard-and-metrics/charts/cohort-explorer&quot;&gt;Cohort Explorer&lt;/a&gt;.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;543&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/cohort-explorer-1024x543.png&quot; alt=&quot;&quot; class=&quot;wp-image-45375&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/cohort-explorer-1024x543.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/cohort-explorer-300x159.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/cohort-explorer-768x408.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/cohort-explorer-1536x815.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/cohort-explorer-2048x1087.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/cohort-explorer-50x27.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/cohort-explorer-75x40.png 75w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/cohort-explorer-696x369.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/cohort-explorer-560x297.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/cohort-explorer-558x296.png 558w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/cohort-explorer-840x446.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/cohort-explorer-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/cohort-explorer-48x25.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The idea here is that at certain points in time we are stepping back and saying, “Hey, right now – at this point in time – how much are customers actually worth to us?”&lt;/p&gt;



&lt;p&gt;We understand that their value will change over time. Of course. But by taking regular snapshots, we can observe how customer value shifts over time, allowing us to take action and allocate budgets more effectively.&lt;/p&gt;



&lt;p&gt;It also forces us to take a cohort based approach to analysis which among other things, has the added benefit of making it pretty quick to spot seasonal trends.&lt;/p&gt;



&lt;p&gt;E.g. “Whilst it appears that Summer cohorts churn at a faster rate than Winter cohorts, they actually just follow a different resurrection pattern. They’re also much more likely to purchase consumables. So overall Day 365 ARPPU is pretty similar”&lt;/p&gt;



&lt;p&gt;When focusing on a single LTV:CAC metric, these kinds of insights might not be so obvious.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-payback-period&quot;&gt;Payback period&lt;/h3&gt;



&lt;p&gt;Once we’ve started tracking these snapshots, it also becomes much easier to dive into unit economics and identify our payback period.&lt;br&gt;&lt;br&gt;Personally, I like to track ARPPU:CAC each time we take an ARPPU snapshot to measure revenue efficiency over time. But the advantages of this approach go beyond this.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Where this really shines is for more granular cohort analysis in line with major user acquisition changes. For example, if we make significant budget shifts or increases across Paid UA, test new creative formats, launch new web to app funnels, or lean in on different JTBDs, we can take more frequent ARPPU snapshots and track the impact of our changes across blended metrics.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-gross-contribution-after-cac&quot;&gt;Gross contribution after CAC&lt;/h3&gt;



&lt;p&gt;Let’s be honest, we aren’t doing all of this work, juggling all of these metrics and reading well written articles in our free time just to break even. 🙃&lt;/p&gt;



&lt;p&gt;We are looking to be profitable.&lt;/p&gt;



&lt;p&gt;And that’s where Gross Contribution after CAC comes in. By continuing to take these periodic snapshots, we can see how much money we are making after CAC at various stages.&lt;br&gt;&lt;br&gt;We can answer questions like:&lt;br&gt;&lt;br&gt;“If we break even by month 3, how much money have we made by month 12?”&lt;/p&gt;



&lt;p&gt;“That cohort that took 8 months to break even, how much have we made from them now?“&lt;br&gt;&lt;br&gt;What’s super important to remember here is that different cohorts may have different values, different payback periods and different gross contributions after CAC. But tracking these over time, across cohorts allows us to closely monitor the health of our subscription app business.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-it-s-time-to-embrace-some-better-metrics&quot;&gt;It’s time to embrace some better metrics&lt;/h3&gt;



&lt;p&gt;So, from LTV to ARRPU Snapshots and from LTV:CAC to ARPPU:CAC.&lt;/p&gt;



&lt;p&gt;These are subtle changes, but adopting metrics that reflect the dynamics of subscription apps makes a huge difference, especially when it comes to rapidly scaling user acquisition.&amp;nbsp;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[From first app to WWDC winner: Leandro Tolaini’s Shipaton story]]></title><description><![CDATA[How building his first app led Leandro Tolaini from Shipaton to winning WWDC's Student Challenge ]]></description><link>https://www.revenuecat.com/blog/company/shipaton-interview-with-leandro-tolaini/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/company/shipaton-interview-with-leandro-tolaini/</guid><pubDate>Mon, 28 Jul 2025 13:10:03 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/3.-Shipaton-interviews_-Leandro-Tolaini-–-Shipaton-as-a-learning-experience.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;&lt;em&gt;As part of this year’s Shipaton, we’re highlighting stories from past participants to show what’s possible when you commit to building in public. Whether you’re aiming to sharpen your skills, launch your first product, or maybe even win, these interviews are meant to spark ideas, share learnings, and inspire you to take part in Shipaton.&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;&lt;em&gt;We’re also including their tips on how to get the most out of Shipaton, from choosing the right idea to managing your time to pushing through the inevitable bugs and blockers.&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;First up: &lt;strong&gt;Leandro Tolaini&lt;/strong&gt;, a computer science student from France who participated in last year’s Shipaton. When he stumbled across a tweet about the event, he was just one month into learning iOS development and had never released an app before:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“The timing was perfect,” Leandro says over our video call. “I had one free month before school started again, and I thought, why not take part in this and actually build something?”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-building-abs-god&quot;&gt;Building Abs God&lt;/h2&gt;



&lt;p&gt;Leandro’s idea for his Shipaton project came from something simple and personal: Leandro wanted a better ab workout app. That’s it. No grand business model, no huge feature roadmap; just a clear problem he personally wanted solved.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“I wanted a summer body,” he laughs. “But more seriously, I wanted to build an app that was simple, clean, and did exactly what I needed.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Leandro did what every app developer should do as the first step before starting any development, he started by looking at what was already out there. It turned out that many fitness apps on the App Store were cluttered, visually dated, or overloaded with upselling and unnecessary features. Others charged high subscription prices but didn’t offer much value in return.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;578&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_3512-1024x578.jpeg&quot; alt=&quot;Leandro working on Abs God&quot; class=&quot;wp-image-44816&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_3512-1024x578.jpeg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_3512-300x169.jpeg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_3512-768x433.jpeg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_3512-1536x866.jpeg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_3512-2048x1155.jpeg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_3512-71x40.jpeg 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_3512-696x393.jpeg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_3512-560x316.jpeg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_3512-525x296.jpeg 525w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_3512-837x472.jpeg 837w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_3512-80x45.jpeg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_3512-48x27.jpeg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;What Leandro wanted didn’t seem to exist — a well-designed native app with straightforward functionality and pricing that made sense. That insight gave him inspiration and direction needed to start working on his first actual mobile app.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“It felt like there was a niche there in just a clean, focused app that looked good and worked well.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Since he now had an idea,&amp;nbsp; the only thing that was needed was the hard part: actually building the app. Before that he would also need to learn how to build an app.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-learning-by-doing&quot;&gt;Learning by Doing&lt;/h3&gt;



&lt;p&gt;One of Leandro’s goals with Shipaton was simple: learn as much as he could. He joined solo, without a team, and started building with SwiftUI and SwiftData. Before this he had barely touched these two tools.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“I basically just brute forced it,” he said. “Eight hours a day, every day, for a month. It was intense, but I was really enjoying it. There’s just something when you’re building for yourself.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Learning while building was far from smooth. SwiftUI was powerful, but at times unpredictable. Newer APIs like SwiftData were under-documented, and many of the tutorials using it had outdated information. Features that seemed easy and straightforward to implement, ended up requiring hours of debugging, googling and asking ChatGPT.&amp;nbsp;&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“If I got stuck on something for too long, I would either try to find a workaround or change the feature. I didn’t want to burn time being stuck.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Leandro leaned on the community for support. Searching Apple developer forums, asking questions on X, and watching tutorials late into the night. Biggest help, however, was ChatGPT, which most often pointed in the right direction, at least.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“That was a big part of it. Just knowing how to ask for help and where to look.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;And while the code wasn’t perfect — “very messy and unmaintainable” in his own words — it &lt;em&gt;worked&lt;/em&gt;. The app shipped. And that was the goal.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-monetizing-abs-god&quot;&gt;Monetizing Abs God&lt;/h3&gt;



&lt;p&gt;When it came time to monetize, which is one of the requirements of Shipaton, Leandro decided to keep things simple. Fitness apps are known to convert well (&lt;a href=&quot;https://www.revenuecat.com/blog/company/the-state-of-subscription-apps-2025-launch/&quot;&gt;learn more from the health and fitness app section in this year’s State of subscription apps report&lt;/a&gt;). They tap into strong habits and motivation cycles, and users are often willing to commit for longer periods if they believe the app will help them stay on track. Similarly how people are very hopeful when joining the gym, signing up for a year from the start.&lt;/p&gt;



&lt;p&gt;Initially, Leandro considered launching with both a free and premium tier. But time was running short, and Shipaton’s deadline required that the first version of the app be live on the App Store. After weighing the tradeoffs, he went with a 7-day free trial followed by a hard paywall.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“It wasn’t ideal, but I just needed to get it out there. I didn’t want to miss the deadline.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Setting up monetization with RevenueCat turned out to be surprisingly smooth. Despite never having used the SDK before,&amp;nbsp; Leandro got everything integrated quickly. The tougher part was dealing with App Store Connect.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“Apple rejected the app several times, and it was never super clear why. That was the most stressful part.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Still, he got it through and just in time. And while he didn’t go viral or hit the top charts, he managed to bring in a handful of paying users and earned around $100-200.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“It covered my Apple developer license. That already felt like a win.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-leandro-got-out-of-shipaton&quot;&gt;What Leandro Got Out of Shipaton&lt;/h2&gt;



&lt;p&gt;When asked to reflect on the experience, Leandro didn’t hesitate: the most valuable part of Shipaton was how much it pushed him to grow fast.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“I went from knowing nothing about shipping apps to actually having something live. That’s not something school ever really taught me.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;The confidence boost was real. Suddenly, building an app wasn’t a hypothetical. It had become something he had done. Doing it in public helped even more. Sharing updates on X connected him with other developers, helped him get unstuck when he hit roadblocks, and gave him feedback he could act on quickly.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“Before that, I felt kind of isolated as a dev. Shipaton made me feel like part of a community.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;In addition to connections and confidence to build apps from scratch, Shipaton had an even bigger impact waiting for him. “For me, Shipaton gave me the confidence to build my second app in such a short time, which led to being selected as a Distinguished Winner of the Swift Student Challenge 2025 and getting invited to WWDC25,” he says.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;768&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_3340-1024x768.jpeg&quot; alt=&quot;Leandro with Tim Apple at 2025 WWDC&quot; class=&quot;wp-image-44830&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_3340-1024x768.jpeg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_3340-300x225.jpeg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_3340-768x576.jpeg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_3340-1536x1152.jpeg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_3340-2048x1536.jpeg 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_3340-53x40.jpeg 53w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_3340-619x464.jpeg 619w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_3340-696x522.jpeg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_3340-560x420.jpeg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_3340-395x296.jpeg 395w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_3340-629x472.jpeg 629w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_3340-80x60.jpeg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/IMG_3340-48x36.jpeg 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-plans-for-this-year-s-shipaton&quot;&gt;Plans for This Year’s Shipaton&lt;/h2&gt;



&lt;p&gt;Leandro isn’t done with Shipaton. He’s planning to participate again this year, and his next app idea leans even harder into the fun side of fitness.&lt;/p&gt;



&lt;p&gt;The concept? An app that uses the Screen Time API to &lt;em&gt;force you to do push-ups before you can unlock your social media apps.&lt;/em&gt;&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“It started as a joke, like, wouldn’t it be funny if you had to earn your Instagram time? But the more I thought about it, the more I liked it.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;It’s playful but rooted in behavior change. The kind of idea that catches attention and makes people smile, but might also help them build healthier habits. He’s already started prototyping, and plans to share updates again as he builds.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“I’m probably not posting as obsessively as last year,” he says, smiling. “But I’ll definitely be building in public again.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-advice-for-shipaton-participants&quot;&gt;Advice for Shipaton Participants&lt;/h2&gt;



&lt;p&gt;We wrapped up by asking Leandro what advice he’d give to anyone thinking of joining Shipaton this year.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;To anyone who’s hesitant to join a hackathon because they’ve never built an app before or don’t feel ‘skilled enough’: just jump into it. You have nothing to lose, and you’ll be amazed by how much you can learn in such a short amount of time.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;He emphasized how welcoming the indie developer and iOS communities are, especially on X, and how much that helped him stay motivated. More than anything, he encouraged builders to be themselves.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“Don’t try to act like a company. Saying things like ‘&lt;/em&gt;&lt;strong&gt;&lt;em&gt;we&lt;/em&gt;&lt;/strong&gt;&lt;em&gt; are looking into it’, when it’s just you makes things sound very unauthentic.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;His final tip? Add a little surprise.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“Even just one small thing,&amp;nbsp; like a fun animation or an unexpected feature, can make your app more memorable and fun in the eyes of the user.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;want-to-build-your-own-story&quot;&gt;&lt;strong&gt;Want to build your own story?&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Shipaton 2025 is open. Build and launch a real app, integrate RevenueCat, and you could win up to $60K — or even end up in Times Square.&lt;/p&gt;



&lt;p&gt;👉 &lt;a class=&quot;&quot; href=&quot;https://www.shipaton.com/&quot;&gt;Join Shipaton&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Play Billing Library 8 support in Purchases SDK v9.0.0]]></title><description><![CDATA[Google Play Billing Library 8 introduces multiple purchase options for one-time products, non-expiring subscriptions, improved error handling, and removes support for querying expired subscriptions and consumed products.]]></description><link>https://www.revenuecat.com/blog/engineering/google-play-billing-v8/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/google-play-billing-v8/</guid><pubDate>Thu, 24 Jul 2025 04:23:43 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Announcing-RevenueCats-Purchases-SDK-v9.0.0.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Google recently announced the release of &lt;a href=&quot;https://developer.android.com/google/play/billing/release-notes#8-0-0&quot;&gt;Google Play Billing Library 8&lt;/a&gt;, introducing new offer capabilities such as multiple purchase options for one-time products and support for non-expiring subscriptions, and introduced new Kotlin extensions.&lt;/p&gt;



&lt;p&gt;In this article, we’ll walk through the key changes in Billing Library 8, what to keep in mind when migrating to the new RevenueCat SDK v9.0.0 for Android, Kotlin Multiplatform, Flutter, and React Native, and how to seamlessly integrate these updates into your project.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The RevenueCat iOS SDK is not affected by these Google Play Billing updates.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-s-new-in-google-play-billing-v8&quot;&gt;What’s new in Google Play Billing v8&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;566&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/whats-new-in-google-play-billing-library-8-1024x566.png&quot; alt=&quot;&quot; class=&quot;wp-image-45323&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/whats-new-in-google-play-billing-library-8-1024x566.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/whats-new-in-google-play-billing-library-8-300x166.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/whats-new-in-google-play-billing-library-8-768x424.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/whats-new-in-google-play-billing-library-8-1536x848.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/whats-new-in-google-play-billing-library-8-2048x1131.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/whats-new-in-google-play-billing-library-8-50x28.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/whats-new-in-google-play-billing-library-8-72x40.png 72w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/whats-new-in-google-play-billing-library-8-696x384.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/whats-new-in-google-play-billing-library-8-560x309.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/whats-new-in-google-play-billing-library-8-536x296.png 536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/whats-new-in-google-play-billing-library-8-840x464.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/whats-new-in-google-play-billing-library-8-80x44.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/whats-new-in-google-play-billing-library-8-48x27.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Version 8 of the Google Play Billing Library introduces a series of improvements aimed at simplifying product management and error handling for developers. The term “in-app items” has officially been replaced with &lt;strong&gt;“one-time products”&lt;/strong&gt;, which now support &lt;strong&gt;multiple purchase options and offers&lt;/strong&gt;, giving developers more flexibility when selling non-subscription items.&lt;/p&gt;



&lt;p&gt;A key change is the enhancement to queryProductDetailsAsync(), which now returns information about products that couldn’t be fetched, including a &lt;strong&gt;product-level status code&lt;/strong&gt;. This update also introduces a signature change in the onProductDetailsResponse() method, which requires adjustments to your implementation.&lt;/p&gt;



&lt;p&gt;BillingClient now supports &lt;strong&gt;automatic service reconnection&lt;/strong&gt;, eliminating the need to manually call startConnection() after disconnections. Additionally, launchBillingFlow() now includes &lt;strong&gt;sub-response codes&lt;/strong&gt; for specific error cases, such as PAYMENT_DECLINED_DUE_TO_INSUFFICIENT_FUNDS.&lt;/p&gt;



&lt;p&gt;As part of ongoing cleanup, several deprecated APIs have been officially removed in v8, including querySkuDetailsAsync(), queryPurchaseHistory(), and the older version of enablePendingPurchases().You can find the full list of updates in the&lt;a href=&quot;https://developer.android.com/google/play/billing/release-notes#8-0-0&quot;&gt; official release notes&lt;/a&gt;.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-you-need-to-know&quot;&gt;What you need to know&lt;/h2&gt;



&lt;p&gt;If you’re planning to migrate to RevenueCat SDK v9.0.0—whether you’re working with Android, Kotlin Multiplatform, Flutter, or React Native—and already using RevenueCat SDKs for in-app purchases, there’s no need to stress over every detail. We’ve designed the migration to handle most of the complexity for you.&lt;/p&gt;



&lt;p&gt;That said, it’s helpful to understand a few key concepts to ensure compatibility and a smooth integration. As part of the update, several deprecated APIs, such as those for querying expired subscriptions and consumed one-time products, have been removed. The release also introduces other important improvements and behavioral changes.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-play-billing-library-8-no-expired-subscriptions-or-consumed-one-time-products&quot;&gt;Play Billing library 8: No expired subscriptions or consumed one-time products&lt;/h2&gt;



&lt;p&gt;Play Billing Library 8 removes the ability to query expired subscriptions and consumed one-time products. For developers migrating from a non-RevenueCat implementation, this means the SDK will no longer be able to retrieve and send purchase data for those past transactions. However, this data can still be imported through a backend historical import, &lt;a href=&quot;https://www.revenuecat.com/docs/migrating-to-revenuecat/migrating-existing-subscriptions&quot;&gt;see the documentation for guidance&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;This change does not impact developers who already manage all transactions through RevenueCat SDK, which applies to the vast majority of users.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-using-the-sdk-with-your-own-iap-code-previously-observer-mode&quot;&gt;Using the SDK with your own IAP code (previously observer mode)&lt;/h2&gt;



&lt;p&gt;Using the SDK alongside your own in-app purchase (IAP) code is still fully supported in RevenueCat SDK v9.0.0. Other than updating the SDK version, no additional changes are required. Just ensure that you’re also using Play Billing Library version 8 or higher.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-migration-guides-for-sdk-v9-0-0&quot;&gt;Migration guides for SDK v9.0.0&lt;/h2&gt;



&lt;p&gt;You’ve seen what’s new in Google Play Billing v8 and the key considerations for upgrading to RevenueCat SDK v9.0.0. Now, let’s dive into the specific migration steps for each platform—Android, Kotlin Multiplatform, Flutter, and React Native—to help you transition smoothly.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;android&quot;&gt;Android&lt;/h3&gt;



&lt;p&gt;&lt;a href=&quot;https://github.com/RevenueCat/purchases-android/releases/tag/9.0.0&quot;&gt;RevenueCat Android SDK v9&lt;/a&gt; upgrades Kotlin to version 2.0.21 and sets the minimum supported Kotlin version to 1.8.0. If your project is using a Kotlin version below 1.8.0, this will be the most breaking change to address. Otherwise, if you’re already on Kotlin 1.8.0 or higher, no additional changes are needed and you can migrate to v9 seamlessly.&lt;/p&gt;



&lt;p&gt;At the time of writing, &lt;a href=&quot;https://github.com/RevenueCat/purchases-android/releases/tag/9.1.1&quot;&gt;version 9.1.1&lt;/a&gt; has already been released, so if possible, we recommend updating to the latest version to take advantage of the most recent improvements and fixes.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;kotlin-multiplatform&quot;&gt;Kotlin Multiplatform&lt;/h3&gt;



&lt;p&gt;&lt;a href=&quot;https://github.com/RevenueCat/purchases-kmp/releases/tag/2.0.0%2B15.0.0&quot;&gt;RevenueCat KMP SDK 2.0.0+15.0.0&lt;/a&gt; upgrades Kotlin to version 2.1.10, with a new minimum requirement of Kotlin 2.1.0 or higher. If you’re using an older Kotlin version, you’ll need to update it to proceed. Otherwise, if you’re already on Kotlin 2.1.0+, no further changes are necessary, and you can migrate to v9 without any issues.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;react-native&quot;&gt;React Native&lt;/h3&gt;



&lt;p&gt;&lt;a href=&quot;https://github.com/RevenueCat/react-native-purchases/releases/tag/9.0.0&quot;&gt;RevenueCat React Native SDK 9.0.0&lt;/a&gt; updates Kotlin to version 2.0.21, with a new minimum requirement of Kotlin 1.8.0 or higher. If your project is using an older Kotlin version, you’ll need to upgrade. However, if you’re already using Kotlin 1.8.0 or above, no additional changes are required and you can migrate to v9 smoothly.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;flutter&quot;&gt;Flutter&lt;/h3&gt;



&lt;p&gt;&lt;a href=&quot;https://github.com/RevenueCat/purchases-flutter/releases/tag/9.0.0&quot;&gt;RevenueCat Flutter SDK 9.0.0&lt;/a&gt; raises the minimum Flutter SDK to 3.22.0 and the minimum Dart SDK to 3.4.0. If your project is using an older version of Flutter or Dart, you’ll need to upgrade. Otherwise, if you’re already on these versions or higher, no additional changes are needed and you can migrate to v9 without any issues.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;



&lt;p&gt;In this article, you explored the key updates in Google Play Billing Library v8 and what to keep in mind when migrating to RevenueCat SDK v9.0.0 across each supported platform. Google typically announces a new version of the Play Billing Library each year—often around Google I/O—and keeping up with these changes across multiple platforms like Android and iOS can be a significant overhead in your engineering team.&lt;/p&gt;



&lt;p&gt;That’s where RevenueCat comes in. We handle the complexity of billing migrations, platform updates, and SDK compatibility, so you can focus on what truly matters, building and growing your app.&lt;/p&gt;



&lt;p&gt;As always, happy coding!&lt;br&gt;— &lt;a href=&quot;https://github.com/skydoves&quot;&gt;Jaewoong&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Introductory offers: a key lever for growth]]></title><description><![CDATA[Introductory offers drove a 433% conversion lift and cut CPA to $13]]></description><link>https://www.revenuecat.com/blog/growth/introductory-offers-apps/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/introductory-offers-apps/</guid><pubDate>Fri, 18 Jul 2025 08:58:08 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/introductory-offers-apps-1.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;I tried to create some hype &lt;a href=&quot;https://www.linkedin.com/posts/davidvargasmontiel_this-month-i-will-prepare-a-new-article-activity-7348255783429533700-uthJ?utm_source=share&amp;amp;utm_medium=member_desktop&amp;amp;rcm=ACoAAAzMmVgBUxDjift40fZ7QZBorscad_ESP2A&quot;&gt;last week on LinkedIn&lt;/a&gt; by teasing this article. It’s my most recent successful case study (I’m running it right now) and the first time I’m getting solid results with introductory offers. My silence since then is because I’ve been locked in, writing the best piece possible for this blog!&lt;/p&gt;



&lt;p&gt;With that explained, here are the questions we’ll answer today:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Are introductory offers really worth it?&lt;/li&gt;



&lt;li&gt;Do they negatively affect LTV?&lt;/li&gt;



&lt;li&gt;How can you measure or estimate the best offer to attract new subscribers to your app?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;These questions have popped into every subscription app marketer’s mind. Today I’ll give you a detailed guide on how to tackle them and how to navigate your tests.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-when-should-you-think-about-introducing-introductory-offers&quot;&gt;When should you think about introducing introductory offers?&lt;/h2&gt;



&lt;p&gt;This is the most basic question, because introductory offers are &lt;strong&gt;not helpful for every single business.&lt;/strong&gt; To give you a detailed answer, here’s some background on the recent case I’m talking about.&lt;/p&gt;



&lt;p&gt;I’ve been working with this client for a few months, trying to run app campaigns in a profitable way according to the LTV that RevenueCat was showing us. We tested all the main channels to see what CAC/CPA (customer-acquisition cost / cost per acquisition) we could get, and the problem was always the same: the conversion rate of our campaigns produced a CAC we couldn’t afford, given our LTV.&lt;/p&gt;



&lt;p&gt;In other words, we had two simple options: either improve the retention rate of the subscribers — or increase prices — so our LTV could grow, or improve the conversion rate of our campaigns to decrease the CPA.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-what-we-had-already-tried&quot;&gt;What we had already tried&lt;/h3&gt;



&lt;p&gt;We obviously tried to improve all three elements before giving up, and believe me, we tried absolutely everything you can imagine. Here’s a short summary of what we tested:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;200+ different creative angles to see if one converted better&lt;/li&gt;



&lt;li&gt;Different countries to target&lt;/li&gt;



&lt;li&gt;Different pricing in each subscription tier&lt;/li&gt;



&lt;li&gt;Different subscription tiers (weekly, monthly, yearly, quarterly, bi-weekly)&lt;/li&gt;



&lt;li&gt;Different free-trial durations&lt;/li&gt;



&lt;li&gt;Different optimization goals in our campaigns (installs, mid-funnel events, down-funnel events)&lt;/li&gt;



&lt;li&gt;Different channels (Google Ads, TikTok Ads, Meta Ads, Apple Ads, influencer marketing, ASO)&lt;/li&gt;



&lt;li&gt;10+ different paywalls&lt;/li&gt;



&lt;li&gt;Different onboardings&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;And… none of the above worked out. We worked on all these changes during the last six months and couldn’t reach breakeven in any reasonable period of time, keeping retention in mind.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-why-we-decided-to-test-offers&quot;&gt;Why we decided to test offers&lt;/h3&gt;



&lt;p&gt;Then I thought about how our conversion rate to purchase improved when we tested removing the free trial (a strategy &lt;a href=&quot;/blog/growth/should-your-app-stop-offering-free-trials/&quot;&gt;I already explained here with another client&lt;/a&gt;) and decided to go further with this approach. I really thought the app was better — or at least equal to — the baseline in the niche (I’ve worked with similar apps before).&lt;/p&gt;



&lt;p&gt;In this case, we thought that by introducing the introductory offer, we could improve the conversion rate from install to purchase and bring our CPA to a level that LTV in 60–90 days could support.&lt;/p&gt;



&lt;p&gt;We made this decision simply because it was the only thing we hadn’t tested. Decreasing subscription prices will 100% harm your LTV, and we were already struggling with the LTV/CPA balance, so the decision was obviously a bit risky.&lt;/p&gt;



&lt;p&gt;However, there was a good reason: &lt;strong&gt;we were launching a major update that included a key feature trending like crazy on social media, something no competitor had at that time.&lt;/strong&gt; We also redesigned the whole interface to make it more streamlined. With this context, we wanted to go bold; we wanted to be as aggressive as possible because we knew we had a unique opportunity to attract users from competitors just by offering something they couldn’t.&lt;/p&gt;



&lt;p&gt;So the answer to the first question doesn’t have a simple answer. It depends on a whole context of decisions and variables that determine whether you should test decreasing your prices significantly.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-the-experiment-we-launched&quot;&gt;The experiment we launched&lt;/h3&gt;



&lt;p&gt;Last but not least, here’s the exact subscription plan for this experiment. We moved from having one weekly subscription with a three-day free trial and one yearly subscription without a trial to three subscription tiers (weekly, monthly, yearly) with a reduction of:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;85% in the weekly subscription&lt;/li&gt;



&lt;li&gt;75% in the monthly subscription&lt;/li&gt;



&lt;li&gt;No reduction in the yearly → we simply increased the initial price by 66% so the “offer” price stayed at our original price. This was a small psychological trick: we put up a paywall where all original prices were greyed out and the new prices highlighted, creating the illusion of a good opportunity on the yearly subscription.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Apart from these pricing changes, we also decided to show the prices per day.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;The logic behind this pricing structure follows a reason.&lt;/strong&gt; From all the failed tests with subscription tiers, we realized weekly subscribers tended to have a higher LTV because retention and payment frequency were higher. So we decided to be more aggressive on this tier; making the pricing more attractive was key.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-what-we-learned-from-earlier-failures&quot;&gt;What we learned from earlier failures&lt;/h3&gt;



&lt;p&gt;On the other hand, we used that trick with the yearly strategy because we saw users who chose yearly didn’t care much about paying $40 or $60 (a test confirmed CVR stayed the same for both). We didn’t want to lose LTV just for the sake of an offer. Thanks to this learning, we made decisions with the offers later.&lt;/p&gt;



&lt;p&gt;The key takeaway: when you test anything in your app, &lt;strong&gt;you are not wasting money.&lt;/strong&gt; All the learnings we gathered during the last six months with these “fails” helped us build a well-founded strategy for this test. Next time you wonder whether to test something to improve performance, just go ahead. Best case you improve; worst case &lt;strong&gt;you learn something about your users.&lt;/strong&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-are-the-main-effects-when-you-apply-introductory-offers&quot;&gt;What are the main effects when you apply introductory offers?&lt;/h2&gt;



&lt;p&gt;I already hinted at the first effect, but since I like showing real data, it’s better if I explain what we saw when we implemented the introductory offers.&lt;/p&gt;



&lt;p&gt;Let’s start with the conversion to paying from new users:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1890&quot; height=&quot;1226&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/conversion-to-paying-new-users-1.png&quot; alt=&quot;&quot; class=&quot;wp-image-44772&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/conversion-to-paying-new-users-1.png 1890w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/conversion-to-paying-new-users-1-300x195.png 300w&quot; sizes=&quot;auto, (max-width: 1890px) 100vw, 1890px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The most obvious effect you should see after implementing an introductory offer is the conversion to paying subscribers. In our case, as I mentioned, we had already tried removing free trials and going directly to subscriptions (that’s why you see a peak in November), but that conversion wasn’t high enough to cover the CPA at that time.&lt;/p&gt;



&lt;p&gt;However, after introducing the offers on 5 June, we saw an increase of &lt;strong&gt;433%&lt;/strong&gt; in CVR when looking at the highest peak compared to the average 3% we usually had with free trials. Seeing this was the first signal that we were heading in the right direction. With such a high CVR, &lt;strong&gt;our CPA started to decrease&lt;/strong&gt; to levels we’d never seen.&lt;/p&gt;



&lt;p&gt;To show that with data, here’s our CPA based on SKAN during June versus the cost we had back in November when we didn’t have the offer:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;CPA (SKAN) November 2024 (paywall: 3 tiers, monthly and yearly, &lt;strong&gt;no&lt;/strong&gt; trial): &lt;strong&gt;$105&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;CPA (SKAN) June 2025 (paywall: weekly, monthly, yearly, &lt;strong&gt;no&lt;/strong&gt; trial, introductory offers): &lt;strong&gt;$13&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;Difference: &lt;strong&gt;-86%&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Huge, right? A big drop in cost per paying subscriber, and the main reason we generated many more subscribers &lt;strong&gt;using the same budget as in November.&lt;/strong&gt; Check the next screenshots to see that:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;912&quot; height=&quot;404&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/image4.png&quot; alt=&quot;&quot; class=&quot;wp-image-44752&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/image4.png 912w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/image4-300x133.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/image4-768x340.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/image4-90x40.png 90w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/image4-696x308.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/image4-560x248.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/image4-840x372.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/image4-80x35.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/image4-48x21.png 48w&quot; sizes=&quot;auto, (max-width: 912px) 100vw, 912px&quot;&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1298&quot; height=&quot;595&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/active-subscriptions-over-time.png&quot; alt=&quot;&quot; class=&quot;wp-image-44756&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/active-subscriptions-over-time.png 1298w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/active-subscriptions-over-time-300x138.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/active-subscriptions-over-time-1024x469.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/active-subscriptions-over-time-768x352.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/active-subscriptions-over-time-87x40.png 87w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/active-subscriptions-over-time-696x319.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/active-subscriptions-over-time-560x257.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/active-subscriptions-over-time-840x385.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/active-subscriptions-over-time-80x37.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/active-subscriptions-over-time-48x22.png 48w&quot; sizes=&quot;auto, (max-width: 1298px) 100vw, 1298px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;We were seeing a huge change, a completely different story, and it was also affecting our MRR, a metric we’d never pushed above $50k with previous experiments:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1884&quot; height=&quot;1194&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/mrr-over-time.png&quot; alt=&quot;&quot; class=&quot;wp-image-44758&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/mrr-over-time.png 1884w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/mrr-over-time-300x190.png 300w&quot; sizes=&quot;auto, (max-width: 1884px) 100vw, 1884px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;That line goes quite up in a very short period of time, doesn’t it? We were so happy to see these trends going up in all directions and, I’m not going to lie, I felt like we’d discovered a gold mine. But there was a factor which was clearly affecting all these graphs. &lt;/p&gt;



&lt;p&gt;The extremely low CPA was caused not only by the introductory offers but also because we were the only app in the niche offering a unique feature and promoting it with a &lt;strong&gt;huge&lt;/strong&gt; trend on social media, which gave us crazy conversion rates on all the TikTok videos (yes, all this magic happened on TikTok Ads).&lt;/p&gt;



&lt;p&gt;So we knew this was a bubble that could burst if the TikTok trend faded or competitors launched the same feature at a better price. That’s why we move now to the third section.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-monitoring-and-adjusting-your-introductory-offers&quot;&gt;Monitoring and adjusting your introductory offers&lt;/h2&gt;



&lt;p&gt;With all the context given, we have a couple of questions left. Our CPA was extremely low due to a seasonal factor (a trend on social media) and a differential factor (unique feature).&lt;/p&gt;



&lt;p&gt;The next question: &lt;strong&gt;was the super-low cost per new subscriber enough to cover the drop in LTV?&lt;/strong&gt; Because, yes, if you start your first subscription with an 85% reduction in your most popular tier, you’ll decrease LTV.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1900&quot; height=&quot;1180&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/ltv-30-days-1.png&quot; alt=&quot;&quot; class=&quot;wp-image-44770&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/ltv-30-days-1.png 1900w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/ltv-30-days-1-300x186.png 300w&quot; sizes=&quot;auto, (max-width: 1900px) 100vw, 1900px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;This is what happened. Comparing LTV-30 in November (no trials) vs. June: &lt;strong&gt;we dropped from $55 to $10 (-81%).&lt;/strong&gt; The decline matches the average price reduction (about 80% between weekly and monthly).&lt;/p&gt;



&lt;p&gt;The declining trend in April and May was due to another experiment (where we aggressively boosted installs to spark organic traffic). The key is &lt;strong&gt;what happened in June.&lt;/strong&gt; The cohort is still immature, but it’s clear our LTV will drop at least 70% versus the $38 average we had October–March.&lt;/p&gt;



&lt;p&gt;Our average CPA this month was $13, so we were obviously &lt;strong&gt;not&lt;/strong&gt; covering CPA, but we were close.&lt;/p&gt;



&lt;p&gt;The next step was to measure the proportion of our subscriptions:&lt;/p&gt;



&lt;p&gt;&lt;a class=&quot;&quot; href=&quot;https://lh7-rt.googleusercontent.com/docsz/AD_4nXdXBxyLRrMzA7zm5U9NNQYQWkizwmIpnlDjeyIWMmBTigsGOijBREeea81qK_7CbbAkZ5KKBw7uEo9ENk2Isvr5j_MvgToM25j2k-kQpCsU1sIfYpjHJVD226DRQg-nYoNJrq9q?key=3wnhCz_cL8QDBYDJ_D03KA&quot;&gt;&lt;/a&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;659&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/new-paid-subscriptions-1024x659.png&quot; alt=&quot;&quot; class=&quot;wp-image-44762&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/new-paid-subscriptions-1024x659.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/new-paid-subscriptions-300x193.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/new-paid-subscriptions-768x494.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/new-paid-subscriptions.png 1856w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;In order, and by colors, you have:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Weekly offer (green)&lt;/li&gt;



&lt;li&gt;Monthly offer (blue)&lt;/li&gt;



&lt;li&gt;Yearly offer (orange)&lt;/li&gt;



&lt;li&gt;Special yearly offer (red) → shown when users closed the onboarding or the paywall a few times&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;We started with a &lt;strong&gt;huge&lt;/strong&gt; number of weekly subscriptions and a much lower number of monthly and yearly subs, and we were expecting this because, looking at the paywall, the weekly offer was much more attractive due to the higher reduction in price.&lt;/p&gt;



&lt;p&gt;At this point you have two options:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Wait&lt;/strong&gt; and see how these weekly and monthly subscriptions keep paying after the introductory offer ends. In this case, you should also expect much lower retention than usual when using an introductory offer, because there are many users who just want to try your app and pay the minimum. For example, in our case, our weekly retention was above 50% in the first renewal back when we had the free trial with the weekly subscription, but in June only 40% paid the full price for the first time. This number keeps declining with the next renewals as well.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Change&lt;/strong&gt; the distribution of your subscriptions so you can increase the LTV in a short time frame to support that LTV.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;And this was the direction we took. We didn’t want to wait 90 or 180 days to see if we were covering the investment; we needed to ensure a positive projected ROI in 60 days or less, because we knew the trend could end quickly. So we &lt;strong&gt;started to play with the pricing again, and this is what happened with our LTV in seven days:&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;474&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/realized-ltv-per-paying-customer-1024x474.png&quot; alt=&quot;&quot; class=&quot;wp-image-44764&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/realized-ltv-per-paying-customer-1024x474.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/realized-ltv-per-paying-customer-300x139.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/realized-ltv-per-paying-customer-768x355.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/realized-ltv-per-paying-customer-86x40.png 86w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/realized-ltv-per-paying-customer-696x322.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/realized-ltv-per-paying-customer-560x259.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/realized-ltv-per-paying-customer-840x389.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/realized-ltv-per-paying-customer-80x37.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/realized-ltv-per-paying-customer-48x22.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/realized-ltv-per-paying-customer.png 1336w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;On 26 June, we decided to increase both the weekly and monthly introductory prices to make the yearly more attractive (remember that the yearly didn’t have any real discount), so users would see a paywall where, despite the reductions on weekly and monthly tiers, &lt;strong&gt;the price per day of the yearly was still lower.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;That quickly changed the distribution of our subscriptions, as well as the trend of our conversion rate shown in the previous screenshot, but also marked here again:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;459&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/conversion-to-paying-change-1024x459.png&quot; alt=&quot;&quot; class=&quot;wp-image-44766&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/conversion-to-paying-change-1024x459.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/conversion-to-paying-change-300x134.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/conversion-to-paying-change-768x344.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/conversion-to-paying-change-89x40.png 89w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/conversion-to-paying-change-696x312.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/conversion-to-paying-change-560x251.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/conversion-to-paying-change-840x376.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/conversion-to-paying-change-80x36.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/conversion-to-paying-change-48x21.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/conversion-to-paying-change.png 1324w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;That drop in the conversion rate was not because the campaigns started to convert worse. It happened because we decided to change the price of the offers, and that directly affected the distribution and the conversion rate.&lt;/p&gt;



&lt;p&gt;This decision also affected the CPA, of course, but the outcome was positive:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Conversion rate was still quite high (average 12%).&lt;/li&gt;



&lt;li&gt;CPA increased to $17.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Our LTV-D7 is now going up steadily, even with immature cohorts&lt;/strong&gt;, and that’s the biggest difference. During the last seven days (I am writing this on 17 July), our average CPA is $17.35 and our LTV-D7 is $14.27, so we are covering &lt;strong&gt;82%&lt;/strong&gt; of the cost in just seven days. We are sure we will eventually cover the investment in 60 days or less.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Our main goal now is to closely monitor that our CPA stays under control so we can keep this profitability over time while we start to scale our paid campaigns to a level that we could never achieve.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-conclusion&quot;&gt;Conclusion&lt;/h2&gt;



&lt;p&gt;Now that we’ve seen the data, let’s revisit those questions posed in the introduction:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Are introductory offers really worth it? &lt;strong&gt;Yes, &lt;em&gt;if&lt;/em&gt; the context is right.&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;Do they negatively affect LTV? &lt;strong&gt;Yes, but that doesn’t mean you can’t grow.&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;How can you measure or estimate the best offer to attract new subscribers to your app? &lt;strong&gt;Depending on the goals of your business, you will have to make some decisions while you run introductory offers. Measuring the balance between CAC and LTV is key and RevenueCat gives you the tools to do this job efficiently.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;I hope you enjoyed this article. I put all of my effort into giving you the whole context of all the decisions we made because in my opinion, &lt;strong&gt;it is the most essential part of this whole case study.&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Everything we tested, all the learnings we gathered through the journey, were in this case a key component in creating a successful growth framework at the end. This is what you can achieve if you keep persisting and iterating. This is what defines a successful story.&lt;/p&gt;



&lt;p&gt;Don’t stop fighting with your managers/CEOs/CMOs — whoever you have to deal with — to test new things. You will never know what works and what doesn’t until you test.&lt;/p&gt;



&lt;p&gt;I will finish this article by paraphrasing Confucius:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;“He who tests a new hypothesis is a fool for a minute; &lt;br&gt;he who does not test is a fool for life”&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded></item><item><title><![CDATA[Weekly subscriptions: when do seven-day plans make sense?]]></title><description><![CDATA[A deep dive into the value and usage of weekly subscriptions]]></description><link>https://www.revenuecat.com/blog/growth/weekly-subscriptions/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/weekly-subscriptions/</guid><pubDate>Thu, 17 Jul 2025 09:38:22 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscriptions.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;The &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps-2025/#:~:text=Subscriptions%20aren%27t%20enough%20anymore,%25)%20are%20leading%20the%20charge.&amp;amp;text=Churn%20hits%20hard%20and%20fast,canceled%20in%20the%20first%20month.&quot;&gt;2025 State of Subscription Apps report&lt;/a&gt; was full of stats that intrigued me, but one that I just couldn’t let go of was weekly subscriptions.&lt;/p&gt;



&lt;p&gt;I’ve never had a weekly subscription myself, yet in gaming, a staggering 77% of users were on weekly plans. And it turns out that gaming isn’t the only one:&amp;nbsp;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Business (44.7%)&lt;/li&gt;



&lt;li&gt;Social and Lifestyle (40.9%)&lt;/li&gt;



&lt;li&gt;Photo &amp;amp; Video (38.8%)&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Utilities (36.1%)&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Most categories report a high proportion of weekly subscriptions. The only ones that didn’t seem as popular were:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Education (5.3%)&lt;/li&gt;



&lt;li&gt;Health &amp;amp; Fitness (4.5%)&lt;/li&gt;



&lt;li&gt;Travel (5.3%)&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;That got me thinking: when do weekly subscriptions actually make sense, and should more apps be testing them?&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;557&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscriptions-by-category-2025-1024x557.png&quot; alt=&quot;SOSA 2025: How the uptake of weekly subscriptions varies per category&quot; class=&quot;wp-image-44729&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscriptions-by-category-2025-1024x557.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscriptions-by-category-2025-300x163.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscriptions-by-category-2025-768x418.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscriptions-by-category-2025-1536x836.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscriptions-by-category-2025-73x40.png 73w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscriptions-by-category-2025-696x379.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscriptions-by-category-2025-560x305.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscriptions-by-category-2025-544x296.png 544w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscriptions-by-category-2025-840x457.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscriptions-by-category-2025-80x44.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscriptions-by-category-2025-48x26.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscriptions-by-category-2025.png 1999w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;SOSA 2025: How the uptake of weekly subscriptions varies per category&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;Being a naturally curious person (read: &lt;em&gt;nosy&lt;/em&gt;), I wanted to understand &lt;em&gt;why&lt;/em&gt; this model has become so popular. Interestingly, it appears to be slightly more prevalent in regions such as India and Southeast Asia (36.4%), the Middle East (34.6%), and Latin America (31.3%).&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;531&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscriptions-by-region-2025-1024x531.png&quot; alt=&quot;SOSA 2025: How the uptake of weekly subscriptions varies per region of the world&quot; class=&quot;wp-image-44731&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscriptions-by-region-2025-1024x531.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscriptions-by-region-2025-300x156.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscriptions-by-region-2025-768x398.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscriptions-by-region-2025-1536x797.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscriptions-by-region-2025-77x40.png 77w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscriptions-by-region-2025-696x361.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscriptions-by-region-2025-560x291.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscriptions-by-region-2025-840x436.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscriptions-by-region-2025-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscriptions-by-region-2025-48x25.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscriptions-by-region-2025.png 1999w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;SOSA 2025: How the uptake of weekly subscriptions varies per region of the world&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;So I dove into the data to understand &lt;em&gt;when&lt;/em&gt; and &lt;em&gt;why&lt;/em&gt; apps offer weekly subscriptions, so you can decide whether it’s worth testing for your own product. There isn’t a lot of research available on weekly subscriptions, so I compiled what insights I could find and spoke with a few experts in the space to fill in the gaps.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-are-weekly-subscriptions-so-popular-in-certain-categories&quot;&gt;Why are weekly subscriptions so popular in certain categories?&lt;/h2&gt;



&lt;p&gt;There appear to be three main drivers (potentially four) behind weekly subscriptions; the first being short-term usage.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-short-term-usage&quot;&gt;1. Short-term usage&lt;/h3&gt;



&lt;p&gt;Why subscribe to an app if you only plan to use it for the short term? You could, in that case, choose not to offer a subscription at all, but one-off payments often end up more expensive for the user and less valuable for the app maker. Not only that, but the duration of that short-term usage can also vary. For example, let’s say you need to edit some photos. This could be a one-time round of edits, but it could also be a project that lasts a few weeks.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://flighty.com/&quot;&gt;Flighty&lt;/a&gt;, a flight tracking app, offers subscriptions for weekly, monthly, annual, and lifetime plans. By offering weekly subscriptions, they can &lt;a href=&quot;https://www.going.com/guides/flighty-review&quot;&gt;reach an audience of infrequent users&lt;/a&gt; who want to use their service but only need it for a limited time.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;703&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/flighty-subscription-options-1-1024x703.png&quot; alt=&quot;&quot; class=&quot;wp-image-44733&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/flighty-subscription-options-1-1024x703.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/flighty-subscription-options-1-300x206.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/flighty-subscription-options-1-768x527.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/flighty-subscription-options-1-1536x1054.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/flighty-subscription-options-1-58x40.png 58w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/flighty-subscription-options-1-676x464.png 676w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/flighty-subscription-options-1-696x478.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/flighty-subscription-options-1-560x384.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/flighty-subscription-options-1-431x296.png 431w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/flighty-subscription-options-1-688x472.png 688w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/flighty-subscription-options-1-80x55.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/flighty-subscription-options-1-48x33.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/flighty-subscription-options-1.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Subscription options for Flighty&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;Interestingly, it costs almost the same per week as it does for a month with the annual subscription. Users are willing to pay quite a bit more when they won’t need your app as long. When offering this to different audiences, it’s essential to clarify who each subscription is intended for. For example, Flighty clearly states that the weekly plan is for less frequent flyers and also excludes features that they probably won’t need from the plan.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Another interesting example is dating apps. Almost everyone has been there, swiping away in the hopes of finding love. But once you match with someone you want to date exclusively, the first thing you’ll want is to cancel your subscription. If this happens at the start of the month, though, you’re stuck paying for the rest of the month without being able to use the app. A lot can happen to a relationship in a month, less so in a week.&lt;/p&gt;



&lt;p&gt;Finally, seasonality is another important consideration I learned from speaking with &lt;a href=&quot;https://www.linkedin.com/in/hannagrevelius/&quot;&gt;Hanna Greveilus&lt;/a&gt;, CPO of &lt;a href=&quot;https://golfgamebook.com/&quot;&gt;Golf Gamebook&lt;/a&gt;, who has extensive experience working with apps that offer weekly subscriptions.&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“Weekly subscriptions can make sense for hobby-based or highly seasonal products, especially those where peak engagement happens over the weekend. Unlike utility apps (think: timers, calendars, to-do lists) where daily use is natural and DAU is a solid metric, hobby-driven apps often see a sharp spike in WAU, with weekends being the clear prime time.&amp;nbsp;&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;&lt;em&gt;Layer on seasonality—like sports or activities that only happen in specific weather (skiing in winter, fishing or golf in summer)—and it’s easy to convince yourself that a weekly subscription aligns perfectly with user behavior.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;This is where the overview of the categories falls a bit short. Something like skiing or fishing may fall under Health &amp;amp; Fitness, but would actually work with a weekly subscription.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-commitment-phobe&quot;&gt;2. Commitment phobe&lt;/h3&gt;



&lt;p&gt;This brings us to the second reason, which is very fitting for dating apps: commitment phobia. &lt;a href=&quot;https://www.pymnts.com/earnings/2023/tinder-taps-short-term-subscriptions-to-tackle-gen-zs-commitment-phobia/&quot;&gt;Tinder found that Gen Z users&lt;/a&gt; didn’t want to commit and often preferred a weekly subscription. So it could also be that certain generations prefer weekly subscriptions. The irony? Tinder increased revenue by playing into that fear of commitment by offering shorter subscriptions.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;985&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/tinder-plus-weekly-pricing-1-985x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-44735&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/tinder-plus-weekly-pricing-1-985x1024.png 985w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/tinder-plus-weekly-pricing-1-289x300.png 289w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/tinder-plus-weekly-pricing-1-768x798.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/tinder-plus-weekly-pricing-1-1478x1536.png 1478w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/tinder-plus-weekly-pricing-1-38x40.png 38w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/tinder-plus-weekly-pricing-1-446x464.png 446w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/tinder-plus-weekly-pricing-1-696x723.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/tinder-plus-weekly-pricing-1-539x560.png 539w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/tinder-plus-weekly-pricing-1-285x296.png 285w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/tinder-plus-weekly-pricing-1-454x472.png 454w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/tinder-plus-weekly-pricing-1-77x80.png 77w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/tinder-plus-weekly-pricing-1-46x48.png 46w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/tinder-plus-weekly-pricing-1.png 1831w&quot; sizes=&quot;auto, (max-width: 985px) 100vw, 985px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Tinder Plus’ weekly pricing&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;Here, the difference isn’t as significant because the monthly alternative still offers flexibility, but you still save 52% on a monthly subscription. Overall, when we compare pricing for weekly vs monthly and annual subscriptions, we see the following trend:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;984&quot; height=&quot;485&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/plan-pricing.png&quot; alt=&quot;&quot; class=&quot;wp-image-44737&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/plan-pricing.png 984w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/plan-pricing-300x148.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/plan-pricing-768x379.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/plan-pricing-81x40.png 81w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/plan-pricing-696x343.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/plan-pricing-560x276.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/plan-pricing-840x414.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/plan-pricing-80x39.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/plan-pricing-48x24.png 48w&quot; sizes=&quot;auto, (max-width: 984px) 100vw, 984px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;The medium weekly price is $4.99, compared to $6.68 for monthly. If we work it out per month (with 4.33 weeks in a month), weekly users are, on average, paying 3.23 times more than monthly users.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-try-before-you-buy&quot;&gt;3. Try before you buy&lt;/h3&gt;



&lt;p&gt;Some apps also use a weekly plan as a trial, which is what we see with &lt;a href=&quot;https://www.google.com/aclk?sa=l&amp;amp;ai=DChcSEwjktfzpudeMAxVWiFAGHb8fFvAYABAAGgJkZw&amp;amp;co=1&amp;amp;gclid=CjwKCAjw5PK_BhBBEiwAL7GTPZw3dyvtqh1i75AslT-vBg_cs5XfXz8w9nIR0ysi5bUCunKATuJlHxoCbAYQAvD_BwE&amp;amp;sig=AOD64_3qynjl0VTTbz3iFd4d01aD2NBZvQ&amp;amp;q&amp;amp;adurl&amp;amp;ved=2ahUKEwiE3fbpudeMAxVaUkEAHUGXEpEQ0Qx6BAgFEAE&quot;&gt;Woofz&lt;/a&gt;, a dog training app:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;947&quot; height=&quot;522&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Woofz-pricing-options.png&quot; alt=&quot;Woofz pricing options&quot; class=&quot;wp-image-44739&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Woofz-pricing-options.png 947w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Woofz-pricing-options-300x165.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Woofz-pricing-options-768x423.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Woofz-pricing-options-73x40.png 73w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Woofz-pricing-options-696x384.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Woofz-pricing-options-560x309.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Woofz-pricing-options-537x296.png 537w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Woofz-pricing-options-840x463.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Woofz-pricing-options-80x44.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Woofz-pricing-options-48x26.png 48w&quot; sizes=&quot;auto, (max-width: 947px) 100vw, 947px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Woofz pricing options&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;Interestingly, they call it a 7-day plan, not even a week, and highlight it as the most popular. As a dog owner, I can almost guarantee that even with dedication, your dog won’t be fully trained after a week. Is this their way of getting people to try out the app without offering a free trial?&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-4-more-accessible-payments&quot;&gt;4. More accessible payments&lt;/h3&gt;



&lt;p&gt;While I couldn’t find any concrete data on it, I imagine a fourth reason could be making payments more accessible to lower-income groups. In the UK, we’re accustomed to being paid monthly, with payday being a real event at the end of the month. However, not every country or role follows that pattern. For those paid weekly or bi-weekly, a weekly subscription model could be more accessible.&lt;/p&gt;



&lt;p&gt;Even if it’s not due to budget constraints, there is a certain affordability around a weekly payment, as &lt;a href=&quot;https://www.linkedin.com/in/hnpvz/&quot;&gt;Hannah Parvaz&lt;/a&gt;, founder of &lt;a href=&quot;https://www.aperture.london/&quot;&gt;Aperture&lt;/a&gt;, shares:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“The main thing is the anchoring element: £3.99 a week feels less expensive than £9.99/month, even though it adds up to more quite quickly. Especially when someone is looking for the result of a long onboarding flow, this small price feels like a tiny hurdle to pay to get their result, or to do their immediate task, like measuring something with a utility app – especially when it’s combined with “cancel anytime” messaging.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;So it can make the price feel more accessible to the user, even if in reality it’s higher.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-are-the-advantages-of-weekly-subscriptions&quot;&gt;What are the advantages of weekly subscriptions?&lt;/h2&gt;



&lt;p&gt;Weekly subscriptions can help you tap into a new target audience, as seen with Flighty. Infrequent fliers were unlikely to commit to a month-long subscription, but they appreciated having the option to pay weekly.&lt;/p&gt;



&lt;p&gt;It may not always be a completely new audience, but rather a subset of your existing users with a shorter-term use case.&lt;/p&gt;



&lt;p&gt;As we discussed earlier, weekly subscriptions also lower the barrier to entry, making it easier for users to try out the service. For those looking to move beyond a free trial, a weekly option could be a great alternative.&lt;/p&gt;



&lt;p&gt;Finally, you can charge more on a weekly basis compared to monthly subscriptions. Despite the higher cost, users still opt for weekly subscriptions, likely due to:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Control / Fear of commitment &lt;/strong&gt;– Ability to cancel each week if financial situation changes&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Mental accounting &lt;/strong&gt;– Smaller payments feel more accessible. This is the rhetoric I’ve taken for my wedding budget: look at the individual costs, not the whole budget (far less painful)&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Loss aversion &lt;/strong&gt;– A fear of wasting money on something you won’t use&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-are-the-disadvantages-of-weekly-subscriptions&quot;&gt;What are the disadvantages of weekly subscriptions?&lt;/h2&gt;



&lt;p&gt;The last thing you want is for users to make the most of their weekly subscription and then leave after a week. If this is a potential issue with your app, you’ll need to assess whether the weekly subscription is adding value or detracting from the overall user experience.&lt;/p&gt;



&lt;p&gt;Another risk is that if the weekly option cannibalizes your monthly subscribers too much, it could negatively impact your Lifetime Value (LTV) and retention. As seen in the SOSA 2025 report, weekly users tend to have lower retention over the course of six months:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;556&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/SOSA-25-Weekly-vs-monthly-retention-rates-1024x556.png&quot; alt=&quot;SOSA 25: Weekly vs monthly retention rates&quot; class=&quot;wp-image-44741&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/SOSA-25-Weekly-vs-monthly-retention-rates-1024x556.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/SOSA-25-Weekly-vs-monthly-retention-rates-300x163.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/SOSA-25-Weekly-vs-monthly-retention-rates-768x417.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/SOSA-25-Weekly-vs-monthly-retention-rates-74x40.png 74w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/SOSA-25-Weekly-vs-monthly-retention-rates-696x378.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/SOSA-25-Weekly-vs-monthly-retention-rates-560x304.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/SOSA-25-Weekly-vs-monthly-retention-rates-545x296.png 545w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/SOSA-25-Weekly-vs-monthly-retention-rates-840x456.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/SOSA-25-Weekly-vs-monthly-retention-rates-80x43.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/SOSA-25-Weekly-vs-monthly-retention-rates-48x26.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/SOSA-25-Weekly-vs-monthly-retention-rates.png 1114w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;SOSA 25: Weekly vs monthly retention rates&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;Sure, a few monthly users may switch to weekly, as I mentioned in the dating example. However, the last thing you want is for so many users to switch and stay for shorter periods, ultimately lowering your overall revenue.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;While you could argue whether this decline is due to the weekly subscription option itself or the overall value you’re providing, the data suggests that retention tends to decline for weekly subscriptions across the board:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;884&quot; height=&quot;465&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/SOSA-25-Retention-rates-after-a-year-for-2024-vs-2025.png&quot; alt=&quot;SOSA 25: Retention rates after a year for 2024 vs 2025&quot; class=&quot;wp-image-44743&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/SOSA-25-Retention-rates-after-a-year-for-2024-vs-2025.png 884w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/SOSA-25-Retention-rates-after-a-year-for-2024-vs-2025-300x158.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/SOSA-25-Retention-rates-after-a-year-for-2024-vs-2025-768x404.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/SOSA-25-Retention-rates-after-a-year-for-2024-vs-2025-76x40.png 76w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/SOSA-25-Retention-rates-after-a-year-for-2024-vs-2025-696x366.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/SOSA-25-Retention-rates-after-a-year-for-2024-vs-2025-560x296.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/SOSA-25-Retention-rates-after-a-year-for-2024-vs-2025-840x442.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/SOSA-25-Retention-rates-after-a-year-for-2024-vs-2025-80x42.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/SOSA-25-Retention-rates-after-a-year-for-2024-vs-2025-48x25.png 48w&quot; sizes=&quot;auto, (max-width: 884px) 100vw, 884px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;SOSA 25: Retention rates after a year for 2024 vs 2025&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;In 2024, on average, 4.2% of weekly subscribers were retained after a year. However, in 2025, that dropped to 3.4%. Hanna Greveilus has experienced this firsthand:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“The challenge with weekly subscriptions? It can look great at first. A weekly plan often boosts conversion rates and gives users a lower barrier to entry. But if you don’t carefully model the long-term impact on LTV, it can become a revenue trap. We’ve seen early metrics look promising, only to realize that the cannibalization of longer-term plans led to a significant hit on overall revenue.&lt;/em&gt; &lt;/p&gt;



&lt;p&gt;&lt;em&gt;So yes, weekly plans can be useful—especially as part of a broader pricing strategy or in specific seasonal windows—but they need to be approached with eyes wide open and a solid LTV model in place.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Now this is a bit of a math game. Weekly users are paying, on average, 3.23 times more than monthly, so that difference needs to be significant in retention for it to make sense. It also needs to be a case that you would have kept the users on a monthly subscription otherwise. While retention is worse, as we saw with Flighty and Tinder, some groups might not have subscribed to the monthly option. Better to get them for a week than not at all, right?&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Finally, there are also certain cases where it doesn’t make sense to offer weekly. If value comes from long-term usage, it may even be more valuable to only offer annual plans and remove monthly and weekly options.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-do-you-know-if-you-should-add-or-remove-weekly-plans&quot;&gt;How do you know if you should add or remove weekly plans?&lt;/h2&gt;



&lt;p&gt;If you’re considering whether weekly subscriptions are right for you, I’d recommend walking through the following questions first:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-do-weekly-subscriptions-make-sense-for-your-category-nbsp&quot;&gt;&lt;strong&gt;1. Do weekly subscriptions make sense for your category?&amp;nbsp;&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Consider where your audience is and what’s common in your category. Based on the data, are weekly subscriptions popular in your space? If the answer is yes, move on to question 2.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-does-it-make-sense-for-your-use-case-nbsp&quot;&gt;&lt;strong&gt;2. Does it make sense for your use case?&amp;nbsp;&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;There’s a reason weekly subscriptions are less prevalent in certain categories: they’re typically better suited for apps that users engage with more frequently and for shorter periods. Even if you’re in a category where weekly subscriptions are common, take a step back and assess if this model aligns with your app’s use case. &lt;a href=&quot;https://www.linkedin.com/in/nathan--hudson/&quot;&gt;Nathan Hudson&lt;/a&gt;, founder of &lt;a href=&quot;https://www.perceptycs.com/&quot;&gt;Perceptycs&lt;/a&gt;, shares:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“In my experience, weekly subscriptions tend to lend themselves to products where both the developer and customer recognise there’s a pretty slim chance of long term retention. So for products whose core value is innately tied to commitment and long term usage, weekly plans often aren’t a great bet. Unless users are just ‘giving it a go’.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-are-you-willing-to-potentially-remove-or-not-offer-a-weekly-trial-nbsp&quot;&gt;&lt;strong&gt;3. Are you willing to potentially remove or not offer a weekly trial?&amp;nbsp;&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Weekly trials and subscriptions can be a tricky mix if you also offer monthly and annual options—it can get confusing for users. If you offer a weekly subscription, it can essentially function as a trial, but you’ll need a clear upsell strategy in place.&lt;/p&gt;



&lt;p&gt;If users are engaging with your app during a trial but not converting to a paid plan, it could signal short-term usage, suggesting that a weekly subscription might be a better fit. Alternatively, for short-term usage apps, consider offering a weekly option with a trial, but without a six-month or annual plan. &lt;a href=&quot;https://apphud.com/blog/experiments-case-study&quot;&gt;A/B testing&lt;/a&gt; by &lt;a href=&quot;https://apps.apple.com/us/app/information-solution/id1635037894&quot;&gt;Information Solution&lt;/a&gt;, a PDF scanner app, showed higher ARPU for users who tried a weekly subscription with a trial compared to just weekly or monthly plans.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-4-will-it-target-a-different-audience-or-use-case-than-monthly-users-nbsp&quot;&gt;&lt;strong&gt;4. Will it target a different audience or use case than monthly users?&amp;nbsp;&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Whether it’s shorter-term usage or a different audience (like those hesitant to commit long-term), ideally, you don’t want to target the same group as your monthly subscribers.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Weekly plans are popular for a reason, but they should align with a different use case or user profile. As Flighty demonstrates, clearly communicate how the weekly plan differs from monthly or annual options in your plan overview.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-5-will-your-cac-support-a-weekly-plan&quot;&gt;&lt;strong&gt;5. Will your CAC support a weekly plan?&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;If your retention for weekly subscriptions is likely to be lower than for monthly plans, can you justify the cost of acquiring weekly users? One solution could be to optimize your acquisition campaigns for monthly or annual users, treating weekly users as ‘extra’ rather than risking damage to your LTV/CAC ratio.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-testing-roadmap&quot;&gt;Testing roadmap&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;804&quot; height=&quot;643&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscription-flow-chart.png&quot; alt=&quot;Should we implement a weekly subscription option? This flow chart will help you decide. &quot; class=&quot;wp-image-44745&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscription-flow-chart.png 804w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscription-flow-chart-300x240.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscription-flow-chart-768x614.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscription-flow-chart-50x40.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscription-flow-chart-580x464.png 580w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscription-flow-chart-696x557.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscription-flow-chart-560x448.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscription-flow-chart-370x296.png 370w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscription-flow-chart-590x472.png 590w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscription-flow-chart-80x64.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/weekly-subscription-flow-chart-48x38.png 48w&quot; sizes=&quot;auto, (max-width: 804px) 100vw, 804px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Even if you answered ‘yes’ to all five questions above, always test it before rolling it out widely. Think carefully about how to structure the test for your app. Some ideas:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Start by testing in select regions&lt;/li&gt;



&lt;li&gt;Show the weekly option only after the initial onboarding flow, and only to users who haven’t yet converted&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;In my experience, adding an extra pricing option can sometimes reduce clarity and introduce confusion. It’s worth testing different layouts and messaging before deciding whether weekly subscriptions are right for you.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-conclusion&quot;&gt;Conclusion&lt;/h2&gt;



&lt;p&gt;Overall, weekly subscriptions can work well, but need to be approached with caution and a strategy to prevent the potential extra churn. Hannah Parvaz explains it as follows:&amp;nbsp;&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“The churn on a weekly basis can be quite brutal, as weekly subs amplify buyer’s remorse. There are often high refund requests for this, and high cancellation rates. It can also feel quite predatory, especially if someone isn’t getting a lot of value. So it works really only when paired with a strong onboarding flow, perceived transparency, and moments of delight or curiosity.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;End of the day, the success metric of testing a weekly subscription isn’t just how many users pick the weekly plan. Ideally, track revenue per user over time (e.g., after 90 days) for each plan and assess whether the weekly option has improved your overall subscription conversion rate. The goal is to increase overall profitability, not to cannibalize your monthly and annual subscribers. And of course, more than ever, to add value for the end user by giving them a payment option that better suits their needs.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[The metrics that actually help you scale paid ads profitably]]></title><description><![CDATA[Why chasing CPC and CTR won’t grow your subscription app]]></description><link>https://www.revenuecat.com/blog/growth/metrics-for-scaling-paid-ads/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/metrics-for-scaling-paid-ads/</guid><pubDate>Wed, 16 Jul 2025 09:16:19 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/metrics-for-scaling-paid-ads.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;When it comes to scaling paid ads, which metrics come to mind first? Probably something like:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;CPC – Cost per click&lt;/li&gt;



&lt;li&gt;CTR – Click-through rate&lt;/li&gt;



&lt;li&gt;CPA – Cost per install / trial / purchase&lt;/li&gt;



&lt;li&gt;CPM – Cost per impression&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Yeah, that’s a lot of acronyms. It probably feels like reading a text chain between two Gen Zs. There are plenty of acronyms to track, and while these metrics can be useful, they won’t help you scale. You could have a low CPC and a high CTR, but if your lifetime value is too low, scaling just won’t work.&lt;/p&gt;



&lt;p&gt;Too many performance marketers focus on platform metrics like those from Meta and Google, instead of looking beyond them. But it’s the off-platform metrics that really drive scale. So I spoke to the best of the best, the ad experts of the industry, to get their advice on the matter.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-fundamentals-of-scaling-paid-ads&quot;&gt;The fundamentals of scaling paid ads&lt;/h2&gt;



&lt;p&gt;At the end of the day, scaling paid ads is a balancing act. On one side, you have lifetime value (LTV): how much a customer is worth over their entire relationship with your business. On the other hand, customer acquisition cost (CAC): how much it costs to bring them in.&lt;/p&gt;



&lt;p&gt;Together, they form your CAC-to-LTV ratio. A strong ratio means you’re earning more than it costs to acquire, which makes scaling possible. A weak one? That’s a signal to optimize before pushing budgets higher.&lt;/p&gt;



&lt;p&gt;As you scale up your budgets on platforms like Meta, your CAC often increases. You’ve already captured the low-hanging fruit — warm audiences who’ve heard of your app or are actively looking for something similar. Now, you’re reaching colder, higher-funnel audiences. Scaling becomes a game of pushing budgets up, then trying to bring CAC back down just to keep going.&lt;/p&gt;



&lt;p&gt;Here’s the catch: most marketers focus too heavily on reducing CAC, chasing an ideal number that’s becoming harder to hit, rather than improving the actual, realized LTV. CACs are rising year after year — and there’s only so low you can go. &lt;strong&gt;So instead of squeezing CAC further, flip the strategy: focus on increasing LTV.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Why? Because the ceiling on LTV is much higher and comes with additional benefits. Improving it doesn’t always come with rising costs. It also means you can grow with fewer new customers while protecting your margins.&lt;/p&gt;



&lt;p&gt;To scale effectively, start paying closer attention to the metrics that move LTV. Improve those, and you’ll feel a whole lot more confident scaling spend and getting bigger budgets signed off.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-do-you-measure-cac&quot;&gt;How do you measure CAC?&lt;/h2&gt;



&lt;p&gt;For subscription apps offering trials, success with paid ads is often measured by the number of trials started on platforms like Meta, TikTok, and Google. This is because many trials don’t convert within the attribution window, especially on iOS. As a result, marketers often rely on trial starts as a proxy for performance.&lt;/p&gt;



&lt;p&gt;But your actual CAC is your cost per subscription purchase. Ideally, you would also account for all the other costs involved in running ads, including the time spent by your team or external partners, attribution platforms, creatives, and more.&lt;/p&gt;



&lt;p&gt;But since you aren’t doing that on the platform, it’s crucial to carefully examine your trial-to-purchase conversion rate and your actual cost per purchase.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-metrics-to-help-you-improve-your-ltv&quot;&gt;Metrics to help you improve your LTV&lt;/h2&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-trial-to-purchase-conversion-rate&quot;&gt;Trial-to-purchase conversion rate&lt;/h3&gt;



&lt;p&gt;The trial-to-purchase conversion rate has a significant impact on the quality of sign-ups and the potential lifetime value (LTV). In my experience, a low trial-to-purchase rate often correlates with a lower LTV. However, it’s essential to layer this with downstream engagement and retention to get a full picture of user value — but more on that later.&lt;/p&gt;



&lt;p&gt;Tools like RevenueCat allow you to &lt;a href=&quot;https://www.revenuecat.com/docs/integrations/attribution/meta-ads#event-names&quot;&gt;send the data of which trials converted&lt;/a&gt; back to Meta, enabling you to double-check and calculate the trial-to-purchase conversion rate using custom metrics. Here’s the key data you’ll want to send back:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;466&quot; height=&quot;342&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/revenuecat-events-meta-event-manager.png&quot; alt=&quot;&quot; class=&quot;wp-image-44653&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/revenuecat-events-meta-event-manager.png 466w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/revenuecat-events-meta-event-manager-300x220.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/revenuecat-events-meta-event-manager-55x40.png 55w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/revenuecat-events-meta-event-manager-403x296.png 403w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/revenuecat-events-meta-event-manager-80x59.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/revenuecat-events-meta-event-manager-48x35.png 48w&quot; sizes=&quot;auto, (max-width: 466px) 100vw, 466px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;RevenueCat metrics to send back to Meta&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;But this data is key to look at not only in Meta ads, but also on your &lt;a href=&quot;https://www.revenuecat.com/docs/dashboard-and-metrics/charts/trial-conversion-chart&quot;&gt;dashboards&lt;/a&gt;. You want to filter and segment it to understand when you have a strong conversion rate and when you don’t.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Marcus Burke, in a &lt;a href=&quot;https://subclub.com/episode/scaling-your-subscription-app-with-meta-ads-marcus-burke-independent-consultant&quot;&gt;Sub Club podcast interview&lt;/a&gt;, discusses how with a younger audience, you may see far cheaper trial sign-ups, so Meta will focus its spending on them. However, looking at the trial conversion rate, you often see that older audiences convert at a higher rate, potentially due to higher spending capacities. In those cases, he experimented with intentionally excluding younger audiences because even with the higher cost per trial, the overall cost per purchase was better. Other ways to look at this are by angle, ad, audience, and country.&lt;/p&gt;



&lt;p&gt;Double-checking the breakdowns is crucial, and even if you use trials as your conversion event, you’re looking at the actual cost per purchase.&lt;/p&gt;



&lt;p&gt;If you’re seeing a low trial-to-conversion rate, it’s crucial to focus on improving it to scale your business. Marcus covers &lt;a href=&quot;https://www.revenuecat.com/blog/growth/how-to-increase-trial-conversion-rates-without-adding-new-features/&quot;&gt;10 ways to improve this ratio&lt;/a&gt;, and none of them involve adding new features.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-post-trial-engagement-as-a-predictor-of-ltv&quot;&gt;Post-trial engagement as a predictor of LTV&lt;/h3&gt;



&lt;p&gt;We know that a trial start alone isn’t a strong indicator of quality, but waiting until the trial ends can take a lot of time, especially for apps that offer longer trials. And for those not offering trials, it’s still important to gauge initial user quality early on.&lt;/p&gt;



&lt;p&gt;This is where engagement metrics come in handy. They offer an indication that new customers are likely to stick around and some form of activation within the first week or so. It could be the use of a key feature or a certain number of sessions within the first week. Just like with trial-to-conversion, understanding who sticks around and who doesn’t is hugely insightful.&lt;/p&gt;



&lt;p&gt;However, as &lt;a href=&quot;https://www.linkedin.com/in/hnpvz/&quot;&gt;Hannah Parvaz&lt;/a&gt;, founder of &lt;a href=&quot;https://www.aperture.london/&quot;&gt;Aperture&lt;/a&gt; (an app growth agency), highlights how this only works if your engagement metric occurs within the first 7 days:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“At a previous company, we identified that users became much less likely to churn after completing &lt;/em&gt;&lt;strong&gt;&lt;em&gt;six core actions across six different days&lt;/em&gt;&lt;/strong&gt;&lt;em&gt;. In this case, a core action was finishing a story. That was our activation point. Not just signing up or trying it once, but reaching the sixth meaningful interaction.Since this point typically occurred after 7 days, we did not optimize for it on Meta or any other platform. Especially because at the time, we were in the pink mist of iOS 14.5, when attribution windows had shortened.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Should you then use trials instead? You can, but if you’re seeing it’s driving low-quality subscribers you could instead send alternative engagement/activation signals back instead.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;I asked Hannah about this given she’s running Meta ads for a multitude of subscription apps. She shared the following:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“&lt;/em&gt;&lt;strong&gt;&lt;em&gt;The optimization point you choose depends on the product.&lt;/em&gt;&lt;/strong&gt;&lt;em&gt; For some companies, we stick to trials. For others, we define an “activated trial” and fire a separate event a few hours after the trial is taken out, if the trial has not been cancelled yet. (You can check the billing status to do this.)&lt;/em&gt; &lt;em&gt;For others, if the budget allows for it, we’ll do a trial + core action custom event and map this. This will be more expensive to achieve and requires a larger investment, but can pay off in the long term.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;I’ve also seen this activated trial work well as a goal, it reduces the focus on subscribers who sign up for a trial only to cancel immediately, and instead pushes Meta to focus on subscribers who are more likely to stick around.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;As a result, it can help improve targeting and ensures you’re acquiring high-quality subscribers.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Note, whilst we are talking a lot about trials here, I am conscious that not all subscription apps offer a free trial. For those that don’t, they may prefer to stick to purchases as a conversion goal instead of an engagement metric because the volume will usually be lower than trials started and an engagement goal may reduce it further making it hard to feed the ad platform algorithm enough data on which ads are performing and which ones aren’t.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;That is not to say you shouldn’t still be monitoring an engagement metrics as a performance marketer, rather that if you want to test it as a conversion goal, you may only do so once you’ve initial scaled spend. In which case it can be worth testing, especially if you’re struggling with lower LTVs holding you back from scaling up further.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Which brings us on to one of my favourite metrics.&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-realized-ltv-per-paying-customer-average-revenue-per-paying-user-arppu&quot;&gt;Realized LTV per paying customer / average revenue per paying User (ARPPU)&lt;/h3&gt;



&lt;p&gt;We’ve talked about overall LTV, but even after years, it’s still often treated as hypothetical — what people &lt;em&gt;might&lt;/em&gt; spend over time.&lt;/p&gt;



&lt;p&gt;If you think of Meta as a growth loop, the loop goes like this:&amp;nbsp;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;You run ads&lt;/li&gt;



&lt;li&gt;You acquire new subscribers&lt;/li&gt;



&lt;li&gt;That generates revenue&lt;/li&gt;



&lt;li&gt;You then reinvest that revenue to run more ads&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Sounds simple and great in theory. The issue? Setting attribution aside (that’s a whole other can of worms we won’t open here), potential revenue can’t be reinvested. So, instead, you want to look at what has &lt;em&gt;actually been&lt;/em&gt; generated to date.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;The way you do this is by focusing on &lt;a href=&quot;https://www.revenuecat.com/docs/dashboard-and-metrics/charts/realized-ltv-per-paying-customer-chart&quot;&gt;Realized LTV per Paying Customer / Average Revenue Per Paying User (ARPPU)&lt;/a&gt;. RevenueCat defines it as follows:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“Realized LTV (Lifetime Value) per Paying Customer (sometimes also called Average Revenue per Paying User, ARPPU) shows the actual revenue (minus refunds) that was generated by a cohort of paying customers, divided by the number of customers in that cohort.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;You also want to be understanding which campaigns and ads are driving a higher ARPPU in order to make your ads more profitable and improve the ratio of ARPPU / CAC.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;When I interviewed Cedric Yarish, co-founder of &lt;a href=&quot;http://admanage.ai&quot;&gt;admanage.ai&lt;/a&gt;, on different ways to experiment on Meta, he shared how, during his time leading user acquisition at &lt;a href=&quot;https://www.photoroom.com/&quot;&gt;Photoroom&lt;/a&gt;, they used onboarding data to distinguish between business users and individual creators. They then associated a higher value with business users and sent that information back to Meta because they saw the realized LTV was much higher for business users. This helped them ensure they were focusing their campaigns on the most profitable customers, allowing them to scale up their ad budgets faster.&lt;/p&gt;



&lt;p&gt;Now knowing your realized LTV per paying customer from Meta helps you work out another key metric that will help you speed up that ad growth loop: &lt;strong&gt;your payback period. &lt;/strong&gt;How long does it take to cover the costs of acquisition?&amp;nbsp;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-payback-period&quot;&gt;Payback period&lt;/h3&gt;



&lt;p&gt;This is a key determinant in how quickly your growth loop can progress. A shorter payback period, assuming you’re confident in attributing those sales to Meta, will allow you to scale up your ads more quickly.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;However, it is a tricky one to calculate correctly, as &lt;a href=&quot;https://www.linkedin.com/in/nathan--hudson/&quot;&gt;Nathan Hudson&lt;/a&gt;, founder of &lt;a href=&quot;https://www.perceptycs.com/&quot;&gt;Perceptycs&lt;/a&gt;, shares:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“With multiple pricing plans and plan durations, different percentages of users purchasing each of these in any given cohort, fluctuating trial conversion rates, and unknown renewal rates influenced by seasonality, it’s very challenging to accurately forecast payback period.&lt;/em&gt; &lt;/p&gt;



&lt;p&gt;&lt;em&gt;For this reason, I’m a big advocate of tracking blended ARPPU:CAC ratio off platform at various periods – day 0, day 3, day 7, day 30, day 90, day 365. If we set a target payback period and have enough historical data, we can &lt;/em&gt;&lt;strong&gt;&lt;em&gt;track a forward-assumed ARPPU:CAC ratio for any given cohort at any given period&lt;/em&gt;&lt;/strong&gt;&lt;em&gt;. &lt;/em&gt;&lt;/p&gt;



&lt;p&gt;&lt;em&gt;Of course, these are just predictions, but they give another view of performance that can be used to scale up or pull back Meta’s acquisition.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;So again, he is looking at actual spend in the past to help predict the potential profitability of future subscribers and how long it will take to earn back the costs.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;As mentioned earlier, make sure to consider your CAC, including all associated costs for the month: time spent by your team or external partners, attribution platforms, creatives, and more. The way I do this is by doing a double check per month of the total costs vs acquired users, as some of these costs will be fixed.&lt;/p&gt;



&lt;p&gt;Now, longer payback periods mean higher risk because if the ARPPU is lower than you predicted, you risk acquiring unprofitable users. So, if the payback period is too long, you can use the realized LTV per paying customer/ARPPU to help you identify and prioritize users who naturally spend more.&lt;/p&gt;



&lt;p&gt;In short, this metric not only shapes your growth pacing but also helps inform which data to send back to your ad platform, so you can attract more of the customers that truly matter.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-churn-rate-amp-renewals&quot;&gt;Churn rate &amp;amp; renewals&lt;/h3&gt;



&lt;p&gt;The churn rate measures the number of subscriptions lost over a given period. When it comes to paid ads, comparing the churn rate of platform-acquired users to your overall churn rate helps you spot whether retention issues are limiting your ability to scale.&lt;/p&gt;



&lt;p&gt;In my experience, paid users tend to churn at a higher rate than those from organic sources. That said, if the gap is too large, it’s a red flag — and we all know that red flags should never be ignored, whether that’s on a first date or paid ads. It could mean you’re attracting the wrong audience or setting unrealistic expectations early in the user journey.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;673&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/revenuecat-churn-chart-1024x673.png&quot; alt=&quot;&quot; class=&quot;wp-image-44655&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/revenuecat-churn-chart-1024x673.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/revenuecat-churn-chart-300x197.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/revenuecat-churn-chart-768x505.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/revenuecat-churn-chart-61x40.png 61w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/revenuecat-churn-chart-696x458.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/revenuecat-churn-chart-560x368.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/revenuecat-churn-chart-450x296.png 450w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/revenuecat-churn-chart-718x472.png 718w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/revenuecat-churn-chart-80x53.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/revenuecat-churn-chart-48x32.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/revenuecat-churn-chart.png 1369w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Churn chart within RevenueCat&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;If your overall churn rate is low, it could be a sign that you need to focus on activation and retention before trying to scale on Meta. Cedric Yarish explains why more marketers don’t prioritize this metric:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“Generally, performance marketers only focus on metrics they can change, and churn is usually outside the scope. But it’s important because it affects your LTV and thus affects your bid in Meta.”&amp;nbsp;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Just because something is out of your direct control doesn’t mean you shouldn’t push to improve it, especially if it’s limiting your ability to scale budgets.&lt;/p&gt;



&lt;p&gt;With annual subscriptions, churn can be a lagging metric, so you should already be tracking engagement early on. That said, looking at monthly renewal rates can offer quicker insight into audience and campaign quality.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-new-trialists-subscriptions&quot;&gt;New trialists/subscriptions&lt;/h3&gt;



&lt;p&gt;If you’re just reacquiring the same subscribers over and over, your CAC/LTV ratio might look great on paper, but in reality, it’s not. It ends up being inefficient, since you’re often spending the same amount to reacquire an existing user as you would to bring in someone new. Not ideal. This would be the equivalent of dating the same person over and over, hoping it will end differently — &lt;em&gt;maybe this time!&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;So, how do you use this in practice? &lt;strong&gt;If you’re using Meta primarily as an acquisition channel, as most brands are, tracking the cost per &lt;/strong&gt;&lt;strong&gt;&lt;em&gt;new&lt;/em&gt;&lt;/strong&gt;&lt;strong&gt; trial or subscriber is essential.&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Even when you &lt;a href=&quot;https://www.revenuecat.com/docs/integrations/attribution/meta-ads#event-names&quot;&gt;connect your subscriber data&lt;/a&gt; with Meta, the system isn’t flawless. In my experience, a proportion of the budget almost always ends up targeting existing users. That’s why it’s important to figure out which ads are actually driving &lt;em&gt;new&lt;/em&gt; subscribers; it’s the only way to make sure scaling your ad spend results in real revenue growth.&lt;/p&gt;



&lt;p&gt;&lt;a href=&quot;https://www.linkedin.com/in/aazarshad/&quot;&gt;Aazar Shad&lt;/a&gt;, who’s helped scale education brands from $1 million to $10 million using Meta Ads, shared that he spent far more time focusing on this dashboard that pulls data directly from the app, as well as looking purely at Meta to see what is happening in terms of new users:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;956&quot; height=&quot;555&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/aazar-shad-dashboard.png&quot; alt=&quot;&quot; class=&quot;wp-image-44659&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/aazar-shad-dashboard.png 956w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/aazar-shad-dashboard-300x174.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/aazar-shad-dashboard-768x446.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/aazar-shad-dashboard-69x40.png 69w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/aazar-shad-dashboard-696x404.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/aazar-shad-dashboard-560x325.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/aazar-shad-dashboard-510x296.png 510w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/aazar-shad-dashboard-813x472.png 813w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/aazar-shad-dashboard-80x46.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/aazar-shad-dashboard-48x28.png 48w&quot; sizes=&quot;auto, (max-width: 956px) 100vw, 956px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Aazar’s dashboard that guides his decision-making&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;One of his favourite metrics is looking at cost per new user:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“I have a dashboard where we connect the Meta data with the app to look at Cost per New User (CPNU) as well as Average Revenue Per Paying User / CAC. I really like looking at CPNU per ad and obsess about it because if the CPNU is down, it’s a good indicator that the ad is working. When this goes higher, I see the cost of purchase increase too, so it’s an early indicator.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Just keep in mind: while CPNU (cost per new user) is a great directional metric, it should always be sanity-checked against incrementality and the quality of your attribution. With new subscribers, incremental testing, and an increase in your budget, and seeing the difference in overall revenue can also provide valuable insights.&lt;/p&gt;



&lt;p&gt;If you’re noticing that the share of new users is too low, there’s another approach worth considering. Cedric Yarish pointed out in our interview that too many brands still rely heavily on view-through attribution. &lt;strong&gt;Instead, he recommends shifting to 1-day or 7-day click attribution, which he believes offers much more accurate and actionable insights.&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;475&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/attribution-setting-meta-ads-1024x475.png&quot; alt=&quot;&quot; class=&quot;wp-image-44661&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/attribution-setting-meta-ads-1024x475.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/attribution-setting-meta-ads-300x139.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/attribution-setting-meta-ads-768x356.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/attribution-setting-meta-ads-86x40.png 86w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/attribution-setting-meta-ads-696x323.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/attribution-setting-meta-ads-560x260.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/attribution-setting-meta-ads-840x390.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/attribution-setting-meta-ads-80x37.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/attribution-setting-meta-ads-48x22.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/attribution-setting-meta-ads.png 1306w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Attribution setting with view through attribution as well as click attribution&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;With ads, you really have to be conscious of whether they’re truly incremental and actually driving results. Broad ad channels can lead to a lot of wasted spend, so the more control you have here, the better. Cedric typically uses 1-day click attribution, but if the consideration period is longer, he switches to 7-day click attribution.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;That’s why tracking the total number of new subscribers is so essential.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-scaling-your-performance-ads&quot;&gt;Scaling your performance ads&lt;/h2&gt;



&lt;p&gt;Scaling paid ads isn’t about chasing cheap clicks; it’s about optimizing for real, lasting value. That means zooming out beyond the ad platforms and focusing on the metrics that truly drive growth: trial-to-subscription conversion, engagement, realized LTV/ARPPU, churn/renewal, and cost per new subscriber.&lt;/p&gt;



&lt;p&gt;Which of these matter the most will change as you grow, Hannah Parvaz summarizes this perfectly:&lt;/p&gt;



&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;em&gt;“At a smaller scale, cost per trial (CPT) is one of the most important metrics. It gives you a fast signal on whether your top-of-funnel economics are working. But CPT alone is not enough. &lt;/em&gt;&lt;/p&gt;



&lt;p&gt;&lt;em&gt;You must also track trial-to-paid conversion rate and your payback window.&lt;/em&gt; &lt;em&gt;As you scale, you should start obsessing less about CPMs or CTRs and more on downstream unit economics. CPMs can fluctuate. CTRs can look great without any revenue behind them. &lt;/em&gt;&lt;strong&gt;&lt;em&gt;The deeper metrics tell you if your growth is sustainable.&lt;/em&gt;&lt;/strong&gt; &lt;/p&gt;



&lt;p&gt;&lt;em&gt;At a very large scale, retention and contribution margin per cohort start to matter even more. But you need to earn the right to worry about that. Early on, cost per trial, trial-to-paid, and payback are your critical path.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Most performance marketers optimize for the top of the funnel rather than for profitability. But to scale effectively, you need to send better data back into your ad platforms, ensure retention is strong enough to support growth, and track the metrics that reflect actual business impact, not just ad performance.&lt;/p&gt;



&lt;p&gt;That’s how you scale faster and more sustainably than any low CPC ever could.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[The biggest misconception about web-to-app funnels (and why it’s costing you money)]]></title><description><![CDATA[If you launch your first web-to-app flow without considering this, you could be pouring gasoline on your marketing budget.]]></description><link>https://www.revenuecat.com/blog/growth/web-to-app-funnels-are-not-onboarding-quizzes/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/web-to-app-funnels-are-not-onboarding-quizzes/</guid><pubDate>Tue, 15 Jul 2025 08:35:21 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/web-to-app-funnels-are-not-onboarding-quizzes.png" length="0" type="image/*"/><content:encoded>&lt;div class=&quot;lazyblock-e525b3a3ae6c-Z1Bepg0 wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Build no-code web funnels in RevenueCat&quot; text=&quot;&lt;p&gt;Unlock the flexibility and profit of web-to-app with our new funnel builder: create custom onboarding, surveys, and checkout flows in an instant. Free and included in your regular plan. &lt;a href=&amp;quot;https://www.revenuecat.com/feature/funnels&amp;quot;&gt;Learn more&lt;/a&gt;.&lt;/p&gt;&quot; icon=&quot;star&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;p&gt;Wasted ad spend is only part of the problem.&lt;/p&gt;



&lt;p&gt;Building the wrong funnel burns developer hours, design resources, and senior stakeholder time — all for something that might not even be the best approach.&lt;/p&gt;



&lt;p&gt;Worst of all? You might come to the completely wrong conclusion that web-to-app funnels “don’t work” for your business… when in reality, &lt;strong&gt;you just didn’t explore all the options.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;I see it happen all the time.&lt;/p&gt;



&lt;p&gt;A subscription app copies a web-to-app funnel from a big-name competitor, assuming that’s the “proven” model. After three months, it’s underperforming&lt;strong&gt;.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;What happens next?&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Half of the team blames the creatives.&lt;/li&gt;



&lt;li&gt;Half of the team blames poor tracking.&lt;/li&gt;



&lt;li&gt;The C-suite blames web-to-app itself.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The truth? They may have just picked the wrong strategy.&lt;/p&gt;



&lt;p&gt;If you think &lt;strong&gt;web-to-app = onboarding quizzes,&lt;/strong&gt; keep reading, because that assumption might be the most expensive web-to-app mistake you make this year.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-who-i-am-and-why-this-matters&quot;&gt;Who I am and why this matters&lt;/h2&gt;



&lt;p&gt;Hey, I’m Nathan Hudson, App Marketer of the Year, and Founder of Perceptycs, where we help subscription apps grow faster. I’ve worked with indie developers grinding it out, VC-backed startups chasing hockey-stick growth, bootstrapped scale-ups fighting for every dollar, and even large enterprises trying to innovate like startups.&lt;/p&gt;



&lt;p&gt;Across all of the conversations I’ve had, one assumption pops up over and over again.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-misconception-web-to-app-funnels-web-onboarding-quizzes&quot;&gt;The misconception: web-to-app funnels = web onboarding quizzes&lt;/h2&gt;



&lt;p&gt;Most people think that web-to-app = web onboarding quizzes.&lt;/p&gt;



&lt;p&gt;They assume that to make web-to-app work, you need a web onboarding journey that feels like a personality test. “What’s your biggest challenge?” “What are your goals?” “Which celebrity do you think you’d be if they were an inanimate object?”&lt;/p&gt;



&lt;p&gt;Now, don’t get me wrong, these onboarding journeys &lt;em&gt;can&lt;/em&gt; work, and in a lot of cases too. We’ve helped countless apps refine their web-to-app quiz funnels. But they’re not the &lt;em&gt;only&lt;/em&gt; way.&lt;/p&gt;



&lt;p&gt;And if that assumption goes unchallenged, it kills experimentation, limits growth, and burns budgets.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-this-assumption-exists&quot;&gt;Why this assumption exists&lt;/h2&gt;



&lt;p&gt;So why is this misconception so prevalent? There are a couple of key reasons:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-reason-1-big-apps-have-normalized-it&quot;&gt;Reason #1: Big apps have normalized it&lt;/h3&gt;



&lt;p&gt;Apps like Calm, Blinkist, Duolingo, and Headway have been running web onboarding funnels for years. And these are the giants of the app world that most growth teams look up to.&lt;/p&gt;



&lt;p&gt;Smaller apps copy them, assuming that’s the way to make web-to-app work. They see the success of these big brands and think, “If it works for them, it’ll work for me.”&lt;/p&gt;



&lt;p&gt;App teardowns (including my own) reinforce this because they often focus on these best in class, industry leaders. The reason for that is because breakdowns of big apps get more attention than smaller niche funnels that don’t have huge scale. Everyone wants to know what Calm is doing, but nobody cares about “Bob’s Discount Meditation App” (no offense to Bob).&amp;nbsp;&lt;/p&gt;



&lt;p&gt;So, the quiz funnel gets all the attention, even though it might not be the best fit for every app.&lt;/p&gt;



&lt;p&gt;But apps that see success with web-to-app onboarding journeys are often Health &amp;amp; Fitness apps, or Education apps. They often already have seen success with long onboarding journeys in app and they have a plethora of reasons to ask users questions (narrowing down use cases, content personalisation, etc)&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-reason-2-the-rise-of-web-onboarding-funnel-builders&quot;&gt;Reason #2: The rise of web onboarding funnel builders&lt;/h3&gt;



&lt;p&gt;The rise of drag-and-drop web onboarding funnel builders has also contributed to this misconception. Many of the most visible tools in the space position themselves as “Web-to-App made easy,” but, if you look closer, their offerings almost always center on onboarding quizzes — a narrow subset of what’s possible.&lt;/p&gt;



&lt;p&gt;Of course, it’s a classic case of building what sells: most teams ask for quiz funnels, so these platforms double down on them. But by only offering one approach, they end up reinforcing the idea that web-to-app = quizzes, limiting the scope of experimentation and nudging the market toward a single, cookie-cutter solution.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-this-misconception-is-dangerous&quot;&gt;Why this misconception is dangerous&lt;/h2&gt;



&lt;p&gt;Here’s why this misconception is so dangerous: If you believe web-to-app = Quizzes, you limit yourself to &lt;em&gt;one&lt;/em&gt; playbook. You’re putting all your eggs in one basket, and that’s never a good idea.&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;If it doesn’t work for your app, you’ll assume web-to-app doesn’t work for your app. &lt;/strong&gt;And this might not be the case. All you’ve proved is that web-to-app onboarding funnels don’t work for you. And more specifically, the web-to-app onboarding quizzes &lt;em&gt;you’ve &lt;/em&gt;tested in your current setup/funnel don’t work for you.&amp;nbsp; And you’ll miss out on all the other potential benefits of web-to-app funnels.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Even if it’s working now, it won’t last forever.&lt;/strong&gt; Marketing trends &lt;em&gt;cycle&lt;/em&gt;. We’ve seen it happen time and time again.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Something works → People copy it → Tools make it easier → More people copy → The market gets saturated → Performance tanks. It’s the marketers circle of life.&lt;/p&gt;



&lt;p&gt;We saw it with banner ads, we see it with &lt;a href=&quot;/blog/growth/detect-ad-fatigue-mobile-apps/&quot;&gt;ad fatigue&lt;/a&gt;, and we’ll see it with onboarding quizzes. Eventually, people will get tired of answering questions and they’ll start tuning out. And then what?&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-when-web-to-app-quizzes-don-t-click-recognizing-the-wrong-fit&quot;&gt;When web-to-app quizzes don’t click (recognizing the wrong fit)&lt;/h2&gt;



&lt;p&gt;Okay. So the obvious next question is – when might a quiz funnel not be the right fit?&lt;br&gt;&lt;br&gt;I find it helpful to break down what types of apps typically see success with web-to-app funnels and try to understand why that might be. What purpose is the onboarding funnel serving for them and their users?&lt;br&gt;&lt;br&gt;Then we can simply reverse this and start with the assumption that if we don’t need to achieve those things, we may not need a&lt;/p&gt;



&lt;p&gt;But for the sake of time, here are a few of those core reasons:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Limited need for personalization&lt;/strong&gt;: Onboarding funnels allow you to capture data which can then be leveraged to personalise the early product experience and filtering down features/content. But what if your app &lt;em&gt;doesn’t&lt;/em&gt; need deep personalization? What if it’s a simple photo inbox cleaner app? A quiz is just unnecessary friction.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Lack of nuance&lt;/strong&gt;: Onboarding funnels are great for &lt;em&gt;teaching&lt;/em&gt; users about nuanced topics and taking them on a journey where the aha mo. But what if your app is incredibly straightforward? What if it’s a simple weather app? A quiz is just overkill.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;No need for empathy building&lt;/strong&gt;: Onboarding funnels are a great way to build and communicate a sense of empathy from the app to the user. It’s essentially a way of saying, we care about you, we understand and we want to go on this journey together. But what if your app &lt;em&gt;doesn’t&lt;/em&gt; need to build that kind of emotional connection? What if it’s a simple tool? Well. Then a quiz is just… weird.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Simple value proposition&lt;/strong&gt;: If your app’s value is immediately obvious, a quiz just delays the user from experiencing it. Why make them jump through hoops when they could be getting value right away?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;High friction introduction&lt;/strong&gt;: Let’s face it: Quizzes can feel intrusive or time-consuming if not done well. They can deter users before they even get a chance to see what your app is all about.&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-truth-web-to-app-is-bigger-than-just-quizzes&quot;&gt;The truth: web-to-app is bigger than just quizzes&lt;/h2&gt;



&lt;p&gt;Here’s the reality: web-to-app is simply the process of using the web to aid mobile app conversion.&lt;/p&gt;



&lt;p&gt;It’s about leveraging the web as part of the user conversion journey.&lt;/p&gt;



&lt;p&gt;You don’t need quizzes. You don’t even technically need account creation or a web checkout to launch a web-to-app funnel.&lt;/p&gt;



&lt;p&gt;Here are just a few other viable web-to-app strategies:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Landing page → Checkout&lt;/li&gt;



&lt;li&gt;Landing page → Sign up → Install&lt;/li&gt;



&lt;li&gt;Smart banners (AppsFlyer, Adjust, etc.)&lt;/li&gt;



&lt;li&gt;QR codes → App Install&lt;/li&gt;



&lt;li&gt;Email sequence → Web Paywall → Checkout&lt;/li&gt;



&lt;li&gt;Lead magnet → App install&lt;/li&gt;



&lt;li&gt;Blog post → Install&lt;/li&gt;



&lt;li&gt;Webinar funnel → Checkout&lt;/li&gt;



&lt;li&gt;Landing page → Web app demo → Checkout&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;And tons more… The possibilities are endless! It’s about thinking creatively and finding what works for &lt;em&gt;your&lt;/em&gt; product and &lt;em&gt;your&lt;/em&gt; audience.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-so-what-should-you-do&quot;&gt;So what should you do?&lt;/h2&gt;



&lt;p&gt;&lt;strong&gt;If your quiz funnel is working&lt;/strong&gt; – amazing! &lt;em&gt;Double down on it&lt;/em&gt;.&amp;nbsp; But also start thinking through whether or not any other web-to-app strategies could be worth testing for your app. Perhaps they could be integrated into your existing funnel or maybe launched as separate funnel tests all together.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Ultimately the goal is to scale efficiently. Some of these alternatives might very well deliver stronger performance for your app. And others may enable you to reach new audiences or convert prospects with different intent.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;If your funnel isn’t working, &lt;/strong&gt;split your resources between optimising what you have and testing new ideas. You most likely have hypotheses around why the funnel isn’t performing and insights from performance so far. Leverage these to both iterate on your quiz funnel and test different types of web-to-app funnels.&lt;/p&gt;



&lt;p&gt;Of course the ultimate goal is to have a profitable web-to-app funnel. But from where you stand right now, an immediate goal should be to figure out whether or not it’s the way you’ve tested quiz funnels, the quiz funnel itself or web-to-app as a whole. But beyond this&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;If you haven’t started yet,&lt;/strong&gt; don’t just copy what everyone else is doing – think through what makes sense for &lt;em&gt;your&lt;/em&gt; product. What are your unique selling points? What are your customers’ pain points? How can you best highlight and address those on the web before they even download your app?&lt;/p&gt;



&lt;p&gt;It might not be a web onboarding quiz.&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-Z1nyPyK wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Create web-to-app funnels in RevenueCat&quot; text=&quot;&lt;p&gt;With RevenueCat Funnels, you can build no-code custom onboarding, surveys, and checkout flows that unlock seamless in-app access. &lt;a class=&amp;quot;notion-link-token notion-focusable-token notion-enable-hover&amp;quot; tabindex=&amp;quot;0&amp;quot; href=&amp;quot;https://www.revenuecat.com/feature/funnels/&amp;quot; rel=&amp;quot;noopener noreferrer&amp;quot; data-token-index=&amp;quot;1&amp;quot;&gt;&lt;span class=&amp;quot;link-annotation-unknown-block-id--717331513&amp;quot;&gt;Learn more&lt;/span&gt;&lt;/a&gt;&lt;span class=&amp;quot;link-annotation-unknown-block-id--717331513&amp;quot;&gt; ↗️&lt;/span&gt;&lt;!-- notionvc: 8ff03936-e607-4e73-895d-f9b30c634e17 --&gt;&lt;/p&gt;&quot; icon=&quot;bulb&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[A beginner’s guide to implementing an ad-free subscription in your Flutter app]]></title><description><![CDATA[A step-by-step tutorial to let users pay to remove ads—using AdMob, and RevenueCat]]></description><link>https://www.revenuecat.com/blog/engineering/a-beginners-guide-to-implementing-an-ad-free-subscription-in-your-flutter-app/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/a-beginners-guide-to-implementing-an-ad-free-subscription-in-your-flutter-app/</guid><pubDate>Fri, 11 Jul 2025 08:54:07 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/05/1.-How-to-offer-an-ad-free-experience-to-Android-users-while-maximizing-revenue.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Mobile apps primarily rely on two monetization strategies: ads and subscriptions. While ads provide free access to users and generate revenue for developers, they often disrupt the user experience and can lead to frustration. This creates an opportunity for developers to offer a premium, ad-free experience through subscriptions—a win-win solution that enhances user satisfaction while generating recurring revenue.&lt;/p&gt;



&lt;p&gt;In this guide, we’ll walk you through the process of implementing an ad-free subscription in your Flutter app using RevenueCat. This tutorial has you covered even if you’re new to subscriptions and ads. Things we will be doing in this tutorial:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Adding ads to our app using AdMob and google_mobile_ads package&lt;/li&gt;



&lt;li&gt;Adding subscriptions to our app using RevenueCat and flutter_purchases&lt;/li&gt;



&lt;li&gt;Configuring ads to be shown only if user is currently not subscribed, after subscribing all ads will be hidden from the users view&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;By the end of this article you should have a Flutter app for iOS and Android, that is capable of showing ads, displaying a paywall, and after purchasing a subscription from that paywall also able to hide the ads for the subscribed user.&lt;/p&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-F9glB wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Track ad revenue in RevenueCat&quot; text=&quot;&lt;p&gt;You can now track your AdMob add revenue in Revenuecat and get a complete picture of your revenue. Simply replace your standard AdMob loading calls with the loadAndTrack methods from the RevenueCat SDK. All ad events are tracked automatically. Read more about our new in-app ad revenue &lt;a href=&amp;quot;https://www.revenuecat.com/blog/growth/track-in-app-ad-revenue-alongside-purchases-get-the-full-picture-on-monetization/&amp;quot;&gt;in our announcement blog post&lt;/a&gt;.&lt;/p&gt;&quot; icon=&quot;bulb&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;

&lt;div class=&quot;lazyblock-dcadc5d83064-1qGmvy wp-block-lazyblock-dcadc5d83064&quot;&gt;&lt;blogposthowtostep level=&quot;h2&quot; title=&quot;Prerequisites&quot; summary=&quot;What is needed to follow this guide such as starting a new Flutter project and setting up App Store and Play Store &quot; image-url=&quot;&quot;&gt;
&lt;/blogposthowtostep&gt;&lt;/div&gt;


&lt;p&gt;In this tutorial, we will build a simple Flutter app, for both iOS and Android, that allows the user to subscribe to a monthly subscription which unlocks an ad-free experience in the app. If you have an existing app in which you’re going to implement subscription functionality, you can jump ahead to the next section.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Start by creating a new Flutter project. &lt;a href=&quot;https://docs.flutter.dev/reference/create-new-app#vs-code&quot;&gt;Follow the steps in this guide&lt;/a&gt; if you need a refresher. Open the project in your editor of choice. After that, run:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Xmekk wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;$ flutter run&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Testing in-app purchases is best on a real device, so choose that option from the presented list and check that your app runs without problems.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-set-up-app-store-and-play-store&quot;&gt;Set up App Store and Play Store&lt;/h3&gt;



&lt;p&gt;Before we can move to implementing subscriptions in our app, we need to configure our subscription product for all the platforms we want to target. Since Flutter is a cross-platform framework, it’s a good idea to target both iOS and Android. In both cases we want to configure a single subscription: a monthly recurring subscription for 5 dollars.&lt;/p&gt;



&lt;p&gt;Create yourself a RevenueCat account and then follow this guide to connect the App Store and Play store to RevenueCat.&amp;nbsp;&lt;/p&gt;


&lt;div class=&quot;lazyblock-dcadc5d83064-ZkBzlB wp-block-lazyblock-dcadc5d83064&quot;&gt;&lt;blogposthowtostep level=&quot;h2&quot; title=&quot;Step 1: Add ads to your Flutter app&quot; summary=&quot;Install Google AdMob to your Flutter app with google_mobile_ads. Configure AdMob ids, initiate your ads at app startup using a custom module that contains code for both subscriptions and ads.&quot; image-url=&quot;&quot;&gt;
&lt;/blogposthowtostep&gt;&lt;/div&gt;


&lt;p&gt;Displaying ads in the app can be done with Google AdMob. Using it requires creating an account, create one if you haven’t already. After creating your account, create the new apps in the AdMob dashboard for all the platforms you plan to target.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Next step is to integrate the Google Mobile ADs SDK into a Flutter app. Add &lt;code&gt;google_mobile_ads&lt;/code&gt; to the &lt;code&gt;pubspec.yaml&lt;/code&gt; file:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ZEb5Ls wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;# pubspec.yaml\ndependencies:\n  google_mobile_ads: ^6.0.0\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;We need to add AdMob App IDs to both the &lt;code&gt;AndroidManifest.xml&lt;/code&gt; file (for Android) and the &lt;code&gt;Info.plist&lt;/code&gt; file (for iOS) Make the following changes:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z19Cyfh wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;\/\/Info.plist\n&lt;key&gt;GADApplicationIdentifier&lt;\/key&gt;\n&lt;string&gt;your-app-id-here&lt;\/string&gt;\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;

&lt;div class=&quot;lazyblock-b77fda85b8ba-ZScRCw wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;\/\/AndroidManifest.xml\n&lt;manifest&gt;\n    &lt;application&gt;\n        &lt;meta-data\n            android:name=\&amp;quot;com.google.android.gms.ads.APPLICATION_ID\&amp;quot;\n            android:value=\&amp;quot;your-app-id-here\&amp;quot;\/&gt;\n    &lt;application&gt;\n&lt;manifest&gt;\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Before we add the code for initializing the ads (and later subscriptions), let’s go over the project structure. Both the subscription and ads logic will be placed in a file called subscription_manager.dart. Create that file inside a services folder and paste the following contents:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1FXA42 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;dart&quot; content=&quot;&amp;quot;import &apos;package:google_mobile_ads\/google_mobile_ads.dart&apos;;\nimport &apos;..\/config\/app_config.dart&apos;;\n\nclass SubscriptionManager {\n  static const String _bannerAdUnitId = AppConfig.bannerAdUnitId;\n  \n  static final SubscriptionManager _instance = SubscriptionManager._internal();\n  factory SubscriptionManager() =&gt; _instance;\n  SubscriptionManager._internal();\n\n  bool _isInitialized = false;\n\n  Future&lt;void&gt; initialize() async {\n    if (_isInitialized) return;\n\n    try {\n      \/\/ Initialize AdMob\n      await MobileAds.instance.initialize();\n      \n      _isInitialized = true;\n    } catch (e) {\n      print(&apos;Failed to initialize services: $e&apos;);\n    }\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Next we need to initialize the ads at app startup. In the &lt;code&gt;main.dart&lt;/code&gt; add this code to call the code :&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1wPo1I wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;dart&quot; content=&quot;&amp;quot;void main() async {\n  WidgetsFlutterBinding.ensureInitialized();\n  \n  \/\/ Initialize subscription manager\n  await SubscriptionManager().initialize();\n  \n  runApp(const MyApp());\n}\n\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-displaying-banner-ads&quot;&gt;Displaying Banner ads&lt;/h3&gt;



&lt;p&gt;Create a new file called &lt;code&gt;ad_banner_widget.dart&lt;/code&gt; file and paste the contents from below:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Mwf33 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;dart&quot; content=&quot;&amp;quot;import &apos;package:flutter\/material.dart&apos;;\nimport &apos;package:google_mobile_ads\/google_mobile_ads.dart&apos;;\nimport &apos;..\/services\/subscription_manager.dart&apos;;\n\nclass BannerAdWidget extends StatefulWidget {\n  const BannerAdWidget({super.key});\n\n  @override\n  State&lt;BannerAdWidget&gt; createState() =&gt; _BannerAdWidgetState();\n}\n\nclass _BannerAdWidgetState extends State&lt;BannerAdWidget&gt; {\n  BannerAd? _bannerAd;\n  bool _isLoaded = false;\n  final SubscriptionManager _subscriptionManager = SubscriptionManager();\n\n  @override\n  void initState() {\n    super.initState();\n    _loadAd();\n  }\n\n  void _loadAd() {\n    _bannerAd = _subscriptionManager.createBannerAd();\n    _bannerAd!.load().then((_) {\n      if (mounted) {\n        setState(() {\n          _isLoaded = true;\n        });\n      }\n    }).catchError((error) {\n      print(&apos;Failed to load banner ad: $error&apos;);\n    });\n  }\n\n  @override\n  void dispose() {\n    _bannerAd?.dispose();\n    super.dispose();\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    if (!_isLoaded || _bannerAd == null) {\n      return SizedBox(\n        height: MediaQuery.of(context).size.height \/ 3,\n        child: const Center(\n          child: CircularProgressIndicator(),\n        ),\n      );\n    }\n\n    return Container(\n      width: double.infinity,\n      height: MediaQuery.of(context).size.height \/ 3,\n      decoration: BoxDecoration(\n        borderRadius: BorderRadius.circular(8),\n        border: Border.all(color: Colors.grey.shade300),\n      ),\n      child: ClipRRect(\n        borderRadius: BorderRadius.circular(8),\n        child: AdWidget(ad: _bannerAd!),\n      ),\n    );\n  }\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This component will display banner ads between the paragraphs that span the full width and one-third of the height of the page. We also need to add a functionality to the SubscriptionManager for creating banner ads:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-WPH2c wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;dart&quot; content=&quot;&amp;quot;import &apos;package:google_mobile_ads\/google_mobile_ads.dart&apos;;\nimport &apos;..\/config\/app_config.dart&apos;;\n\nclass SubscriptionManager {\n  static const String _bannerAdUnitId = AppConfig.bannerAdUnitId;\n  \n  static final SubscriptionManager _instance = SubscriptionManager._internal();\n  factory SubscriptionManager() =&gt; _instance;\n  SubscriptionManager._internal();\n\n  bool _isInitialized = false;\n\n  Future&lt;void&gt; initialize() async {\n    if (_isInitialized) return;\n\n    try {\n      \/\/ Initialize AdMob\n      await MobileAds.instance.initialize();\n      \n      _isInitialized = true;\n    } catch (e) {\n      print(&apos;Failed to initialize services: $e&apos;);\n    }\n  }\n\n  Future&lt;bool&gt; isSubscribed() async {\n    try {\n      CustomerInfo customerInfo = await Purchases.getCustomerInfo();\n      return customerInfo.entitlements.active.containsKey(_entitlementId);\n    } catch (e) {\n      print(&apos;Failed to check subscription status: $e&apos;);\n      return false;\n    }\n  }\n\n  BannerAd createBannerAd() {\n    return BannerAd(\n      adUnitId: _bannerAdUnitId,\n      size: AdSize.banner,\n      request: const AdRequest(),\n      listener: BannerAdListener(\n        onAdFailedToLoad: (ad, error) {\n          print(&apos;Banner ad failed to load: $error&apos;);\n          ad.dispose();\n        },\n      ),\n    );\n  }\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Update the &lt;code&gt;main.dart&lt;/code&gt; file to make use of the new Banner ads:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-2iuoVF wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;dart&quot; content=&quot;&amp;quot;Widget build(BuildContext context) {\n    if (_loading) {\n      return const Scaffold(\n        body: Center(child: CircularProgressIndicator()),\n      );\n    }\n\n    return Scaffold(\n      appBar: AppBar(\n        backgroundColor: Theme.of(context).colorScheme.inverseSurface,\n        title: const Text(&apos;Article&apos;),\n        actions: [\n          IconButton(\n            icon: Icon(\n              _isSubscribed ? Icons.star : Icons.star_border,\n              color: _isSubscribed ? Colors.amber : null,\n            ),\n            onPressed: _openSubscriptionScreen,\n            tooltip: _isSubscribed ? &apos;Ad free&apos; : &apos;Go Ad free&apos;,\n          ),\n        ],\n      ),\n      body: SingleChildScrollView(\n        padding: const EdgeInsets.all(16),\n        child: Column(\n          crossAxisAlignment: CrossAxisAlignment.start,\n          children: [\n            Text(\n              &apos;Understanding Flutter Development for Beginners&apos;,\n              style: Theme.of(context).textTheme.headlineMedium?.copyWith(\n                fontWeight: FontWeight.bold,\n              ),\n            ),\n            const SizedBox(height: 16),\n\n            _buildParagraph(\n              &apos;One of the main benefits of Flutter is the ability to share code &apos;\n              &apos;between platforms. This means you can maintain a single codebase for &apos;\n              &apos;both iOS and Android applications, significantly reducing development &apos;\n              &apos;time and effort.&apos;,\n            ),\n\n            if (!_isSubscribed) ...[\n              const SizedBox(height: 12),\n              const BannerAdWidget(),\n              const SizedBox(height: 12),\n            ],\n\n            _buildParagraph(\n              &apos;Flutter\\&apos;s widget-based architecture makes it easy to build &apos;\n              &apos;complex UIs with reusable components. Everything in Flutter is a &apos;\n              &apos;widget, from simple text elements to complex layouts.&apos;,\n            ),\n\n            if (!_isSubscribed) ...[\n              const SizedBox(height: 12),\n              const BannerAdWidget(),\n              const SizedBox(height: 12),\n            ],\n\n            _buildParagraph(\n              &apos;With Flutter, you can also target web and desktop platforms &apos;\n              &apos;from the same codebase, making it a truly cross-platform solution &apos;\n              &apos;for modern application development.&apos;,\n            ),\n          ],\n        ),\n      ),\n    );\n  }&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;After these code changes, your apps should look like this:&lt;br&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image&quot;&gt;&lt;img decoding=&quot;async&quot; src=&quot;https://lh7-rt.googleusercontent.com/docsz/AD_4nXc_sMytXKdYG6hAefkunEw02rkHsZ70IrZcKQvp1LU0TKv7Ek5iTCW_HaFrWaZenvQPrNyKC5U01VORqKA6qlThgffkHMrZl2XAt32hoKKdX4YNf0BWkwEaIDOQ7xyymX31SxaseQ?key=FPcGoCgoI6zqHGT6Kr6OUPtb&quot; alt=&quot;Screenshot of iOS simulator running the example app built for this tutorial.&quot;&gt;&lt;/figure&gt;


&lt;div class=&quot;lazyblock-dcadc5d83064-Z10SVt0 wp-block-lazyblock-dcadc5d83064&quot;&gt;&lt;blogposthowtostep level=&quot;h2&quot; title=&quot;Step 2: set up products&quot; summary=&quot;Set up products named ad_free_monthly for both iOS and Android , one entitlement called ad_free_entitlement, and group them together in RevenueCat.&quot; image-url=&quot;&quot;&gt;
&lt;/blogposthowtostep&gt;&lt;/div&gt;


&lt;p&gt;Once you’ve configured the store of your choice, or both in the previous steps, it’s time to set up Revenuecat. If you’re not familiar with Revenuecat, or time has passed since the last time you used it, &lt;a href=&quot;https://www.revenuecat.com/docs/getting-started/quickstart#2-product-configuration&quot;&gt;this quickstart guide&lt;/a&gt; will help you get up to speed.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;You need to configure your RevenueCat products, offerings and entitlements to have:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;One entitlement for the ad-free subscription level, using the identifier &lt;strong&gt;&lt;em&gt;ad_free_entitlement&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;Two separate products for App Store and Play Store, for example with identifier &lt;strong&gt;&lt;em&gt;ad_free_monthly&lt;/em&gt;&lt;/strong&gt; (learn more about the naming practices: &lt;a href=&quot;https://www.revenuecat.com/docs/getting-started/entitlements/ios-products&quot;&gt;iOS&lt;/a&gt;, &lt;a href=&quot;https://www.revenuecat.com/docs/getting-started/entitlements/android-products#tips-for-creating-robust-product-ids&quot;&gt;Android&lt;/a&gt;)&lt;/li&gt;



&lt;li&gt;Matching subscriptions in Play Store console and App Store connect with the same identifiers&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Remember to group your product under the entitlement you created. &amp;nbsp;&lt;/p&gt;


&lt;div class=&quot;lazyblock-dcadc5d83064-1A4jFg wp-block-lazyblock-dcadc5d83064&quot;&gt;&lt;blogposthowtostep level=&quot;h2&quot; title=&quot;Step 3: Add subscriptions to your Flutter app&quot; summary=&quot;Add subscriptions by installing RevenueCat SDKs purchases_flutter and purchases_flutter_ui adding the necessary code parts.&quot; image-url=&quot;&quot;&gt;
&lt;/blogposthowtostep&gt;&lt;/div&gt;


&lt;p&gt;Now that we have everything configured, it’s time to add &lt;code&gt;purchases_flutter&lt;/code&gt; and &lt;code&gt;purchases_flutter_ui&lt;/code&gt;; the Flutter client for RevenueCat&amp;nbsp;subscriptions and paywall UI components. Add the dependencies:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z6EVB2 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;# pubspec.yaml\ndependencies:\n  google_mobile_ads: ^6.0.0\n  purchases_flutter: ^8.10.5\n  purchases_ui_flutter: ^8.10.5\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;We want RevenueCat to be initialized when the application starts, so at the same time as we initialize the ads. Update SubscriptionManager:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-2sowkt wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;dart&quot; content=&quot;&amp;quot;import &apos;package:google_mobile_ads\/google_mobile_ads.dart&apos;;\nimport &apos;package:purchases_flutter\/purchases_flutter.dart&apos;;\nimport &apos;..\/config\/app_config.dart&apos;;\n\nclass SubscriptionManager {\n  static const String _apiKey = AppConfig.revenueCatApiKey;\n  static const String _entitlementId = AppConfig.entitlementId;\n  static const String _bannerAdUnitId = AppConfig.bannerAdUnitId;\n  \n  static final SubscriptionManager _instance = SubscriptionManager._internal();\n  factory SubscriptionManager() =&gt; _instance;\n  SubscriptionManager._internal();\n\n  bool _isInitialized = false;\n\n  Future&lt;void&gt; initialize() async {\n    if (_isInitialized) return;\n\n    try {\n      \/\/ Initialize RevenueCat\n      PurchasesConfiguration configuration = PurchasesConfiguration(_apiKey);\n      await Purchases.configure(configuration);\n      \n      \/\/ Initialize AdMob\n      await MobileAds.instance.initialize();\n      \n      _isInitialized = true;\n    } catch (e) {\n      print(&apos;Failed to initialize services: $e&apos;);\n    }\n  }\n\n  Future&lt;bool&gt; isSubscribed() async {\n    try {\n      CustomerInfo customerInfo = await Purchases.getCustomerInfo();\n      return customerInfo.entitlements.active.containsKey(_entitlementId);\n    } catch (e) {\n      print(&apos;Failed to check subscription status: $e&apos;);\n      return false;\n    }\n  }\n\n  BannerAd createBannerAd() {\n    return BannerAd(\n      adUnitId: _bannerAdUnitId,\n      size: AdSize.banner,\n      request: const AdRequest(),\n      listener: BannerAdListener(\n        onAdFailedToLoad: (ad, error) {\n          print(&apos;Banner ad failed to load: $error&apos;);\n          ad.dispose();\n        },\n      ),\n    );\n  }\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;You can use the RevenueCat public API key directly or use an app_config.dart file like in this example. If you see RevenueCat error logs in the console, review and fix them.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-checking-user-entitlements&quot;&gt;Checking user entitlements&lt;/h3&gt;



&lt;p&gt;To keep track of whether a user has purchased a subscription and is eligible for ad-free experience, we implement a helper service. Add a function for checking if user is subscribed:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-1T2LL4 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;dart&quot; content=&quot;&amp;quot;\/\/ subscription_manager.dart\n\n\/\/ existing code\n\nFuture&lt;bool&gt; isSubscribed() async {\n    try {\n      CustomerInfo customerInfo = await Purchases.getCustomerInfo();\n      return customerInfo.entitlements.active.containsKey(_entitlementId);\n    } catch (e) {\n      print(&apos;Failed to check subscription status: $e&apos;);\n      return false;\n    }\n  }\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-using-the-entitlement-status-in-your-ui&quot;&gt;Using the entitlement status in your UI&lt;/h3&gt;



&lt;p&gt;Before showing ads we need to check if user is subscribed:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z2nD68L wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;dart&quot; content=&quot;&amp;quot;import &apos;dart:io&apos;;\nimport &apos;package:flutter\/material.dart&apos;;\nimport &apos;package:purchases_ui_flutter\/purchases_ui_flutter.dart&apos;;\nimport &apos;services\/subscription_manager.dart&apos;;\nimport &apos;widgets\/banner_ad_widget.dart&apos;;\nimport &apos;config\/app_config.dart&apos;;\n\nvoid main() async {\n  WidgetsFlutterBinding.ensureInitialized();\n  \n  \n  \/\/ Initialize subscription manager\n  await SubscriptionManager().initialize();\n  \n  runApp(const MyApp());\n}\n\nclass MyApp extends StatelessWidget {\n  const MyApp({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    return MaterialApp(\n      title: AppConfig.appName,\n      theme: ThemeData(\n        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),\n        useMaterial3: true,\n      ),\n      home: const ArticlePage(),\n    );\n  }\n}\n\nclass ArticlePage extends StatefulWidget {\n  const ArticlePage({super.key});\n\n  @override\n  State&lt;ArticlePage&gt; createState() =&gt; _ArticlePageState();\n}\n\nclass _ArticlePageState extends State&lt;ArticlePage&gt; {\n  final SubscriptionManager _subscriptionManager = SubscriptionManager();\n  bool _isSubscribed = false;\n  bool _loading = true;\n\n  @override\n  void initState() {\n    super.initState();\n    _checkSubscriptionStatus();\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    if (_loading) {\n      return const Scaffold(\n        body: Center(child: CircularProgressIndicator()),\n      );\n    }\n\n    return Scaffold(\n      appBar: AppBar(\n        backgroundColor: Theme.of(context).colorScheme.inverseSurface,\n        title: const Text(&apos;Article&apos;),\n        actions: [\n          IconButton(\n            icon: Icon(\n              _isSubscribed ? Icons.star : Icons.star_border,\n              color: _isSubscribed ? Colors.amber : null,\n            ),\n            onPressed: _openSubscriptionScreen,\n            tooltip: _isSubscribed ? &apos;Ad free&apos; : &apos;Go Ad free&apos;,\n          ),\n        ],\n      ),\n      body: SingleChildScrollView(\n        padding: const EdgeInsets.all(16),\n        child: Column(\n          crossAxisAlignment: CrossAxisAlignment.start,\n          children: [\n            Text(\n              &apos;Understanding Flutter Development for Beginners&apos;,\n              style: Theme.of(context).textTheme.headlineMedium?.copyWith(\n                fontWeight: FontWeight.bold,\n              ),\n            ),\n            const SizedBox(height: 16),\n\n     \n            _buildParagraph(\n              &apos;Flutter is a popular framework for building mobile applications. It &apos;\n              &apos;allows developers to use Dart programming language along with native &apos;\n              &apos;platform capabilities to create apps for iOS and Android.&apos;,\n            ),\n\n            if (!_isSubscribed) ...[\n              const SizedBox(height: 12),\n              const BannerAdWidget(),\n              const SizedBox(height: 12),\n            ],\n\n    \n          ],\n        ),\n      ),\n    );\n  }\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-implement-purchasing-functionality&quot;&gt;Implement purchasing functionality&lt;/h3&gt;



&lt;p&gt;Now that we can check if a user has purchased a subscription, it’s time to implement the purchasing functionality. We can do this easily with RevenueCat paywalls, which you can then customize through RevenueCat’s dashboard. &lt;a href=&quot;https://www.revenuecat.com/docs/tools/paywalls&quot;&gt;Learn more about paywalls here&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;Add the code below to enable showing paywalls:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z2bRoKr wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;\/\/ Existing class and state declaration\nclass _ArticlePageState extends State&lt;ArticlePage&gt; {\n  final SubscriptionManager _subscriptionManager = SubscriptionManager();\n  bool _isSubscribed = false;\n  bool _loading = true;\n\n  @override\n  void initState() {\n    super.initState();\n    _checkSubscriptionStatus();\n  }\n\n  \/\/ Check if user has active entitlement\n  Future&lt;void&gt; _checkSubscriptionStatus() async {\n    final isSubscribed = await _subscriptionManager.isSubscribed();\n    if (mounted) {\n      setState(() {\n        _isSubscribed = isSubscribed;\n        _loading = false;\n      });\n    }\n  }\n\n  \/\/ Show RevenueCat paywall\n  Future&lt;void&gt; _purchaseSubscription() async {\n    try {\n      await RevenueCatUI.presentPaywall(); \/\/ Opens default paywall configured in RevenueCat\n\n      \/\/ Refresh subscription status after paywall closes\n      await _checkSubscriptionStatus();\n\n      if (mounted &amp;amp;&amp;amp; _isSubscribed) {\n        ScaffoldMessenger.of(context).showSnackBar(\n          const SnackBar(\n            content: Text(&apos;Subscription activated successfully!&apos;),\n            backgroundColor: Colors.green,\n          ),\n        );\n      }\n    } catch (e) {\n      if (mounted) {\n        ScaffoldMessenger.of(context).showSnackBar(\n          SnackBar(\n            content: Text(&apos;Failed to show paywall: $e&apos;),\n            backgroundColor: Colors.red,\n          ),\n        );\n      }\n    }\n  }\n@override\n  Widget build(BuildContext context) {\n    if (_loading) {\n      return const Scaffold(\n        body: Center(child: CircularProgressIndicator()),\n      );\n    }\n\n    return Scaffold(\n      appBar: AppBar(\n        backgroundColor: Theme.of(context).colorScheme.inverseSurface,\n        title: const Text(&apos;Article&apos;),\n        actions: [\n          IconButton(\n            icon: Icon(\n              _isSubscribed ? Icons.star : Icons.star_border,\n              color: _isSubscribed ? Colors.amber : null,\n            ),\n            onPressed: _openSubscriptionScreen,\n            tooltip: _isSubscribed ? &apos;Ad free&apos; : &apos;Go Ad free&apos;,\n          ),\n        ],\n      ),\n\nbody: SingleChildScrollView(\n        padding: const EdgeInsets.all(16),\n        child: Column(\n          crossAxisAlignment: CrossAxisAlignment.start,\n          children: [\n            Text(\n              &apos;Understanding Flutter Development for Beginners&apos;,\n              style: Theme.of(context).textTheme.headlineMedium?.copyWith(\n                fontWeight: FontWeight.bold,\n              ),\n            ),\n            const SizedBox(height: 16),\n\n            if (!_isSubscribed) ...[\n              SizedBox(\n                width: double.infinity,\n                child: ElevatedButton(\n                  onPressed: _purchaseSubscription,\n                  style: ElevatedButton.styleFrom(\n                    backgroundColor: Colors.green,\n                    foregroundColor: Colors.white,\n                    padding: const EdgeInsets.symmetric(vertical: 16),\n                    shape: RoundedRectangleBorder(\n                      borderRadius: BorderRadius.circular(8),\n                    ),\n                  ),\n                  child: const Text(\n                    &apos;Remove Ads - Subscribe Now&apos;,\n                    style: TextStyle(\n                      fontSize: 16,\n                      fontWeight: FontWeight.bold,\n                    ),\n                  ),\n                ),\n              ),\n              const SizedBox(height: 16),\n            ],\n\t\/\/... rest of the code\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Run the app on a real device, press the button, and complete the purchase flow. After a successful purchase, the app will update to remove ads and give the user the ad-free experience. &lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;576&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Rotato-Image-CD6B-1024x576.png&quot; alt=&quot;Final result, an app that shows both content and ads together and has a button for disabling the ads by subscribing.&quot; class=&quot;wp-image-44592&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Rotato-Image-CD6B-1024x576.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Rotato-Image-CD6B-300x169.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Rotato-Image-CD6B-768x432.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Rotato-Image-CD6B-1536x864.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Rotato-Image-CD6B-2048x1152.png 2048w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Rotato-Image-CD6B-71x40.png 71w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Rotato-Image-CD6B-696x392.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Rotato-Image-CD6B-560x315.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Rotato-Image-CD6B-526x296.png 526w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Rotato-Image-CD6B-840x472.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Rotato-Image-CD6B-80x45.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/Rotato-Image-CD6B-48x27.png 48w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-conclusion&quot;&gt;Conclusion&lt;/h2&gt;



&lt;p&gt;Great work! You’ve successfully built a Flutter app that lets users subscribe to unlock an ad-free experience. From integrating AdMob for ads to implementing subscriptions with RevenueCat, you now have a strong foundation for monetizing your app. From here, you can take things further—customize your paywall directly in the RevenueCat dashboard, experiment with different pricing strategies, or add premium features that offer even more value behind the subscription. This is just the beginning of what’s possible with a flexible, subscription-based model.&lt;br&gt;&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[How real demand turned a hobby app into a business]]></title><description><![CDATA[Why saying no to a buyout gave one indie developer his breakthrough]]></description><link>https://www.revenuecat.com/blog/growth/eric-duffet-spot-pattern-sub-club-podcast-2025/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/eric-duffet-spot-pattern-sub-club-podcast-2025/</guid><pubDate>Wed, 09 Jul 2025 10:28:15 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/eric-duffet-spot-pattern-sub-club-podcast-2025.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;We all know the saying: “If at first you don’t succeed, try, try again.” But this doesn’t always mean you should keep doing the same thing and hope your determination will eventually pay off — sometimes you have to give up on a bad idea and move on to a better one in order to find the success you’re looking for.&lt;/p&gt;



&lt;p&gt;That’s exactly what happened for &lt;a href=&quot;https://www.linkedin.com/in/eric-duffett/&quot;&gt;Eric Duffet&lt;/a&gt;, a high school teacher and indie app developer who created the golf GPS app &lt;a href=&quot;https://shotpattern.app/&quot;&gt;Shot Pattern&lt;/a&gt;. For Eric, the road to success wasn’t a straight line (not by a long shot). We recently hosted Eric on the &lt;a href=&quot;https://subclub.com/&quot;&gt;Sub Club podcast&lt;/a&gt;, where he shared all the ups and downs of his journey as a one-man-show indie app developer.&lt;/p&gt;



&lt;iframe loading=&quot;lazy&quot; width=&quot;100%&quot; height=&quot;180&quot; frameborder=&quot;no&quot; scrolling=&quot;no&quot; seamless=&quot;&quot; src=&quot;https://share.transistor.fm/e/2bf59b9d?color=FFFFFF&amp;amp;background=30343C&quot;&gt;&lt;/iframe&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;Turning a Side Project into a Six-Figure Subscription Business – Eric Duffett, Shot Pattern&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/VWWNRsLTJDM?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-a-lesson-in-product-market-fit&quot;&gt;&lt;strong&gt;A lesson in product-market fit&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Like a lot of indie developers, Eric started coding as a hobby. As a high school teacher and golf coach, Eric was first inspired to build an app when he noticed his students struggling with the combined pressures of homework, athletics, and applying for college scholarships. “I felt like they needed something to deal with the adversity they were facing in their sport… so I thought … ‘I want to build something that can help you perform better, build resilience, and build some mental hygiene.’ And so I started creating that app for them.” Eric took a Udemy course on app development and eventually launched &lt;a href=&quot;https://apps.apple.com/us/app/undaunted-golf/id1116731367&quot;&gt;Undaunted Golf&lt;/a&gt;, a meditation app for golfers.&lt;/p&gt;



&lt;p&gt;But what happened next is what Eric describes as “a lesson in what product-market fit &lt;em&gt;isn’t&lt;/em&gt;.” After launching Undaunted Golf, it just didn’t take off the way he expected. The more he talked to users, the more he heard that folks weren’t particularly interested in the product. After five years of working on the app, he decided to call it quits — and thought his career as an indie developer was over.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-taking-another-swing&quot;&gt;&lt;strong&gt;Taking another swing&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;But the story doesn’t end there. Through his experience with Undaunted Golf, Eric developed a love for building apps, eventually creating one for the high school where he works, doing some consulting work, and even applying for software developer jobs. Eventually, his love of golf inspired him to start another pet project: a golf GPS app he built to make it easier to judge golf course distances and aim his swings effectively. Eric originally built the app for himself, but after hearing lots of chatter in the golf community about how GPS can help golfers improve their game, he launched &lt;a href=&quot;https://shotpattern.app/&quot;&gt;Shot Pattern&lt;/a&gt; on the App Store hoping to passively earn $1,000/month or so to pay for his hobby.&lt;/p&gt;



&lt;p&gt;And this time, things were different. Almost immediately, Eric saw promising signs of adoption. “I didn’t have to work that hard to get the first downloads, to see early signs of monetization,” Eric said. “One of the best signs that something was working was that people were paying for it that I never heard from …&amp;nbsp; I was like, ‘This is not the same as before. This is working.’” Without realizing it, Eric had filled a growing need in the golf world. Hobbyists and &lt;a href=&quot;https://decade.golf/about/&quot;&gt;pros&lt;/a&gt; were already measuring golf course distances by hand with Google Maps — Shot Pattern just made it easier to do. As Eric put it, “[Instead of] me trying to force a new behavior upon people, [I was] just giving them an easier way to do what they already wanted to.”&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-bye-bye-birdie&quot;&gt;Bye, bye, birdie?&lt;/h2&gt;



&lt;p&gt;Four months after releasing the app, Eric received an offer from a company interested in buying Shot Pattern for $75,000. So he had a choice to make: take a $75,000 windfall or bet on the future success of his app and keep building. Unsure of what to do, Eric reached out to a few subscription app experts and the RevenueCat community asking for advice. At the same time, Eric compared some of his app’s early performance data to the latest &lt;a href=&quot;https://www.revenuecat.com/state-of-subscription-apps-2025/&quot;&gt;subscription app benchmarks&lt;/a&gt; and was able to determine a rough valuation for his business. He &lt;a href=&quot;https://www.revenuecat.com/blog/growth/why-i-didnt-sell-my-app-shot-pattern-story/&quot;&gt;turned down the acquisition offer&lt;/a&gt; and kept building.&lt;/p&gt;



&lt;p&gt;The bet paid off. After Eric implemented a scrappy, video-based content marketing strategy, Shot Pattern kept doing better and better — ultimately bringing in $185,000 in revenue in 2024.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-shot-pattern-s-story-shows&quot;&gt;What Shot Pattern’s story shows&lt;/h2&gt;



&lt;p&gt;Eric’s story just goes to show that product-market fit is about finding some kind of &lt;em&gt;pull&lt;/em&gt; in the market, not trying to push a solution onto users that they might not really want or need. No matter how great you think your app idea is, sometimes there just isn’t enough demand in the market to justify building it. So take it from Eric: don’t spend five years working on an app that’s never going to pay off. Move on to your next great idea — it could be the one that takes off.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Announcing Shipaton 2025: Build, ship, and win big!]]></title><description><![CDATA[Join the mobile hackathon that’s all about shipping… a ton.]]></description><link>https://www.revenuecat.com/blog/company/shipaton-2025/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/company/shipaton-2025/</guid><pubDate>Mon, 07 Jul 2025 13:07:00 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/hackathon-blog-header-blue.jpg" length="0" type="image/*"/><content:encoded>&lt;p&gt;At RevenueCat, we’re all about supporting developers to build and monetize amazing apps. After the overwhelming success of last year’s Shipaton, we’re thrilled to announce the return of our global hackathon-&lt;a href=&quot;https://shipaton.com&quot;&gt;Shipaton 2025&lt;/a&gt;.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;This &lt;strong&gt;August and September&lt;/strong&gt;, we’re inviting developers from all corners of the globe to ship new apps and compete for over &lt;strong&gt;$350,000&lt;/strong&gt; in cash prizes and truly unique rewards.&lt;/p&gt;



&lt;p&gt;Read on for more details, or go ahead and &lt;a href=&quot;https://revenuecat-shipaton-2025.devpost.com/&quot;&gt;sign up right now&lt;/a&gt;.&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; title=&quot;RevenueCat Shipaton 2025&quot; width=&quot;500&quot; height=&quot;281&quot; src=&quot;https://www.youtube.com/embed/-EoEwPFD3N0?feature=oembed&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-challenge&quot;&gt;The challenge&lt;/h2&gt;



&lt;p&gt;Your mission is simple:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Ship a brand-new app&lt;/strong&gt; to the iOS, Android, or Mac App Store between August 1st and September 30th, 2025.&lt;/li&gt;



&lt;li&gt;Integrate the &lt;strong&gt;RevenueCat SDK&lt;/strong&gt; to power at least one in-app or web purchase.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Our goal is to give you that final push to ship that project you’ve had in the back of your mind but never took the time to get started.&lt;/p&gt;



&lt;p&gt;&lt;em&gt;Note: Updates to previously released apps won’t qualify – it’s all about bringing something new to life!&lt;/em&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-bigger-and-better&quot;&gt;Bigger and better&lt;/h2&gt;



&lt;p&gt;Last year’s Shipaton sparked a frenzy of creativity and innovation across the internet. Developers blew us away by launching incredible apps, producing inspiring &lt;a href=&quot;https://www.youtube.com/results?search_query=shipaton&quot;&gt;YouTube series&lt;/a&gt;, flooding &lt;a href=&quot;https://x.com/search?q=%23Shipaton&quot;&gt;social media&lt;/a&gt; with #BuildInPublic journeys, and creating insightful shorts on TikTok and Instagram.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image&quot;&gt;&lt;img decoding=&quot;async&quot; src=&quot;https://lh7-rt.googleusercontent.com/docsz/AD_4nXecC30d3W4TQrQiUNjqfgQTlxgq1b08Se7MsbT0uNJAgafk-z3LnA8GhZQ3K-3kpiWkZhOozDXBnUqPbKEzwSTMH0ZQMDhdYMvOM2hjfbWYq1WZ0VwTbB7npsuQqCEGbSHJU6Ok?key=yAtrDiAG97MKnhNWrb2C2A&quot; alt=&quot;&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;You could receive a coveted “Shippy” award and your app displayed on the iconic “The One” billboard in Times Square!&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;Inspired by your amazing contributions, we’ve upped the ante for 2025:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Over &lt;strong&gt;$350,000 in cash prizes&lt;/strong&gt;.&lt;/li&gt;



&lt;li&gt;Winning apps featured prominently on a &lt;strong&gt;giant billboard in Times Square&lt;/strong&gt;.&lt;/li&gt;



&lt;li&gt;Trip to New York City with invites to RevenueCat’s &lt;a href=&quot;https://appgrowthannual.com/&quot;&gt;App Growth Annual&lt;/a&gt; conference.&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-categories-and-prizes&quot;&gt;&lt;strong&gt;Categories and prizes&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Our panel of expert judges will select winners across eight exciting categories:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;918&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/shipaton-categories-9-1024x918.png&quot; alt=&quot;&quot; class=&quot;wp-image-45365&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/shipaton-categories-9-1024x918.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/shipaton-categories-9-300x269.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/shipaton-categories-9-768x688.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/shipaton-categories-9-50x45.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/shipaton-categories-9-45x40.png 45w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/shipaton-categories-9-518x464.png 518w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/shipaton-categories-9-696x624.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/shipaton-categories-9-560x502.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/shipaton-categories-9-330x296.png 330w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/shipaton-categories-9-527x472.png 527w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/shipaton-categories-9-80x72.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/shipaton-categories-9-48x43.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/shipaton-categories-9.png 1040w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Grand Prize: Build &amp;amp; Grow Award&lt;/strong&gt; ($65,000): Goes to the app that releases early and iterates to grow their app the fastest. We want to hear about what you’ve done post-release to push your app growth to the next level.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;#BuildInPublic Award&lt;/strong&gt;: For developers who shared the most interesting development journey on social media. We’re looking for compelling lessons learned or clever ideas that came from engaging with the community.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Buzziest Launch Award:&lt;/strong&gt; Highlights teams that make the biggest splash during their launch (e.g., viral social campaigns, creative marketing stunts).&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;HAMM Award (Help Apps Make Money):&lt;/strong&gt;&amp;nbsp; RevenueCat exists to “Help Apps Make More Money”. This award goes to the project that designs the most robust and creative monetization strategy by mixing subscriptions, virtual currency, or other revenue streams.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Best Vibes Award:&lt;/strong&gt; Awarded to the app developer that shares the most compelling vibe-coding story using one of our vibe-coding app partners as part of your development journey. &amp;nbsp;The full list of eligible tools will be available on &lt;a href=&quot;https://revenuecat-shipaton-2025.devpost.com/&quot;&gt;DevPost&lt;/a&gt; before the event begins.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;RevenueCat Design Award: &lt;/strong&gt;For the most visually interesting apps – regardless of business potential. We’re looking for innovative ideas and/or beautiful app design and animations.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;RevenueCat Peace Prize: &lt;/strong&gt;Awarded to the project that provides the greatest social good. We’re looking for apps with big benefits to communities or society at large.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;OneSignal Boost Award: &lt;/strong&gt;Honors the app that shows the most creative or impactful use of messaging to elevate user engagement using &lt;a href=&quot;https://onesignal.com/&quot;&gt;OneSignal&lt;/a&gt;.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Kotlin Multiplatform Boost&amp;nbsp;Award:&lt;/strong&gt;&amp;nbsp;For the team that ships the best cross-platform app using&amp;nbsp;&lt;a href=&quot;https://www.jetbrains.com/kotlin-multiplatform/&quot;&gt;Kotlin Multiplatform&lt;/a&gt;&amp;nbsp;and/or&amp;nbsp;&lt;a href=&quot;https://www.jetbrains.com/compose-multiplatform/&quot;&gt;Compose Multiplatform&lt;/a&gt;.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Staff &amp;amp; Sponsors Award:&lt;/strong&gt; A special category just for employees at RevenueCat and our amazing sponsors who couldn’t resist joining the fun. While they’re not eligible for cash prizes, we still want to celebrate the coolest thing they ship during the event and give them a shot at glory on the Times Square billboard.&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-prize-structure&quot;&gt;&lt;strong&gt;Prize structure&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Here’s how the prizes break down:&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-grand-prize-winner&quot;&gt;🏆 &lt;strong&gt;Grand Prize Winner&lt;/strong&gt;&lt;/h4&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;$65,000&lt;/li&gt;



&lt;li&gt;Trip to New York City to attend the RevenueCat App Growth Annual conference&lt;/li&gt;



&lt;li&gt;Custom Shippy trophy (presented live on stage!)&lt;/li&gt;



&lt;li&gt;App featured on a massive Times Square billboard&lt;/li&gt;
&lt;/ul&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-all-other-categories-except-onesignal-boost&quot;&gt;🥇&lt;strong&gt;All Other Categories&lt;/strong&gt; (except OneSignal Boost)&lt;/h4&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;1st Place: &lt;/strong&gt;$15,000 + custom Shippy trophy + Times Square billboard feature&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;2nd Place:&lt;/strong&gt; $10,000&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;3rd Place:&lt;/strong&gt; $5,000&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The &lt;strong&gt;#BuildInPublic Award&lt;/strong&gt; 1st-place winner will also receive a trip to New York City for App Growth Annual and trophy presentation.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot; id=&quot;h-onesignal-boost-award&quot;&gt;📣 &lt;strong&gt;OneSignal Boost Award&lt;/strong&gt;&lt;/h4&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;1st Place:&lt;/strong&gt; $20,000&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;2nd Place:&lt;/strong&gt; $15,000&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;3rd Place:&lt;/strong&gt; $10,000&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;4th Place:&lt;/strong&gt; $5,000&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;5th Place:&lt;/strong&gt; $5,000&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-supported-by-the-industry&quot;&gt;Supported by the industry&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;329&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/shipaton-sponsors-20-1024x329.png&quot; alt=&quot;&quot; class=&quot;wp-image-45367&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/shipaton-sponsors-20-1024x329.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/shipaton-sponsors-20-300x96.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/shipaton-sponsors-20-768x247.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/shipaton-sponsors-20-50x16.png 50w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/shipaton-sponsors-20-125x40.png 125w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/shipaton-sponsors-20-696x224.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/shipaton-sponsors-20-560x180.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/shipaton-sponsors-20-840x270.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/shipaton-sponsors-20-80x26.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/shipaton-sponsors-20-48x15.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/shipaton-sponsors-20.png 1512w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;For Shipaton 2025 we reached out to our favorite tech partners and asked them to contribute. These sponsors chipped in for the prize pool, will be contributing tips and tricks during official Shipaton livestreams, and have generously contributed to something new for Shipaton 2025:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;introducing-ship-kit-freebies-for-every-shipaton-participant&quot;&gt;Introducing, Ship Kit: Freebies for every Shipaton participant&lt;/h3&gt;



&lt;p&gt;This year, we’re introducing Ship Kit. A digital bundle of exclusive perks and tools from our sponsors to help power your app shipping journey. We’ll be revealing more details soon, but all you need to do to receive a Ship Kit is &lt;a href=&quot;https://revenuecat-shipaton-2025.devpost.com/&quot;&gt;sign up to participate in Shipaton&lt;/a&gt;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-shipaton-irl-events-near-you&quot;&gt;Shipaton IRL: Events near you&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image&quot;&gt;&lt;img decoding=&quot;async&quot; src=&quot;https://lh7-rt.googleusercontent.com/docsz/AD_4nXdCwHHXWInTqvuDv2viIRHH4FFWy8Znf7orVHLA-OHijbltO8v3aof4X2muMy6K5GaIBw6SlcPoxTjETt7At9qIMd-A4gnCK34oD6HVt4oTZeXHVfwVea-tu1l5Yi5nNBklynwzSw?key=yAtrDiAG97MKnhNWrb2C2A&quot; alt=&quot;&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Photo from last year’s Shipaton x &lt;/em&gt;&lt;a href=&quot;https://melting-hack.tokyo/&quot;&gt;&lt;em&gt;MeltingHack&lt;/em&gt;&lt;/a&gt;&lt;em&gt; event in Tokyo.&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;We’re excited to take Shipaton directly to developers around the world with Shipaton IRL – a series of in-person and virtual events designed to connect, inspire, and educate:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Kickoff Party&lt;/strong&gt;: Join us August 1st at our &lt;a href=&quot;https://app.getriver.io/beta/events/vibe-coding-popup-catfe-tokyo-shipaton-kickoff-iyc&quot;&gt;pop-up Catfe&lt;/a&gt; in Tokyo, Japan.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Local Events&lt;/strong&gt;: Including &lt;a href=&quot;https://lu.ma/e5iz710q&quot;&gt;Core Coffee Shipaton Edition&lt;/a&gt; in Vancouver, Canada, regular co-working spaces with &lt;a href=&quot;https://netaville.mk/details/event/bf1f7b6b-6e68-46df-a0ea-1a44db4a4ecc&quot;&gt;CocoaHeadsMK&lt;/a&gt; in Skopje, Macedonia, and a Shipaton Showcase with &lt;a href=&quot;https://www.meetup.com/mobilewarsaw/&quot;&gt;Mobile Warsaw&lt;/a&gt; in Poland.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Online Events&lt;/strong&gt;: &lt;a href=&quot;https://lu.ma/oyvtw770&quot;&gt;CommunityKit’s AppJam&lt;/a&gt; will help you jumpstart your Shipaton journey.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Check out our &lt;a href=&quot;https://app.getriver.io/shipaton&quot;&gt;events page&lt;/a&gt; regularly, as new events are being added every day!&lt;/p&gt;



&lt;p&gt;Want to host an in-person Shipaton event yourself? &lt;a href=&quot;https://forms.gle/De31seRPX1TfrpRX7&quot;&gt;Apply now&lt;/a&gt; – we’d love to support you. We have special meetup support boxes ready to ship to you and your community.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-join-the-conversation-on-discord&quot;&gt;Join the conversation on Discord!&lt;/h2&gt;



&lt;p&gt;Shipaton isn’t just about shipping code – &lt;strong&gt;it’s about community&lt;/strong&gt;. Whether you’re brainstorming your first idea or prepping for launch day, the official &lt;a href=&quot;https://discord.gg/shipaton&quot;&gt;Shipaton Discord&lt;/a&gt; is the place to connect, collaborate, and share the journey.&lt;/p&gt;



&lt;p&gt;Inside, you’ll find fellow developers from around the world debugging code, creating paywall experiments, discussing launch strategies, and more. Looking to form a team? Need quick feedback? Want to hang out with other shippers? You’ll find it here.&lt;/p&gt;



&lt;p&gt;We’ve also created a dedicated &lt;strong&gt;#post-engagement-boost&lt;/strong&gt; channel where you can share your YouTube videos, Tweets, Reddit posts or other #BuildInPublic content so other participants can like, comment or share to help you reach a bigger audience. There’s also a dedicated #launch-day channel for you to share your go-live and get some community support. It’s all about creating a positive, encouraging space where we lift each other up – and help each other ship.&lt;/p&gt;



&lt;p&gt;Come say hi 👋 and make the most of Shipaton!&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-ready-set-ship&quot;&gt;Ready, set, ship!&lt;/h2&gt;



&lt;p&gt;Submissions open on &lt;strong&gt;August 1st and close on September 30th&lt;/strong&gt;. Be sure to carefully review all submission requirements to ensure your app qualifies.&lt;/p&gt;



&lt;p&gt;We’re beyond excited to see what the global developer community creates this year. Visit &lt;a href=&quot;https://shipaton.com/&quot;&gt;shipaton.com&lt;/a&gt; for detailed rules, submission guidelines, or skip ahead and &lt;a href=&quot;https://revenuecat-shipaton-2025.devpost.com/&quot;&gt;register today&lt;/a&gt;. We’ll keep you updated via the email address you use there.&lt;/p&gt;



&lt;p&gt;Let’s get shipping!&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Charlie Chapman&lt;/strong&gt;&lt;br&gt;&lt;em&gt;Captain of the Shipaton&lt;/em&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Scaling UA without wrecking your conversion rate: A Meta campaign playbook]]></title><description><![CDATA[A structured testing system helped one app lower cost-per-trial while targeting its most profitable users]]></description><link>https://www.revenuecat.com/blog/growth/high-velocity-creative-testing-framework-apps-meta/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/high-velocity-creative-testing-framework-apps-meta/</guid><pubDate>Thu, 03 Jul 2025 10:12:44 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/high-velocity-creative-testing-framework-apps-meta.png" length="0" type="image/*"/><content:encoded>&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;: Meta UA campaign performance can be improved by using a high-velocity creative testing framework that separates proven ads (BAU) from experimental creatives. This structure enables rapid iteration, controlled delivery, and reduced cost per trial (CPT) without sacrificing trial-to-subscription conversion. Key tactics include ICE scoring, 10,000-impression thresholds, and placement monitoring to maintain targeting accuracy and algorithm efficiency.&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;At this point, we all know that targeting in your UA campaigns is done through creatives, not through audience settings (I think I’ve even repeated this sentence in some of my articles already).&lt;br&gt;&lt;br&gt;And although you can still achieve success with narrower audiences, you’ll eventually hit a ceiling when you try to scale. In this case, if going to broad audiences allows you to grow, having a good set of creatives and enough creative testing volume becomes the key that unlocks profitable scale.&lt;/p&gt;



&lt;p&gt;In this article, I’ll show how a high-velocity creative testing framework helped me scale a subscription app with Meta campaigns – while driving the cost per trial (the event we optimized for) to a level they hadn’t reached even with lower spend.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;491&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-cpt-vs-spend-line-chart-1024x491.png&quot; alt=&quot;Line chart showing how cost per trial decreased while ad spend increased from Jan–May 2025.
&quot; class=&quot;wp-image-43431&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-cpt-vs-spend-line-chart-1024x491.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-cpt-vs-spend-line-chart-300x144.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-cpt-vs-spend-line-chart-768x368.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-cpt-vs-spend-line-chart-1536x737.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-cpt-vs-spend-line-chart-83x40.png 83w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-cpt-vs-spend-line-chart-696x334.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-cpt-vs-spend-line-chart-560x269.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-cpt-vs-spend-line-chart-840x403.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-cpt-vs-spend-line-chart-80x38.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-cpt-vs-spend-line-chart-48x23.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-cpt-vs-spend-line-chart.png 1999w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;strong&gt;Cost per trial dropped as spend increased&lt;/strong&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-was-the-situation-before-i-took-over&quot;&gt;What was the situation before I took over?&lt;/h2&gt;



&lt;p&gt;Before explaining how to create this framework to accelerate your creative testing and generate positive growth for your app, let me tell you that having a good product that converts well is key. In this case, this subscription app was offering a 14-day free trial that worked well during the previous year but was struggling to grow in the first half of this year.&lt;/p&gt;



&lt;p&gt;With such a long free trial, we couldn’t optimize for subscriptions directly—the attribution window on most ad networks maxes out at 7 days post-click. So we used free trials as our proxy event. Our goal: scale spend while lowering cost per trial (CPT), without hurting the conversion rate from trial to subscription.&lt;/p&gt;



&lt;p&gt;Right now in most ad networks, decreasing the CPA of a proxy event like trial isn’t hard. You simply need to build the creative framework that we’re going to explain in this article (or something similar) and also have a daily budget that feeds the algorithm with constant, quality signals (what Thomas Petit recently described as &lt;a href=&quot;https://www.youtube.com/live/nm2RngDr2AY&quot;&gt;signal engineering&lt;/a&gt;).&lt;/p&gt;



&lt;p&gt;However, there’s an important catch in this process.&lt;/p&gt;



&lt;p&gt;Lowering the cost per trial often comes from targeting younger audiences that have lower purchase intent, which usually hurts the final subscription conversion rate – and remember, we couldn’t affect this CVR if we wanted to achieve profitable growth, so we had to keep targeting our core audience (primarily men over 45).&lt;/p&gt;



&lt;p&gt;I’ve seen this pattern of Meta optimizing towards upper-funnel events repeatedly, and if you don’t keep an eye on the age and placement distribution of your campaigns, you will end up worsening your overall ROAS, although your cost per trial goes down.&lt;/p&gt;



&lt;p&gt;This means that, apart from creating the framework for the creatives, we also had to monitor the delivery of our campaigns constantly to be sure that our target audience was still the main objective for our new campaigns and creatives.&lt;/p&gt;



&lt;p&gt;With all that being said, it was time to check the campaigns, and what I found is also one of the problems that many UA managers face in Meta ads: only one creative from the few they had was gathering most of the impressions and spend.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;468&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-ad-spend-distribution-table-1024x468.png&quot; alt=&quot;Spend breakdown across three ads in Meta, showing one creative receiving the vast majority of budget.&quot; class=&quot;wp-image-43490&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-ad-spend-distribution-table-1024x468.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-ad-spend-distribution-table-300x137.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-ad-spend-distribution-table-768x351.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-ad-spend-distribution-table-1536x702.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-ad-spend-distribution-table-88x40.png 88w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-ad-spend-distribution-table-696x318.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-ad-spend-distribution-table-560x256.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-ad-spend-distribution-table-840x384.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-ad-spend-distribution-table-80x37.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-ad-spend-distribution-table-48x22.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-ad-spend-distribution-table.png 1703w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;strong&gt;Meta optimized all spend to a single ad&lt;/strong&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;Does it sound familiar to you?&lt;/p&gt;



&lt;p&gt;Well, this is just Meta optimizing towards one creative simply because the algorithm finds better upper-funnel metrics on it (CTR, hook rate, hold rate) than other ads.&lt;/p&gt;



&lt;p&gt;We had a bunch of new ads ready to test and scale, so we had to create a new strategy that could prevent us from such a situation while we also scaled the app under the conditions I explained above. So we simply changed the campaign setup.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;463&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-old-campaign-setup-diagram-1024x463.png&quot; alt=&quot;Diagram of a previous Meta campaign setup with a single broad ad group serving multiple creatives.&quot; class=&quot;wp-image-43492&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-old-campaign-setup-diagram-1024x463.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-old-campaign-setup-diagram-300x136.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-old-campaign-setup-diagram-768x347.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-old-campaign-setup-diagram-88x40.png 88w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-old-campaign-setup-diagram-696x315.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-old-campaign-setup-diagram-560x253.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-old-campaign-setup-diagram-840x380.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-old-campaign-setup-diagram-80x36.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-old-campaign-setup-diagram-48x22.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-old-campaign-setup-diagram.png 1482w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;strong&gt;The old setup relied on Meta to pick winners&lt;/strong&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;Here’s what the original setup looked like. They were relying on Meta’s algorithm to choose the top-performing creative. This can work for smaller apps with tight budgets if you rotate ads regularly and keep a close eye on CPA and targeting.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-to-create-a-high-velocity-creative-testing-framework-to-scale-your-app&quot;&gt;How to create a high-velocity creative testing framework to scale your app&lt;/h2&gt;



&lt;p&gt;When you have the resources to create new assets continuously and your goal is to scale through profitable growth, you need a setup that allows you to move fast with both variables: creatives and budgets. With this in mind, I built a new structure to support them both:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;386&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-new-testing-framework-diagram-1024x386.png&quot; alt=&quot;Visual framework showing a high-velocity creative testing setup with BAU and multiple testing ad groups.
&quot; class=&quot;wp-image-43494&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-new-testing-framework-diagram-1024x386.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-new-testing-framework-diagram-300x113.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-new-testing-framework-diagram-768x290.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-new-testing-framework-diagram-1536x579.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-new-testing-framework-diagram-106x40.png 106w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-new-testing-framework-diagram-696x263.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-new-testing-framework-diagram-560x211.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-new-testing-framework-diagram-840x317.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-new-testing-framework-diagram-80x30.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-new-testing-framework-diagram-48x18.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-new-testing-framework-diagram.png 1999w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;strong&gt;How the new testing setup works&lt;/strong&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;With this setup, instead of relying on the algorithm to pick the creative, we had control over everything: data, creatives, budgets, and testing velocity. The functioning of this setup was quite straightforward:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;We created one “winning” ad group with all the winning assets that they had detected before I joined. This ad group had the majority of the budget, as we already knew that the creatives were producing a good cost per trial and they also targeted our audience segment efficiently (so our conversion rate from free trial to subscription was not affected negatively).&lt;/li&gt;



&lt;li&gt;We created 3 testing ad groups which always had different creatives. The goal of this ad group was always to nurture the BAU ad group with new winning ads and also to serve as the engine of the high-velocity creative testing framework. The more budget we could put on these ad groups, the faster we could test new variants.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The day-to-day management of such a setup was simple:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;We checked the BAU ad group and monitored the cost per trial. If CPT was 20% above baseline during the last 2 days, we paused that winner and put a new winner from the testing ad groups.&lt;/li&gt;



&lt;li&gt;We checked every testing ad group, and if CPT was on the baseline or slightly better and it was targeting our target audience after achieving at least 10,000 impressions, we moved it to the BAU ad group if there was any slot available. If not, the creative was in reserve until a new slot was available. (In these cases, you can add more BAU ad groups with more winning assets if you have more budget, but that was not our case, so we had to go a bit slower – that’s why I always say that velocity depends on the size of your pocket mostly.)&lt;/li&gt;



&lt;li&gt;If any of the creatives within the testing ad groups were not receiving spend after being active for 2 days or had a bad cost per trial during the same period, we simply paused that creative and uploaded a new one.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;With this setup, we were able to test 30+ creatives and to detect at least 2–3 winners per week. This allowed us to scale the BAU ad group and generate the trend that you can see in the beginning of the article: scaling the spend while we decreased the cost per trial.&lt;/p&gt;



&lt;p&gt;And the most important part is we drastically changed the placement distribution with this setup:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;494&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-placement-shift-line-chart-1024x494.png&quot; alt=&quot;Line chart showing increased impressions in Facebook Feed and Reels after campaign structure changes.&quot; class=&quot;wp-image-43496&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-placement-shift-line-chart-1024x494.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-placement-shift-line-chart-300x145.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-placement-shift-line-chart-768x370.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-placement-shift-line-chart-1536x741.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-placement-shift-line-chart-83x40.png 83w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-placement-shift-line-chart-696x336.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-placement-shift-line-chart-560x270.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-placement-shift-line-chart-840x405.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-placement-shift-line-chart-80x39.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-placement-shift-line-chart-48x23.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/meta-placement-shift-line-chart.png 1999w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;strong&gt;Testing velocity drove more efficient placements&lt;/strong&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-biggest-win-placement-distribution&quot;&gt;&lt;strong&gt;The biggest win: placement distribution&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;This was, without any doubt, the biggest win of the whole strategy: all our money started to be spent in the placements where our core audience spent time in social media – Facebook – and that allowed us to:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Decrease the cost per trial by 29%&lt;/li&gt;



&lt;li&gt;Increase trial-to-subscription conversion by 2%&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Obviously, apart from iterating the campaigns as explained above, we were continuously monitoring how the conversion rate from free trial to subscription was performing for every single daily cohort. This was completely necessary to be sure that the campaign data was actually confirming our hypothesis about the correlation between the placement and the purchase intention of our users.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-managing-creatives-how-the-system-runs&quot;&gt;&lt;strong&gt;Managing creatives: how the system runs&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;Once we had the setup in place, we needed a way to analyze, iterate, and manage creatives on a daily basis.&lt;/p&gt;



&lt;p&gt;The rules for moving creatives between groups were simple:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Cost per Trial needs to be equal or better than the baseline after achieving 10,000 impressions (just to be sure that performance is sustained by solid data)&lt;/li&gt;



&lt;li&gt;The placement distribution of that creative must be clearly focused on your target audience (in my case, Facebook)&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;With these two conditions, we created a spreadsheet where we tracked the status of the creatives and their performance. Every time that we found a winner, we created a new tab within the spreadsheet to work on some iterations that could work as new winners:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;152&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/creative-tracking-ice-score-sheet-1024x152.png&quot; alt=&quot;Spreadsheet showing creative variants, ICE scores, and performance metrics to support creative testing decisions.
&quot; class=&quot;wp-image-43498&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/creative-tracking-ice-score-sheet-1024x152.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/creative-tracking-ice-score-sheet-300x45.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/creative-tracking-ice-score-sheet-768x114.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/creative-tracking-ice-score-sheet-1536x228.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/creative-tracking-ice-score-sheet-125x19.png 125w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/creative-tracking-ice-score-sheet-696x103.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/creative-tracking-ice-score-sheet-560x83.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/creative-tracking-ice-score-sheet-840x125.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/creative-tracking-ice-score-sheet-80x12.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/creative-tracking-ice-score-sheet-48x7.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/creative-tracking-ice-score-sheet.png 1999w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;strong&gt;Creative tracker used to prioritize and score iterations&lt;/strong&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;As you can see, each winner could have multiple iterations. We normally produced some iterations completely from scratch, some were generated by ChatGPT, and others were inspired by looking at the competitors. It doesn’t matter how: the important thing here is to produce enough iterations of the winner to be completely sure that you milk that concept to the maximum.&lt;/p&gt;



&lt;p&gt;Once we had some ideas to iterate, we just filled out the template – as you can see in the screenshot. In this case, apart from the generic information about the name of the ad, language, format, etc, we had to fill out an ICE SCORE for each iteration according to our experience with other ads.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Putting an ICE SCORE was crucial to prioritize the order of the creatives and it actually worked as a filter when one spot was available in the BAU ad group. Thanks to this system, scalability was achieved even faster because the iterations with more potential were run before other iterations, feeding the whole system with more potential winners at a higher pace.&lt;/p&gt;



&lt;p&gt;Once we tested the iterations, we also put the main engagement metrics next to the iteration and compared them with the metrics of the original winning asset. With this quick analysis, we were able to see if the ideas we were developing were actually having the effect we were hoping for.&lt;/p&gt;



&lt;p&gt;For example, if we had an iteration where the main change was the hook, we expected that the hook rate in that iteration would be higher than in the original winning asset. Or if we changed the content of the video to retain more users, we expected to have a higher hold rate than in the winning concept.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-conclusion&quot;&gt;Conclusion&lt;/h2&gt;



&lt;p&gt;With this well-structured framework, you can really nurture your campaigns with the best assets possible, giving the algorithm the right conditions to hit your CPA goals.&lt;/p&gt;



&lt;p&gt;Of course, this process takes time and constant analysis across your campaigns, creatives, and product. But if you have the resources to implement it, your chances of achieving profitable growth go way up – just like they did for this company.&lt;/p&gt;



&lt;p&gt;As I mentioned above, the more budget you have, the faster you can move with the testing. In our case, we were limited to one BAU ad group, but if you have higher budgets, you can run multiple BAU and testing groups in parallel, giving you more slots to scale and test every day.&lt;/p&gt;



&lt;p&gt;I hope this case study gives you a few ideas to test and maybe a faster way to scale profitably!&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Navigating Google Play’s 14-Day testing rule: a Shipaton survival guide]]></title><description><![CDATA[This article explains Google Play’s 14-day testing rule and how to start the clock immediately to ensure it doesn’t delay your submission.]]></description><link>https://www.revenuecat.com/blog/engineering/google-play-14-day/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/google-play-14-day/</guid><pubDate>Thu, 03 Jul 2025 01:09:22 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/1.-Navigating-Google-Plays-14-Day-testing-rule_-a-Shipaton-survival-guide.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;You’re in the final stretch of the &lt;a href=&quot;https://www.shipaton.com/&quot;&gt;Shipaton&lt;/a&gt;. Your app is taking shape, the code is coming together, and you’re excited to hit that “Publish” button. But wait..! What’s this about a mandatory 14-day testing period?&lt;/p&gt;



&lt;p&gt;For many new developers, this requirement can feel like an unexpected roadblock. Don’t let it be! This guide will explain what it is and how to get the clock started immediately so it doesn’t stop you from submitting in time.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-is-the-14-day-testing-requirement&quot;&gt;What is the 14-Day testing requirement?&lt;/h2&gt;



&lt;p&gt;To improve app quality and prevent malicious software, Google implemented a policy for new developers.&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Who it affects:&lt;/strong&gt; Developers with personal Play Console accounts created after November 13, 2023.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;The requirement:&lt;/strong&gt; Before you can apply to publish your app to production (for the whole world to see), you must run a &lt;strong&gt;closed test&lt;/strong&gt; for your app with &lt;strong&gt;at least 12 testers&lt;/strong&gt; for &lt;strong&gt;14 continuous days&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The goal is to ensure your app has been reviewed by real people and is stable before it reaches a wider audience. For a time-sensitive event like a Shipaton, this means you can’t wait until the last day to start the process.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-critical-step-start-the-clock-on-day-one&quot;&gt;The critical step: start the clock on day one!&lt;/h2&gt;



&lt;p&gt;The most important takeaway is this: &lt;strong&gt;the 14-day countdown doesn’t start until your test is properly set up and active.&lt;/strong&gt; You need to do this as soon as you have something literally “anything” to upload.&lt;/p&gt;



&lt;p&gt;Follow these steps on the first day of the Shipaton, even with your most basic “hello world” version of the app.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-1-create-a-closed-test-track&quot;&gt;Step 1: Create a closed test track&lt;/h3&gt;



&lt;p&gt;In your Google Play Console, go to your app, then find the Test and release &amp;gt; Testing section in the left-hand menu and select Closed testing. Create a new track. This is where your pre-release version will live.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;281&quot; height=&quot;409&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/Screenshot-2025-06-27-at-11.05.54 AM.png&quot; alt=&quot;&quot; class=&quot;wp-image-43344&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/Screenshot-2025-06-27-at-11.05.54 AM.png 281w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/Screenshot-2025-06-27-at-11.05.54 AM-206x300.png 206w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/Screenshot-2025-06-27-at-11.05.54 AM-27x40.png 27w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/Screenshot-2025-06-27-at-11.05.54 AM-203x296.png 203w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/Screenshot-2025-06-27-at-11.05.54 AM-55x80.png 55w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/Screenshot-2025-06-27-at-11.05.54 AM-33x48.png 33w&quot; sizes=&quot;auto, (max-width: 281px) 100vw, 281px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;step-2-upload-your-first-build-apk-or-aab&quot;&gt;Step 2: Upload your first build (APK or AAB)&lt;/h3&gt;



&lt;p&gt;Your app doesn’t need to be finished! As soon as you have a build that can be installed and opened, upload it to your new closed test track. This is the crucial step that makes the test “active.” You can (and should) upload new, improved versions to this same track throughout the Shipaton.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;step-3-create-your-tester-email-list&quot;&gt;Step 3: Create your tester email list&lt;/h3&gt;



&lt;p&gt;In your closed test track settings, you’ll see an option to manage testers. You can create a new email list. You will need to add the Gmail addresses of at least 12 people to this list.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;step-4-get-your-testers-to-opt-in&quot;&gt;Step 4: Get your testers to opt-in&lt;/h3&gt;



&lt;p&gt;This is the final, crucial piece. After adding testers to your list, the Play Console will provide a unique opt-in link. You must share this link with your 12+ testers.&lt;/p&gt;



&lt;p&gt;Here’s what they need to do:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Click the link on their Android device.&lt;/li&gt;



&lt;li&gt;Follow the prompts to “Become a Tester.”&lt;/li&gt;



&lt;li&gt;Once they’ve opted in, they will be able to find and download your app from the Google Play Store.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;The 14-day period of “continuous testing” begins once your test is active with a build and you have your group of opted-in testers.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-to-find-12-testers-quickly&quot;&gt;How to find 12 testers quickly&lt;/h2&gt;



&lt;p&gt;This can be the hardest part, so let’s think creatively:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Fellow Shipaton participants:&lt;/strong&gt; Your fellow hackers are in the same boat! Offer to be a tester or exchange your testers with fellow Shipaton participants on our &lt;a href=&quot;https://discord.gg/vnFGZcKW&quot;&gt;Discord channel&lt;/a&gt; (#looking-for-google-play-tester) for their app if they’ll be a tester for yours. This is the fastest and most effective method.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Friends &amp;amp; family:&lt;/strong&gt; The classic go-to. Send them the opt-in link and simple instructions.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Online communities:&lt;/strong&gt; There are communities on Reddit (like &lt;a href=&quot;https://www.reddit.com/r/AndroidAppTesters/&quot;&gt;r/androiddevtesters&lt;/a&gt;), Discord, and Slack dedicated to app testing. Be cautious, but they can be a great resource for finding willing participants.&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;what-to-do-during-the-14-days&quot;&gt;What to do during the 14 days&lt;/h2&gt;



&lt;p&gt;The clock is ticking, but you’re not just idly waiting.&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Keep building:&lt;/strong&gt; Continue coding and finishing your app.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Push updates:&lt;/strong&gt; As you complete features, push new builds to the same closed test track. This shows Google your app is under active development and gives your testers an improved version to try.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Gather feedback:&lt;/strong&gt; Use this as a real-world opportunity to get feedback on what you’ve built.&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;dont-let-it-stop-your-shipping&quot;&gt;Don’t let it stop your shipping&lt;/h2&gt;



&lt;p&gt;The 14-day testing requirement is a hurdle, not a wall. By starting your closed test on the very first day of the Shipaton, you ensure the waiting period happens &lt;em&gt;while&lt;/em&gt; you’re still building and shipping. Plan ahead, and this administrative step won’t get in the way of your submission.&lt;/p&gt;



&lt;p&gt;Good luck, and happy shipping!&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Gamification in apps: A complete guide to using motivation to drive real value]]></title><description><![CDATA[Why streaks fall short and 11 apps getting gamification right]]></description><link>https://www.revenuecat.com/blog/growth/gamification-in-apps-complete-guide/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/gamification-in-apps-complete-guide/</guid><pubDate>Tue, 01 Jul 2025 09:47:10 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/gamification-in-apps-complete-guide.png" length="0" type="image/*"/><content:encoded>&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;&lt;/blockquote&gt;



&lt;p&gt;Confession time: I had a two-week addiction to the mobile game &lt;a href=&quot;https://playrix.com/games/township&quot;&gt;Township&lt;/a&gt;. This isn’t the kind of thing you’re supposed to admit, but I fall victim to these apps too. The ad popped up on Meta, and it made me nostalgic for the days I played &lt;em&gt;Age of Empires&lt;/em&gt; and &lt;em&gt;Zeus&lt;/em&gt;. So I figured, “It’s free, what’s the harm?” That’s when things started to go downhill…&lt;/p&gt;



&lt;p&gt;For those of you who haven’t fallen for the trap, aka &lt;a href=&quot;https://www.pocketgamer.biz/playrix-celebrates-10-years-of-township-and-major-2-billion-revenue/&quot;&gt;a mobile game that’s part of a $2 billion gaming empire&lt;/a&gt;, the way it works is simple: you are the proud owner of a little plot of land. You farm to earn money, and you use that money to expand your town by buying houses, expanding your territory, unlocking more farmland, and so on. The catch? You need to wait for your crops to grow before you can earn money. So there I was, obsessively harvesting like a maniac, desperate to scrape together enough to expand my little empire.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;461&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-farm-1024x461.jpg&quot; alt=&quot;Overview of a Township farm&quot; class=&quot;wp-image-43355&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-farm-1024x461.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-farm-300x135.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-farm-768x345.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-farm-1536x691.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-farm-89x40.jpg 89w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-farm-696x313.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-farm-560x252.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-farm-840x378.jpg 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-farm-80x36.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-farm-48x22.jpg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-farm.jpg 1999w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Overview of a Township farm&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;I was growing digital corn, carrots, and wheat like there was no tomorrow. The gamification was next-level. It threw everything at me: the usual streaks and badges, sure, but also internal currency (hello, Township Cash), leadership boards, and even mini-games within the game. And it &lt;em&gt;worked&lt;/em&gt;.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;I’d already banned myself from using it during work, but somehow my mornings, evenings, and, &lt;em&gt;fine&lt;/em&gt;, lunch breaks were suddenly dedicated to farming. There I was: a full-on corporate girlie living her best online farm life.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;461&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-daily-button-1024x461.jpg&quot; alt=&quot;Daily bonus for playing in Township&quot; class=&quot;wp-image-43357&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-daily-button-1024x461.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-daily-button-300x135.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-daily-button-768x346.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-daily-button-1536x691.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-daily-button-89x40.jpg 89w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-daily-button-696x313.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-daily-button-560x252.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-daily-button-840x378.jpg 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-daily-button-80x36.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-daily-button-48x22.jpg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-daily-button.jpg 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Daily bonus for playing in Township&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;461&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-additional-rewards-1024x461.jpg&quot; alt=&quot;Additional rewards in Township&quot; class=&quot;wp-image-43359&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-additional-rewards-1024x461.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-additional-rewards-300x135.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-additional-rewards-768x345.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-additional-rewards-1536x691.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-additional-rewards-89x40.jpg 89w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-additional-rewards-696x313.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-additional-rewards-560x252.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-additional-rewards-840x378.jpg 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-additional-rewards-80x36.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-additional-rewards-48x22.jpg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-additional-rewards.jpg 1999w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Additional rewards in Township&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;461&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-leadership-board-1024x461.jpg&quot; alt=&quot;Leadership board in Township&quot; class=&quot;wp-image-43361&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-leadership-board-1024x461.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-leadership-board-300x135.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-leadership-board-768x345.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-leadership-board-1536x691.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-leadership-board-89x40.jpg 89w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-leadership-board-696x313.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-leadership-board-560x252.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-leadership-board-840x378.jpg 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-leadership-board-80x36.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-leadership-board-48x22.jpg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-leadership-board.jpg 1999w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Leadership board in Township&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;Then the offer came, an enticing amount of virtual currency in return for just a few pounds. But, &lt;em&gt;wait&lt;/em&gt;! This offer is only available for a few hours. I quickly did some girl maths: this game is free, and I’ve spent hours on it. What are a few pounds when I spent so much more buying &lt;em&gt;Hogwarts Legacy&lt;/em&gt;?&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;461&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-deals-1024x461.jpg&quot; alt=&quot;Offer to buy township cash and other goodies&quot; class=&quot;wp-image-43363&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-deals-1024x461.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-deals-300x135.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-deals-768x345.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-deals-1536x691.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-deals-89x40.jpg 89w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-deals-696x313.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-deals-560x252.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-deals-840x378.jpg 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-deals-80x36.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-deals-48x22.jpg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-deals.jpg 1999w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Offer to buy township cash and other goodies&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;Obviously, I fell for it a few times. With every new level, everything gets more expensive—and we thought &lt;em&gt;real-life&lt;/em&gt; inflation was bad, it’s got nothing on the economic chaos in Township.&amp;nbsp; Honestly, Donald Trump’s tariffs are hitting that community harder than anyone expected.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;At a certain point, enough was enough. Bye-bye Township. It’s time for real life. It was so bad that the only solution was to go cold turkey and delete the app.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;I mourned and missed my little farm for days afterwards, wondering how this game had gotten me to hand over cash (well, I use Apple Pay) to buy its currency (Township Cash), all in the hope of building out and improving my farm. RIP, my little town. How, even though I knew it was a game, it’d mastered gamification in a way I’d never seen before.&lt;/p&gt;



&lt;p&gt;When we think of gamification, we think of the classic badges and streaks. But gamification is so much more than that, and with its rise, we need to get cleverer and better at using it. As much as I love my ‘Goal Getter’ badge on my &lt;a href=&quot;https://connect.garmin.com/&quot;&gt;Garmin Connect app&lt;/a&gt;, it’s not enough to keep me around or using the app.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;473&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/garmin-badges-473x1024.png&quot; alt=&quot;Example of badges gamification in Garmin&quot; class=&quot;wp-image-43365&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/garmin-badges-473x1024.png 473w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/garmin-badges-139x300.png 139w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/garmin-badges-768x1663.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/garmin-badges-709x1536.png 709w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/garmin-badges-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/garmin-badges-214x464.png 214w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/garmin-badges-696x1507.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/garmin-badges-259x560.png 259w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/garmin-badges-137x296.png 137w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/garmin-badges-218x472.png 218w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/garmin-badges-37x80.png 37w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/garmin-badges-22x48.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/garmin-badges.png 923w&quot; sizes=&quot;auto, (max-width: 473px) 100vw, 473px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Example of badges gamification in Garmin&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;Don’t worry.&lt;strong&gt; I’m not going to claim gamification is dead; it definitely isn’t, but we need to explore how we can best use it to create an emotional investment in our app.&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;We’ll start with the basics: a 101 on gamification: what it is, when to use it, and which types of apps it actually makes sense for. Then, we’ll draw inspiration from the gamification greats (yes, Duolingo, but also Peloton, Strava, and Mimo), as well as some lesser-known but brilliantly executed examples like Dwellspring, Klarna, and Bloom. You’ll walk away with a solid understanding and a backlog of gamification ideas ready to test.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-which-kinds-of-apps-should-use-gamification&quot;&gt;Which kinds of apps should use gamification?&lt;/h2&gt;



&lt;p&gt;The most obvious categories are:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Education&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Productivity&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Fitness/Health&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;These are spaces where people are actively trying to learn and improve, which makes them naturally well-suited for gamification. But there are also categories where gamification is underused:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Finance / Banking&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Deep learning&amp;nbsp;&lt;/li&gt;



&lt;li&gt;News&lt;/li&gt;



&lt;li&gt;Entertainment&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Utilities and Tools&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Photo and Video editing&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Why? &lt;strong&gt;Gamification is there to help users achieve their goals. &lt;/strong&gt;Gamifying an app is not a goal in itself.&lt;strong&gt; &lt;/strong&gt;It should be linked closely to delivering value for users. This is where the controversy about &lt;a href=&quot;https://www.duolingo.com/&quot;&gt;Duolingo&lt;/a&gt; and its addictive streak comes in. I think that’s why Duolingo sometimes gets a bad rap.&lt;/p&gt;



&lt;p&gt;The goal of Duolingo is to help you learn languages, but in the sake of building gamification, it almost gets caught up in pushing translations and indirect learning:&lt;/p&gt;



&lt;p&gt;&lt;em&gt;“Finally, none of the reviewed studies attempted to challenge or reimagine the standard use of Duolingo – that is, as a largely behaviorist learning tool focused on rote learning, translation, competition and extrinsic rewards – which stands in contrast to a widely accepted view on language learning as process rooted in social and cultural exchange.” – &lt;/em&gt;Lantolf et al.,&lt;a href=&quot;https://www.tandfonline.com/doi/full/10.1080/09588221.2021.1933540#&quot;&gt; &lt;em&gt;Citation2015&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;So, circling back to the less obvious examples, gamification doesn’t really help you achieve your goal when reading the news or transferring money. That said, there are exceptions. Take saving money, for instance: gamifying it can make the process more engaging and rewarding. In other words, it’s less about the category itself and more about the specific use case.&lt;/p&gt;



&lt;p&gt;Let’s determine what good gamification could look like for you.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-how-to-work-out-your-gamification-approach&quot;&gt;How to work out your gamification approach&lt;/h2&gt;



&lt;p&gt;As usual—and I know I sound like a broken record saying this—it all starts with user research. You need to understand &lt;a href=&quot;https://www.storyly.io/post/best-gamification-practices-to-boost-user-engagement&quot;&gt;what is meaningful to your audience and what actually motivates them&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;This will help you see how to play on these motivations to help them achieve their goals. Let’s get more concrete. For &lt;a href=&quot;https://www.strava.com/&quot;&gt;Strava&lt;/a&gt;, users want to not only have routes for biking and running, but also measure and improve their performance. They are motivated by competitiveness. So what type of gamification do they use? Leaderboards as well as social competition and comparison. I don’t even have a premium Strava subscription, but I was excited to receive an email that said I was a ‘Local Legend.’ Then I discovered it wasn’t for speed but the frequency of a specific route, but still, I’ll take it.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;553&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/strava-leaderboard-email-553x1024.png&quot; alt=&quot;Email from Strava about their leaderboard&quot; class=&quot;wp-image-43367&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/strava-leaderboard-email-553x1024.png 553w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/strava-leaderboard-email-162x300.png 162w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/strava-leaderboard-email-22x40.png 22w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/strava-leaderboard-email-250x464.png 250w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/strava-leaderboard-email-302x560.png 302w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/strava-leaderboard-email-160x296.png 160w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/strava-leaderboard-email-255x472.png 255w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/strava-leaderboard-email-43x80.png 43w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/strava-leaderboard-email-26x48.png 26w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/strava-leaderboard-email.png 638w&quot; sizes=&quot;auto, (max-width: 553px) 100vw, 553px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Email from Strava about their leaderboard&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;You also want to think about the value of gamification you want it to provide:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Provide real-time feedback (progress bars)&lt;/li&gt;



&lt;li&gt;Reward behavior (milestones and goals)&lt;/li&gt;



&lt;li&gt;Prevent stopping through loss aversion (streaks)&lt;/li&gt;



&lt;li&gt;Push for interaction with others (community elements)&lt;/li&gt;



&lt;li&gt;Break up bigger tasks into smaller steps (milestones)&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;My advice is to write it out for yourself as follows:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;What is the main value my app provides?&lt;/li&gt;



&lt;li&gt;What are users trying to achieve?&lt;/li&gt;



&lt;li&gt;Where in their journey do they need extra support?&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Knowing this will keep you focused as we discuss various examples of gamification. I’ll start with the obvious two, streaks and badges, before sharing some less common but equally powerful forms of gamification.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-streaks&quot;&gt;1. Streaks&lt;/h3&gt;



&lt;p&gt;I thought I was above streaks after I broke free from the evil Duolingo owl, only to realize I had fallen hard again. I recently had a killer streak on Garmin: for 89 days, I had walked 10,000+ steps. I was so proud, I even did extra living room circles in the evening.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Until one day, a friend was visiting. We had such a great time catching up and chatting away that I forgot about my streak. The following day I woke to a broken streak… I’d walked 9,873 steps… I was way sadder than I should have been. After that, my addiction diminished (and thankfully so). I still usually walk 10,000+ steps a day (mainly because I have ADHD and an equally hyperactive dog), but I don’t care the same way I did anymore. The power of the Garmin streak was broken.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;This is the risk with streaks: they are powerful when you’re on one, but easily lost or de-motivating when you break one.&lt;/strong&gt; You realize the world didn’t end with that streak.&lt;/p&gt;



&lt;p&gt;Both Duolingo and &lt;a href=&quot;https://mimo.org/&quot;&gt;Mimo&lt;/a&gt; use the same clever solution: you get days off, aka you can miss your streak once or twice and keep your streak. Even more ridiculous, you can pay using their internal currency (another form of gamification we’ll get to later) to continue the streak. So, before you worship the 500+ day Duolingo users, know that they probably have had quite a few ‘freezes.’&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;451&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-streaks-451x1024.png&quot; alt=&quot;Duolingo Streak and below it shows a freeze was used&quot; class=&quot;wp-image-43369&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-streaks-451x1024.png 451w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-streaks-132x300.png 132w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-streaks-768x1743.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-streaks-677x1536.png 677w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-streaks-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-streaks-204x464.png 204w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-streaks-696x1579.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-streaks-247x560.png 247w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-streaks-130x296.png 130w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-streaks-208x472.png 208w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-streaks-35x80.png 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-streaks-21x48.png 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-streaks.png 881w&quot; sizes=&quot;auto, (max-width: 451px) 100vw, 451px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Duolingo Streak and below it shows a freeze was used&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;451&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/mimo-streak-freeze-451x1024.png&quot; alt=&quot;Mimo streak freeze option&quot; class=&quot;wp-image-43371&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/mimo-streak-freeze-451x1024.png 451w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/mimo-streak-freeze-132x300.png 132w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/mimo-streak-freeze-768x1745.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/mimo-streak-freeze-676x1536.png 676w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/mimo-streak-freeze-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/mimo-streak-freeze-204x464.png 204w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/mimo-streak-freeze-696x1581.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/mimo-streak-freeze-247x560.png 247w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/mimo-streak-freeze-130x296.png 130w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/mimo-streak-freeze-208x472.png 208w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/mimo-streak-freeze-35x80.png 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/mimo-streak-freeze-21x48.png 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/mimo-streak-freeze.png 880w&quot; sizes=&quot;auto, (max-width: 451px) 100vw, 451px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Mimo streak freeze option&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;With streaks, getting the right frequency is key. I really like that many fitness apps do weekly streaks, as it’s unlikely and unnecessary for people to use them every day. The workout app &lt;a href=&quot;https://www.joinladder.com/&quot;&gt;Ladder&lt;/a&gt; solves this by having a streak based on a number of workouts per week, e.g., three workouts in this example:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;451&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/ladder-streaks-451x1024.png&quot; alt=&quot;Ladder’s tracking of weekly streaks&quot; class=&quot;wp-image-43373&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/ladder-streaks-451x1024.png 451w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/ladder-streaks-132x300.png 132w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/ladder-streaks-768x1743.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/ladder-streaks-677x1536.png 677w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/ladder-streaks-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/ladder-streaks-204x464.png 204w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/ladder-streaks-696x1579.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/ladder-streaks-247x560.png 247w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/ladder-streaks-130x296.png 130w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/ladder-streaks-208x472.png 208w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/ladder-streaks-35x80.png 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/ladder-streaks-21x48.png 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/ladder-streaks.png 881w&quot; sizes=&quot;auto, (max-width: 451px) 100vw, 451px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Ladder’s tracking of weekly streaks&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;So, if you plan to use streaks, consider how often users should use your app to gain value.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Try to come up with a fun visual to represent the streak; I love how &lt;a href=&quot;https://fable.co/&quot;&gt;Fable&lt;/a&gt;, a book and TV tracking app, does this visualising the books you read per month, with the streak secondary below:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;451&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/fable-streak-451x1024.png&quot; alt=&quot;Fable reading app streak&amp;nbsp;&quot; class=&quot;wp-image-43375&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/fable-streak-451x1024.png 451w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/fable-streak-132x300.png 132w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/fable-streak-768x1743.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/fable-streak-677x1536.png 677w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/fable-streak-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/fable-streak-204x464.png 204w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/fable-streak-696x1579.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/fable-streak-247x560.png 247w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/fable-streak-130x296.png 130w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/fable-streak-208x472.png 208w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/fable-streak-35x80.png 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/fable-streak-21x48.png 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/fable-streak.png 881w&quot; sizes=&quot;auto, (max-width: 451px) 100vw, 451px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Fable reading app streak&amp;nbsp;&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;Another great example is &lt;a href=&quot;https://dwellspring.io/&quot;&gt;Dwellspring&lt;/a&gt;, a soundscape app. Rather than your classic streak, each day of listening grows your tree of serenity. You can see the tree expand with every track you listen to:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;965&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/dwellspring-leafy-streak-1-965x1024.jpg&quot; alt=&quot;Dwellspring’s leafy version of a streak&quot; class=&quot;wp-image-43417&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/dwellspring-leafy-streak-1-965x1024.jpg 965w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/dwellspring-leafy-streak-1-283x300.jpg 283w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/dwellspring-leafy-streak-1-768x815.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/dwellspring-leafy-streak-1-1448x1536.jpg 1448w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/dwellspring-leafy-streak-1-38x40.jpg 38w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/dwellspring-leafy-streak-1-437x464.jpg 437w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/dwellspring-leafy-streak-1-696x738.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/dwellspring-leafy-streak-1-528x560.jpg 528w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/dwellspring-leafy-streak-1-279x296.jpg 279w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/dwellspring-leafy-streak-1-445x472.jpg 445w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/dwellspring-leafy-streak-1-75x80.jpg 75w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/dwellspring-leafy-streak-1-45x48.jpg 45w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/dwellspring-leafy-streak-1.jpg 1600w&quot; sizes=&quot;auto, (max-width: 965px) 100vw, 965px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Dwellspring’s leafy version of a streak&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;I like that if you miss a day, it’s more forgiving. You lose one ring and not all progress. What I like less is that it talks about rings, which for me was confusing. I think they’re referring to the rings of a tree, but it isn’t the right word choice to hit home, in my humble opinion.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-badges&quot;&gt;2. Badges&lt;/h3&gt;



&lt;p&gt;Badges are everywhere, and they’re especially useful for long-term products, where they help break up the user journey. They offer small moments of celebration along the way. That said, in my opinion, they often feel a bit generic or disconnected from the overall experience.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;451&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-badges-451x1024.png&quot; alt=&quot;Duolingo badges&quot; class=&quot;wp-image-43381&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-badges-451x1024.png 451w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-badges-132x300.png 132w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-badges-768x1743.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-badges-677x1536.png 677w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-badges-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-badges-204x464.png 204w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-badges-696x1579.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-badges-247x560.png 247w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-badges-130x296.png 130w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-badges-208x472.png 208w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-badges-35x80.png 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-badges-21x48.png 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-badges.png 881w&quot; sizes=&quot;auto, (max-width: 451px) 100vw, 451px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Duolingo badges&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;If you plan to use badges, go all in and have a party for it. &lt;a href=&quot;https://www.onepeloton.com/en-GB&quot;&gt;Peloton&lt;/a&gt; nails this. Hit 500 rides during a live class? The instructor shouts you out by name, hypes you up, and gets the whole class cheering. It’s a moment of glory. Now compare that to a tiny badge quietly tucked away in an app… not quite the same, is it?&lt;/p&gt;



&lt;p&gt;In my opinion, only use badges if your users &lt;em&gt;would&lt;/em&gt; or &lt;em&gt;should&lt;/em&gt; be proud of that achievement anyway. They meditate for 100 days straight? Incredible! Next, make sure you send it via push notification and/or email so they don’t miss it.&lt;/p&gt;



&lt;p&gt;I also like how the activity tracker &lt;a href=&quot;https://store.google.com/gb/category/watches_trackers?hl=en-GB&quot;&gt;Fitbit&lt;/a&gt; makes badges fun, talking you through what you achieved:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;922&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/fitbit-badges-922x1024.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-43419&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/fitbit-badges-922x1024.jpg 922w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/fitbit-badges-270x300.jpg 270w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/fitbit-badges-768x853.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/fitbit-badges-1382x1536.jpg 1382w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/fitbit-badges-36x40.jpg 36w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/fitbit-badges-418x464.jpg 418w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/fitbit-badges-696x773.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/fitbit-badges-504x560.jpg 504w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/fitbit-badges-266x296.jpg 266w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/fitbit-badges-425x472.jpg 425w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/fitbit-badges-72x80.jpg 72w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/fitbit-badges-43x48.jpg 43w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/fitbit-badges.jpg 1800w&quot; sizes=&quot;auto, (max-width: 922px) 100vw, 922px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Fitbit badges&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-internal-currency-amp-point-based-rewards&quot;&gt;3. Internal currency &amp;amp; point-based rewards&lt;/h3&gt;



&lt;p&gt;I don’t feel like I need to convince you of the power of internal currencies. You’ve heard firsthand how I bought Township Cash not once but multiple times. But internal currencies are popular, not only in games but also commonly used in education apps. They allow users to personalize or improve their experience.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Internal currencies can also drive upsells, adding value for your brand. Even if you offer a subscription, you can unlock additional revenue by encouraging users to purchase in-app currency to enhance their experience.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Now I’ve grouped these together as sometimes, you get internal currencies you can’t purchase and other times you get points you can buy.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;If you’re not using currency or points to drive revenue, you can still boost retention and extend user sessions. Duolingo, for example, no longer rewards lesson completion with gems (their shiny internal currency). Instead, they offer 1.5x to 3x points for lessons completed within a time window. Usually, the window is 10 minutes, but they’ll occasionally bump it to 15-30 minutes. This, combined with the scoreboard, encourages users to stay longer. While you only need to complete one lesson to maintain your streak, the challenge of climbing the leaderboard keeps you engaged beyond that initial task.&lt;/p&gt;



&lt;p&gt;Points can also be seen as the equivalent of an e-commerce loyalty programme, so in my opinion, they are a lighter, more accessible form of gamification to use. For example, &lt;a href=&quot;https://www.klarna.com/uk/&quot;&gt;Klarna&lt;/a&gt;, a pay-later app, uses a point system:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;562&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/klarna-point-system-1024x562.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-43421&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/klarna-point-system-1024x562.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/klarna-point-system-300x165.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/klarna-point-system-768x421.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/klarna-point-system-1536x843.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/klarna-point-system-73x40.jpg 73w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/klarna-point-system-696x382.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/klarna-point-system-560x307.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/klarna-point-system-539x296.jpg 539w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/klarna-point-system-840x461.jpg 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/klarna-point-system-80x44.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/klarna-point-system-48x26.jpg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/klarna-point-system.jpg 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Klarna’s point system&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;Here, the goal is to get you to actively use and explore the app. &lt;strong&gt;Another interesting case for points or an internal currency is when your app topic requires quite a high level of knowledge and understanding.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;For example, &lt;a href=&quot;https://bloomapp.com/&quot;&gt;Bloom&lt;/a&gt;, a financial investment app, uses an internal currency to encourage its users to take lessons about investing (or play quizzes about investing), which will help them become more comfortable using the app. The motivator to gain the points is that they can then use them to win prizes.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;753&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/bloom-oink-currency-1024x753.jpg&quot; alt=&quot;Bloom’s Oink currency&quot; class=&quot;wp-image-43423&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/bloom-oink-currency-1024x753.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/bloom-oink-currency-300x221.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/bloom-oink-currency-768x564.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/bloom-oink-currency-1536x1129.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/bloom-oink-currency-54x40.jpg 54w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/bloom-oink-currency-631x464.jpg 631w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/bloom-oink-currency-696x512.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/bloom-oink-currency-560x412.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/bloom-oink-currency-403x296.jpg 403w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/bloom-oink-currency-642x472.jpg 642w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/bloom-oink-currency-80x59.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/bloom-oink-currency-48x35.jpg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/bloom-oink-currency.jpg 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Bloom’s Oink currency&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-4-leaderboards-amp-communities&quot;&gt;4. Leaderboards &amp;amp; Communities&lt;/h3&gt;



&lt;p&gt;By now, you’ve probably noticed that gamification rarely occurs in isolation. Points work well with leaderboards and come in combination with them as a measure of performance. Some apps don’t work with points, but still use leaderboards, like Peloton. For their bike, you get an output in terms of effort. During your bike ride, you can see how you rank against the 30,000 or so others who have done the ride.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;451&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/peloton-leadership-board-451x1024.png&quot; alt=&quot;Peloton’s leadership board&quot; class=&quot;wp-image-43401&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/peloton-leadership-board-451x1024.png 451w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/peloton-leadership-board-132x300.png 132w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/peloton-leadership-board-768x1745.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/peloton-leadership-board-676x1536.png 676w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/peloton-leadership-board-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/peloton-leadership-board-204x464.png 204w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/peloton-leadership-board-696x1581.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/peloton-leadership-board-247x560.png 247w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/peloton-leadership-board-130x296.png 130w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/peloton-leadership-board-208x472.png 208w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/peloton-leadership-board-35x80.png 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/peloton-leadership-board-21x48.png 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/peloton-leadership-board.png 880w&quot; sizes=&quot;auto, (max-width: 451px) 100vw, 451px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Peloton’s leadership board&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;The interesting thing about this is that it’s the opposite of what Mimo and Duolingo both do. Mimo leaderboards are small-scale; you’re in a mini competition aiming to move up a level.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;563&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/mimo-leaderboard-1-1024x563.jpg&quot; alt=&quot;Mimo’s weekly leaderboard&quot; class=&quot;wp-image-43427&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/mimo-leaderboard-1-1024x563.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/mimo-leaderboard-1-300x165.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/mimo-leaderboard-1-768x422.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/mimo-leaderboard-1-1536x844.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/mimo-leaderboard-1-73x40.jpg 73w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/mimo-leaderboard-1-696x382.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/mimo-leaderboard-1-560x308.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/mimo-leaderboard-1-539x296.jpg 539w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/mimo-leaderboard-1-840x461.jpg 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/mimo-leaderboard-1-80x44.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/mimo-leaderboard-1-48x26.jpg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/mimo-leaderboard-1.jpg 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Mimo’s weekly leaderboard&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;With Peloton, you can compete either with those taking the class live (which is more engaging) or against a broader group. This dynamic is fascinating because, with 30K competitors (unless you’re Pogacar), the goal isn’t necessarily to be number one, but to see progress by moving up the ranks. This progress-driven competition is a powerful motivator, and it’s one way you can leverage leaderboards effectively.&lt;/p&gt;



&lt;p&gt;Leaderboards are most effective in community-based apps, where there’s a sense of competition or coexistence between users.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-5-challenges&quot;&gt;5. Challenges&lt;/h3&gt;



&lt;p&gt;Who doesn’t love a challenge? I’m so competitive I’m banned from playing &lt;em&gt;Monopoly&lt;/em&gt; with my family, so this type of gamification works &lt;em&gt;too&lt;/em&gt; well on me.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Challenges are particularly popular with fitness apps. I’ve used Fitbit and Garmin, both of which utilize challenges. My relentless testing of workout apps has had me complete multiple 10-day, 4-week, 6-week, and more challenges.&lt;/p&gt;



&lt;p&gt;With challenges, you need to think clearly about the motivator and explain that upfront. This isn’t just about a sense of achievement (or intense competitiveness); it can also be a drive to build a new habit. Hence, challenges and streaks often go hand in hand.&lt;/p&gt;



&lt;p&gt;Challenges are also great for activation. A small initial challenge can get them to commit to trying out your app. I suggest linking the duration to the frequency of usage in that initial period that best correlates with retention.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;451&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/strava-challenges-451x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-43411&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/strava-challenges-451x1024.png 451w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/strava-challenges-132x300.png 132w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/strava-challenges-768x1743.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/strava-challenges-677x1536.png 677w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/strava-challenges-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/strava-challenges-204x464.png 204w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/strava-challenges-696x1579.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/strava-challenges-247x560.png 247w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/strava-challenges-130x296.png 130w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/strava-challenges-208x472.png 208w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/strava-challenges-35x80.png 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/strava-challenges-21x48.png 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/strava-challenges.png 881w&quot; sizes=&quot;auto, (max-width: 451px) 100vw, 451px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;em&gt;Strava challenges&lt;/em&gt;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-6-guided-progression&quot;&gt;6. Guided progression&lt;/h3&gt;



&lt;p&gt;Imagine you paid for an app and then discovered you could only access part of the content. Okay… you want &lt;em&gt;more&lt;/em&gt; money? No, if you want the rest, you’ve got to work for it. It sounds crazy put like that, but guided progression actually works really well for education apps. This is exactly what Duolingo and Mimo do. Want to go further? Got to complete the level first. Sure, you can skip to a section, but you’ve got to prove you know enough to be worth it.&lt;/p&gt;



&lt;p&gt;This form of gamification is great for keeping your app exciting and rewarding progress. You could always have special content that only gets unlocked for the most active users. This is a classic reward mechanism, but it works well. You can add clear progress bars to help users see how much is still needed to unlock the next part.&lt;/p&gt;



&lt;p&gt;Township (how I miss you) actually did this, too. Each level unlocked new buildings, crops, and more. I went from being a basic wheat farmer to having cacao and fetching tropical fruits from other islands. This is also what kept it from becoming repetitive.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;461&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-guided-progress-1024x461.jpg&quot; alt=&quot;Guided progress within Township&quot; class=&quot;wp-image-43413&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-guided-progress-1024x461.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-guided-progress-300x135.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-guided-progress-768x345.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-guided-progress-1536x691.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-guided-progress-89x40.jpg 89w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-guided-progress-696x313.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-guided-progress-560x252.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-guided-progress-840x378.jpg 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-guided-progress-80x36.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-guided-progress-48x22.jpg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/township-guided-progress.jpg 1999w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Guided progress within Township&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-7-social-interaction&quot;&gt;7. Social interaction&lt;/h3&gt;



&lt;p&gt;Before my Peloton era (I finally caved), I was all about &lt;a href=&quot;https://www.zwift.com/&quot;&gt;Zwift&lt;/a&gt;. Zwift is a hardcore biker’s paradise; you attach your real bike to a Tacx and cycle through virtual worlds. Before laziness set in and I stopped bothering with the whole bike attachment process, I loved it. I’d be huffing and puffing along, only for a complete stranger to send me a thumbs-up. Sure, they could only see my virtual self, but I promise, I sat up straighter and pedaled just a bit faster. The irony? I never actually figured out how to give a thumbs-up back—&lt;em&gt;oops&lt;/em&gt;.&lt;/p&gt;



&lt;p&gt;Using social interaction as a form of gamification only works if you have a big enough community or a tight-knit community to interact frequently. It can also be a great way to refer friends (let’s virtually bike together) as there is often a network effect: more people add value.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;451&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-quests-451x1024.png&quot; alt=&quot;Quests together in Duolingo&quot; class=&quot;wp-image-43415&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-quests-451x1024.png 451w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-quests-132x300.png 132w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-quests-768x1743.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-quests-677x1536.png 677w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-quests-18x40.png 18w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-quests-204x464.png 204w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-quests-696x1579.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-quests-247x560.png 247w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-quests-130x296.png 130w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-quests-208x472.png 208w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-quests-35x80.png 35w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-quests-21x48.png 21w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/07/duolingo-quests.png 881w&quot; sizes=&quot;auto, (max-width: 451px) 100vw, 451px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Quests together in Duolingo&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-gamifying-for-value&quot;&gt;Gamifying for value&lt;/h2&gt;



&lt;p&gt;Before you go wild and add the different types of gamification we covered, please hold your horses.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;With every form of gamification, you need to critically think about how it adds value. &lt;/strong&gt;When gamification occurs for the sake of engagement rather than value, a study found it actually detracts from &lt;a href=&quot;https://journals.sagepub.com/doi/10.1177/00222437241275927&quot;&gt;users’ participation in value-adding activities&lt;/a&gt;. I think this is why there are so many jokes about how people use Duolingo for 500 days and still don’t dare speak the language.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;You want to use gamification in a way that pushes users towards activities that drive revenue for the app, or help them on their journey there. We’ve seen great examples of this throughout:&amp;nbsp;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Bloom helps people become more comfortable with investing (value) by giving them Oinks, their internal currency (reward) for learning about investing&lt;/li&gt;



&lt;li&gt;Peloton shows you where you are on a leaderboard (reward) to encourage you to push yourself throughout a workout (value)&lt;/li&gt;



&lt;li&gt;Dwellspring shows you with a beautiful serenity tree (reward) if you consistently listen (value)&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;strong&gt;The study in the &lt;/strong&gt;&lt;a href=&quot;https://journals.sagepub.com/doi/10.1177/00222437241275927&quot;&gt;&lt;strong&gt;&lt;em&gt;Journal of Marketing Research&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt; goes on to suggest that rather than starting with gamification, you could potentially only offer it at a later stage, once they’ve started gaining value from the app:&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;&lt;em&gt;“One potential issue for app providers is that success in game-reward attainment makes users less inclined to engage in value-added activities. To prevent this effect, app providers can restrict access to certain game rewards until users have engaged with a certain number of value-added activities.”&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;While gamification can be incredibly powerful, especially in this age of short attention spans (guilty), it’s important to only consider it once users truly see and understand the value, rather than slapping it on as a quick fix. You want users to feel good about the experience, not pressured by gamification for its own sake.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;I think that’s the real reason I stopped using Township; I became so consumed by the constant stream of gamification elements that I lost sight of why I started using it in the first place: the nostalgic joy of building my own little farm and town, just like I did in childhood games.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Apple’s June 2025 EU update: one entitlement, three fees, and CTF’s 2026 sunset]]></title><description><![CDATA[What apps in the EU should do after Apple’s DMA tweak.]]></description><link>https://www.revenuecat.com/blog/growth/apple-eu-dma-update-june-2025/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/apple-eu-dma-update-june-2025/</guid><pubDate>Fri, 27 Jun 2025 17:02:58 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/apple-eu-june-2025-update-header.jpg" length="0" type="image/*"/><content:encoded>&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;: Apple’s June-2025 EU update merges every non-IAP option — link-outs, web-views, and&amp;nbsp;alternative payment processing&amp;nbsp;— into a single “communication &amp;amp; promotion of offers” entitlement. Turning it on means removing in-app purchases. Fees are now 2 % initial-acquisition + 5-13 % Store Services + 5 % Core Technology Commission, which will replace the per-install CTF by Jan 2026. Skipping tier-2 App Store Services halves the Store slice but loses auto-updates, discovery, reviews, and analytics.&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Yesterday, Apple &lt;a href=&quot;https://developer.apple.com/news/?id=awedznci&quot;&gt;announced some changes&lt;/a&gt; to their rules in the EU, based on rulings by the European Commission under the Digital Markets Act. These changes are quite hard to parse and understand, so we read them for you so you can decide whether or not to take action.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-the-big-changes&quot;&gt;The big changes&lt;/h2&gt;



&lt;p&gt;There are a few major changes in the announcement:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Apple no longer distinguishes between alternative payment processing (e.g. using Stripe inside your app) and linking out. Instead, it folds all in-app purchase alternatives into the term “communication and promotion of offers” in a destination which “can be a website, alternative app marketplace, or another app, and can be accessed outside the app or within the app via a web view or native experience.” Apple is offering a new entitlement along with a terms addendum for this.&lt;/li&gt;



&lt;li&gt;The fee structure for transactions using these offers has changed, and differs depending on whether or not the developer has opted in to the Alternative Terms Addendum for Apps in the EU (“AEUTA”). One important new element is the “Core Technology Commission” (CTC), which is a new fee on digital goods and services purchases. The name is reminiscent of the Core Technology Fee (CTF) which still applies under the AEUTA, but Apple says that it will replace the CTF with the CTC by January 2026.&lt;/li&gt;



&lt;li&gt;Apps that adopt “communication and promotion of offers” can now opt out of some optional (“tier 2”) App Store Services, reducing their fee. This reduces the App Store to a glorified download link.&lt;/li&gt;



&lt;li&gt;The “scare sheet” that needs to be shown before making a non-IAP purchase has changed slightly, and so has the UX for downloading apps from alternative marketplaces or directly from the web.&lt;/li&gt;



&lt;li&gt;Streaming apps in the EEA can also use this new entitlement (instead of the &lt;a href=&quot;https://developer.apple.com/support/music-streaming-services-entitlement-eea/&quot;&gt;Music Streaming Services Entitlement (EEA)&lt;/a&gt;). The EEA includes the EU but also Iceland, Liechtenstein, and Norway, which are not part of the EU.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;As before, app developers that want to use non-IAP purchasing (“communication and promotion of offers”) can’t use in-app purchases in the same app, so it’s an either-or situation.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-pared-down-app-store-service-tier&quot;&gt;Pared down App Store Service tier&lt;/h2&gt;



&lt;p&gt;One notable change is the ability to opt out of some non-essential (“tier 2”) App Store Services. Apple provides a helpful &lt;a href=&quot;https://developer.apple.com/help/app-store-connect/reference/store-services-tiers&quot;&gt;overview&lt;/a&gt;. Here is the summary of what apps opting out of tier 2 Services won’t get:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Automatic app update&lt;/li&gt;



&lt;li&gt;Ratings &amp;amp; reviews&lt;/li&gt;



&lt;li&gt;App Store discovery (search except for exact match, custom product pages, featuring, custom product pages, in-app events, recommendations, etc.)&lt;/li&gt;



&lt;li&gt;Data insights in App Store Connect&lt;/li&gt;



&lt;li&gt;Expedited app review, phased release&lt;/li&gt;



&lt;li&gt;Apple Business Manager / Apple School Manager&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Basically, opting out of tier 2 App Store Services makes the App Store a pure download mechanism for the app. Even for app updates, apps will have to develop their own solutions (eg. an in-app message saying that there is a new update with a link to the store page).&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Opting out of tier 2 App Store Services likely is only a feasible option for apps who have their own channels and audience (think Fortnite or Spotify).&lt;/p&gt;



&lt;p&gt;Developers can change whether or not they opt in or out of tier 2 Services on a quarterly basis.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-new-fee-structure&quot;&gt;New fee structure&lt;/h2&gt;



&lt;p&gt;One of the most important questions that will determine the viability of these changes is the fee structure. For reference, we have also included the previous fee structure bwloe.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-without-adopting-the-alternative-terms-for-the-eu-aeuta&quot;&gt;Without adopting the alternative terms for the EU (“AEUTA”)&lt;/h3&gt;



&lt;p&gt;Here is the fee structure that applies to any developer that has not adopted the alternative terms for the EU.&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;New fee structure&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Previous fee structure&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Use in-app purchases&lt;/td&gt;&lt;td&gt;&lt;strong&gt;30%&lt;/strong&gt; (regular)&lt;br&gt;&lt;strong&gt;15%&lt;/strong&gt; (Small Business Program, subscriptions in year 2+)&lt;/td&gt;&lt;td&gt;(unchanged)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;“Communication and promotion of offers”&amp;nbsp;&lt;br&gt;Regular App Store Service&lt;br&gt;Not in the Small Business Program&lt;/td&gt;&lt;td&gt;2% initial acquisition fee (first 6 months)&lt;br&gt;13% Store Services fee&lt;br&gt;5% CTC&lt;br&gt;&lt;strong&gt;= 20% total Apple fee for initial purchases&lt;/strong&gt;&lt;br&gt;(payment processing on top)&lt;/td&gt;&lt;td&gt;5% initial acquisition (first 12 months)&lt;br&gt;20% Store Services fee&lt;br&gt;&lt;strong&gt;= 25% total fee for initial purchases&lt;/strong&gt;&lt;br&gt;(payment processing on top)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;“Communication and promotion of offers”&amp;nbsp;&lt;br&gt;Without tier 2 App Store Services&lt;br&gt;Not in the Small Business Program&lt;/td&gt;&lt;td&gt;2% initial acquisition fee (first 6 months)&lt;br&gt;5% Store Services fee&lt;br&gt;5% CTC&lt;br&gt;&lt;strong&gt;= 12% total for initial purchases&lt;/strong&gt;&lt;br&gt;(payment processing on top)&lt;/td&gt;&lt;td&gt;n/a&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;“Communication and promotion of offers”&amp;nbsp;&lt;br&gt;Regular App Store Service&lt;br&gt;Small Business Program&lt;/td&gt;&lt;td&gt;0% initial acquisition fee (first 6 months)&lt;br&gt;10% Store Services fee&lt;br&gt;5% CTC&lt;br&gt;&lt;strong&gt;= 15% total fee for initial purchases&lt;/strong&gt;&lt;br&gt;(payment processing on top)&lt;/td&gt;&lt;td&gt;5% initial acquisition (first 12 months)&lt;br&gt;7% store Services fee&lt;br&gt;&lt;strong&gt;= 12% total fee for initial purchases&lt;/strong&gt;&lt;br&gt;(payment processing on top)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;“Communication and promotion of offers”&amp;nbsp;&lt;br&gt;Without tier 2 App Store Services&lt;br&gt;Small Business Program&lt;/td&gt;&lt;td&gt;0% initial acquisition fee (first 6 months)&lt;br&gt;5% Store Services fee&lt;br&gt;5% CTC&lt;br&gt;&lt;strong&gt;= 10% total for initial purchases&lt;/strong&gt;&lt;br&gt;(payment processing on top)&lt;/td&gt;&lt;td&gt;n/a&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;The takeaway from the above is that, even more so than before, for developers under the Small Business Program it does not make economic sense to adopt anything other than in-app purchases. The lowest possible fees in this case are 10%, but for that you would have to forgo any discovery in the App Store, and you would have to pay a payment processor on top of that 10%.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;For bigger apps, adopting non-IAP purchasing options &lt;em&gt;could&lt;/em&gt; be a little bit more attractive. In this case, the fee has dropped to a maximum of 20% when using the full App Store Services, and apps with their own channels and audience could even go down to 12% by opting out of tier 2 Services. While it’s not guaranteed that these lower margins are a guaranteed economic benefit (after all, &lt;a href=&quot;https://www.revenuecat.com/blog/growth/iap-vs-web-purchases-conversion-test/&quot;&gt;conversion rates will likely be lower than for in-app purchases&lt;/a&gt;), it might be worth testing. The biggest drawback is that Apple forbids using in-app purchases in the app in addition to alternative purchasing.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-when-adopting-the-alternative-terms-for-the-eu-aeuta&quot;&gt;When adopting the alternative terms for the EU (“AEUTA”)&lt;/h3&gt;



&lt;p&gt;Alternatively, developers can still opt in to the alternative terms for the EU. In Apple’s original DMA compliance changes, opting in to these terms was required to link out or use alternative payment processing. This rule had already been softened back in August when &lt;a href=&quot;https://developer.apple.com/news/?id=szrqxadx&quot;&gt;linking out became possible without adopting the alternative terms for the EU&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;The alternative terms for the EU include fees in addition to commissions on purchases: the core technology fee (CTF). The CTF is a €0.50 per-download fee that applies for any annual download after the first million downloads. It is worth noting that the CTF does not only count initial downloads, but also any app updates (once per year) – unless an app is never updated, you can think of this as a tax on each yearly active user of the app. Apple states that by January 2026, they will move away from the CTF in favor of the CTC (which is a percentage of purchase revenue instead of a per-install fee).&lt;/p&gt;



&lt;p&gt;Here is the fee structure that applies to developers adopting the alternative terms for the EU:&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;New fee structure&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Previous fee structure&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Use in-app purchases&lt;/td&gt;&lt;td&gt;17% (regular)&lt;br&gt;10% (subscriptions after 1 year / Small Business Program)&lt;br&gt;3% IAP fee&lt;br&gt;&lt;strong&gt;= 20% / 13% commission&lt;br&gt;+ CTF on top&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;(unchanged)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;“Communication and promotion of offers”&amp;nbsp;&lt;br&gt;Regular App Store Service&lt;br&gt;Not in the Small Business Program&lt;/td&gt;&lt;td&gt;2% initial acquisition fee (first 6 months)&lt;br&gt;13% store svc fee&lt;br&gt;&lt;strong&gt;= 15% total for initial purchases&lt;br&gt;+ CTF on top&lt;br&gt;&lt;/strong&gt;(payment processing on top)&lt;/td&gt;&lt;td&gt;17% (regular)&lt;br&gt;10% (subscriptions after 1 year)&lt;br&gt;3% IAP fee&lt;br&gt;&lt;strong&gt;= 20% / 13% total Apple commission &lt;br&gt;+ CTF on top&lt;br&gt;&lt;/strong&gt;(payment processing on top)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;“Communication and promotion of offers”&amp;nbsp;&lt;br&gt;Without tier 2 App Store Services&lt;br&gt;Not in the Small Business Program&lt;/td&gt;&lt;td&gt;2% initial acquisition fee (6 months)&lt;br&gt;5% store svc fee&lt;br&gt;&lt;strong&gt;= 7% total for initial purchases&lt;br&gt;+ CTF on top&lt;br&gt;&lt;/strong&gt;(payment processing on top)&lt;/td&gt;&lt;td&gt;n/a&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;“Communication and promotion of offers”&amp;nbsp;&lt;br&gt;Regular App Store Service&lt;br&gt;Small Business Program&lt;/td&gt;&lt;td&gt;&lt;strong&gt;10% Store Services fee &lt;br&gt;+ CTF on top&lt;br&gt;&lt;/strong&gt;(payment processing on top)&lt;/td&gt;&lt;td&gt;10% commission&lt;br&gt;3% IAP fee&lt;br&gt;&lt;strong&gt;= 13% total Apple commission &lt;br&gt;+ CTF on top&lt;/strong&gt;&lt;br&gt;(payment processing on top)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;“Communication and promotion of offers”&amp;nbsp;&lt;br&gt;Without tier 2 App Store Services&lt;br&gt;Small Business Program&lt;/td&gt;&lt;td&gt;&lt;strong&gt;5% Store Services fee&lt;br&gt;+ CTF on top&lt;br&gt;&lt;/strong&gt;(payment processing on top)&lt;/td&gt;&lt;td&gt;n/a&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;As before, the economic feasibility of these terms hinges on how large the CTF is that an app can expect to have to pay. As for the non-AEUTA case, for Small Businesses Program developers, it is very unlikely that the non-IAP option is economically feasible.&lt;/p&gt;



&lt;p&gt;For apps with large revenue but a small audience (ie. that are unlikely to have to pay large amounts of CTF), adopting the terms &lt;em&gt;might&lt;/em&gt; make economic sense.&lt;/p&gt;



&lt;p&gt;For apps that want to distribute via alternative app marketplaces or directly via the web, the fee structure has not changed: you still need to adopt the alternative terms and pay the CTF of €0.50 per install after the first million installs. App marketplaces have to pay the CTF starting with the first install.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-ux-changes&quot;&gt;UX changes&lt;/h2&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-communication-and-promotion-of-offers&quot;&gt;“Communication and promotion of offers”&lt;/h3&gt;



&lt;p&gt;When making non-IAP purchases, Apple still mandates a “scare sheet” before initializing a purchase in the app or linking out to an external purchase. The good news is that the scare sheet has become less, well, scary. (If you’re curious, you can find the old versions in our &lt;a href=&quot;https://www.revenuecat.com/blog/growth/apple-eu-dma-app-store-policy-changes/&quot;&gt;previous blog post&lt;/a&gt;). Still, having to show this big message before a purchase is bound to reduce your conversion rates.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;499&quot; height=&quot;1024&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/new-scare-sheet-499x1024.png&quot; alt=&quot;&quot; class=&quot;wp-image-43334&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/new-scare-sheet-499x1024.png 499w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/new-scare-sheet-146x300.png 146w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/new-scare-sheet-768x1575.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/new-scare-sheet-749x1536.png 749w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/new-scare-sheet-20x40.png 20w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/new-scare-sheet-226x464.png 226w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/new-scare-sheet-696x1427.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/new-scare-sheet-273x560.png 273w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/new-scare-sheet-144x296.png 144w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/new-scare-sheet-230x472.png 230w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/new-scare-sheet-39x80.png 39w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/new-scare-sheet-23x48.png 23w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/new-scare-sheet.png 864w&quot; sizes=&quot;auto, (max-width: 499px) 100vw, 499px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-installing-apps-and-marketplaces-from-the-web&quot;&gt;Installing apps and marketplaces from the web&lt;/h3&gt;



&lt;p&gt;Apple has also changed the UX for installing marketplaces from the web, and will soon allow apps to install other apps from the same developer from the web. Apple has an &lt;a href=&quot;https://developer.apple.com/support/alt-distribution-ux-in-the-eu/&quot;&gt;overview of the flows&lt;/a&gt;.&lt;/p&gt;



&lt;p&gt;So far, alternative app marketplaces and web distribution of apps have not yet taken off, and since the rules around these aren’t changing much, that is unlikely to change.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-conclusion&quot;&gt;Conclusion&lt;/h2&gt;



&lt;p&gt;One new entitlement, but three moving fees. For Small Business Program apps, standard IAP still wins — losing App Store discovery to save a few points rarely pencils out. Larger brands with their own channels and/or marginal costs to serve each customer can think about testing the 12% route, but must budget for CTF until its 2026 sunset, watch conversion drop-offs closely, and be okay with not offering in-app purchases as the most convenient purchase option.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[A beginner’s guide to implementing ad-free subscriptions in your React Native app]]></title><description><![CDATA[A step-by-step tutorial to let users pay to remove ads—using Expo, AdMob, and RevenueCat]]></description><link>https://www.revenuecat.com/blog/engineering/ad-free-subscriptions-in-react-native/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/ad-free-subscriptions-in-react-native/</guid><pubDate>Thu, 26 Jun 2025 14:16:49 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/1.-A-Beginners-guide-to-implementing-an-ad-free-subscription-in-your-React-Native-app.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Mobile apps primarily rely on two monetization strategies: ads and subscriptions. While ads provide free access to users and generate revenue for developers, they often disrupt the user experience and can lead to frustration. This creates an opportunity for developers to offer a premium, ad-free experience through subscriptions—a win-win solution that enhances user satisfaction while generating recurring revenue.&lt;/p&gt;



&lt;p&gt;In this guide, we’ll walk you through the process of implementing an ad-free subscription in your React Native app using RevenueCat. This tutorial is beginner-friendly. Here’s what we’ll cover:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Adding &lt;code&gt;react-native-purchases&lt;/code&gt; to enable in-app purchasing in our app&lt;/li&gt;



&lt;li&gt;Adding &lt;code&gt;react-native-google-mobile-ads&lt;/code&gt; to display inline ads in our app&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Configuring in-app products in RevenueCat and required entitlements that unlock the ad-free experience&lt;/li&gt;
&lt;/ul&gt;


&lt;div class=&quot;lazyblock-e525b3a3ae6c-Z28ufmR wp-block-lazyblock-e525b3a3ae6c&quot;&gt;&lt;blogposttip title=&quot;Track ad revenue in RevenueCat&quot; text=&quot;&lt;p&gt;You can now track your AdMob add revenue in Revenuecat and get a complete picture of your revenue. Simply replace your standard AdMob loading calls with the loadAndTrack methods from the RevenueCat SDK. All ad events are tracked automatically. Read more about our new in-app ad revenue &lt;a href=&amp;quot;https://www.revenuecat.com/blog/growth/track-in-app-ad-revenue-alongside-purchases-get-the-full-picture-on-monetization/&amp;quot;&gt;in our announcement blog post&lt;/a&gt;.&lt;/p&gt;&quot; icon=&quot;bulb&quot;&gt;
&lt;/blogposttip&gt;&lt;/div&gt;


&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-prerequisites&quot;&gt;Prerequisites&lt;/h2&gt;



&lt;p&gt;Next let’s add some lovely ads to our app&lt;/p&gt;



&lt;p&gt;In this tutorial, we will build a simple React Native app, for both iOS and Android, that allows the user to subscribe to a monthly subscription which unlocks an ad-free experience in the app.&amp;nbsp; If you have an existing app which you’re going to implement subscription functionality, you can jump ahead to the next section. Follow along by cloning the sample project, built with Expo.&lt;/p&gt;



&lt;p&gt;When using react-native-purchases with Expo you need to install expo-dev-tools and create a development build as Expo Go does not support native modules which are required by react-native-purchases. Learn how to create a development build and install it on your device from &lt;a href=&quot;https://docs.expo.dev/get-started/set-up-your-environment/?mode=development-build&quot;&gt;this interactive guide&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Start by cloning this GitHub repository which contains the template for this project.&amp;nbsp;&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1yzgzO wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;$ git clone git@github.com:plahteenlahti\/ad-iap-example.git&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The template comes configured with Expo, react-native-google-mobile-ads, and &lt;em&gt;expo-dev-client&lt;/em&gt;. Expo Go doesn’t support native modules by default, which are required for react-native-purchases. Run &lt;strong&gt;&lt;em&gt;npm install&lt;/em&gt;&lt;/strong&gt; to install all the dependencies and open the project in your editor of choice. After that, run &lt;strong&gt;&lt;em&gt;npx expo start&lt;/em&gt;&lt;/strong&gt; to start the development server.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Testing in-app purchases is best on a real device, so choose that option from the above list and you should see something like this:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image&quot;&gt;&lt;img decoding=&quot;async&quot; src=&quot;https://lh7-rt.googleusercontent.com/docsz/AD_4nXduolP1bYmzoU8lmtCgftdSC-ChiQnNMXMnAw2iISbjQrHMF0N0Q4aURLvOARF42JCULca6IW-eiQET04Z5Y-NfWdLBiClNN5fsvz2qgP2IBtE2uQz9IoNzS8Wm-cMeMIm6eUGtWw?key=mAiJpxm6Z4Wx5JqHeFAKxhZd&quot; alt=&quot;Screenshot of our example project&quot;&gt;&lt;/figure&gt;


&lt;div class=&quot;lazyblock-dcadc5d83064-2cjOsD wp-block-lazyblock-dcadc5d83064&quot;&gt;&lt;blogposthowtostep level=&quot;h2&quot; title=&quot;Step 1: Set up App Store and Play Store&quot; summary=&quot;Set up your subscription product in the App Store and Play Store so users on both platforms can subscribe.&quot; image-url=&quot;&quot;&gt;
&lt;/blogposthowtostep&gt;&lt;/div&gt;


&lt;p&gt;Before we can move to implementing subscriptions in our app, we need to configure our subscription product for all the platforms we want to target. Since React Native is a cross-platform solution, targeting both iOS and Android is a good idea. In both cases we want to configure a single subscription: a monthly recurring subscription for 5 dollars.&lt;/p&gt;


&lt;div class=&quot;lazyblock-dcadc5d83064-1GrRqO wp-block-lazyblock-dcadc5d83064&quot;&gt;&lt;blogposthowtostep level=&quot;h3&quot; title=&quot;Step 1.1: Set up App Store&quot; summary=&quot;Set up your subscription product in the App Store so users on both platforms can subscribe.&quot; image-url=&quot;&quot;&gt;
&lt;/blogposthowtostep&gt;&lt;/div&gt;


&lt;p&gt;Create a RevenueCat account and then&lt;a href=&quot;https://www.revenuecat.com/docs/projects/connect-a-store&quot;&gt; follow this guide to connect the App Store to RevenueCat.&lt;/a&gt;&lt;/p&gt;


&lt;div class=&quot;lazyblock-dcadc5d83064-ZHQnM5 wp-block-lazyblock-dcadc5d83064&quot;&gt;&lt;blogposthowtostep level=&quot;h3&quot; title=&quot;Step 1.2: Set up Play Store&quot; summary=&quot;Set up your subscription product in the Play Store so users on both platforms can subscribe.&quot; image-url=&quot;&quot;&gt;
&lt;/blogposthowtostep&gt;&lt;/div&gt;


&lt;p&gt;Create a RevenueCat account and then&lt;a href=&quot;https://www.revenuecat.com/docs/projects/connect-a-store&quot;&gt; follow this guide to connect the Play Store to RevenueCat.&lt;/a&gt;&lt;/p&gt;


&lt;div class=&quot;lazyblock-dcadc5d83064-15uuac wp-block-lazyblock-dcadc5d83064&quot;&gt;&lt;blogposthowtostep level=&quot;h2&quot; title=&quot;Step 2: Set up RevenueCat products&quot; summary=&quot;Configure RevenueCat with your app’s products and entitlements to manage and track ad-free subscriptions.

&quot; image-url=&quot;&quot;&gt;
&lt;/blogposthowtostep&gt;&lt;/div&gt;


&lt;p&gt;Once you’ve configured the store of your choice, or both, it’s time to set up Revenuecat. If you’re not familiar with Revenuecat before, or time has passed since the last time you used it, &lt;a href=&quot;https://www.revenuecat.com/docs/getting-started/quickstart#2-product-configuration&quot;&gt;this quickstart guide&lt;/a&gt; will help you get up to speed.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;You should configure your RevenueCat products, offerings and entitlements so that you have:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;One entitlement for the ad-free subscription level, using the identifier &lt;strong&gt;&lt;em&gt;ad_free_entitlement&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;



&lt;li&gt;Two separate products for App Store and Play Store, for example with identifier &lt;strong&gt;&lt;em&gt;ad_free_monthly &lt;/em&gt;&lt;/strong&gt;(learn more about the naming practises: &lt;a href=&quot;https://www.revenuecat.com/docs/getting-started/entitlements/ios-products&quot;&gt;iOS&lt;/a&gt;, &lt;a href=&quot;https://www.revenuecat.com/docs/getting-started/entitlements/android-products#tips-for-creating-robust-product-ids&quot;&gt;Android&lt;/a&gt;)&lt;/li&gt;



&lt;li&gt;Matching subscriptions in Play Store console and App Store connect with the same identifiers&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Remember to group your product under the entitlement you created.&amp;nbsp;&lt;/p&gt;


&lt;div class=&quot;lazyblock-dcadc5d83064-Z10o96C wp-block-lazyblock-dcadc5d83064&quot;&gt;&lt;blogposthowtostep level=&quot;h2&quot; title=&quot;Step 3: Add ads with react-native-google-mobile-ads&quot; summary=&quot;Install and configure AdMob to show ads in your app for non-subscribers, helping monetize free users.&quot; image-url=&quot;&quot;&gt;
&lt;/blogposthowtostep&gt;&lt;/div&gt;


&lt;p&gt;Next let’s add some ads to our app. First we need to install the &lt;code&gt;react-native-google-mobile-ads&lt;/code&gt;. Use the command below&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-ezdKe wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;npx expo install react-native-google-mobile-ads&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Also install expo-build-properties:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Zu7ymt wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;npx expo install expo-build-properties\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;We also need to enable static frameworks for everything to work. In your &lt;code&gt;app.json&lt;/code&gt;, in the plugins section add the following:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Fcqzu wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;plugins\&amp;quot;: [\n     \t\/\/\/ ... other plugins\n      [\n        \&amp;quot;react-native-google-mobile-ads\&amp;quot;,\n        {\n          \&amp;quot;iosAppId\&amp;quot;: \&amp;quot;you-app-id\&amp;quot;,\n          \&amp;quot;androidAppId\&amp;quot;: \&amp;quot;you-app-id\&amp;quot;\n        }\n      ],\n      [\n        \&amp;quot;expo-build-properties\&amp;quot;,\n        {\n          \&amp;quot;ios\&amp;quot;: {\n            \&amp;quot;useFrameworks\&amp;quot;: \&amp;quot;static\&amp;quot;\n          }\n        }\n      ]\n    ],&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Before displaying ads, you’ll need a Google AdMob account. Create one if you haven’t already and create new apps in the AdMob dashboard for all the platforms you plan to target. Notice that you need to place your AdMob key in the config plugin’s section. Using an invalid key will cause your app to crash.&lt;/p&gt;



&lt;p&gt;Run your app and ensure that everything is working properly. The next step is to add the correct type of ads into our app.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-initialize-the-google-mobile-ads-sdk-nbsp-nbsp-nbsp&quot;&gt;Initialize the Google Mobile Ads SDK&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/h3&gt;



&lt;p&gt;Before you can load ads in your app, you need to initialize the Google Mobile Ads SDK by calling the initialize method. This call needs to be done only once, preferably right after the app launch.&lt;/p&gt;



&lt;p&gt;In your app entrypoint (&lt;code&gt;_layout.tsx&lt;/code&gt; in Expo router or App.tsx in bare project) do the following:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z1Yhe9g wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;import { Stack } from \&amp;quot;expo-router\&amp;quot;;\nimport { useEffect } from \&amp;quot;react\&amp;quot;;\nimport { Platform } from \&amp;quot;react-native\&amp;quot;;\nimport mobileAds from \&amp;quot;react-native-google-mobile-ads\&amp;quot;;\n\nexport default function RootLayout() {\n  useEffect(() =&gt; {\n    \/\/ Initialize mobile ads\n    mobileAds()\n      .initialize()\n      .then(adapterStatuses =&gt; {\n        console.log(&apos;Mobile ads initialized successfully&apos;);\n      })\n      .catch(error =&gt; {\n        console.error(&apos;Failed to initialize mobile ads:&apos;, error);\n      });\n\n  }, []);\n\n  return &lt;Stack screenOptions={{ title: \&amp;quot;Article\&amp;quot; }} \/&gt;;\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;You also need to take care of requesting app tracking transparency authorization. Follow&lt;a href=&quot;https://docs.page/invertase/react-native-google-mobile-ads#requesting-app-tracking-transparency-authorization&quot;&gt; React Native Google Mobile Ads documentation for doing that correctly.&lt;/a&gt;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-show-banner-apps-in-your-app&quot;&gt;Show banner apps in your app&lt;/h3&gt;



&lt;p&gt;React native Google Mobile Ads provides multiple different types of ads to show in your app. In our case we want to show banner ads that take a limited amount of space on the screen, allowing the user to still see the main content but with a slightly hindered user experience.&lt;/p&gt;



&lt;p&gt;Banner ads work like this:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;You import the BannerAd component and include it in the code. In the example project there is an existing Ad component that we can place the BannerAd component in.&lt;/li&gt;



&lt;li&gt;Since BannerAd is a WebView we need to call the useForeground hook to detect when app is brought back from background and request a new ad so that banner ads don’t end up showing empty ads.&lt;/li&gt;



&lt;li&gt;Define unitId and size. The former should in testing be a TestIds.ADAPTIVE_BANNER and in production a real ad id, while the latter should be of the size we want to show in our app. In the example ⅓ of the device height is used, based on Dimensions.get&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Add the following snippet to your code to show banner ads:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-14md3E wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;\/\/\/ Ad.tsx\n\nimport React, { useRef } from &apos;react&apos;;\nimport { Platform, View, Dimensions } from &apos;react-native&apos;;\nimport { BannerAd, BannerAdSize, TestIds, useForeground } from &apos;react-native-google-mobile-ads&apos;;\n\nconst adUnitId = __DEV__ ? TestIds.ADAPTIVE_BANNER : &apos;ca-app-pub-xxxxxxxxxxxxx\/yyyyyyyyyyyyyy&apos;;\n\ninterface AdProps {\n  style?: any;\n}\n\nexport const Ad = ({ style }: AdProps) =&gt; {\n  const bannerRef = useRef&lt;BannerAd&gt;(null);\n  const screenHeight = Dimensions.get(&apos;window&apos;).height;\n  const adHeight = screenHeight \/ 3;\n\n  \/\/ react-native-google-mobile-ads documentation:\n  \/\/ (iOS) WKWebView can terminate if app is in a \&amp;quot;suspended state\&amp;quot;, resulting in an empty banner when app returns to foreground.\n  \/\/ Therefore it&apos;s advised to \&amp;quot;manually\&amp;quot; request a new ad when the app is foregrounded (https:\/\/groups.google.com\/g\/google-admob-ads-sdk\/c\/rwBpqOUr8m8).\n  useForeground(() =&gt; {\n    Platform.OS === &apos;ios&apos; &amp;amp;&amp;amp; bannerRef.current?.load();\n  });\n\n  return (\n    &lt;View style={[{ height: adHeight }, style]}&gt;\n      &lt;BannerAd \n        ref={bannerRef} \n        unitId={adUnitId} \n        size={`${Dimensions.get(&apos;window&apos;).width - 20}x${adHeight}`}\n      \/&gt;\n    &lt;\/View&gt;\n  );\n};\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Your app should now display banner ads between the main content blocks, and look like this now:&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h&quot;&gt;&lt;img decoding=&quot;async&quot; src=&quot;https://lh7-rt.googleusercontent.com/docsz/AD_4nXfNi1xfBOt2-DmwYWtLv5hbYdVnPec9oj9rd1h5jw0N0BSPc6UpsxeZl9mWDtYsSbQTIdLtOlQnb_hTtXzD4COXGdIuKWWx4-z2YALgJgp4NQ1WhvT3zOYMfJA4xUJdy5yCQmW2Bg?key=mAiJpxm6Z4Wx5JqHeFAKxhZd&quot; style=&quot;&quot; alt=&quot;Screenshot of how your app should look after enabling adMob ads &quot;&gt;&lt;/h2&gt;


&lt;div class=&quot;lazyblock-dcadc5d83064-1HnKuq wp-block-lazyblock-dcadc5d83064&quot;&gt;&lt;blogposthowtostep level=&quot;h2&quot; title=&quot;Step 4: Add subscriptions to your React Native app&quot; summary=&quot;Integrate RevenueCat to let users buy subscriptions and unlock the ad-free experience directly in your app.&quot; image-url=&quot;&quot;&gt;
&lt;/blogposthowtostep&gt;&lt;/div&gt;


&lt;p&gt;Now that we have ads configured it’s time to add &lt;em&gt;react-native-purchases&lt;/em&gt; and &lt;em&gt;react-native-purchases&lt;/em&gt;,&amp;nbsp; RevenueCat’s SDKs for in-app purchasing. Run the command below:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-hLFsX wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;$ npx expo install react-native-purchases react-native-purchase-ui&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;If you run into problems with the setup,&lt;a href=&quot;https://www.revenuecat.com/docs/getting-started/installation/reactnative&quot;&gt; see this for guidance.&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;We want RevenueCat to be initialized on app start, add this piece of code to entry file of your app, in our example project that means the layout&amp;nbsp; file:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Z18PnC7 wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;\/\/ _layout.tsx\n\nimport { Stack } from \&amp;quot;expo-router\&amp;quot;;\nimport { useEffect } from \&amp;quot;react\&amp;quot;;\nimport { Platform } from \&amp;quot;react-native\&amp;quot;;\nimport Purchases from \&amp;quot;react-native-purchases\&amp;quot;;\nimport mobileAds from \&amp;quot;react-native-google-mobile-ads\&amp;quot;;\n\nexport default function RootLayout() {\n  useEffect(() =&gt; {\n    \/\/ Initialize mobile ads\n    mobileAds()\n      .initialize()\n      .then(adapterStatuses =&gt; {\n        console.log(&apos;Mobile ads initialized successfully&apos;);\n      })\n      .catch(error =&gt; {\n        console.error(&apos;Failed to initialize mobile ads:&apos;, error);\n      });\n\n  }, []);\n\n  useEffect(() =&gt; {\n    \/\/ Enable development logging\n    Purchases.setLogLevel(Purchases.LOG_LEVEL.DEBUG);\n    if (Platform.OS === \&amp;quot;ios\&amp;quot;) {\n      Purchases.configure({ apiKey: \&amp;quot;your_ios_api_key\&amp;quot; });\n    } else if (Platform.OS === \&amp;quot;android\&amp;quot;) {\n      Purchases.configure({ apiKey: \&amp;quot;your_android_api_key\&amp;quot; });\n    }\n  }, []);\n\n  return &lt;Stack screenOptions={{ title: \&amp;quot;Article\&amp;quot; }} \/&gt;;\n}\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;This code runs on app mount. Replace placeholder &lt;strong&gt;&lt;em&gt;apiKeys&lt;/em&gt;&lt;/strong&gt; with your RevenueCat Project Settings keys. If you see RevenueCat error logs in the console, review and fix them.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-checking-user-entitlements&quot;&gt;Checking user entitlements&lt;/h3&gt;



&lt;p&gt;To keep track whether a user has purchased a subscription and is eligible for ad-free experience, we implement a custom hook for checking the subscription status. Add this code for in a separate file called &lt;strong&gt;&lt;em&gt;useIsAdFree.ts&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;



&lt;p&gt;Import the hook in &lt;strong&gt;&lt;em&gt;index.tsx&lt;/em&gt;&lt;/strong&gt;, make the following changes to the app code, and save them. Most things should be the same now, but you should see a loader when the app loads.&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-implement-purchasing-functionality&quot;&gt;Implement purchasing functionality&lt;/h3&gt;



&lt;p&gt;Now that we can check if a user has purchased a subscription, it’s time to implement the purchasing functionality. Create a new file called &lt;strong&gt;&lt;em&gt;usePurchaseSubscription.ts&lt;/em&gt;&lt;/strong&gt;:&lt;/p&gt;



&lt;p&gt;In a real case you should handle the error differently, but this works for now, since we’re only using a single product in our app for now.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Next, change the &lt;strong&gt;&lt;em&gt;index.tsx&lt;/em&gt;&lt;/strong&gt; code to have a button for calling the purchase subscription function:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-Zc3Ezo wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;\/\/ useIsAdFree.ts\nimport { useEffect, useState } from \&amp;quot;react\&amp;quot;;\nimport Purchases from \&amp;quot;react-native-purchases\&amp;quot;;\n\nexport const useIsAdFree = () =&gt; {\n  const [adFree, setAdFree] = useState(false);\n  const [loading, setLoading] = useState(true);\n\n  useEffect(() =&gt; {\n    const checkCustomerEntitlement = async () =&gt; {\n      try {\n        setLoading(true);\n        const customerInfo = await Purchases.getCustomerInfo();\n\n        const entitlementActive =\n          customerInfo?.entitlements?.active?.[\&amp;quot;ad_free_entitlement\&amp;quot;];\n        setAdFree(!!entitlementActive);\n      } catch (error) {\n        console.error(\&amp;quot;Error checking customer entitlement:\&amp;quot;, error);\n        setAdFree(false);\n      } finally {\n        setLoading(false);\n      }\n    };\n\n    checkCustomerEntitlement();\n  }, []);\n\n  return { adFree, loading };\n};\n&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;Test your app by pressing on the button and buying the subscription. If all goes well, you should see a loader after which the ads disappear and you can enjoy your content ad free.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-conclusion&quot;&gt;Conclusion&lt;/h2&gt;



&lt;p&gt;Nice job, you’ve reached the end of this tutorial and you now have an app allowing users to subscribe to unlock an ad-free reading experience. Although this is a very good start, getting your app accepted for distribution will require building a few more features such as restoring purchases. We’ve collected some additional reading here for you to continue building the best possible in-app purchases experience:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/plahteenlahti/ad-iap-example/tree/finished-demo&quot;&gt;Example project with the full code we wrote in this tutorial&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/tools/paywalls&quot;&gt;Creating Paywalls in Revenuecat&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/getting-started/restoring-purchases&quot;&gt;Restoring purchases&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/test-and-launch/sandbox&quot;&gt;Testing subscriptions&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.revenuecat.com/docs/test-and-launch/launch-checklist&quot;&gt;App Subscription Launch Checklist&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[How to build a Blinkist-style paywall using RevenueCat webhooks and Zapier]]></title><description><![CDATA[Build a Blinkist-style paywall with RevenueCat and Zapier—no backend required.]]></description><link>https://www.revenuecat.com/blog/engineering/how-to-build-a-blinkist-style-paywall-using-revenuecat-webhooks-and-zapier/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/engineering/how-to-build-a-blinkist-style-paywall-using-revenuecat-webhooks-and-zapier/</guid><pubDate>Fri, 20 Jun 2025 11:36:27 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/1.-How-to-build-a-Blinkist-style-paywall-automation-with-Zapier-and-RevenueCat-Webhooks.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;Paywalls V2 makes it possible to create more sophisticated, user-friendly paywalls—including one inspired by Blinkist. In this guide, we’ll walk you through recreating the logic behind Blinkist’s timeline-style paywall using RevenueCat Webhooks and Zapier.&lt;/p&gt;



&lt;p&gt;We won’t focus heavily on paywall design (though we’ll briefly cover it). Instead, the goal is to automate trust-building messaging, such as sending reminders before a trial ends. You don’t need to write any backend code. With a few clicks and some setup, you can build an end-to-end workflow that boosts transparency and improves conversion.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-what-makes-the-blinkist-paywall-different&quot;&gt;What makes the Blinkist paywall different&lt;/h3&gt;



&lt;p&gt;The most common approach to paywalls is one that highlights the features users will get after purchasing. While this works when the user is already familiar with the product or accustomed to buying subscriptions, it doesn’t do much to reduce the fear of subscribing—especially for new users.&lt;/p&gt;



&lt;p&gt;If your user acquisition strategy relies on a “try before you buy” approach, i.e. offering a free trial, the key to conversion becomes reducing that fear.&lt;/p&gt;



&lt;p&gt;The Blinkist paywall does exactly this—reduces fear through clearer communication. Instead of focusing on features, the paywall displays a simple timeline outlining what happens after the user subscribes. The timeline usually includes at least the following three elements:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-1-start-with-a-free-trial&quot;&gt;1. Start with a free trial&lt;/h3&gt;



&lt;p&gt;The user is clearly informed that they won’t be charged immediately. Instead, they get a free trial, typically seven days, to try the app.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-2-remind-before-trial-ends&quot;&gt;2. Remind before trial ends&lt;/h3&gt;



&lt;p&gt;A few days before the subscription converts to a paid one, the user is notified (e.g. via email or push). This gives them a chance to cancel if they’re not interested. Mentioning this in the timeline directly helps ease concerns about being charged unexpectedly.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-3-show-trial-end-date-up-front&quot;&gt;3. Show trial end date up front&lt;/h3&gt;



&lt;p&gt;The timeline explicitly states the day the trial ends and billing begins. This gives users a clear expectation and helps build trust from the start.&lt;/p&gt;



&lt;p&gt;This style of paywall not only builds trust, but it also leads to measurable improvements in key business metrics:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Higher opt-in and trial conversion rates&lt;/li&gt;



&lt;li&gt;Fewer customer support issues related to billing confusion&lt;/li&gt;



&lt;li&gt;Stronger engagement with push notifications and emails&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-implement-the-timeline-in-revenuecat&quot;&gt;Implement the timeline in RevenueCat&lt;/h2&gt;



&lt;p&gt;In RevenueCat Paywall builder, this component is called Timeline, and you can add it to any of your existing paywalls, or if you want to create a new paywall, you can also start with the paywall sample that has it already included. You only need to tweak some of the content of the timeline to match the dates of your trial.&lt;/p&gt;



&lt;p&gt;&lt;br&gt;To learn more about timeline design, see&lt;a href=&quot;https://www.youtube.com/watch?v=aJp7m4TYK7E&quot;&gt; Charlie’s video about it&lt;/a&gt;.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image&quot;&gt;&lt;img decoding=&quot;async&quot; src=&quot;https://lh7-rt.googleusercontent.com/docsz/AD_4nXcfROUd-vF6JPUatcbMenOWPmtAhyawjifnKMuSGfB1dgDYzPD0_7nJgrt-CYlnSwFQQtVLcugZo35OM9GJQOtR5-84xB01eNn1xCWAmlWkiUp_EVP-qxWg1YowfTBkxp7XUYQPUw?key=NA0hbEhH-Bk1r485Zvm0JSMx&quot; alt=&quot;Example of the timeline paywall in RevenueCat paywall builder&quot;&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-tools-for-building-automations&quot;&gt;Tools for building automations&lt;/h2&gt;



&lt;p&gt;To automate notifications like “Your trial is ending soon,” we’ll use RevenueCat webhooks to detect subscription events and Zapier to handle the actual messaging (e.g. email or push).&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-why-use-zapier&quot;&gt;Why Use Zapier?&lt;/h3&gt;



&lt;p&gt;Zapier lets you create automations (called Zaps) without writing any backend code. This allows us to build the automation without having to include an engineer in this, instead only requiring access to RevenueCat and Zapier.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Go through Zapier’s onboarding. Once you’re done, come back to this guide to connect RevenueCat and Zapier.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-revenuecat-webhooks&quot;&gt;RevenueCat Webhooks&lt;/h3&gt;



&lt;p&gt;RevenueCat can send notifications (webhooks) to your server or a tool like Zapier whenever something happens in a user’s subscription lifecycle—such as starting a trial, renewing, or canceling. You can find more information about the webhooks in the &lt;a href=&quot;https://www.revenuecat.com/docs/integrations/webhooks&quot;&gt;webhooks documentation&lt;/a&gt;.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-build-the-trial-automation&quot;&gt;Build the trial automation&lt;/h2&gt;



&lt;p&gt;Before we start building our automation in Zapier, let’s outline how our Zap should work: &lt;/p&gt;



&lt;p&gt;1. We want to capture all the webhook events about started subscriptions. Since we are only interested in events which are for trials, and not for example win-back subscriptions, we need a way to filter either on RevenueCat side or in Zapier.&lt;/p&gt;



&lt;p&gt;2. Once we call the webhook from Zapier, we need the email of the user so we can send them a confirmation two days before their trial ends. You can include this in the webhook call, but you must &lt;a href=&quot;https://www.revenuecat.com/docs/customers/identifying-customers&quot;&gt;identify the customer to RevenueCat when you initialize the SDK&lt;/a&gt; or fetch the users email and id from your own backend to match the subscription event with the correct user.&lt;/p&gt;



&lt;p&gt;Rather than sending the email immediately, we’ll use &lt;strong&gt;Zapier’s Delay&lt;/strong&gt; step to wait five days, timing the message to arrive two days before the subscription converts to paid.&lt;/p&gt;



&lt;p&gt;3. We need a way to monitor unsubscribe events so that users who cancel don’t receive the reminder.&lt;/p&gt;



&lt;p&gt;Start a new Zap by selecting &lt;strong&gt;Create&lt;/strong&gt; and then &lt;strong&gt;Zaps&lt;/strong&gt;, and you will see something like the image below:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image&quot;&gt;&lt;img decoding=&quot;async&quot; src=&quot;https://lh7-rt.googleusercontent.com/docsz/AD_4nXdMddt-iX_WV9dgUl5qGJnR5rU4-kUuXukNsYjGwBhcx39Twug3BYH64SbV2lth5sH_ekdWEDiEj1aP_hdazOJYZWG85IbpQpznTAcMzw2piOz53vzRTu_N2S8aOMMnyxu7QEjj7w?key=NA0hbEhH-Bk1r485Zvm0JSMx&quot; alt=&quot;Screenhot of Zapier dashboard before building the automation&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-1-nbsp-capture-webhooks-from-revenuecat&quot;&gt;Step 1:&amp;nbsp; Capture webhooks from RevenueCat&lt;/h3&gt;



&lt;p&gt;For our first step we need to configure our Zap to receive events from Revenuecat. For that we need to select and add a new webhook. For the trigger event select Catch Hook. In the configuration tab for the field Pick off a Child Key add this&lt;br&gt;&lt;/p&gt;



&lt;p&gt;event.subscriber_attributes.$email.value&lt;/p&gt;



&lt;p&gt;This will ensure that we will capture the email from all the subscriber attributes, allowing us to use it later for sending email.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image&quot;&gt;&lt;img decoding=&quot;async&quot; src=&quot;https://lh7-rt.googleusercontent.com/docsz/AD_4nXfn0QZSWWPJd-326_Mj6jRhSQdxo1YYoWuEdsTmmBjjYNXMKBhawJUh_6N9jZX_Y_E6IQ8V77-6oywbCSROZNRz3eDj4kvQSQMUj6q1Oc6DHRGWXsArtop2PPqnA_dJpp8A3MKa?key=NA0hbEhH-Bk1r485Zvm0JSMx&quot; alt=&quot;Screenshot of the catch hook configuration in Zapier&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Zapier will now prompt you to test the webhook. Copy the webhook URL and navigate to RevenueCat Dashboard. From the Integrations section in the sidebar, press &lt;strong&gt;New&lt;/strong&gt;, and select &lt;strong&gt;Webhooks&lt;/strong&gt;. Click to add new Webhook configuration. Name your webhook for example Zapier | Trial Reminder, paste the webhook URL here, and select Sandbox for the&lt;strong&gt; Environment to send events for&lt;/strong&gt;, we can change it to include Production once we’ve tested our app. Lastly, you can configure if any of your apps should be filtered from sending events, before clicking &lt;strong&gt;add webhook.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Now we can test if your Webhook works correctly. Open your webhook if you have not already, and click the button &lt;strong&gt;Send test event&lt;/strong&gt;. Now go back to the Zapier dashboard and click&lt;strong&gt; Find new records&lt;/strong&gt; and you should see a JSON response that looks something like this:&lt;/p&gt;


&lt;div class=&quot;lazyblock-b77fda85b8ba-18a3Re wp-block-lazyblock-b77fda85b8ba&quot;&gt;&lt;blogpostcode language=&quot;javascript&quot; content=&quot;&amp;quot;{\n  \&amp;quot;event\&amp;quot;: {\n    \&amp;quot;event_timestamp_ms\&amp;quot;: 1746471203817,\n    \&amp;quot;product_id\&amp;quot;: \&amp;quot;test_product\&amp;quot;,\n    \&amp;quot;period_type\&amp;quot;: \&amp;quot;NORMAL\&amp;quot;,\n    \&amp;quot;purchased_at_ms\&amp;quot;: 1746471203817,\n    \&amp;quot;expiration_at_ms\&amp;quot;: 1746478403817,\n    \&amp;quot;environment\&amp;quot;: \&amp;quot;SANDBOX\&amp;quot;,\n    \&amp;quot;entitlement_id\&amp;quot;: null,\n    \&amp;quot;entitlement_ids\&amp;quot;: [],\n    \&amp;quot;presented_offering_id\&amp;quot;: null,\n    \&amp;quot;transaction_id\&amp;quot;: null,\n    \&amp;quot;original_transaction_id\&amp;quot;: null,\n    \&amp;quot;is_family_share\&amp;quot;: null,\n    \&amp;quot;country_code\&amp;quot;: \&amp;quot;US\&amp;quot;,\n    \&amp;quot;app_user_id\&amp;quot;: \&amp;quot;1bf2f016-d74e-43fc-b3fa-b61156a03799\&amp;quot;,\n    \&amp;quot;aliases\&amp;quot;: [\n      \&amp;quot;1bf2f016-d74e-43fc-b3fa-b61156a03799\&amp;quot;,\n      \&amp;quot;863ee341-6e5b-4dda-b279-f73b77070460\&amp;quot;\n    ],\n    \&amp;quot;original_app_user_id\&amp;quot;: \&amp;quot;1bf2f016-d74e-43fc-b3fa-b61156a03799\&amp;quot;,\n    \&amp;quot;currency\&amp;quot;: null,\n    \&amp;quot;price\&amp;quot;: null,\n    \&amp;quot;price_in_purchased_currency\&amp;quot;: null,\n    \&amp;quot;subscriber_attributes\&amp;quot;: {\n      \&amp;quot;$email\&amp;quot;: {\n        \&amp;quot;value\&amp;quot;: \&amp;quot;tuxedo@revenuecat.com\&amp;quot;,\n        \&amp;quot;updated_at_ms\&amp;quot;: 1746471203817\n      },\n      \&amp;quot;$displayName\&amp;quot;: {\n        \&amp;quot;value\&amp;quot;: \&amp;quot;Mister Mistoffelees\&amp;quot;,\n        \&amp;quot;updated_at_ms\&amp;quot;: 1746471203817\n      },\n      \&amp;quot;$phoneNumber\&amp;quot;: {\n        \&amp;quot;value\&amp;quot;: \&amp;quot;+19795551234\&amp;quot;,\n        \&amp;quot;updated_at_ms\&amp;quot;: 1746471203817\n      },\n      \&amp;quot;my_custom_attribute_1\&amp;quot;: {\n        \&amp;quot;value\&amp;quot;: \&amp;quot;catnip\&amp;quot;,\n        \&amp;quot;updated_at_ms\&amp;quot;: 1746471203817\n      }\n    },\n    \&amp;quot;store\&amp;quot;: \&amp;quot;PLAY_STORE\&amp;quot;,\n    \&amp;quot;takehome_percentage\&amp;quot;: null,\n    \&amp;quot;offer_code\&amp;quot;: null,\n    \&amp;quot;tax_percentage\&amp;quot;: null,\n    \&amp;quot;commission_percentage\&amp;quot;: null,\n    \&amp;quot;metadata\&amp;quot;: null,\n    \&amp;quot;renewal_number\&amp;quot;: null,\n    \&amp;quot;type\&amp;quot;: \&amp;quot;TEST\&amp;quot;,\n    \&amp;quot;id\&amp;quot;: \&amp;quot;665CA53F-301D-46D3-A977-20C8A3EF336F\&amp;quot;,\n    \&amp;quot;app_id\&amp;quot;: \&amp;quot;app54c5dea9ab\&amp;quot;,\n    \&amp;quot;api_version\&amp;quot;: \&amp;quot;1.0\&amp;quot;,\n    \&amp;quot;querystring\&amp;quot;: null\n  }\n}&amp;quot;&quot;&gt;
&lt;/blogpostcode&gt;&lt;/div&gt;


&lt;p&gt;The webhook response includes a lot of valuable information. If you want, you can use this information to customize the email we are going to use later, for example by providing different copy based on which store the user subscribed from. If everything looks good press &lt;strong&gt;Continue with selected record.&lt;/strong&gt;&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-2-add-a-delay-to-the-automation&quot;&gt;Step 2: Add a delay to the automation&lt;/h3&gt;



&lt;p&gt;Next step we need to implement is the waiting for 5 days after subscription has started before sending the user a reminder of their subscription continuing for the full price. Press the &lt;strong&gt;+ button&lt;/strong&gt; to add a new step, and select &lt;strong&gt;Delay by Zapier&lt;/strong&gt;. In the setup tab select Delay for as the &lt;strong&gt;Action event&lt;/strong&gt;. In the configuration tab select “5” for &lt;strong&gt;Time delayed for (value)&lt;/strong&gt; and for the Unit select Days.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image&quot;&gt;&lt;img decoding=&quot;async&quot; src=&quot;https://lh7-rt.googleusercontent.com/docsz/AD_4nXfLbzTkcxG4zoLarJPRI6veHSZ3ryUmk8uyQrBGcGhEKLSfT9eKzOPgyaL7QaX7uQECW8Lnemi0adOZLNKG7xne2GsT_oaDQ-IJoGp34IE4ncoPDwo8-J5tjmrkGG6s2TOMi7F47Q?key=NA0hbEhH-Bk1r485Zvm0JSMx&quot; alt=&quot;Screenshot of the Delay by Zapier automation&quot;&gt;&lt;/figure&gt;



&lt;p&gt;You can adapt the delay time to the amount of time your timeline logic requires. During testing you can also set it to something like 5 minutes, so that you only need to wait briefly during testing before seeing the email.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-3-send-reminder-email-nbsp&quot;&gt;Step 3: Send reminder email&amp;nbsp;&lt;/h3&gt;



&lt;p&gt;Now, we just need to configure the email that will be sent. Zapier integrates with many email providers, allowing you to choose the service that best fits your needs. For simple setups or testing, you can use &lt;strong&gt;Email by Zapier&lt;/strong&gt; to quickly send a basic, unstyled message, for example: &lt;em&gt;“Your subscription will continue in 2 days.”&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;However, for production use or more polished communications, consider using a dedicated email service such as &lt;strong&gt;Mailchimp&lt;/strong&gt;, &lt;strong&gt;Postmark&lt;/strong&gt;, &lt;strong&gt;SendGrid&lt;/strong&gt;, or &lt;strong&gt;Customer.io&lt;/strong&gt;. These services offer better deliverability, customization, analytics, and support for branded templates.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image&quot;&gt;&lt;img decoding=&quot;async&quot; src=&quot;https://lh7-rt.googleusercontent.com/docsz/AD_4nXcOQBR6ij-5l5dos03cw5PODUh7rkRg_2-JfjMCxoua4sRd6h12pn5_yX-wpvyVdGdN-4d9g00xsnvSQisUOwgjouMNAQm2LFXcVMwIRb5gUkKrg3uzBvjGtSEBAH7F52a-u6mt?key=NA0hbEhH-Bk1r485Zvm0JSMx&quot; alt=&quot;Screenshot the outbound email template in Zapier&quot;&gt;&lt;/figure&gt;



&lt;p&gt;I added my personal email as the CC field value so that I can see all the testing emails. If you ended up doing the same, better to remove this value.&lt;/p&gt;



&lt;p&gt;After all this our Zap should look something like this:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image&quot;&gt;&lt;img decoding=&quot;async&quot; src=&quot;https://lh7-rt.googleusercontent.com/docsz/AD_4nXdAC0MwaA4_Rc_bhnTaYkZIvf6HiVrgy19jBD7nuzFROW-FhUHTq3LmfFKMwSxjvlKncC3Cy5bVMmNBTaSNrYCPhdmxiMhq_ttnWfhTeJxllmxr2lq8I4a0aST-CoF95gnK1bd-?key=NA0hbEhH-Bk1r485Zvm0JSMx&quot; alt=&quot;Our finished Zapier automation that enables sending emails when user subscribes&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-step-4-test-the-automation&quot;&gt;Step 4: Test the automation&lt;/h3&gt;



&lt;p&gt;Our Zap is now ready so let’s test that everything works. Because we don’t want to wait for 5 days after subscribing, let’s go back and change the delay from days to minutes. Now we just need to fire the subscription event. You can either go to your app to start a new subscription or you can add yourself into the CC field in the Send outbound email step and fire the test event. RevenueCat will send this email to a dummy email. After 5 minutes you should see an email in your inbox. After that, remember to go back to change the delay back to days.&lt;/p&gt;



&lt;p&gt;Change the 5 minutes back to days and hit publish and you have a fully functioning automation for notifying users before their trial ends!&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-conclusion&quot;&gt;Conclusion&lt;/h2&gt;



&lt;p&gt;You should now have a working automation that listens to RevenueCat webhooks and sends a reminder email five days after a user starts a subscription. This setup provides a solid foundation for building trust and reducing churn during the trial period.&lt;/p&gt;



&lt;p&gt;To take things further, you can:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Add filtering logic to ensure reminders are only sent for new users with a 7-day trial. All the necessary data to do this is available in the webhook payload.&lt;/li&gt;



&lt;li&gt;Introduce A/B testing to experiment with different messaging, timing, or channels to see what improves conversion most effectively.&lt;/li&gt;



&lt;li&gt;Send push notifications in addition to or instead of emails, especially if your app has strong in-app engagement. Zapier or other tools like OneSignal or Firebase can help with this.&lt;/li&gt;



&lt;li&gt;Personalize your messages based on attributes like the user’s name, platform (iOS vs Android), or acquisition channel. These attributes can be passed through RevenueCat and used to tailor the experience.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[7 Meta ad testing frameworks for subscription apps]]></title><description><![CDATA[Balancing speed and accuracy with creative testing]]></description><link>https://www.revenuecat.com/blog/growth/7-meta-ad-testing-frameworks-for-subscription-apps/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/7-meta-ad-testing-frameworks-for-subscription-apps/</guid><pubDate>Thu, 19 Jun 2025 11:14:25 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/7-meta-ad-testing-frameworks-for-subscription-apps.png" length="0" type="image/*"/><content:encoded>&lt;p&gt;“Don’t wait for statistical significance, it’s going to limit how fast you can move.”&amp;nbsp;&lt;/p&gt;



&lt;p&gt;My heart dropped when Cedric said this so casually, as we discussed common testing mistakes in Meta ad experiments.&lt;/p&gt;



&lt;p&gt;I tried to collect myself as an interviewer while he continued, “The top advertisers are launching hundreds of ads, so it’s worth giving up on significance and valuing the learnings overall, rather than trying to create a perfectly fair test setup. Even if you reupload an ad, [Meta] recognizes what’s different and what’s not.”&lt;/p&gt;



&lt;p&gt;It felt like the opposite of everything I’d learned and loved about data: statistical significance gives you confidence; the confidence to stand behind an experiment and trust its results. But that isn’t where Cedric Yarish, co-founder of &lt;a href=&quot;http://admanage.ai&quot;&gt;AdManage.ai&lt;/a&gt;, a fast-growing ad management platform, places his trust. He trusts Meta and the signals it provides.&lt;/p&gt;



&lt;p&gt;This isn’t just gut feeling, it’s backed by Cedric’s experience managing multi-million dollar ad budgets at &lt;a href=&quot;https://www.photoroom.com/&quot;&gt;Photoroom&lt;/a&gt;, along with a wide range of high-growth subscription apps like Speechify and Clearminds. He’s tested seven different ad experimentation structures, and his clear takeaway? Trust Meta over statistical significance (even if it breaks my data-driven heart).&lt;/p&gt;



&lt;p&gt;As he explained, even if an ad has only spent $2, it’s already gained a few hundred to a thousand impressions, and with all the additional signals Meta has access to, it’s usually right.&lt;/p&gt;



&lt;p&gt;If that left you reeling, you’re not alone. Our hour-long conversation was a deep dive into:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;What to consider when testing on iOS&lt;/li&gt;



&lt;li&gt;All seven methods for experimenting on Meta&lt;/li&gt;



&lt;li&gt;The advantages and disadvantages of each approach&lt;/li&gt;



&lt;li&gt;His favorite method and why&lt;/li&gt;



&lt;li&gt;Common pitfalls in ad experimentation&lt;/li&gt;



&lt;li&gt;How to know if an ad has real potential&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Everyone approaches experimenting on Meta differently. I’ve seen it firsthand, nosing through 50+ ad accounts over the past ten years—one marketer swears by one ad per ad set, while another is all-in on what used to be called dynamic ads, and is now known as flexible ads.&lt;/p&gt;



&lt;p&gt;It’s time to figure out what &lt;em&gt;actually&lt;/em&gt; works for you—especially if speed of testing is your priority.&lt;/p&gt;



&lt;p&gt;Still need convincing that Cedric knows his stuff? Here’s how many ads are currently being tested through his platform:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;451&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/admanage-ai-status-1024x451.png&quot; alt=&quot;&quot; class=&quot;wp-image-43234&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/admanage-ai-status-1024x451.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/admanage-ai-status-300x132.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/admanage-ai-status-768x338.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/admanage-ai-status-91x40.png 91w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/admanage-ai-status-696x307.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/admanage-ai-status-560x247.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/admanage-ai-status-840x370.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/admanage-ai-status-80x35.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/admanage-ai-status-48x21.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/admanage-ai-status.png 1525w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;a href=&quot;http://admanage.ai&quot;&gt;&lt;em&gt;Admanage.ai status on ads testing&lt;/em&gt;&amp;nbsp;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Woah.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;He has visibility into &lt;strong&gt;over 68,000 ads at any given time&lt;/strong&gt;. Together with his brother, &lt;a href=&quot;https://www.linkedin.com/in/raphaelyarish/&quot;&gt;Raphael Yarish&lt;/a&gt;, Cedric has combined nearly two decades of performance marketing experience to build AdManage: a tool designed to test hundreds of ads in seconds.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;769&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/cedric-yarish-1024x769.png&quot; alt=&quot;&quot; class=&quot;wp-image-43236&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/cedric-yarish-1024x769.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/cedric-yarish-300x225.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/cedric-yarish-768x576.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/cedric-yarish-1536x1153.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/cedric-yarish-53x40.png 53w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/cedric-yarish-618x464.png 618w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/cedric-yarish-696x522.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/cedric-yarish-560x420.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/cedric-yarish-394x296.png 394w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/cedric-yarish-629x472.png 629w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/cedric-yarish-80x60.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/cedric-yarish-48x36.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/cedric-yarish.png 1600w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;Before we dive in, one quick caveat: when testing subscription ads, consider the limitations on campaign and ad set numbers for iOS. If you’re already familiar with this, feel free to skip ahead to the frameworks.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;ios-testing-limitations&quot;&gt;&lt;strong&gt;iOS testing limitations&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;When it comes to testing on iOS 14+, there are a few important limitations to keep in mind. While Android and Web give you much more freedom to test at scale, &lt;a href=&quot;https://en-gb.facebook.com/business/help/651033805513936?id=428636648170202&quot;&gt;iOS limits the number of campaigns&lt;/a&gt; and ad sets available per app ID.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;You’re limited to:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;18 active campaigns&lt;/li&gt;



&lt;li&gt;5 active ad sets per campaign&lt;/li&gt;



&lt;li&gt;50 ads per ad set&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Now, you &lt;em&gt;can&lt;/em&gt; run more campaigns for earlier iOS versions (13.7 or earlier) or test first on Android or Web. &lt;strong&gt;Advantage+ campaigns&lt;/strong&gt; also come with fewer restrictions, so they can be a smart workaround if your testing needs are more complex.&lt;/p&gt;



&lt;p&gt;For smaller advertisers, these limits usually aren’t an issue; you’ll likely have just a few campaigns running in early phases. But for larger advertisers, especially those testing across multiple countries and languages, it can get tricky fast.&lt;/p&gt;



&lt;p&gt;That’s why factoring these limitations into your framework decisions is crucial. Since most apps generate the majority of their revenue from iOS users, ideally, you want to test on iOS where possible. But if you’re prioritizing volume or precision in your testing, Android or Web might be better starting points.&lt;/p&gt;



&lt;p&gt;Another reason this matters: &lt;strong&gt;the second you switch the destination link from Android or Web to iOS, you lose all the likes and comments.&lt;/strong&gt; And social proof—likes, shares, and comments—&lt;em&gt;does&lt;/em&gt; matter. Ads with strong social proof consistently perform better.&lt;/p&gt;



&lt;p&gt;In e-commerce, it’s easier to preserve social proof using post IDs, because the product link doesn’t change. But for mobile apps, switching between iOS, Android, or Web resets that engagement history. So, if possible, test on the channel you plan to scale: &lt;strong&gt;to keep those likes and comments intact&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;Now, let’s get into the experimentation frameworks. If you’ve been running ads for a while, some of these will definitely sound familiar. Buckle up, we have a lot of frameworks to get through today.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;testing-framework-1-advantage-campaign-with-5-ads&quot;&gt;Testing Framework 1: Advantage+ campaign with 5 ads&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;407&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/What-testing-framework-1-looks-like-in-Meta-Ads-Manager-1024x407.png&quot; alt=&quot;&quot; class=&quot;wp-image-43238&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/What-testing-framework-1-looks-like-in-Meta-Ads-Manager-1024x407.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/What-testing-framework-1-looks-like-in-Meta-Ads-Manager-300x119.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/What-testing-framework-1-looks-like-in-Meta-Ads-Manager-768x306.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/What-testing-framework-1-looks-like-in-Meta-Ads-Manager-101x40.png 101w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/What-testing-framework-1-looks-like-in-Meta-Ads-Manager-696x277.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/What-testing-framework-1-looks-like-in-Meta-Ads-Manager-560x223.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/What-testing-framework-1-looks-like-in-Meta-Ads-Manager-840x334.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/What-testing-framework-1-looks-like-in-Meta-Ads-Manager-80x32.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/What-testing-framework-1-looks-like-in-Meta-Ads-Manager-48x19.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/What-testing-framework-1-looks-like-in-Meta-Ads-Manager.png 1048w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;What testing framework 1 looks like in Meta Ads Manager&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;“It’s the golden age of apps,” Cedric Yarish says excitedly. “It’s super easy to launch an app.”&lt;/p&gt;



&lt;p&gt;He’s not wrong, everyone left, right, and center seems to be launching an app (usually AI-powered). But just because it’s easy to launch doesn’t mean it’s easy to grow. Many of the new app developers Cedric meets have never run a Facebook ad before—and often have little to no marketing experience.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;For those just getting started, Framework 1 is usually the best&lt;/strong&gt;. It’s simple, accessible, and requires minimal knowledge of ad setup.&lt;/p&gt;



&lt;p&gt;How it works:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Create an Advantage+ campaign with “Trial Started” as the conversion goal&lt;/li&gt;



&lt;li&gt;Use the built-in Advantage+ audience (Meta will only allow one ad set here)&lt;/li&gt;



&lt;li&gt;Upload five ads to test&lt;/li&gt;



&lt;li&gt;At the end of the week, keep what’s working and rotate out the rest&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Your campaign structure will look something like this:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Campaign
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Advantage+ Audience
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Ad 1&lt;/li&gt;



&lt;li&gt;Ad 2&lt;/li&gt;



&lt;li&gt;Ad 3&lt;/li&gt;



&lt;li&gt;Ad 4&lt;/li&gt;



&lt;li&gt;Ad 5&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Even if Meta doesn’t spend on one or two of the ads, no stress—you pause them and test something new. Typically, Meta will allocate ~80% of spend to the top three ads, and the rest can be used to cycle in new creatives.&lt;/p&gt;



&lt;p&gt;Cedric usually &lt;strong&gt;recommends that founders start with a&lt;/strong&gt; &lt;strong&gt;hook + product demo&lt;/strong&gt; format for creatives. Think low-fi, user-generated-style videos—simple, scrappy, and effective. Then just run five ads and iterate based on results. If your cost per trial is too high, it might also signal a need for product tweaks (in my experience, this is more common than people expect).&lt;/p&gt;



&lt;p&gt;This framework is all about building initial learnings and insights &lt;em&gt;before&lt;/em&gt; moving into a more complex setup.&lt;/p&gt;



&lt;p&gt;Now, the disadvantage of this approach is that &lt;strong&gt;you’re optimizing for trials rather than paid subscribers&lt;/strong&gt; as your key event (assuming your app offers a trial). But at this early stage, you need data, and you might not have the technical support to track subscriptions properly yet. Cedric recommends using cost per trial as your main metric. If that’s not working, fall back to cost per install, and then use tools like RevenueCat to double-check user quality. It’s not ideal, but it works when you’re operating with a smaller ad budget.&lt;/p&gt;



&lt;p&gt;Another drawback is that you’re probably only testing 2–3 ads per week. That’s why &lt;strong&gt;this framework is better suited to smaller budgets&lt;/strong&gt;, e.g., under $5,000/month.&lt;/p&gt;



&lt;p&gt;If this framework feels too basic for you, Option 2 might be a better fit—especially for brands ready to scale faster.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;testing-framework-2-one-ad-per-ad-set&quot;&gt;Testing Framework 2 – One ad per ad set&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;565&quot; height=&quot;344&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/What-testing-framework-2-looks-like-in-Meta-Ads-Manager.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-43240&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/What-testing-framework-2-looks-like-in-Meta-Ads-Manager.jpg 565w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/What-testing-framework-2-looks-like-in-Meta-Ads-Manager-300x183.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/What-testing-framework-2-looks-like-in-Meta-Ads-Manager-66x40.jpg 66w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/What-testing-framework-2-looks-like-in-Meta-Ads-Manager-560x341.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/What-testing-framework-2-looks-like-in-Meta-Ads-Manager-486x296.jpg 486w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/What-testing-framework-2-looks-like-in-Meta-Ads-Manager-80x49.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/What-testing-framework-2-looks-like-in-Meta-Ads-Manager-48x29.jpg 48w&quot; sizes=&quot;auto, (max-width: 565px) 100vw, 565px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;What testing framework 2 looks like in Meta Ads Manager&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;If you’re a classic Type A like me, you’ll love this framework—it’s the ultimate control setup with &lt;em&gt;zero&lt;/em&gt; faith in Meta’s optimization. The structure is simple and gives you full visibility:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;1 Campaign with budgets set at ad level (ABO)
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Ad set 1
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Ad 1&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;



&lt;li&gt;Ad set 2
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Ad 2&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;



&lt;li&gt;Ad set 3
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Ad 3&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;



&lt;li&gt;Ad set 4
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Ad 4&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;



&lt;li&gt;Ad set 5
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Ad 5&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Apparently, it’s not just us Type A folks who love this setup. According to Cedric, people with affiliate marketing backgrounds often lean toward this framework too. Makes sense—you’re properly testing each ad and guaranteeing it gets a minimum spend, which gives you far more clarity on performance.&lt;/p&gt;



&lt;p&gt;I’ve found this is great for newer brands (another reason I like this framework, given that I’m mainly working with startups). Assets cost more to create at the start as you don’t have economies of scale, so you want to be confident you’ve tested them properly. Also, when using ads to test more fundamental areas—like messaging or target audience—you don’t want to make a decision after just $2 of spend.&lt;/p&gt;



&lt;p&gt;However, it is slow (which explains why Cedric is less a fan of it) and harder to set up. &lt;strong&gt;So while it can work really well for smaller brands, it gets a bit tiresome when you want to be testing 100s of ads.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;The limitations of iOS we discussed at the beginning also make this technique tricky. Cedric tends to see brands use this approach on Android and Web first, where it’s easier to manage, and then scale up their budget once they have a winning creative or message.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;testing-framework-3-meta-ab-testing-feature&quot;&gt;Testing Framework 3 – Meta A/B testing feature&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;650&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/How-to-use-Meta-Ads-AB-testing-feature-1024x650.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-43242&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/How-to-use-Meta-Ads-AB-testing-feature-1024x650.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/How-to-use-Meta-Ads-AB-testing-feature-300x190.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/How-to-use-Meta-Ads-AB-testing-feature-768x487.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/How-to-use-Meta-Ads-AB-testing-feature-63x40.jpg 63w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/How-to-use-Meta-Ads-AB-testing-feature-696x442.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/How-to-use-Meta-Ads-AB-testing-feature-560x355.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/How-to-use-Meta-Ads-AB-testing-feature-467x296.jpg 467w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/How-to-use-Meta-Ads-AB-testing-feature-744x472.jpg 744w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/How-to-use-Meta-Ads-AB-testing-feature-80x51.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/How-to-use-Meta-Ads-AB-testing-feature-48x30.jpg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/How-to-use-Meta-Ads-AB-testing-feature.jpg 1305w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;How to use Meta Ads A/B testing feature&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;Meta has its own built-in A/B testing platform. Cedric has used this approach the least (mainly because he’s spoilt with big budgets… I’m &lt;em&gt;totally&lt;/em&gt; not jealous here). But don’t worry; I’ve used it plenty.&lt;/p&gt;



&lt;p&gt;With the previous setup, there’s another catch we haven’t discussed: what if someone sees ads 1 and 2 and then converts through ad 3? That could mess up the already challenging attribution for apps.&lt;/p&gt;



&lt;p&gt;The &lt;a href=&quot;https://en-gb.facebook.com/business/help/3506622486044209&quot;&gt;A/B testing feature of Meta&lt;/a&gt; solves this by keeping the audience clean. I typically take the setup from Framework 2 and run it through an experiment, which provides a more reliable and accurate setup.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;694&quot; height=&quot;840&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/a-b-testing-in-meta.png&quot; alt=&quot;&quot; class=&quot;wp-image-43244&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/a-b-testing-in-meta.png 694w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/a-b-testing-in-meta-248x300.png 248w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/a-b-testing-in-meta-33x40.png 33w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/a-b-testing-in-meta-383x464.png 383w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/a-b-testing-in-meta-463x560.png 463w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/a-b-testing-in-meta-245x296.png 245w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/a-b-testing-in-meta-390x472.png 390w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/a-b-testing-in-meta-66x80.png 66w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/a-b-testing-in-meta-40x48.png 40w&quot; sizes=&quot;auto, (max-width: 694px) 100vw, 694px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Meta has various tools to test, you want to use the A/B testing one&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;When using this method, I usually follow the same approach as Framework 2, but &lt;strong&gt;with just 2-3 ad sets to stay intentional about what we’re testing.&lt;/strong&gt;&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;1 Campaign with budgets set at ad level (ABO)
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Ad set 1
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Ad 1&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;



&lt;li&gt;Ad set 2
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Ad 2&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;



&lt;li&gt;Ad set 3
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Ad 3&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;However, you can also test campaigns against each other:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;881&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-ad-set-up-1024x881.png&quot; alt=&quot;&quot; class=&quot;wp-image-43246&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-ad-set-up-1024x881.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-ad-set-up-300x258.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-ad-set-up-768x660.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-ad-set-up-47x40.png 47w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-ad-set-up-540x464.png 540w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-ad-set-up-696x599.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-ad-set-up-560x482.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-ad-set-up-344x296.png 344w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-ad-set-up-549x472.png 549w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-ad-set-up-80x69.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-ad-set-up-48x41.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-ad-set-up.png 1414w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;The test setup in Meta, you can set tests at both campaign and ad level&amp;nbsp;&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;It works well for startups that want to be confident in their tests and reduce the risk of needing to retest. You can create a more controlled test for different ad creatives and test audiences as well. This is where the Campaign level comes in handy—especially if you want to compare an Advantage+ audience (which limits you to one ad set per campaign) against a broad, interest, or lookalike audience.&lt;/p&gt;



&lt;p&gt;However, it’s time-consuming and doesn’t scale well. Managing more than 3-4 different experiments at the same time can get overwhelming. I guess that’s the other reason Cedric has stayed away from it: it’s a slow approach.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;testing-framework-4-new-campaign-per-experiment&quot;&gt;Testing Framework 4 – New campaign per experiment&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;652&quot; height=&quot;330&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-framework-4.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-43250&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-framework-4.jpg 652w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-framework-4-300x152.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-framework-4-79x40.jpg 79w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-framework-4-560x283.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-framework-4-80x40.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-framework-4-48x24.jpg 48w&quot; sizes=&quot;auto, (max-width: 652px) 100vw, 652px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;What testing framework 4 looks like in Meta Ads Manager&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;&lt;strong&gt;As we move to Frameworks 4–7, the iOS limitations start to become a bigger challenge. &lt;/strong&gt;These frameworks are more commonly used by larger brands.&lt;/p&gt;



&lt;p&gt;When Cedric was leading user acquisition at PhotoRoom, they were spending over $1 million a month. At that scale, using frameworks 1–3 doesn’t work. You can’t rely on just one campaign to test, or carefully place each ad in a separate ad set.&lt;/p&gt;



&lt;p&gt;One way to tackle this is by creating a &lt;strong&gt;new campaign for each experiment&lt;/strong&gt;. Because of these limitations, this framework isn’t very popular for subscription apps, but it’s commonly used in e-commerce. So, it’s worth mentioning here.&lt;/p&gt;



&lt;p&gt;Many people like the control campaigns give you when splitting out tests. However, it can get messy. Overall, this isn’t a framework we’d recommend unless you’re focused on Android or Web, and you don’t mind the added complexity (Type A friends, I’m looking at you—this is a hard pass).&lt;/p&gt;



&lt;p&gt;Let’s swiftly sweep that mess under the rug and move on to a framework that better balances control with testing capacity.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;testing-framework-5-each-ad-set-has-5-ads&quot;&gt;Testing Framework 5 – Each ad set has 5 ads&amp;nbsp;&lt;/h2&gt;



&lt;p&gt;This is one of the most common frameworks Cedric sees being used for testing. It works as follows: each ad set contains five ads, all centered around a clear theme and format that’s being tested. For example:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;1 Campaign with budgets set at ad level (ABO)
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Ad set 1 – Testing Carousel ads
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Ad 1&lt;/li&gt;



&lt;li&gt;Ad 2&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Ad 3&lt;/li&gt;



&lt;li&gt;Ad 4&lt;/li&gt;



&lt;li&gt;Ad 5&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;



&lt;li&gt;Ad set 2 – Testing Video Ads
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Ad 1&lt;/li&gt;



&lt;li&gt;Ad 2&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Ad 3&lt;/li&gt;



&lt;li&gt;Ad 4&lt;/li&gt;



&lt;li&gt;Ad 5&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;



&lt;li&gt;Ad set 3 – Images
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Ad 1&lt;/li&gt;



&lt;li&gt;Ad 2&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Ad 3&lt;/li&gt;



&lt;li&gt;Ad 4&lt;/li&gt;



&lt;li&gt;Ad 5&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Visually this looks similar to Framework 1, but with multiple ad sets (so not an advantage+ campaign).&lt;/p&gt;



&lt;p&gt;Cedric has found that by keeping the ads relative, you can ensure a fairer test. Otherwise, one format might unfairly dominate. Ah, control and volume, now we’re talking. Not only does this make testing a bit fairer, but it also allows you to increase your volume. You’re still working with a maximum of 25 ads per campaign on iOS, but with 18 campaigns, that’s still 450 ads. And if you increase that limit or add more ads to winning campaigns (remember, the actual limit is 50 ads per ad set), you can go even higher.&lt;/p&gt;



&lt;p&gt;Other downsides? It’s still not the fastest framework to work with.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;testing-framework-6-each-ad-set-has-50-ads&quot;&gt;Testing Framework 6 – Each ad set has 50 ads&amp;nbsp;&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;647&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-testing-framework-6-1024x647.jpg&quot; alt=&quot;&quot; class=&quot;wp-image-43252&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-testing-framework-6-1024x647.jpg 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-testing-framework-6-300x190.jpg 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-testing-framework-6-768x485.jpg 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-testing-framework-6-1536x970.jpg 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-testing-framework-6-63x40.jpg 63w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-testing-framework-6-696x440.jpg 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-testing-framework-6-560x354.jpg 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-testing-framework-6-468x296.jpg 468w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-testing-framework-6-747x472.jpg 747w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-testing-framework-6-80x51.jpg 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-testing-framework-6-48x30.jpg 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-testing-framework-6.jpg 1999w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;What testing framework 6 looks like in Meta Ads Manager&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;That was not a typo… 50 ads per ad set that you are testing. &lt;em&gt;Toto, I have a feeling we’re not in Kansas anymore.&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;The overview then is:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;1 Campaign with budgets set at ad level (ABO)
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Ad set 1
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Ad 1-50&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;



&lt;li&gt;Ad set 2
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Ad 51-100&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;



&lt;li&gt;Ad set 3
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Ad 101-150&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;



&lt;li&gt;Ad set 4
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Ad 151-200&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;



&lt;li&gt;Ad set 5
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Ad 201-250&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Guess whose favorite framework this is? Cedric, of course! Usually, when you’re working with lots of ads, you’re optimizing for speed, but doing all of this manually takes a lot of time. As I mentioned earlier, Cedric likes to hand the reins over to Meta and let it run the show.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;This framework is all about efficiency, moving fast, and ensuring you learn quickly.&lt;/strong&gt; Using something like &lt;a href=&quot;http://admanage.ai&quot;&gt;&lt;strong&gt;AdManage.ai&lt;/strong&gt;&lt;/a&gt; or bulk upload is key. Mainly, big spenders use this approach because their cost per creative is low due to economies of scale, and testing creative nuances, like different headlines, hooks, backgrounds, etc., is crucial for them.&lt;/p&gt;



&lt;p&gt;However, as you can imagine, some ads will get zero spend. This isn’t an issue if you trust Meta’s optimization.&lt;/p&gt;



&lt;p&gt;I couldn’t believe Cedric fully hands it over to Meta, so I asked him about it, did he really never intervene? For me, it’s like saying you’ve worked at a place with a candy jar for two years and never taken a piece. Possible, but very unlikely.&lt;/p&gt;



&lt;p&gt;He admitted to occasionally giving in and taking back control—&lt;em&gt;ha, I knew it!&lt;/em&gt; This wasn’t based on a specific stat, but if an ad that had a lot of data behind it or he had high hopes for didn’t get any spend, he’d separate it out. Sometimes he was right; other times, he was wrong.&lt;strong&gt; This perfectly highlights what you need to consider with a speed approach: you might miss a winner here and there, but the speed of testing usually makes up for it.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Now, let’s move on to one more framework, it’s a bit of an odd one out compared to the rest, but it has its uses.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;testing-framework-7-flexible-ads&quot;&gt;Testing Framework 7: Flexible Ads&lt;/h2&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;481&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-testing-framework-7-1024x481.png&quot; alt=&quot;&quot; class=&quot;wp-image-43254&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-testing-framework-7-1024x481.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-testing-framework-7-300x141.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-testing-framework-7-768x361.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-testing-framework-7-1536x721.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-testing-framework-7-85x40.png 85w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-testing-framework-7-696x327.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-testing-framework-7-560x263.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-testing-framework-7-840x394.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-testing-framework-7-80x38.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-testing-framework-7-48x23.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/meta-testing-framework-7.png 1700w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;What testing framework 7 looks like in Meta Ads Manager&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;Given Cedric’s wealth of Meta knowledge, I was hoping he could finally answer a question I’ve been wondering: &lt;strong&gt;why did Meta rebrand Dynamic Ads to Flexible Ads?&lt;/strong&gt; Unfortunately, he had no idea either. His best guess was that maybe internal surveys showed “dynamic” was misleading. Oh, Meta—you strange, strange platform.&lt;/p&gt;



&lt;p&gt;For those not familiar with Flexible Ads, you set it up at the ad level:&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;914&quot; height=&quot;606&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/flexible-ads-formats.png&quot; alt=&quot;&quot; class=&quot;wp-image-43256&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/flexible-ads-formats.png 914w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/flexible-ads-formats-300x199.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/flexible-ads-formats-768x509.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/flexible-ads-formats-60x40.png 60w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/flexible-ads-formats-696x461.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/flexible-ads-formats-560x371.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/flexible-ads-formats-446x296.png 446w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/flexible-ads-formats-712x472.png 712w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/flexible-ads-formats-80x53.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/flexible-ads-formats-48x32.png 48w&quot; sizes=&quot;auto, (max-width: 914px) 100vw, 914px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;You can upload up to ten media assets (images and videos). It’s a very fast way to set up ad experiments directly in Meta, and it also allows Meta to choose which one to show your audience based on what it believes will work best.&lt;/p&gt;



&lt;p&gt;This is great for testing around a certain theme or experimenting with smaller nuances in ads once you’ve already found your winners, but want to optimize them further. While the setup is fast, &lt;strong&gt;it does take longer to analyze because you need to dive into ad breakdowns to see which media performed the best.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;One downside is that you’ll potentially lose social proof when scaling up a winner, as you’ll likely want to set it up as a new ad (you should be able to keep the social proof if you continue to run the flex ad).&lt;/p&gt;



&lt;p&gt;So there you have it—seven frameworks. Now, let’s wrap up with some final advice from Cedric on experimenting successfully.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;what-are-the-most-common-testing-mistakes-made-by-subscription-apps&quot;&gt;What are the most common testing mistakes made by subscription apps?&lt;/h2&gt;



&lt;p&gt;We’ve already discussed Cedric’s disdain for waiting on statistical significance, which he considers the biggest mistake. &lt;strong&gt;He strongly encourages, especially for bigger brands, to choose a framework that prioritizes speed over precision.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;The second mistake revolves around attribution: specifically, not checking blended ROAS. Meta tends to underreport on iOS, so &lt;strong&gt;it’s essential to calculate your own internal metrics and set up a Mobile Measurement Partner (MMP),&lt;/strong&gt; rather than just trusting Meta’s numbers at face value.&lt;/p&gt;



&lt;p&gt;Cedric also sees far too many brands still relying on view-through attribution instead of using 1-day or 7-day click attribution, which he believes offers much more accurate insights.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;475&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/attribution-set-view-through-click-1024x475.png&quot; alt=&quot;&quot; class=&quot;wp-image-43258&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/attribution-set-view-through-click-1024x475.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/attribution-set-view-through-click-300x139.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/attribution-set-view-through-click-768x356.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/attribution-set-view-through-click-86x40.png 86w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/attribution-set-view-through-click-696x323.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/attribution-set-view-through-click-560x260.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/attribution-set-view-through-click-840x390.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/attribution-set-view-through-click-80x37.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/attribution-set-view-through-click-48x22.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/attribution-set-view-through-click.png 1306w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Attribution set with view through attribution as well as click attribution&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;So, not leaving engaged-view and view-through attribution on is key. In Cedric’s experience, leaving them on leads to ads cannibalizing another channel. While he’s seen a few cases where this works, most of the time, it’s meaningless.&lt;/p&gt;



&lt;p&gt;With ads, you really have to be conscious of whether they’re incremental and if they’re actually helping. There’s so much waste in broad ad channels, and the more you can do to control for this, the better. Cedric tends to use 1-day click attribution, but if the consideration period is longer, he’s used 7-day click attribution instead.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;306&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/duration-click-through-attribution-1024x306.png&quot; alt=&quot;&quot; class=&quot;wp-image-43260&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/duration-click-through-attribution-1024x306.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/duration-click-through-attribution-300x90.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/duration-click-through-attribution-768x229.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/duration-click-through-attribution-125x37.png 125w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/duration-click-through-attribution-696x208.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/duration-click-through-attribution-560x167.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/duration-click-through-attribution-840x251.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/duration-click-through-attribution-80x24.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/duration-click-through-attribution-48x14.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/duration-click-through-attribution.png 1306w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;figcaption class=&quot;wp-element-caption&quot;&gt;&lt;em&gt;Adjusting the duration of the click-through attribution&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;



&lt;p&gt;This is where an MMP is key, as they’ll de-duplicate the data, so always benchmark against that.&lt;/p&gt;



&lt;p&gt;In the first framework, we talked about using trials initially to get volume, but Cedric sees many brands failing to improve this setup as they grow. In his experience, around 70% of free trial users will unsubscribe, which means this signal to Meta is 70% diluted.&lt;/p&gt;



&lt;p&gt;Ideally, you should be getting more sophisticated with your measurement. You can’t always rely on purchases, especially with longer trial periods, but you can look at factors like the type of subscription (annual vs. monthly) or even the type of user. This is exactly what Cedric did at Photobook. They used data from the onboarding flow to identify whether the user was a business or an individual creator. They then associated a higher value with business users and sent that information back to Meta. If you want to trust Meta, you need to feed it good data.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;how-can-you-know-if-an-ad-has-potential&quot;&gt;How can you know if an ad has potential?&lt;/h2&gt;



&lt;p&gt;Cedric is quite liberal when it comes to choosing which ads to scale. He usually runs an evergreen campaign with 50 ads. Then, he tends to delete the bottom 5 ads and upload the top 5 from the testing campaigns every week into the evergreen campaign.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;A key reason for this is team morale.&lt;/strong&gt; It keeps the team motivated to see that there are always at least a few winners. He even adds the creator’s name to the ad so the team can see which content is performing well and which isn’t, and so creators can see their names in the winning campaigns.&lt;/p&gt;



&lt;p&gt;If the ads are performing similarly, this approach has very little downside. In fact, they’re likely to improve with scale as the extra data and social proof accumulate over time.&lt;/p&gt;



&lt;p&gt;However, I pushed him to get more specific: &lt;strong&gt;How do you determine whether an ad is a true winner versus just a short-term success?&lt;/strong&gt; For Cedric, CPA benchmarks are very accurate and more important than other signals. If the average CPA in the evergreen campaign is $5, and your test ad comes in at $4, that’s a good sign. A CPA of $8 might still work, but anything $10 or above should be left out. It’s all about relative performance compared to the evergreen campaign, especially since the evergreen campaign is nearly always lower.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;choosing-the-right-framework-for-your-app&quot;&gt;Choosing the right framework for your app&lt;/h2&gt;



&lt;p&gt;At the end of the day, picking the right framework comes down to several key considerations:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Time: &lt;/strong&gt;How much time do you have to set up and also analyze campaigns?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Expertise in Meta: &lt;/strong&gt;If you haven’t used Meta much before, you’ll probably prefer a simpler framework&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Trust in the algorithm: &lt;/strong&gt;Are you comfortable accepting that if Meta doesn’t spend on an ad, there’s likely a reason for it?&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Scale/Budget&lt;/strong&gt;: Frameworks 1-3 are better suited for smaller-scale ad accounts, while frameworks 4-7 are more suitable for larger accounts&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Amount of creatives you have: &lt;/strong&gt;If you don’t have a lot of creative assets, you’ll want to ensure you’re testing each creative more thoroughly&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Amount of data:&lt;/strong&gt; Testing 50 ads in an ad set requires a significant amount of data for Meta to properly understand what’s working and what isn’t&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Keep these factors in mind as you weigh the seven frameworks and the advantages and disadvantages of each one. There’s no concrete right answer, just the right answer for you right now.&lt;/p&gt;



&lt;figure class=&quot;wp-block-table&quot;&gt;&lt;table class=&quot;has-fixed-layout&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Framework&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;How It Works&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;When to Use&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Advantages&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Disadvantages&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Helpful Tips&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;1. Advantage+ Campaign with 5 Ads&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Single Advantage+ campaign with 1 ad set and 5 ads. Kill underperformers weekly and replace them.&lt;/td&gt;&lt;td&gt;Early-stage apps or teams with low ad knowledge or small budgets (&amp;lt;$5K/month).&lt;/td&gt;&lt;td&gt;Simple to set up. Great for low-fi UGC. Requires minimal media buying knowledge.&lt;/td&gt;&lt;td&gt;Limited testing volume (2-3 ads/week). Optimizes for trial not paid. Less control over distribution.&lt;/td&gt;&lt;td&gt;Use RevenueCat to validate quality.&amp;nbsp;&lt;br&gt;Prioritize hook + product demo creatives.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;2. One Ad per Ad Set (ABO)&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Each ad gets its own ad set, with ad-level budgets.&lt;/td&gt;&lt;td&gt;Startups that want control or testing fundamentals (e.g. messaging). Useful for Android/Web.&lt;/td&gt;&lt;td&gt;Guarantees spend per ad. Clear attribution. Ideal when assets are costly.&lt;/td&gt;&lt;td&gt;Slower to execute. Harder to scale. iOS limitations make it tricky.&lt;/td&gt;&lt;td&gt;Great for small brands wanting to ensure accurate testing.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;3. Meta A/B Testing Feature&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Run split tests using Meta’s experiment tool. Keeps audiences separate.&lt;/td&gt;&lt;td&gt;Startups that need confidence in results. When clean attribution matters.&lt;/td&gt;&lt;td&gt;Fair, isolated tests. Test campaigns, ad sets, or creatives.&lt;/td&gt;&lt;td&gt;Slower. Cumbersome at scale. Max 3-4 tests manageable.&lt;/td&gt;&lt;td&gt;Combine with Framework 2 for structured A/B testing.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;4. New Campaign per Experiment&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Set up a new campaign for each test to avoid overlap.&lt;/td&gt;&lt;td&gt;Large budgets, ecommerce-heavy or Android/Web-focused apps.&lt;/td&gt;&lt;td&gt;Maximum isolation and control.&lt;/td&gt;&lt;td&gt;Messy and hard to manage. Not ideal for iOS or subscriptions.&lt;/td&gt;&lt;td&gt;Use only if other frameworks aren’t viable due to audience overlap or platform constraints.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;5. Each Ad Set Has 5 Ads&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Multiple ad sets, each testing a format/theme with 5 ads each.&lt;/td&gt;&lt;td&gt;Brands ready to scale creative testing while maintaining structure.&lt;/td&gt;&lt;td&gt;Balanced control and volume. Up to 450 ads across campaigns.&lt;/td&gt;&lt;td&gt;Slower execution. Still capped (25 ads/campaign on iOS).&lt;/td&gt;&lt;td&gt;Keep each ad set’s theme tight to ensure fair comparisons.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;6. Each Ad Set Has 50 Ads&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Upload 50 ads per ad set. Let Meta optimize. Use tools like AdManagei for scale.&lt;/td&gt;&lt;td&gt;Bigger spenders testing at speed with creative nuance.&lt;/td&gt;&lt;td&gt;Fast, efficient learning. Huge creative volume.&lt;/td&gt;&lt;td&gt;Little control. Risk of Meta skipping promising ads. Manual setup is time-consuming.&lt;/td&gt;&lt;td&gt;Use automation tools. Occasionally, separate key creatives if they get zero spend.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;7. Flexible Ads (Formerly Dynamic)&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Upload up to 10 assets (images/videos) in a single flexible ad. Meta mixes and matches.&lt;/td&gt;&lt;td&gt;Quick creative optimization. Ideal after finding early winners.&lt;/td&gt;&lt;td&gt;Fast to set up. Good for optimizing winners further.&lt;/td&gt;&lt;td&gt;Harder to analyze. Loses social proof when scaling.&lt;/td&gt;&lt;td&gt;Use for micro-testing variations (e.g. hooks, backgrounds). Pull winners out to scale them manually.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;



&lt;p&gt;While I may not have gotten the definitive answer I wanted on which framework is best after chatting to Cedric, I’m 100% fine with it. The vague answer most give, “It depends,” has become a very clear and structured approach for evaluating and experimenting with frameworks to find the best one for you. The Type A struggling to escape within me will simply have to accept that answer, and pour her frustrations elsewhere… &lt;em&gt;*cue internal screaming*&lt;/em&gt;.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[A new way to navigate RevenueCat]]></title><description><![CDATA[Meet the redesigned dashboard navigation]]></description><link>https://www.revenuecat.com/blog/company/dashboard-navigation-redesign/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/company/dashboard-navigation-redesign/</guid><pubDate>Wed, 18 Jun 2025 11:23:23 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/dashboard-navigation-redesign-1600.png" length="0" type="image/*"/><content:encoded>&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;: RevenueCat’s dashboard navigation has a new look and it’s now live. The update introduces a vertical layout, promotes Projects to a top-level view, and simplifies tool access across Web, Paywalls, and Customer center. We’re rolling it out starting today. You can still switch back for a limited time.&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;We’ve redesigned how you navigate RevenueCat. The new layout is cleaner, more scalable, and designed for how real teams work. Whether you’re switching projects, exploring charts, or working in tools like Paywalls or Customer center, everything’s easier to find — with less friction.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-new-navigation-is-now-rolling-out&quot;&gt;New navigation is now rolling out&lt;/h2&gt;



&lt;p&gt;We’ve rolled out the updated dashboard navigation for everyone. You can still switch back to the previous layout for a limited time.&lt;/p&gt;



&lt;p&gt;Your feedback helped shape this update — and we’re still listening. If something doesn’t feel right or you have ideas to improve the experience, let us know. &lt;a href=&quot;https://form.typeform.com/to/x5su8nNN&quot;&gt;Share feedback →&lt;/a&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-embed is-type-wp-embed is-provider-wistia-inc wp-block-embed-wistia-inc&quot;&gt;&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;
&lt;iframe loading=&quot;lazy&quot; class=&quot;wp-embedded-content&quot; sandbox=&quot;allow-scripts&quot; security=&quot;restricted&quot; title=&quot;Switching projects in the new navigation Video&quot; src=&quot;https://fast.wistia.net/embed/iframe/wr2fw863yb?dnt=1#?secret=NlCEYaTywq&quot; data-secret=&quot;NlCEYaTywq&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; width=&quot;500&quot; height=&quot;313&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;&lt;/figure&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-what-s-different-nbsp&quot;&gt;&lt;strong&gt;What’s different&amp;nbsp;&lt;/strong&gt;&lt;/h2&gt;



&lt;p&gt;&lt;strong&gt;Vertical layout&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;More space, especially on smaller screens. A more consistent experience across tools.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;512&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/vertical-layout-1024x512.png&quot; alt=&quot;&quot; class=&quot;wp-image-43231&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/vertical-layout-1024x512.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/vertical-layout-300x150.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/vertical-layout-768x384.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/vertical-layout-80x40.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/vertical-layout-696x348.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/vertical-layout-560x280.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/vertical-layout-840x420.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/vertical-layout-48x24.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/vertical-layout.png 1360w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;strong&gt;Projects are now top-level&lt;/strong&gt;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;512&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/project-1024x512.png&quot; alt=&quot;&quot; class=&quot;wp-image-43226&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/project-1024x512.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/project-300x150.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/project-768x384.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/project-80x40.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/project-696x348.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/project-560x280.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/project-840x420.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/project-48x24.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/project.png 1360w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;strong&gt;Clearer structure, fewer clicks&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Faster access to the thing you switch between most.&lt;/p&gt;



&lt;p&gt;Customers and Charts are easier to find and shown in the context of the project.&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;512&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/charts-and-customers-1024x512.png&quot; alt=&quot;&quot; class=&quot;wp-image-43229&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/charts-and-customers-1024x512.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/charts-and-customers-300x150.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/charts-and-customers-768x384.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/charts-and-customers-80x40.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/charts-and-customers-696x348.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/charts-and-customers-560x280.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/charts-and-customers-840x420.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/charts-and-customers-48x24.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/charts-and-customers.png 1360w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;&lt;strong&gt;Built to grow&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;This layout scales with us, so we can add new features without adding clutter.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;h-why-we-made-the-change&quot;&gt;Why we made the change&lt;/h2&gt;



&lt;p&gt;The old navigation worked, but only up to a point. As RevenueCat grew, the dashboard became harder to navigate. Features were added, workflows evolved, and what once felt simple started to feel scattered.&lt;/p&gt;



&lt;p&gt;We heard the same things again and again:&lt;/p&gt;



&lt;p&gt;“I didn’t know that feature existed.”&lt;/p&gt;



&lt;p&gt;“It takes too many clicks to switch projects.”&lt;/p&gt;



&lt;p&gt;“Navigation feels inconsistent across tools.”&lt;/p&gt;



&lt;p&gt;It became clear that the structure wasn’t scaling with our product, or your needs. Tools were buried. Key actions were hard to find. And the experience varied too much between sections.&lt;/p&gt;



&lt;p&gt;This redesign is our response. It brings a clearer hierarchy, faster access to what matters, and a layout that can grow with you. We’ve built it to support teams working across multiple products and platforms, and to reduce friction every step of the way.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;h-faq-new-navigation&quot;&gt;&lt;strong&gt;FAQ: New navigation&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;&lt;strong&gt;&amp;nbsp;What changed in the Overview page?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;You’ll now find an Overview section for each project, making it easier to focus on the project you’re working on, and still have an Overview with data from all of your projects in one place.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Can I still see charts across all projects?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Yes. Cross-project charts are still available via the &lt;strong&gt;Explore all charts&lt;/strong&gt; button on the home screen.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;How do I switch between projects now?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Use the &lt;strong&gt;project pills&lt;/strong&gt; at the top of the screen or the &lt;strong&gt;project selector&lt;/strong&gt; in the sidebar to jump between projects quickly.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;What’s changed inside the project view?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;We’ve replaced the old structure with a &lt;strong&gt;vertical menu&lt;/strong&gt; for a cleaner, more scalable layout.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Where are Charts and Customers now?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;They now live inside each project, so your context stays consistent.&lt;/p&gt;



&lt;p&gt;Collapse the submenu to focus on just the section list — great for small screens or focused work.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;What happened to the old “Apps” landing page?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;It’s been replaced by &lt;strong&gt;Platforms&lt;/strong&gt;, a more organized way to manage your integrations and keys.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Where are my API keys?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;API keys now live under &lt;strong&gt;Platforms&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;What’s in the new Product Catalog?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;The Product Catalog now includes &lt;strong&gt;Products, Offerings, Entitlements and Virtual Currencies&lt;/strong&gt;—everything you need to manage monetization in one place.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Can I change the app’s accent color?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Yes! Go to &lt;strong&gt;Account Settings &amp;gt; Interface&lt;/strong&gt; to customize the theme tint. If you don’t want to use the app icon color, you can override it there.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;How can I switch back to the old navigation?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;You’ll find it under the &lt;strong&gt;Help&lt;/strong&gt; icon or in &lt;strong&gt;Account settings &amp;gt; Interface&lt;/strong&gt;.&lt;/p&gt;
</content:encoded></item><item><title><![CDATA[Detecting ad fatigue in 2025]]></title><description><![CDATA[Key metrics and methods subscription apps need to know]]></description><link>https://www.revenuecat.com/blog/growth/detect-ad-fatigue-mobile-apps/</link><guid isPermaLink="false">https://www.revenuecat.com/blog/growth/detect-ad-fatigue-mobile-apps/</guid><pubDate>Wed, 18 Jun 2025 10:04:07 GMT</pubDate><enclosure url="https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/detect-ad-fatigue-mobile-apps.png" length="0" type="image/*"/><content:encoded>&lt;blockquote class=&quot;wp-block-quote is-layout-flow wp-block-quote-is-layout-flow&quot;&gt;
&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;: Ad fatigue in 2025 can be identified through early signals like declining CTR, rising frequency, onboarding drop-offs, and cross-channel performance shifts. Reliable detection methods include tracking saturation curves, analyzing SKAN 4.0 anonymity tiers, monitoring blended ROAS and subscription rates, and using proxies like Custom Product Page (CPP) performance and App Store referrer data.&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p id=&quot;block-e08093cf-0d17-48d0-b8ce-836c3e7c5472&quot;&gt;With ad creative lifespans shrinking and signal loss making performance harder to read, spotting ad fatigue early has never been more critical — especially for subscription apps. A slight delay in refreshing underperforming assets can compound into real revenue loss.&lt;/p&gt;



&lt;p id=&quot;block-89e8a405-9cf1-4fa8-a71c-21ce9e4ef625&quot;&gt;This article explores advanced techniques for detecting and combating ad fatigue, leveraging multiple data sources, including SKAdNetwork (SKAN), onboarding flows, and conversion patterns to predict when your ads are losing their impact before it’s too late.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;what-is-ad-fatigue&quot;&gt;What is ad fatigue?&lt;/h2&gt;



&lt;p&gt;Ad fatigue occurs when users become desensitized to ads due to excessive exposure, resulting in decreased engagement and reduced overall effectiveness.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;According to a study by Simulmedia, people who saw an ad 6-10 times were 4.1% less likely to buy a product than those who saw the ad 2-5 times. This highlights the delicate balance marketers must strike between ad frequency and effectiveness.&lt;/p&gt;



&lt;p&gt;However, the challenge relies in finding the right timing to stop, add, and prioritize the budget allocation to new assets that could generate a higher return on investment.&lt;/p&gt;



&lt;p&gt;📚 &lt;strong&gt;Need a primer on why creative fatigue happens in the first place?&lt;/strong&gt;&lt;br&gt;Check out &lt;a class=&quot;&quot; href=&quot;https://www.revenuecat.com/blog/growth/creative-fatigue-mobile-apps-roas&quot;&gt;David Vargas’s post on how ad platforms accelerate fatigue&lt;/a&gt; — especially when they over-optimize for early wins. This post builds on that with early-warning signs to act &lt;em&gt;before&lt;/em&gt; your ROAS drops.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;detection-methodologies&quot;&gt;Detection methodologies&lt;/h2&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;cross-channel-correlation&quot;&gt;Cross-channel correlation&lt;/h3&gt;



&lt;p&gt;One powerful approach is to analyze cross-channel correlation, using the performance on specific ad networks as a proxy for creatives running across multiple channels. In practice, this means if you run the same ad creative on different platforms (e.g., Meta, TikTok, Google UAC, Snap), trends on one network can foreshadow performance on others. Marketers can predict ad fatigue by identifying leading indicators on a platform that saturates faster or has a more sensitive audience.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;For example, consider a subscription fitness app with a successful video ad on Facebook and TikTok. They observe the following on TikTok:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Click-through rate (CTR) has steadily declined over the past week.&lt;/li&gt;



&lt;li&gt;Ad frequency is increasing.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The younger audience and fast content cycle on TikTok may lead to faster creative wear-out. This early CTR drop on TikTok can indicate that the same creative might soon underperform on Facebook, assuming the audience age is similar. Even if Facebook installs or conversions haven’t decreased yet, the TikTok trend provides an early warning to:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Refresh the creative.&lt;/li&gt;



&lt;li&gt;Act before a performance decline impacts Facebook’s larger ad spend.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Apply this technique to spot patterns like:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Rising CPC/CTR on one channel&lt;/strong&gt;: If the cost per click suddenly spikes on Google App Campaigns for a given creative, it might indicate the audience that finds it appealing is tapped out. That same creative running on another channel could be close to hitting the wall as well.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Conversion rate decay&lt;/strong&gt;: A drop in install-to-trial conversion rate on Network A for Creative X (perhaps due to users seeing it too often and ignoring the call-to-action) may predict a similar drop on Network B soon after.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Time-lagged trends&lt;/strong&gt;: By measuring the time lag between performance peaks and declines on each channel, you can create a “fatigue map.” For example, you might find that a creative tends to peak on Facebook and then peaks on smaller channels like Pinterest one week later. That means Pinterest could serve as an early warning system for creative wear-out that will eventually reflect on Facebook.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;&lt;strong&gt;Pro Tip:&lt;/strong&gt; Create a data pattern. For example, a mobile meditation app observed that when a particular calming ad creative reached ~2 million impressions on Instagram, its daily subscription trials from Facebook (where the same creative ran) began to decline, despite steady spending. The research showed that the Instagram audience saturated first; many in that audience also use Facebook. Seeing Instagram engagement drop off alerted them that the creative was “tired.” They preemptively rotated in a new creative on both platforms, avoiding deeper drops in acquisition&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;onboarding-flow&quot;&gt;Onboarding flow&lt;/h3&gt;



&lt;p&gt;Sometimes the clues of ad fatigue appear within your app’s onboarding flow rather than in the ad metrics themselves. In other words, by examining how new users behave after clicking an ad and installing, you can infer if those ads attract the proper attention or if users are arriving under pretenses (often when an ad grows stale or overexposed).&lt;/p&gt;



&lt;p&gt;Leveraging onboarding metrics and qualitative inputs during user sign-up can help identify trends related to ad fatigue. One clever tactic subscription apps use is adding a “Where did you hear about us?” question in the onboarding process. This optional survey screen can capture whether users recall seeing an ad and on what platform.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot;&gt;&lt;strong&gt;Example: Language learning app&lt;/strong&gt;&lt;/h4&gt;



&lt;p&gt;Classic signs of ad fatigue:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Typically, 40% of new users report hearing about the app from “Instagram Ads.”&lt;/li&gt;



&lt;li&gt;In the last two weeks, this has dropped to 25%.&lt;/li&gt;



&lt;li&gt;More users are now selecting “Friend/word of mouth” or “App Store search.”&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;This shift could indicate Instagram ads are becoming less effective due to ad fatigue, meaning:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Fewer people are clicking the ads.&lt;/li&gt;



&lt;li&gt;Those who do click don’t find the ads memorable or impactful.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;If Instagram ad spending remains constant, this decrease in self-reported attribution suggests:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;The ads are less memorable.&lt;/li&gt;



&lt;li&gt;The ads are less engaging than before.&lt;/li&gt;
&lt;/ul&gt;



&lt;h4 class=&quot;wp-block-heading&quot;&gt;&lt;strong&gt;Onboarding drop-off as a fatigue signal&lt;/strong&gt;&lt;/h4&gt;



&lt;p&gt;If a formerly strong ad campaign is now delivering users who abandon onboarding at higher rates, it could be because the ad is attracting less qualified or less enthusiastic users. These users may have seen the ad multiple times and clicked out of boredom or annoyance rather than genuine interest.&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot;&gt;&lt;strong&gt;Example: Productivity app&lt;/strong&gt;&lt;/h4&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Users coming from its long-running YouTube ad (showcasing a to-do list feature) used to have a 50% onboarding completion rate.&lt;/li&gt;



&lt;li&gt;Now, only 30% of users from the same YouTube ad complete onboarding.&lt;/li&gt;



&lt;li&gt;Users from a fresh TikTok ad are still at 50% completion.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The drop in onboarding completion from the YouTube ad suggests:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;The appeal of YouTube creatives has faded.&lt;/li&gt;



&lt;li&gt;People click the ad but don’t find the app compelling enough to finish onboarding.&lt;/li&gt;



&lt;li&gt;The ad might have over-promised or simply no longer resonate.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;This significant drop is a strong indicator of creative fatigue, suggesting it’s time to:&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Refresh the YouTube video.&lt;/li&gt;



&lt;li&gt;Replace it with new messaging.&lt;/li&gt;
&lt;/ul&gt;



&lt;h4 class=&quot;wp-block-heading&quot;&gt;&lt;strong&gt;In summary:&amp;nbsp;&lt;/strong&gt;&lt;/h4&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Monitor onboarding completion and early conversion rates as a real-time pulse check on ad performance.&lt;/li&gt;



&lt;li&gt;A sudden dip in quality or engagement of new users often signals creative fatigue or excessive ad frequency.&lt;/li&gt;



&lt;li&gt;Link onboarding metrics to their acquisition sources (campaign, network, creative ID) to pinpoint under-performing ads quickly.&lt;/li&gt;



&lt;li&gt;Act fast: refresh creatives or rebalance spend the moment onboarding data shows a sustained decline.&lt;/li&gt;
&lt;/ol&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;saturation-curves&quot;&gt;Saturation curves&lt;/h3&gt;



&lt;p&gt;Another advanced technique to detect when creatives are wearing out is to chart saturation curves for your campaigns. Saturation curves visualize how performance metrics change as spend or impressions accumulate, helping pinpoint the inflection point where returns diminish – essentially showing when an ad has hit audience saturation.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;In real-world terms, especially for subscription apps, these curves can be invaluable for knowing exactly when a creative has given you all it can, and pushing it further only yields fatigue.&amp;nbsp;&lt;/p&gt;



&lt;figure class=&quot;wp-block-image size-full&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;989&quot; height=&quot;590&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/saturation-curve-analysis.png&quot; alt=&quot;&quot; class=&quot;wp-image-43186&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/saturation-curve-analysis.png 989w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/saturation-curve-analysis-300x179.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/saturation-curve-analysis-768x458.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/saturation-curve-analysis-67x40.png 67w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/saturation-curve-analysis-696x415.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/saturation-curve-analysis-560x334.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/saturation-curve-analysis-496x296.png 496w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/saturation-curve-analysis-791x472.png 791w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/saturation-curve-analysis-80x48.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/saturation-curve-analysis-48x29.png 48w&quot; sizes=&quot;auto, (max-width: 989px) 100vw, 989px&quot;&gt;&lt;/figure&gt;



&lt;p&gt;What is a saturation curve? It’s typically a plot of an outcome (like conversions, installs, or revenue) versus an input (often spend or impressions). Early on, as you increase spend, conversions also increase – but beyond a certain spend level, the increase in conversions slows down and eventually plateaus. That plateau is the saturation point.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;Saturation curves help visualize when ad performance plateaus, indicating fatigue. This is a real-life example from a meditation app:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;&lt;strong&gt;Scenario&lt;/strong&gt;: New video ad creative showing a 30-day transformation.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Initial results&lt;/strong&gt;: Increasing ad spend ($1k to $5k daily) significantly increases daily trial sign-ups (each $1k ≈ 100 extra trials).&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Saturation point&lt;/strong&gt;: The trial increase slows significantly beyond $5k daily spend. At $8k, an extra $1k yields only ~20 trials. At $10k, almost no new trials are gained.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Curve behavior&lt;/strong&gt;: The spend vs. trial sign-up curve flattens, indicating saturation. Further spending is inefficient.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;CTR/Conversion rate&lt;/strong&gt;: Plotting CTR or conversion rate over cumulative impressions will likely decline as the audience sees the ad repeatedly.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Key takeaway&lt;/strong&gt;: The plateau or decline in the saturation curve signals ad fatigue.&lt;/li&gt;
&lt;/ol&gt;



&lt;h4 class=&quot;wp-block-heading&quot;&gt;Key takeaways on how to implement the best practices:&lt;/h4&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Use visualization tools to plot metrics.&lt;/li&gt;



&lt;li&gt;Identify the inflection point (fatigue point).&lt;/li&gt;



&lt;li&gt;Use this as a guideline for future campaigns and creative refresh cycles.&lt;/li&gt;



&lt;li&gt;Compare curves between creatives to understand their longevity.&lt;/li&gt;
&lt;/ol&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;ios-analysis&quot;&gt;iOS analysis&lt;/h2&gt;



&lt;p&gt;In a post-IDFA era, where multiple limitations push mobile app advertisers to think outside the box, having an effective strategy to measure the impact of iOS efforts is essential to achieve profitable growth. For this to happen, getting as close as possible to a reliable source of truth that reports stable and valid data is vital to making better decisions.&lt;/p&gt;



&lt;p&gt;These are three different paths advertisers can follow to predict ad performance impact on a business (hint: leveraging all of them at the same time is what will set you apart).&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;skan-capabilities&quot;&gt;SKAN capabilities&lt;/h3&gt;



&lt;p&gt;This article won’t cover all the pros and cons of SKAdNetwork’s framework, but instead will focus on maximizing its current features to obtain reliable and deterministic insights into understanding when an ad is becoming fatigued and delivering poor performance.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Key concepts:&lt;/strong&gt;&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;SKAdNetwork will only provide deterministic insights at the campaign level, and then the ad networks are responsible for modeling the data to the ad level (measurement tools like &lt;a href=&quot;http://www.app-stack.tech&quot;&gt;Appstack&lt;/a&gt; provide independent data enrichment to avoid relying on the ad networks).&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Adding revenue ranges to the conversion value mapping is the only way for advertisers to get estimated revenue from the marketing efforts.&lt;/li&gt;



&lt;li&gt;Null values greatly limit the amount of context we have regarding performance from a specific campaign. So, it’s essential to have product insights like ARPU to build advanced estimations. More on how to do this: &lt;a href=&quot;https://www.revenuecat.com/blog/growth/skadnetwork-guide-subscription-apps/#h-working-with-no-user-level-data&quot;&gt;https://www.revenuecat.com/blog/growth/skadnetwork-guide-subscription-apps/#h-working-with-no-user-level-data&lt;/a&gt;&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Depending on the postback version, more or less data will be collected. So, push for 4.0 postbacks as much as possible to reduce dependency on modeled efforts.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;The big question is: How can I predict ad fatigue on iOS that negatively impacts my business?&lt;/p&gt;



&lt;p&gt;These are the things you must be doing to be able to answer the question:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Add revenue ranges to key conversion values that generate revenue, and have a simple mapping to reduce the noise and increase the number of postbacks with revenue attached. For example, avoid adding revenue to events like paywall_viewed and setting an order of priority where the most frequent in-app event that brings in the most revenue gets overridden by less relevant events.&lt;/li&gt;



&lt;li&gt;Instead of focusing on the number of null values, the main KPI is the total number of postbacks (conversions) that Apple is passing back to you and the ad networks. Although a null postback lacks the context of what the users did, it still shows an attributed in-app event by a user.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;If you are running on SKAN 4.0, a great way to detect ad fatigue is to monitor whether the anonymity tier is decreasing while the ad spend remains stable. This means that due to a decrease in downloads, Apple is starting to limit the data you get back because fewer users are converting (the image below explains easily how you can identify the anonymity tier using Appstack).&lt;/li&gt;
&lt;/ol&gt;



&lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;290&quot; src=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/appstack-1024x290.png&quot; alt=&quot;&quot; class=&quot;wp-image-43188&quot; srcset=&quot;https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/appstack-1024x290.png 1024w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/appstack-300x85.png 300w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/appstack-768x218.png 768w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/appstack-1536x436.png 1536w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/appstack-125x35.png 125w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/appstack-696x197.png 696w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/appstack-560x159.png 560w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/appstack-840x238.png 840w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/appstack-80x23.png 80w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/appstack-48x14.png 48w, https://revenuecat.wpenginepowered.com/wp-content/uploads/2025/06/appstack.png 1999w&quot; sizes=&quot;auto, (max-width: 1024px) 100vw, 1024px&quot;&gt;&lt;/figure&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;blended-approach&quot;&gt;Blended approach&lt;/h3&gt;



&lt;p&gt;Thus far, we’ve discussed specific channels and signals. Another high-level methodology is to build a blended metric that combines various data sources, such as app store analytics and ad data, to gauge the impact of ad fatigue on your business.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;To make this possible, you must fetch the data from App Store Connect and Google Play Console. But using RevenueCat could help you avoid unnecessary pain since these APIs are complex to handle.&lt;/p&gt;



&lt;p&gt;These are some real-life examples you can apply:&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Looking at Day 0 revenue from new users (excluding subscription renewals). For subscription apps, Day 0 revenue might include first subscription payments (if you offer no free trial) or one-time starter pack purchases, etc., but excludes money from existing subscribers renewing. When the metric dips, it’s a warning that your ads (collectively) are losing effectiveness.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Take the total new subscriptions (or trial starts) in a period and divide by the total paid ad impressions served. This is a cross-channel efficiency metric. If, over time, each 1,000 ad impressions yields fewer and fewer subscribers, despite similar targeting, it likely means the creatives are less compelling (due to fatigue or creative burnout). The metric naturally blends all channels and creatives into one rate.&lt;/li&gt;



&lt;li&gt;Blended ROAS on initial purchase (say an annual sub upfront), measures the return on ad spend within the first 24 hours of install. If, historically, your blended Day0 ROAS was 20% (i.e., you earned back 20% of the spending on Day0 from new users) and now it’s 10%, something has degraded. It could be targeting, but if targeting is constant, it is likely due to creative fatigue, leading to lower intent installs.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;It’s essential to remember that any blended proxy use for decision making has a potential deviation, resulting in inaccurate decisions. Although the data is accurate at a high level, granular actions lack the necessary evidence to justify a potential uplift.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot; id=&quot;available-proxies&quot;&gt;Available proxies&lt;/h3&gt;



&lt;p&gt;In the era of user privacy (post-IDFA, SKAN, etc.), it’s become harder to get granular ad data, especially on iOS. However, savvy marketers can leverage the two main available proxies to approximate creative performance decline.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;These proxies are:&lt;/p&gt;



&lt;h4 class=&quot;wp-block-heading&quot;&gt;1. Custom Product Pages (CPPs)&lt;/h4&gt;



&lt;p&gt;Apple’s App Store allows developers to create multiple versions of the product page (each with different screenshots, app preview videos, and copy) and tie them to different campaigns via unique URLs. Many subscription apps use CPPs to align the App Store listing with the ad creative.&lt;/p&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;&lt;/ol&gt;



&lt;ol class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Create specific App Store product page versions (CPPs) that match your ad creatives (e.g., a “Yoga” for yoga-focused ads). Since you will have multiple creatives deployed simultaneously, a pro tip is to simplify the CPP structure by using angles that resonate with the ads you want to test.&lt;/li&gt;



&lt;li&gt;App Store Connect CPP’s tracks metrics like impressions, installs, and proceeds.&lt;/li&gt;



&lt;li&gt;A decline in multiple metrics on a specific CPP suggests the linked ad creative is becoming less effective.&lt;/li&gt;



&lt;li&gt;For example, a finance app sees a drop in conversion on its “Budgeting” CPP, mirroring a CTR decline on the associated ads, indicating ad fatigue for that theme.&lt;/li&gt;



&lt;li&gt;Without CPPs, you’d only see overall campaign data in SKAN and might miss creative-specific fatigue.&lt;/li&g