Skip to main content
Answer

Add Event Listener to RevenueCatUI.presentPaywall - Capacitor

  • October 14, 2025
  • 1 reply
  • 41 views

Forum|alt.badge.img+1

I am using Ionic + Capacitor + RevenueCatUI to present Paywalls for my app’s subscriptions. 

 

I want to add event listeners so I can handle cases such as:

  • Restore Purchases with no Active Subscriptions
    • DEBUG: Restored purchases successfully with no subscriptions
  • Purchase Error due to Restore Behavior = ‘Keep with original App User ID’
    • ERROR: 😿‼️ There is already another active subscriber using the same receipt.

However, I see that RevenueCatUI only allows listeners for paywallDisplayed and paywallDismissed.

I am using:

"@revenuecat/purchases-capacitor": "^10.4.0",
"@revenuecat/purchases-capacitor-ui": "^10.4.0",

Is there any way I can handle the cases described above?

Best answer by guilherme

Hey ​@max-c4cd33 ,

RevenueCatUI only provides paywallDisplayed and paywallDismissed event listeners, but you can handle restore purchases and purchase errors by combining the PaywallResult from RevenueCatUI with the Purchases SDK's customer info listener:

  • restorePurchases with no active subscriptions: check the PaywallResult returned from presentPaywall() (example here) - when it's RESTORED, you can then inspect the CustomerInfo to see if there are active entitlements.
     
  • Purchase/Restore Errors: when PaywallResult is ERROR, this indicates an error occurred during the transaction, but specific error details are not included in the result. You can use verbose logging and check CustomerInfo updates to understand what happened.
     
  • CustomerInfo Updates: use addCustomerInfoUpdateListener() (docs here)from the main Purchases SDK (not RevenueCatUI) to listen for any customer info changes, which fires after restores, purchases, and other subscription events.

 For more information on displaying paywalls, see the official documentation.

Quick Example Snippet:

import { Purchases, LOG_LEVEL } from '@revenuecat/purchases-capacitor';
import { RevenueCatUI, PAYWALL_RESULT } from '@revenuecat/purchases-capacitor-ui';

// Enable verbose logging for debugging (optional)
await Purchases.setLogLevel({ level: LOG_LEVEL.VERBOSE });

// Set up listener during app initialization
await Purchases.addCustomerInfoUpdateListener((customerInfo) => {
const hasActiveEntitlements = Object.keys(customerInfo.entitlements.active).length > 0;

if (!hasActiveEntitlements) {
console.log('DEBUG: No active subscriptions found');
}
});

// When presenting paywall
try {
const paywallResult = await RevenueCatUI.presentPaywall();

switch (paywallResult.result) {
case PAYWALL_RESULT.RESTORED:
// Restore completed - check customer info
const { customerInfo } = await Purchases.getCustomerInfo();
const hasActive = Object.keys(customerInfo.entitlements.active).length > 0;
if (!hasActive) {
console.log('DEBUG: Restored purchases successfully with no subscriptions');
}
break;

case PAYWALL_RESULT.ERROR:
// An error occurred during purchase or restore
// Specific error details are not available in the result
// Check logs and CustomerInfo for more information
console.error('Transaction error occurred');
break;

case PAYWALL_RESULT.PURCHASED:
console.log('Purchase successful');
break;

case PAYWALL_RESULT.CANCELLED:
console.log('Paywall dismissed without action');
break;
}

} catch (error) {
// Handle paywall presentation errors
console.error('Paywall presentation error:', error);
}

This should help you in monitoring those other cases you mentioned.

This post has been closed for comments

1 reply

guilherme
RevenueCat Staff
Forum|alt.badge.img+6
  • RevenueCat Staff
  • Answer
  • October 16, 2025

Hey ​@max-c4cd33 ,

RevenueCatUI only provides paywallDisplayed and paywallDismissed event listeners, but you can handle restore purchases and purchase errors by combining the PaywallResult from RevenueCatUI with the Purchases SDK's customer info listener:

  • restorePurchases with no active subscriptions: check the PaywallResult returned from presentPaywall() (example here) - when it's RESTORED, you can then inspect the CustomerInfo to see if there are active entitlements.
     
  • Purchase/Restore Errors: when PaywallResult is ERROR, this indicates an error occurred during the transaction, but specific error details are not included in the result. You can use verbose logging and check CustomerInfo updates to understand what happened.
     
  • CustomerInfo Updates: use addCustomerInfoUpdateListener() (docs here)from the main Purchases SDK (not RevenueCatUI) to listen for any customer info changes, which fires after restores, purchases, and other subscription events.

 For more information on displaying paywalls, see the official documentation.

Quick Example Snippet:

import { Purchases, LOG_LEVEL } from '@revenuecat/purchases-capacitor';
import { RevenueCatUI, PAYWALL_RESULT } from '@revenuecat/purchases-capacitor-ui';

// Enable verbose logging for debugging (optional)
await Purchases.setLogLevel({ level: LOG_LEVEL.VERBOSE });

// Set up listener during app initialization
await Purchases.addCustomerInfoUpdateListener((customerInfo) => {
const hasActiveEntitlements = Object.keys(customerInfo.entitlements.active).length > 0;

if (!hasActiveEntitlements) {
console.log('DEBUG: No active subscriptions found');
}
});

// When presenting paywall
try {
const paywallResult = await RevenueCatUI.presentPaywall();

switch (paywallResult.result) {
case PAYWALL_RESULT.RESTORED:
// Restore completed - check customer info
const { customerInfo } = await Purchases.getCustomerInfo();
const hasActive = Object.keys(customerInfo.entitlements.active).length > 0;
if (!hasActive) {
console.log('DEBUG: Restored purchases successfully with no subscriptions');
}
break;

case PAYWALL_RESULT.ERROR:
// An error occurred during purchase or restore
// Specific error details are not available in the result
// Check logs and CustomerInfo for more information
console.error('Transaction error occurred');
break;

case PAYWALL_RESULT.PURCHASED:
console.log('Purchase successful');
break;

case PAYWALL_RESULT.CANCELLED:
console.log('Paywall dismissed without action');
break;
}

} catch (error) {
// Handle paywall presentation errors
console.error('Paywall presentation error:', error);
}

This should help you in monitoring those other cases you mentioned.