Every day there are more apps in the Windows Phone Store that offer in-app purchase: in the past 6 months alone, the sales of in-app purchase items in Windows Phone Store has grown by over 20x. Windows Phone apps with the highest in-app revenue share some key characteristics, which we believe could be valuable to you as a set of best practices for implementing in-app purchase. In this post we also look at practical approaches and scenarios that can help you avoid common errors when you decide to monetize your Windows Phone apps via in-app purchase.
Best practices
Apps and games sold in the Windows Phone Store that have the highest in-app revenue share several important characteristics:
- They use in-app purchase to extend or accelerate gameplay, or to unlock highly valuable content.
- They have a high replay value, to give users incentive to spend more time in the app.
- They make it easy to purchase in-app items using custom UI, and they lead the user to the purchase experience at the right time.
- They offer multiple options, at different price points, to appeal to the most number of users.
Here are some useful examples from apps in the Store that have been the most successful in their implementation of in-app purchase.
Royal Revolt! (flaregames GmbH)
CoPilot GPS (ALK Technologies Limited)
Drag Racing (Creative Mobile)
Scenarios
Along with the increase in apps that feature in-app purchase, we are seeing an increase in the number of apps that don’t implement in-app purchase correctly. This could generate certification delays, lost income opportunity for the developer, and if not fixed, can cause a negative experience for app users, who can submit negative feedback.
Three of the most common in-app purchase errors occur in these scenarios:
- Purchase flow is interrupted.
- Purchase is cancelled by the user.
- Multiple consumable items are purchased.
Read on for testing and fine-tuning you can do to help bypass these trouble spots in your app.
Purchaseflow is interrupted
In Windows Phone apps, there are two primary instances in which an app “owes” the user a purchased item. More than 80% of the failures we see in in-app purchase app submission don’t handle these events correctly.
- App is reinstalled: An app user acquires a durable in-app purchase item and the app awards the item. If the user changes phones or reinstalls the same app, they should have the same durable in-app purchase item available that they had purchased previously.
- Purchase was completed, but fulfillment process was interrupted: A user purchases any in-app purchase item, the purchase is completed, but fulfillment is interrupted. The user is not returned to the app, and the purchased item is not installed in the app.
In both of these cases, because of an interruption, the app is not “aware” that a purchase needs to be awarded to the user – either again for an app reinstall or as an initial fulfillment if the fulfillment process was interrupted at time of purchase.
You can test your app before submitting for certification to see how it handles these events.
How to test:
- Launch your app, and then purchase a durable item. Ensure the item is installed or unlocked, however a user would access the purchased item. Then uninstall the app. Reinstall the app and the item should either be automatically unlocked or reinstalled. If this doesn’t occur automatically, the app should offer you an option to reinstall the item (at no cost).
- Launch your app, purchase an item, and before the purchase process returns you to the app, touch the home button on the phone and then relaunch the app. The app should detect that it has unfulfilled purchased items and award them to the user.
How to handle app interruptions correctly:
Design your app to check for previously purchased items that are not yet awarded, and to fulfill them when the app starts.
You can use a version of DoFullfillment() from the In-App Purchase API documentation to create a function to handle these scenarios. Here’s an example:
- // This is called during startup, ideally in a background process
- // Well check for unfulfilled items, and fulfill if needed
- publicvoid CheckUnfulfilledItemsAtStartupTime()
- {
- var productLicenses = CurrentApp.LicenseInformation.ProductLicenses;
- // Check fulfillment for CONSUMABLE products with hard-coded asset counts
- FullfillItemsIfUnfulfilled(productLicenses["50gold"], 50);
- FullfillItemsIfUnfulfilled(productLicenses["100gold"], 100);
- // Check fulfillment for DURABLE products, if not fulfilled already
- if (!InfiniteGoldPurchased)
- FullfillItemsIfUnfulfilled(productLicenses["Infinitegold"], 99999);
- }
- // Gold to be awarded is passed as a parameter
- void FullfillItemsIfUnfulfilled(ProductLicense license, int goldCount)
- {
- if (license.IsConsumable && license.IsActive)
- {
- m_goldCount += goldCount;
- CurrentApp.ReportProductFulfillment(license.ProductId);
- // and store the data in the app if needed
- }
- if (license.IsDurable && license.IsActive)
- {
- m_goldCount += goldCount;
- InfiniteGoldPurchased = true;
- // and store the data in the app if needed
- }
- }
Take a look at the DoFullfillment method in In-App Purchase API overview for Windows Phone 8 and call something similar when the app launches, as well as when the user tries to purchase an app. Even if the app crashes or the phone shuts down in the middle of the transaction, the purchase is not lost.
Purchase is canceled by the user
Sometimes a user initiates an in-app purchase, but then decides they don’t want to make the purchase after all. Your app should not award the items, and ideally it will inform the user that the purchase was not successful.
How to test:
Launch your app, purchase an item, cancel the purchase before the purchase is completed (either by tapping back or by tapping cancel). The app should continue to run normally, and it should not award the item you initially started to purchase, but then cancelled. Ideally a notification will inform you that the purchase did not complete, and that the item will not be awarded.
How to handle cancellations correctly:
Here’s an example from the In-App Purchase API documentation that shows how to handle cancellations and errors correctly:
- asyncvoid PurchaseProduct(string productId)
- {
- try
- {
- // Kick off purchase; don't ask for a receipt when it returns
- await CurrentApp.RequestProductPurchaseAsync(productId, false);
- // Now that the purchase is done, give the user the goods they paid for
- DoFulfillment();// (DoFulfillment is your function)
- }
- catch (Exception ex)
- {
- // When the user does not complete the purchase (e.g. cancels or navigates back from the Purchase Page), an exception with an HRESULT of E_FAIL is expected.
- // The in-app purchase was not completed successfully, so no items should be awarded to the user.
- }
- }
Multiple consumable items are purchased
When a user purchases the same Consumable item multiple times, the game should be able to handle each purchase as an item that is eligible for repurchase, and allow the user to purchase the same item again.
How to test:
Launch your app, purchase an item, and verify that the item is awarded (for example, you received the 10 gold coins you purchased). Then, purchase the same item again: the app should add an additional 10 gold coins in the game.
How to handle multiple consumable purchases correctly:
The In-App Purchase API documentation describes a DoFulfillement() function that handles consumables correctly. You call ReportProductFulfillment() to indicate that a purchased item has been fulfilled, and so it can be purchased again.
- publicvoid DoFulfillment()
- {
- var productLicenses = CurrentApp.LicenseInformation.ProductLicenses;
- // Check fulfillment for consumable products with hard-coded asset counts
- MaybeGiveMeGold(productLicenses["50gold"], 50);
- MaybeGiveMeGold(productLicenses["100gold"], 100);
- // Check fulfillment for consumable products with variable asset counts
- MaybeGiveMeSilver(productLicenses);
- }
- void MaybeGiveMeGold(ProductLicense license, int goldCount)
- {
- if (license.IsConsumable && license.IsActive)
- {
- m_goldCount += goldCount;
- // Report item fulfilled, so it can be purchased again
- CurrentApp.ReportProductFulfillment(license.ProductId);
- }
- }
Next steps
We encourage you to test your apps before submitting to the Windows Phone Store, learn from the in-app purchase code sample, and consider following the best practices implemented in the apps we highlighted. All of these approaches can help you build an in-app purchase app that passes app submission certification, and which delights your users.
If you have questions about in-app purchase for Windows Phone, leave a blog comment, and let me know how I can help add in-app purchase to your app.