iOS Subscription upgrades, downgrades, and service levels

iOS subscription levels and events like subscription upgrades and downgrades can cause a lot of confusion. This guide summarises everything you need to know on these subjects.

First, you need to understand the following two concepts used by Apple on the App Store Connect:

  • Subscription group
  • Service Level

What is a subscription group?

A subscription group is a set of in-app products that unlock access to a set of app’s features.

You have to add a product to a group when you are creating it. So you must have at least one subscription group. One group is enough in many cases for most apps. A group has the following important characteristics: 

  • A user can have only one subscription within one group
  • A user can use the introductory offer only once within one group

It is recommended to avoid creating more than one group with products that unlock the same access to your premium features. In this case, a user can occasionally subscribe twice to get essentially the same features. 

You can find your available subscription groups in your App Store Connect account. Choose your app and select Subscriptions Groups under the In-App Purchases title.

Subscription groups

What is a subscription service level?

In-app products unlock premium access on your app for your users. For example, in some well-known apps the product unlocks access to the following app service:

  • YouTube Premium
  • Netflix Standart, Netflix Premium
  • Duolingo Plus

You have to manage the logic of user access on your app on your own or let Qonversion Permissions handle that for you. But the App Store provides a subscription service level essentially to distinguish what level of premium access a user gets for each product. App Store needs to know a subscription service level for each product to understand how to handle a subscriber if he switches between the products. We’ll dive into that in a moment.

But first, let’s have a look at how to manage in-app product subscription levels on the App Store. 

Navigate to Subscription Groups in your App Store Connect account. You can change the order of the in-app products and combine them by dragging and dropping. Have a look at the video below:

The number you see to the left of your products is a subscription level. So far we have shown that in-app products within the subscription group may have different service levels. After a user purchases any of the in-app products he can make an upgrade, downgrade, or cross-grade to a different product within this subscription group. A user can navigate to his subscription settings and see all of the available subscription options within the subscription group of his current subscription.

Subscription Upgrade

Subscription upgrade happens when a user choses a subscription with higher service level than his current subscription. For example, a user switches from standard (level 2) subscription to premium (level 1) subscription as shown on the picture below. A user is refunded for the remainder of his current subscription (remainder of the weekly subscription) in case of upgrade. And the new monthly subscription price is charged. The upgrade is applied immediately.

Subscription levels

Another example of an upgrade (using Apple Music app) would be switching from Premium Apple Music to Family Premium:

Subscription upgrade

How to handle subscription upgrade in a user receipt?

When a user upgrades a subscription, the following two fields appear in transaction responseBody.Latest_receipt_info in user receipt:

  1. is_upgraded field equals true.
  2. cancellation_date field contains the date of the original subscription cancellation and it’s also the date of the partial refund for the original subscription.

You must check that both of these fields are provided. cancellation_date field alone appears in case of a full refund not connected to an upgrade.

"latest_receipt_info": [
        {
            "quantity": "1",
            "product_id": "product.99.trial.3d",
            "transaction_id": "10000000306492965",
            "original_transaction_id": "10000000306492965",
            "purchase_date": "2020-01-10 04:13:34 Etc/GMT",
            "purchase_date_ms": "1578629614000",
            "purchase_date_pst": "2020-01-09 20:13:34 America/Los_Angeles",
            "original_purchase_date": "2020-01-10 04:13:34 Etc/GMT",
            "original_purchase_date_ms": "1578629614000",
            "original_purchase_date_pst": "2020-01-09 20:13:34 America/Los_Angeles",
            "expires_date": "2020-01-17 04:13:34 Etc/GMT",
            "expires_date_ms": "1579234414000",
            "expires_date_pst": "2020-01-16 20:13:34 America/Los_Angeles",
            "cancellation_date": "2020-01-19 08:27:22 Etc/GMT",
            "cancellation_date_ms": "1579422442000",
            "cancellation_date_pst": "2020-01-19 01:27:22 America/Los_Angeles",
            "web_order_line_item_id": "100000246215806",
            "is_trial_period": "false",
            "is_in_intro_offer_period": "false",
            "in_app_ownership_type": "PURCHASED",
            "subscription_group_identifier": "1000000",
            "is_upgraded": "true"
        }
]

If you want to calculate the prorated refund value you have to divide the unused period of the subscription by the subscription duration and multiply it by subscription price. You can calculate the unused period as the time between the cancellation_date described above and the original subscription expiration date:

transaction_value / (expires_date_ms - purchase_date_ms) * (expires_date_ms - cancellation_date_ms)

where transaction_value is the subscription price.

Subscription Downgrade

Downgrade happens when a user switches to a lower service level subscription from a higher service level subscription. The change is applied at the end of his current subscription period. The original subscription lapses at the time of his next subscription renewal, and the new lower service level subscription starts.

How to detect subscription downgrade in a user receipt?

You have to check the auto_renew_product_id field in responseBody.Pending_renewal_info

The value of this field must be different from product_id:

 "pending_renewal_info": [
        {
            "auto_renew_product_id": "product.99.trial.3d",
            "original_transaction_id": "10000000306492965",
            "product_id": "product.49",
            "auto_renew_status": "1"
        }
    ]

You can also use Apple’s server-to-server notifications to detect any planned subscription changes. This information is contained in the notification of type DID_CHANGE_RENEWAL_PREF. You can check our article on handling Apple server-to-server notification for more details.

Subscription Cross-grades

Cross-grade happens when a user switches between in-app subscriptions with the same service level. Cross-grade can have different behavior depending on the durations of the subscriptions.

Same duration cross-grade

Cross-grade between subscriptions with the same duration is handled exactly the same as an upgrade.

Different duration cross-grade 

Cross-grade between subscriptions with different durations is handled similar to downgrade. The original subscription is active until the next renewal date when a new subscription starts.

Handling in-app subscription events is time-consuming. You have to build a complex back-end logic on top of the server-side receipt validation. The good thing is that you can hand it over to Qonversion. Qonversion provides 

  • an out-of-the-box server to validate user receipts
  • in-app subscription analytics
  • integrations to send accurate subscription data where you need it

It requires just a few lines of code to set everything up in your app.