Skip to main content

Displaying Paywalls

πŸ“˜Paywalls v2 Beta

These docs refer to our beta of Paywalls v2. For our original Paywalls, click here.

Platform specific instructions​

iOS​

RevenueCat Paywalls v2 will show paywalls fullscreen, and there are multiple ways to do this with SwiftUI and UIKit.

  • Depending on an entitlement with presentPaywallIfNeeded
  • Custom logic with presentPaywallIfNeeded
  • Manually with PaywallView or PaywallViewController
import SwiftUI

import RevenueCat
import RevenueCatUI

struct App: View {
var body: some View {
ContentView()
.presentPaywallIfNeeded(
requiredEntitlementIdentifier: "pro",
purchaseCompleted: { customerInfo in
print("Purchase completed: \(customerInfo.entitlements)")
},
restoreCompleted: { customerInfo in
// Paywall will be dismissed automatically if "pro" is now active.
print("Purchases restored: \(customerInfo.entitlements)")
}
)
}
}

Android​

RevenueCat Paywalls will, by default, show paywalls fullscreen and there are multiple ways to do this with Activitys and Jetpack Compose.

  • Depending on an entitlement with PaywallDialog
  • Custom logic with PaywallDialog
  • Manually with Paywall, PaywallDialog, or PaywallActivityLauncher
@OptIn(ExperimentalPreviewRevenueCatUIPurchasesAPI::class)
@Composable
private fun LockedScreen() {
YourContent()

PaywallDialog(
PaywallDialogOptions.Builder()
.setRequiredEntitlementIdentifier(Constants.ENTITLEMENT_ID)
.setListener(
object : PaywallListener {
override fun onPurchaseCompleted(customerInfo: CustomerInfo, storeTransaction: StoreTransaction) {}
override fun onRestoreCompleted(customerInfo: CustomerInfo) {}
}
)
.build()
)
}

React Native​

There are several ways to present paywalls:

  • 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.
import RevenueCatUI, { PAYWALL_RESULT } from "react-native-purchases-ui";

async function presentPaywall(): Promise<boolean> {
// Present paywall for current offering:
const paywallResult: PAYWALL_RESULT = await RevenueCatUI.presentPaywall();
// or if you need to present a specific offering:
const paywallResult: PAYWALL_RESULT = await RevenueCatUI.presentPaywall({
offering: offering // Optional Offering object obtained through getOfferings
});

switch (paywallResult) {
case PAYWALL_RESULT.NOT_PRESENTED:
case PAYWALL_RESULT.ERROR:
case PAYWALL_RESULT.CANCELLED:
return false;
case PAYWALL_RESULT.PURCHASED:
case PAYWALL_RESULT.RESTORED:
return true;
default:
return false;
}
}

async function presentPaywallIfNeeded() {
// Present paywall for current offering:
const paywallResult: PAYWALL_RESULT = await RevenueCatUI.presentPaywallIfNeeded({
requiredEntitlementIdentifier: "pro"
});
// If you need to present a specific offering:
const paywallResult: PAYWALL_RESULT = await RevenueCatUI.presentPaywallIfNeeded({
offering: offering, // Optional Offering object obtained through getOfferings
requiredEntitlementIdentifier: "pro"
});
}

There are also several listeners that can be used to handle the paywall lifecycle, such as onPurchaseStarted, onPurchaseCompleted, and onRestoreStarted.

Listeners​

When using RevenueCatUI.Paywall, you may use one of the provided listeners to react to user actions.

Available listeners at this time are:

  • onPurchaseStarted
  • onPurchaseCompleted
  • onPurchaseError
  • onPurchaseCancelled
  • onRestoreStarted
  • onRestoreCompleted
  • onRestoreError
  • onDismiss

Flutter​

There are several ways to present paywalls:

  • 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 PaywallView: this gives you more flexibility on how the paywall is presented.
import 'dart:async';
import 'dart:developer';

import 'package:purchases_ui_flutter/purchases_ui_flutter.dart';

void presentPaywall() async {
final paywallResult = await RevenueCatUI.presentPaywall();
log('Paywall result: $paywallResult');
}

void presentPaywallIfNeeded() async {
final paywallResult = await RevenueCatUI.presentPaywallIfNeeded("pro");
log('Paywall result: $paywallResult');
}

Listeners​

When using PaywallView, you may use one of the provided listeners to react to user actions. Available listeners at this time are:

  • onPurchaseStarted
  • onPurchaseCompleted
  • onPurchaseError
  • onRestoreCompleted
  • onRestoreError
  • onDismiss

Kotlin Multiplatform​

You can present a fullscreen Paywall using the Paywall composable. You have the flexibility to decide when to call this. You could, for instance, add it to your navigation graph.

val options = remember {
PaywallOptions(dismissRequest = { TODO("Handle dismiss") }) {
shouldDisplayDismissButton = true
}
}

Paywall(options)

Listeners​

When using Paywall, you may use one of the provided listeners to react to user actions. Available listeners at this time are:

  • onPurchaseStarted
  • onPurchaseCompleted
  • onPurchaseError
  • onPurchaseCancelled
  • onRestoreStarted
  • onRestoreCompleted
  • onRestoreError

Handling paywall navigation​

When creating a paywall, consider whether it will be presented in a sheet, or as a full screen view. Sheets won't require a dedicated close button. Full screen views should have either a close button (if presented modally) or a back button (if part of a navigation stack or host) unless you intend to provide a hard paywall to your customers that cannot be bypassed.

Custom fonts​

Paywalls v2 supports custom fonts, but it works slightly differently than original Paywalls. The FontProvider in the SDKs is ignored for v2 Paywalls. Instead, every text component in the paywall editor has a "Font family" property with a gear icon next to it. Clicking the gear icon allows you to configure your font families. In the modal that opens, you can name your font family, and set up the corresponding font for both Android and iOS. Fonts you can use include:

  • System fonts
  • Any of sans-serif, serif, or monospace
  • Custom fonts already included in your app

Including custom fonts in your app​

Android​

To add a custom font to your Android app, place the font file in the res/font folder. Make sure that the filename (without the extension) corresponds to the font name in the paywall editor. See the official Android documentation for more information.

iOS​

To add a custom font to your iOS app, go to File and then Add Files to β€œYour Project Name”. The font file should be a target member of your app, and be registered with iOS by adding the "Fonts provided by the application" key to your Info.plist file. Make sure that the filename (without the extension) corresponds to the font name in the paywall editor. See the official iOS documentation for more information.

Kotlin Multiplatform, React Native, and Flutter​

Adding custom fonts to a hybrid app involves adding the font files to the underlying Android and iOS projects following the instructions above.

Changes from original Paywalls​

Paywalls v2 does not support footer Paywalls. If your app requests the Paywall for an Offering to display that has a v2 Paywall, it will display a default version of that paywall instead (see below). Footer mode can still be used on original Paywalls templates using the existing method, or the new .originalTemplatePaywallFooter() method on iOS SDK versions 5.16.0+.

Close buttons​

Paywalls v2 does not require the displayCloseButton parameter (or equivalent for other platforms), and it will have no effect if used, since close buttons can be optionally added directly to your paywall as a component if desired.

Font provider​

Paywalls v2 does not support passing in a custom font provider as original Paywalls did. Instead, you can now configure Paywalls to use the fonts you've already installed in your app directly from the Dashboard. Using the original handler will have no effect on Paywalls v2. See the Custom fonts section for more information.

Default Paywall​

If you attempt to display a Paywall for an Offering that doesn't have one configured, or that has a Paywall configured which is not supported on the installed SDK version, the RevenueCatUI SDK will display a default Paywall.

The default paywall displays all packages in the Offering.

On iOS it uses the app's accentColor for styling. On Android, it uses the app's Material3's ColorScheme.

πŸ“˜Targeting

If your app supports our original Paywall templates, consider using Targeting to create an audience that only receives your v2 Paywall if they're using an SDK version that does not support Paywalls v2. This will ensure that older app versions continue to receive the Offering and Paywall that they support, while any app versions running a supported RC SDK version receive your new v2 Paywall. Learn more about Targeting.