Fetch paywalls and products for remote config paywalls in iOS SDK
Before showcasing remote config and custom paywalls, you need to fetch the information about them. Please be aware that this topic refers to remote config and custom paywalls. For guidance on fetching paywalls for Paywall Builder-customized paywalls, please consult the guides on how to fetch Paywall Builder paywalls in your app .
Want to see a real-world example of how Adapty SDK is integrated into a mobile app? Check out our sample apps, which demonstrate the full setup, including displaying paywalls, making purchases, and other basic functionality.
Before you start fetching paywalls and products in your mobile app (click to expand)
-
Create your products in the Adapty Dashboard.
-
Create a paywall and incorporate the products into your paywall in the Adapty Dashboard.
-
Create placements and incorporate your paywall into the placement in the Adapty Dashboard.
-
Install Adapty SDK in your mobile app.
Fetch paywall information
In Adapty, a product serves as a combination of products from both the App Store and Google Play. These cross-platform products are integrated into paywalls, enabling you to showcase them within specific mobile app placements.
To display the products, you need to obtain a Paywall from one of your placements with getPaywall
method.
- Swift
- Swift-Callback
do {
let paywall = try await Adapty.getPaywall(placementId: "YOUR_PLACEMENT_ID")
// the requested paywall
} catch {
// handle the error
}
Adapty.getPaywall(placementId: "YOUR_PLACEMENT_ID", locale: "en") { result in
switch result {
case let .success(paywall):
// the requested paywall
case let .failure(error):
// handle the error
}
}
Parameter | Presence | Description |
---|---|---|
placementId | required | The identifier of the Placement. This is the value you specified when creating a placement in your Adapty Dashboard. |
locale | optional default: | The identifier of the paywall localization. This parameter is expected to be a language code composed of one or more subtags separated by the minus (-) character. The first subtag is for the language, the second one is for the region. Example: See Localizations and locale codes for more information on locale codes and how we recommend using them. |
fetchPolicy | default: .reloadRevalidatingCacheData | By default, SDK will try to load data from the server and will return cached data in case of failure. We recommend this variant because it ensures your users always get the most up-to-date data. However, if you believe your users deal with unstable internet, consider using Note that the cache remains intact upon restarting the app and is only cleared when the app is reinstalled or through manual cleanup. Adapty SDK stores paywalls in two layers: regularly updated cache described above and fallback paywalls . We also use CDN to fetch paywalls faster and a stand-alone fallback server in case the CDN is unreachable. This system is designed to make sure you always get the latest version of your paywalls while ensuring reliability even in cases where internet connection is scarce. |
loadTimeout | default: 5 sec | This value limits the timeout for this method. If the timeout is reached, cached data or local fallback will be returned. Note that in rare cases this method can timeout slightly later than specified in |
Don't hardcode product IDs! Since paywalls are configured remotely, the available products, the number of products, and special offers (such as free trials) can change over time. Make sure your code handles these scenarios.
For example, if you initially retrieve 2 products, your app should display those 2 products. However, if you later retrieve 3 products, your app should display all 3 without requiring any code changes. The only thing you have to hardcode is placement ID.
Response parameters:
Parameter | Description |
---|---|
Paywall | An AdaptyPaywall object with: a list of product IDs, the paywall identifier, remote config, and several other properties. |
Fetch products
Once you have the paywall, you can query the product array that corresponds to it:
- Swift
- Swift-Callback
do {
let products = try await Adapty.getPaywallProducts(paywall: paywall)
// the requested products array
} catch {
// handle the error
}
Adapty.getPaywallProducts(paywall: paywall) { result in
switch result {
case let .success(products):
// the requested products array
case let .failure(error):
// handle the error
}
}
Response parameters:
Parameter | Description |
---|---|
Products | List of AdaptyPaywallProduct objects with: product identifier, product name, price, currency, subscription length, and several other properties. |
When implementing your own paywall design, you will likely need access to these properties from the AdaptyPaywallProduct
object. Illustrated below are the most commonly used properties, but refer to the linked document for full details on all available properties.
Property | Description |
---|---|
Title | To display the title of the product, use product.localizedTitle . Note that the localization is based on the users' selected store country rather than the locale of the device itself. |
Price | To display a localized version of the price, use product.localizedPrice . This localization is based on the locale info of the device. You can also access the price as a number using product.price . The value will be provided in the local currency. To get the associated currency symbol, use product.currencySymbol . |
Subscription Period | To display the period (e.g. week, month, year, etc.), use product.localizedSubscriptionPeriod . This localization is based on the locale of the device. To fetch the subscription period programmatically, use product.subscriptionPeriod . From there you can access the unit enum to get the length (i.e. day, week, month, year, or unknown). The numberOfUnits value will get you the number of period units. For example, for a quarterly subscription, you'd see .month in the unit property, and 3 in the numberOfUnits property. |
Introductory Offer | To display a badge or other indicator that a subscription contains an introductory offer, check out the product.subscriptionOffer property. Within this object are the following helpful properties:• offerType : an enum with values introductory , promotional , and winBack . Free trials and initial discounted subscriptions will be the introductory type.• price : The discounted price as a number. For free trials, look for 0 here.• localizedPrice : A formatted price of the discount for the user's locale.• localizedNumberOfPeriods : a string localized using the device's locale describing the length of the offer. For example, a three day trial offer shows 3 days in this field.• subscriptionPeriod : Alternatively, you can get the individual details of the offer period with this property. It works in the same manner for offers as the previous section describes.• localizedSubscriptionPeriod : A formatted subscription period of the discount for the user's locale. |
Check intro offer eligibility on iOS
By default, the getPaywallProducts
method checks eligibility for introductory, promotional, and win-back offers. If you need to display products before the SDK determines offer eligibility, use the getPaywallProductsWithoutDeterminingOffer
method instead.
After showing the initial products, be sure to call the regular getPaywallProducts
method to update the products with accurate offer eligibility information.
- Swift
- Swift-Callback
do {
let products = try await Adapty.getPaywallProductsWithoutDeterminingOffer(paywall: paywall)
// the requested products array without subscriptionOffer
} catch {
// handle the error
}
Adapty.getPaywallProductsWithoutDeterminingOffer(paywall: paywall) { result in
switch result {
case let .success(products):
// the requested products array without subscriptionOffer
case let .failure(error):
// handle the error
}
}
Speed up paywall fetching with default audience paywall
Typically, paywalls are fetched almost instantly, so you don’t need to worry about speeding up this process. However, in cases where you have numerous audiences and paywalls, and your users have a weak internet connection, fetching a paywall may take longer than you'd like. In such situations, you might want to display a default paywall to ensure a smooth user experience rather than showing no paywall at all.
To address this, you can use the getPaywallForDefaultAudience
method, which fetches the paywall of the specified placement for the All Users audience. However, it's crucial to understand that the recommended approach is to fetch the paywall by the getPaywall
method, as detailed in the Fetch Paywall Information section above.
Why we recommend using getPaywall
The getPaywallForDefaultAudience
method comes with a few significant drawbacks:
- Potential backward compatibility issues: If you need to show different paywalls for different app versions (current and future), you may face challenges. You’ll either have to design paywalls that support the current (legacy) version or accept that users with the current (legacy) version might encounter issues with non-rendered paywalls.
- Loss of targeting: All users will see the same paywall designed for the All Users audience, which means you lose personalized targeting (including based on countries, marketing attribution or your own custom attributes).
If you're willing to accept these drawbacks to benefit from faster paywall fetching, use the getPaywallForDefaultAudience
method as follows. Otherwise, stick to the getPaywall
described above.
- Swift
- Swift-Callback
do {
let paywall = try await Adapty.getPaywallForDefaultAudience("YOUR_PLACEMENT_ID")
// the requested paywall
} catch {
// handle the error
}
Adapty.getPaywallForDefaultAudience(placementId: "YOUR_PLACEMENT_ID", locale: "en") { result in
switch result {
case let .success(paywall):
// the requested paywall
case let .failure(error):
// handle the error
}
}
The getPaywallForDefaultAudience
method is available starting from iOS SDK version 2.11.2.
Parameter | Presence | Description |
---|---|---|
placementId | required | The identifier of the Placement. This is the value you specified when creating a placement in your Adapty Dashboard. |
locale | optional default: | The identifier of the paywall localization. This parameter is expected to be a language code composed of one or more subtags separated by the minus (-) character. The first subtag is for the language, the second one is for the region. Example: See Localizations and locale codes for more information on locale codes and how we recommend using them. |
fetchPolicy | default: .reloadRevalidatingCacheData | By default, SDK will try to load data from the server and will return cached data in case of failure. We recommend this variant because it ensures your users always get the most up-to-date data. However, if you believe your users deal with unstable internet, consider using Note that the cache remains intact upon restarting the app and is only cleared when the app is reinstalled or through manual cleanup. |