Subscription Offers Best Practices

Session 305 WWDC 2019

Dive into implementation best practices for Subscription Offers using StoreKit and server-side logic. Learn how to generate signatures, determine customer eligibility, and reduce churn, plus gain insights into strategies for distributing offers to your customers and utilizing Subscription Offers to give your subscribers the best experience.

[ Music ]

[ Applause ]

Good afternoon and welcome to Subscription Offers Best Practices.

My name is Ross LaBeau.

I'm an engineer on the App Store Team.

And today we're going to take a deep dive into the App Store's latest in-app purchase feature.

So Subscription Offers are an exciting new way for subscription developers to offer a discounted price to the customers for a specific duration of time.

Now we know that churn is one of the major reducers of profit for subscription apps.

And this is a powerful new tool to help mitigate churn by retaining customers or by winning back customers who have already churned.

So the coolest part of Subscription Offers is actually that you choose when to offer customers an offer and you choose which ones to show them.

So for example, if you've just received an auto-renewable subscription server-to-server notification saying the customer has disabled auto-renew, you may want to take that time, take action right then and send them an offer for say three months at half off to try and keep them engaged with your app and staying subscribed.

Now unlike introductory offers, customers can redeem as many Subscription Offers as you allow, and they can even redeem the same one more than once.

And the only qualification that the App Store puts is that the customer must be an existing or previous subscriber to an auto-renewable subscription in your app.

So today we'll go over the setup of how you create these offers in App Store Connect.

We'll discuss how to generate the cryptographic signature that you need to send up with each transaction.

And we'll talk about the new StoreKit APIs and how to use them to send up a transaction to the App Store and make a purchase.

We'll discuss the eligibility from both the App Store's point of view and also how to create your own custom business rules.

We'll offer some tips and tricks for how to distribute and market these offers to your customers.

And finally, we'll go over more business strategies for how to reduce churn.

So first, just like introductory offers, you set up Subscription Offers in App Store Connect.

Go to the In-App Purchases section under the Features tab, and just select any auto-renewable subscription.

Then click the Plus button next to Subscription Prices and select Create Promotional Offer.

There you'll put in a human readable name for the offer as well as a product code.

This product code is also known as the identifier.

And this is the unique identifier you'll use to refer to this offer from now on.

After that, it's just like an introductory offer.

You'll select the type, the duration and the pricing.

Now in addition to setting up these offers, you'll also have to set up a private key so you can generate that signature we talked about.

Now we'll go over more about the signature later.

But to create your private key, just go into the Users and Access section of App Store Connect.

Select Keys and make sure to select Subscriptions on the left.

Click that plus button.

Just enter a human readable name for your key and click generate.

When you do that, you'll see the new key in the list of active keys up top.

And you'll also see that App Store Connect has generated a key ID for it.

This again is a unique identifier which you'll use to refer to that key in StoreKit.

Now you can download your private key, by clicking Download Key of course.

But it's important to note that you can only download this key one time.

That's right, just once.

Once you do download it, App Store Connect will delete it from Apple servers permanently.

Now the reason for this is that these keys are really sensitive cryptographic information.

This private key is kind of like your identity.

It's what you use to prove that it's actually you who's authorizing this user to redeem this transaction.

So these keys are valid across your entire developer account if you use a single key for all of your apps and for all of your offers that you set up on those apps.

But if you want, you can use multiple keys.

So say you're using a single developer account to serve several different apps or different parts of your business, you can create multiple keys to segment them off that way.

So as I said, each transaction requires a cryptographic signature when you send it to the App Store to actually redeem an offer.

Now we do this to ensure that only authorized users can redeem offers.

Generate a signature using a payload which you'll also send up to the App Store.

And this signature uses something called asymmetric cryptography.

Asymmetric cryptography is a common technique where you use two keys to generate and validate a signature versus a private key which we just talked about.

We use that as a proof of your identity to sign your payload.

And the second key is called the public key.

And just as it sounds, this public key is actually okay to show to other people.

You can't generate any signature with it.

All you can do with the public key is prove that that signature was generated with your private key and matches that payload you used to sign.

So because generating signature requires using your private key, you should always do it on a secure server and never do it from the device itself because you don't want to be putting this piece of cryptographic information on someone else's hardware.

So we're going to take a look at a server that we've built using NodeJS and Express.

This is actually sample code that you'll be able to download online.

And if you don't use JavaScript, don't worry.

Everything we do here can be easily done in other languages, say Python, PHP, Java, Swift or whatever you use.

So the first step is when your app is ready to display the offer to the customer, you'll want to send up this request to the server to generate a signature right then.

In this case, the app already knows several pieces of that payload we want to sign, so we're just going to go ahead and grab them from the body of the request here.

We'll get the application's bundle identifier, the product identifier of a subscription.

And then the offer identifier for the offer that you want to show the customer.

And finally we'll get the hashed application username.

Now this is a one-way salted secure hash of some piece of identifying information about the user.

Maybe their username in your app or their email.

But it's really important that you always hash this and never send up plain text identifying information to the App Store.

You want to keep that secure on your own database.

So the next piece of the payload is something called a nonce.

This is just a random piece of data to ensure that no two transactions are the same.

We use this to prevent replay attacks and other ways of getting around it, so users can't resend the same request and get a free subscription over and over without your approval.

The App Store uses a version 4 UUID for this, so that's what we'll create here.

And next we'll get a timestamp.

This is a timestamp in the milliseconds since the Unix Epoch format.

This is a really common format to use.

You can see it's very easy to generate here in JavaScript.

And this timestamp is also used to help prevent against attacks.

It's important that each transaction you make will only be accepted within 24 hours after that timestamp.

So you don't want to be generating these signatures, you know, a week ahead of time.

The final part of the payload is the key ID.

This is that key ID that App Store Connect generated earlier.

So I have implanted a function here called GetKeyID.

All we're going to do there is return our key ID which we've stored in an environment variable.

We do that instead of committing it to our code and putting it in our repository, because it's more secure that way.

Open to fewer eyes.

And if you have just returned a single key ID but this is actually an ideal place to implement logic if you are using multiple keys.

Or perhaps if you determined that one of your keys has been compromised, someone has gained unauthorized access to it, you can go disable it in App Store Connect.

You can generate a new one and then start signing them using the new key here just by switching out logic here.

And you don't even have to push an app update, so you can keep downtime to a minimum.

So now that we've got all of the pieces of our payload to sign, we want to combine them into one piece of data to actually generate the signature from.

Now you can see here, the way we do that is by combining them into a string in this order.

We'll concatenate them using the character with the code point U2063 in between each one.

All right, I know, why didn't we just use space, right?

Well, it's really important that when you're generating or verifying cryptographic signatures, you're very exact about which characters you use, and as some of you may know, just the word space can refer to multiple different kinds of white space characters.

So we'll use this one here.

So now that we've got our payload, next step is to get the key itself.

So we have this GetKeyString for key ID.

All we're going to do in there is check, make sure the key ID matches the one that we expect.

And then we'll return the key from another environment variable.

Now here what I'm doing is using the key in a string.

It's formatted in the PM format.

This is a really common format.

This is the one that App Store Connect will send it to you in, and pretty much any third-party or first-party library will be able to handle it.

So we've got our key, we've got our payload.

We're ready to do the signing.

What we do here is we create an elliptical curve digital signing algorithm object which sounds really fancy, but it's pretty easy to do.

As you can see, just one line here using the ECKey library in JavaScript from NodeJS.

And libraries in other languages also make it quite easy.

We'll pass in our key string and we'll tell it that it's in the PEM format.

And we'll go ahead and make this cryptoSign object part of NodeJS's crypto library.

And we're going to tell it to use the SHA256 hashing algorithm.

So that's always the one you should use.

You should make sure to specify that, whatever library you're using as well.

Next we'll add our payload to this sign object.

It's just saying this is the thing we want to generate the signature from.

And finally generate the signature itself.

Now the crypto library here happens to generate the signature by default in the DER format.

Most of them do, but if your library doesn't use that by default, make sure you specify DER here.

And also instead of just having it return us back a whole bunch of raw cryptographic bytes, we're going to ask it to send us a string in a base-64 encoding.

Now this makes it really easy to transfer this data from your server to your device, and this is also the format that StoreKit uses.

So now we have our signature.

The next step is to do some verification.

You don't have to do this verification every time, but it can be really helpful to do say while you're writing this signature generation code in your own server, just to make sure there are no errors and nothing weird happened.

What this does is generates a public key based on your private key, and then verifies your signature and payload just like the App Store would.

Finally, all that's left is to send the signature back to device along with these pieces of the payload we generated here, being the key ID, the nonce and a timestamp.

So now that you've set up your server to generate these signatures, the next step is to set up your app to actually make the request and send up a transaction.

So the first thing to do is actually get the offer details, the ones you set up in App Store Connect which you'll do of course using the SKProducts request.

And we'll add some code to send the signature request to the server and run that code we just went over.

A good strategy for doing this is sending up that signature request just about when the customer is ready to make a purchase.

We recommend doing it just before you show your story [inaudible] or show this offer to the customer.

You want to do this not only because of that 24-hour timestamp limit, but also so you have the most up-to-date business logic from your own server.

So any keys you may have swapped out or you have a new eligibility information about your customers who you actually want to send an offer to or not.

You want to have all of that up-to-date.

And finally we'll handle that response from the server and then send the transaction to the App Store.

So when you make your SKProducts request, you'll notice that on each SKProduct, there is a new property for Subscription Offers.

It's called Discounts.

This is just an array of SKProductDiscount objects.

You may recognize that SKProductDiscount since it's the same model we use for introductory offers, as these are very similar.

And you can see it's got info such as the price, subscription period and such.

But we've also added two new properties for Subscription Offers.

That of the identifier this is that product code that you added in App Store Connect.

It's an optional because there's no identifier for introductory offers, so it will be nill there.

But it will be present for every subscription offer.

And we've added a type.

This is just an enum that will tell you whether this is in fact a subscription offer or an introductory offer.

However, you'll never get an introductory offer in that discounts array.

Those will still be only on the introductory price property of SKProduct.

So you're ready to display the offer to your customer.

The first step is to send a request to your server to fetchOfferDetails.

So in this example we'll pass in the application username, that hashed version, our product identifier for the subscription, and the offer identifier.

And here our server already knows what application bundle ID we're using.

So it will run all that code we went over and send us back the nonce, a timestamp, a key identifier and of course the signature itself in that base-64 formatted string.

So we're not going to go over the details of how to make a secure HTTPS request and response.

There's lots of other resources on that.

We'll just continue here inside our completion block.

What you want to do with all this information is create this new class called SKPaymentDiscount.

Now, this is SKPaymentDiscount, not SKProductDiscount.

The SKProductDiscount is what we just went over which gives you the details of the offer you set up in App Store Connect.

This SKPaymentDiscount actually holds all the details of the payload and the signature.

And it's what you use to attach to a payment to send up to StoreKit.

So we'll create one here, passing in those details into the initializer, and then just return that into our completion block and we're ready to display the offer.

So when the customer taps that they want to purchase it, we'll call this BuyProduct function here.

You want to make sure to have the SKProduct for the subscription itself, that same hashed application username that you used to generate the signature, and that SKPaymentDiscount we just made.

From there, setting it up is really simple.

Create a new SKMutablePayment with that product.

We'll set the application username.

Then you'll set this new PaymentDiscount property with that SKPaymentDiscount.

And that's all there is to it.

And simply add the payment to the payment queue as you do with any other in-app purchase.

So in addition to this, we've added a few new SKErrorCodes specific for Subscription Offers.

The first one is invalidOfferIdentifier.

As it sounds, this will be returned if the offer identifier you tried to use can't be found of if you've disabled it yourself in App Store Connect.

The next one is invalidOfferPrice.

So the App Store actually does some price validation for pay-as-you-go Subscription Offers.

We basically want to make sure that the offer has a lower price than the base subscription itself.

So this could happen say if you set up an offer and then later you've reduced the price of the base subscription.

We want to make sure that's actually a discount.

However, the App Store does not do price validation for pay-up-front Subscription Offers.

The reason for that is we want to empower you to create bundles, for example if you're starting a new subscription-based game, you may want to give some customers an offer that's like three months of subscription access plus an additional piece of legendary gear or experience boosters or something like that that offers more value than just three months of subscription.

The next error is invalidSignature.

We'll send this back if the signature you sent up can't be validated against the private key you've told us you used.

Or if it can't be validated against the payload that you sent up so something was switched in between.

Finally, there's missingOfferParams.

You'll get this if you forget to send up or if you send up say an empty string version of any of those pieces of the payload.

The most common example of this is forgetting to set the application username on the SKMutablePayment.

So all this code we just looked at is actually available online.

As I said, that NodeJS server, you can go and download right now and run it locally.

It's a ready-to-run app.

And the Swift code we looked at is available on these documentation pages, so even more detailed documentation about it.

Plus if you have any questions, please stop by our lab just after this at 3:00.

So now that we've talked about how to generate a signature and how to actually send up a transaction to StoreKit, and you may be thinking, "Great, but who do I even send these offers to?"

Well, the App Store, as I said, only enforces a single rule.

Each customer who wants to redeem an offer must have previously subscribed to an auto-renewable subscription in that app.

So this includes any auto-renewable subscription.

It doesn't have to be the same one that you're trying to make an offer for.

And it can be from any subscription group.

Once again, it doesn't have to match.

This includes both current subscribers and those who already lapsed and churned out, so you can use this for both retaining customers as well as winning those back.

And customers will be eligible from the very first subscription period.

And this includes if they're in a free or a paid introductory offer.

With that in mind, the way that you can check to make sure that a customer is actually eligible is of course looking at the receipt.

So it's actually pretty easy.

You just want to look at the in-app array or the latestReceiptInfo array if that's available.

And just iterate through all the objects there.

You'll want to look at the product ID for each one as you go through.

If you find a product ID that is an auto-renewable subscription and you know that they have already subscribed and thus they're eligible to redeem any subscription offer on any auto-renewable subscription in that app.

But this is just the App Store's version of eligibility.

It's pretty simple and we leave almost everything up to you.

You almost certainly want to implement your own business rules for determining which customers you want to show offers to and what offers you want show them.

So to give you some great tips and insight on how to do that, I'd like to invite my colleague Michael to the stage.

[ Applause ]

Thanks, Ross.

[ Applause ]

Good afternoon.

My name is Michael Gargas and I'm a technical advocate on the App Store Commerce Team.

And I'm really excited to discuss with you all today eligibility, distribution and reduction of voluntary churn using our great new feature: Subscription Offers.

As a developer, you may have asked yourselves some of these questions about customer subscription activity inside of your applications.

Things like, when do the majority of my customers churn?

Has a customer churned?

Or, why may a customer have cancelled their subscription?

As Ross mentioned, you can determine basic eligibility for Subscription Offers via the app receipt.

In the in-app array and latestReceiptInfo you will have the previous subscription activity for that subscriber or customer.

Additionally, we will provide this information via our updated server-to-server notifications.

But that's just about what product the user or customer has been subscribed to.

Inside of the app receipt, we provide lots of additional, valuable customer subscription information.

Things like the subscription status will my customer renew in the subsequent subscription period?

Or is my customer in a failed payment state?

We also provide unique identifiers such as the original transaction ID and web order line item ID in order for you to determine a unique subscription for a specific customer on your server.

We provide subscriber dates such as the subscription start and expires for the current period as well as all previous renewal period for that customer.

And we provide subscriber intent, letting you know if someone cancelled their subscription, why did they cancel it?

And if they requested a refund, was it an issue with your application or something else?

Now last year in Engineering Subscriptions, we discussed this concept of storing additional user data from the app receipt.

Here we have an example of looking at the customer's expires date, storing that on your server and determining that this customer is no longer eligible for subscription service.

But we also built upon that and we talked about storing additional subscriber status fields from verifyReceipt.

And then parsing out specific fields from that response, such as the auto-renew status.

Additionally, we recommend that you now save status changes from our server-to-server notifications as we are including the unified app receipt in those server-to-server notifications as well.

Now this is the data that Apple is providing you about subscribers and customers in your application.

As a developer, you have a lot of additional information that Apple does not about user subscription activity inside of your application.

By taking this information and marrying it alongside the JSOJN data that we provide after a purchase or renewal, you can begin to curate specific offers for cohorts of customers.

And then over time, you can monitor how those cohorts of customers respond to offers using key subscription metrics such as conversion, engagement, retention and churn.

So to visualize this, let's take a look at an example user table on your servers.

Here we see users ordered by user ID and original transaction ID, which is the parent unique identifier for any subscription purchase for a specific customer.

But as we said, you can begin to layer in additional customer information that is found in the app receipt, such as the user's auto-renewal status and billing-retry status.

But you shouldn't stop there; you can combine that with information that you have about customer activity inside your application.

Here we have an example of content consumed.

This could be videos watched, articles read, stories saved, anything.

By taking a look at this information, we're able to determine which users or customers are eligible for Subscription Offers and which are not.

Taking this one step further, we can begin to store additional information such as the renewal periods, number of billing errors that customer has experienced, and if they're eligible for specific types of offers.

As Ross mentioned, you can have up to ten Subscription Offers per subscriptions queue, allowing you to essentially create up to ten different cohorts of users to identify and distribute Subscription Offers too.

If we take a look at three example customers in your server, you'll see that based on their subscription activity, we've been able to make them eligible for things like a win-back offer where a customer disabled auto-renewal during a free trial and subsequently churned out of their subscription.

Or a retention offer, someone who's currently subscribed but has disabled auto-renew and you want to show them a retention offer in order to keep them subscribed to your service.

And lastly, something like an upgrade offer.

Finding your customers who have consecutive renewals on maybe a lower tier of subscription such as a monthly, and then providing them a subscription offer to upgrade them to something like an annual [inaudible].

So that's determining customer eligibility with a little bit more information than just looking at has the customer previously been subscribed to my subscription product within my app.

Once you've built this detailed customer eligibility, the next step in this is distributing your Subscription Offers.

Let's take a look at the path a subscription offer might take.

First, as we discussed, you have to identify which customers or cohorts of customers are eligible for a subscription offer.

You then engage with those customers, you fetch that information from the App Store and you present it to your users.

At which point hopefully the customer will purchase and engage with the subscription offer.

If we go back to our identification, you can see that we have marked three different users eligible for three different types of Subscription Offers.

So where do you present this information?

Well, if the customer is still engaged with your application but is in an unsubscribed state, you can present the Subscription Offers directly to them with inside the application via messaging or local notifications.

It's important to understand that your application is the landing point for all offer consumption.

So it's important that when you drive a user to engage with an offer, that you think about that call to action and make sure you clearly state the value proposition of the subscription offer as well as the terms that they'll be agreeing to.

And as always, make sure that you're in compliance with the latest app review guidelines around subscriptions.

But that's if the user is engaged inside your application.

What happens if the user's no longer launching the app?

How does this journey change for a subscription offer?

Here we can see the identifications phase, but we also need to understand the ability to circulate Subscription Offers outside of your applications.

And then presenting those Subscription Offers outside of the App Store in order to or outside of your application in order to drive users back in.

So let's talk about presenting offers outside of your applications.

You can use your existing external channels to distribute calls to action for Subscription Offers.

Things like your already-existing paid advertising or email marketing.

And then using universal links, you can drive users back into the application from these external channels and identifying which subscription offer they are potentially available to receive.

For more information on universal links, I strongly encourage you to check out our What's New in Universal Links session, which is available in this year's WWDC application.

So we've now talked about determining customer eligibility and then distributing Subscription Offers to those eligible customers, either inside of your applications or via your existing external channels.

So next, let's talk about some tactics or strategies that we can use with these Subscription Offers in order to reduce churn.

During Engineering Subscriptions last year, we spoke about voluntary churn, the act of a customer cancelling a subscription during a subscription period.

Voluntary churn is customer choice to leave your subscription product.

This differs from involuntary churn where no choice was made and it was a result of a billing issue.

Last year we gave you some tactics such as presenting alternative subscription products to users who voluntarily churned.

But that's not a great way to win customers back.

And so this year we're recommending the following.

We want you to analyze your customer subscription behavior using data from the app receipt as well as information you have around how subscribers are consuming content inside your app.

We want you to take this information and identify specific customer cohorts.

And then distribute your Subscription Offers, relevant Subscription Offers hopefully, to these different customer cohorts.

Now in thinking about Subscription Offers, oftentimes we just think about the concept of winning a customer back that has been unsubscribed.

But we want to expand upon this a little bit and talk about five other ways that you could implement Subscription Offers for your subscribers.

You can leverage Subscription Offers for retention marketing.

When you see someone has opted not to renew in the subsequent subscription period, you can try to retain that customer with a subscription offer.

If you have information that leads you to believe at some point in time this customer may churn, you could offer them a save offer, essentially predicting that the customer may churn out of the application.

You can look at customer subscription activity and products that they're currently subscribed to in the app receipt and you can offer Subscription Offers to upgrade or downgrade that customer within subscription groups.

Additionally, you can use Subscription Offers to appease customers that may have had a poor experience inside your application.

And you can also use Subscription Offers to reward your most loyal subscribers.

So let's take a look at each one of these and show how you can display these Subscription Offers to customers within your application.

First, let's take a look at a win-back example.

Here we have a subscriber that has purchased on the 26th.

Midway through the subscription, this customer opted to cancel.

They called Apple Care and they stated that they were not happy with the service and they wanted to have a cancel and a refund.

As we spoke to you in our earlier session today, we let you know about this information via the receipt with fields such as cancelation date letting you know immediately when the refund and cancelation has taken place.

And cancelation reason so you can find out if it was a reason with your application or another issue.

But we also send this information with our newly-updated server-to-server notifications so that you can keep a pulse on your subscribers and customers in real time.

Letting them know that they should see alternative Subscription Offers.

When we think about this conceptually, we want to take the information from the receipt or server-to-server notifications such as the auto-renewal status, expiration intent, so on and so forth.

And we want to store that on the server.

Flagging customers available for something like a win-back offer this is your signal to display the subscription offer to your customers.

As an example, here you can see a call to explore with us again for a customer that may have churned out, and you as a developer are now attempting to win that customer back.

We also have a developer example from iTranslate who's using Subscription Offers to provide another free month for their customers.

These are great implementations of the subscription offer feature.

Now let's talk about retention the act of retaining a subscriber who is still currently subscribed to your application.

Here we see a customer has purchased their subscription.

And partway through, they have opted to navigate to our Apple Manage Subscriptions infrastructure and cancel the subscription.

Now, before, we updated our server-to-server notifications, you would find this information by re-validating the receipt with Apple and seeing that the auto-renew status has changed from a one to a zero.

This is your signal that your customer will not renew in the subsequent subscription period.

But as of the release of Subscription Offers, we are now going to send a status or server-to-server notification letting you know that this customer will no longer renew.

And we send this both when a customer disables their renewal status and when a customer enables their renewal status.

This is your signal to let them know that they shouldn't leave yet, and potentially check out what's coming in the future for your subscription product.

If we look back at the example of the customer in your database, you can see that we've updated the field and made them available for a retention offer, at which point when this customer returns into the application, either driven by your marketing or just use, you can prompt them with a subscription offer letting them know that they can subscribe now.

"Please explore with us again.

We've noticed that you won't be staying with us next month."

This is a great call to action to win and retain customers back into your subscription application.

We also have an example from Ultimate Guitar offering a free month and 50% off, letting customers know that this offer is for today only.

So that's retention.

Let's take a look at an upgrade example.

Here, we see a subscriber that has opted to downgrade their subscription on April 1st.

As you know, we will surface the upcoming renewal product in the receipt.

You can choose to parse that out of the response and store it in your servers.

And we also send you the server-to-server notification letting you know that that customer has opted to downgrade their subscription.

If a customer has selected another product, you understand what they've been consuming on the higher tier of service, whether it be an annual subscription where there's a discount included by subscribing for a longer duration of time, or a higher tier of service that the lower tier no longer has access to specific pieces of content that you know that customer was watching.

So in this example, when you see a customer has downgraded, you can mark them eligible for an upgrade offer.

When that customer returns back into your application, you can display a subscription offer with a clear and concise call to action stating what the offer is and what they'll be getting by accepting it.

We also have a great developer example DashLane, which is trying to get customers to upgrade again to their premium tier of service.

So that's an upgrade example.

Let's discuss customer service.

We all try our best to make perfect software, but obviously there are times when users may experience an issue or outage or some type of bug or downtime within your subscription product.

This user may decide to contact you through your support channels and let you know that they had a less than optimal experience.

If we reflect back on our user table on your servers, if your customer service agents have the ability to look up that unique customer, identify them as offer-eligible, they can then instruct that customer to relaunch the app because they're now offer-eligible.

You may potentially want to display the subscription offer on your settings screen.

Here we see an offer to redeem your free month and an apology for any interruption in service that that customer might have experienced.

When engaged upon, the customer is shown a subscription offer with a clear and concise call to action.

This is a great way to keep your customers happy and appease any that have had a poor experience in your application.

You can also use Subscription Offers to reward your most loyal subscribers.

Here we see a customer that is set to hit their 11th consecutive renewal.

This is obviously an amazing subscription customer for you as a developer.

So we want to reward them.

If we look at our user tables on your servers, you'll see that we've been capturing renewal periods.

And this is found via storing information from the app receipt.

If we reflect back to the timeline of the customer, we now can mark this customer as loyalty offer-eligible because they've crossed a threshold with which we feel we want to reward those customers.

The next time that customer launches the application you can reward them for their service and their loyalty by offering them something like a one month free.

Here we see a developer example of Luminary Premium rewarding their early Premium subscribers with an additional two months of service if they activate now.

Lastly, let's talk about a save offer.

Save offer is very similar to a retention offer.

Except you as a developer may have information that leads you to believe that this customer may churn.

It's before they've opted to take the action to navigate to Manage Subscriptions and potentially cancel.

If you see that one of these customers that you feel has a propensity to churn engages with maybe a deep link that you've placed in your application settings to drive that customer to Apple's Manage Subscriptions infrastructure, you could alternatively decide to show a subscription offer to that customer before driving them into the Manage Subscriptions interface.

So those are six different examples of how you could use Subscription Offers to minimize voluntary churn inside of your applications.

But this is just the beginning and I'm really excited to see what amazing ideas you as developers can come up with to provide a great customer experience to your subscribers within your applications.

After Subscription Offers have been distributed to customers, the next step in this is analyzing the performance of your Subscription Offers.

And today, I'm excited to announce that we've launched two new reporting dashboards that are meant to help you analyze subscription activity: a Subscription State Dashboard and a Subscription Event Dashboard.

Let's take a look at App Store Connect.

If you navigate to the sales and trends module, you will see that we've launched a Subscription State Dashboard.

This dashboard allows you to understand your subscriber base over time.

For example, you'll be able to see exactly how many subscribers you have in say a standard price versus an introductory offer or a subscription offer.

This is a great tool to see and analyze your subscriber growth over time and across different territories.

Additionally, you can also use this dashboard to see what offers are being taken advantage of by your customers inside of your application.

We've also launched the new Subscription Events Dashboard.

This allows you to see user subscription or customer subscription activity over time.

You can use this to see how well customers are converting to the standard price of your subscription, or you can even use it to understand the ratio of say new subscribers to returning subscribers.

By applying the right filters, you can also use this to specifically see how a particular subscription offer won back previously unsubscribed users and then you can use these insights to inform and optimize your Subscription Offers and how you're distributing them over time.

In summary, if you take anything away from this session today, it would be to obviously implement Subscription Offers.

But you must implement them in your app as well as on your server.

We strongly encourage you to implement detailed customer eligibility rules.

By using information from the receipt, our updated server-to-server notifications so that you can keep a real-time pulse on customer activity.

As well as the data that you as developers have that Apple does not.

Then we encourage you to present Subscription Offers to customers contextually.

We hope that you do this so that you provide the best customer experience inside your application.

And lastly, after your Subscription Offers are deployed to customers, you want to use our two amazing new reporting dashboards to monitor the performance of these offers over time.

For more information, I'd like to welcome you all to our lab immediately following the presentation today at 3:00 PM.

And I'd like to thank you all for attending the Subscription Offers session and I'm really excited to see what you guys can bake into your application to provide a great experience for our shared customers.

Thank you.

[ Applause ]

Apple, Inc. AAPL
1 Infinite Loop Cupertino CA 95014 US