Best React Native in-app subscription libraries - LogRocket Blog (2024)

Editor’s note: This post was updated on 21 September 2023 to remove mention of the now-deprecated expo-in-app-purchases library. It is now recommended that you use react-native-iap or react-native-purchases, both of which we discuss in this post.

Best React Native in-app subscription libraries - LogRocket Blog (1)

Implementing in-app subscription purchases (IASP) is one of the key ways you can earn money from your mobile application. With IAP, you can easily monetize your app’s features, and content, and even offer digital products for sale.

React Native offers different libraries built on top of both Apple’s StoreKit framework and the Google Play Billing Library, which helps simplify IAP integration in mobile apps. In this article, we’ll explore a selection of some of the best IAP libraries for implementing in-app subscriptions in your React Native application.

Jump ahead:

  • Choosing the right React Native in-app purchase subscription library
  • react-native-iap
  • react-native-adapty
  • react-native-purchases
  • react-native-qonversion
  • Comparison summary

Choosing the right React Native in-app purchase subscription library

When deciding on which IAP library to use in your application, there are several factors you need to consider, including the following:

  • Documentation and support: You should generally go for libraries that have up-to-date and comprehensive documentation to ensure a smooth integration process. Additionally, check if there is an active support channel or community that will assist you in case of any issues or questions
  • Features offered: Assess the features provided by a library and determine if they align with your requirements. For instance, you may need a library that can handle receipt validation, dynamic product listings, refunds, and so on
  • Security and compliance: Consider the security measures a library’s developer has put in place to ensure adequate protection of user data, secure payment processing, and adherence to relevant store guidelines
  • Flexibility: Assess whether the library is flexible in terms of localization, UI customization, pricing models, and integration with third-party tools
  • Restoration and synchronization: Consider whether the library supports restoring purchases across devices and platforms. This feature allows users to regain access to previously purchased content or services when switching devices or reinstalling the application

react-native-iap

react-native-iap is a popular IAP library developed and maintained by dooboolab. It supports in-app subscription implementation for the App Store, Play Store, and Amazon Appstore.

react-native-iap provides a set of Hooks and exposes a set of APIs for processing product purchases and subscriptions, listening for completed and failed transactions, and fetching your product listing.

However, react-native-iap does not support receipt validation, so you must verify transactions on your backend.

Prior to integrating the react-native-iap library, you need to configure and create your product catalog with unique identifiers in the respective stores; react-native-iap uses these IDs to fetch your product listing.

You can install react-native-iap through npm:

npm install react-native-iap

Afterward, follow the installation instructions outlined in the documentation for both Android and iOS to complete the configuration process.

Example usage:

import React, { useEffect, useState } from 'react';import { StyleSheet, Text, View, Platform, Pressable } from 'react-native';import { initConnection, endConnection, finishTransaction, flushFailedPurchasesCachedAsPendingAndroid, purchaseUpdatedListener, purchaseErrorListener, getProducts, requestPurchase,} from 'react-native-iap'const App = () => { const [products, setProducts] = useState([]); useEffect(() => { const initializeConnection = async () => { try { await initConnection(); if (Platform.OS === "android") { await flushFailedPurchasesCachedAsPendingAndroid(); } } catch (error) { console.error("An error occurred", error.message); } } const purchaseUpdate = purchaseUpdatedListener( async (purchase) => { const receipt = purchase.transactionReceipt; if (receipt) { try { await finishTransaction({ purchase, isConsumable: true }); } catch (error) { console.error("An error occurred", error.message); } } }); const purchaseError = purchaseErrorListener((error) => console.error('Purchase error', error.message)); initializeConnection(); purchaseUpdate(); purchaseError(); fetchProducts(); return () => { endConnection(); purchaseUpdate.remove(); purchaseError.remove(); } }, []); const fetchProducts = async () => { try { const products = await getProducts({ skus: Platform.select({ ios: ['com.rniap.product10', 'com.rniap.product20'], android: ['com.rniap.product100', 'com.rniap.product200'], }) }); setProducts(products); } catch (error) { console.error("Error occurred while fetching products", error.message); } }; const makePurchase = async (sku) => { try { requestPurchase({ sku }) } catch (error) { console.error("Error making purchase", error.message); } } return ( <View style={styles.container}> { products.map((product) => ( <View key={product.productId} style={styles.row}> <Text>{product.title}</Text> <Pressable onPress={() => makePurchase(product.productId)}>Buy Product</Pressable></View> )) } </View> );}const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center', padding: 10 }, row: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', }, text: { fontSize: 16, marginEnd: 20 }});export default App;

This code snippet sets up the necessary connections and listeners for in-app purchases, fetches products from the store, and allows the user to make purchases by pressing a button for each product displayed on the screen.

The initializeConnection function initializes the in-app purchase connection using the initConnection function. If the platform is Android, it also flushes any failed purchases that are cached as pending using flushFailedPurchasesCachedAsPendingAndroid.

The purchaseUpdate function is a listener that is triggered when a purchase is updated. It calls the finishTransaction function to finish the transaction after a successful purchase. The purchaseError function is a listener that is triggered when a purchase error occurs.

react-native-adapty

The react-native-adapty library allows you to integrate in-app subscriptions into your React Native applications seamlessly. It provides a comprehensive set of features you‘d typically need to manage subscriptions, such as A/B testing, free trials, refunds, renewals, upgrades, downgrades, one-time purchases, and lifetime subscriptions. react-native-adapty can be used in both Expo-managed and native React Native workflows.

In addition, it offers an intuitive dashboard where you can track performance metrics, view users’ payment history, customize UI elements, and manage product listings without releasing new versions of your application.

To begin using react-native-adapty, you need to create an Adapty account and then register your application, after which you will get your public SDK key for use in your application.

You can install the react-native-adapty SDK using Yarn:

yarn add react-native-adapty

After installation, follow the instructions described in the documentation to complete installation for both Android and iOS.

Example usage:

import React, { useEffect, useState } from 'react';import { StyleSheet, Text, View, Pressable } from 'react-native';import { adapty } from 'react-native-adapty';const App = () => { const [products, setProducts] = useState([]); useEffect(() => { const initialize = async () => { try { await adapty.activate("PUBLIC_SDK_KEY", { customerUserId: "USER_ID", logLevel: 'ERROR', }); } catch (error) { console.error("An error occurred while activating adapty", error.message); } } initialize(); fetchPaywall("paywall_id"); }, []); //pawywallId is the id specified when creating a paywall in the adapty dashboard const fetchPaywall = async (paywallId) => { try { const paywallResult = await adapty.getPaywall(paywallId); const productResult = await adapty.getPaywallProducts(paywallResult); setProducts(productResult); } catch (error) { console.error("Error occured while fetching paywall", error.message); } }; const makePurchase = async (product) => { try { await adapty.makePurchase(product) } catch (error) { console.error("Error making purchase", error.message); } } return ( <View style={styles.container}> { products.map((product) => ( <View key={product.vendorProductId} style={styles.row}> <Text>{product.localizedTitle}</Text> <Pressable onPress={() => makePurchase(product)}>Buy Product</Pressable></View> )) } </View> );}const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center', padding: 10 }, row: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', }, text: { fontSize: 16, marginEnd: 20 }});export default App;

Use the adapty.makePurchase method enables in-app purchases. The fetchPaywall function is an asynchronous function that fetches the paywall using the adapty.getPaywall method and then fetches the paywall products using the adapty.getPaywallProducts method.

Over 200k developers use LogRocket to create better digital experiencesLearn more →

The initialize function is an asynchronous function that activates the Adapty SDK using the adapty.activate method. It takes a public SDK key, customer user ID, and log level as parameters.

To use this code, you need to have the necessary dependencies installed, including the Adapty SDK. Additionally, you need to replace:

  • "PUBLIC_SDK_KEY" with your actual Adapty SDK public key
  • "USER_ID" with the customer user ID
  • "paywall_id" with the ID of the paywall you want to fetch

react-native-purchases

react-native-purchases is a user-friendly IAP library developed and maintained by RevenueCat. It is a wrapper around the StoreKit framework, Google Play Billing Library, and the RevenueCat backend. However, if you’re using an Expo-managed workflow, you will need to create a development build as well.

It has built-in support for receipt validation, subscription status tracking, analytics metrics, and webhooks, which you can use to set up notifications for specific purchase events. In addition, you can remotely configure your product listings from your dashboard, view users’ transaction history, and easily integrate with third-party analytic tools.

To get started with integrating react-native-purchases in your application, you first need to sign up for a RevenueCat account and also set up a new project, and then proceed to add your application, after which you will obtain an API key for use in your project.

You can install the react-native-purchases SDK through npm:

npm install react-native-purchases

After installation, you also have to perform some additional configuration for iOS. Additionally, remember to also include the “Billing” permission in your AndroidManifest.xml file.

<uses-permission android:name="com.android.vending.BILLING" />

Example usage:

import React, { useEffect, useState } from 'react';import { StyleSheet, Text, View, Pressable } from 'react-native';import Purchases from 'react-native-purchases';const App = () => { const [packages, setPackages] = useState([]); useEffect(() => { Purchases.setLogLevel(Purchases.LOG_LEVEL.ERROR); const initialize = () => { Purchases.configure({ apiKey: "API_KEY", appUserID: null, observerMode: false, useAmazon: false }); } initialize(); fetchPackages(); }, []); const fetchPackages = async () => { try { const offerings = await Purchases.getOfferings() if(offerings.current !== null) { setPackages(offerings.current.availablePackages) } } catch (error) { console.error("Error occured while fetching packages", error.message); } }; const makePurchase = async (pkg) => { try { const {customerInfo} = await Purchases.purchasePackage(pkg); if(typeof customerInfo.entitlements.active["ENTITLEMENT_ID"] !== 'undefined') { //do something } } catch (error) { if(!error.userCancelled) { console.error("Error making purchase", error.message); } } } return ( <View style={styles.container}> { packages.map((pkg) => ( <View key={pkg.identifier} style={styles.row}> <Text>{pkg.title}</Text> <Pressable onPress={() => makePurchase(pkg)}>Buy Product</Pressable></View> )) } </View> );}const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center', padding: 10 }, row: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', }, text: { fontSize: 16, marginEnd: 20 }});export default App;

This code sets up a React Native app with a purchases integration for in-app purchases. It initializes purchases, fetches the available packages, and provides a UI to display and purchase those packages.

A call to Purchases.purchasePackage initiates the purchase process. Purchases.getOfferings fetches the offerings. The initialize function configures purchases with the API key, appUserID, observerMode, and useAmazon properties using Purchases.configure. If an error occurs during configuration, it is logged to the console.

react-native-qonversion

react-native-qonversion is another notable IAP library that allows you to swiftly incorporate in-app subscriptions into your application, eliminating the need to set up a backend for receipt validation — this is all handled by Qonversion.

You can also send users personalized push notifications triggered by purchase events, discover optimal pricing options via A/B tests, view detailed subscription analytics, share subscription data with your favorite analytics tool, handle both App Store and Play Store purchases, and so on.

To begin integrating react-native-qonversion, you need to create an account and proceed to create a project and register your application. After that, you can get your project key for use in your application. Also, don’t forget to create your IAP products on App Store Connect and the Google Play console!

The react-native-qonversion library can be installed through npm:

npm install react-native-qonversion

However, if you’re developing with Expo, you need to create a development build as well.

More great articles from LogRocket:

  • Don't miss a moment with The Replay, a curated newsletter from LogRocket
  • Learn how LogRocket's Galileo cuts through the noise to proactively resolve issues in your app
  • Use React's useEffect to optimize your application's performance
  • Switch between multiple versions of Node
  • Discover how to use the React children prop with TypeScript
  • Explore creating a custom mouse cursor with CSS
  • Advisory boards aren’t just for executives. Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.

Example usage:

import React, { useEffect, useState } from 'react';import { StyleSheet, Text, View, Pressable } from 'react-native';import Qonversion, {QonversionConfigBuilder, LaunchMode, Entitlement} from 'react-native-qonversion'const config = new QonversionConfigBuilder( 'PROJECT_KEY', LaunchMode.SUBSCRIPTION_MANAGEMENT).build();const App = () => { const [products, setProducts] = useState([]); useEffect(() => { const initialize = () => { Qonversion.initialize(config); } initialize(); fetchProducts(); }, []); const fetchProducts = async () => { try { const offerings = await Qonversion.getSharedInstance().offerings(); if(offerings.main != null && offerings.main.products.length > 0) { setProducts(offerings.main.products); } } catch (error) { console.error("Error occured while fetching products", error.message); } }; const makePurchase = async (product) => { try { const entitlements = await Qonversion.getSharedInstance().purchaseProduct(product); if(entitlements !== null && entitlements['premium'].isActive) { //do something } } catch (error) { if(!error.userCanceled) { console.error("Error making purchase", error.message); } } } return ( <View style={styles.container}> { products.map((product) => ( <View key={product.qonversionID} style={styles.row}> <Text>{product.qonversionID}</Text> <Pressable onPress={() => makePurchase(product)}>Buy Product</Pressable></View> )) } </View> );}const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center', padding: 10 }, row: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', }, text: { fontSize: 16, marginEnd: 20 }});export default App;

This code sets up a React Native app with Qonversion integration for subscription management. It initializes the Qonversion SDK, fetches the available products, and provides a UI to display and purchase those products.

The QonversionConfigBuilder object is created using the 'PROJECT_KEY' and 'LaunchMode.SUBSCRIPTION_MANAGEMENT' values. This configures the Qonversion SDK with the appropriate project key and sets the launch mode to subscription management.

A call to Qonversion.getSharedInstance().purchaseProduct(product) initiates the purchase process. Qonversion.getSharedInstance().offerings() fetches the product offerings.

Comparison summary

The following table shows an overview of the features of each of the highlighted IAP libraries:

Libraryreact-native-iapreact-native-adaptyreact-native-purchasesreact-native-qonversion
Stores supportedApple App Store, Google Play Store, Amazon AppstoreApple App Store and Google Play StoreApple App Store, Google Play Store, and Amazon AppstoreApple App Store and Google Play Store
Receipt validationNoYesYesYes
Supports A/B testsNoYesYesYes
No-code paywallNoYesNoNo
Dynamic paywallNoYesYesYes
Third-party integrationsNoYesYesYes
PricingFreeFree up to $10,000 monthly tracked revenue (MTR)Free up to $10,000 MTRFree up to $1,000 MTR

Conclusion

In-app purchase is an important method of app monetization. When incorporating IAP in React Native applications, several libraries stand out for their robust features, flexibility, and cross-platform support. These libraries simplify the process of integrating IAP functionality and offer various capabilities such as purchasing products, verifying receipts, listing products, managing subscriptions, and so on.

By harnessing the features provided by these libraries, you can streamline the integration of in-app purchases in your React Native application, enabling effective app monetization and enhancing the overall user experience.

LogRocket: Instantly recreate issues in your React Native apps

LogRocket is a React Native monitoring solution that helps you reproduce issues instantly, prioritize bugs, and understand performance in your React Native apps.

LogRocket also helps you increase conversion rates and product usage by showing you exactly how users are interacting with your app. LogRocket's product analytics features surface the reasons why users don't complete a particular flow or don't adopt a new feature.

Start proactively monitoring your React Native apps — try LogRocket for free.

Best React Native in-app subscription libraries - LogRocket Blog (2024)
Top Articles
Latest Posts
Article information

Author: Francesca Jacobs Ret

Last Updated:

Views: 5724

Rating: 4.8 / 5 (48 voted)

Reviews: 95% of readers found this page helpful

Author information

Name: Francesca Jacobs Ret

Birthday: 1996-12-09

Address: Apt. 141 1406 Mitch Summit, New Teganshire, UT 82655-0699

Phone: +2296092334654

Job: Technology Architect

Hobby: Snowboarding, Scouting, Foreign language learning, Dowsing, Baton twirling, Sculpting, Cabaret

Introduction: My name is Francesca Jacobs Ret, I am a innocent, super, beautiful, charming, lucky, gentle, clever person who loves writing and wants to share my knowledge and understanding with you.