At Purchasely, we believe that every app deserves to be profitable. That's why we're excited to announce the release of our new SDK version 4.0.0, which allows you to set promotional offers.
This new version makes it easier than ever to create and manage effective promotional campaigns, helping you to increase your app's revenue.
Take note that :
On Android, we have adopted Google Billing v5.2.1 and the minimum required Kotlin version is 1.6.0
On iOS, setting a StoreKit version is mandatory
Initialization update
The start method no longer includes the uiListener/uiDelegate and eventListener/eventDelegate configuration options as part of its initial configuration, but they can still be set after calling the start() method.
importPurchaselyPurchasely.start(withAPIKey:"API_KEY", appUserId:"USER_ID", runningMode: .full, paywallActionsInterceptor: PLYPaywallActionsInterceptor, storekitSettings: .storeKit2, // Set your StoreKit version logLevel: .debug, // set to warning or error for release initialized: PLYSuccessErrorClosure))// Paywall interceptor can be setted afterwards by callingPurchasely.setPaywallActionsInterceptor { [weak self](action, parameters, presentationInfo, proceed)in}// Set your ui listenerPurchasely.Purchasely.setUIDelegate(PLYUIDelegate?)
#import <Purchasely/Purchasely-Swift.h>
[Purchasely startWithAPIKey:@"API_KEY"
appUserId:@"USER_ID"
runningMode: PLYRunningModeFull
paywallActionsInterceptor:nil
storekitSettings: [StorekitSettings .storekit2] // optional but set to StoreKit 2 by default.
// Fallsback to StoreKit 1 in case the informations are not setup correctly on Purchasely console
logLevel: LogLevelInfo
initialized: nil];
// Paywall interceptor can be setted afterwards by calling
[Purchasely setPaywallActionsInterceptor:^(enum PLYPresentationAction, PLYPresentationActionParameters * _Nullable, PLYPresentationInfo * _Nullable, void (^ _Nonnull)(BOOL)) {
}];
// Set your ui listener
[Purchasely setUIDelegate:(id<PLYUIDelegate> _Nullable)
import io.purchasely.ext.PurchaselyPurchasely.Builder(applicationContext) .apiKey("API_KEY") .logLevel(LogLevel.DEBUG) // set to warning or error for release .userId("USER_ID") .readyToOpenDeeplink(true) .runningMode(PLYRunningMode.Full) .stores(listOf(GoogleStore(), HuaweiStore())) .build()// When you are ready for Purchasely to initialize,// you must call start() method that will grab configuration and products// from the selected stores.Purchasely.start { isConfigured ->}// Set your event listenerPurchasely.eventListener =object : EventListener {overridefunonEvent(event: PLYEvent) {}}// Set your ui listenerPurchasely.uiListener =object : UIListener {overridefunonAlert(alert: PLYAlertMessage) {}overridefunonView(view: View, type: PLYUIViewType) {}}
List<Store> stores =newArrayList();stores.add(newGoogleStore(),newHuaweiStore());new Purchasely.Builder(getApplicationContext()).apiKey("API_KEY").logLevel(LogLevel.DEBUG) // set to warning or error for release.userId("USER_ID").readyToOpenDeeplink(true).runningMode(PLYRunningMode.Full.INSTANCE).stores(stores).build();// When you are ready for Purchasely to initialize,// you must call start() method that will grab configuration and products// from the selected stores.Purchasely.start(isConfigured -> {null;});// Set your event listenerPurchasely.setEventListener(newEventListener() { @OverridepublicvoidonEvent(@NonNullPLYEvent event) {} });// Set your ui listenerPurchasely.setUiListener(newUIListener() { @OverridepublicvoidonAlert(@NonNullPLYAlertMessage alert) {} @OverridepublicvoidonView(@NonNullView view, @NonNullPLYUIViewType type) {} });
// Everything is optional except apiKey and storeKit1// Example with default valuesawaitPurchasely.start({ apiKey:'YOUR_API_KEY', storeKit1:false,// set to false to use StoreKit2, true to use StoreKit1, logLevel:LogLevels.ERROR,// set to debug in development mode to see logs userId:null,// if you know your user id, set it here runningMode:RunningMode.FULL,// select between full and paywallObserver androidStores: ['Google'] // default is Google, don't forget to add the dependency to the same version });
// Everything is optional except apiKey and storeKit1// Example with default valuesawaitPurchasely.start( apiKey:'YOUR_API_KEY', androidStores: ['Google'], // default is Google, don't forget to add the dependency to the same version storeKit1:false, // set to false to use StoreKit2, true to use StoreKit1 logLevel:PLYLogLevel.error, // set to debug in development mode to see logs runningMode:PLYRunningMode.full, // select between full and paywallObserver userId:null, // set a user id if you have one );
Update for deeplinks
The attribute isReadyToPurchase , to indicate that your app is ready to open deeplinks, has been renamed to readyToOpenDeeplink
We have additionally changed the name of the method handle to isDeeplinkHandled
Purchasely.readyToOpenDeeplink(true);Purchasely.isDeeplinkHandled('app://ply/presentations/').then((value) =>console.log('Deeplink handled by Purchasely ? '+ value));
Methods for presentation display
Only with our bridges SDKs: ReactNative, Flutter and Unity
Before you could call the method Purchasely.closePresentation() to hide the presentation or Purchasely.closePresentation(true) to close it
We have changed those methods and added new ones to make it easier to manage and understand, see below
// Hide the presentation being display// for example when you are in paywall action interceptor// to display your own screen like a login screenPurchasely.hidePresentation();// Display the presentation previously hiddenPurchasely.showPresentation();// Close the presentation// cannot be displayed again until you call Purchasely.presentPresentation()Purchasely.closePresentation();
// Hide the presentation being display// for example when you are in paywall action interceptor// to display your own screen like a login screenPurchasely.hidePresentation();// Display the presentation previously hiddenPurchasely.showPresentation();// Close the presentation// cannot be displayed again until you call Purchasely.presentPresentation()Purchasely.closePresentation();
Fetch presentation with context (Android only)
The methods FetchPresentation and FetchPresentationForPresentation have been updated as well. The previously required parameters Context and PLYPresentationResultHandler have been removed and are no longer necessary.
Purchasely.fetchPresentationForPlacement(placementId ="placementId") { presentation, error ->if(presentation?.type == PLYPresentationType.NORMAL || presentation?.type == PLYPresentationType.FALLBACK) {val paywallView = presentation?.buildView(context, viewProperties =PLYPresentationViewProperties(onClose = {//TODO remove paywallView from layout })) { result, plan ->// Paywall is closed, check result to know if a purchase happenedwhen(result) { PLYProductViewResult.PURCHASED -> Log.d("Purchasely", "User purchased ${plan?.name}") PLYProductViewResult.CANCELLED -> Log.d("Purchasely", "User cancelled purchased") PLYProductViewResult.RESTORED -> Log.d("Purchasely", "User restored ${plan?.name}") } }// TODO Add paywallView to your layout to display it }}// You should always use a placement to display paywalls // but if you really need to display a specific paywall// you can use properties to set the your paywall idPurchasely.fetchPresentation(properties = PLYPresentationViewProperties(presentationId = "paywall_id")) { presentation, error ->
if(presentation?.type == PLYPresentationType.NORMAL || presentation?.type == PLYPresentationType.FALLBACK) {val paywallView = presentation?.buildView(context, viewProperties =PLYPresentationViewProperties(onClose = {//TODO remove paywallView from layout })) { result, plan ->// Paywall is closed, check result to know if a purchase happenedwhen(result) { PLYProductViewResult.PURCHASED -> Log.d("Purchasely", "User purchased ${plan?.name}") PLYProductViewResult.CANCELLED -> Log.d("Purchasely", "User cancelled purchased") PLYProductViewResult.RESTORED -> Log.d("Purchasely", "User restored ${plan?.name}") } }// TODO Add paywallView to your layout to display it }}
In this version, we have taken the step to entirely eliminate fragment-related methods that had been deprecated in our prior releases. Instead, opt for one of the view-related methods to display your presentations: