Blocking Paywalls

Learn how to use a paywall to block access to features or content in your app.

Blocking paywalls are a powerful way to make sure that your users are paying for the best parts of your app. In this guide, we'll walk through the technical details of how to implement a blocking paywall.

Control Center Configuration

  1. Log in to the Control Center, navigate to the Paywalls section, and select a paywall.
1211
  1. Navigate to the Controls tab and set the Blocking toggle to On.
1211

Once this is done, you then need to add some code to your app to tell it what to do when a user closes a blocking paywall. You might want to direct the user to another screen or take some other action.

How these blocking actions work are slightly different by platform. Each platform is discussed below.

Android

Android uses a common requestCode and resultCode pattern via
Activity.setResult() and Activity.onActivityResult() to provide information about if user did close a blocking Nami paywall by clicking on the close button.

Note that if the paywall is of the type non-blocking, then SDK will not set the result and thus you will not be able to know when a user closes the paywall. For non-blocking paywalls, the app behavior should just continue as normal when the user dismisses the paywall screen and no special action is required.

🚧

When using a blocking paywall to gate access to premium content or features, it is important that you present the paywall before sending the user to the blocked content.

If you raise the paywall on the blocked content itself, the paywall can still be dismissed and if your onActivityResult() does not handle this situation correctly the user would get access to the premium content.

class AppActivity : AppCompatActivity() {
  
  private fun someMethod() {
    if (NamiPaywallManager.canRaisePaywall)) {
        NamiPaywallManager.raisePaywall(this)
    }
  }
  
  override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    // Here use this convenient method to get boolean value
    // to deteremine whether user did close a blocking Nami 
    // paywall by clicking on close button or not
    if (NamiPaywallManager.didUserCloseBlockingNamiPaywall(requestCode, resultCode)) {
      Toast.makeText(this, "User closed the paywall", Toast.LENGTH_SHORT).show()
    }
  }
}
public class AppActivity extends AppCompatActivity {
  
  private void someMethod() {
    if (NamiPaywallManager.canRaisePaywall()) {
      NamiPaywallManager.raisePaywall(this);
    }
  }
  
  @Override
  protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    // Here use this convenient method to get boolean value
    // to deteremine whether user did close a blocking Nami 
    // paywall by clicking on close button or not
    if (NamiPaywallManager.didUserCloseBlockingNamiPaywall(requestCode, resultCode)) {
      Toast.makeText(this, "User closed the paywall", Toast.LENGTH_SHORT).show();
    }
  }
}

Apple

On Apple devices, if you set a paywall to be blocking, then by default the paywall will not be able to be closed by the user after raising and the close button will not appear. It will stay up until the user terminates the application.

🚧

When setting a paywall to be blocking on Apple devices, it is important to provide an applicationBlockingPaywallClosedHandler otherwise your users will get stuck on the paywall until they kill the app.

If you have opted to disallow the close button for a paywall, but then provide an applicationBlockingPaywallClosedHandler, the close button will re-appear. When the close button is used or the user dismisses the paywall via gestures, your callback will be called and can at that point chose to navigate the user to somewhere specific in the application where they can be directed to after closing not to pay at that time.

If the user does select a payment option and completes a payment transaction, the paywall will be dismissed normally and the blocked handler will not be called.

The applicationBlockingPaywallClosedHandler is not sent any arguments.

NamiPaywallManager.registerBlockingPaywallClosedHandler() {
   if let rootController = UIApplication.shared.windows.first?.rootViewController {
     let alertController = UIAlertController.init(title: "Blocked Paywall Closed", message: "Blocking paywall closed without purchase.", preferredStyle: .alert)
     let okAction = UIAlertAction(title: "OK", style: .default) { (alertAction) in
                    
         rootController.dismiss(animated: true) {
           // Do anything extra after alert dismisses.
         }
      }
                
     alertController.addAction(okAction)
                
     // Present the alert
     DispatchQueue.main.async() {
       rootController.present(alertController, animated: true) {
       }
     }
   }
 })
[NamiPaywallManager registerBlockingPaywallClosedHandler:^{
  UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Blocked Paywall Closed" message:@"Blocking paywall closed without purchase." preferredStyle:UIAlertControllerStyleAlert];
        
  UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
    [alertController dismissViewControllerAnimated:true completion:^{
    }]
  }];
  
  [alertController addAction:okAction];
  UIViewController *rootViewController = [[[UIApplication sharedApplication] keyWindow] rootViewController];
  [rootViewController presentViewController:alertController animated:true completion:^{}];
}];

React Native

In React Native apps, blocking paywalls will not actually prevent the user from accessing parts of the app unless you direct them away from the screen when a BlockingPaywallClosed event is produced.

This event will only be fired when the paywall is set as Blocking in the Control Center and the paywall is dismissed without a successful purchase being made.

const { NamiEmitter } = NativeModules;
const eventEmitter = new NativeEventEmitter(NamiEmitter);

const onBlockedPaywallClosed = (event) => {
  // Add code to handle the case where a blocked paywall has been closed, for example returning to initial app screen.                   
  console.log("ExampleApp: Blocking paywall has been closed ");
}

useEffect(() => {
  eventEmitter.addListener('BlockingPaywallClosed', onBlockedPaywallClosed);
})