Purchasely
4.4
4.4
  • Welcome page
  • General
    • Presentation
    • Release notes
  • Quick start
    • Console Configuration
    • SDK Implementation
    • Testing
    • Sample
  • Basic configuration
    • Console Configuration
      • Creating a new application
      • Creating your Products
        • App Store
        • Play Store
        • Huawei App Gallery
        • Amazon App Store
        • Products & Plans
      • Design your Paywalls
      • Design your Paywalls-Latest
        • Carousel
        • Carousel Flow
        • Features List
        • Features List & Plan Picker with 2 & 3 columns
        • Feature list overlay
        • Plan picker horizontal
        • Plan picker with 2 and 3 Column
    • SDK installation
      • iOS SDK
      • Android SDK
      • React Native SDK
      • Cordova SDK
      • Flutter SDK
      • Unity SDK
    • SDK configurations
      • Paywall observer mode
      • Full mode
      • StoreKit 2
      • Appendices
        • Start the SDK
        • Set User Id
        • Notify when the app is ready
        • Present paywalls
        • Unlock content / service
        • Close SDK (Android only)
    • Stripe
    • Purchasely with RevenueCat
  • S2S notifications
    • Server-to-server notifications ?
    • Apple App Store
    • Google Play Store
    • Huawei App Gallery
  • Analytics
    • Dashboards
      • Introduction
      • Live
      • Subscriptions
      • Cohorts
      • Trials
      • Events
    • Events
      • Webhook events
        • Subscription events
        • Subscription events attributes
      • SDK events
        • UI events
        • UI attributes
  • Integrations
    • Webhook
      • Receiving and understanding messages
      • Managing entitlements
      • Detailed sequence diagrams
    • Airship
    • Amplitude
    • AppsFlyer
    • Adjust
    • Piano analytics(ex AT Internet)
    • Batch
    • Branch
    • Braze
    • Clevertap
    • Customer.io
    • Firebase
    • Iterable
    • Mixpanel
    • MoEngage
    • OneSignal
    • Segment
    • Brevo(ex Sendinblue)
  • Advanced Features
    • Asynchronous paywalls
    • NEW: Promotional offers
    • Anonymous user
    • Associating content
    • Audiences
    • Customising UI
      • Errors & alerts
      • Controllers (iOS) / Fragments (Android)
    • Deeplinks automations
    • Disable placements
    • Displaying users subscriptions
    • Localization
    • Lottie animations
    • Non-subscription products
    • Paywall action interceptor
    • Promoting your products
      • Self-promotion
      • Promoting In-App Purchases
    • Purchase manually
    • Subscription status
    • Use your own paywall
  • Others
    • Frequently Asked Questions
    • Migration guides
      • Migrate to Purchasely
      • Webhook
        • Migrate to Webhook v3.0
      • SDK
        • Migrate to SDK v3.0
          • v2.2.0
          • v2.1.3
        • Migrate to SDK v3.1
        • Migrate to SDK v3.2
        • Migrate to SDK v4.0.0
  • TESTING
    • Testing Cycle Durations
Powered by GitBook

© Purchasely 2020-2023

On this page

Was this helpful?

Edit on GitHub
  1. Advanced Features

Asynchronous paywalls

Pre-fetch and customize paywalls display

PreviousBrevo(ex Sendinblue)NextNEW: Promotional offers

Last updated 1 year ago

Was this helpful?

The feature described in this section is supported on the following versions and above:

  • iOS: 3.5.0

  • Android: 3.5.0

  • ReactNative: 2.5.0

  • Cordova: 2.5.0

  • Flutter: 1.5.0

Purchasely, by default, with a loading indicator while fetching the paywall from the network and preparing it for display.

Using Purchasely.fetchPresentation() method, you can pre-fetch the paywall from the network before displaying it. This provides the following benefits:

  • Display the paywall only after it has been loaded from the network

  • Handle network errors gracefully

  • Show a custom loading screen

  • Pre-load the paywall while users navigate through your app, such as during onboarding screens

  • Choose for a specific placement

  • Display

Implementation

Call Purchasely.fetchPresentation for a placement or with a presentation id

  1. An error may be returned if the presentation could not be fetched from the network.

  2. If successful, you will have a PLYPresentation instance containing the following properties

class PLYPresentation(
    id: String?
    placementId: String?
    audienceId: String?
    abTestId: String?
    abTestVariantId: String?
    language: String?
    type: PLYPresentationType
    plans: [String] // get PLYPlan instance with Purchasely.plan("planId")

    // Android SDK only (Kotlin or Java)
    view: PLYTemplateView?
    
    // iOS SDK only (Swift or Objective-C)
    controller: UIViewController?
}

A presentation can be one of the following types:

  • Normal: The default behavior, a Purchasely paywall created from our console.

  • Fallback: A Purchasely paywall, but not the one you requested, as it could not be found.

// fetch presentation with id
Purchasely.fetchPresentation(with: "presentationId", fetchCompletion: { presentation, error in
})

// fetch presentation for placement
Purchasely.fetchPresentation(
    for: "onboarding",
    fetchCompletion: { presentation, error in
         // closure to get presentation and display it
         guard let presentation = presentation, error == nil else {
             print("Error while fetching presentation: \(error?.localizedDescription ?? "unknown")")
             return
         }
         
         if presentation.type == .normal || presentation.type == .fallback {
             let paywallController = presentation.controller
             
             // display paywall controller.
             
         } else if presentation.type == .deactivated {
             
             // nothing to display
             
         } else if presentation.type == .client {
             let presentationId = presentation.id
             let planIds = presentation.plans
             
             // display your own paywall
             
         }
    },
    completion: { result, plan in
        // closure when presentation controller is closed to get result
        switch result {
            case .purchased:
                print("User purchased: \(plan?.name)")
                break
            case .restored:
                print("User restored: \(plan?.name)")
                break
            case .cancelled:
                break
            @unknown default:
                break
        }
    })
[Purchasely fetchPresentationFor:@"onboarding" fetchCompletion:^(PLYPresentation * _Nullable presentation, NSError * _Nullable error) {
        if (error != nil) {
            NSLog(@"Error while fetching presentation: %@", error.localizedDescription);
            return;
        }
        
        if (presentation.type == PLYPresentationTypeNormal || presentation.type == PLYPresentationTypeFallback) {
            PLYPresentationViewController *paywallController = presentation.controller;
            
            // display paywall controller.
            
        } else if (presentation.type == PLYPresentationTypeDeactivated) {
            
            // nothing to display
            
        } else if (presentation.type == PLYPresentationTypeClient) {
            NSString *presentationId = presentation.id;
            NSArray<NSString *> *plans = presentation.plans;
            
            //display your own paywall
            
        }
    } completion:nil];
Purchasely.fetchPresentationForPlacement("onboarding") { presentation, error ->
    if(error != null) {
        Log.d("Purchasely", "Error fetching paywall", error)
        return@fetchPresentationForPlacement
    }

    when(presentation?.type) {
        PLYPresentationType.NORMAL,
        PLYPresentationType.FALLBACK -> {
            val paywallView = presentation.buildView(
                context = this@MainActivity,
                viewProperties = PLYPresentationViewProperties(
                    onClose = {
                        // TODO remove view from your layout
                    }
                )
            ) { result, plan ->
                // Paywall is closed, check result to know if a purchase happened
                when(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}")
                }
            }
            
            // Display Purchasely paywall by adding paywallView to your layout
        }
        PLYPresentationType.DEACTIVATED -> {
            // Nothing to display
        }
        PLYPresentationType.CLIENT -> {
            val paywallId = presentation.id
            val planIds = presentation.plans
            // Display your own paywall
        }
        else -> {
            //No presentation, it means an error was triggered
        }
    }
}
Purchasely.fetchPresentationForPlacement(
    this, 
    "onboarding", 
    null,
    (presentation, error) -> {
        if(error != null) {
            Log.d("Purchasely", "Error fetching paywall", error);
            return null;
        }
        
        if(presentation.getType() == PLYPresentationType.NORMAL
            || presentation.getType() == PLYPresentationType.FALLBACK) {
            // display Purchasely paywall
            PLYTemplateView paywallView = presentation.view
        }
        
        if(presentation.getType() == PLYPresentationType.DEACTIVATED) {
            // nothing to display
        }
        
        if(presentation.getType() == PLYPresentationType.CLIENT) {
            String paywallId = presentation.getId();
            List<String> planIds = presentation.getPlans();
            // Display your own paywall
        }
        
        return null;
    }
);
try {
  // Fetch presentation to display
  const presentation = await Purchasely.fetchPresentation({
      placementId: 'onboarding'
  })

  if(presentation.type == PLYPresentationType.DEACTIVATED) {
    // No paywall to display
    return
  }

  if(presentation.type == PLYPresentationType.CLIENT) {
    // Display my own paywall
    return
  }

  //Display Purchasely paywall
  const result = await Purchasely.presentPresentation({
    presentation: presentation
  })
  
  switch (result.result) {
    case ProductResult.PRODUCT_RESULT_PURCHASED:
    case ProductResult.PRODUCT_RESULT_RESTORED:
      if (result.plan != null) {
        console.log('User purchased ' + result.plan.name);
      }

      break;
    case ProductResult.PRODUCT_RESULT_CANCELLED:
      console.log('User cancelled');
      break;
  }

} catch (e) {
  console.error(e);
}
try {
  var presentation = await Purchasely.fetchPresentation("ONBOARDING");

  if (presentation == null) {
    print("No presentation found");
    return;
  }

  if (presentation.type == PLYPresentationType.deactivated) {
    // No paywall to display
    return;
  }

  if (presentation.type == PLYPresentationType.client) {
    // Display my own paywall
    return;
  }

  //Display Purchasely paywall

  var presentResult = await Purchasely.presentPresentation(presentation,
      isFullscreen: false);

  switch (presentResult.result) {
    case PLYPurchaseResult.cancelled:
      {
        print("User cancelled purchased");
      }
      break;
    case PLYPurchaseResult.purchased:
      {
        print("User purchased ${presentResult.plan?.name}");
      }
      break;
    case PLYPurchaseResult.restored:
      {
        print("User restored ${presentResult.plan?.name}");
      }
      break;
  }
} catch (e) {
  print(e);
}
// coming soon
private PurchaselyRuntime.Purchasely _purchasely;

...
_purchasely.FetchPresentation("presentationId",
			OnFetchPresentationSuccess,
			Log,
			"contentId");		
...

private void OnFetchPresentationSuccess(Presentation presentation)
{
	Log("Fetch Presentation Success.");
	LogPresentation(presentation);

	switch (presentation.presentationType)
	{
		case PresentationType.Normal:
		case PresentationType.Fallback:
			_purchasely.PresentPresentationWithId(presentation.id,
				OnPresentationResult,
				OnPresentationContentLoaded,
				OnPresentationContentClosed);
			break;
		case PresentationType.Unknown:
		case PresentationType.Deactivated:
			Log($"Fetched presentation with type: {presentation.presentationType}. Will not show content.");
			break;
		case PresentationType.Client:
			paywall.Show(presentation);
			break;
	}
}

Deactivated: No with that placement, possibly for a specific A/B test or .

Client: You declared and should . Use the list of plans to determine which offers to display to your users.\

shows the paywall screen
not to display a paywall
your own paywall
paywall associated
audience
your own paywall in our console
display it