Create a great in-app purchase experience for your iPhone, iPad, Mac, and Apple Watch apps. Discover how to handle refunds, integrate new App Store server notifications, and find out how to use receipts and server notifications to manage subscriber status. We'll also walk you through the latest updates in StoreKit, including in-app purchases on Apple Watch, Family Sharing, SKOverlay, SKAdNetwork, and more.
Hello and welcome to WWDC. Hello and welcome to WWDC. I'm Tori, and I'll also be presenting with my colleague Ross who you'll hear from later today. I'm so excited to share with you what we have new for you with in-app purchases. And we have a lot to cover today.
This session will be divided into two sections. I'll focus on covering what's new on the server side. And later I'll hand it off to Ross to cover StoreKit updates.
So let's get started with our server updates. On the server side, first we'll cover refunds and how you can handle transactions that are refunded.
Next we'll cover some new ways to help you manage the subscription status for your customers and how you can use App Store server notifications to get notified and respond to various subscription billing events. We'll also cover the different scenarios where you may still need to use verify receipt to get the latest status. And finally we'll dive into Family Sharing.
We have a lot to cover so let's dive right in with arguably what brought us all here today, an in-app purchase. So this is an in-app purchase in one of my apps. I'm so excited to use this. But what happens if I change my mind, if I have an issue with the content and call Apple to request a refund, what should you as a developer do? That's why handling refunds is so important.
But keep in mind that while it's important it only affects a small percentage of transactions. However proper refund management could drive that percentage down.
So let's dive into that now by walking through a typical refund scenario.
First a customer purchases some content in an app like 100 Gems. However the purchase was an accident so they call Apple for support. After considering their case we issue a refund. Later the customer contacts you for support as they notice they still have the gems that were refunded. If you don't know that Apple has refunded the content it's difficult to determine how to respond. It would be so much better if you could easily determine if we had already refunded that purchase so you could take action appropriately.
Such as acknowledging the refund but letting the customer keep their gems or deducting their balance. That's why we're working to bring you new ways to manage refunds for your content. Having the ability to manage your refunded purchases is important for many reasons. Most importantly it gives you control to take action as you see fit. Such as messaging the customer or even taking back the content if needed. It also lets you handle any potential abuse of your content such as customers trying to keep their content after receiving a refund from Apple. And you can resolve customer issues like the previous one swiftly. This will also allow you to manage your in-game economy, making game play more fair for all players as there will be repercussions for refunds. So for all of these reasons and because we want you to be able to manage refunds for purchases in your app we're bringing you a brand new App Store server notification and our first ever notification for content types other than auto renewable subscriptions. The Refund notification.
So why did we decide on an App Store server notification for this. Well the primary reason is that you don't have to ask us for information. We'll just tell you. You're notified immediately with a JSON post upon a status change and we even retry up to three times if we don't get an HTTP OK back from you. If you're already receiving App Store server notifications for auto-renewing subscriptions then you'll get the new refund notification for your other content types with little additional work on your end. We'll also send you an updated unified receipt with your canceled transactions included so you can update your records. And this solution is also scalable as you grow your business on our platform. So our goal for all content types is to allow you to obtain information about refunded purchases through App Store server notifications. For consumables, non-consumables and non-renewing subscriptions you'll receive the brand new refund notification.
For subscriptions, you'll continue to receive the cancel notification. enabling App Store server notifications is straightforward if you've never done it before and can be done in a few steps. First set up your desired end point for your notifications and App Store Connect. Next make sure your End Point meets app transport security requirements as outlined in the developer documentation. Then you're all set to start receiving notifications.
So in App Store Connect, just navigate to your apps page and find the URL for App Store server notifications section. Enter your desired end point here so we know where to send your notifications. Know that if your end point already meets security requirements you'll immediately start receiving notifications. Now let's take a deeper look at the refund notification.
We'll send you this notification when any consumable, non-consumable or non-renewing subscription is refunded for your app, after we issue a refund to the customer for that purchase. Getting notified in this way makes it easy for you to take immediate action on your refunded content. This notification has also been implemented in a privacy friendly way as we're not giving you any information about the customer only information you'd already have about the purchase. The refund notification is live today so if you're already receiving App Store server notifications make sure you're looking for it. With that in mind when you receive this notification there are a few things I want you to look out for in the payload. You should look for the original_transaction_id to tell you which transaction we've refunded.
The cancellation date to know when we refunded it and the cancellation reason.
The reason can have values of zero or one and a value of one can indicate the customer requested a refund due to an issue within the app which you could then investigate. Also look for the bid, and the product_id to verify the app and product you've received a notification for. All these fields can be found in the unified_receipt object in the App Store server notification payload and the latest_receipt_info section. Except for the bid which is found at the top level of the payload. So what does the App Store server notification look like. Well it looks something like this.
Not all the fields are listed here but we have explanations for all possible fields in the developer documentation. Right now let's take a look at the ones we just discussed plus a few others. In addition to those transaction identifying fields, look for the password and the payload. This is a shared secret for your app which you can find an App Store Connect and it allows you to verify the payload is from Apple and is trustworthy. At the same level as the password you'll find the bundle identifier. You can verify this field to know which app you've received a refund for. Next look in the unified_receipt object specifically in the latest_receipt_info array for information about your refund transactions. This array contains the 100 latest transactions for your app and the four fields we told you to look for, the cancellation date, the cancellation reason, the original transaction ID and the product ID. So let's revisit our refund scenario from earlier and look at how the refund notification can now help you in a slightly different situation. In this situation the customer still buys 100 gems but then consumes the gems and still asks Apple for support with their purchase.
Once again we make a decision to honor or deny the refund because we don't know if the customer has consumed the gems. We may still honor the refund and if we do we'll send you a refund notification. Then if the customer reaches out to you asking for further support such as in-game compensation.
But now you'll know the purchase has been refunded and you can choose to take proactive action such as providing an in-app message in your app. A message such as this is great as it notifies the customer that you've observed a refund for their purchase. The action you've taken and what they can do to regain access to their content. In-app messaging is just one of many actions you can take upon observing a refund. Let's take a quick look at those now. So there are many actions you can take depending on the content type ranging from moderate to severe. For all content types, you can use this for refund monitoring. For in-app messaging and restricting access to the refunded purchase. Because we're sending you a server to server notification, this gives you the ability to restrict access cross-platform if needed.
In the case of consumables there are additional actions you can take like deducting the in-app currency balance. You as a developer are responsible for making decisions on what measures to take and how to implement them. So think carefully about which action you decide to take in order to promote a healthy community within your app. So now we've covered a lot about refunds and how to handle them appropriately. So now let's switch gears and jump into how we're making it easier for you to manage your subscriptions. First taking a look at some of the key events in the subscription lifecycle.
These include acquiring a subscriber for the first time, any auto-renew successful or unsuccessful, disabling or enabling auto-renew upgrades or downgrades and cancellations. So what do all these events look like for a customer and for you. So when the customer first subscribes we establish the subscription period and a fixed auto-renew period to repeat renewal after renewal. Within the first subscription period, your customer decides to turn off auto-renew thinking that they just aren't using the subscription enough, but later turns it back on after a little more time with their subscription.
After that we approach our first scheduled auto-renew. But there is an auto-renew failure due to a billing issue. At this point, we'll try to auto renew for the duration of the billing retry period. Also establishing a grace period. Luckily the subscription is recovered during our grace period so the renewal cycle remains the same. Shortly thereafter your customer decides they are enjoying their subscription so much that they want to upgrade. For an upgrade we start the customer at the higher tier immediately, shifting our upcoming renewals. Later after not using that higher tier as much as expected your customer decides to downgrade back to a more basic tier.
Downgrades take place at the end of the subscription period. So your customer will have access to the higher tier of service until their next scheduled auto-renew. So how can you keep track of all of these important events for your subscriptions. What we recommend is using App Store server notifications for status updates. This is a push approach, meaning you don't ask us for information we'll just tell you when something happens. And we do. We notify you when the status of one of your subscriptions changes providing you with a new receipt for your records at that time but only when you need it.
This solution is also more scalable as you require more subscribers. So let's dive into our App Store server notifications now to see what we offer and to learn a little bit more about them. When you start receiving App Store server notifications or if you already are. This is the payload you can expect to see. Note that this is a subset of possible fields and not all of these may be present all the time. There's a lot of information here, so I want to focus on some of the key components. When you received this payload first look for the auto_renew_product_id to see exactly which product the notification applies to and the product we plan to auto-renew next.
Then check the notification_type. This will tell you the type of event you are receiving. You should also verify the value and the password field matches your shared secret. So you know the content comes directly from Apple and is trustworthy. You should also look for the bundle identifier. This will tell you which of your apps you've received a notification for.
Then you want to look for the unified_receipt, this object mimics the response from verify receipt, so if you're already using verify receipt this should be familiar. The latest_receipt in the unified_receipt object gives you an updated accuracy for this customer for your app. The latest_receipt_info array contains the 100 latest transactions for your app. You can search here by the original transaction id to know which subscriptions are active for this customer. Finally look at the pending_renewal_info array to find the upcoming renewal info for each subscription the customer uses in your app. Now let's quickly revisit the notification type field. We'll send you notifications for several events and the notification type field can have the following possible values. INITIAL_BUY when a customer first subscribes. INTERACTIVE_RENEWAL when a customer upgrades or renews their subscription in your app or through managed subscriptions. DID_CHANGE_RENEWAL_STAUS when a customer changes their renewal status such as toggling auto-renew on or off. DID_CHANGE_RENEWAL_PREF when a customer makes a change that takes place at the end of the subscription period such as a downgrade. CANCEL when a customer calls Apple support and we issue a refund to them for their subscription or for an upgrade as we cancel the previous lower tier subscription. DID_FAIL_TO_RENEW when we failed to auto-renew as scheduled due to a billing issue. And DID_RECOVER, when we recover billing of the subscription in the billing retry period or grace period.
For more information on these notifications and when you can expect to observe them see our WWDC 2019 session "In-App Purchases and Using Server-to-Server Notifications". And to learn more about which notifications are available to you in sandbox. Check out this year's session "Introducing StoreKit Testing in Xcode". So if we go back to our timeline from earlier we have notifications to cover almost all of these events.
Initial buy for the purchase of the subscription did change renewal status for disabling and enabling auto-renew did fail to renew for the renewal failure did recover for the billing recovery, interactive renewal for the upgrade plus a cancel for the previous lower tier subscription and did change renewal preferences for the downgrade. So with App Store server notifications you can easily monitor your subscription events. But we decided we could make this just a little bit better. Which is why this year we're bringing you an App Store server notification for every successful auto-renew.
This is a new notification type which we're calling DID_RENEW. Coming later this year, we'll send you this notification after every single successful auto-renew, every time. Like all the other notifications it contains the unified receipt which gives you all the information you need to identify the subscription that was renewed. This includes the original transaction id, which is a unique identifier for the subscription. The transaction id, a unique identifier for the new subscription period. The expiration date of the new period and the auto-renew product id to tell you exactly which product was auto-renewed. So jumping back to our timeline. Notice that the addition of the did renew notification completes our events, bringing you everything you need to monitor your subscriptions in App Store server notifications. However, in addition to this new notification we thought there was a little more information you might need concerning your subscriptions. We think you should know if one of your customers has decided to apply a subscription offer before we renew the subscription with that offer. That's why we've added the promotional offer id to the pending renewal info section. This will be available through your verify receipt and in the App Store server notification and the pending renewal info array so you'll know if there are any pending offers for that subscription. This feature is live in the pending renewal info section today. So be sure you're looking for it. For more information on using subscription offers. See our WWDC 2019 session "Subscription Offers Best Practices". So now that we have a did renew notification and the promotional offer id in the pending renewal info, what should you do with this new information? Most importantly this allows you to rely on App Store server notifications for updates, eliminating the need to poll verify receipt. However you should still use verify receipt for a few key use cases. If you experience an outage on your server the next time one of your customers comes online you can call verify receipt to check their status. Making up for any missed updates. In this way verify receipt offers of recovery mode. Second you can use verify receipt to immediately determine entitlements for a customer. To learn more about determining entitlements, tune into this year's architecting for a subscription session.
Finally you can use verify receipt to verify a successful auto-renew. So what do we mean by using verified receipt to verify a successful auto-renew.
Because auto-renew is so critical. You want to ensure that you get the update.
For this reason approach marking an auto-renew through a double check.
First subscribe to our App Store server notifications so you receive the renew notification in addition to our other notification types. Second schedule a call to verify receipt for your subscription shortly after its scheduled expiration date. When you received the did renew notification as expected you can cancel this job, but if there is a delay you can fall back to verify receipt to verify a successful auto-renew. So we just covered a lot about App Store service notifications and subscriptions. Now I'd like to discuss a new feature for App Store subscriptions. One of the things customers love most about subscriptions like News Plus or Apple Arcade is that they can be shared with their family members. Well we're very excited to announce that this year the app store will support Family Sharing for in-app purchases, which will allow up to five additional family members to share a single purchase. Family Sharing works for both auto-renewal subscriptions and non-consumable in-app purchases like those that are used to offer a full feature unlock. Customers will choose which in-app purchases they'd like to share with their family. We're so excited about what this means for developers and your ability to engage millions of family members that are already set up. Because the use of family is so widely adopted, Family Sharing for in-app purchases can help increase customer engagement and improve retention for your app. To begin, you can visit App Store Connect to turn on Family Sharing for a specific product. You can navigate to your apps page and select 'Turn On' in the Family Sharing section. Note that once you turn on Family Sharing for a product you cannot turn it off. Let's review how customers will manage their shared purchases. When new customers subscribe, the subscription will be shared by default. Subscribers can turn off sharing later for their family on the managed subscriptions page. For existing purchasers, they'll be notified if one of their subscriptions becomes shareable. Then they can manage their sharing preference from the same managed subscriptions page. For non-consumables all purchases will be shared with the family, if the customer has turned on 'Share Purchases with Family' in Settings. So what do you need to do in your app. So family members can enjoy access to the shared purchase. With this feature not only are we creating a transaction for the purchaser we're also creating a transaction for each family member. So when a family member opens the app they will have a transaction available in the transaction queue for each of their devices and there will be a unique receipt for each family member that will contain shared transactions in the latest receipt info array.
You should keep track of the original transaction id for each family member as you already would for your subscriptions. Note that this only applies to new purchases made after sharing is enabled. For non-consumable purchases made before sharing was enabled, you'll still have to restore purchases for these to be available to all family members. So let's get an idea of what this looks like for new purchasers. After you've enabled Family Sharing In App Store Connect, when a family member makes a shareable purchase not only do we put a transaction in the transaction queue for their devices we also put a transaction in the transaction queue for every member of their family, for all of their devices. So when their family members open up your app later you can unlock access to the subscription or non-consumable instantly.
It's like magic. And it makes it so easy for you to reach more developers than ever before. Before moving on let's quickly review what this looks like for both new and existing subscribers for both subscriptions and non-consumables.
So for new purchasers any shareable subscription they purchase is shared with their family by default. Any shareable non-consumable they purchase is shared with their family, if they have purchase sharing enabled in iCloud. If the family is sharing payment and if the app is not hidden from their purchase history. For existing purchasers for a shareable subscription to be shared with their family they must opt in from the managed subscriptions page. For existing non-consumables to be shared, the same three conditions must be met and you have to restore purchases to unlock the content for the family member. To manage access for all family members you'll need to use the receipt. You can get an updated receipt from verify receipt or from App Store server notifications. Additionally whenever the customer opens the app you can refresh the receipt on device to verify access for each customer. But I'm getting ahead of myself here. So with that I'll hand off to my colleague Ross who who'll talk to you more about Family Sharing within StoreKit.
Thanks Tori. So let's take a look at how Family Sharing in-app purchases works within your app. First off how can your app tell if a product supports Family Sharing. Well we've added a handy new property on SKProduct called isFamilySharable. It's as easy to use as requesting your product information from the App Store and then checking this isFamilySharable boolean.
You can use this to programmatically display to customers that one of your products is family shareable and not have to hard code any logic. So now one of your customers has seen this family sharable product and taps to purchase it. What happens next? Well when a customer purchases a family shareable in-app purchase everything begins as normal. Your app uses StoreKit to send the purchase to the App Store and then you get a transaction back in the purchase date. The next time their family members open your app each of the family members will get a transaction that looks just like a restored purchase, so your existing app logic should be able to handle it with no additional coding. Now Tori mentioned that customers can also enable and disable sharing for specific products. When a customer enables Family Sharing for a product something similar to a purchase happens. Their family devices will all get a transaction that looks just like a restored purchase.
So again your app should be able to handle it with no additional coding.
What about the opposite case. What about when a customer disables Family Sharing.
Well normally non-consumables are permanent and auto-renewal subscriptions only end when they expire. But when a customer disables Family Sharing they expect access to be halted immediately. So for this case we've added a new API.
It's a new method on the SKPaymentTransactionObserver protocol called paymentQueue(didRevokeEntitlementsForProductIdentifiers:) When a customer disables Family Sharing StoreKit will automatically update your receipt and then call this method. Inside the method you should be prepared to verify the receipt whether locally or by uploading it to your server and using the verify receipt endpoint.
Products that have been revoked will no longer be present in the receipt.
Now you should make sure that you're not simply looking at the product identifiers in the array and revoking access based on that. Depending on the setup of your products and other products the customer may have purchased they may still be entitled to some access that overlap the revoked purchase.
So we added this API to handle a couple of new situations that occur due to Family Sharing. As I mentioned it will be called when a purchaser disables Family Sharing for a product. It will also be called if a customer leaves a family group that was sharing the purchase. And we've also taken this opportunity to add support for refunds. If a customer receives a refund for a non-consumable or an auto-renewable subscription, StoreKit will call this method and you may revoke access immediate. And that wraps up Family Sharing which we think users will love. And we'll give you new opportunities to increase value to your customers and improve engagement and retention.
Now I'm going to give you a tour of some of the other improvements and features we've added to StoreKit, and what to look forward to in the latest releases.
First I'll throw out a couple of things we already shipped since WWDC last year. We have in-app purchase on Apple Watch and improved store subscription price increase flow. Then I'll move on to what's new including SKOverlay and improvements to SKAdNetwork. So this first one is especially for all you Apple Watch developers out there. As of watchOS 6.2 earlier this year we've added StoreKit and in-app purchases to watchOS. This means that for apps your customers use mostly on the watch. You can offer in-app purchases directly in the watchOS interface your customers are already using.
Using StoreKit on watchOS is almost exactly the same as using it on any other platform.
You can observe the payment queue, request products, and add them to the payment queue the same as you do on other platforms. When it comes to verifying the receipt you can of course continue to use server to server validation.
However if you prefer to do local validation there is just one difference you should be aware of. When you're retrieving the device identifier, instead of using UIDevice, you need to use the WKInterfaceDevice API. Here's an example of some code that runs on both iOS and watchOS. Once you've retrieved the device identifier everything else is the same. Use that device identifier along with your PAKE value in the receipt to create a hash.
Then make sure that hash matches the one in the receipt.
And that's all you need to know to add in-app purchases to your watchOS app.
Another feature we rolled out in iOS 13.3 is an improvement to handling subscription price increases. A subscription price increase occurs when you have an existing subscription product you want to charge more for.
Setting up for price increases is easy. Just go into App Store Connect and change the price, but you can't just bump up the price of an auto-renewal subscription without telling your customers. That's why the App Store requires each customer to agree to the new price. You should know that if you decrease the price of the subscription customers don't have to take any action and look at the new price automatically. Now unfortunately this process of informing the customer and asking them to agree to the new price can result in churn. Churn is when customers stop using your product and are no longer paying for it. And now you're thinking well of course customers don't want to pay more. But actually found in a lot of cases that's not the issue.
Customers can sometimes miss the e-mails that the App Store sends. Or perhaps they don't want or engage in the price increase flow at that time.
And sometimes they put it off until later and simply forget.
Additionally customers might not be informed of additional value that you're providing.
For example if you run a video service and you've added new content. So for users experiencing a price increase who are using your app, we've implemented an automatic in-app price increase consent sheet. After you initiate a price increase in App Store Connect any affected customers will see this App Store UI when opening your app. This way customers are informed and can agree to continue their subscription, at the time they're using the app, which presumably means they're finding value in your products. Once they agree or dismiss the sheet your apps UI is underneath it and continues as normal.
Now we realize that not all apps will want to display the sheet immediately upon opening, so we've added some tools to allow you to control the flow.
First you'll want to implement this new SKPaymentQueue delegate method.
StoreKit will always call this method before presenting the price consent sheet.
Inside the method, its up to you to determine if you want to show a sheet now and then return true if you do, and false if you don't.
Now if you return false here you're going to want a way to show the sheet later at a time that's more opportune. Perhaps after you've educated the customer about additional value you're providing.
To do that simply call this other new StoreKit API. SKPaymentQueue.showPriceConsentIfNeeded Now you should only call this if you've previously returned false to the method above. However if you do call it and there's no pending price increase don't worry. StoreKit will always check to make sure there is a pending price increase for the customer before showing the sheet and it won't show it at all if there isn't. Next I'm happy to introduce an entirely new API in the latest iOS release. It's called SKOverlay and it's a sleek new UI element for displaying and promoting apps.
Take a look. SKOverlay presents a floating view at the bottom of your UI that displays information about an app. It's similar to the SKStoreProductViewController class that exists In StoreKit today, except SKOverlay was designed to work seamlessly with your apps UI. Additionally unlike SKStoreProductViewController, SKOverlay is only used to display apps.
SKOverlay was also designed to work seamlessly with your app clips in order to help you transition users From your app clip to your full app.
But that's not all it's used for. You're entirely able to use it within your full apps as well. Simply enter the app id of the app you want to display and customers can install it directly from the overlay. If you're interested in learning more about our new app clips feature, I highly recommend checking out the "Exploring App Clips" session as well as the "Streamline Your App Clip Experience" session both in this year's WWDC. So now let's dive into the SKOverlay APIs and see how you can best integrate SKOverlay into your app. Creating and presenting an SKOverlay is fairly straightforward. First you initialize it using an SKOverlay configuration object. We'll get back into that configuration object later but it essentially allows you to set up the details of the overlay.
Then you call the present method passing in the window scene where you want the overlay to appear. That's all you need to do to create and present an SKOverlay. Of course we've also added lots of other tools to allow you to customize the overlay flow. First there's a dismiss function that allows you to manually dismiss the overlay. You'll notice that this dismissal function is a class function and it doesn't take an overlay as an argument but rather another UIWindowScene. That's because only one overlay can be displayed in a scene at a time and doing it this way allows you to remove any overlays that may be on a scene even if your current code context doesn't have access to the specific overlay object. SKOverlay also has a delegate.
As you'd expect this delegate allows you to react to changes in the overlay status.
We'll see the details of that later. And finally SKOverlay has a configuration object.
This allows you to see the configuration that was used to set it up. Now that we've come back around to the configuration, let's take a look at those two objects. SKOverlay is actually comprised of two classes. The first is called AppClipConfiguration and this configuration is used to transition users from your app clip to your full app. The AppClipConfiguration can only display the full app for the current app clip the overlays displayed in.
The next class is the AppConfiguration. And this configuration can be used to display any app. Much of these two classes is the same. So let's start there.
Both classes have a campaign token and a provider token so that you can use SKOverlay with app analytics. They also have functions that allow you to set and get arbitrary key values. Now most developers don't need to use these but they're there so you can integrate SKOverlay with other StoreKit APIS such as SKAdNetwork.
Both classes also have a position property. While SKOverlay always appears at the bottom of your screen apps that use tab bars will want to choose the bottomRaised property so that the overlay appears just above the tab bar rather than on top of it. In addition to these properties and functions the app configuration also offers two additional properties on top of these.
First is the app identifier. You can use this to enter the iTunes identifier of the app you wish to display. The AppClipConfiguration doesn't have this property because as I mentioned before that configuration is only used for displaying the full app of the current app clip the overlay is in. And the app configuration also has a user dismissible boolean. This is set to true by default which means that the user will be able to swipe down on the overlay to dismiss it from the screen. If you set this to false the user will not be able to swipe down on it. And the overlay will only go away when you call the dismiss function manually. That's it for the configuration.
So let's move on to the delegate. The first delegate method is simply an error handler. If you try to present an overlay and an unexpected error occurs it'll call this delegate method passing in the overlay and the specific error as an argument. The rest of the delegate methods are all revolving around animating of the overlay. You can see there's a method for the start and end of the presentation as well as the start and end of the dismissal.
You can also see that each of these methods includes an SKOverlay TransitionContext object. That's because these methods are used to help coordinate your UI animations alongside the overlay. Let's walk through how you might present an overlay and use these APIs to coordinate animations.
Here we're creating and presenting an SKOverlay inside our app clip. First we grab the current window scene and then we create an app clip configuration using the bottom position. We'll then initialize an overlay using that configuration object and we'll set its delegate. Finally, we present the overlay in that scene.
And this is all you need to do to use SKOverlay in your app or app clip.
If we want to animate our own UI alongside the overlay. We can do so using the delegate methods. First we can set up any initial state for our UI elements directly inside the delegate method. These delegate methods are always called in the main queue so you can manipulate UI right inside them.
Then we add any animations we want inside an animation block on the transition context.
Again simply declare any changes in animatable properties here. There is no need to use a UI view animate block, since any code inside this block will be animated for you by the overlay. Whether you're optimizing your app clip or promoting other apps inside your own app. SKOverlay is a great option for seamless integration and beautiful UI. Finally I'd like to share with you some updates about our SKAdNetwork API. Introduced in iOS 11.3, SKAdNetwork allows ad networks to measure the effectiveness of their ads while still respecting customer privacy. In the latest iOS release we've made it even more powerful while still not compromising on customer privacy.
Let's start with an overview of SKAdNetwork. SKAdNetwork involves three stakeholders. Ad networks, source apps and advertising apps. Each stakeholder has a role in making the feature work. Ad networks place ads within apps and receive postbacks when ads results in conversions. Source apps display the ads that are sent to them by the ad networks. And advertising apps are the ones that appear in the ads and then submit the post back to SKAdNetwork once they're opened. Let's take a closer look at this flow from start to finish. First the ad network places the SKAdNetwork data inside an ad for the advertising app, which we'll call App B. Then it displays this ad in the source app, which we can call App A. Once the user taps the ad, installs App B and opens it, App B should call another SKAdNetwork API in order to initialize the postback. Calling this API will set a timer. And once that timer expires the user's device will send the postback to the ad networks URL. Ad networks should use Apple's public key to verify the data in the postback and make sure it's legitimate. So that first bundle of data that the ad network sends up when displaying an ad looks like this. And contains the Ad network id, which has been registered with Apple and the Campaign ID from 1 to 100 which ad networks can use to measure their campaign effectiveness.
It contains the id of the advertising app, the one that's displayed in the ad. And it has a timestamp. This timestamps should be generated at the time the ad is displayed because timestamps that are too old will cause the ad data to be rejected. The nonce is just a random UUID used to ensure that each ad impression is unique and to prevent double counting. And finally the signature is generated using all of the other pieces of data in this bundle to ensure that only your ad network can start ads using your ad network id.
In the latest iOS release we're requiring two new pieces of data. The first is the version which is now 2.0. And the second is the source app id.
This is the id of the app thats displaying the ad. Next the postback API should be called by the advertising app, App B, upon the first launch of their app. This method generates a postback which is the cryptographically signed data validating that a user installed and launched this app after seeing the ad. The first call to this API starts the postback process, if the device has attribution data for the app, and subsequent calls have no effect. Starting in the latest iOS advertising apps will be able to call the updateConversionValue API if they choose. This allows the app to add an additional 6-bit value that represents some action that took place in the app. For example let's say you want to know whether a user purchased an item in your app before you count the conversion. In this case you can call updateConversionValue and include a value that you mapped purchasing an item. Since the conversion value is chosen at runtime we can't sign it on the App Store server. So it's the only piece of the postback that isn't protected with cryptography. The value itself as an integer between 0 and 63, which may represent actions such as making a purchase, signing up for a free trial, or completing a level. Apps can call this API multiple times to update the conversion value. However only values that are higher than the previous value will be accepted. Values that are lower than the currently stored value will simply be ignored. This means you don't have to worry about accidentally over writing your conversion value with a lower value. Now let's see the details of the postback that StoreKit sends to the ad network once the process is complete. We'll send up the ad network id and the campaign id that were used in the ad, as well as the id of the advertising app, App B. The transaction id is another unique identifier you can use to make sure you aren't double counting conversions. And you can use Apple's public key to verify the signature to know that it's all legitimate.
In the latest iOS we've added new information to the postback too. First we added the version. We've also added a key called redownload which will indicate whether this was the first time the customer purchased the app or if they'd previously purchased it and are installing it again. Prior to this SKAdNetwork only worked for the first purchase of an app.
So adding re-downloads will give you a lot more insight into the effectiveness of your ads. Furthermore in the latest iOS we've added two new optional items to the postback. The first is the idea of the source app so that you can know which app displayed the ad that resulted in the conversion.
And the second is the conversion value that was chosen by the advertising app.
It's important to note that these last two pieces of data won't always show up in the postback. In order to preserve customer privacy the App Store servers do calculations to make sure that sharing these values won't allow the post back to be linked to the customer that generated it. So we'll share them when we can. But your server should be ready to handle the postbacks both with and without them. So how do you get started.
If you're interested in using SKAdNetwork as an ad network you'll need to sign up with Apple so we can register your information. You should enroll in the developer program as an organization and then fill out the form to request access to SKAdNetwork.
Well then send you instructions on how to generate a public / private key pair and you'll send us the URL all you want postbacks to be sent to along with your public key. Remember never send your private key. Always keep that secure. Then you're registered and you're ready to begin using SKAdNetwork. If you're a source app and you want to work with an ad network, ask them for their ad network id and put it into your info.plist file.
This will make sure StoreKit knows to accept the ad data, when you display an ad in your app.
And finally if you're an advertising app and you want to measure the conversion of your ads make sure to configure your app so that it initializes the postback when it first launches. Today we've covered lots of information on best practices and new features in both server to server and customer device environments. You can now take advantage of new server to server notifications for refunded purchases. And we saw how you can use subscription notifications to get the latest information without needing to poll the verify receipt endpoint. We introduced our brand new way to share in-app purchases among family members, giving you a new tool to increase value and engagement with your customers. On the client side you can now offer in-app purchases directly inside your watchOS apps. And subscription developers will benefit from our new improved subscription price increase flow.
We got into the details of our new SKOverlay API for promoting apps including using it inside app clips. And finally we explained how our SKAdNetwork API can help advertisers gather and use conversion data without compromising on customer privacy. We think these tools will help you continue to grow your business with in-app purchases.
For more information please join us on the forums and in the labs. Thank you.
Looking for something specific? Enter a topic above and jump straight to the good stuff.
An error occurred when submitting your query. Please check your Internet connection and try again.