Solved

Eligibility of introductory offers


Badge +1

Hi guys,

I complete setup for product and introductory offers for it on AppStore connect. Now I check eligibility for new user (by checkTrialOrIntroductoryPriceEligibility), and completion block return dictionary with eligibility statuses and associated products. My problem is that status for all products is “Not eligible for trial or introductory price.” Why SDK return wrong status?

icon

Best answer by cody 21 July 2021, 17:09

View original

36 replies

Userlevel 5
Badge +8

Hey @Dmitry!

The checkTrialOrIntroductoryPriceEligibility method takes the existing receipt on your device and checks the transactions to determine if the user is eligible or not for the product ID in question. If there’s no receipt available, this method will return ‘unknown’. If there’s an error parsing the local receipt, we’ll ask the backend for eligibility information, which will do its best to return a value based on the information in the user’s receipt. Debug logs will help to provide any relevant information about this method and potential errors.

If the method is returning ‘ineligible’, the method has likely found previous transactions from the user’s receipt either on-device or from the backend that indicate the user is ineligible for the introductory price. If you’re testing this method in sandbox, I’d recommend creating a new sandbox user and/or trying a fresh installation.

Generally, you should handle each of these cases, and inform your users based on the information you have available. Even if our method returns unknown or ineligible, Apple’s payment sheet will ultimately display the introductory price if the user is eligible for it and the user will confirm the terms of the purchase during the checkout.

Badge +5

@cody If the user has never purchased anything, will there be a receipt available to parse?

Badge +3

Hi @cody, we implemented checkTrialOrIntroductoryPriceEligibility

Some of our testers use TestFlight and tested purchases in the past, so they reset eligibility for intro pricing from App Store settings but the result remains “Not eligible for trial or introductory price.”.

We can confirm the intro (in this case a trial) was available by trying to proceed to the payment and checking the purchase confirmation page.

Is it possible that there is a bug regarding this specific case?

Thanks

Userlevel 1
Badge +1

I couldn't find `checkTrialOrIntroductoryPriceEligibility` and have eventually found out that it has been renamed to `checkTrialOrIntroDiscountEligibility` as of Purchases 4.0.0 as seen here, in case it helps someone visiting this thread.

Userlevel 1
Badge +1

I have found the same behaviour as @Marco Muratore: testing in the sandbox, a user is considered non-eligible for free trial for any of the products if they have subscribed before, even after resetting eligibility in the iPhone Settings.

I tried the following and none of it served to reset the eligibility of the user for a free trial:
- delete the user in RevenueCat's sandbox dashboard
- reinstall the app from scratch
- log out the sandbox user and log in again

If I start the flow, then the system prompts tell me that the user has the free trial, but the response from RevenueCat is always non-eligible.

The only thing that worked to have a user eligible for free trial was to create a new test user in the sandbox in App Store Connect. Once I subscribed with this new sandbox user, I couldn't reset their eligibility again.

So as of these tests, it would look like once a sandbox users is used to subscribe once, then they are "burnt" and can't be used to test the full subscription scenarios. Is this intended behaviour? Is there a way to reset a test user eligibility for a free trial?

Userlevel 3
Badge +7

HI @atineoSE ,

 

Unfortunately I don’t know of another way to consistently test user eligibility except for creating a new sandbox user each time. That is usually our solution to this issue.   

Badge +3

Confirmed - `checkTrialOrIntroductoryPriceEligibility` is what you need.

Would be good if this were documented in the official guides, probably under “Displaying Products”. Until finding this thread, found it confusing on how to determine if user should see free trial paywall, or regular paid paywall. 

Badge +4

Shall we use TrialOrIntroPriceEligibilityChecker’s checkEligibility function to check for trial eligibility for iOS 14 +
Edit: Okey found checkTrialOrIntroDiscountEligibility

Badge +3

I may have found a bug.

 

I have a product that has no introductory offer set up on Connect. However, `checkTrialOrIntroductoryPriceEligibility` is returning `eligible`.

 

Do note, I have other product id’s in the same subscription group that do have trials. 

 

Happening in both sandbox and production. Latest iOS sdk. 

Userlevel 5
Badge +8

@Jonah thanks for reporting! We already have a fix in place, which will go out very soon. In the meantime, one way to work around this is to configure the SDK to use StoreKit 1. 

 

Purchases.configure(with:

    Configuration.Builder(withAPIKey: Constants.apiKey)

        .with(appUserID: "<app_user_id>")

        .with(usesStoreKit2IfAvailable: false)

        .build()

)

Badge +3

@Jonah thanks for reporting! We already have a fix in place, which will go out very soon. In the meantime, one way to work around this is to configure the SDK to use StoreKit 1. 

 

Purchases.configure(with:

    Configuration.Builder(withAPIKey: Constants.apiKey)

        .with(appUserID: "<app_user_id>")

        .with(usesStoreKit2IfAvailable: false)

        .build()

)

Thanks for the quick reply. Ok will give that a shot!

Badge +3

Hi @Andy  - I’m now on latest iOS SDK (4.12.0). I’m using a SKProduct that has a free trial. `checkTrialOrIntroDiscountEligibility` is returning elligible, however. `package.storeProduct.discounts` is empty. 

 

Is this expected?

Badge +3

.

Badge +4

Is this available in Android SDK? I could not find anything related to `checkTrialOrIntroDiscountEligibility` in the Android API?

Userlevel 5
Badge +8

@Jonah I’m sorry I missed your questions!! I’m super late to reply, but: `package.storeProduct.discounts` relates to Promotional Offers, whereas `checkTrialOrIntroDiscountEligibility` relates to Introductory Offers. To get the Introductory Offers, use `package.storeProduct.introductoryDiscount`. 

 

@Petri `checkTrialOrIntroDiscountEligibility` is currently not available in our Android API, although we do have plans to introduce it later this year. 

Badge +4

@Jonah I’m sorry I missed your questions!! I’m super late to reply, but: `package.storeProduct.discounts` relates to Promotional Offers, whereas `checkTrialOrIntroDiscountEligibility` relates to Introductory Offers. To get the Introductory Offers, use `package.storeProduct.introductoryDiscount`. 

 

@Petri `checkTrialOrIntroDiscountEligibility` is currently not available in our Android API, although we do have plans to introduce it later this year. 


Is there some other way to to check eligibility if checkTrialOrIntroDiscountEligibility is not available on Android? (we are using the Flutter SDK)

Userlevel 5
Badge +8

@Bilance you should be able to get eligibility information by following the steps outlined here: 

Note that the reply refers to purchaserInfo, however, on Flutter v4 or higher, the object is called customerInfo. The steps should otherwise remain the same. 

Userlevel 1

@cody I am attempting to implement checkTrialOrIntroductoryPriceEligibility in our app using RC and just wanted to check this statement:

 

The checkTrialOrIntroductoryPriceEligibility method takes the existing receipt on your device and checks the transactions to determine if the user is eligible or not for the product ID in question. If there’s no receipt available, this method will return ‘unknown’.

 

Does that mean that it’s likely all new users will get an “unknown” eligibility response? (I am testing with a new sandbox account and get “unknown” but wanted to check if this is also the case for real-world production users)

Thanks in advance!

Badge +5

@cody

I would also like to know what happens for new users who don’t have any receipt on their device … 

Userlevel 1

@skuske I asked my question above in a support ticket and got a helpful answer from Michael at Developer Support.

The receipt not being available is most commonly seen in Sandbox and is not usually an issue in production. So this case of not having a receipt generated causing the eligibility to be off would be less common to see in production. In production, a receipt is generated when a user downloads the app and is saved against the Apple account.

 

So it seems that most, if not all, users on production will have a receipt and therefore return “eligible” or “ineligible”.

 

If there is no receipt for any reason, the method will always return “unknown”.

Badge +5

@ian-l 

Many thanks, that helps a lot!

Badge

@skuske I asked my question above in a support ticket and got a helpful answer from Michael at Developer Support.

The receipt not being available is most commonly seen in Sandbox and is not usually an issue in production. So this case of not having a receipt generated causing the eligibility to be off would be less common to see in production. In production, a receipt is generated when a user downloads the app and is saved against the Apple account.

 

So it seems that most, if not all, users on production will have a receipt and therefore return “eligible” or “ineligible”.

 

If there is no receipt for any reason, the method will always return “unknown”.

I’ll just go with this and hope for the best. Thank you! 

Badge +3

@Jonah I’m sorry I missed your questions!! I’m super late to reply, but: `package.storeProduct.discounts` relates to Promotional Offers, whereas `checkTrialOrIntroDiscountEligibility` relates to Introductory Offers. To get the Introductory Offers, use `package.storeProduct.introductoryDiscount`. 

 

@Petri `checkTrialOrIntroDiscountEligibility` is currently not available in our Android API, although we do have plans to introduce it later this year. 

 

@Andy Are there any updates on this already? I am using Capacitor and just trying to implement Trials but checking if somebody is eligible seems still quite sensitive to errors, especially because Android needs a workaround. Thank you as always for your great work, I highly appreciate it.

Userlevel 5
Badge +8

@manuel-becker sorry for the lack of an update. 

 

We didn’t end up adding this new API, since on Android since the introduction of BillingClient 5, the answer to whether your user is eligible for an intro offer is: yes, as long as they can see them. 

 

This means that anything you get through getOfferings, the user is eligible for on Android. This is a different story from iOS. 

 

I’m thinking of ways to make this behavior more standardized across the board, although there are technical limitations that make that a bit tricky. 

 

For the time being, I’d advise: 

  • on iOS, use the API for intro eligibility
  • on Android, you can look for the `freePhase` on the PricingPhases within SubscriptionOption, if there’s one there it means the user is eligible for a free trial

 

Badge +3

@Andy No worries, you don’t have to be sorry. Anything helps and any hint is highly appreciated, especially with something like that which probably affects all RC’s users which are developing not natively.

That definitely sounds like a big step forward in terms of not having to sync purchases first. I don’t know yet how to get SubscriptionOption but I will deep dive the Capacitor documentation and hopefully find out. This should also prevent users from simply creating a new account and using the next free trial again because it’s iOS and Android which decides about the eligibility, right?

Thank you so much as always for all your efforts and for doing such a fantastic job, I appreciate it a lot.

Reply