How to know when user upgrades/downgraded/crossgrades their subscription on the client

Hey, in our app we show post-purchase flow when a user purchases a subscription and its appearance should depend on the type of purchase: upgrade, downgrade or crossgrade. I found a way how to get this type on the backend side but can not figure out how to get this within the app. I see that Transaction has isUpgraded property but it is always false even if I move from a lower service plan to a higher one. So, I have two questions:

  1. Is this actually possible to know on the client when the user upgrades, downgrades or crossgrades?
  2. If yes, then how?

Thanks

What is an upgrade is determined on your product setup in App Store Connect in the subscription group.

Please confirm your setup in App Store Connect aligns with your expected “upgrade” scenarios.

For an upgrade to occur, the current plan must be at a “lower” level, or if they are the same level, then the duration must be the same in order for the change to be an upgrade. Upgrades just mean the plan change goes into effect instantly and customers is billed in full for new plan and issued a pro-rated refund for the previous plan.

Levels in a group are defined with “1” as the highest and you can move products to 2 to n. Lower number is “higher” level of service. E.g. 2 to a 1 is an upgrade. 1 to a 2 is a downgrade. 5 to a 1 is an upgrade.

See this doc for more info: https://help.apple.com/app-store-connect/en.lproj/static.html#dev75708c031

This is precisely what we have - 1 subscription group with 4 plans:

  • 1 Advanced monthly
  • 1 Advanced yearly
  • 2 Basic monthly
  • 2 Basic yearly

So I want to know when a user changes their plan

  • from Basic Monthly to Advanced Monthly (upgrade)
  • from Advanced Monthly to Basic Yearly (downgrade)
  • from Advanced Monthly to Advanced Yearly (crossgrade)

With this setup, should I have isUpgraded == true in case of an upgrade? How in the code can I figure out other scenarios?

I tried some digging into it, to get the information about downgrade from purchase history, but with no luck.

Steps to reproduce:

  • do purchase of subscription A level 1 (monthly = 5mins)
  • do purchase of subscription B level 2 (monthly)
  • look into Transaction.all
  • note: only print last 5 transactions otherwise log will become long and unreadable
 for await result in Transaction.all {
                do {
                    counter += 1

                    let transaction = try checkVerified(result)

                    if counter < 5 {
                     print("Original Transaction Identifier: \(transaction.id)")
                     print("Product Identifier: \(transaction.productID)")
                     print("purchaseDate: \(transaction.purchaseDate)")
                     print("-------------------------------------")
                    }
  • when I try to purchase subscription B twice, the error already-purchased occurs, so StoreKit somehow has to know it is already purchased.

Can it be only Sandbox/development thing? Is there any other API I'm missing? Any other ideas?

Well...we also have the 2x2 setup - two plans, basic and pro, with two periods: monthly and annual. We obtained information about changing subscription types on the client side by implementing our logic.

Using RenewalInfo, we can retrieve autoRenewPreference, which represents the next subscription product ID. When a change occurs, we compare it to the new ID, and then it's a matter of implementing an if-else code structure to cover all possible states (DOWNGRADE, UPGRADE, CROSSGRADE, and NO_INFO).

Like this (but more complex):

 if ((isCurrentMonthly && isNextAnnual) || (isCurrentAnnual && isNextMonthly)) {
      return ChangeSubscriptionType.CROSSGRADE
    }

Disclaimer: Don't know if it's the best solution, but it's 100% working for us ;).

How to know when user upgrades/downgraded/crossgrades their subscription on the client
 
 
Q