Visual paywalls

Learn how to show visual paywalls using Adapty iOS SDK.

🚧

This functionality is beta stage right now. Contact support for early access.

Adapty allows you remotely configure paywall through dashboard that could be displayed in your app without any client side updates.

At first place you need to configure your paywall in Adapty dashboard and after that you will be able to use them inside your app.

Show paywall

To show visual paywall as a modal screen, you need to call .showVisualPaywall() method.

Adapty.showVisualPaywall(for: paywall, from: self, delegate: self)

Request parameters:

  • For (required): PaywallModel which needs to be shown.
  • From (required): UIViewController object which modally displays paywall.
  • Delegate (required): AdaptyVisualPaywallDelegate object which provides callbacks for user actions.

Response parameters:

  • PaywallViewController: presented PaywallViewController object

In case if you want to show paywall in any other way, use .getVisualPaywall() method, which provides fully configured paywall controller which can be used as a subview in your flow or it can be pushed in your navigation stack, etc.

let paywallViewController = Adapty.getVisualPaywall(for: paywall, delegate: delegate)

Request parameters:

  • For (required): PaywallModel which needs to be shown.
  • Delegate (required): AdaptyVisualPaywallDelegate object which provides callbacks for user actions.

Response parameters:

  • PaywallViewController: PaywallViewController object

Close paywall

To close modal visual paywall, you need to call .closeVisualPaywall() method.

Adapty.closeVisualPaywall(paywallController)

Request parameters:

  • Paywall (optional): PaywallViewController object which should be closed. In case of nill value the latest presented paywall will be closed.

🚧

Make sure you use this method only if paywall was shown through Adapty.showVisualPaywall() method.
If you showed your paywall as a part of other screen (ex., onboarding slider), then only you responsible for dismissing such paywall.

AdaptyVisualPaywallDelegate

AdaptyVisualPaywallDelegate allows you to handle actions performed by the user in the paywall:

extension Listener: AdaptyVisualPaywallDelegate {
  
  func didPurchase(product: ProductModel, purchaserInfo: PurchaserInfoModel?, receipt: String?, appleValidationResult: Parameters?, paywall: PaywallViewController) {    
    // handle successful purchase and close paywall if needed
  }
  
  func didFailPurchase(product: ProductModel, error: AdaptyError, paywall: PaywallViewController) {
    // handle purchase error and close paywall if needed
  }
  
  func didCancel(paywall: PaywallViewController) {
     // close paywall by SDK method if it was shown modally
     // or handle closing in any other way
  }
  
  func didRestore(purchaserInfo: PurchaserInfoModel?, receipt: String?, appleValidationResult: Parameters?, error: AdaptyError?, paywall: PaywallViewController) {
     // handle purchases restore event  
  }
  
}

Basic flow

To show visual paywall, you need to call .showVisualPaywall() method.
Handle user actions from AdaptyVisualPaywallDelegate and close controller by .closeVisualPaywall() method.

func showPaywall() {
  // present visual paywall modaly 
  Adapty.showVisualPaywall(for: paywall, from: self, delegate: self)
}

extension Listener: AdaptyVisualPaywallDelegate {
  ...
  
  func didPurchase(product: ProductModel, purchaserInfo: PurchaserInfoModel?, receipt: String?, appleValidationResult: Parameters?, paywall: PaywallViewController) {    
    // handle successful purchase and close paywall if needed
    showSuccessfulPurchaseAlert()
    Adapty.closeVisualPaywall(paywall)
  }
  
  func didCancel(paywall: PaywallViewController) {
      // close paywall by SDK method
    Adapty.closeVisualPaywall(paywall)
  }
  
  ...
}

🚧

Make sure you close paywall by Adapty.closeVisualPaywall() if it was shown through Adapty.showVisualPaywall() method.

Advanced flow

Use .getVisualPaywall() method to get fully configured paywall controller which you can show the way you need.
Handle user actions from AdaptyVisualPaywallDelegate and dismiss controller in the same way you showed it.

func showPaywall() {
  // show visual paywall the way you need 
  let paywallViewController = Adapty.getVisualPaywall(for: paywall, delegate: delegate)
  navigationController?.pushViewController(paywallViewController, animated: true)
}

extension ViewController: AdaptyVisualPaywallDelegate {
  ...
  
  func didPurchase(product: ProductModel, purchaserInfo: PurchaserInfoModel?, receipt: String?, appleValidationResult: Parameters?, paywall: PaywallViewController) {    
    // handle successful purchase
    showSuccessfulPurchaseAlert()
    // handle closing paywall the way you want
    navigationController?.popViewController(animated: true)
  }
  
  func didCancel(paywall: PaywallViewController) {
     // handle closing paywall the way you want
    navigationController?.popViewController(animated: true)
  }
  
  ...
}

🚧

Make sure you don't close paywall by Adapty.closeVisualPaywall() if it was shown in any other way rather than Adapty.showVisualPaywall() because, for example, that way you can loose your navigation stack.

Visual paywalls with SwiftUI

Presenting PaywallViewController via SwiftUI can be complicated. Here is an example of a very basic implementation.

import SwiftUI
import Adapty

struct SwiftUISampleView: View {
    @ObservedObject var subscriptionInteractor = SubscriptionInteractor()
    
    var body: some View {
        Text("Sample")
            // bind "isPresented" property and present our controller when needed
            .fullScreenCover(isPresented: $subscriptionInteractor.isPresented) {
                PaywallViewControllerRepresentation(paywallModel: subscriptionInteractor.paywall!, delegate: subscriptionInteractor)
            }
    }
}

class SubscriptionInteractor: ObservableObject {
    var paywall: PaywallModel? = nil
    @Published var isPresented = false
    
    init() {
        Adapty.getPaywalls { (paywalls, products, error) in
            if let paywall = paywalls?.first {
                // receive needed synced paywall
                self.paywall = paywall
                self.isPresented = true
            }
        }
    }
}

extension SubscriptionInteractor: AdaptyVisualPaywallDelegate { ... }

struct PaywallViewControllerRepresentation: UIViewControllerRepresentable {
    let paywallModel: PaywallModel
    let delegate: AdaptyVisualPaywallDelegate
    
    // wrapper over our controller for SwiftUI
    func makeUIViewController(context: Context) -> PaywallViewController {
        return Adapty.getVisualPaywall(for: paywallModel, delegate: delegate)
    }
    
    func updateUIViewController(_ uiViewController: PaywallViewController, context: Context) { }
}

Did this page help you?