Expo + RevenueCat: The fastest way to make money with your app

Development•React Native••13 minutes read

Perttu Lähteenlahti

Perttu Lähteenlahti

Guest Author

Add in-app subscriptions to your Expo app with RevenueCat. Follow this guide to install SDKs, set up stores, and launch a custom paywall in minutes.

Expo + RevenueCat: The fastest way to make money with your app
💡TL;DR: Want to add in-app subscriptions to your Expo app? This guide walks you through setting up RevenueCat’s React Native SDKs, creating store listings for iOS and Android, and deploying a custom paywall using RevenueCat’s visual editor. With Expo’s dev build tools and RevenueCat’s UI components, you can go from zero to monetized in under 20 minutes.

If you're building an app with Expo, adding in-app subscriptions shouldn't be a major hurdle. While in-app purchases can be tricky to implement and manage across platforms, tools like RevenueCat can simplify the process. With support for both iOS and Android, and full compatibility with React Native, RevenueCat handles the underlying infrastructure so you can focus on your app.

In this guide, we'll walk through how to integrate RevenueCat into an Expo app. You'll learn how to install the necessary SDKs, set up products and offerings in the app stores, and create a custom paywall that restricts access to premium content. The goal is to get subscriptions working in your app with minimal time and friction.

Getting started with RevenueCat and Expo

Before we dive into the code, let’s cover what you’ll need and how everything fits together.

Prerequisites

To follow this guide, make sure you have:

First is the RevenueCat SDK powering purchases, called react-native-purchases. It works on both iOS and Android, and allows your app to:

  • Purchase subscriptions
  • Restore previous purchases
  • Track purchases across platforms
  • React to subscription events (like renewals or cancellations)

The second dependency is react-native-purchases-ui. This includes a set of prebuilt native UI components, such as paywalls and customer center views, that you can integrate directly into your app. These components can be fully customized in RevenueCat's Paywall Builder, making it easy to create compelling subscription screens that drive conversions.

⚠️ While these SDKs can technically be added to an Expo Go–based app; purchases won't work in Expo Go because it doesn't include all the native APIs required (it's a sandbox!). You can still build out your UI and logic, but for actual testing and production use, you'll need a development build using Expo Dev Client and EAS Build.

We'll cover how to set up that development build in the next section.

Step 1: Install RevenueCat SDKs and create your dev build

The first step is to create an app with Expo, install the Expo CLI tools, make a development build and install the required packages.

Navigate to your project folder. Let’s first install required dependencies: expo-dev-client, and then two react-native-purchases packages:

Terminal
- npx expo install react-native-purchases react-native-purchases-ui

You now have all the dependencies needed to purchase products and display paywalls. You can at this point run your project to ensure that everything works.

The expo-dev-client will allow you to create development builds of your app. In this guide we are going to build our development builds using EAS, as it requires no native build tools to be installed on the device we are building with. You can also build locally using EAS CLI, or without EAS entirely if you have native tooling set up. Check Expo's documentation for detailed options.

Step 2: Configure your products, offerings, and our paywall

The next steps are mostly done outside of your app, but they are essential before you can begin testing purchases. Now that we have the base app set up, we'll step away from the code briefly to configure both RevenueCat and the app store accounts where your app will be published.

As mentioned earlier, we want our app to offer subscriptions on both iOS and Android. This requires you to have both an Apple Developer account and a Google Play Console account. RevenueCat has detailed and up-to-date documentation on how to complete these steps in the SDK Quickstart guide, so we won't cover every detail here. At a high level, you'll need to complete the following:

  • Create a RevenueCat project and configure it in your dashboard.
  • Set up your app in App Store Connect, and add the subscription products.
  • Do the same for Google Play Console, making sure the app and subscriptions are correctly configured.

Both Apple and Google require your app binary to be uploaded and reviewed before subscriptions can be added, so these steps need to be completed before any testing is possible. Fortunately, Expo's EAS Submit simplifies this process—you can submit your builds directly to both stores using the EAS CLI.

Once your app store accounts are ready and your app is uploaded, it's time to create the subscription products that users will purchase. For this guide, we'll be setting up a monthly subscription on each platform. You'll create one subscription in App Store Connect and another in Google Play Console—these should both represent the same subscription tier.

Next, head to the RevenueCat dashboard to mirror the products you just created in the app stores. You’ll do this by setting up an entitlement, a product, and an offering.

  1. Create an entitlement An entitlement represents the access level or feature your app will unlock after a successful purchase. In this guide, we’ll use an entitlement called "pro", which your app will later check to determine if the user has access to premium features. Learn more about entitlements →
  2. Add your products Each subscription product you created in App Store Connect and Google Play Console (for example, a monthly subscription) should now be added to RevenueCat. These products will be associated with the "pro" entitlement so RevenueCat knows what features they unlock. Learn more about adding products →
  3. Set up your offering Offerings are groups of one or more products that you want to display to users in your app. For this example, create a default offering that includes the monthly product from each store. You’ll reference this offering in your app when you display the paywall. Learn more about offerings →

Once complete, you'll be ready to integrate the SDK and display your paywall in the next step.

Step 3: Integrate react-native-purchases and react-native-purchase-ui

Once you have a development build of your app, both app stores configured with the apps and the subscriptions you want to have in your app, it’s time to update the code in our app to initialize the SDK and show a paywall.

You can find the full code for doing this here, but let’s go through the parts in detail to understand what is happening:

How to Initialize the SDK

We need to initialize the RevenueCat SDK with Purchases.configure call. Add the following code to the entry point of your app. If you’re using Expo router in your project this means the top most _Layout.tsx component, otherwise it is most likely your App.tsx file. Notice that everything needs to be called in a useEffect hook without any dependencies, to initialize the SDK only once.

Code
import { Platform, useEffect } from 'react-native';
import { useEffect } from 'react';
import Purchases, { LOG_LEVEL } from 'react-native-purchases';
//...
export default function App() {
useEffect(() => {
Purchases.setLogLevel(LOG_LEVEL.VERBOSE);
if (Platform.OS === 'ios') {
Purchases.configure({apiKey: <revenuecat_project_apple_api_key>});
} else if (Platform.OS === 'android') {
Purchases.configure({apiKey: <revenuecat_project_google_api_key>});
}
}, []);

We are first calling the setLogLevel to start logging. This will help us to notice problems in our setup, for example if we are calling things with the wrong API key. Take a look at RevenueCat’s debug log guide if you start seeing any error messages.

After that we do the actual initialization using separate keys.These keys can be found on the RevenueCat dashboard. Since iOS and Android have different keys we need to detect which platform the app is running using the Platform.OS.

Once you run your app you should not see any visual changes but there should be logs telling about successful initialization of the RevenueCat SDK. In case there are any problems or error messages, double check the previous checks. If you’re running into problems with native modules missing, rebuild your app completely.

Step 4: Displaying our paywall

Next we want to display our subscription options to the users using a paywall. To do this completely we first need to create a new paywall in RevenueCat’s paywall editor, and then add the paywall component to our app.

Creating a paywall in RevenueCat

Navigate to your RevenueCat dashboard and select your project if you have not already. In the navigation on the left you see Paywalls under ‘Monetization tools’, click that and then ‘+ new paywall’

Before presenting you with the paywall starters, it asks you to choose an offering to use. We created this in an earlier step, so select the offering you created. Alternatively you can also select the option to ‘continue without adding an Offering’

You have the option to create your paywall from scratch using RevenueCat’s visual paywall builder, or select from the premade templates. In this case since we’ve configured our product with annual and monthly options, I’m going to select the first option available.

You can fully customize what is shown on the paywall screen in this editor; from copy to colors and even custom components like feature carousel. Once you’re happy with the paywall, press Publish paywall to deploy the changes you’ve made. RevenueCat will automatically fetch changes to the paywall when you open the app, so you can always make changes to it without having to deploy a new version of your app to app stores.

Adding the paywall component to your app

For displaying the paywall we have few different options:

  • Using RevenueCatUI.presentPaywall: this will display a paywall when invoked.
  • Using RevenueCatUI.presentPaywallIfNeeded: this will present a paywall only if the customer does not have an unlocked entitlement.
  • Manually presenting <RevenueCatUI.Paywall>: this gives you more flexibility on how the paywall is presented.

In this project we want to present the user with a paywall that restricts user from accessing the app before they have subscribed. This is not the most user friendly option, but enough for us for now. Easiest way to achieve this behavior is to use the presentPaywallIfNeeded function

Insert the following code in the same place where you initialized the RevenueCat SDK but in a separate hook. This call is asynchronous. We need to call it asynchronously in a useEffect. Now save your changes and wait for the app to reload. If everything is initialized correctly your app should open and shortly after present the user with the paywall we configured in the dashboard.

Code
import { useEffect } from "react";
import { Button, Text, View } from "react-native";
import RevenueCatUI, { PAYWALL_RESULT } from "react-native-purchases-ui";
export default function Index() {
useEffect(() => {
const checkPaywall = async () => {
try {
const paywallResult = await RevenueCatUI.presentPaywallIfNeeded({
requiredEntitlementIdentifier: "pro"
});
if (paywallResult === PAYWALL_RESULT.PURCHASED ||
paywallResult === PAYWALL_RESULT.RESTORED) {
console.log("User has access to pro features");
// Handle successful purchase or restore here
}
} catch (error) {
console.error("Error presenting paywall:", error);
}
};
checkPaywall();
}, []);
return (
<View
style={{
flex: 1,
justifyContent: "center",
alignItems: "center",
}}
>
<Text style={{ marginBottom: 20 }}>RevenueCat Paywall Example</Text>
<Button
title="Show Paywall"
onPress={() => RevenueCatUI.presentPaywallIfNeeded({
requiredEntitlementIdentifier: "pro"
})}
/>
</View>
);
}

Hooray! You now have working subscriptions and a paywall to prompt the user to get them to pay. Try purchasing any of the two subscriptions on the paywall and after a successful payment the paywall should disappear and you now have full access to the features of your app.

Conclusion

Adding in-app subscriptions to your Expo app doesn't have to be a time-consuming or technically daunting task. With the features provided by RevenueCat’s React Native SDKs, developers can focus less on backend infrastructure and more on building experiences that delight users.

In this guide, we’ve walked through the complete process of setting up subscriptions in an Expo app – from installing the necessary SDKs, creating a development build, and configuring your products and offerings, to customizing and deploying a paywall with RevenueCat’s powerful UI tools. With just a few lines of code and minimal setup effort, your app is now capable of handling cross-platform subscription logic, entitlement checks, and user-friendly monetization flows.

Now that you have a working paywall and subscription system, the next step is to experiment with your offerings, iterate on your paywall design, and monitor your metrics in the RevenueCat dashboard; to build a sustainable subscription-based business with ease.

RevenueCat
paywall
mobile monetization
EAS Build
development builds
iOS subscriptions
Android subscriptions

Create amazing apps, in record time with EAS

Learn more