Skip to main content
Question

Preventing Unlimited Free Trials with Anonymous Users on New Devices

  • Jan 31, 2025 9:04 PM UTC
  • 2 replies
  • 538 views

Forum|alt.badge.img+6

I'm facing a challenge with managing trial offers for anonymous users on new devices
 

The Problem

RevenueCat’s checkTrialOrIntroductoryEligibility is iOS-only, so I’ve built a workaround using allPurchasedProductIdentifiers to determine trial eligibility. It works like this:

 

const customerInfo = (await Purchases.getCustomerInfo()).customerInfo;

const numPurchases = customerInfo.allPurchasedProductIdentifiers.length;

if (numPurchases > 0) {
setShowTrialOffer(false);
}

 

This works as long as the user stays on the same device because RevenueCat caches the Anonymous ID. However, if the user:

  1. Starts a free trial
  2. Cancels the trial before it ends
  3. Deletes and reinstalls the app (or switches devices)

RevenueCat creates a new Anonymous ID when the user reopens the app. As a result, allPurchasedProductIdentifiers will be empty. This allows the user to start another free trial, repeating the process indefinitely.

 

Potential Solution: syncPurchases

Calling restorePurchases could prevent this, but it may trigger OS-level sign-in prompts, so RevenueCat recommends syncPurchases instead. However, the documentation is unclear:

  • General Docs:

    "syncPurchases allows you to programmatically trigger a restore. This method, like restorePurchases, reactivates any content previously purchased from the same store account."

  • SDK Docs:

    "syncPurchases sends all purchases to the RevenueCat backend. Call this when using your own subscription implementation anytime a sync is needed, like after a successful purchase."

These descriptions seem contradictory:

  • Does syncPurchases pull past purchases from the app stores?
  • Or does it just sync purchases from my app to RevenueCat?

Key Questions

If syncPurchases does pull past purchases from the app stores, what happens in this scenario?

  1. A user starts a trial (RevenueCat creates AnonymousAppUserID#1)
  2. The user deletes and reinstalls the app (RevenueCat creates AnonymousAppUserID#2)
  3. The user opens the app, and I call syncPurchases.

After calling syncPurchases:

  • Will CustomerInfo.originalAppUserId return AnonymousAppUserID#1?
  • Will CustomerInfo.allPurchasedProductIdentifiers include the original trial?
  • Will future webhooks for the user have AnonymousAppUserID#1 in the original_app_user_id field?

Any clarity would be greatly appreciated!

Chris

This post has been closed for comments

2 replies

Forum|alt.badge.img+8
  • RevenueCat Staff
  • Feb 4, 2025 10:59 PM UTC

Hi, syncPurchases does the same thing as restorePurchases, just programatically. Both methods will pull all past purchases from the app stores associated with your app. 

 

Will CustomerInfo.originalAppUserId return AnonymousAppUserID#1?

The original_app_user_id will be the first seen alias. This should be the user that was first created which will be  the AnonymousAppUserID#1 if it was created first.

 

Will CustomerInfo.allPurchasedProductIdentifiers include the original trial?

Yes it will as the users and their purchases are merged.

 

Will future webhooks for the user have AnonymousAppUserID#1 in the original_app_user_id field?

This depends on the above.


Forum|alt.badge.img+6

Thanks ​@Haley Pace 

I kept digging into this, and after half a day of testing, I found that the original_app_user_id  is  AnonymousAppUserID#1 after calling  syncPurchases() .

Hopefully, this helps anyone else looking for this answer.

Take care,


Chris