When a paywall is presenting and a user converts, you can view the purchased products in several different ways.

Use the PaywallPresentationHandler

Arguably the easiest of the options — simply pass in a presentation handler and check out the product within the onDismiss block.

let handler = PaywallPresentationHandler()
handler.onDismiss { _, result in
  switch result {
  case .declined:
      print("No purchased occurred.")
  case .purchased(let product):
      print("Purchased \(product.productIdentifier)")
  case .restored:
      print("Restored purchases.")
  }
}

Superwall.shared.register(placement: "caffeineLogged", handler: handler) {
  logCaffeine()
}

Use SuperwallDelegate

Next, the SuperwallDelegate offers up much more information, and can inform you of virtually any Superwall event that occurred:

class SWDelegate: SuperwallDelegate {
  func handleSuperwallEvent(withInfo eventInfo: SuperwallEventInfo) {
    switch eventInfo.event {
    case .transactionComplete(_, let product, _, _):
      print("Transaction complete: product: \(product.productIdentifier)")
    case .subscriptionStart(let product, _):
      print("Subscription start: product: \(product.productIdentifier)")
    case .freeTrialStart(let product, _):
      print("Free trial start: product: \(product.productIdentifier)")
    case .transactionRestore(_, _):
      print("Transaction restored")
    case .nonRecurringProductPurchase(let product, _):
      print("Consumable product purchased: \(product.id)")
    default:
      print("Unhandled event.")
    }
  }
}

@main
struct Caffeine_PalApp: App {
@State private var swDelegate: SWDelegate = .init()

init() {
Superwall.configure(apiKey: "my_api_key")
Superwall.shared.delegate = swDelegate
}

var body: some Scene {
WindowGroup {
ContentView()
}
}
}

Use a purchase controller

If you are controlling the purchasing pipeline yourself via a purchase controller, then naturally the purchased product is available:

final class MyPurchaseController: PurchaseController {
  func purchase(product: StoreProduct) async -> PurchaseResult {
    print("Kicking off purchase of \(product.productIdentifier)")

    do {
      let result = try await MyPurchaseLogic.purchase(product: product)
      return .purchased // .cancelled,  .pending, .failed(Error)
    } catch {
      return .failed(error)
    }

}

// 2
func restorePurchases() async -> RestorationResult {
print("Restoring purchases")
return .restored // false
}
}

@main
struct Caffeine_PalApp: App {
private let pc: MyPurchaseController = .init()

init() {
Superwall.configure(apiKey: "my_api_key", purchaseController: pc)
}

var body: some Scene {
WindowGroup {
ContentView()
}
}
}

SwiftUI - Use PaywallView

The PaywallView allows you to show a paywall by sending it a placement. It also has a dismiss handler where the purchased product will be vended:

@main
struct Caffeine_PalApp: App {
  @State private var presentPaywall: Bool = false

  init() {
    Superwall.configure(apiKey: "my_api_key")
  }

  var body: some Scene {
    WindowGroup {
      Button("Log") {
        presentPaywall.toggle()
      }
      .sheet(isPresented: $presentPaywall) {
        PaywallView(placement: "caffeineLogged", params: nil, paywallOverrides: nil) { info, result in
          switch result {
          case .declined:
            print("No purchased occurred.")
          case .purchased(let product):
            print("Purchased \(product.productIdentifier)")
          case .restored:
            print("Restored purchases.")
          }
        } feature: {
          print("Converted")
          presentPaywall.toggle()
        }
      }
    }
  }
}