iOS - Handle paywall events

For: Developers

Paywalls configured with the Paywall Builder don't need extra code to make and restore purchases. However, they generate some events that your app can respond to. Those events include button presses (close buttons, URLs, product selections, and so on) as well as notifications on purchase-related actions taken on the paywall. Learn how to respond to these events below.

Handling events in Swift

To control or monitor processes occurring on the paywall screen within your mobile app, implement the AdaptyPaywallControllerDelegate methods.

User-generated events

Actions

If a user performs some action (close, openURL(url:) or custom(id:)), the method below will be invoked. Note that this is just an example and you can implement the response to actions differently:

func paywallController(_ controller: AdaptyPaywallController,
                       didPerform action: AdaptyUI.Action) {

    switch action {
        case .close:
            controller.dismiss(animated: true)
        case let .openURL(url):
      			// handle URL opens (incl. terms and privacy links)
            UIApplication.shared.open(url, options: [:])
        case let .custom(id):
            if id == "login" {
               // implement login flow 
            }
            break
    }
}

For example, if a user taps the close button, the action close will occur and you are supposed to dismiss the paywall. Note that at the very least you need to implement the reactions to both close and openURL.

💡

Login Action

If you have configured Login Action in the dashboard, you should also implement reaction for custom action with id "login".

Product selection

If a user selects a product for purchase, this method will be invoked:

    func paywallController(_ controller: AdaptyPaywallController,
                           didSelectProduct product: AdaptyPaywallProduct) {
    }

Started purchase

If a user initiates the purchase process, this method will be invoked:

func paywallController(_ controller: AdaptyPaywallController,
                       didStartPurchase product: AdaptyPaywallProduct) {
}

Canceled purchase

If a user initiates the purchase process but manually interrupts it, the method below will be invoked. This event occurs when the Adapty.makePurchase() function completes with a .paymentCancelled error:

func paywallController(_ controller: AdaptyPaywallController,
                       didCancelPurchase product: AdaptyPaywallProduct) {
}

Successful purchase

If Adapty.makePurchase() succeeds, this method will be invoked:

func paywallController(_ controller: AdaptyPaywallController,
                       didFinishPurchase product: AdaptyPaywallProduct,
                       purchasedInfo: AdaptyPurchasedInfo) {      
    controller.dismiss(animated: true)
}

We recommend dismissing the paywall screen in that case.

Failed purchase

If Adapty.makePurchase() fails, this method will be invoked:

func paywallController(_ controller: AdaptyPaywallController,
                       didFailPurchase product: AdaptyPaywallProduct,
                       error: AdaptyError) {
}

Successful restore

If Adapty.restorePurchases() succeeds, this method will be invoked:

func paywallController(_ controller: AdaptyPaywallController, 
                       didFinishRestoreWith profile: AdaptyProfile) {
}

We recommend dismissing the screen if a the has the required accessLevel. Refer to the Subscription status topic to learn how to check it.

Failed restore

If Adapty.restorePurchases() fails, this method will be invoked:

public func paywallController(_ controller: AdaptyPaywallController, 
                              didFailRestoreWith error: AdaptyError) {
}

Data fetching and rendering

Product loading errors

If you don't pass the product array during the initialization, AdaptyUI will retrieve the necessary objects from the server by itself. If this operation fails, AdaptyUI will report the error by calling this method:

public func paywallController(_ controller: AdaptyPaywallController,
                              didFailLoadingProductsWith error: AdaptyError) -> Bool {
    return true
}

If you return true, AdaptyUI will repeat the request after 2 seconds.

Rendering errors

If an error occurs during the interface rendering, it will be reported by this method:

public func paywallController(_ controller: AdaptyPaywallController,
                              didFailRenderingWith error: AdaptyError) {
}

In a normal situation, such errors should not occur, so if you come across one, please let us know.

Handling events in SwiftUI

To control or monitor processes occurring on the paywall screen within your mobile app, use the .paywall modifier in SwiftUI:

@State var paywallPresented = false

var body: some View {
	Text("Hello, AdaptyUI!")
			.paywall(
          isPresented: $paywallPresented,
          paywall: paywall,
          configuration: viewConfig,
          didPerformAction: { action in
              switch action {
                  case .close:
                      paywallPresented = false
                	case .openURL(url):
                			// handle opening the URL (incl. for terms and privacy)
                	case 
                  default:
                      // handle other actions
                      break
              }
          },
          didSelectProduct: { /* Handle the event */  },
          didStartPurchase: { /* Handle the event */ },
          didFinishPurchase: { product, info in /* Handle the event */ },
          didFailPurchase: { product, error in /* Handle the event */ },
          didCancelPurchase: { /* Handle the event */ },
          didStartRestore: { /* Handle the event */ },
          didFinishRestore: { /* Handle the event */ },
          didFailRestore: { /* Handle the event */ },
          didFailRendering: { error in
              paywallPresented = false
          },
          didFailLoadingProducts: { error in
              return false
          }
      )
}

You can register only the closure parameters you need, and omit those you do not need. In this case, unused closure parameters will not be created.

Closure parameterDescription
didSelectProductIf a user selects a product for purchase, this parameter will be invoked.
didStartPurchaseIf a user initiates the purchase process, this parameter will be invoked.
didFinishPurchaseIf Adapty.makePurchase() succeeds, this parameter will be invoked.
didFailPurchaseIf Adapty.makePurchase() fails, this parameter will be invoked.
didCancelPurchaseIf a user initiates the purchase process but manually interrupts it, this parameter will be invoked.
didStartRestoreIf a user initiates the purchase restoration, this parameter will be invoked.
didFinishRestoreIf Adapty.restorePurchases() succeeds, this parameter will be invoked.
didFailRestoreIf Adapty.restorePurchases() fails, this parameter will be invoked.
didFailRenderingIf an error occurs during the interface rendering, this parameter will be invoked.
didFailLoadingProductsIf you don't pass the product array during the initialization, AdaptyUI will retrieve the necessary objects from the server by itself. If this operation fails, AdaptyUI will invoke this parameter.

Note that at the very least you need to implement the reactions to both close and openURL.


What’s Next