Changelog
Release notes for the Superwall iOS SDK
4.10.8
Enhancements
- Adds support for
Set user attributesaction. - Adds new
SuperwallDelegatemethod calleduserAttributesDidChangethat notifies you when user attributes change from an external source. - Adds
firebaseInstallationIdas anIntegrationAttribute.
Fixes
- Fixes a crash caused by a race condition when accessing JSON dictionaries concurrently.
- Fixes issue returning the
PurchaseResultfromSuperwall.shared.purchase(_:)when using StoreKit 1 inside aPurchaseController. - Fixes
handleDeepLinkreturning true for non-Superwall URLs when called before configuration completes.
4.10.6
Fixes
- Fixes issue that prevented the SDK from being built on old Xcode versions.
4.10.5
Fixes
- Updates
device.isApplePayAvailablefor more accurate filtering. Previously it returned true whenever the device supported Apple Pay, even if no card was added. It now returns true only when the device supports Apple Pay and the user has added a card. - Fixes issue where
didRedeemLinkmight not get called if there's no paywall available to present an alert from.
4.10.4
Fixes
- Updates Superscript version to 1.0.10. This fixes an issue with namespacing in cocoapods. View the original Rust release changelog here.
- Fixes some issues building for visionOS.
4.10.3
Fixes
- Fixes issue where
Superwall.shared.confirmAllAssignments()would be return an emptySetif config hadn't been retrieved.
4.10.1
Fixes
- Fixes issue where
willRedeemLinkmight get called twice during the web checkout payment sheet flow. - Fixes issue where paywall might get dismissed prematurely during web checkout.
- Fixes issue where the spinner on the paywall wasn't showing for a few seconds after the system closed the web checkout payment sheet due to a successful purchase.
4.10.0
Enhancements
- Adds
CustomerInfo. This contains the latest information about all of the customer's purchase and subscription data. This can be accessed via the published propertySuperwall.shared.customerInfo, viaSuperwall.shared.getCustomerInfo(), via theAsyncStreamcustomerInfoStream, or via the delegate methodcustomerInfoDidChange(from:to:). This updates theEntitlementobject to have more properties such asstartsAtandexpiredAt. These can be used in audience filters. - Adds
Superwall.shared.entitlements.byProductIds(_:)to return aSetofEntitlementobjects belonging to a given set of product identifiers. - Changes the
PurchaseControllerexamples to account forCustomerInfochanges. - Adds
transaction_abandoncapability to web checkout payment sheet.
Fixes
- Fixes issue after purchasing web products where localized strings weren't correct in SDK wrappers like Expo.
4.9.3
Enhancements
- Zero second delay when presenting paywalls after calling
Superwall.configureif 1. the user is subscribed, and 2. there is a cached configuration.
Fixes
- Allowed paywall webviews to refresh if they were terminated by the system. This typically happened in Expo apps if very large photos were used in the paywall.
4.9.2
Fixes
- Fixes delay in paywall presentation if there's an issue retrieving web entitlements.
4.9.1
Fixes
- Fixes a rare issue where calling reset while the SDK was still retrieving its configuration could occasionally prevent paywalls from appearing.
- Fixes positioning issue for surveys in iOS 26.
4.9.0
Enhancements
- Adds ability to open the web checkout page in a payment sheet style web view.
- Updates Superscript version to 1.0.4. View the original Rust release changelog here.
- Adds the
SuperwallOptionshouldBypassAppTransactionCheck, which allows you to opt out ofAppTransaction.sharedusage during SDK initialization. This is useful in testing environments to avoid triggering the Apple ID sign-in prompt. - Adds
device.isApplePayAvailableto the device attributes that can be used in audience filters. - Adds
onWillDismissto thePaywallPresentationHandler, which is called when the paywall will dismiss.
Enhancements
- Updates Superscript version to 1.0.4. View the original Rust release changelog here.
Fixes
- Changes "With/Without Free Trial" to "With/Without Intro Offer" in the debugger.
- Fixes rare crash caused by a concurrency issue.
- Fixes issue where no internet would cause a minute delay for paywall presentation.
4.8.3
Enhancements
- Adds support for redeeming web entitlements with Paddle.
4.8.2
Enhancements
- Adds
review_requestedevent when a review is requested.
4.8.1
Enhancements
- Adds ability to specify a custom height and corner radius for the drawer presentation style.
- Adds ability to grant an entitlement to anyone.
- Adds
Superwall.shared.setIntegrationAttributes(_:)which allows you to set attributes for third-party integrations. - Adds
Superwall.shared.setIntegrationAttribute(_:_:)for setting individual integration attributes. - Adds
Superwall.shared.integrationAttributesto get the attributes you've set. - Adds the ability to ask for an App Store review from a paywall tap action.
- Adds a popup presentation style.
- Adds product retrying if StoreKit 2 encounters an error while fetching products.
- Tracks a
paywallProductsLoad_missingProductsevent if the products were missing.
Fixes
- Fixes issue with tracking
demandScoreanddemandTieron paywall open. - Fixes a rare crash due to memory allocation issues.
- Fixes a rare crash due to a race condition during data processing.
- Fixes issue where weekly StoreKit 2 products might have the wrong daily price.
4.7.0
Enhancements
- Adds
placementsInXwhich can be used in audience filters. This means you can make a filter that will only fire if a placement has been fired X times in the past hour/day/week/year/since install. - Updates Superscript version to 1.0.2. View the original Rust release changelog here.
- Adds
swiftVersionandcompilerVersionto the device attributes.
Fixes
- Makes sure web entitlements are always redeemed the first time the app loads from a cold start.
- Fixes issue where the Superwall config wasn't timing out and falling back to the cached config after 1 second.
4.6.0
Enhancements
- Adds the
PaywallOptionoverrideProductsByName, which can be used to globally override products on any paywall that have a given name. This can also be set after configure has been called by settingSuperwall.shared.overrideProductsByName. - Adds the
PaywallOptionshouldShowWebPurchaseConfirmationAlert, which shows a localized alert confirming a successful purchase via web checkout. Defaults totrue.
Fixes
- Fixes issue where deep links passed to the SDK before configure completes aren’t handled after configure finishes.
4.5.2
Fixes
- Replace
UIApplication.sharedwithsharedApplicationaccessed via KVC so that SuperwallKit can be used in app extensions. - Fixes issue where the paywall debugger would crash when viewing template variables if products weren't loaded.
- Fixes issue where an in-app web checkout wouldn't close Safari after purchase.
4.5.1
Fixes
- Fixes issue where
webViewLoad_failevents weren't being tracked.
4.5.0
Enhancements
- Adds
handleSuperwallDeepLink(_:pathComponents:queryParameters:)to theSuperwallDelegate. This is called when all deep links from the web checkout are handled. This link may arrive as either a universal link (https://yoursubdomain.superwall.app/app-link/...) or a custom URL scheme (subdomain://yoursubdomain.superwall.app/app-link/...). - Adds
url,path,pathExtension,lastPathComponent,host,query, andfragmentto thedeepLink_openevent, which you can use in audience filters.
Fixes
- Fixes a race condition when identifying and then immediately getting user attributes.
- Removes usage of private API
LSApplicationWorkspace.
4.4.2
Enhancements
- Updates Superscript to 0.2.8.
Fixes
- Fix for old versions of Xcode not building due to not supporting
.winBacktransaction offer types. - Fixes an issue where the paywall could be presented from the wrong scene in multi-window apps.
4.4.1
Fixes
- Fixes race condition when initialising the SDK that could result in a crash.
4.4.0
Enhancements
- Adds
Superwall.shared.getDeviceAttributes(), which returns the device attributes that are used when evaluating audience filters.
4.3.11
Fixes
- Fixes an issue when serialising some device attributes in the flutter SDK.
4.3.10
Enhancements
- Adds
networkDecoding_failevent to help with debugging if a decoding error happens. - Adds
stateto thePaywallInfoobject. This is set on dismiss of the paywall and can be used to access state variables set in the editor.
Fixes
- Fixes issue where the configuration completion block could take a long time to complete if the user had a lot of transactions.
- Fixes issue where
didDismissPaywall(withInfo:)and theonDismisspaywall presentation handler would be called before the presenting window was destroyed.
4.3.9
Fixes
- Fixes issue with a paywall not closing if you had a survey attached to a paywall that fires after purchasing and a
survey_responseimplicit trigger.
4.3.8
Fixes
- Fixes build issue with VisionOS.
4.3.7
Enhancements
- Adds
storeFrontCountryCode,storeFrontCurrency, andstoreFrontIdto the device variables. These can be used to display web checkout paywalls exclusively to those in the USA. - Adds support for redeeming a code via a universal link.
- Adds
codeandtypeto redemption events to improve debugging.
Fixes
- Ensures that the UUID from the automatically assigned Superwall alias is passed as the
appAccountTokenfor purchases whenidentify(userId:)has not been called.
4.3.5
Fixes
- Fixes issue where
Superwall.shared.dismiss()wouldn't work as expected if the in-app browser was open.
4.3.4
Enhancements
- Sends the campaign details to the paywall.
4.3.3
Fixes
- Prevents the blocking of paywall presentation if the enrichment request fails.
- Fixes an issue where an app extension accessing Superwall wouldn't work.
- Sometimes transactions weren't being retrieved by our SDK after a purchase so we've made this process more robust.
- Fixes issue with compiler failing to build for CocoaPods on older Xcode versions.
4.3.0
Enhancements
- Adds a
SuperwallOptionnamedenableExperimentalDeviceVariables. When set totrue, this enables additional device-level variables:latestSubscriptionPeriodType,latestSubscriptionState, andlatestSubscriptionWillAutoRenew. These properties provide information about the most recent StoreKit 2 subscription on the device and can be used in audience filters. Note that due to their experimental nature, they are subject to change in future updates.
4.2.2
Fixes
- Fixes an issue where computed properties used in audience filters (e.g. "minutes since") weren’t being properly encoded. This could lead to incorrect behavior when falling back to the cached config after a network issue.
4.2.1
Enhancements
- Adds the
PaywallOptionshouldShowWebRestorationAlert, which can be set tofalseto suppress the alert prompting users to restore their purchase via the web.
Fixes
- Fixes issue where the redeeming of web entitlements may have been incorrectly counted as a restoration.
- Fixes issue where the web checkout redemption endpoint was being called on identify even if you hadn't enabled web checkout.
4.2.0
Enhancements
- Adds
demandScoreanddemandTierto device attributes using an off-device advanced machine learning model. A user is assigned these based on a variety of factors to determine whether they're more or less likely to convert and can be used within audience filters. - Adds the static method
Superwall.handleDeepLink(_:)and deprecates the instance methodSuperwall.shared.handleDeepLink(_:). Now if the deep link gets called beforeconfigureis called, we store the deep link and handle it after configuring. - Adds support for web checkout.
- Updates Superscript to 0.2.4.
Fixes
- Fixes a timeout issue for the loading of the Superwall config when the cached config feature flag is enabled.
4.2.0-beta.1
Enhancements
- Adds
demandScoreanddemandTierto device attributes using an off-device advanced machine learning model. A user is assigned these based on a variety of factors to determine whether they're more or less likely to convert and can be used within audience filters. - Updates Superscript to 0.2.4.
4.1.0-beta.6
Breaking Changes
- Renames
ExpiredInfotoExpiredCodeInfoto be more explicit. - Renames
codeExpiredRedemptionResultcase toexpiredCode.
Enhancements
- Adds Objective-C support for web checkout.
4.1.0-beta.5
Enhancements
- Adds the static method
Superwall.handleDeepLink(_:)and deprecates the instance methodSuperwall.shared.handleDeepLink(_:). Now if the deep link gets called beforeconfigureis called, we store the deep link and handle it after configuring.
4.1.0-beta.3
Fixes
- Updates the SuperwallDelegate
didRedeemCode(code:)example code for RevenueCat web checkout. - Fixes decoding error for an expired code.
- Prevents
willRedeem()from being called onidentify. - Makes sure
subscriptionStatusis set on the main thread when redeeming codes.
4.1.0-beta.2
Breaking Changes
- Adds Stripe subscription IDs to the
stripeStoreIdentifiercase. - Changes
codeExpired(code: String, expired: ExpiredInfo)RedemptionResultcase tocodeExpired(code: String, expiredInfo: ExpiredInfo).
Enhancements
- Adds
willRedeemCodeto theSuperwallDelegateto indicate that a code redemption is about to happen. - Adds
stripeSubscriptionIdsconvenience variable to theRedemptionResultfor quick access.
Fixes
- Adjusts
RCPurchaseControllerexample and submits the stripe subscription ID from thedidRedeemCode(result:)delegate method to the RevenueCat API. - Makes sure to present alert on web entitlement restoration failure.
4.1.0-beta.1
Enhancements
- Adds support for web checkout.
4.0.6
Fixes
- Prevents all overloads of
Superwall.shared.purchase(_:)from being called when theshouldObservePurchasesSuperwallOptionis set totrue.
4.0.5
Fixes
- Fixes a visionOS build-time issue.
4.0.4
Fixes
- Adds in missing
appAccountTokenfor StoreKit 2 purchases.
4.0.3
Enhancements
- Adds
$storekitVersion,$maxConfigRetryCount, and$shouldObservePurchasesto theconfig_attributesevent. - Updates Superscript to 0.1.18.
- Confirms all paywall assignments locally to reduce the amount of preloading of paywalls on each cold app open.
- Migrates documents used for user and app data out of the documents folder and into the application support folder.
- If the SDK is using StoreKit 2 and not using a purchase controller, a refunded purchase is no longer considered active and therefore does not give the user an active entitlement.
Fixes
- Deprecates the naming of
handleSuperwallPlacement(withInfo:)back tohandleSuperwallEvent(withInfo:). - Deprecates
SuperwallPlacementback toSuperwallEvent. - Deprecates
SuperwallPlacementInfoback toSuperwallEventInfo.
4.0.1
Fixes
- Fixes a bug where unsupported value types as user attributes or placement parameters would cause a
noAudienceMatch
4.0.0
Breaking Changes
- Removes
trigger_session_idfromPaywallInfoparams. ProductInfois renamed toProductand the oldProductclass no longer exists.- Renames
subscriptionStatusDidChange(to:)tosubscriptionStatusDidChange(to:from:)in theSuperwallDelegate. - Renames
productItemstoproductsinPaywallInfo. - Renames
register(event:)toregister(placement:). - Renames
preloadPaywalls(forEvents:)topreloadPaywalls(forPlacements:). - Renames
PaywallView(event:)toPaywallView(placement:). - Renames
getPaywall(forEvent:)togetPaywall(forPlacement:). - Renames
getPresentationResult(forEvent:)togetPresentationResult(forPlacement:). - Renames the
TriggerResult,PresentationResultandPaywallSkippedReasoneventNotFoundcase toplacementNotFoundandnoEventMatchtonoAudienceMatch. - Renames
handleSuperwallEvent(withInfo:)to `handleSuperwallPlacement(withInfo:). - Moves
ComputedPropertyRequestTypeto be a top-level type. - Renames
StoretoProductStore. - Removes
Superwall.shared.isConfiguredin favor ofSuperwall.shared.configurationStatus. - Defaults to StoreKit 2 for product purchasing for apps running on iOS 15+. You can change this back to StoreKit 1 by setting the
SuperwallOptionstoreKitVersionto.storeKit1. When using Objective-C and providing a PurchaseController or using observer mode, the SDK will default to.storeKit1. If you're using Objective-C and usingpurchase(_:), you must use.storeKit1. - Changes the
PurchaseControllerpurchase function tofunc purchase(product: StoreProduct) async -> PurchaseResult. There will be an StoreKit 2 product accessible viaproduct.sk2Productby default. However, if you're using the StoreKit 1SuperwallOptionor your app is running on an iOS version lower than iOS 15, this will beniland you can access the StoreKit 1 product viaproduct.sk1Product. - Consumables no longer count as lifetime subscriptions when using StoreKit 2.
- Renames the
PurchaseResultcasepurchased(productId: String)topurchased(Product). - Changes the Swift
onDismissblock of thePaywallPresentationHandlerto accept both aPaywallInfoobject and aPaywallResultobject so you know which product was purchased after dismiss. - Changes the
onRequestDismissblock of thePaywallViewto accept both aPaywallInfoobject and aPaywallResultobject. - Changes the Objective-C
onDismissblock of thePaywallPresentationHandlerto accept both aPaywallInfoobject, aPaywallResultobject, and an optionalStoreProduct, so you know which product was purchased after dismiss. - Renames
LogScopecasepaywallTransactionstotransactions. - Adds
typeto thetransactionCompleteplacement. - Removes the
restoredresult fromPurchaseResult.
Enhancements
- Adds
purchase(_:)support for both StoreKit 2 products andStoreProduct. - Adds
Superwall.shared.subscriptionStatus.isActiveas a convenience variable. - Adds entitlements as associated values to the
activecase ofSuperwall.shared.subscriptionStatus. If you're not using aPurchaseController, we will handle the entitlements for you depending on what products the user purchases. - Adds
Superwall.shared.entitlementswhich has the following properties:all,activeandinactive. - Adds
setUnknownSubscriptionStatus(),setInactiveSubscriptionStatus(), andsetActiveSubscriptionStatus(with:)for Objective-C users. - Updates the example apps. We now have Basic and Advanced. Basic is a simple plug-and-play superwall setup that doesn't use entitlements. Advanced uses entitlements and has three possible ways of configuring Superwall: 1. Letting Superwall manage everything, 2. Using a purchase controller with StoreKit, 2. Using a purchase controller with RevenueCat.
- Uses
Superscriptfor all audience filter evaluations. This is our in-house package that uses Google's Common Expression Language to evaluate audience filters. It allows for complex expressions within the audience filter builder. - Adds StoreKit 2 observer mode. This can be enabled by setting the
SuperwallOptionsshouldObservePurchasestotrueandstoreKitVersionto.storeKit2(which is the default value). Note that this is only available with apps running iOS 17.2+. - Adds
products(for:)which gets the ``StoreProduct`s for given product identifiers.
Please see our migration guide and docs for a full breakdown of what's new.
4.0.0-beta.7
Fixes
- Fixes an SK1 swift continuation leak when purchasing.
4.0.0-beta.6
Breaking Changes
- Removes the
restoredresult fromPurchaseResult.
4.0.0-beta.5
Breaking Changes
- Replaces
entitlements.statuswithsubscriptionStatus. entitlementStatusDidChangereverted tosubscriptionStatusDidChange.EntitlementStatusremoved in favor ofSubscriptionStatus.
Enhancements
- Adds
Superwall.shared.subscriptionStatus.isActiveas a convenience variable.
4.0.0-beta.4
Fixes
- Fixes a crash that was caused by a concurrency issue.
4.0.0-beta.3
Breaking Changes
- Renames
PaywallView(event:)toPaywallView(placement:).
Fixes
- Adds extra check to get StoreKit 2 transaction data on
transaction_complete.
4.0.0-beta.2
Fixes
- Fixes an issue to do with audience filters.
- Re-adds unavailable functions from v3 to make the upgrade path smoother.
4.0.0-beta.1
Fixes
- Removes date checking for transactions, which was resulting in some purchases being marked as restored.
- Checks for the
SKIncludeConsumableInAppPurchaseHistoryinfo.plist key. If set totrue, defaults to using.storeKit2only if on iOS 18+. - Fixes visionOS issues.
4.0.0-alpha.4
Fixes
- Fixes bug for StoreKit version specified in a
transaction_completeevent. - Reverts change of
presented_by_placement_nametopresented_by_event_nameto fix campaign charts.
4.0.0-alpha.3
Enhancements
- Adds the obsoleted attribute to more variants of
register(event:)for a smoother upgrade path.
Fixes
- Fixes issue with optional audience filter properties inside
PaywallInfo.
4.0.0-alpha.2
Breaking Changes
- Removes
trigger_session_idfromPaywallInfoparams. ProductInfois renamed toProductand the oldProductclass no longer exists.- Removes
Superwall.shared.subscriptionStatusin favor of entitlements. - Removes
subscriptionStatus_didChange. - Removes
subscriptionStatusDidChange(to:)from theSuperwallDelegate. - Renames
productItemstoproductsinPaywallInfo. - Renames
register(event:)toregister(placement:). - Renames
preloadPaywalls(forEvents:)topreloadPaywalls(forPlacements:). - Renames
getPaywall(forEvent:)togetPaywall(forPlacement:). - Renames
getPresentationResult(forEvent:)togetPresentationResult(forPlacement:). - Renames the
TriggerResult,PresentationResultandPaywallSkippedReasoneventNotFoundcase toplacementNotFoundandnoEventMatchtonoAudienceMatch. - Renames
handleSuperwallEvent(withInfo:)to `handleSuperwallPlacement(withInfo:). - Moves
ComputedPropertyRequestTypeto be a top-level type. - Renames
StoretoProductStore. - Removes
Superwall.shared.isConfiguredin favor ofSuperwall.shared.configurationStatus. - Defaults to StoreKit 2 for product purchasing for apps running on iOS 15+. You can change this back to StoreKit 1 by setting the
SuperwallOptionstoreKitVersionto.storeKit1. When using Objective-C and providing a PurchaseController or using observer mode, the SDK will default to.storeKit1. If you're using Objective-C and usingpurchase(_:), you must use.storeKit1. - Changes the
PurchaseControllerpurchase function tofunc purchase(product: StoreProduct) async -> PurchaseResult. There will be an StoreKit 2 product accessible viaproduct.sk2Productby default. However, if you're using the StoreKit 1SuperwallOptionor your app is running on an iOS version lower than iOS 15, this will beniland you can access the StoreKit 1 product viaproduct.sk1Product. - Consumables no longer count as lifetime subscriptions when using StoreKit 2.
- Renames the
PurchaseResultcasepurchased(productId: String)topurchased(Product). - Changes the Swift
onDismissblock of thePaywallPresentationHandlerto accept both aPaywallInfoobject and aPaywallResultobject so you know which product was purchased after dismiss. - Changes the
onRequestDismissblock of thePaywallViewto accept both aPaywallInfoobject and aPaywallResultobject. - Changes the Objective-C
onDismissblock of thePaywallPresentationHandlerto accept both aPaywallInfoobject, aPaywallResultobject, and an optionalStoreProduct, so you know which product was purchased after dismiss. - Renames
LogScopecasepaywallTransactionstotransactions. - Adds
typeto thetransactionCompleteplacement.
Enhancements
- Adds
purchase(_:)support for both StoreKit 2 products andStoreProduct. - Adds
Superwall.shared.entitlements. This is a published property of typeEntitlementStatus. If you're using Combine or SwiftUI, you can listen to this to receive updates whenever it changes. Otherwise, you can use theSuperwallDelegatemethodentitlementStatusDidChange(from:to:). If you're not using aPurchaseController, we will handle the entitlements for you depending on what products the user purchases. However, if you're using aPurchaseControler, you can set the entitlement status, which can be.unknown,.inactive, or.active(Set<Entitlement>). You can also accessall,activeandinactiveentitlements from the entitlements object. - Adds
getStatus(),setUnknownStatus(),setInactiveStatus(), andsetActiveStatus(with:)onSuperwall.shared.entitlementsfor Objective-C users. - Tracks an
entitlementStatus_didChangeevent whenever the entitlement status changes. - Updates the example apps. We now have Basic and Advanced. Basic is a simple plug-and-play superwall setup that doesn't use entitlements. Advanced uses entitlements and has three possible ways of configuring Superwall: 1. Letting Superwall manage everything, 2. Using a purchase controller with StoreKit, 2. Using a purchase controller with RevenueCat.
- Uses
Superscriptfor all audience filter evaluations. This is our in-house package that uses Google's Common Expression Language to evaluate audience filters. It allows for complex expressions within the audience filter builder. - Adds the
LogScopecaseentitlements. - Adds StoreKit 2 observer mode. This can be enabled by setting the
SuperwallOptionsshouldObservePurchasestotrueandstoreKitVersionto.storeKit2(which is the default value). Note that this is only available with apps running iOS 17.2+. - Adds
products(for:)which gets the ``StoreProduct`s for given product identifiers.
3.12.5
Fixes
- Fixes a rare crash to do with a swift continuation leak when purchasing.
3.12.4
Fixes
- Simplifies and corrects logic for choosing paywall variants.
3.12.3
Fixes
- Fixes an issue where trying to purchase a product that was previously purchased may prevent the spinner from disappearing on the paywall.
3.12.2
Fixes
- Fixes visionOS build issues.
3.12.1
Fixes
- Fixes issue for flutter when enabling Apple Search Ads on the Dashboard. This is done by cleaning all user attributes such that only those that are JSON serializable are stored.
- Removes date checking for transactions, which was resulting in some purchases being marked as restored.
3.12.0
Enhancements
- Adds the
SuperwallOptionshouldObservePurchases. Set this totrueto allow us to observe StoreKit 1 transactions you make with your app outside of Superwall. When this is enabled Superwall will not finish your external transactions. StoreKit 2 will be widely supported in the next major version of our SDK. - Adds Apple Search Ads attribution data to user attributes, which is visible on the user's page in Superwall. Attribution data will be collected if you have enabled Basic or Advanced Apple Search Ads in the Superwall dashboard settings. Advanced attribution data includes the keyword name, campaign name, bid amount, match type, and more. Otherwise, the basic attribution data will be collected, which is mostly IDs. This data will soon be added to Charts.
- Adds
isSubscribedto product attributes so that you can useproducts.primary.isSubscribedas a dynamic value in the paywall editor. - Adds
device.appVersionPaddedto the device properties that you can use in audience filters. - Adds a
notificationPermissionsDeniedPaywallOption, which you can set to show an alert after a user denies notification permissions.
Fixes
- Fixes issue where network requests that returned an error code weren't being retried.
- Fixes date formatting on a device property.
3.11.3
Enhancements
- Updates Superscript to 0.1.16.
3.11.2
Enhancements
- Adds
shimmerView_startandshimmerView_completeevents. TheshimmerView_completeevent contains avisible_durationparameter which indicates how long the shimmer view was visible after paywall open, if at all. - Adds
isScrollEnabledtoPaywallInfo, which indicates whether the webview should scroll or not. - Updates Superscript to v0.1.15.
- Adds
$source,$store, and$storekit_versionto transaction events.
Fixes
- Fixes issue where using a
PurchaseControllerwithSuperwall.shared.purchase(product)was resulting in transaction events being tracked twice. - Fixes build issues for visionOS, Mac Catalyst, and watchOS.
3.11.1
Fixes
- Fixes an issue when getting the Superscript package.
3.11.0
Enhancements
- Adds a
PaywallViewfor SwiftUI users using iOS 14+. You can use this as a standalone paywall view that you can embed and present however you like instead of usingregister. This usesgetPaywall(forEvent:params:paywallOverrides:)under the hood. Note that you're responsible for the deallocation of the view. If you have aPaywallViewpresented somewhere and you try to present the samePaywallViewelsewhere, you will get a crash. - Adds our
Superscriptpackage as a dependency. We are migrating towards using Google's Common Expression Language (CEL) in audience filters to allow for more complex expressions. The use of this is behind a feature flag.
Fixes
- visionOS fixes.
3.10.2
Enhancements
- Adds
maxConfigRetryCountas aSuperwallOption. Use this to determine the number of times the SDK will attempt to get the Superwall configuration after a network failure before it times out.
3.10.1
Fixes
- Tweaks logic for
purchase(_:)andrestorePurchases()so the SDK never finishes transactions made when there's a purchase controller present. - Fixes internal caching issues of the Superwall config.
3.10.0
Enhancements
- Adds
purchase(_:)to initiate a purchase of anSKProductvia Superwall regardless of whether you are using paywalls or not. - Adds
restorePurchases()to restore purchases via Superwall. - Adds an optional
paywall(_:loadingStateDidChange)function to thePaywallViewControllerDelegate. This is called when the loading state of the presentedPaywallViewControllerdid change. - Makes
loadingStateon thePaywallViewControllera public published property.
Fixes
- Tweaks AdServices token logic to prevent getting the token twice.
3.9.1
Fixes
- Moves to collecting just the AdServices attribute token, which will be process by our backend. Adds
adServicesTokenRequest_start,adServicesTokenRequest_complete, andadServicesTokenRequest_fail.
3.9.0
Enhancements
- If a network issue occurs while retrieving the latest Superwall configuration, or it takes longer than 1s to retrieve, the SDK falls back to a cached version. Then it tries to refresh it in the background. This behavior is behind a feature flag.
- When the Superwall configuration is set or refreshed, a
config_refreshevent is tracked, which will give insight into whether a cached version of the Superwall configuration is being used or not. - When the Superwall configuration fails to be retrieved, a
config_failevent is tracked. - Adds the
config_cachingcapability. - Adds the
SuperwallOptioncollectAdServicesAttribution. When set totrue, this will get the app-download campaign attributes associated with Apple Search Ads and attach them to the user attributes. This happens once per user per install. CallingSuperwall.shared.reset()will fetch the attributes again and attach them to the new user. - Adds
adServicesAttributionRequest_start,adServicesAttributionRequest_fail, andadServicesAttributionRequest_completeevents for the lifecycle of collecting AdServices attributes.
Fixes
- Adds in missing
weak selfreferences inside task group closures.
3.8.0
Enhancements
- Adds
Superwall.shared.confirmAllAssignments(), which confirms assignments for all placements and returns an array of all confirmed experiment assignments. Note that the assignments may be different when a placement is registered due to changes in user, placement, or device parameters used in audience filters. - Adds a published property
Superwall.shared.configurationStatus, which replacesisConfigured. This is an enum which can either bepending,configured, orfailed.
Fixes
- Fixes
UIScreen unavailable in visionOSerror message inPaywallViewController. - Fixes the error
Symbol not found: _$s10Foundation14NSDecimalRoundyySpySo0B0aG_SPyADGSiSo14NSRoundingModeVtF, which is an Xcode 16 bug.
3.7.4
Fixes
- Fixes rare crash caused by a Combine issue.
- Confirms the assigment to holdouts for implicit placements like
paywall_decline. - Tracks the
trigger_fireevent for implicit placements.
3.7.3
Fixes
- Fixes issue with decoding custom placements from paywalls.
3.7.2
Fixes
- Changes access level of a property used by our Flutter and React Native wrapper SDKs.
3.7.1
Enhancements
- Adds a
custom_placementevent that you can attach to any element in the paywall with a dictionary of parameters. When the element is tapped, the event will be tracked. The name of the placement can be used to trigger a paywall and its params used in audience filters. - Tracks a
config_attributesevent after callingSuperwall.configure, which contains info about the configuration of the SDK. This gets tracked whenever you set the delegate. - Adds in device attributes tracking after setting the interface style override.
- Adds
close_reasontoPaywallInfoproperties.
3.7.0
Enhancements
- Adds support for multiple paywall URLs, incase one CDN provider fails.
- Adds the ability for the SDK to refresh the Superwall configuration every session start, subject to a feature flag. This means the paywalls will be kept updated even if the app has been open for a long time in the background.
- Adds
build_idandcache_keytoPaywallInfo. - Tracks a
config_refreshSuperwall event when the configuration is refreshed. - Adds product retrying if we fail to fetch an
SKProduct. This tracks apaywallProductsLoad_retryevent whenever the product loading request gets retried. - SW-2899: Adds
Superwall.shared.localeIdentifieras a convenience variable that you can use to dynamically update the locale used for evaluating rules and getting localized paywalls. - Adds feature flag to enable text interaction with a paywall.
- SW-2901: Adds
abandoned_product_idto atransaction_abandonevent to use in audience filters. You can use this to show a paywall if a user abandons the transaction for a specific product. - Updates RevenueCat example app to use v5 of their SDK.
Fixes
- Fixes error message
undefined is not an objectthat sometimes appeared when opening a paywall. - SW-2871: Makes sure to track device attributes after geo location data is found.
- Fixes issue where restored transactions were being finished even if a
PurchaseControllerwas supplied in configure. - SW-2879: Adds
capabilitiesto device attributes. This is a comma-separated list of capabilities the SDK has that you can target in audience filters. This release adds thepaywall_event_receivercapability. This indicates that the paywall can receive transaction and restore events from the SDK. - SW-2879: Adds
configCapabiltieswhich contains anameof the capability and any additional info. Thepaywall_event_receivercapability contains a list of eventNames specifying the exact events paywalljs can receive. - Fixes a crash caused by an arithmetic overflow if there was an issue with audience filter limits.
- Fixes
UIScreen unavailable in visionOSerror message inPaywallViewController.
3.6.6
Enhancements
- SW-2804: Exposes a
presentationproperty on thePaywallInfoobject. This contains information about the presentation of the paywall. - Adds
restore_start,restore_complete, andrestore_failevents. - SW-2850: Adds error message to
paywallWebviewLoad_fail. - SW-2851: Adds error message to
paywallProductsLoad_fail. - SW-2783: Logs error when trying to purchase a product that has failed to load.
Fixes
- Makes sure the formatting of SK2 product variables use the same locale as the product.
3.6.5
Enhancements
- Adds
enable_webview_process_pool,enable_suppresses_incremental_rendering,enable_throttle_scheduling_policy,enable_none_scheduling_policyas feature flags for the webview configuration.
3.6.4
Enhancements
- Tweaks to webview configuration for performance improvements.
Fixes
- Fixes bug where paywall background wasn't being set.
3.6.3
Enhancements
- SW-2828: Adds the Superwall
appUserIdas theapplicationUsernamefor internalSKPayments. - SW-2817: Adds support for dark mode paywall background color.
- SW-2815: Adds ability to target devices based on their IP address location. Use
device.ipRegion,device.ipRegionCode,device.ipCountry,device.ipCity,device.ipContinent, ordevice.ipTimezone. - Paywalls built with the new editor can be downloaded as webarchive files. This allows for shared resources and faster loading times for paywalls.
Fixes
- Fixes issue where implicit triggers weren't sending a
paywallPresentationRequestwhen they didn't result in a paywall. Now this applies only to implicit triggers that are derived from an action on the paywall, likepaywall_decline.
3.6.2
Enhancements
- Tracks an
identity_aliasevent whenever identify is called to alias Superwall's anonymous ID with a developer provided id. - Adds
setInterfaceStyle(to:)which can be used to override the system interface style. - Adds
device.interfaceStyleModeto the device template, which can beautomaticormanualif overriding the interface style.
Fixes
- Changes the
$feature_gatingparameter inPaywallInfofrom 0 and 1 toGATEDandNON_GATEDto prevent confusion. - Fixes issue where feature gating wasn't working correctly when an implicit event triggered by
paywall_decline,transaction_fail,transaction_abandon, orsurvey_responsewas resulting in askippedPaywallState. - Fixes issue where a
transaction_abandonimplicit event that resulted in askippedPaywallStatewas accidentally closing a paywall when it shouldn't have.
3.6.1
Enhancements
- Adds privacy manifest.
3.6.0
Enhancements
- Adds support for unlimited products in a paywall.
- SW-2767: Adds
device.regionCodeanddevice.preferredRegionCode, which returns theregionCodeof the locale. For example, if a locale isen_GB, theregionCodewill beGB. You can use this in the filters of your campaign. - Adds ability to specify custom API endpoints using
SuperwallOptionsto facilitate local testing more easily.
Fixes
- Calls the completion block even if Superwall.configure is called more than once.
getPresentationResultnow confirms assignments for holdouts.
3.5.0
Enhancements
- Adds visionOS support.
Fixes
- Moves resources into their own resources bundle when installing via CocoaPods.
3.5.0-rc.3
Fixes
- Moves resources into their own resources bundle when installing via CocoaPods.
3.5.0-rc.1
This is our first visionOS pre-release, we'll test this on a few devices to ensure everything works as expected!
Enhancements
- Adds support for visionOS!
3.4.8
Enhancements
- SW-2667: Adds
preferredLanguageCodeandpreferredLocaleto device attributes. If your app isn't already localized for a language you're trying to target, thedeviceLanguageCodeanddeviceLocalemay not be what you're expecting. Use these device attributes instead to access the first preferred locale the user has in their device settings.
Fixes
- Fixes bug where a
transaction_abandonortransaction_failevent would prevent the presented paywall from dismissing ifpaywall_declinewas a trigger. - SW-2678: Fixes issue where the
subscription_startevent was being fired even if a non-recurring product was purchased. - SW-2659: Fixes issue on macOS where the window behind a paywall wasn't being removed when a paywall was dismissed, leading to the app appearing to be in a frozen state.
3.4.6
Enhancements
- Adds internal code for SDK wrappers like Flutter.
3.4.5
Enhancements
- Adds internal feature flag to disable verbose events like
paywallResponseLoad_start. - Tracks a Superwall Event
resetwheneverSuperwall.shared.reset()is called.
Fixes
- Fixes issue where holdouts were still matching even if the limit set for their corresponding rules were exceeded.
- Fixes potential crash if the free trial notification delay was set to zero seconds.
3.4.4
Enhancements
- Tracks user attributes on session start.
- Exposes
triggerSessionIdon thePaywallInfoobject. - Makes
PaywallSkippedReasonconform toCustomStringConvertible. - Adds the Superwall SDK version and your app's version/build number to the debugger menu. Press the hamburger icon on the top left in the debugger to access it.
Fixes
- Changes the way paywall presentation serialization is performed to avoid mixing of concurrency paradigms.
- Prevents
preloadAllPaywalls()from being called if the SDK is already preloading paywalls. - Fixes issue where experiment and trigger session details were missing from transaction events if a paywall was closed before returning a
PurchaseResultin thePurchaseController. - Prevents multiple taps on a purchase button from firing the
PurchaseControllerpurchase function multiple times. - Tracks
survey_responsewhen selected in debugger.
3.4.3
Enhancements
- Exposes
isPaywallPresentedconvenience variable. - Adds
device_attributesevent, which tracks the device attributes every new session. - Stops preloading paywalls that we know won't ever match.
- Adds a
.restoredcase toPurchaseResultandPurchaseResultObjc. Return this from yourPurchaseControllerwhen you detect a user has tried to purchase a product that they've already purchased. This happens whentransaction.transactionDate < purchaseDate, wherepurchaseDateis the date that the purchase was initiated. Check outRCPurchaseController.swiftin our Superwall-UIKit+RevenueCat example app for how to implement this. If you let Superwall handle purchasing, then we will automatically detect this. - Adds
restore_via_purchase_attemptto atransaction_restoreevent. This indicates whether the restoration happened due to the user purchasing or restoring.
3.4.2
Fixes
- Fixes issue where multiple events registered in quick succession may not be performed in serial, resulting in unexpected paywalls.
- Fixes issue where transaction data wouldn't be available for those who are using a purchase controller.
3.4.0
Enhancements
- Adds
sdkVersion,sdkVersionPadded,appBuildString, andappBuildStringNumberto the device object for use in rules.sdkVersionis the version of the sdk, e.g.3.4.0.sdkVersionPaddedis the sdk version padded with zeros for use with string comparison. For example003.004.000.appBuildStringis the build of your app andappBuildStringNumberis the build of your app casted as an Int (if possible). - When you experience
no_rule_match, theTriggerFireevent params will specify which part of the rules didn't match in the format"unmatched_rule_<id>": "<outcome>". Whereoutcomewill either beOCCURRENCE, referring to the limit applied to a rule, orEXPRESSION. Theidis the experiment id. - Adds a
touches_beganimplicit trigger. By adding thetouches_beganevent to a campaign, you can show a paywall the first time a user touches anywhere in your app. - Adds the ability to include a close button on a survey.
- If running in sandbox, the duration of a free trial notification added to a paywall will be converted from days to minutes for testing purposes.
- Adds the ability to show a survey after purchasing a product.
Fixes
- Fixes issue where a survey attached to a paywall wouldn't show if you were also using the
paywall_declinetrigger. - Fixes issue where verification was happening after the finishing of transactions when not using a
PurchaseController. - Fixes issue where the retrieved
StoreTransactionassociated with the purchased product may benil. - Fixes issue where a
presentationRequestwasn't being tracked for implicit triggers likesession_startwhen there was no internet.
3.3.2
Fixes
- Fixes issue where a rule added with
paywall_declinewould result in the feature block being called too early. - Fixes issue where paywall assignments may not have been cleared when resetting.
3.3.1
Enhancements
- Adds logic to enhance debugging by sending a stringified version of all the device/user/event parameters used to evaluate rules within the
paywallPresentationRequestevent. This is behind a feature flag. - Adds logic to keep the user's generated
seedvalue consistent whenSuperwall.identifyis called. This is behind a feature flag.
Fixes
- Fixes rare issue when using limits on a campaign rule. If a paywall encountered an error preventing it from being presented, it may still have been counted as having been presented. This would then have affected future paywall presentation requests underneath the same rule.
- Fixes issue where assets weren't being accessed correctly when installing the SDK via CocoaPods.
- Fixes crash if you tried to save an object that didn't conform to NSSecureCoding in user attributes.
3.3.0
Enhancements
- Adds the ability to add a paywall exit survey. Surveys are configured via the dashboard and added to paywalls. When added to a paywall, it will attempt to display when the user taps the close button. If the paywall has the
modalPresentationStyleofpageSheet,formSheet, orpopover, the survey will also attempt to display when the user tries to drag to dismiss the paywall. The probability of the survey showing is determined by the survey's configuration in the dashboard. A user will only ever see the survey once unless you reset responses via the dashboard. The survey will always show on exit of the paywall in the debugger. - Adds the ability to add
survey_responseas a trigger and use the selected option title in rules. - Adds new
PaywallCloseReason.manualClose.
Fixes
- Fixes a recursive issue that was happening if you forgot to configure the Superwall instance.
- Fixes issue where a preloaded
Paywallobject wouldn't have had an experiment available on itsinfoproperty. - Fixes "error while deleting file" log on clean install of app.
- Exposes the
IdentityOptionsinitializer. - Fixes thread safety issues.
3.2.2
Fixes
- If using a purchase controller, returning
.restoredfromrestorePurchases()would dismiss the paywall and assume an active subscription status. This was incorrect behavior. Now we specifically check both the subscription status and the restoration result to determine whether to dismiss the paywall, regardless of whether a purchase controller is being used. - Added extra logging when a timeout occurs during paywall presentation.
3.2.1
Fixes
- Fixes
user_attributesbeing unnecessarily fired on every cold app launch.
3.2.0
Enhancements
- Adds
user.seedto user attributes for use in campaign rules. This assigns a user a random number from 0 to 99. This allows you to segment users into cohorts across campaigns. For example, in campaign A you may sayif user.seed < 50 { show variant A } else { show variant B }, in campaign B you may sayif user.seed < 50 { show variant X } else { show variant Y }. Therefore users who see variant A will then see variant X. - Adds ability to use
device.interfaceTypein campaign rules to show different paywalls for different interface types. Use this instead ofdevice.deviceModel, as that can lead to inaccurate results on some devices.interfaceTypecan be one ofipad/iphone/mac/carplay/tv/unspecified. Note that iPhone screen size emulated in iPad will beiphone. Built for iPad on Mac will beipad. - Adds
presentation_source_typetoPaywallInfo, which lets you know the source function that retrieved the paywall – register/getPaywall/implicit. - Tracks whether a purchase controller is being used on the
AppInstallevent.
Fixes
- Fixes issue where the transition from background to foreground may not have been detected on app launch, resulting in paywalls not showing.
- Fixes iOS 14 transaction validation issue that affects apps on v3.0.2+.
- Adds safeguard for developers returning an empty
NSErroron purchase failure which could cause a crash.
3.1.1
Enhancements
- Adds
shouldShowPurchaseFailureAlertas aPaywallOption. This defaults totrue. If you're using aPurchaseController, set this tofalseto disable the alert that shows after the purchase fails.
Fixes
- Fixes issue where a secondary paywall wouldn't present with the
transaction_failtrigger. - Fixes issue where the paywall preview wasn't obeying free trial/default paywall overrides.
- Fixes issue where preloaded paywalls may be associated with the incorrect experiment.
3.1.0
Enhancements
- Adds support for paywalls that include a free trial notification. After starting a free trial, the app checks whether the paywall should notify the user when their trial is about to end. If so, the user will be asked to enable notifications (if they haven't already) before scheduling a local notification. You can add a free trial notification to your paywall from the paywall editor.
- Adds ability to use
device.minutesSince_X,device.hoursSince_X,device.daysSince_X,device.monthsSince_X, anddevice.yearsSince_Xin campaign rules and paywalls, whereXis an event name. This can include Superwall events, such asapp_open, or your own events. - Prints out the Superwall SDK version when the
debuglogLevel is enabled. - Adds
removeAllPendingSuperwallNotificationRequests(),removeAllPendingNonSuperwallNotificationRequests(),removeAllDeliveredSuperwallNotifications(), andremoveAllDeliveredNonSuperwallNotifications()toUNUserNotificationCenter. You can use these methods to remove your app's notifications without affecting Superwall's local notifications and vice-versa. - Updates RevenueCat to the latest version in our RevenueCat example app.
Fixes
- Fixes a Core Data multi-threading issue when performing a count. If you had enabled Core Data multi-threading assertions in Xcode, this will have caused a crash.
- Fixes very rare crash when purchasing without a
PurchaseController. - Reduces reliance on Combine when using register to fix memory management crashes.
3.0.3
Fixes
- Fixes an issue where Superwall events
app_launch,app_install, andsession_startweren't working as paywall triggers from a cold start.
3.0.2
Fixes
- Fixes issues with Xcode 15 and iOS 17.
- Moves the loading of localizations to only when the debugger is launched, therefore reducing setup time of Superwall.
- Removes reliance on force unwrapping/force casting as a safety precaution.
- Moves tracking of free trial start and transaction complete events to a higher priority Task. Before, this was of background priority and would take a while to track.
- Fix crash when trying to access
Superwall.shared.userId. - Prices in variables are now rounded down, e.g. 3.999 becomes 3.99, rather than 4.00.
- Fixes incorrect values for
trialPeriodPrice,trialPeriodDailyPrice,trialPeriodWeeklyPrice,trialPeriodMonthlyPrice,trialPeriodYearlyPricevariables.
3.0.1
Fixes
- Fixes bug that prevented Superwall from configuring when SwiftUI users in sandbox mode used the App file's
init()to configure Superwall.
3.0.0
Welcome to SuperwallKit v3.0, the framework formally known as Paywall!
This update is a major release, containing lots of breaking changes, enhancements and bug fixes. We're excited for you to use it!
We understand that transitions between major SDK releases can become frustrating, so we've made a migration guide to make your life easier. We've also updated our example apps to v3, including RevenueCat+SuperwallKit and Objective-C apps. Finally, we recommend you check out our updated docs.
Breaking Changes
- Renames the package from
PaywalltoSuperwallKit. - Renames the primary static class for integrating Superwall from
PaywalltoSuperwall. - Sets the minimum iOS version to iOS 13.
- Moves all functions and variables to the
sharedinstance for consistency. - Renames
preloadPaywalls(forTriggers:)topreloadPaywalls(forEvents:) - Renames
configure(apiKey:userId:delegate:options:)toconfigure(apiKey:purchaseController:options:completion:). You can use the completion block to know when Superwall has finished configuring. - Removes delegate from
configure. You now set the delegate viaSuperwall.shared.delegate. - Changes
PaywallOptionstoSuperwallOptions. This now clearly defines which of the options are explicit to paywalls vs other configuration options within the SDK. - Makes
Superwall.shared.optionsinternal so that options must be set inconfigure. - Removes
Superwall.trigger(event:)and replaces with register(event:params:handler). This is Superwall's most powerful feature yet. Wrap your features with this method to conditionally show paywalls, lock features and more. - Renames
Paywall.EventNametoSuperwallEventand removes.manualPresentas aSuperwallEvent. - Renames
PaywallDelegatetoSuperwallDelegate. - Superwall now automatically handles all subscription-related logic. However, if you'd still like control (e.g. if you're using RevenueCat), you'll need to implement a
PurchaseControllerand setSuperwall.shared.subscriptionStatusyourself whenever the subscription status of the user changes. You pass yourPurchaseControllertoconfigure(apiKey:purchaseController:options:completion:). - Removes
isUserSubscribed()from the delegate and replaces this with a published instance variablesubscriptionStatus. This is enum that defaults to.unknownon first install and the cached value on subsequent app opens. If you're using aPurchaseControllerto handle subscription-related logic, you must setsubscriptionStatusevery time the user's subscription status changes. If you're letting Superwall handle subscription-related logic, this value will be updated with the device receipt. - For Objective-C users, this changes the
SWKPurchaseControllermethodpurchase(product:)topurchase(product:completion:). You call the completion block with the result of the user attempting to purchase a product, making sure you handle all cases ofSWKPurchaseResult:.purchased,.cancelled,.pending,failed. When you have a purchasing error, you need to call the completion block with the.failedcase along with the error. - Changes
restorePurchases()to an async function that returns a boolean instead of having a completion block. - Removes
Paywall.load(identifier:). This was being used to preload a paywall by identifier. - Removes
.triggerPaywall()for SwiftUI apps. Instead, SwiftUI users should now use the UIKit functionSuperwall.register(). - Changes the
periodandperiodlyattributes for 2, 3 and 6 month products. Previously, theperiodwould be "month", and theperiodlywould be "monthly" for all three. Now theperiodreturns "2 months", "quarter", "6 months" and theperiodlyreturns "every 2 months", "quarterly", and "every 6 months". - Removes
localizationOverride(localeIdentifier:)and replaces it with theSuperwallOptionlocaleIdentifier. You set this on configure. - Removes ASN1Swift as a package dependency.
- Changes free trial logic. Previously we'd look at just the primary product. However, we determing free trial eligibility based on the first product in the paywall that has a free trial available.
- Changes Objective-C method
setUserAttributesDictionary(_:)tosetUserAttributes(_:). - Adds
PaywallInfotoSuperwallDelegatemethodsWillPresentPaywall(withInfo:),didPresentPaywall(withInfo:),willDismissPaywall(withInfo:)anddidDismissPaywall(withInfo:). - Renames
SuperwallDelegatemethoddidTrackSuperwallEventInfo(_:SuperwallEventInfo)tohandleSuperwallEvent(withInfo eventInfo: SuperwallEventInfo)for clarity. - Renames
SuperwallDelegatemethodswillOpenURL(url:)andwillOpenDeepLink(url:)topaywallWillOpenURL(url:)andpaywallWillOpenDeepLink(url:)respectively. - Changes the
logLevelto be non-optional and introduces anonecase to turn off logging. - Removes all guides from the SDK documentation. From now on, our online docs provide guides and the SDK documentation is only there as a technical reference.
- Changes the return type of
PurchaseController.restorePurchases()fromBooltoRestorationResult. - Changes
DismissStatetoPaywallResult. - Renamed the
PaywallResultcaseclosedtodeclined. - Removes .error(Error) from
PaywallSkippedReasonin favor of a newPaywallStatecase.presentationError(Error). - Exposes the
transactionBackgroundViewPaywallOptionto Objective-C by making it non-optional and adding anonecase in place of setting it tonil.
Enhancements
- Adds
getPaywall(forEvent:params:paywallOverrides:delegate:)! You can use this to request thePaywallViewControllerto present however you like. Please read our docs to learn more about how to use this. - Adds paywall caching. This is enabled on all paywalls by default, however it can be turned off on a case by case basis via the dashboard. With this enhancement, your paywalls will load lightning fast and will reduce network load of your app.
- You can now pass an
IdentityOptionsobject toidentify(userId:options). This should only be used in advanced use cases. By setting therestorePaywallAssignmentsproperty ofIdentityOptionstotrue, it prevents paywalls from showing until after paywall assignments have been restored. If you expect users of your app to switch accounts or delete/reinstall a lot, you'd set this when identifying an existing account. - Adds
Superwall.shared.isLoggedInto check whether the user is logged in to the SDK or not. This will be true if you've previously calledidentify(userId:options:). This is added to user properties, which means you can create a rule based on whether the user is logged in vs. whether they're anonymous. - Adds a new example app, UIKit+RevenueCat, which shows you how to use Superwall with RevenueCat.
- Adds a new Objective-C example app UIKit-Objc.
- Adds an Objective-C-only function
removeUserAttributes(_:)to remove user attributes. In Swift, to remove attributes you can pass innilfor a specific attribute insetUserAttributes(_:). - Adds
getPresentationResult(forEvent:params:). This returns aPresentationResult, which preemptively gets the result of registering an event. This helps you determine whether a particular event will present a paywall in the future. - Logs when products fail to load with a link to help diagnose the cause.
- Adds a published property
isConfigured. This is a boolean which you can use to check whether Superwall is configured and ready to present paywalls. - Adds
isFreeTrialAvailabletoPaywallInfo. - Adds
subscriptionStatusDidChange(to:)delegate function. If you're letting Superwall handle subscription logic you can use this to receive a callback whenever the user's internal subscription status changes. You can also listen to the publishedsubscriptionStatusvariable. - Adds a completion handler to
Superwall.configure(...)that lets you know when Superwall has finished configuring. You can also listen to the publishedisConfiguredvariable. - If you let Superwall handle your subscription-related logic, we now assume that a non-consumable product on your paywall is a lifetime subscription. If not, you'll need to return a
SubscriptionControllerfrom the delegate. handleDeepLink(_:)now returns a discardableBoolindicating whether the deep link was handled. If you're usingapplication(_:open:options:)you can return its value there.- Adds
togglePaywallSpinner(isHidden:)to arbitrarily toggle the loading spinner on and off. This is particularly useful when you're doing async work when performing a custom action inhandleCustomPaywallAction(withName:). - Adds a new event
SubscriptionStatusDidChangewhich is logged on the dashboard whenever the user's subscription status changes. - You can now target
device.isSandboxin rules. - Tweaks the loading indicator UI.
- Prevents the registering of events that have the same name as internally tracked
SuperwallEventslikepaywall_open. - Adds a drawer display option which displays the paywall at 70% screen height on iOS 16 iPhones.
- Adds
$is_feature_gatablestandard property to register calls. - Cleans up and reformats SDK logs.
- If you're using SwiftUI, you can now call
Superwall.configurein theinit()of yourAppfile. This means you don't need to have aUIApplicationDelegate. - You can access
device.subscriptionStatusin a rule, which is a string that's eitherACTIVE,INACTIVE, orUNKNOWN. - You no longer need to have swiftlint installed to run our example apps.
- Adds static variable
Superwall.isInitializedwhich istruewhen initialization is complete andSuperwall.sharedcan be accessed. - Adds
transaction_abandon,transaction_failandpaywall_declineas potential triggers. This comes with a newPaywallInfoproperty calledcloseReason, which can either benone,.systemLogic, or.forNextPaywall. - Changes default logging level to
INFO. - Adds new automatically tracked event
presentation_requestthat gets sent with properties explaining why a paywall was or was not shown. - Adds a
device.isFirstAppOpenproperty that you can use in paywall rules. This istruefor the very first time a user opens the app. When the user closes and reopens the app, this will befalse. - Adds
isInspectableto the paywall web view if running on iOS 16.4+. - Adds
rawTrialPeriodPrice,trialPeriodPrice,trialPeriodDailyPrice,trialPeriodWeeklyPrice,trialPeriodMonthlyPrice,trialPeriodYearlyPriceto product variables. - Fully handles what happens when there are network failures.
Fixes
- Fixes race condition issue where the free trial paywall information would still be shown even if you had previously used a free trial on an expired product.
- Fixes a caching issue where the paywall was still showing in free trial mode when it shouldn't have. This was happening if you had purchased a free trial, let it expire, then reopened the paywall. Note that in Sandbox environments this issue may still occur due to introductory offers not being added to a receipt until after a purchase.
- The API uses background threads wherever possible, dispatching to the main thread only when necessary and when calling completion blocks.
- The API is now fully compatible with Objective-C.
- Setting the
PaywallOptionautomaticallyDismisstofalsenow keeps the loading indicator visible after restoring and successfully purchasing until you manually dismiss the paywall. - Improves the speed of requests by changing the cache policy of requests to our servers.
- Fixes
session_start,app_launchandfirst_seennot being tracked if the SDK was initialised a few seconds after app launch. - Stops the unnecessary retemplating of paywall variables when coming back to the paywall after visiting a link via the in-app browser.
- Removes the transaction timeout popup. This was causing a raft of issues so we now rely on overlayTimeout to cancel the transaction flow.
- Fixes bug in
<iOS 14where the spinner wasn't appearing when transacting. - Fixes an rare crash associated with the loading and saving of Core Data.
- Makes
NetworkEnvironmentObjective-C compatible. - Fixes race condition when calling identify and registering an event.
- Fixes a long term bug where registering an event to show a paywall and registering an event that results in noRuleMatch would interfere with each other and cause the trigger session to be set to
nil. This resulted in some paywall data being incorrect on the dashboard. - Fixes issue where an invalid URL provided for an "Open URL" click behavior would result in a crash.
- Fixes various memory related crashes.
- Fixes a crash when calling
reset()when a paywall is displayed. - Fixes issue where a crash would occur if storage was full and a persistent container couldn't be created.
- If the internet is offline when trying to present a paywall, the paywall configuration hasn't been retrieved, and the user is not subscribed, it now throws a presentationError. If the internet reconnects future paywalls will show.
- Fixes retry logic for requests.
- Fixes crash when handling a deep link.
3.0.0-rc.7
Breaking Changes
- Exposes the
transactionBackgroundViewPaywallOptionto Objective-C by making it non-optional and adding anonecase in place of setting it tonil. - Renames
getPaywallViewControllertogetPaywall. - Renames
paywallStatePublisherproperty onPaywallViewControllertostatePublisher. - Changes the presentation error domain code from
SWPresentationErrortoSWKPresentationError.
Enhancements
- Adds paywall caching. This is disabled by default but we'll roll this out to users accounts remotely. With this enhancement, your paywalls will load lightning fast and will reduce network load of your app.
- Exposes
LoggingSuperwallOptionto Objective C. - Exposes
infoon thePaywallViewController. - Adds
rawTrialPeriodPrice,trialPeriodPrice,trialPeriodDailyPrice,trialPeriodWeeklyPrice,trialPeriodMonthlyPrice,trialPeriodYearlyPrice.
Fixes
- Fixes issue where a crash would occur if storage was full and a persistent container couldn't be created.
- Fixes thread safety issue when using a lazy variable to retrieve products.
- If the internet is offline when trying to present a paywall, the paywall configuration hasn't been retrieved, and the user is not subscribed, it now throws a presentationError. If the internet reconnects future paywalls will show.
- Fixes retry logic for requests.
- Fixes crash when handling a deep link.
- Creates a strong reference to the purchase controller as it was getting deallocated if you didn't keep a hold on it.
3.0.0-rc.6
Breaking Changes
- Adds a
PaywallViewControllerDelegateto thegetPaywallViewControllerfunctions. This is mandatory and is how you control what happens after a paywall is dismissed. - The completion block of
getPaywallViewController(forEvent:params:paywallOverrides:delegate:completion:)now accepts an optionalPaywallViewController, an optionalPaywallSkippedReasonand an optionalError. This makes it easier to understand when the paywall was skipped vs when a real error occurred. - Renamed the
PaywallResultcaseclosedtodeclined.
Enhancements
- Exposes
PaywallOverridesandPaywallViewControllerto Objective-C. - Adds Objective-C convenience methods to
PaywallOverrides. - Adds a
device.isFirstAppOpenproperty that you can use in paywall rules. This istruefor the very first time a user opens the app. When the user closes and reopens the app, this will befalse. - Removes the need to tell us when you're going to present/have presented a
PaywallViewControllerthat has been retrieved usinggetPaywallViewController(...). - Adds
isInspectableto the paywall web view if running on iOS 16.4+. - Exposes
PaywallViewControllerDelegateto be used withgetPaywallViewController(...)
Fixes
- Fixes various memory related crashes.
- Fixes a crash when calling
reset()when a paywall is displayed.
3.0.0-rc.5
Fixes
- Fixes bug where
Superwall.shared.register's feature handler would not be called if the user is subscribed.
3.0.0-rc.4
Breaking Changes
- Changes
DismissStatetoPaywallResult. - Removes the
closedForNextPaywallcase fromPaywallResultin favor of a newPaywallInfoproperty calledcloseReason, which can either benil,.systemLogic, or.forNextPaywall. - Changes the
PaywallPresentationHandlervariables to functions. - Removes
Superwall.shared.track. We're going all in onSuperwall.shared.registerbaby! - Removes .error(Error) from
PaywallSkippedReasonin favor of a newPaywallStatecase.presentationError(Error). - Removes
PaywallPresentationHandlercompletion block variables removed in favor of function calls with the same names. - Changes
.onErrorofPaywallPresentationHandlerto no longer be called when a paywall is intentionally not shown (i.e. user is subscribed, user is in holdout, no rule match, event not configured) - Adds
.onSkip(reason:)toPaywallPresentationHandlerto handle cases where paywall isn't shown because user is subscribed, user is in holdout, no rules match, event not configured
Enhancements
- Adds
getPaywallViewController! You can no request an actual view controller to present however you like. Check function documentation in Xcode for instructions – follow directions closely. - Changes default logging level to
INFO. - Adds new automatically tracked
paywall_declineevent that can be used to present a new paywall when a user dismisses a paywall. - Allows
transaction_abandonto trigger new paywalls when added to a campaign – called when a user abandons checkout (did you know 75% of the time, users abandon checkout when Apple's payment sheet comes up?!). - Adds
.onSkiptoPaywallPresentationHandlerwhich is passed aPaywallSkippedReasonwhen a paywall is not supposed to show. - Adds logging at
INFOlevel, mansplaining exactly why a paywall is not shown when callingregisterorgetPaywallViewController. - Adds new automatically tracked event
presentation_requestthat gets sent with properties explaining why a paywall was or was not shown.
Fixes
- Paywalls will now show even if you are missing products.
3.0.0-rc.3
Breaking Changes
- Changes the
logLevelto be non-optional and introduces anonecase to turn off logging. - Removes all guides from the SDK documentation. From now on, our online docs provide guides and the SDK documentation is only there as a technical reference.
- Changes
TrackResultObjctoPresentationResultObjc - Removes convenience methods for creating PaywallPresentationHandlers because they were a bit confusing
- Changes the return type of
PurchaseController.restorePurchases()frombooltoRestorationResult
Enhancements
- If you're using SwiftUI, you can now call
Superwall.configurein theinit()of yourAppfile. This means you don't need to have aUIApplicationDelegate. - Prevents validation of restorations and purchases if you're using a
PurchaseController- it's now all on you! - Updates Objective-C sample app to use
Superwall.registerand removes legacy StoreKit code. - Simplifies SwiftUI and RevenueCat example app.
- You can now access
device.subscriptionStatusin a rule, which is a string that's eitherACTIVE,INACTIVE, orUNKNOWN. - You no longer need to have swiftlint installed to run our example apps.
- If you're not using a
PurchaseControllerand a user comes across the "You're already subscribed to this product" popup, we will now correctly identify this as a restoration and not a purchase. This can happen when testing in sandbox if you purchase a product -> delete and reinstall the app -> open a paywall and purchase. - Adds static variable
Superwall.isInitializedwhich istruewhen initialization is complete andSuperwall.sharedcan be accessed. - Adds
transaction_abandonandtransaction_failas potential triggers. This comes with a newDismissStatecaseclosedForNextPaywall, which is returned when dismissing one paywall for another.
Fixes
- Fixes issue where an invalid URL provided for an "Open URL" click behavior would result in a crash.
- Exposes
PaywallPresentationHandlerasSWKPaywallPresentationHandlerfor Objective-C.
3.0.0-rc.2
Enhancements
- Simplifies Superwall-UIKit-Swift example project.
Fixes
- Fixes bug where calling Superwall.shared prior to Superwall.configure would result in a recursive loop.
3.0.0-rc.1
Breaking Changes
- Adds
PaywallInfotoSuperwallDelegatemethodspaywallWillPresent(withInfo:),paywallDidPresent(withInfo:),paywallWillDismiss(withInfo:)andpaywallDidDismiss(withInfo:). - Renames
SuperwallDelegatemethoddidTrackSuperwallEventInfo(_:SuperwallEventInfo)tohandleSuperwallEvent(withInfo eventInfo: SuperwallEventInfo)for clarity - Renames
SuperwallDelegatemethodswillOpenURL(url:)andwillOpenDeepLink(url:)topaywallWillOpenURL(url:)andpaywallWillOpenDeepLink(url:)respectively - Decouples associated value of
.dismissedinSuperwall.shared.track()closure toPaywallInfoandDismissState. - Changes
subscription_status_did_changetosubscriptionStatus_didChange. - Renames
TrackResulttoPresentationResult
Enhancements
- Introducing
Superwall.shared.register(event:params:handler:feature), Superwall's most powerful feature yet. Wrap your features with this method to conditionally show paywalls, lock features and more. - Adds a drawer display option which displays the paywall at 70% screen height on iOS 16 iPhones.
- Adds warning if setting subscription status without passing through a PurchaseController during config.
- Adds
$is_feature_gatablestandard property to register and track calls - Cleans up and reformats SDK logs
Fixes
- Fixes a long term bug where tracking an event to show a paywall and tracking an event that results in noRuleMatch would interfere with each other and cause the trigger session to be set to
nil. This resulted in some paywall data being incorrect on the dashboard.
3.0.0-beta.8
Enhancements
- Prevents the tracking of events that have the same name as internally tracked
SuperwallEventslikepaywall_open.
Fixes
- Fixes an issue with reporting in the dashboard due to a mismatch of keys between client and server.
3.0.0-beta.7
Breaking Changes
- Changes Objective-C method
getTrackInfotogetTrackResultto be in line with the Swift API. - Removes the error case from the
TrackResultand adds inuserIsSubscribedandpaywallNotAvailablecases. - Moves main actor conformance to functions of PurchaseController protocol rather than the whole protocol.
- Changes Objective-C method
setUserAttributesDictionary(_:)tosetUserAttributes(_:).
Fixes
- Makes
NetworkEnvironmentObjective-C compatible. - Fixes an issue where a manually dismissed modally presented paywall wouldn't properly dismiss.
- Fixes race condition when calling identify and tracking a paywall.
3.0.0-beta.6
Breaking Changes
identify(userId:)is not longer a throwing async function. Any error that occurs is logged.resetis no longer an async function.presentedViewControllerandlatestPaywallInfono longer restricted to the main actor.- Removes
localizationOverride(localeIdentifier:)and replaces it with theSuperwallOptionlocaleIdentifier. You set this on configure. - Removes delegate from
configure. You now set the delegate viaSuperwall.shared.delegate. - Removes
presenterintroduced in beta 5. - Removes ASN1Swift as a package dependency.
- Changes free trial logic. Previously we'd look at just the primary product. However, we determing free trial eligibility based on the first product in the paywall that has a free trial available.
Enhancements
- You can now target
device.isSandboxin rules.
Fixes
- Fixes bug where calling identify and immediately tracking a paywall would result in an error if it happened before configure returned.
- Fixes compiler bug when calling track.
- Tweaks the loading indicator.
- Fixes removing an attribute using Objective-C.
- Fixes issues where some functions tagged for the main actor weren't actually running on the main actor.
- Fixes issues with paywall product overrides.
3.0.0-beta.5
Breaking Changes
- Changes
SubscriptionControllertoPurchaseController. You now set this inSuperwall.shared.configure, rather than via the delegate. - Removes
isUserSubscribed()from theSuperwallDelegateand replaces this with a published instance variablesubscriptionStatus. This is enum that defaults to.unknownon first install and the cached value on subsequent app opens. If you're using aSubscriptionControllerto handle subscription-related logic, you must setsubscriptionStatusevery time the user's subscription status changes. If you're letting Superwall handle subscription-related logic, this value will be updated with the device receipt. hasActiveSubscriptionDidChange(to:)is replaced in favour ofsubscriptionStatusDidChange(to:).- Makes
Superwall.shared.optionsinternal so that options must be set inconfigure.
Enhancements
- Adds a new event
SubscriptionStatusDidChangewhich is logged on the dashboard. - Adds an optional
presenterparameter totrack. In v2 this was known ason. This takes aUIViewControllerwhich is used to present the paywall.
3.0.0-beta.4
Breaking Changes
- Moves back to using
Superwall.shared.identify(userId: userId)andreset()instead of logIn/createAccount/logout/reset. This is so that it's easier for integration. However, you can now pass anIdentityOptionsobject toidentify(userId:options). This should only be used in advanced use cases. By setting therestorePaywallAssignmentsproperty ofIdentityOptionstotrue, it prevents paywalls from showing until after paywall assignments have been restored. If you expect users of your app to switch accounts or delete/reinstall a lot, you'd set this when identifying an existing account.
Enhancements
- Adds
hasActiveSubscriptionDidChange(to:)delegate function. If you're letting Superwall handle subscription logic you can use this to receive a callback whenever the user's internal subscription status changes. You can also listen to the publishedhasActiveSubscriptionvariable. - Adds a completion handler to
Superwall.configure(...)that lets you know when Superwall has finished configuring. You can also listen to the publishedisConfiguredvariable. - If you let Superwall handle your subscription-related logic, we now assume that a non-consumable product on your paywall is a lifetime subscription. If not, you'll need to return a
SubscriptionControllerfrom the delegate. handleDeepLink(_:)now returns a discardableBoolindicating whether the deep link was handled. If you're usingapplication(_:open:options:)you can return its value there.- Adds
togglePaywallSpinner(isHidden:)to arbitrarily toggle the loading spinner on and off. This is particularly useful when you're doing async work when performing a custom action inhandleCustomPaywallAction(withName:).
Fixes
- Fixes occasional thread safety related crash when loading products.
- Reverts a issue from the last beta where the paywall spinner would move up before the payment sheet appeared.
3.0.0-beta.3
Fixes
- Fixes potential crash due to a using a lazy variable.
3.0.0-beta.2
Breaking Changes
- Moves all functions and variables to the
sharedinstance for consistency, e.g. it's nowSuperwall.shared.track()instead ofSuperwall.track().
Enhancements
- Readds
Superwall.shared.logLevelas a top level static convenience variable so you can easily change the log level. - Adds
isLoggedInto user properties, which means you can create a rule based on whether the user is logged in vs. whether they're anonymous.
Fixes
- Fixes bug in
<iOS 14where the spinner wasn't appearing when transacting. - Fixes bug where PaywallOverrides weren't being passed in to the paywall.
- Fixes bug where purchasing, deleting then reinstalling your app, and tapping a purchase button would throw an error.
- Fixes an rare crash associated with the loading and saving of Core Data.
3.0.0-beta.1
Welcome to SuperwallKit v3.0, the framework formally known as Paywall!
This update is a major release, containing lots of breaking changes, enhancements and some bug fixes. We're excited for you to use it!
We understand that transitions between major SDK releases can become frustrating, so we've made a migration guide to make your life easier. We've also updated out sample apps to v3, including RevenueCat+SuperwallKit and Objective-C apps. For new users, we've created a Quick Start Guide to get up and running in no time. Finally, we recommend you check out our updated docs.
Breaking Changes
- Renames the package from
PaywalltoSuperwallKit. - Renames the primary static class for integrating Superwall from
PaywalltoSuperwall. - Sets the minimum iOS version to iOS 13.
- Renames
preloadPaywalls(forTriggers:)topreloadPaywalls(forEvents:) - Renames
configure(apiKey:userId:delegate:options:)toconfigure(apiKey:delegate:options:). This means you no longer provide auserIdwith configure. Instead you must use the new identity API detailed below. - Changes
PaywallOptionstoSuperwallOptions. This now clearly defines which of the options are explicit to paywalls vs other configuration options within the SDK. - Renames
Superwall.trigger(event:)toSuperwall.track(event:). We found that having separate implicit (Superwall.track(event:)) and explicit (Superwall.trigger(event:)) trigger functions caused confusion. So from now on, you'll just useSuperwall.track(event:)for all events within your app. - Renames
Paywall.EventNametoSuperwallEventand removes.manualPresentas aSuperwallEvent. - Renames
PaywallDelegatetoSuperwallDelegate. - Superwall automatically handles all subscription-related logic, meaning that it's no longer a requirement to implement any of the delegate methods. Note that if you're using RevenueCat, you will still need to use the delegate methods. This is because the Superwall-handled subscription status is App Store account-specific, whereas RevenueCat is logged in user-specific. If this isn't a problem, you can just set RevenueCat in observer mode and we'll take care of the rest :)
- Moves purchasing logic from the delegate into a protocol called
SubscriptionController. You return yourSubscriptionControllerfrom the delegate methodsubscriptionController(). - For Swift users, this changes the
SubscriptionControllermethodpurchase(product:)to an async function that returns aPurchaseResult. Here, you need to return the result of the user attempting to purchase a product, making sure you handle all cases ofPurchaseResult:.purchased,.cancelled,.pending,failed(Error). - For Objective-C users, this changes the delegate method
purchase(product:)topurchase(product:completion:). You call the completion block with the result of the user attempting to purchase a product, making sure you handle all cases ofPurchaseResultObjc:.purchased,.cancelled,.pending,failed. When you have a purchasing error, you need to call the completion block with the.failedcase along with the error. - Changes
restorePurchases()to an async function that returns a boolean instead of having a completion block. - Removes
identify(userId:)in favor of the new Identity API detailed below. - Removes
Paywall.load(identifier:). This was being used to preload a paywall by identifier. - Removes
.triggerPaywall()for SwiftUI apps. Instead, SwiftUI users should now use the UIKit functionSuperwall.track(). Take a look at our SwiftUI example app to see how that works. - Changes the
periodandperiodlyattributes for 2, 3 and 6 month products. Previously, theperiodwould be "month", and theperiodlywould be "monthly" for all three. Now theperiodreturns "2 months", "quarter", "6 months" and theperiodlyreturns "every 2 months", "quarterly", and "every 6 months".
Enhancements
- New identity API:
logIn(userId:): Logs in a user with theiruserIdto retrieve paywalls that they've been assigned to.createAccount(userId:): Creates an account with Superwall. This links auserIdto Superwall's automatically generated alias.logOut(userId:): Logs out the user, which resets on-device paywall assignments and theuserIdstored by Superwall.reset(): Resets theuserId, on-device paywall assignments, and data stored by Superwall. This can be called even if the user isn't logged in.
- The identity API can be accessed using async/await or completion handlers.
- New function
Superwall.publisher(forEvent:params:overrides)which returns aPaywallStatePublisher(AnyPublisher<PaywallState, Never>) for those Combine lovers. By subscribing to this publisher, you can receive state updates of your paywall. We've updated our sample apps to show you how to use that. - Adds
Superwall.isLoggedInto check whether the user is logged in to the SDK or not. This will be true if you've previously calledlogIn(userId:)orcreateAccount(userId:). - Adds a new example app, UIKit+RevenueCat, which shows you how to use Superwall with RevenueCat.
- Adds a new Objective-C example app UIKit-Objc.
- Adds an Objective-C-only function
removeUserAttributes(_:)to remove user attributes. In Swift, to remove attributes you can pass innilfor a specific attribute insetUserAttributes(_:). - Adds
getTrackResult(forEvent:params:). This returns aTrackResultwhich tells you the result of tracking an event, without actually tracking it. This is useful if you want to figure out whether a paywall will show in the future. - Logs when products fail to load with a link to help diagnose the cause.
- Adds a published property
hasActiveSubscription, which you can check to determine whether Superwall detects an active subscription. Its value is stored on disk and synced with the active purchases on device. If you're using Combine or SwiftUI, you can subscribe or bind to this to get notified whenever the user's subscription status changes. If you're implementing your ownSubscriptionController, you should rely on your own logic to determine subscription status. - Adds a published property
isConfigured. This is a boolean which you can use to check whether Superwall is configured and ready to present paywalls. - Adds
isFreeTrialAvailabletoPaywallInfo. - Tracks whenever the paywall isn't presented for easier debugging.
Fixes
- Fixes a caching issue where the paywall was still showing in free trial mode when it shouldn't have. This was happening if you had purchased a free trial, let it expire, then reopened the paywall. Note that in Sandbox environments this issue may still occur due to introductory offers not being added to a receipt until after a purchase.
- The API uses background threads wherever possible, dispatching to the main thread only when necessary and when returning from completion blocks.
- The API is now fully compatible with Objective-C.
- Setting the
PaywallOptionautomaticallyDismisstofalsenow keeps the loading indicator visible after restoring and successfully purchasing until you manually dismiss the paywall. - Improves the speed of requests by changing the cache policy of requests to our servers.
- Fixes
session_start,app_launchandfirst_seennot being tracked if the SDK was initialised a few seconds after app launch. - Stops the unnecessary retemplating of paywall variables when coming back to the paywall after visiting a link via the in-app browser.
- Removes the transaction timeout popup. This was causing a raft of issues so we now rely on overlayTimeout to cancel the transaction flow.
2.5.8
Enhancements
- Adds
isExternalDataCollectionEnableddata privacyPaywallOption. Whenfalse, prevents non-Superwall events and properties from being sent back to the superwall servers. - Adds an
X-Is-Sandboxheader to all requests such that sandbox data doesn't affect your production analytics on superwall.com.
Fixes
- Fixes a bug that prevented the correct calculation of a new app session.
- Fixes missing loading times of the webview and products.
2.5.6
Fixes
- Fixes a bug found in the previous version. Disabling the preloading of paywalls for specific triggers via remote config now works correctly.
2.5.5
Fixes
- Fixes a crash when all variants of a campaign rule are set to 0%.
Enhancements
- Adds ablity to disable the preloading of paywalls from specific triggers via config.
2.5.4
Fixes
- Fixes a crash issue where the completion blocks for triggering a paywall were being called on a background thread in a specific scenario.
- Fixes an issue where lazy properties were causing an occasional crash due to the use of multithreading.
2.5.3
Fixes
- Fixes a bug where
Paywall.reset()couldn't be called on a background thread.
2.5.2
Fixes
- Fixed memory and time issues associated with the shimmer view when loading a paywall. Special thanks to Martin from Planta for spotting that one. We've rebuilt the shimmer view and only add it when the paywall is visible and loading. This means it doesn't get added to paywalls preloading in the background. After loading, we remove the shimmer view from memory.
- Moves internal operations for templating paywall variables from the main thread to a background thread. This prevents hangs on the main thread.
- Stops UIAlertViewControllers being unnecessarily created when loading a paywall.
- Removes the dependency on
TPInAppReceiptfrom our podspec and replaces it with aASN1Swiftdependency to keep it in line with our Swift Package file.
2.5.0
Enhancements
- Assigments of paywall variants are now performed on device, meaning reduced network calls and faster setup time for the SDK.
- Adds
Paywall.latestPaywallInfo. You can read this to access thePaywallInfoobject of the most recently presented view controller. - Adds feature flags under the hood so new features can be turned on for specific organizations and apps.
- Adds the ability to specify
SKProductswith triggers. These override products defined in the dashboard. You do this by creating aPaywallProductsobject and callingPaywall.trigger(event: "event", products: products). - Updates sample projects to iOS 16.
Fixes
- Shimmer view is no longer visible beneath a paywall's
WKWebViewwhen there is nobodyorhtmlbackground color set - Previously calls to
Paywall.preloadPaywalls(forTriggers:)beforePaywall.config()finished were ignored. This has been fixed. - If a user had already bought a product within a subscription group, they were still being offered a free trial on other products within that group. This is incorrect logic and this update fixes that.
-
Fixed a bug where
Paywall.reset()couldn't be called on a background thread. - Previously, calling
Paywall.preloadPaywalls(forTriggers:)beforePaywall.config()finished would not work. This has been fixed. - Previously, if a user purchases a product within a subscription group, they would still be offered a free trial on other products within that group. This has been fixed.
- Fixes a bug where
Paywall.reset()couldn't be called on a background thread.
2.4.1
Enhancements
- Adds
Paywall.preloadAllPaywalls()andPaywall.preloadPaywalls(forTriggers:). Use this withSuperwall.options.shouldPreloadPaywall = falseto have more control over when/what paywalls are preloaded.
Fixes
- Paywall options specified prior to config are now respected, regardless of whether you pass an options object through to config or not.
- Ensures /config's request and response is always handled on the main thread
2.4.0
Enhancements
- New push presentation style. By selecting Push on the superwall dashboard, your paywall will push and pop in as if it's being pushed/popped from a navigation controller. If you are using UIKit, you can provide a view controller to
Paywall.triggerlike this:Paywall.trigger(event: "MyEvent", on: self). This will make the push transition more realistic, by moving its view in the transition. Note: This is not backwards compatible with previous versions of the SDK. - New no animation presentation style. By selecting No Animation in the superwall dashboard, you can disable presentation/dismissal animation. This release deprecates
Paywall.shouldAnimatePaywallDismissalandPaywall.shouldAnimatePaywallPresentation. - A new
PaywallOptionsobject that you configure and pass to `Paywall.configure(apiKey:userId:delegate) to override the default appearance and presentation of the paywall. This deprecates a lot of static variables for better organisation. - New
shouldPreloadPaywallsoption. Set this tofalseto make paywalls load and cache in a just-in-time fashion. This replaces the oldPaywall.shouldPreloadTriggersflag. - New dedicated function for handling deeplinks:
Paywall.handleDeepLink(url). - Deprecates old
trackfunctions. The only one you should use isSuperwall.track(_:_:), to which you pass an event name and a dictionary of parameters. Note: This is not backwards compatible with previous versions of the SDK. - Adds a new way of internally tracking analytics associated with a paywall and the app session. This will greatly improve the Superwall dashboard analytics.
- Adds support for javascript expressions defined in rules on the Superwall dashboard.
- Updates the SDK documentation.
- Adds
trialPeriodEndDateas a product variable. This means you can tell your users when their trial period will end, e.g.Start your trial today — you won't be billed until {{primary.trialPeriodEndDate}}will print outStart your trial today — you won't be billed until June 21, 2023. - Adds support for having more than 3 products on your paywall.
- Exposes
Paywall.presentedViewController. This gives you access to theUIViewControllerof the paywall incase you need to present a view controller on top of it. - Adds
today,daysSinceInstall,minutesSinceInstall,daysSinceLastPaywallView,minutesSinceLastPaywallViewandtotalPaywallViewsasdeviceparameters. These can be references in your rules and paywalls with{{ device.paramName }}. - Paywalls can now be configured via the dashboard to always present, regardless of the subscription status of the user.
- Adds a
presentationStyleOverrideparameter toPaywall.trigger()andPaywall.present(). By setting this, you can override the configured presentation style on case by case basis. - Rules can now be limited by occurrence and date. For example, you could set a rule to only match 10 times within the last 5 hours.
- Adds
Paywall.userIdto grab the id of the current user. - Adds
$url,$path,$pathExtension,$lastPathComponent,$host,$query,$fragmentas standard parameters to thedeepLink_openevent trigger (automatically tracked). - Parses URL parameters and adds them as trigger parameters to the
deepLink_openevent trigger (automatically tracked). - Fixes window logic for opening the debugger and launching paywalls on
deepLink_open. - Launching a paywall using the
deepLink_openTrigger now dismisses a currently presenting paywall before presenting the new one.
Fixes
- Adds the missing Superwall events
app_install,paywallWebviewLoad_fail,paywallWebviewLoad_timeoutandnonRecurringProduct_purchase. - Adds
trigger_nameto atriggerFireSuperwall event, which can be accessed in the parameters sent back to thetrackAnalyticsEvent(name:params:)delegate function. - Product prices were being sent back to the dashboard with weird values like 89.999998. We fixed that.
- Modal presentation now uses
.pageSheetinstead of.formSheet. This results in a less compact paywall popover on iPad. Thanks to Daniel Yoo from the Daily Bible Inspirations app for spotting that! - For SwiftUI users, we've fixed an issue where the explicitly triggered paywalls and presented paywalls would sometimes randomly dismiss. We found that state changes within the presenting view caused a rerendering of the view which temporarily reset the state of the binding that controlled the presentation of the paywall. This was causing the Paywall to dismiss.
- Fixes an issue where the wrong paywall was shown if a trigger was fired before the config was fetched from the server. Thanks to Zac from Blue Candy for help with finding that :)
- Future proofs enums internally to increase backwards compatibility.
- Fixes a bug where long term data was being stored in the cache directory. This update migrates that to the document directory. This means the data stays around until we tell it to delete, rather than the system deleting it at random.
- Prevents Paywall.configure from being called twice and logs a warning if this occurs.
- Prevents Paywall.configure from being called in the background.
- Fixes an issue where the keyboard couldn't be dismissed in the UIKit sample app.
- Mentions SwiftLint as a requirement to run the sample apps.
- Deprecates
Paywall.debugMode. All logs are now controlled by setting the paywall option.logLevel. The defaultlogLevelis now.warn. - Fixes broken webview based deeplinks and closes the paywall view before calling the delegate handler.
- Deprecates
Paywall.presentforPaywall.trigger. - Fixes issue where preloaded paywalls would be cleared upon calling
Paywall.identify()if config was called without auserId. - Fixes logic for grabbing the active view controller.
2.3.0
Enhancements
- New UIKit Example App.
- Better SDK documentation. This is built from the ground up using DocC which means you view it directly in Xcode by selecting Product ▸ Build Documentation.
- New Pull Request and Bug Report templates for the repo.
- Added a setup file that installs GitHooks as well as SwiftLint if you don't already have it. This is located at
scripts/setup.shand can be run from anywhere. - Added a CONTIBUTING.md file for detailed instructions on how to get set up and contribute to the codebase.
- Added a Code of Conduct file to the repo.
- Added a CHANGELOG.md file.
- Removed the
TPInnAppReceiptdependency for the SDK.
Fixes
- All readme links for the UIKit example app now work.
- Adds an
experimentparameter toPaywallInfo. This will be useful in the next version of Triggers, where you can see details about the experiment that triggered the presentation of the paywall. - When triggering or presenting a paywall, if the default value for
isPresentedwastrue, the paywall would not present/trigger. It now works as expected.
How is this guide?
Edit on GitHub