PaywallPresentationHandler
A handler class that provides status updates for paywall presentation in registerPlacement() calls.
Use this handler when you need fine-grained control over paywall events for a specific
registerPlacement() call, rather than global events
via SuperwallDelegate.
This handler is specific to the individual registerPlacement() call. For global paywall events
across your app, use SuperwallDelegate instead.
Purpose
Provides callbacks for paywall lifecycle events when using registerPlacement() with a specific handler instance.
Signature
class PaywallPresentationHandler {
void onPresent(Function(PaywallInfo) handler);
void onDismiss(Function(PaywallInfo, PaywallResult) handler);
void onSkip(Function(PaywallSkippedReason) handler);
void onError(Function(String) handler);
void onCustomCallback(
Future<CustomCallbackResult> Function(CustomCallback) handler,
);
}Parameters
Prop
Type
Returns / State
Each method returns void and configures the handler for the specific paywall lifecycle event.
CustomCallback (2.4.8+)
The onCustomCallback handler receives a CustomCallback object.
Prop
Type
CustomCallbackResult (2.4.8+)
Return a CustomCallbackResult from your callback handler to control paywall flow:
CustomCallbackResult.success([Map<String, Object>? data])
CustomCallbackResult.failure([Map<String, Object>? data])Use data to send values back to the paywall, available as callbacks.<name>.data.<key>.
PaywallInfo State (2.4.8+)
PaywallInfo now includes state, a Map<String, Object>? with current paywall state values.
Usage
Basic handler setup:
Future<void> _registerFeatureWithHandler() async {
final handler = PaywallPresentationHandler();
handler.onPresent((paywallInfo) {
print('Paywall presented: ${paywallInfo.identifier}');
print('Paywall state: ${paywallInfo.state}');
});
handler.onDismiss((paywallInfo, result) {
print('Paywall dismissed with result: $result');
switch (result) {
case PaywallResult.purchased:
_showSuccessMessage();
break;
case PaywallResult.cancelled:
_showPromotionalOffer();
break;
case PaywallResult.restored:
_updateUIForActiveSubscription();
break;
}
});
await Superwall.shared.registerPlacement(
'premium_feature',
params: {'source': 'feature_screen'},
handler: handler,
feature: () {
_unlockPremiumFeature();
},
);
}Handle skip, error, and custom callbacks:
Future<void> _setupComprehensiveHandler() async {
final handler = PaywallPresentationHandler();
handler.onSkip((reason) {
print('Paywall skipped: $reason');
switch (reason) {
case PaywallSkippedReason.userIsSubscribed:
_proceedToFeature();
break;
case PaywallSkippedReason.holdout:
_proceedToFeature();
break;
default:
break;
}
});
handler.onError((error) {
print('Paywall error: $error');
_showErrorDialog(error);
});
handler.onCustomCallback((callback) async {
switch (callback.name) {
case 'validate_email':
final email = callback.variables?['email'] as String?;
if (email != null && email.contains('@')) {
return CustomCallbackResult.success({'validated': true});
}
return CustomCallbackResult.failure({'error': 'Invalid email'});
default:
return CustomCallbackResult.failure({'error': 'Unknown callback'});
}
});
await Superwall.shared.registerPlacement(
'remove_ads',
handler: handler,
feature: () {
_hideAdsFromUI();
},
);
}How is this guide?