Skip to main content
Question

Is appuserId and original appuser Id different??


Forum|alt.badge.img

❓ RevenueCat Anonymous User Confusion — Purchases Made Without Login

Hi everyone,

I'm currently integrating RevenueCat in a Flutter app and I've run into an issue where a user made a successful purchase anonymously, even though I've explicitly configured the SDK to use Purchases.logIn(userId) after login.

📦 My Setup

I initialize RevenueCat in main.dart only after the user has logged in. Here's the relevant initialization code:

 

 

🔍 My Questions

  1. Can I safely call Purchases.logOut() if the user is anonymous? Will it throw or is it a no-op?

  2. Does Purchases.logIn(userId) guarantee that the userId will be used for future purchases? Or is there any chance of fallback to an anonymous ID?

  3. Why is originalAppUserId still showing an anonymous ID even after calling logIn(userId)?
    Shouldn't it update to match appUserId after login?

  4. Does Purchases.isAnonymous reliably tell me whether the current user is anonymous?

📎 Notes

  • The userId is definitely non-null and only passed after the user has logged in.

  • I’m using a guest user pattern — the SDK is initially configured in main.dart without a user ID to allow the guest to browse offerings and see subscription info.

  • At the time of purchase, I log in the user and call initRevenueCat() with their custom userId.

  • Despite calling logIn(userId) and restorePurchases(), one of the users was still tracked under an anonymous appUserId, and their purchase wasn’t linked to their logged-in account.


    Today i lose a subscription and a in-app purchase because i have to refund ,

 
This post has been closed for comments

3 replies

guilherme
RevenueCat Staff
Forum|alt.badge.img+4
  • RevenueCat Staff
  • 66 replies
  • June 15, 2025

Hey ​@aman-singh-968081 ,

Looking at your current described setup, while you mentioned that initRevenueCat() is only called after login, you clarify too that the SDK is initially configured in a main.dart and without a user ID; that setup means a RevenueCat anonymous user session is already live before that login happens. If a user somehow initiates a purchase before the logIn(userId) call, that purchase is attributed to the anonymous App User ID. Even calling logIn afterward won't retroactively reassign it.

Also, I noticed your call to restorePurchases, so it’s important to understand what it is doing and if it’s the best approach for your flow. Understanding the difference between restorePurchases() and the existing syncPurchases():

  • restorePurchases is a user-initiated action that should be triggered by a "Restore Purchases" button in your UI. Not programmatically in your init flow;
  • syncPurchases() is for programmatic syncing and should only be called once after authentication/login. Seems more in line with what you are trying to do.

Now, to give a bit more context/answer your questions:

 

Can I safely call `Purchases.logOut()` if the user is anonymous?

In Flutter specifically, calling logOut() when already anonymous will throw a PlatformException (logOutWithAnonymousUserError). This is SDK-specific behavior but more importantly, logOut() is often unnecessary - it's primarily designed for account switching scenarios. When a user logs in, you can simply call logIn() directly on top of the current state. The SDK will handle the identity transition appropriately.

 

Does `Purchases.logIn(userId)` guarantee that the `userId` will be used for future purchases?

Yes, once you call logIn(userId) successfully, all future transactions are tied to that userId.

However, if a purchase happens before this call, as already mentioned, it will belong to the current App User ID (which could still be anonymous).

 

Why is `originalAppUserId` showing an anonymous ID even after calling logIn()

This is expected, originalAppUserId reflects the first identity ever assigned, which in your case was the anonymous user. Even after logging in and aliasing to a new appUserId, originalAppUserId remains as the anonymous ID, by design.

The only scenario where originalAppUserId could later change is when using the legacy restore behavior ("Share between App User IDs") and automatic aliasing is triggered across multiple receipts. But that's rare and generally discouraged.

This means that:

  • appUserId represents the current active identity;
  • originalAppUserId preserves the history of how the user first interacted with your app.

 

Does `Purchases.isAnonymous` reliably detect whether the user is anonymous?

Yes, it returns true if the current App User ID is a RevenueCat-generated anonymous ID (e.g., starts with $RCAnonymousID:). It's a reliable indicator of current identity state.

 

Hope this helps clarify the expected behavior! If anything still feels off or you’d like us to take a closer look, feel free to reply here or send a couple example App User IDs via our support form (and link this post, for extra context): https://app.revenuecat.com/settings/support

 

Best,


Forum|alt.badge.img

Hello, I read about restore purchases and purchase sync method but i have some doubts regarding them.
 

This screenshot tells us restore Purchase will return us customer Info and from that we can see if user has any active plans or not.
so, restore purchase will be trigger manually by user when he was not able to see his purchases.

also, for Purchases.Sync method i am calling this method after doing any purchase or if i did any cancellation is it right approach.

sorry but in docs i didnt get much information.
 


guilherme
RevenueCat Staff
Forum|alt.badge.img+4
  • RevenueCat Staff
  • 66 replies
  • June 20, 2025

Hey ​@aman-singh-968081 ,

These two methods behave/should be used as such:

  • restorePurchases(): this is for users who tap a “Restore Purchases” button, usually in your app’s settings or paywall. It might show a system popup and is required for users who want to recover past purchases. You shouldn’t call this outside of user interaction;

  • syncPurchases(): this is a method that is more appropriate for programmatic calls. Syncing purchases should only be called after a user is authenticated in your app and in RevenueCat set up (anonymous or not, depending on your case). It checks for any purchases made on the device and syncs them with RevenueCat. You only need to call this once, not after every purchase.

If RevenueCat starts without a user ID, it creates an anonymous ID. Any purchases made before login are tied to this anonymous ID and can’t be moved to a logged-in account later.

When you call logIn(userId), RevenueCat links the anonymous user to the logged-in user (unless there’s conflicting purchase history). Future purchases will be tied to the logged-in user, but the original anonymous ID will still be shown as originalAppUserID- this is normal and keeps the user’s history intact.

If you call logOut() , it creates a new anonymous ID in the logout state. When the user is already anonymous, it throws an error. So you don’t need to call it unless you’re switching accounts. Logging in on top of an anonymous session is safe; RevenueCat handles it for you.

Hope this clears things up! If you have any more questions or run into issues, just let me know.

Best,


Cookie policy

We use cookies to enhance and personalize your experience. If you accept you agree to our full cookie policy. Learn more about our cookies.

 
Cookie settings