Fetch Paywall Builder paywalls and their configuration

For: Developers

After you designed the visual part for your paywall with Paywall Builder in the Adapty Dashboard, you can display it in your mobile app. The first step in this process is to get the paywall associated with the placement and its view configuration as described below.

Please be aware that this topic refers to Paywall Builder-customized paywalls. For guidance on fetching remote config paywalls, please refer to the Fetch paywalls and products for remote config paywalls in your mobile app topic.

Before you start displaying paywalls in your mobile app (click to expand)
  1. Create your products in the Adapty Dashboard.
  2. Create a paywall and incorporate the products into it in the Adapty Dashboard.
  3. Create placements and incorporate your paywall into it in the Adapty Dashboard.
  4. Install Adapty SDK and AdaptyUI DSK in your mobile app.

Fetch paywall designed with Paywall Builder

If you've designed a paywall using the Paywall Builder, you don't need to worry about rendering it in your mobile app code to display it to the user. Such a paywall contains both what should be shown within the paywall and how it should be shown. Nevertheless, you need to get its ID via the placement, its view configuration, and then present it in your mobile app.

To ensure optimal performance, it's crucial to retrieve the paywall and its view configuration as early as possible, allowing sufficient time for images to download before presenting them to the user.

To get a paywall, use the getPaywall method:

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
    }
}
Adapty.getPaywall("YOUR_PLACEMENT_ID", locale = "en") { result ->
    when (result) {
        is AdaptyResult.Success -> {
            val paywall = result.value
            // the requested paywall
        }
        is AdaptyResult.Error -> {
            val error = result.error
            // handle the error
        }
    }
}
Adapty.getPaywall("YOUR_PLACEMENT_ID", "en", result -> {
    if (result instanceof AdaptyResult.Success) {
        AdaptyPaywall paywall = ((AdaptyResult.Success<AdaptyPaywall>) result).getValue();
        // the requested paywall
      
    } else if (result instanceof AdaptyResult.Error) {
        AdaptyError error = ((AdaptyResult.Error) result).getError();
        // handle the error
      
    }
});
try {
  final paywall = await Adapty().getPaywall(id: "YOUR_PLACEMENT_ID", locale: "en");
  // the requested paywall
} on AdaptyError catch (adaptyError) {
  // handle the error
} catch (e) {
}
Adapty.GetPaywall("YOUR_PLACEMENT_ID", "en", (paywall, error) => {
  if(error != null) {
    // handle the error
    return;
  }
  
  // paywall - the resulting object
});
try {
	const id = 'YOUR_PLACEMENT_ID';
	const locale = 'en';

	const paywall = await adapty.getPaywall(id, locale);
  // the requested paywall
} catch (error) {
	// handle the error
}
ParameterPresenceDescription
placementIdrequiredThe identifier of the desired Placement. This is the value you specified when creating a placement in the Adapty Dashboard.
localeoptional
default: en
The identifier of the paywall localization. This parameter is expected to be a language code composed of one or two subtags separated by the minus (-) character. The first subtag is for the language, the second one is for the region.

Example: en means English, pt-br represents the Brazilian Portuguese language.

See Localizations and locale codes for more information on locale codes and how we recommend using them.
fetchPolicydefault: .reloadRevalidatingCacheDataBy 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 .returnCacheDataElseLoad to return cached data if it exists. In this scenario, users might not get the absolute latest data, but they'll experience faster loading times, no matter how patchy their internet connection is. The cache is updated regularly, so it's safe to use it during the session to avoid network requests.

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 locally 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.
loadTimeoutdefault: 5 secThis 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 loadTimeout, since the operation may consist of different requests under the hood.

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 should hardcode is the placement ID.

Response parameters:

ParameterDescription
PaywallAn AdaptyPaywall object with a list of product IDs, the paywall identifier, remote config, and several other properties.

Fetch the view configuration of paywall designed using Paywall Builder

After you've fetched the paywall ID, call the getViewConfiguration(forPaywall:locale:) method to load its view configuration (for cross-platform SDKs, you should call createPaywallView since there is no need to preliminarily fetch view configuration manually):

import Adapty

AdaptyUI.getViewConfiguration(forPaywall: paywall, locale: "en") { result in
    switch result {
    case let .success(viewConfiguration):
        // use loaded configuration
    case let .failure(error):
        // handle the error
    }
}
Adapty.getViewConfiguration(paywall, locale = "en") { result ->
    when(result) {
        is AdaptyResult.Success -> {
            val viewConfiguration = result.value
            // use loaded configuration
        }
        is AdaptyResult.Error -> {
            val error = result.error
            // handle the error
        }
    }
}
Adapty.getViewConfiguration(paywall, "en", result -> {
    if (result instanceof AdaptyResult.Success) {
        AdaptyViewConfiguration viewConfiguration =
                ((AdaptyResult.Success<AdaptyViewConfiguration>) result).getValue();
        // use loaded configuration
    } else if (result instanceof AdaptyResult.Error) {
        AdaptyError error = ((AdaptyResult.Error) result).getError();
        // handle the error
    }
});
import 'package:adapty_ui_flutter/adapty_ui_flutter.dart';

try {
  final view = await AdaptyUI().createPaywallView(paywall: paywall);
} on AdaptyError catch (e) {
  // handle the error
} catch (e) {
  // handle the error
}
import {createPaywallView} from '@adapty/react-native-ui';

try {
  const view = await createPaywallView(paywall);
} catch (error) {
  // handle the error
}

AdaptyUI.CreatePaywallView(paywall, locale: 'en', preloadProducts: true, (view, error) => {
  // use the view
});

📘

If you are using multiple languages, learn how to add a Paywall builder localization and how to use locale codes correctly here.

Once you have successfully loaded the paywall and its view configuration, you can proceed to presenting the paywall in your mobile app.