Every year, as Apple Worldwide Developers Conference (WWDC) 2019 takes place in San Jose, California, new features and innovations are presented to the world.
As a developer that works daily with managing products running on subscription business model, it is extremely important to be up to date to all what's new from this standpoint.
Based on sessions 302 and 305 of this year's WWDC, and also on the following documentations (reach them in the end of this post), I’ve written some valuable tips for anyone willing to strive on subscriptions taking all the advantages of Apple In-app Purchases.
To start, 3 sentences to sum up what will change your life from now on regarding App Store Connect:
- Testflight: They reinforced the value of using public links for distribution to external testers. Now they’ve done Testflight Localization and included a feedback feature.
- Feedback (screenshot and crash). Through the App Store Connect, we now can manage feedbacks.
- Localization: Included more languages and facilitated multi-country distribution. This will even be portrayed on product pages.
And now, the most expected part of this article, what is really hot and new in StoreKit and subscriptions.
While coding and testing the purchase flow, please make sure to note 3 important coding tips:
SKStorefront: Used to display customer-specific purchases (by countryCode and device type).TransactionObserver: you now can reload your product list based on StoreFront return. There is now an observer to validate that the purchase items offered are correct by region.Pre-Orders App: It will become a parameter within the receipt to know which customers pre-ordered the product.
While testing your subscriptions in your backend, please note that there will be a couple of new things regarding Server-to-Server Notifications.
First of all, please make sure you always return a 200 status code when receiving any notification.
If you don't return a status code, you may receive the same notification again (up to three times) and this will mess things around. Believe me, I've been on this place before. More than once.
Also, make sure to comply with App Transport Security (currently managed by the subscription library).
Regarding receipt data, new fields will be added:
As presented, unified receipt will now return the entire receipt on trigger [with limit of last 100 purchases] (which previously returned in / verifyReceipt). For more than 100 purchases from the same receipt (if you need this history indeed) they will stick with the verifyReceipt endpoint.
What about server-side notifications?
Regarding the notifications, there is a lot of new features (similarly, but as the same time differently, from what's been developed on Google's RTDN). Please make sure to handle the new ones (always looking for the lockup with original_transaction_id):
- DID_CHANGE_RENEWAL_STATUS: Whether the user cancels the automatic renewal. This must be the trigger for callback actions. Look at the following payload fields: auto_renew_status (true, which means it will renew, or false — always as a string). This notification is already available for the public.
- DID_FAIL_TO_RENEWAL: Renewal charge failed. This is the case with grace period (“inactive” or “billing retry”). Make sure to look for the is_in_billing_retry_period field (1 represents being charged). The expires_date is in the past, as it would be the renewal date. This notification, and the following, are not yet available.
- DID_RECOVER: This mean that the user was retrieved during retry. This may replace the renewal trigger. The renewal date may not change [unlike in Google Account Hold]. Must become subscription state as “active”.
- PRICE_INCREASE_CONSENT: User has entered inthe price change flow; this will include a field in the payload (price_increase_date). They recommend using a flag for this subscription (something like “price increase”). Make sure to track payload price_consent_status (0/1) field.
Regarding the already known notifications, they also presented some tips:
- INITIAL_BUY: Sent on user’s first in-app purchase. They recommend us to use some active / subscriber flag and make sure to enable the product usage immediately; content purchase_date_ms represents the start date of the subscription; web_order_line_item_id links purchase with other notifications.
- INTERACTIVE_RENEWAL: will always come with a CANCEL notification (in case of upgrade); however, if the user re-subscribed after churn, we will only receive the trigger from INTERACTIVE_RENEWAL.
- DID_CHANGE_RENEWAL_PREF: When user downgrades inside a subscription group.
- CANCEL: When the user cancels through customer support, but also if he has upgraded his subscription. Make sure to track cancellation_date_ms.
So, how about a full subscription lifecycle?
This was really helpful, and I do recommend you guys checking the videos listed in the beginning of this post. Regarding the subscription lifecycle itself, they also made some recommendations. When the new user subscribes, in addition to saving the original_transaction_id, they recommend us to link web_order_line_item_id to link with notifications (at this time, you will receive INITIAL_BUY’s).
In the case of renewal, there is no notification at this time. We follow with `/verifyReceipt` endpoint.
In case of subscription upgrade, CANCEL and INTERACTIVE_RENEWAL notifications will be sent. At this time, they recommend us keepting track the date of the upgrade (something like "upgradeDate").
In case of cancellation, we recommend that we no longer use / verifyReceipt, but rather DID_CHANGE_RENEWAL_STATUS notification.
For billing errors, look for DID_FAIL_TO_RENEW notifications. From then on, wait for DID_RECOVER in case billing retry works.
A small pause to talk about billing retry: They've updated retry models using ML and new techniques, and concluded that most recoveries (80%) are within the first 16 days. On any recovery, make sure to immediately release the service (never too much to repeat this). Also, please note that the renewal date will be modifie (subscription starts a new billing cycle and the paid service days are reinstated).
Another great anoucement: Billing grace period will be also available! To implement it, you will need to authorize on App Store Connect (default will be 16 days — unlike Google Play, where you may select from a few options). The verify receipt endpoint will now contain a key referred as the grace_period_expires_date in the payload. It may make sense to keep this date in your database, as well as for other platforms. For billing retry customer messaging, they reinforce the recommendation to use deeplinks to this path: apps.apple.com/billing. Now, Apple customer's can have up to 10 forms of payment, and the best way for each case will be chosen.
So, that's it?
This is just the first part of this session covering what's new about subscriptions in WWDC 2019. Make sure to look for part 2, where I will cover all about subscription offer best practices. See you soon! Any feedbacks will be appreciated!