This is a guest post from Lennart Brandt - a Product Designer and React Native developer with over 10 years of experience turning ideas into beautiful, reliable digital products.
...
Turning your Expo app from a great idea into consistent revenue doesn’t have to be complicated. I'll walk you through how I designed and implemented subscriptions into Roamwise using Expo and RevenueCat. I'll share three practical React hooks you can use immediately – usePurchasesInitialize, usePurchasesMonitor, and usePurchases – plus design insights to boost your conversions.
Meet Roamwise
At Roamwise, my goal is simple: help digital nomads and frequent travelers track their time abroad, avoiding visa and tax headaches. To sustain and grow the app, an intuitive subscription model was essential. In the next sections, I'll show you why Expo and RevenueCat are the perfect combination for creating seamless subscriptions.
Setting up your Expo project
Start by installing RevenueCat’s React Native SDK alongside Expo's DevClient:
RevenueCat’s React Native Purchases: React Native Purchases simplifies integrating RevenueCat’s robust in-app purchase system, effortlessly managing subscriptions and payments across platforms.
Expo’s DevClient: The Expo DevClient gives you complete control over native code, crucial for integrating libraries like react-native-purchases not supported by Expo Go.
Running your project locally
Compile and run your app directly on your device:
Make sure your setup matches Expo’s guidelines here.
Configuring RevenueCat
Create a RevenueCat account, set up your products, and then add API keys securely to your .env file:
Using usePurchasesInitialize to set up RevenueCat
To simplify initialization and manage subscription states seamlessly in Roamwise, I built the usePurchasesInitialize hook. It abstracts away setup complexity, gracefully handles network interruptions, and keeps your app state in sync:
- Performs a one-time RevenueCat initialization using the correct platform-specific API key.
- Fetches user subscription status with Purchases.getCustomerInfo() and checks for active entitlements.
- Implements a retry mechanism with exponential backoff, attempting up to three times in case of network failures.
- Stores the result in a global Zustand store, ensuring immediate UI responsiveness.
- Returns a boolean flag isInitialized to signal when RevenueCat setup is complete, useful for loading indicators or gated content.
Full code:
Example usage:
This pattern keeps your codebase clean while giving you full control over subscription logic, retries, and global app state – all without repeating yourself across components.
Keeping your app updated with usePurchasesMonitor
Subscription states can change outside your app, so staying updated is critical. The usePurchasesMonitor hook handles real-time updates seamlessly:
- Ensures RevenueCat is fully initialized before setting up listeners.
- Sets listeners for both app lifecycle events (using React Native’s AppState) and RevenueCat customer info updates (
addCustomerInfoUpdateListener). - Automatically refreshes subscription status whenever the app regains focus or a subscription change occurs externally.
- Updates global subscription state through Zustand, avoiding redundant UI renders.
- Returns a boolean flag
isPurchaseMonitorSetUpto verify monitoring is active, aiding debugging and UI state management.
Full code:
Example implementation:
With this hook in place, your app will stay in sync with RevenueCat in real time – no extra logic required. It’s a reliable way to ensure your users always get the experience they’re paying for.
Handling Purchases with usePurchases
The usePurchases hook provides a straightforward and structured API for purchasing and restoring subscriptions, offering robust error handling and UI-friendly states:
- Confirms SDK initialization with Purchases.isConfigured() before proceeding.
- Fetches available packages and current customer info concurrently, ready for use in your pricing screens.
- Offers purchasePackage for initiating subscription transactions, silently handling user cancellations without unnecessary errors.
- Includes restorePurchases to easily recover subscriptions, crucial for device switches or reinstalls.
- Provides a helper hasActiveEntitlement to conditionally unlock premium features based on the current subscription status.
- Manages UI states clearly: isLoading for initial data fetches, isProcessing during transactions, and structured error information for effective user messaging.
Whenever a user subscribes through purchasePackage or restores their subscription via restorePurchases, the usePurchasesMonitor hook immediately receives this update. This means your app automatically recognizes the user as a premium subscriber, seamlessly unlocking all your pro features without manual intervention.
Full code:
This modular approach ensures your purchase flow remains maintainable, clear, and user-friendly.
Tip: RevenueCat’s Paywalls can help you iterate quickly on your subscription screens without app updates—though personally, I prefer custom designs for full control.
Designing paywalls for high conversion
When launching an app successfully it's easy to underestimate its importance or to overload it with untested growth hacks. From my experience scaling WeBurn (a fitness app reaching $15K monthly recurring revenue), I learned paywall strategies aren't universally applicable. Every audience requires thoughtful tailoring. For Roamwise, I returned to proven fundamentals to ensure high conversions:
Position paywalls when user motivation Is highest
Timing matters immensely. Placing the paywall immediately after onboarding, when user curiosity and engagement are at their peak, significantly improves conversion rates. This approach leverages user excitement, turning initial interest into decisive action. By focusing on these fundamental principles, Roamwise achieved a clear, user-focused paywall experience, turning curiosity into committed subscribers effectively and reliably.
Create an instant "Aha" moment
Demonstrating immediate value significantly increases conversions. Roamwise's paywall instantly leverages onboarding insights. When users first reach the paywall, it directly shows them their top visited countries extracted from their photo libraries. This immediate, personalized demonstration showcases Roamwise’s value clearly, removing uncertainty right at the moment of decision.
Thoughtful animations
Animations shouldn't merely be decorative. They should gently guide attention to key information. Subtle animations help users focus precisely when it matters most, reducing cognitive load during decision-making moments. In Roamwise, I employed smooth entrance animations using react-native-reanimated and react-native-bottom-sheet. Features such as a softly bouncing arrow and gently pulsing icons enhance user engagement subtly yet effectively.
Use clear, benefit-driven copy
Great copy instantly communicates the value users will receive: clearly, simply, and directly. On Roamwise’s paywall, each feature is named with straightforward, outcome-focused language. For instance, “History+” clearly states users will access extended travel history beyond 30 days, and “SchengenPro” makes managing Schengen days simple. Clear headlines and personal, benefit-oriented subtexts help users immediately see why subscribing makes sense. Even the main headline – “Unlock All Features” – is straightforward and benefit-oriented. The supporting text, “A special offer for frequent travelers like you,” is personal and specific, reinforcing the app’s target audience and purpose.
Emphasize the free trial clearly and frequently
Free trials dramatically reduce perceived risk, but only if clearly communicated. Roamwise repeatedly emphasizes its free trial through headlines (“Try Roamwise Pro For Free”), toggles clearly labeled "Free Trial Enabled," and bold, high-contrast text on the subscription button and fine print. Reiterating this offer multiple times helps build trust, making users comfortable to commit.
Make discounts impossible to miss
Discounts significantly boost conversion rates, but only when users clearly see and understand them. Roamwise prominently highlights savings, like “Save 69%” on annual plans, with bold visuals right next to pricing options. Positioning these discounts clearly within the pricing context makes them instantly understandable and compelling, prompting immediate action.
Use price anchoring to demonstrate value
Users naturally compare options when evaluating pricing. Price anchoring strategically positions your primary subscription plan between clearly more expensive and less expensive alternatives, making your targeted plan seem optimal. In Roamwise, the annual plan (€14.99/year) is clearly positioned between a lifetime option (€59.99) and a monthly plan (€3.99/month). Breaking down annual prices into monthly costs (just €1.25/month) further reinforces the perceived value.
Final thoughts
Subscriptions can feel daunting, but with Expo and RevenueCat the heavy lifting is already done—you just need a clear plan. Here’s what matters most:
- Foundation first.
usePurchasesInitialize,usePurchasesMonitor, andusePurchasesgive you a predictable, test-friendly layer for all purchase logic. Drop them in early so every screen can rely on the same source of truth. - Surface value before price. Show users exactly what they gain—whether that’s an instant travel summary or another “aha” moment unique to your app—before presenting a paywall. When the benefit is obvious, the subscription feels like a small step, not a gamble.
- Design with intent. A paywall is part of onboarding, not an interruption. Clear, benefit-driven copy, thoughtful motion, prominent free-trial messaging, and transparent discounts all work together to remove friction and build trust.
- Iterate ruthlessly. RevenueCat’s remote configs and analytics make it painless to A/B test headline tweaks, price anchoring, and trial lengths. Treat the paywall like any other feature: ship, measure, refine.
Add these pieces and your app will deliver subscriptions seamlessly, turning first-time users into long-term supporters without hijacking your roadmap.


