Make purchases in mobile app in React Native SDK
Displaying paywalls within your mobile app is an essential step in offering users access to premium content or services. However, simply presenting these paywalls is enough to support purchases only if you use Paywall Builder to customize your paywalls.
If you don’t use the Paywall Builder, you must use a separate method called .makePurchase() to complete a purchase and unlock the desired content. This method serves as the gateway for users to engage with the paywalls and proceed with their desired transactions.
If your paywall has an active promotional offer for the product a user is trying to buy, Adapty will automatically apply it at the time of purchase.
Keep in mind that the introductory offer will be applied automatically only if you use the paywalls set up using the Paywall Builder.
In other cases, you’ll need to verify the user’s eligibility for an introductory offer on iOS. Skipping this step may result in your app being rejected during release. Moreover, it could lead to charging the full price to users who are eligible for an introductory offer.
Make sure you’ve done the initial configuration without skipping a single step. Without it, we can’t validate purchases.
Make purchase
Using Paywall Builder? Purchases are processed automatically—you can skip this step.
Looking for step-by-step guidance? Check out the quickstart guide for end-to-end implementation instructions with full context.
try {
const purchaseResult = await adapty.makePurchase(product);
switch (purchaseResult.type) {
case 'success':
const isSubscribed = purchaseResult.profile?.accessLevels['YOUR_ACCESS_LEVEL']?.isActive;
if (isSubscribed) {
// Grant access to the paid features
}
break;
case 'user_cancelled':
// Handle the case where the user canceled the purchase
break;
case 'pending':
// Handle deferred purchases (e.g., the user will pay offline with cash)
break;
}
} catch (error) {
// Handle the error
}
Request parameters:
| Parameter | Presence | Description |
|---|---|---|
| Product | required | An AdaptyPaywallProduct object retrieved from the paywall. |
Response parameters:
| Parameter | Description |
|---|---|
| Profile | If the request has been successful, the response contains this object. An AdaptyProfile object provides comprehensive information about a user’s access levels, subscriptions, and non-subscription purchases within the app. Check the access level status to ascertain whether the user has the required access to the app. |
Note: if you’re still on Apple’s StoreKit version lower than v2.0 and Adapty SDK version lowers than v.2.9.0, you need to provide Apple App Store shared secret instead. This method is currently deprecated by Apple.
Change subscription when making a purchase
When a user opts for a new subscription instead of renewing the current one, the way it works depends on the app store:
- For the App Store, the subscription is automatically updated within the subscription group. If a user purchases a subscription from one group while already having a subscription from another, both subscriptions will be active at the same time.
- For Google Play, the subscription isn’t automatically updated. You’ll need to manage the switch in your mobile app code as described below.
To replace the subscription with another one in Android, call .makePurchase() method with the additional parameter:
try {
const purchaseResult = await adapty.makePurchase(product, params);
switch (purchaseResult.type) {
case 'success':
const isSubscribed = purchaseResult.profile?.accessLevels['YOUR_ACCESS_LEVEL']?.isActive;
if (isSubscribed) {
// Grant access to the paid features
}
break;
case 'user_cancelled':
// Handle the case where the user canceled the purchase
break;
case 'pending':
// Handle deferred purchases (e.g., the user will pay offline with cash)
break;
}
} catch (error) {
// Handle the error
}
Additional request parameter:
| Parameter | Presence | Description |
|---|---|---|
| params | required | an object of the MakePurchaseParamsInput type. |
Version 3.8.2+: The MakePurchaseParamsInput structure has been updated. oldSubVendorProductId and prorationMode are now nested under subscriptionUpdateParams, and isOfferPersonalized is moved to the upper level.
Example:
makePurchase(product, {
android: {
subscriptionUpdateParams: {
oldSubVendorProductId: 'old_product_id',
prorationMode: 'charge_prorated_price'
},
isOfferPersonalized: true
}
}); You can read more about subscriptions and replacement modes in the Google Developer documentation:
- About replacement modes
- Recommendations from Google for replacement modes
- Replacement mode
CHARGE_PRORATED_PRICE. Note: this method is available only for subscription upgrades. Downgrades are not supported. - Replacement mode
DEFERRED. Note: A real subscription change will occur only when the current subscription billing period ends.
Redeem offer codes in iOS
About offer codes
Offer codes allow you to give discounts or free trials to specific users. Unlike regular offers that are applied automatically, offer codes are distributed outside the app — through email campaigns, social media, or printed materials. Users redeem them by entering the code in the App Store, following a redemption URL, or through an in-app dialog.
To set up offer codes, open a subscription in App Store Connect and go to its Offer Codes section. You can create three kinds of offer codes:
- Free — the subscription is free for a set duration, and the next renewal is at full price.
- Pay as you go — the user pays a discounted price each billing cycle for a set duration, then the subscription renews at full price.
- Pay up front — the user pays a single discounted price for the entire offer duration, then the subscription renews at full price.
You don’t need to add offer codes to Adapty. Apple tags every transaction during the offer period with the offer code category. This includes the initial redemption and all subsequent discounted renewals. Adapty detects the tag and records each transaction with the offer category offer_code. Once the offer period ends and the subscription renews at full price, the tag is no longer present. You can filter analytics by the Offer Code offer type in the Adapty Dashboard.
Revenue discrepancy troubleshooting
If you notice that an offer code transaction appears in Adapty at the full product price instead of the discounted offer price, verify the following in App Store Connect:
- The offer code has the correct pricing configured for all regions where users can redeem it.
- The offer price is set for the specific country or region of the user. Apple sends the regional price in the transaction. If no regional price is configured for the offer, Apple may send the full product price instead.
You can filter and verify offer code transactions in the Adapty Dashboard by the Offer Code offer type and Offer Discount Type filters.
Legacy promo codes (deprecated)
Apple deprecated promo codes for in-app purchases in March 2026. Offer codes replace them with more capabilities: configurable eligibility, expiration dates, and up to 1 million codes per quarter. If you previously used promo codes for in-app purchases, transition to offer codes in App Store Connect.
Legacy promo codes (limited to 100 per app per version) granted free access to a subscription. Unlike offer codes, Apple did not include discount information in promo code transactions — it sent the full product price in the receipt. As a result, Adapty recorded these transactions at the full price, which caused revenue discrepancies between Adapty analytics and App Store Connect.
If you see historical transactions at full price that should have been free, they are likely from legacy promo codes. Since these codes are now deprecated, transition to offer codes for accurate revenue tracking.
To display the code redemption sheet in your app:
adapty.presentCodeRedemptionSheet();
Based on our observations, the Offer Code Redemption sheet in some apps may not work reliably. We recommend redirecting the user directly to the App Store.
In order to do this, you need to open the url of the following format:
https://apps.apple.com/redeem?ctx=offercodes&id={apple_app_id}&code={code}
Manage prepaid plans (Android)
If your app users can purchase prepaid plans (e.g., buy a non-renewable subscription for several months), you can enable pending transactions for prepaid plans.
adapty.activate("PUBLIC_SDK_KEY", {
android: { pendingPrepaidPlansEnabled: true }
});