Paywalls
Measure how your paywalls are seen and dismissed.
Mark when a paywall opens and when it closes. Riveora measures how long it stayed on screen and how it was closed, per paywall. If most people close it within two seconds, they never read your offer, and the problem is when you show it, not the price.
The Paywalls page also lists everyone who saw each paywall: how many times, their longest look, their total time and whether they bought. Open a person to see each view with its exact time (UTC), where it was shown from, and a link that replays that visit in their journey.
Open and close
import { Riveora } from '@riveora/react-native';
const visitId = Riveora.paywall.open({
paywallId: 'main_offer', // your name for this paywall
source: 'results_screen', // where the user was
trigger: 'unlock_more_matches', // why it opened
});
// Later, when it goes away:
Riveora.paywall.close(visitId, { reason: 'dismissed' }); // or 'purchased'| Reason | Type | Description |
|---|---|---|
dismissed | default | The user closed it. |
purchased | string | The user paid. Counts as a sale on the sales pages. Don’t use it for a free trial that hasn’t been charged yet. |
restored | string | The user restored an earlier purchase. Not counted as a new sale. |
presentation_failed | string | The paywall couldn’t be shown. |
background | string | The app went to the background while it was open. |
Dynamic paywalls
Change the paywall your app shows without releasing a new version. You pick the paywall in RevenueCat, your app shows it, and Riveora tracks each one separately under its offering’s name, so you can compare them.
Load the current offering instead of naming one, and pass it to Riveora:
import Purchases from 'react-native-purchases';
import RevenueCatUI from 'react-native-purchases-ui';
import { trackRevenueCatPaywall } from '@riveora/react-native';
const offering = (await Purchases.getOfferings()).current;
const result = await trackRevenueCatPaywall(
() => RevenueCatUI.presentPaywall({ offering }),
{ offering, source: 'results_screen', trigger: 'unlock_more_matches' },
);It records the visit and how it ended (purchased, restored, closed or failed to show) and returns RevenueCat’s result unchanged. It works the same with presentPaywallIfNeeded(); when RevenueCat doesn’t show the paywall because the person already has access, nothing is recorded.
Showing the <RevenueCatUI.Paywall> component instead? Pass your callbacks through the hook and spread what it returns:
import { useRevenueCatPaywallTracking } from '@riveora/react-native';
const tracking = useRevenueCatPaywallTracking({
offering,
source: 'home',
onDismiss: () => setVisible(false),
});
return <RevenueCatUI.Paywall options={{ offering }} {...tracking} />;With RevenueCat connected, the Paywalls page also shows purchases and revenue for each offering. That comes from RevenueCat, so it works for app versions already in the stores too. An offering that sells but isn’t tracked in your app yet still gets a row.
Test different paywalls
Each paywall in RevenueCat belongs to an offering, and Riveora gives each offering its own row. To compare two paywalls, give each one its own offering:
- In RevenueCat, create a second offering under Offerings → + New, with a clear identifier like
pro_v2. That identifier is its name in Riveora. - Under Paywalls → Create paywall, design the new paywall, link it to that offering and click Publish Paywall.
- Choose who sees it, in one of the two ways below.
Switch everyone to it. In Offerings, make the new offering the Default. Everyone gets the new paywall, the old offering’s row stops getting views, and you compare the two rows: before and after. It’s simple, but the two paywalls are seen by different people at different times, so a sale, a holiday, an app release or more ad traffic can move the numbers too. To keep it fair:
- Compare periods of the same length, for example two weeks against two weeks.
- Don’t change prices or release your app at the same moment.
- Wait for a few hundred views on the new paywall before deciding.
- Decide within a month: the Paywalls page covers the last 30 days, so the old row drops off after that.
To try it on part of your users first, add a Targeting → New rule that shows the new offering to one group only, such as one country.
Run an experiment. Under Experiments → New experiment, pick your current offering and the new one as the variants. RevenueCat splits people between them at the same time, so it’s the fairest comparison. Use RevenueCat’s experiment results to pick the winner, and Riveora to see why it won.
Either way, no app release is needed, and both offerings show side by side on the Paywalls page: how long people looked at each, how often they closed it and, with RevenueCat connected, what each one sold.
Editing a paywall in place keeps its offering, so the old and new design are counted in the same row. Make a new offering whenever you want to compare.
If the paywall doesn’t change
- Your app loads one offering by name, like
offerings.all['default']. It then always shows that one. Useofferings.current, which follows the Default offering and your Targeting rules. - The app still has the old offerings. RevenueCat caches them on the device. Close and reopen the app, or wait a few minutes.
- The new offering has no published paywall. Link a paywall to it and publish it.
Native paywalls draw their own screens, so taps inside them aren’t captured. The open, close and time on screen are.
React components
For paywalls built in React Native, two helpers handle open and close for you:
import { TrackedPaywall } from '@riveora/react-native';
<TrackedPaywall paywallId="main_offer" source="home" visible={visible}>
<MyPaywall onClose={() => setVisible(false)} />
</TrackedPaywall>Or use the usePaywallTracking hook for full control; see the SDK reference.
Insights
When more than half of a paywall’s views in the last 30 days last under 2 seconds, Riveora raises an insight, once that paywall has at least 50 views.
When to show it
Once purchases are recorded, the Paywalls page shows which moment sells best: first view or a later one, minutes or days after install, and which screen or trigger opened it. Pass a meaningful source and trigger so those comparisons are useful.
The purchased reason comes from your app. Connect RevenueCat to use verified store transactions instead; see Revenue and drop-offs.