Transcript
[ 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 ]