If you use Adapty UI library to render no-code paywalls, please note that this v2.6.0 release is not compatible with older UI library versions, you need at least to have Adapty UI library v1.1.0
⚡ BREAKING CHANGES ⚡
We are going toward semver, but do not currently follow it strictly. Please note that this update includes a number of breaking changes.
- Billing Library 5 supported for Android
- StoreKit 2 partial support
- Much more stable and optimized data communication in bridge layer
- Improved error handling: less unexpected/unknown errors, more descriptive errors messages
- Everything is serializable now. For example, you now can put products from
getPaywallProducts
into a JSON file and safely decode JSON in other sessions, where these products were not loaded
activate
- iOS apps can now partially enable StoreKit 2 in your
activate
call. Read more - You can now disable IDFA collection within your
activate
call for iOS. Read more - You can now delay SDK activation until your next SDK call to avoid having constant iOS simulator authentication (#60). Read more
- Activation property
lockMethodsUntilReady
is now turned on for everyone, flag deprecated - Activation property
enableUsageLogs
moved to ios category (ios.enableUsageLogs
) as it haven't done anything to Android applications
Complete activation call now looks like this:
adapty.activate('PUBLIC_SDK_KEY', {
observerMode: false,
customerUserId: 'YOUR_USER_ID',
logLevel: 'error',
__debugDeferActivation: false,
ios: {
storeKit2Usage: 'disabled',
idfaCollectionDisabled: false,
enableUsageLogs: false,
},
});
getPaywall
, getPaywallProducts
, getProductsIntroductoryOfferEligibility
New StoreKits provide new ways of checking promotional eligibility. It is a rather costly operation and it includes the only really dynamic data about products. We decided to further break up product fetching flow, following newer Store Kits:
const paywall = await adapty.getPaywall(id);
const products = await adapty.getPaywallProducts(paywall);
const offerEligibilityMap = await adapty.getProductsIntroductoryOfferEligibility(products);
const isIntroOfferEligible = offerEligibilityMap[product.vendorProductId];
This also allows to discard on device product caching, so if you want to statically store products, we recommend storing the response from getPaywallProducts
, and then only fetching data for getProductsIntroductoryOfferEligibility
if needed.
Also, please note that products AdaptyProduct
interface has changed considerably. Details below.
Types & Interfaces changes
For most developers, who doesn't directly work with Adapty types following section may not be of huge interest.
Still it is worthwhile to have a glance at changed interfaces and types, especially if TypeScript or JSDoc don't back your up.
Every change is marked with what it can affect, please update all affected areas in your code if necessary.
For TypeScript developers tsc will mark every broken change during compilation, so feel free to ignore this and refer once needed.
LogLevel
Previously, logLevel accepted "ERROR" string, while all other values were lower-cased. This is fixed now.
What is affected
- Setting log level in
adapty.activate(sdkKey, {logLevel: ... })
- Setting log level in
adapty.setLogLevel
type LogLevel = {
VERBOSE: 'verbose',
- ERROR: 'ERROR',
+ ERROR: 'error',
WARN: 'warn',
INFO: 'info',
};
FetchPolicy
FetchPolicy
is removed as StoreKit2 handles products data differently.
What is affected
- iOS
AndroidSubscriptionUpdateProrationMode
→ AdaptyAndroidSubscriptionUpdateReplacementMode
AndroidSubscriptionUpdateProrationMode
has been renamed to AdaptyAndroidSubscriptionUpdateReplacementMode
to match all Adapty docs and all properties have been trimmed a little
What is affected
- Making complex android purchases via
adapty.makePurchase(product, {android: { prorationMode: ... }})
type AdaptyAndroidSubscriptionUpdateReplacementMode = {
+ ChargeFullPrice: "charge_full_price";
Deferred: "deferred";
+ WithoutProration: "without_proration";
- ImmediateWithoutProration: "immediate_without_proration";
+ ChargeProratedPrice: "charge_prorated_price";
- ImmediateAndChargeProratedPrice: "immediate_and_charge_prorated_price";
+ WithTimeProration: "with_time_proration";
- ImmediateWithTimeProration: "immediate_with_time_proration";
};
OfferEligibility
Value 'unknown'
is removed as StoreKit2 & Billing Library 5 now have different flows to discover eligibility. Value 'not_applicable'
added for some products.
What is affected
- Certain ways of displaying that a user is not eligible for promotionals after
adapty.getPaywallProducts
call
type OfferEligibility = {
Eligible: "eligible";
Ineligible: "ineligible";
- Unknown: "unknown";
+ NotApplicable: "not_applicable";
};
AdaptyPaywall
All paywalls now have hasViewConfiguration
property that shows whether these paywalls can be rendered using Adapty paywall UI library. Property vendorProductIds
has been removed. Property products
has been added instead. It lists the minimal available info about products beforehand.
What is affected
If you used paywall.vendorProductIds
somehow, consider updating to paywall.products
type AdaptyPaywall = {
+ hasViewConfiguration: boolean;
+ products: ProductReference[];
- vendorProductIds?: string[];
...
};
+type ProductReference = {
+ vendorId: string;
+ ios?: {
+ discountId?: string;
+ };
+ android?: {
+ basePlanId?: string;
+ offerId?: string;
+ };
+};
AdaptyPrice
New sub-model used in new AdaptyPaywallProduct
and AdaptyDiscountPhase
interfaces.
+type AdaptyPrice = {
+ amount: number;
+ currencyCode?: string;
+ currencySymbol?: string;
+ localizedString?: string;
+}
AdaptySubscriptionDetails
New sub-model used in new AdaptyPaywallProduct
interface. Describes subscription info.
+type AdaptySubscriptionDetails = {
+ subscriptionPeriod: AdaptySubscriptionPeriod;
+ localizedSubscriptionPeriod?: string;
+ introductoryOffers?: AdaptyDiscountPhase[];
+ ios?: {
+ promotionalOffer?: AdaptyDiscountPhase;
+ subscriptionGroupIdentifier?: string;
+ };
+ android?: {
+ offerId?: string;
+ basePlanId: string;
+ introductoryOfferEligibility: OfferEligibility;
+ offerTags?: string[];
+ renewalType?: 'prepaid' | 'autorenewable';
+};
AdaptyAccessLevel
Property android.offerId
has been added that shows an identifier of a discount offer in Google Play that unlocked this access level.
type AdaptyAccessLevel = {
+ android: {
+ offerId?: string;
+ };
};
AdaptyProductDiscount
→ AdaptyDiscountPhase
AdaptyProductDiscount
has been renamed to AdaptyDiscountPhase
. Pricing properties has moved to 'price: AdaptyPrice' property. Property paymentMode
is now available on both iOS and Android.
What is affected
- Displaying price drops
- Displaying payment modes with discounts
type AdaptyDiscountPhase = {
- localizedPrice?: string;
- price: number;
+ price: AdaptyPrice;
+ paymentMode: OfferType;
ios: {
- paymentMode: OfferType;
}
};
AdaptyProduct
→ AdaptyPaywallProduct
AdaptyProduct
has been renamed to AdaptyPaywallProduct
. Pricing properties have been moved into price?: AdaptyPrice
property. Subscription details properties have been moved inside subscriptionDetails
property.
What is affected
- Displaying products info
type AdaptyPaywallProduct = {
+ price?: AdaptyPrice;
- localizedPrice?: string;
- price: number;
- currencyCode?: string;
- currencySymbol?: string;
+ subscriptionDetails?: AdaptySubscriptionDetails;
- introductoryDiscount?: AdaptyProductDiscount;
- localizedSubscriptionPeriod?: string;
- introductoryOfferEligibility: OfferEligibility;
- android?: {
- freeTrialPeriod?: AdaptySubscriptionPeriod;
- localizedFreeTrialPeriod?: string;
- };
ios: {
isFamilyShareable: boolean;
- subscriptionGroupIdentifier?: string;
- discounts: AdaptyProductDiscount[];
- promotionalOfferEligibility: OfferEligibility;
- promotionalOfferId?: string;
- subscriptionGroupIdentifier?: string;
};
};