Transcript
>> Good morning, everyone.
[ Applause ]
Welcome to What's New in
StoreKit.
My name is Pete Hare, and I'm an
engineer on the App Store Team
here, at Apple.
In-app purchases represent a
huge percentage of revenue,
generated by apps on the App
Store.
So, to be able to implement them
and to sell content to your
users.
And to provide a great
experience throughout this
process, is becoming
increasingly important for you
and your business.
Now, we're working on ways for
you to do all of these things,
even more effectively.
And we're here, today, to talk
to you about some enhancements
to the StoreKit framework.
StoreKit is the framework that
powers in-app purchases, amongst
some other store related
abilities.
But we've got some new
advancements in iOS 11.
Firstly, you're going to have
the ability now, to promote your
in-app purchases directly in the
App Store app.
So, a user can buy an in-app
purchase and complete that in
your own application.
Secondly, we're introducing some
enhancements to the
subscription, auto-renewable
subscription flows.
We've got new server to server
subscription notifications.
This is really going to make
your lives easier if you're
dealing with auto-renewable
subscriptions.
Yeah.
[ Applause ]
We've also got some new detailed
subscription status information
when you're dealing with service
side management.
This is going to give you much
greater insight into some of
those business questions about
individual users and their
subscription states.
We also, introduced earlier this
year, the ability for you to
respond to user's reviews on the
App Store.
And along with that, we have
some new enhancements in the
ways you can ask for ratings and
reviews.
Now, before we go into some of
these new features, I'd like to
start with an overview of the
in-app purchase process.
So, let's look at implementing
in-app purchases in your
application.
Now, in app purchases haven't
really changed much.
They were introduced in iOS 3.
An in-app purchase is really the
ability for you to sell digital
content or a service inside your
app.
So, when it comes to physical
goods or services, it's not
really appropriate for in-app
purchases.
We provide things like Apple
Pay, and you can implement your
own payment systems to
accomplish selling physical
goods.
But when it comes to digital
services, that's what in-app
purchases are good for.
We have four different types of
in-app purchases that you can
use.
Firstly, we have consumable
products.
Now, this type of in-app
purchase is the kind of in-app
purchase that can be consumed,
as the name suggests, and used
up by a user.
So, this might be gold coins in
a game that a user buys and
maybe spends.
And it doesn't persist around
subsequent restores or new
devices.
The second kind is a
non-consumable product.
It's a little different than the
consumable product in that it
does persist.
So, this might be more
appropriate for things like
unlocking a pro feature in your
application, or maybe,
downloading a level pack for a
game.
We also offer two different
types of subscription products.
We have the nonrenewing
subscriptions.
Now, as the name suggests, this
is the type of subscription
product that doesn't
automatically charge the user at
the end of the billing period.
You can kind of think of this
one like a consumable product
with an expiry date on it.
And of course, the last type is
the auto-renewable
subscriptions.
So, we open the categories of
auto-renewable subscriptions to
a much wider array of
categories, last year.
And have seen some great uptake
of that.
In this particular talk, we're
just going to focus on these
first two types, though.
Mostly, consumable and
non-consumable.
We're going to be going into
subscriptions in much greater
detail, in the Advanced talk,
this afternoon.
It's at 1:50 p.m. in the Grand
Ballroom A.
So, if you're dealing with
subscriptions in a particularly
service side environment, I
definitely encourage you to come
along to that session.
We've got some great new
enhancements, there.
So, let's look at how to
implement in-app purchases in
your application.
It starts with loading up your
in-app identifiers in your
application.
We're going to dive into each of
these steps in a little more
detail.
But I'll just give you an
overview, now.
Using those in-app identifiers,
you can fetch localized product
information from the App Store.
And once you have that localized
information for the products,
you can display in-app UI to the
user.
This gives the user an
opportunity to tap that Buy
button and agree to purchase it,
at which point it's up to you to
go ahead and request a payment.
The user then, elects to buy
your in-app purchase and
authenticate the payment.
And it's up to you, to then
process the transaction that
comes back from StoreKit.
Once the transaction's been
processed, it's up to you to
unlock the content.
Make that in-app purchase
available to the user.
And finally, the last step is to
finish the transaction.
So, let's dive into the first
step, loading the in-app
identifiers.
The in-app identifiers are
really just kind of product
skews that you set up in iTunes
Connect.
Each product that you sell has
its own identifier.
And when it comes to loading
these in your applications, you
can do it a couple of ways.
Firstly, you can just bake them
directly into your application.
So, in this case, I've just got
an array of strings.
Or the other way, of course, is
to maybe fetch them from your
own server.
Either one of these techniques
will work, but the important
thing is that you just have this
set of strings, these in-app
identifiers that you can use to
go ahead and fetch product
information for.
Which is the next step.
So, if you have these, it's just
a simple step to go ahead and
load up the product information.
Let's look at the code for it.
You take that set of identifiers
and you pass it through to an
SKProductsRequest initializer.
Set a delegate on that request.
And then, just kick it off using
the start method.
Now, you've set a delegate
method on this so you'll get a
response in the didReceive
response callback.
So, inside this callback you'll
receive an array of products
that match those in-app
identifiers that you've sent up
in the request.
Now, you can loop through these
products.
And we'll just highlight some of
the fields that are included on
these product objects.
There's a localized title and a
localized description for that
product.
There's also localized price
information about that product
in the store that, that user's
logged into.
And we also have the information
here, about any downloadable
content that might be associated
with this product.
So, one more important point,
here, just to highlight, is that
you shouldn't cache the
SKProduct that comes back in
this point.
It's really important that you
get up to date product
information, by performing these
requests regularly.
Because things like currency can
fluctuate.
You know, a user might log out,
log into a different store
front.
So, the locale might change.
Make sure that as often as you
need to, you're requesting new
product information from the App
Store, and not holding onto an
instance of these SKProducts.
But now, you have your SKProduct
object and you're ready to go
ahead and show an actual in-app
UI to the user.
So, when it comes to showing the
UI, of course, this is really up
to your application.
And every application's a little
different in how you're going to
present the products to the
users.
It can have a large effect on
sales.
So, I'd encourage you to really
be careful about how you
structure this UI.
And if you want to learn a bit
more about that, we've got some
information online on our
developer website, here, to
check out.
This has useful tips about how
to format this particular page
in a way that can, you know,
improve your sales.
One tip, though, just on
formatting the product price.
So, when it comes to the product
price, this is the technique you
can use to actually display that
in your UI.
Create a number formatter
object.
Set the number style to be the
currency style.
And then, set the locale to be
the product price locale.
Now, this is a really important
step.
Because if you don't do this,
it's going to default to the
system device locale.
Which may not actually match the
store that the user's logged
into.
So, the user might be logged
into say, the Chinese
storefront, but have the device
set to U.S. English.
That's important that all the
pricing and currency stuff
matches what they're seeing in
the App Store.
So, make sure you set the
product's price locale under the
number formatting, here.
But once you've done that, you
can just take a string from the
number formatter, and you've got
yourself a formatted string that
you can display in your UI.
Another point, here, don't
perform any currency conversion
yourself.
There's no need to actually
convert currency.
You can let StoreKit handle all
this for you.
So, just take that number and
price locale that you get and
let the number formatter do the
job for you.
The next step, though, once
you've displayed your UI, is to
request a payment.
So, at this point, hopefully the
user's elected to buy your
in-app purchase.
They've hit that Buy button.
So, at this point it's up to you
to go ahead and request a
payment of the user.
Again, this is a really simple
step.
It's just a couple of lines.
You take that SKProduct that the
user's agreed to buy, pass it
into an SKPayment initializer to
create a payment object.
Then, you add that payment to
the SKPaymentQueue's default
queue.
Now, as soon as you add the
payment to the default queue,
the user sees this great new
looking in-app purchase payment
sheet.
So, this is new in iOS 11.
[ Applause ]
And the user, of course, can
just authenticate the purchase
using Touch ID, and then,
continue using your app.
So, we think this is a much
improved design that's going to
make that experience a lot nicer
for users.
Now, at this point, I'll just
take a quick sidestep to talk a
bit about detecting irregular
activity.
So, the ability to detect
irregular activity gives us
warning signs if potentially
something fishy might be going
on in this particular process.
Now, Apple has an advanced
engine to detect and block
irregular activity before it
happens, in the best cases.
But there are some cases where
this happens after a payment's
gone through.
And it can only detect it after
the fact.
Now, in those cases, we refund
developers or users as
appropriate, but that's not a
great experience.
So, we try to ask for a little
collaboration from you, at this
point, to help us detect these
things a little earlier.
Now, I'll just go through an
illustration that'll probably
demonstrate what I'm talking
about a bit better.
Let's say I have three devices,
here.
Three different users that are
logged into different Apple IDs.
These three users are purchasing
the same gold coin product from
the App Store from your
application.
Now, this is a really normal
scenario.
This happens millions of times
from millions of users around
the world, every day.
But let's add in another piece
of information to this puzzle
that changes the picture, quite
a lot.
Let's say that these three users
buy gold coins in your
application, but all these
separate IDs are actually
cashing these gold coins into
the same game account on your
server.
Suddenly, this picture looks
highly suspicious.
So, how do we detect these sort
of scenarios earlier on in the
process?
We ask you to provide an account
identifier with this payment
step.
Now, this is really for
applications that have their own
account management.
So, if you've got, say, a server
account and a user is logged in
as a particular user.
And we ask for an opaque
identifier at this step.
Now, what is an opaque
identifier?
Well, we don't really want you
to give us actual information
about the user.
We already know the user's Apple
ID, so don't give us that.
We don't want to know what the
actual username is for the user
or the password.
We don't want to know any of
these details.
What we suggest here, is that
you create a hash of the account
name, or something like this,
right.
This just gives us a unique
identifier to be able to match
these payments across different
Apple IDs and associate them
together.
It's a really simple step to be
able to do this.
When you create the SKPayment
that we just saw a moment ago,
there's just an extra step you
can do.
Which is to set the application
username.
And here, you can just set that
hash of the account name, and
that'll just help us detect the
irregular activity earlier on,
in the process.
So, that's a really simple step
you can do to make your payments
a little more secure in your
app.
Once the user's authenticated
they payment, though, the credit
card's charged.
And it's up to you to go ahead
and process the transaction that
comes down from StoreKit.
So, let's see what that looks
like.
Right at the beginning of your
application lifecycle.
And here, I'm doing it at the
didFinishLaunchingWithOptions
app delegate method.
It's important to set a
transaction observer onto the
SKPayment queue.
Now, here I'm adding the actual
AppDelegate, itself, as my
SKPayment transaction observer.
But you could use another object
if you want to actually monitor
these transactions.
The really important thing here,
is that it's happening as early
on in the application lifecycle,
as possible.
See, transactions can come into
this transaction observer any
point during your application
lifecycle.
So, make sure that you're
registering it right at the
start.
But once that's registered,
you're ready to start receiving
transactions in the callbacks.
There's this one callback
updated transactions, which is
kind of the center of where this
all happens.
You receive an array of
transactions that come in, and
you can check the transaction
state on each of these
transactions.
And you'll look for a
transaction in the purchased
state.
This is a transaction that's
StoreKit deems appropriate for
you to go ahead and check for
validity and unlock content for,
accordingly.
There are some other states
here, that we won't go into in
this talk.
But one of the ones that I will
call out, is the deferred state.
A transaction can come through
in a deferred state if the user
has asked to buy turned on.
So, a child might ask to buy an
in-app purchase and a request
goes to their parent for
approval to actually approve the
purchase.
And that could take anywhere
between seconds, minutes, weeks,
who knows how long.
So, it's important if something
comes through in this deferred
state, while they're waiting for
an approval, that you allow
access to the application.
Allow them to keep using your
app, and don't let them get
stuck on any kind of modal
loading spinners or things like
that.
The transaction will eventually
come through as a purchased one,
once it does get approved.
And you can just handle it like
any purchase transaction.
In order to test out deferred
transactions, we provide a way
for you to do this.
You can create a mutable payment
object.
And you can set the
simulatesAskToBuy flag on this
object.
Now, this is effective when
you're using the Sandbox
environment.
We're not going to go into the
Sandbox as much, this talk.
But this is what it looks like,
in code.
You just set that
simulatesAskToBuyInSandbox flag
to true.
And this just means that when
you're testing out developing
in-app purchases, this
particular transaction's going
to come through in the updated
transactions call a deferred
transaction.
So, you can just test out how
you handle those particular
cases.
When it comes to handling
errors, couple of points to
remember.
Now, not all errors that come
through this process are equal.
And that means you really need
to pay attention to the error
code that comes through with a
transaction.
So, maybe don't show an alert
unless it's absolutely necessary
to inform your user of a
particular error.
You know, we see things like
maybe a user cancels a payment,
which has a specific error code.
And you don't need to show an
alert that says user cancelled
to the user.
You know, they hit the Cancel
button, they know they
cancelled.
You don't need to let them know,
again.
It's also important to let
StoreKit handle the transaction
flow as much as possible.
And this means that you don't
need to ask for confirmation for
things like in-app purchases,
once they elect to buy it.
We have that nice new payment
sheet to do that for you.
And you can let StoreKit handle
that.
Now, once a transaction comes
through in the purchase state, I
mentioned that it's important
for you to verify that
transaction.
How do we do that?
How are we sure that money has
actually changed hands?
Well, we use the application
receipt to do this.
This application receipt is
really just like any receipt you
get in the department store.
It's a proof of purchase that is
evidence that the user has
bought something they say
they've bought.
So, in this particular case,
it's a trusted record of the app
and any in-app purchases that
have occurred for a particular
application.
Every app actually has an app
receipt, because it includes
information about initial app
purchases and even information
about the original free app
downloads, as well.
This document's stored on the
user's device, and it's issued
and put there by the App Store.
And it's also a signed and
verifiable document.
So, you can be sure that this is
a document issued by Apple.
And you can use certificates to
actually check that that's the
case.
Finally, it's for your app, on
that device only.
So, this receipt document can't
be shared across devices.
And it can't be shared amongst
applications on the same device.
Now, to be sure that the
document that you're using to
check these transactions is
indeed a valid one, you do what
we call receipt validation.
Receipt validation can be done a
couple of ways.
You can do it directly on the
user's device using on device
validation.
And you can unlock features,
accordingly.
Well, the other way is to use
server to server validation.
So, you can take that encrypted
receipt data, and you can send
it up to your server.
And from there you can send it
over to the App Store server, in
order to perform some of those
checks for you.
We're not going to go into the
details about receipt
validation.
And this talk that's going to be
talked about, again, in the
Advanced Session, this
afternoon.
I'm going to talk about you
know, how to read in this
receipt data from the device.
And also, how to do the server
to server exchanges for that,
too.
But once you've confirmed that
this receipt is an authentic
document, you can go ahead and
read in transactions and ensure
that this transaction that's
come through in this process is
present in the receipt.
And that means that you've got a
valid purchase ready to go ahead
with for the next step.
Which is to unlock the content
for your in-app purchase.
This is, obviously, a pretty
important step.
To make the functionality that
the user's bought, available to
the user.
This is the step where you might
download any additional content
and make it available to the
user.
If you are downloading content
for in-app purchases, there's a
couple of ways you can do this.
Apple actually offers two
techniques for you to use, as
well.
We have on-demand resources,
which is an API that we
introduced a couple of years,
ago.
And we also have what I
mentioned earlier.
The hosted in-app purchase
downloadable content.
So, you can associate
downloadable content through
iTunes Connect that's accessed
through the SKProduct object,
directly.
Of course, the other way is just
to host the content, yourself,
on your own server.
Which is perfectly okay.
But if you do that, I just
encourage you to remember to use
the appropriate background
downloading APIs.
Use NSURL session to make sure
that these downloads aren't
interrupted, you know, when a
user exits your application.
Once you've unlocked your
content, maybe you've made that
pro version of your application
available to the user.
You can go ahead and finish the
transaction.
This is the last step in
implementing in-app purchases.
So, it's important to finish all
transactions that come through
this process.
Even if they're in like an error
state, you got to finish all
transactions that come through
in this flow.
And that includes when you're
dealing with auto-renewable
subscriptions.
Any renewal transactions that
come in this flow, as well.
So, any of those, billing period
renewals that come through, you
have to make sure you take all
of these through this process to
finish them.
If you don't finish the
transaction, they actually
remain on the payment queue.
And they're going to keep on
popping up in that updated
transactions callback on every
app launch.
So, make sure that you are
finishing them properly and
getting them out of that payment
queue.
In fact, when it comes to
auto-renewable subscriptions,
we've got some details around
billing retry that relies on up
to date knowledge around the
state of all these renewal
transactions.
So, It's really important that
you do keep these finished and
up to date.
When it comes to finishing them,
it's actually just one line of
code.
So, there's no excuses.
You just pass the transaction
through to the finished
transaction callback.
This is a API on the
SKPaymentQueue's default queue.
But once you do that, you've
finished the transaction, that's
the last step in actually
implementing the in-app purchase
flow on a device.
So, the user's now got access to
that in-app purchase that
they've paid for.
A couple of tips just while
we're on the subject.
When you're in app review, you
must have a Restore button if
you've got non-consumable or
auto-renewable subscription
products in your application.
And this Restore button has to
be a separate button from the
actual purchase button.
So, it can be somewhere in your
app, maybe buried in your
settings, somewhere.
But it's just a tool to allow
users to restore completed
transactions.
And it's not just a backup tool.
You know. People use this all
the time when they're dealing
with maybe a new device.
If they go and buy a new iPad,
and they want to unlock the
content that they've paid for on
their phone.
They use that Restore
Transactions feature to be able
to do that.
So, it's important you have a
Restore Transactions button,
somewhere in your application.
As I mentioned, though, it does
only restore transactions for
non-consumable and
auto-renewable subscription
products.
So, if you're selling consumable
products or non-renewing
subscriptions, you've got to
persist the state of those
things, yourself.
So, maybe you've got a game
account, you might associate it
with that account information
somewhere on your own server.
In order to actually restore
them, this is the API for it.
It's
restoreCompletedTransactions as
the method, and it's on the
default payment queue.
If you call that, that's going
to cause all the completed
transactions in those categories
to reappear on the updated
transactions callback.
So, you can just do the same
process that we just saw, check
for them being in the purchase
state, do receipt validation,
unlock all the features
accordingly.
There's a couple more APIs
around the restoring completed
transactions.
You can understand if it's
finished or if there was an
error with a particular process.
But the real thing to do, here,
is just if you have a
transaction observer registered
early on in your application.
You can just handle all of these
transactions as they come
through that updated
transactions callback.
So, just to summarize this
process that we just talked
about.
Always observe the payment queue
and make sure you're doing it as
early on in your application
lifecycle, as possible.
Use an SKProducts request to
request localized information
about the products from the App
Store.
And use that to display
localized pricing information.
Use that technique we just saw
with the number formatter, to
make sure that your price is
being displayed in the user's
store locale.
Use the receipt to actually
validate that the purchase has
taken place.
This is an important security
step and we'll talk a bit more
about that, this afternoon.
You got to remember to make the
content available to the user.
So, make sure they get what
they've paid for.
And then, finish the transaction
at the end of this process.
Make sure that you call
finishTransaction and pass in
that transaction object.
And then, somewhere in your app,
have a Restore button to allow
users to restore completed
transactions onto that device.
So, that's a bit about
implementing in-app purchases
and that process.
Next, we're going to discuss the
new ability to promote in-app
purchases, directly in the App
Store app.
And to talk a bit more about
that, I'd like to invite Ross
LeBeau up onto the stage.
[ Applause ]
>> Hi. I'm Ross.
I'm an engineer on the App Store
team.
And today, I'm excited to tell
you about our latest addition to
the App Store.
It's called Promoting In-App
Purchases.
And it's a great way to reach an
even wider audience with
everything your app has to
offer.
So, before today, if a user
wasn't actively using your app,
your in-app purchases were
pretty hard to find.
But starting in iOS 11, your
in-app purchases will be
discoverable, right in the App
Store.
They'll be visible on your app
page.
They'll be eligible for
editorial feature.
And they can even show up in
search results.
Not only that, but users will be
able to begin a purchase right
from the App Store itself.
We think this will be a huge
improvement to how users view
your in-app purchases.
So, how does it all work?
Well, promoting your in-app
purchases is easy.
You'll need to do to things.
First, choose up to 20 in-app
purchases to promote per app,
and set them up in iTunes
Connect with an accompanying
image.
Then, implement a single
delegate method in your app to
handle the purchase info sent to
you from the App Store.
In most cases, this
implementation can be just a
single line of code, and
StoreKit will handle the rest of
the transaction for you.
Also, if you want, you can
override the order and
visibility that they show up in,
locally.
Now, this isn't required, but it
can be useful in a variety of
situations.
So, we've already gone into
detail on how to do the iTunes
Connect setup in the What's New
in iTunes Connect session.
That was yesterday.
If you missed it, you can just
catch it online.
But for now, let's dive in and
take a look at handling your
transaction info when it's sent
to you from the App Store.
So, a user has clicked to
purchase one of your in-app
purchases in the App Store.
StoreKit will automatically open
your app and send information
about the transaction to you via
a new delegate method on the
SKPaymentTransaction observer
protocol.
Now, you already have an object
implementing this protocol,
doing things like observing a
transaction state, as Pete was
talking about earlier.
So, you can put your new code
for promoting in-app purchases
right next to your already
existing code.
It's good to know that if your
app isn't already installed, the
App Store will download or
prompt the user to buy it.
In this case, it can't be opened
automatically, so instead, the
user will receive a
notification.
And when they tap on that, then
your app will open and be sent
the transaction info.
So, what's the code look like?
Well, this is all the new code
you need to get started
promoting in-app purchases.
StoreKit will send you the
SKPayment queue, the SKPayment,
and the SKProduct.
Which is everything you need to
handle the transaction.
And the SKPayment will already
be set up with the SKProduct on
it.
When you return true, the user
will be shown that nice new
in-app purchase payment sheet,
so they can complete the
transaction.
And that's it.
We're done.
Time to ship it.
Oh, all right.
Well, what if the user is in the
middle of onboarding?
Or if they're creating an
account?
Or if they've already unlocked
the item they're trying to buy?
Well, in this case, you can hold
onto the payment and return
false.
Then, when the user is done
onboarding or whatever they
needed to do, simply add the
payment to the payment queue as
you would with a normal in-app
purchase.
It's important that you add the
SKPayment that was sent to you
in this delegate method and not
create a new one with the same
product.
If for some reason you need to
cancel the transaction entirely,
just return false and no other
action is required.
If you're going to cancel or
defer a payment, you should
definitely consider letting the
user know, in some way.
What you don't want, is for the
user to tap on the in-app
purchase in the App Store, be
brought to your app, and then,
nothing happens.
They're going to think there's a
bug, and that's not good.
Okay. So, now you've got this
all set up.
You want to test it.
Right. Well, your in-app
purchases won't actually show up
in the App Store, until you've
submitted a binary that has this
delegate method.
So, we know you can handle the
transactions.
So, instead, we've created a
system URL for you to use.
This URL has the ITMS services
protocol and three parameters.
The first parameter is action,
and that's always purchase
intent.
The next parameter is bundleID,
which is of course, the bundle
ID for your app.
And the last one is
productIdentifier, which you
fill in with the product
identifier of the in-app
purchase you want to test.
And once you've constructed this
URL like so, you can simple send
it to yourself in an iMessage or
an email, and tap it on your
device.
You'll now it's working, because
your app will be opened
automatically.
And you can test its behavior
from there.
All right.
Now, we've gone over how to
handle the payment info when
it's sent to you from the App
Store.
Let's take a look at the more
advanced setup.
When you set up your promoted
in-app purchases in iTunes
Connect, you'll be able to
choose a default order that they
appear in on your app page.
You'll also be able to choose to
set some to hidden, so that they
don't appear, at all.
Then, when your app is running
on the device, you can set
overrides for these, locally, to
change the order of visibility.
So, for example, if you're
making a racing game you may
want to hide in-app purchases
for a car until the user has
actually unlocked that car.
Then, when they do, you can move
that in-app purchase to the top
of the list and unhide it.
So, they've just unlocked the
car, and now they'll see the
most relevant in-app purchase
right at the front of the list.
it's important to know that
these are not synched across the
bases.
They're stored locally on each
device.
So, if you need to replicate the
same behavior, you should make
sure that your app locally can
reproduce the results.
All right.
Let's take a look at some
specific examples.
Here, we have an app called
Forest Explorer.
This is an app we made up that
helps people discover and travel
to destinations.
This app doesn't exist in the
App Store.
It's only this presentation.
So, here we're promoting three
app purchases.
We have the Pro Subscription,
which upgrades the level of
detail the user sees and maps
and directions.
We have the Fishing Hotspots and
the Hidden Beaches packs.
Which simply unlock more
destinations that follow those
themes.
So, one thing you may want to do
is, say a user has purchased the
Pro Subscription in-app
purchase, is hide this from your
app page.
So, this is not something that
StoreKit or the App Store does,
automatically.
If they buy this and then, go to
the App Store, they'll still see
it there on your list.
Which might not make sense,
because they can't buy it,
again.
So, instead, what you can do is
use the local visibility
override to hide the app
purchase.
And then, they'll only see items
that are relevant to them on
your app page.
So, what's the code look like
for this?
Here it is.
First, you want to start by
fetching the SKProduct so you
have the most up to date
information from the server.
Here, we'll fetch the info for
the Pro Subscription in-app
purchase.
Then, we have a new class for
dealing with these local
overrides called
SKProductStorePromotion
Controller.
You'll want to get the default
controller.
And then, passing your SKProduct
to the update
StorePromotionVisibility
forProduct method.
Along with the new visibility
you want to set it to.
So, here we want to hide the Pro
Subscription, since the user
just purchased it.
That's all there is to it.
Pretty simple.
Now, if you want to check to see
what overrides you've already
set, start again by fetching the
SKProduct.
Here, we'll look at the Hidden
Beaches pack.
So, pass this into the fetch
StorePromotionVisibilityFor
Product method.
And what we can see here, is the
visibility is done, default.
Now, this is because we haven't
set any overrides, yet.
And it means that it will be
hidden or shown based on what
you've set as a default in
iTunes Connect.
Okay. So, we've talked about
overriding the visibility.
How about changing the order
that your in-app purchases
appear in on your app page?
Let's go back to Forest
Explorer.
Now, maybe you've been looking
at your metrics, and you notice
that this user is going to a lot
of beaches.
Could make sense to move the
Hidden Beaches back to the front
of the list so that they're more
likely to see it.
And since it's something that's
interesting to them, they might
be more likely to buy it.
Now, the code for this looks
very similar to updating
visibility overrides.
You'll want to fetch the
SKProducts for every in-app
purchase you want to override
the order of, so here we'll do
all three.
We'll do the Pro Subscription,
Fishing Hotspots, and the Hidden
Beaches.
Then, create an array that has
these in-app purchases in the
order that you want to override
them to be.
So, move the Hidden Beaches to
the front.
Finally, pass this array into
the updateStorePromotionOrder
method.
And there you go.
It's been updated.
Now, if we want to view the
overrides we may have set,
already.
Once again, it's very similar.
Grab the default
storePromotionController and
simply use the
fetchStorePromotionalOrder
method.
Here, we can see that we get an
array back and Hidden Beaches is
in front, since we've just set
that override.
Now, you don't need to use every
in-app purchase in your array
when you set the overrides.
You can actually use any subset
of them that you want.
If you do, what'll happen is
that subset will be shown at the
front of the list in the order
you've specified the override
for.
The rest of your in-app
purchases will be shown after
those, in the same relative
order as you've set in iTunes
Connect.
Also, you can receive an empty
array from this method.
This would mean that you haven't
set any order overrides, at all.
And similarly, you could pass in
an empty array to the update
method.
And that would be the same as
cancelling all the overrides.
You can think of this as using
the empty set of overrides.
So, this is all the code there
is for promoting in-app
purchases.
The new delegate method and the
test URL are available, right
now, in the Seed we sent out,
earlier this week.
And this order and visibility
override will be available in a
later Seed.
To recap on promoting in-app
purchases, it's a great way to
make them more discoverable, by
promoting them in the App Store.
You'll choose up to 20 to
promote per app and set them up
in iTunes Connect.
Then, a user can tap in the App
Store to begin the purchase.
The transaction info will be
sent to your app as it's opened
automatically via a new delegate
method on the SKPayment
transaction observer protocol.
Finally, if you want, you can
override the order and
visibility of they appear on
your app page, locally at
runtime.
Now, I'm really excited to see
how you all will use promoting
app purchases in your apps.
But for now, I hand the stage
back over to Pete, so he can
tell you what's new in working
with customer reviews.
[ Applause ]
>> Thanks, Ross.
I can't wait to try out Forest
Explorer.
Looks like a great app.
Well, now we've learned a bit
about implementing in-app
purchases and how to promote
them in the App Store.
Let's look at some ways you can
now interact with your
customers.
So, in iOS 11 we've got this
great new looking App Store
design.
And this is a product page.
If you scroll down the product
page, this is the new ratings
and reviews section, with a new
unified rating there.
And the user can just swipe
through different reviews in
order to read information about
user's experience with your
apps.
So, what's new in this regard?
Well, we've got a few new
features, here.
The first one, you can now
choose when you want your rating
to reset.
When you release your
application, you can decide if
this is something you want to
happen or not.
Previously, this would reset
your rating every single time.
So, now it's kind of up to you.
Yeah.
[ Applause ]
We've also, recently added the
ability for you to respond to
reviews on the App Store.
So, you can have that dialog
with consumers, now.
There's also some new ways for
you to ask for ratings and
reviews by the
SKStoreReviewController.
And finally, we added a new deep
link in iOS 10.3, that can link
directly to be able to write a
review in the App Store.
We also have added Helpfulness
and Report a Concern to iOS.
So, what does that look like?
Well, a user can now 3D Touch on
a review itself, and they get
presented with this Helpful or
Not Helpful menu.
They can mark them as helpful or
not helpful.
They can even report a concern
directly in the iOS app.
And when it comes to responding
to reviews, we introduced this
in iOS 10.3.
And the response has been really
fantastic.
We think users have loved this
feature and we've seen
developers really utilizing this
in a great way.
And when you respond to a user's
review, the user gets a
notification on their device,
informing them of your response.
They also get an email, as well,
detailing that response to their
review.
Now, down at the bottom of this
email, we actually have a link
for them to be able to update
their review.
So, we give them that
opportunity to tap that link.
And they get a chance to
actually edit their rating and
perhaps change their review, as
well.
And we've found that as users
are doing this, when they're
updating their reviews after
receiving a response, across the
board we've seen an average
increase of 1.5 stars per
review.
So, as you can see, it's a
really great opportunity to see
a better rating.
A better experience for the
user, and also, a better rating
for your app on the App Store,
entirely.
So, for more information about
this, we have a guide online
about some techniques and the
best ways to respond to reviews
and to interact with your
customers.
And we also chatted about this
in the What's New in iTunes
Connect session, yesterday.
So, if you weren't able to make
that, I'd encourage you to check
out the video for that, too.
When it comes to receiving
reviews, there's a couple of
ways you can do this, now.
You can prompt the user for
reviews in the
SKStoreReviewController class.
And we also provide this deep
link to be able to write a
review in the App Store,
directly.
So first, let's look at the
SKStoreReviewController.
This was a class that we
introduced in iOS 10.3 And it
provides a really nice clean
interface for the user to be
able to rate your application
without leaving it.
So, they can now, just tap a
star, hit submit, and rate your
application in a really seamless
experience.
They can ever write a review
without leaving your
application, now.
Now, if you're asking for
reviews using another kind of
alert or modal prompt, I just
highly encourage you to start
adopting this API, because at
some point in the future, we are
going to start requiring that
any modal presentation, any
modal prompts for reviews do use
this API, instead.
And there are some restrictions
in place for how this API can be
used.
There's a limited number of
requests per device.
So, we limit the amount of times
a user gets bombarded with these
alerts.
And the user can actually now,
in iOS 11, switch it off in the
Setting app.
So, they can go into the App
Store Settings, hit a toggle to
actually turn off these prompts
for ratings.
So, we think this is going to be
a better experience for users
and for developers, alike.
A couple of tips for
implementing this.
The SKStoreReviewController is a
prompt, so it's kind of
interruptive by nature.
So, think about doing this thing
at the end of maybe, some kind
of user interaction.
Maybe after a user has completed
a task.
Maybe, then use that opportunity
to ask them for a rating or
review.
Don't interrupt them when
they're in the middle of
something.
It's also, not appropriate to
use this API from a button.
Because you're not kind of
guaranteed to have UI presented
to the user, based on those
restrictions we just saw.
So, it's not appropriate to use
from some kind of embedded link
in your application.
But when you do want to do it,
this is what is looks like in
code.
It's just one line of code.
But you can wrap it in your own
business logic.
So, in this example here, we're
checking to see if this
particular user is the kind of
user that we want to ask a
review of.
And if we determine that they
are, we can call the request
review method on the
SKStoreReviewController.
And that's the only thing you
need to call.
And that'll present that rating
prompt to a user while they're
using your application.
The other way, of course, is
this new deep link to write a
review that I mentioned.
So, this was also actually
introduced in iOS 10.3, but
we're talking a bit about it,
now.
This provides you a link to open
your app page in the App Store.
But straightaway actually
presents the write review sheet,
or the edit review in the case
of they've already written one.
And this is more appropriate for
thing like user initiated
actions.
So, in the case that maybe you
do want a persistent link in
your app, maybe a button in your
Settings to write a review for
your app in the App Store.
And it's a little different to
the SKStoreReviewController, in
that sense.
You can kind of think about it
as being the opposite.
So, it's more appropriate from a
button in your Settings, or some
embedded content in your
application.
Because it provides that
consistent experience, a
guaranteed action that's going
to happen.
However, it's not appropriate to
use from an alert.
I mentioned if you're going to
use alerts to prompt users for
reviews, make sure that you
start to adopt
SKStoreReviewController,
instead.
This is how you actually form
the deep link.
You take you app page URL, which
you can get online from the Link
Maker website, if you don't know
what that is, already.
And you just append the query
parameter action equals write
review onto the end of it.
And that just means when the
user arrives at your app page,
they get presented with that
Write Review sheet.
So, for more information about
ratings and reviews and some of
the changes we introduced
earlier, this year, I'd
encourage you to check out the
developer website, here.
We've got some more information,
there.
So, we've covered a few of the
new features, today, for what's
new in StoreKit.
Just to recap.
We talked about the way to
implement in-app purchases in
your application, that seven
step flow for implementing
in-app purchases.
Ross, got up here and discussed
some of the newer ways that you
can promote your in-app
purchases, directly in the App
Store.
So, you can now sell content to
your users while they're
browsing the App Store app.
We've got that new App Store
design, featuring the new
Ratings and Reviews section,
including developer responses.
And we've seen that using
developer responses, we've got
some great new opportunities to
actually see improvements in
your ratings and reviews.
Better customer experiences, in
that regard as well.
For more information about this
session, we've got some links on
the website, here.
And this is Session 303.
There's also, some related
sessions, particularly this
afternoon, with the Advanced
StoreKit session.
And I can see you there,
hopefully, if you come along.
We've got some more details
about receipt validation.
We're going to go really
in-depth into subscription
management, persisting state
across the server environment,
and that kind of thing.
So, please come along and we've
got some more content for you,
there.
But that's it for today.
Thank you, for coming along this
session.
And I hope you have a great
lunch.
[ Applause ]