Architecting Subscription Entitlement Engine

This article is based on the WWDC 2020 presentation and provides guidance on a subscription app’s entitlement architecture. It would be useful for engineers, server-side teams, and data analysts.

Understanding the subscriber journey

In the past, it was enough to check Product ID, and the expiration date of receipt to check if a user has an active subscription and grant premium access. But with Apple adding Billing Retry state and Billing Grace Period, this combination of user receipt fields is not enough.

Let’s look at the following example. For a subscription purchased on May 1, Apple will send a server-to-server notification indicating the initial purchase. This subscription will be renewed automatically by Apple on June 1.

The subscriber canceled the subscription on June 17, i.e. he navigated to the App Store manage subscriptions settings and turned off auto-renewal of the subscription. Apple sends server-to-server DID_CHANGE_RENEWAL_STATUS notification letting you know that the subscriber has changed the auto-renewable status. The subscription will expire on July 1 in this case. It will be indicated in the receipt in the expiration_date and expiration_intent fields.

Voluntary Churn

Now let’s look at another case. Let’s assume that Apple was not able to charge the user card at the time of the first renewal i.e. on June 1. In this case, you will get the first server-to-server DID_FAIL_TO_RENEW notification on June 1. And let’s assume that the user navigated to the App Store manage subscriptions settings and update their payment method on June 15. At this point, Apple will deliver you the server-to-server DID_RENEW notification indicating that the subscription was renewed. Apple will continue to renew this subscription on the 15th of each month going forward. This case is illustrated on the calendar snapshot below.

Billing Retry

Now let’s assume that you, the developer of the app, have enabled Grace Period in App Store Connect settings, and Apple was not able to renew the subscription on June 1. With grace period enabled any recoveries which happen within 16 days will keep billing date continuity. So Apple will continue to renew this subscription on the 1st going forward.

Grace Period

From the examples above you can see that each subscriber journey is unique. To be able to handle user access in your app it’s important to understand all of the receipt fields, Apple server notifications, and different subscription states that result from different customer actions. 

Deep knowledge of the data within the receipt is crucial to understand subscription states.

Each renewal event in the receipt is a static entry showing that subscriber state at that moment in time. Using these states provides you the information needed to take the relevant actions in the app. Here is the summary of available states and sub-states:

Subscriber States

It’s necessary to look at the most recent receipt data. If you are just checking the expiration_date you might conclude that the subscription is active. But by looking a bit deeper you can get significantly more data. Here are just a few examples:

  • You can find an opportunity for retention subscription offers based on the auto-renewal status and the current subscription product.
  • In case a user is in a grace period you can introduce the count down alert in your app showing when the subscriber will lose premium access.
  • You can also leverage receipt data to win subscriptions that have already expired back. Check the exact reason why the subscription expired and provide a better offer through a push notification. A push notification will need to deep link a user to the appropriate payment screen with the special offer.
Win lapsed subscribers back with push notifications

Subscription Entitlement Engine

Access to content is the fundamental basis of subscription entitlement. And access may vary depending on the level of service, geography, and other factors. As was shown above, a subscription can have several states. The entitlement process needs to account for all of the potential subscription states. 

To be able to manage user access, power tailored communication with your users, win lapsed users back, and so on, you need to build server-side logic that digests all subscription state data. Apple refers to this as the Entitlement Engine. (Note: Apple provided the sample Entitlement Engine code in node.js.)

The data digested by the Entitlement Engine is used to calculate the user’s entitlement. The Engine needs to calculate the correct entitlement info using the receipt data, app insights, and server-to-server notifications. The output of the Entitlement Engine is a simple JSON payload that you can use to entitle service and update your user database.

Key processes of the Entitlement Engine:

  • Prepare data: The app receipt is the source of truth for transactional data. So you need to fetch the most up-to-date info for the receipt from App Store to make sure it’s not outdated. Get server-to-server notifications.
  • Synthesize data: Digest transactional data, detect where the user is in the subscriber journey. Add data from the app, for example, hours watched, upcoming events a user is interested in, etc.
  • Condense the data into actionable insights, that will be used in the response.
  • Build the Response Object
Entitlement Engine Response Object

Distinguish cohorts of subscribers based on the subscription state and sub-state as shown below. 

You can assign positive values for cases where you would unlock access and negative values for cases where access would not be provided. Add substates using the decimal values to enhance the entitlement process. By combining state and substate you can have a value to represent the exact state of the product. You can send this value to the client. It can be used as a simple signal to unlock the service when it’s positive.

Subscription states and sub-states – Entitlement Code Example

For example, entitlement code 4.1 represents a subscriber who is currently in a trial period and has disabled auto-renewal: 

Another example, based on 4.0 code (user with standard subscription turned-off auto-renewal) you can trigger a retention message and link the user to a specific product offer.

Entitlement code example: trigger promotional offer 

Conclusions

A highly available entitlement engine will allow you to manage user access, tailor your customer communication, increase your app retention, and win lapsed subscribers back. Additionally building the server-side entitlement engine will allow you to support cross-platform entitlement logic for your web or Android apps. Yet it’s a lot of work to build and support such infrastructure.

If you want to focus on building your product, instead of building a complex server-side engine to handle the subscription logic of your app, there is a solution for that. We at Qonversion.io provide a cross-platform entitlement engine for your app out of the box. Qonversion handles receipt validation, receives server-to-server notifications, and provides you with simple output to handle user access and power your subscriber communication. On top of that, you get comprehensive subscription analytics, real-time app monitoring dashboards, integrations with 3rd party platforms like AppsFlyer, Amplitude, Facebook Ads, and more.