Kendall Gelner is a Senior iOS Engineer at Fieldwire. Previous, he was the founding iOS Architect at Nami ML. He is well regarded in the iOS development community for his technical knowledge and platform experience going back to the App Store launch. The last SDK Kendall was responsible for shipped inside of some of the most widely installed apps, reaching more than 200 million devices.
So your app was rejected. App Store rejections are common but are usually simple to resolve. This article covers typical rejection reasons, including those relating to apps utilizing StoreKit, in-app purchases and subscriptions.
This article is for people who have submitted to the App Store, but have had the application rejected for some kind of technical (not policy) reason.
First of all, don't panic! App Store rejections are pretty common and it does not affect your standing with Apple or necessarily mean you have a serious problem to fix. Often it’s a small detail of Apple's requirements you need to address, and then all will be well.
So what should you do when your app is rejected? Here are some useful starting steps:
👉Read more: Offering App Store Alternative Payments in South Korea
Here are specific suggestions to issues we’ve seen submitting apps with purchases:
Authentication Screen Remained open
Apple considers your payment request screen (paywall) to be a form of authentication, they are saying after a purchase was made there was no indication from the app the purchase succeeded - such as dismissing the paywall view.
Solution: Try to reproduce a case where a paywall remains open after purchase. Does turning off the network not yield any messages when attempting to purchase? Would any error case in purchasing leave the screen up? Make sure a successful purchase messages the user.
Guideline 5.2.1 - Legal - Intellectual Property
This means App Store review has found images in your application or in app preview images for the App Store that are copyrighted - for example if your application sample images showed album covers or images from other people.
Solution: One possibility for App Store preview items, is to simply blur out copyrighted material from preview images so that it is no longer recognizable. You could also edit out anything copyrighted and replace with images you do have rights to.
Guideline 3.1.1 - Business - Payments - In-App Purchase
Read the details of the problem they had, one common item is that your application did not offer a way to restore purchases.
Solution: If your app does offer a restore purchase option, respond directing them as to where it can be found. If it does not already, add that feature - usually it is placed somewhere on the product selection screen (paywall).
Guideline 3.1.2 - Business - Payments - Subscriptions
This category includes specific issues with subscriptions.
One common possibility here is that you forgot to include some way to access purchase terms, and the privacy policy of your app.
Solution: These can be anywhere, make sure to point out where they can be found if the app reviewer says they are missing but you have included them. One common technique is to have these legal documents hosted on your website, and use a Safari web view in your app to display them for reading.
Guideline 2.1 - Performance - App Completeness
This guideline can come into play if you've forgotten to include products to submit with the build of the application you are submitting to the App Store.
Solution: If you have not filled out all product metadata (including screen shots of the purchase screen for app review), then the section to include products in the app metadata for review will not appear - make sure all of the products you want to use in the release of your application are marked as "ready for review" and have been added to a build you are submitting for review.
Another possibility: Tapping purchase buttons produces no result.
Solution: If a user attempts to purchase, there should always be some indication by the application that it is attempting to make a purchase - make sure that the button will always initiate a purchase with StoreKit, and listen to any possible response to fail gracefully if StoreKit returns any errors. Double-check all of your purchases from a device Sandbox test account, to make sure you do not have anything like incorrect product identifiers, and are listening to transaction results from Apple.
Another possibility: A user attempted an in-app purchase outside the application, but the app did not show the purchase was made (for example, an App Store page that shows subscription options might be used to make a purchase instead of in-app).
Solution: Make sure you start up store kit listeners at app launch, and process any incoming transactions as soon as you see them - ave some way for the application to react to purchases made at any time, not just when on a purchase screen (paywall).
Guideline 2.1 - Performance
This more general category may arise if your application does not work on IPV6 networks. They will mention this in the notes if that is the issue.
Solution: Check Apple's documentation on supporting IPV6 networking, including some common items to look for that may trip up IPV6 support. Learn more about how to set up an IPV6 network for testing.
Missing Info.plist key
Accessing a variety of protected system features, like location or bluetooth, requires an entry in the info.plist. Over time, Apple may add new entries (as when they added “when in use”) that require new entries for capabilities you supported with other plots entries previously.
Solution: Review all of the plist entries required for protected capabilities your app supports, also make sure they are clear as to why the user needs to grant you access to that ability.
For more impactful abilities like the location “always” permission, you may want to add something to the Notes metadata file the app submission, so the reviewer is clear as to why the application needs that permission.
👉Read more: What the Epic v. Apple Ruling Could Mean for Your App
The Xcode simulators for iOS 14 work differently than iOS 13 and earlier. We step you through how to get IAP purchase testing working in the iOS 14 simulators.
Apple just released Xcode 12 and iOS 14. This release includes great new features for in-app purchases which we’ve discussed here. With iOS 14 now live for your customers, there are some very important changes to how you need to test and develop your app with StoreKit and IAPs. In this article, we provide an overview of important changes to testing purchases in the iOS 14 simulators.
If you've installed Xcode 12 and run anything using StoreKit in an iOS 14 simulator, you may have noticed a problem - StoreKit products you set up on AppStoreConnect no longer load, so any purchase pages you set up may be blank!
App running in iOS 13.2 simulator from Xcode 12. Products still appear.
Now, iOS 13 simulators will still work as you are used to, as will sandbox testing on device (with some enhancements which we'll get into in future articles). You'll likely want to continue testing on iOS 14 simulators as well, so how can we get our products back?
The answer: migrate our existing App Store Connect product definitions to a StoreKit configuration file for Xcode12
There you can see a list of the products defined in your application. Find the ones you want to use for testing, then click on one to load product details:
Open your application project in Xcode 12 and create a new StoreKit Configuration:
You can choose whatever name you like and save it into your project; if desired you could even have multiple StoreKit Configuration files. Do not add it to the project on creation; it actually gets set up in the application Scheme as we'll see shortly.
The configuration .storekit file will be added to your project navigation, where you can then select it to edit:
When you have the configuration open for editing, use the "+" button to add the product you previously had selected in App Store Connect:
At this step, choose the type of product that you have set up in App Store Connect, either consumable, non-consumable, or auto-renewable subscription in-app purchase. In this example case I'll add an auto-renewable subscription product.
As a first step because I've not added a subscription product before, it will ask for a subscription group - it's a good practice to name this group the same as you have in your App Store Connect product:
Now we have a new product with a temporary name, ID, and price.
The most important thing to change is to alter the product ID to match what you have in AppStoreConnect since your code will be expecting a product with a specific product ID, as I've done with this example product:
You can enter as many products as you like.
Now that we have a StoreKit configuration file, how can we make use of it? In the top menu bar target dropdown, select "Edit Scheme":
When you select Edit Scheme, you'll be able to select the configuration file you just created for the "StoreKit Configuration" entry:
When you activate this configuration, it will stay enabled for any change in simulator or device you select to run on. Note that it will not have any effect on pre-iOS 14 simulators or devices, it needs iOS 14 to take effect.
Also it is worth noting that after adding this Configuration to the scheme, the project will still load and work in older versions of Xcode, but they may revert or clear the chosen StoreKit configuration.
Now when I run on an iOS 14 simulator I see the product I added on my payment screen:
👉Read more: Test In-App Purchases iOS Guide
Note that in my case my payment screen is showing only the product I entered correctly, that's also the only one that would work for any purchase attempts that used StoreKit to purchase. The others are products the paywall knows should be there, but provides only placeholder values for since it can find only one of the three products desired in the StoreKit configuration.
To keep testing simple you may want to keep the number of products defined in a StoreKit configuration minimal so it's easier to track with App Store Connect changes, or you can exactly duplicate your full product set.
In the case of subscription testing in the simulator, because you can select custom time acceleration you could use any subscription duration and have it expire quickly if you wished - that and more will be talked about in more detail in a future article.
Note that this StoreKit configuration you've enabled in the Scheme will also be used on an iOS 14 device, and you'll not be using a sandbox account. If you want to run a device build and still use a Sandbox account for testing, simply deselect the StoreKit Configuration in the application Scheme.
👉Read more: Maximize iOS Testing Coverage: Unit Test vs. UI Test
How to put the customer experience at the center of your mobile SDK.
Yesterday, we released of the Nami SDK for iOS. To mark this release, we thought we’d share some details about how we approach development of the SDK including our key design goals.
Creating great customer experiences is a core part of Nami’s company values. As part of our mission of BCE, the Nami SDK was built around five key concepts that we believe to be vitally important:
Below we’ll touch on each of these concepts in more detail.
We’ve experienced SDKs that take way too much time to integrate or create additional unforeseen work. Adding a new SDK to your app should be as painless as possible. That’s why we’ve focused on making the Nami SDK incredibly straightforward to adopt.
Minimal code to get started. We strive to get you up and running with just a few lines of code. The basic integration steps are straight forward so you can stay focused on what really matters: building a great app!
No third-party dependencies. The Nami SDK does not require any third-party code or dependencies. This helps us keep the size small and the integration points to a minimum. The Nami SDK will never generate a dependency conflict.
👉Read more: Announcing Our New Documentation Portal
Receipt validation. We take care of the complexity in the Apple APIs for details around app purchase receipts, including monitoring updates to purchases including users canceling a subscription or getting a refund for a purchase, thus re-disabling a feature in an application.
Easy purchase testing. We know that testing in-app purchases is a hassle. That’s why we wanted to make it much easier to test a variety of purchase flows, so that you do not have to spend as much time managing StoreKit test users or going through tedious system prompts just to test your apps reaction to purchase changes.
Cached purchase details. StoreKit doesn’t offer a way to ask for purchased products, so developers typically have to cache purchases. The Nami SDK stores away information about purchases so they can be easily checked at launch if the user is already subscribed without relying on the network.
Avoiding "Restore Purchases”. The restore purchase flow is clumsy for a user of any application so we use receipt validation and other techniques to determine if a user on a new device or with a reloaded app has previously purchased products.
Cloud-enable your existing sales sheet. Attach your existing subscription sales sheet or offer screen to the Nami SDK to make it more dynamic. This means you can make changes from the cloud and require fewer app updates.
Adopt a Nami Paywall. Ready to turn over control of the sales sheet to your product or marketing team? The Nami Paywall is a native (no WebViews!), feature rich sales sheet experience that can be fully managed in the cloud by non-developers. Meanwhile, in your app code the Nami Paywall handles much of the complexity of offering subscriptions with StoreKit.
Maintain main app performance. Nami uses background, low priority queues for work whenever possible. Sometimes providing a great user experience means processing or information must be fetched quickly. When this is necessary, we strive to do as little work on the main thread as we can, or at times when app performance is not impacted.
No UI impact. We strive to ensure whenever possible that none of the work that Nami does will impact UI performance. As described above, whenever possible Nami works on the background thread, but we also take extra care to avoid doing work during certain kinds of animations such as controller transitions.
Protect and conserve battery life. We avoid unneeded work on the device. This means taking care to exercise power consuming features like network requests in a way that allows the system to batch with other requests as much as possible.
Customers are expecting more privacy in apps every day and the regulatory landscape is constantly changing, making it more risky to be producing software and not have your user’s privacy as a top priority. Are your vendors and partners helping you reach your privacy goals? The Nami SDK strives to be a strong partner in your goal to protect your users data.
Privacy is core tenant of our company mission: BCE, so expect read more in future posts detailing our technical approaches.
No PII. While we do have to collect a unique identifier to be able to offer personalized experiences, the Nami SDK does not collect email addresses, geolocation information (except at a country level), or device identifiers.
Data minimization. We employ data minimization to limit what we collect to only what is absolutely necessary. This is in stark contrast to the many SDKs that collect voluminous and invasive data with little regard for the user.
👉Read more: Cross-Platform App Development
Simplify but do not hide complex StoreKit workflows. We want our SDK to help provide you with the simplest possible means of receiving important information about the purchase flow within an application, while still providing access to the underlying StoreKit metadata you may need for more complex workflows.
Built for Swift 5. We built the Nami SDK using Swift 5 to ensure we get all the benefits of Apple’s modern programming language. This helps us iterate more quickly and keep quality high.
Detailed release notes. With each update to our SDK, we’re adding detailed release notes to our GitHub repository. While it’s generally a good idea to keep the SDKs you ship in your app current, our detailed release notes will help you prioritize updates.
Example apps included. Code fragments are great, but we appreciate SDKs that include fully functional example apps (that compile!). With our latest release, we shipped our first example app with more to come. We’ll be sure to keep examples updated with new operating system, developer IDE, and toolchain releases.
Take a look at our developer documentation and let us know how we’re doing.
We want the Nami SDK to be as delightful as possible to use, so if there is anything you find confusing or would find helpful, please let us know or open a GitHub issue!
Apple announced a lot of changes to subscriptions and IAP in iOS 14 at WWDC this year. Our summary has you covered on the most important changes.
Apple’s WWDC20 conference this year contained many updates about in-app purchases, subscriptions, and the StoreKit framework. In case you did not catch it all or have time to watch all the videos, we’ve got a short recap of the most important updates you’ll want to be aware of.
The major updates to in-app purchases fall into three main categories
Let’s take a look at each one of these in a little more detail.
👉Read more: Monetizing SwiftUI Apps: IAP Subscriptions
The ability to create a subscription that can be shared by a family is one of the most exciting announcements this year. Now you will have the option to create products at different price points for a family shareable subscription or a subscription for an individual consumer.
To use this feature, you first must enable family sharing in App Store Connect for a particular subscription. By turning this feature on, all members of the same family set up in iCloud can share a single purchase to a subscription. This is a great new benefit you can offer your customers with a little bit of configuration on your app.
Once you turn on family sharing for a subscription, you cannot disable it.
The consumer purchasing the subscription must also agree to enable subscription sharing for family members. The person making the purchase can also choose to shut this off. Once a subscription with family sharing has been purchased, other members of the family can access the subscription by doing a Restore Purchase action on their device.
StoreKit will see each family member’s subscription as a unique transaction as if they had purchased the subscription themselves.
SKProduct now also adds an "isFamilySharable" flag to a product, so you can tell which products are available to share with other family members and present that information to the user.
There is also a new API on the SKPaymentQueue to help manage when a user decides to disable family sharing called didRevokeEntitlementForProductIdentifiers. In this method, you’ll need to re-verify the receipt and revoke access as needed.
Apple announced some exciting improvements to how you can track attribution of any ad campaigns you are running for your app. The highlights include
Setting custom conversion values is a very powerful new feature. Now instead of just tracking installs, you can track whether users are engaging with specific features in your app, registering for an account, or even making an in-app purchase.
SKAdNetwork now has an updateConversionValue that takes an integer. On subsequent calls, Apple will update this value only if the new integer is greater than the old one. This means it is very important to structure your conversion values along a path of increasing engagement in your app, to get the most insight.
Apple used to only track first-time downloads via SKAdNetwork, but now there is a new field Redownload. You can use this to see if your ad was successful in getting a user to reinstall your app.
Finally, Apple has added a Source App ID, so you can track if certain apps are better at acquiring you downloads.
In your SKAdNetwork postback, you’ll now receive Redownload, and optional values for Source App ID and Conversion Value. These last two are optional because Apple will only include them if it can do so without risking identifying a specific customer.
If you have a catalog of multiple apps, Apple announced some great new features for you. There’s a new API called SKOverlay that allows you to present an overlay at the bottom of your app’s UI that customers can directly install an app from.
Two main uses for this new UI element are
For more details on each of these customer facing updates, watch the second half of this video:
https://developer.apple.com/wwdc20/10661
There were two new Server to Server notifications announced this year
REFUND is the first ever server notification for content types other than auto-renewable subscriptions.
With the introduction of the REFUND notification, Apple is broadening the scope of this service to include all purchase types. We expect more server-side data for all IAP types to be added over time, so it is important to make sure you are handling server-side events from Apple in your IAP process.
In StoreKit, there's a new listener callback to detect refunds, or subscriptions being revoked, didrevokeEntitlemnetsForProductIdentifiers.
The new DID_RENEW event is going to be a great addition that gives a more clear signal to track what is happening with your users.
Apple continues to move step-by-step in the direction of their Server to Server notifications being the primary way for an app to understand the customer lifecycle and payment activity. When receiving a Server to Server notification, server-side verification of the receipt is still the best way to then validate the status of your customers.
For more details on the latest changes for server to server notifications, watch the first half of this video:
https://developer.apple.com/wwdc20/10661
Apple announced a whole set of tools for testing your in-app purchases in Xcode. These new capabilities will be a huge help in testing and adding IAP to your app.
It is now possible to use and test StoreKit in the simulator. This will allow you to
Apple introduced StoreKitTesting, a testing framework to enable you to test various aspects of purchase flows for both unit and UI tests.
👉Read more: What’s New with In-App Purchases at WWDC 21
Apple has announced a number of on-device improvements to working with the Sandbox.
All of these new StoreKit testing options open up a bunch of new ways to be confident that your purchase process is working correctly and reliably.
For more details on StoreKit Testing, watch this video:
https://developer.apple.com/videos/play/wwdc2020/10659/
Nami’s platform offers tools to simplify providing great purchase experiences to your app users, handle all the server-side events including receipt verification and Server to Server notifications, as well as tools to help you test the purchase lifecycle in your app. Sign up for free to get started.
iOS 15 introduces tons of new subscription and IAP capabilties including refunds, customer support, StoreKit 2, new server APIs and server notifications, and more.
The introduction of iOS 15 is bringing many new updates to in-app purchases and subscriptions, including StoreKit 2, Server Notifications v2, new server-side APIs, customer refunds, signed transactions, in-app events, new customer support capabilities, and new sandbox testing options. It was a huge week at Apple’s WWDC 21 for subscription and in-app purchase news. Tons of updates are coming this year to help make it even easier to sell subscriptions and IAPs in your apps. Below we’ll look at the highlights of the various announcements, how they might impact your apps, and how Nami works with all the latest and greatest tools from Apple.
Let’s start with refunds as this was the single biggest announcement that offers new capabilities to app publishers to help create and maintain happy customers.
Apple had 2 big announcements here:
Starting a refund request in your app is very simple, there’s a new StoreKit method beginRefundRequest(). This will launch an Apple-controlled UI that collects a reason for the refund request.
Note that the request still goes to Apple for review and then they make a decision and let the customer know, the refund is not instantaneous.
Another new interesting feature is Apple has already started sending a new CONSUMPTION_REQUEST server notification. This is a request for information about whether the customer has made use of their consumable IAP to help in making a decision on a refund request. For apps that sell consumable purchases, this will be a very important request to respond to.
To learn more about refunds, check out Apple’s full session.
Customer support on the App Store has always been tricky because Apple did not have any tools to help app developers look up a particular customer record or transaction. They’ve now introduced a new server-side API that will enable building tools to help you look up customer records. It is all triggered from the Invoice ID that the customer receives via email for each purchase (and each renewal of an auto-renewable subscription).
The only challenge here is that this ID is only available to the customer and not to the app developer, so you can’t pre-build and store this type of information in advance. It will only be provided by the customer when they reach out to your customer service.
There are a number of updates included in what Apple is calling Signed Transactions, which are an update to the existing Apple receipt. We won’t get into the technical details of working with Signed Transactions in this article but look for some coverage from us soon to help you understand how to work with these new elements. These new transactions are signed using JSON Web Signature (JWS) and you’ll have to decode them to validate and check the data contained within.
Perhaps the single most important part of Signed Transactions is you can now directly verify a purchase in your app on-device without having a server that talks to Apple to verify the receipt. This requirement was often a barrier to app developers and is a big simplification for fighting against fraud in your app.
A couple of other interesting notes:
iOS 15 is bringing big changes to Swift in general and the StoreKit framework in particular. Most notably is the introduction of Swift Concurrency which is heavily used in the new StoreKit 2 framework.
In addition to simplifying how you work with receipts using the new Signed Transactions discussed in the last section, there are a few new capabilities that are coming with StoreKit 2
Let’s look at a few simple examples here. In the new StoreKit you no longer have to work through SKProductRequest. Getting a product is as simple as:
To then purchase that product, you can make the following call:
Finally, to verify the purchase on-device you can:
Pretty simple! There’s a lot more you can do with StoreKit 2, but this simple set of a couple of examples really highlights the power and simplicity o the new APIs.
The other big capability we mentioned above is to help you if your app has accounts. You can now create an App Account Token that is a UUID that Apple will tie to the purchase for you.
Simply add this App Account Token to the purchase and it will show up in any method where you access purchases as well as in the Signed Transactions. This greatly simplifies how you manage access to purchases when you have an app account. In StoreKit 1, all this logic has to be custom-built on your server.
Watch Apple’s Meet StoreKit 2 session to learn more.
Apple announced a number of new server-side APIs. Here’s a full list:
Consumption - provide data on consumable IAP usage to help Apple make a decision on a refund request
In-App Purchase History - Get a list of Signed Transactions for all purchase the user has made
Invoice Lookup - takes the order ID from their emailed invoice and returns if the ID is valid and any associated Signed Transactions
Refunded Purchases - takes the original transaction ID and returns a list of Signed Transactions for any purchases that have been refunded
Renewal Extension - allows you to extend the current bill term of a subscription by up to 90 days. Used to issue refunds or credits on subscriptions
Subscription Status - Check the status of a subscription at any time with the original transaction ID
There was a lot of news here if you maintain the server-side portion of Apple’s in-app purchase system for your app. There were 2 big pieces of news here:
As many of you will know, the existing Server Notifications from Apple do not have a 1:1 mapping to subscription lifecycle events. In some cases, multiple events are sent that have to be interpreted in combination to understand what has happened. Additionally, you always have to make an additional API call to Apple to get the latest receipt which is required to determine the lifecycle state of the customer.
In addition to these big changes, a few other items were announced:
The new family notifications will be sent in both v1 and v2 versions of Server notifications. Different notifications will be available in each version.
Learn more in Apple’s Manage in-app purchases on your server WWDC 21 session.
Apple announced new capabilities in sandbox testing, including the ability to:
You will be able to control all of this from App Store Connect.
This is a huge improvement that will enable easier testing on a few key items:
Look for more recommendations from us on improved testing patterns for your in-app purchases in the future.
👉Read more: IAP Updates WWDC20
In a very exciting announcement from Apple, they now support In-App Events. In-app events will be promoted and searchable on the App Store. Events can require specific in-app purchases or subscriptions to access and may contain a deep link to take you directly to the specific event page in your app.
If you plan to create in-app events for your app, you can use Nami Paywalls to help gate access to your in-app events. Simply create an Entitlement that grants access to the event and when deep linking to the screen for the event, check the entitlement status with the Nami SDK. If the user does not have the correct entitlement, display a paywall created with our cloud Paywall Creator to ask them to make the purchase to grant access.
This is a great new feature to help create value in your app for your paying customers. We are looking forward to seeing how different apps use this in the future.
The great news here is that most of these updates only require some internal changes to our platform, and do not affect how you as a developer use Nami.
Nami also helps to solve the challenge of leveraging iOS 15 only features in apps that still have a large install base on iOS 14 as we’ll be supporting both frameworks in our SDK.
We are excited about the new IAP use cases around in-app events that you’ll be able to enable with Nami and will be working to seamlessly integrate the new refund capabilities with our existing Customer Support tools.
Excited about testing out StoreKit 2 code yourself? Did you know Nami can run along-side a custom-written StoreKit implementation. You can still leverage all the great tools on the Nami platform and use your own StoreKit code. Reach out to us to learn more.
👉Read more: Monetizing SwiftUI Apps: IAP Subscriptions
Tip jars are an easy way to start generating revenue from users that love your app. We step through the entire process of adding a tip jar to an iOS app.
These days, it's easier than ever to put together an application you see a need for and release it to help the world.
Over time all apps need updating - new devices are released, features like Dark Mode, or just graphic design overhauls.
Anyone can support these changes for a while but eventually, the reality is that all app developers need money to keep an application going.
So why not let your biggest fans, the people who love using your app, help you out? If you don't even try, you might never know just how much people appreciate what you have built.
It seems daunting to put together a payment system, even more, to figure out what areas of your app you might want to change to paid access - but you don't have to go that far, there's a simpler path to start - the tip jar!
Simply put, the tip jar is a way for someone who really loves using your application, to show support for you through a one-time in-app purchase. It's a reward for work you've already done and for improving someone's life, a way for someone to ask you to please keep going because they love what you have done.
Technically speaking, Apple provides three distinct ways to receive payment:
The last category, consumable products, is perfect for tip jars - you can simply message your users from time to time or add a screen for them to find in your app when they seek a way to reward you for your work.
It's a single purchase that doesn't have to be remembered, although you may choose to do so if you wish to remember who recognized your app so you can provide them with some small reward.
👉Read more: Monetizing Digital Products with Subscriptions
You can just set up StoreKit yourself to create your own tip jar, but it can be complex to do right and frustrating to add without bugs that are hard to test for.
Nami can help you by providing the UI for the paywall for you, and over time can figure out what people are doing in your app (and for how long) that makes them more likely to tip - that way in the future you can prompt for tips only for users that are gaining the most from your application, and most likely would be happy to share their appreciation!
Setting up payments can be complex, Nami makes these basic cases incredibly simple for you to start using.
Create a consumable or non-recurring subscription product for your app (or possibly a few at different price points). In App Store Connect, visit your app, click on Features, then add products:
Give it a name and a product identifier, then set the price:
Sign-up for a Nami account for your app
Setup an application in our system
You'll need the application bundle ID.
Take the one or more product ID's you created earlier in App Store Connect, In Nami, go to Products, then add the same product ID's you have defined in App Store Connect - if they do not match exactly, you'll not see that product appear in your paywall (which can be a useful thing to double-check if you see a paywall but not your products).
Nami can handle more advanced cases like multiple paywalls, and campaigns that you can change out on the fly - but to start with for our simple Tip Jar, all we need is a single paywall built using the Paywall Creator!
Once you've added your products, go to the paywall tab on the side, and create a new paywall - Name it something like Tip Jar, then for the title and body put in something that makes people excited to be supporting your application, and gives further explanation of how their contributions will help you continue to improve the app. The products you add to this paywall will automatically show up below the title and body and can be purchased by your users. Also, make sure to add a background image for iPad and iPhone which is required to fully set up a paywall!
For example, here's the Nami Tip Jar example paywall:
Lastly even though you have just one paywall, you still need a campaign to display it - so quickly create a campaign, add your paywall you just added, and make the campaign live. You can leave the rules alone for now or have the paywall appear every so often after they open the app by selecting the rule to open after so many sessions. Here's how we have the tip jar for our example configured:
Be sure to make the campaign Active on the Overview tab, then you are ready to go! For more help please see the Nami documentation on setting up paywalls and campaigns.
👉Read more: Promotional In-App Purchase Best Practices
Although Nami paywalls can be made to show automatically, for tip jars it's great to have a way for users to be able to seek out and find your tip jar to use whenever they like.
Usually, it's good to put this in something like an "About Me" page that you probably have already - for example in our demo app we have a section describing the basic philosophy of color, and telling people who the application developers are. That's the first place someone might look for ways to support your app, without it being too in the face for your users.
For example, to start with our sample Tip Jar application has this About screen:
After adding some text about why someone might want to tip, and a button that will enable the user to get to our tip jar:
Now that we have the UI to show the user how to get to our tip jar, we are ready to add Nami so that it can present the tip jar for us and handle payments!
Add the SDK to your application as described here:
https://docs.namiml.com/docs/add-the-nami-sdk-to-your-project
After you follow those instructions, you should have the Nami Framework added to your project/workspace like so:
Also make sure you have code in your AppDelegate to tell Nami what your App Platform ID is:
Once the SDK has been added, you just need one line of code to have the button you added raise the tip jar on demand!
Don't forget to import the Nami framework at the top of the file!
Run the project, and you should see something like this come up in the simulator when you use your button:
If you like, you can go ahead and tap one of the buttons to simulate a purchase.
There's one other thing we need to do to make sure the purchases work as intended - if we are using Consumable products, we need to consume them after purchase so they can be purchased again in the future.
It's also probably a good idea to thank whoever supports your app through purchases, so the last step is to add code that does just that - in the app delegate you can set up a handler to display such a message whenever a purchase through your tip jar is detected. Let's add a handler to do both things:
Now when a purchase is made, the user should get a nice message and the tip jar product will be cleared!
Once that is working, you should raise the test paywall again and take screenshot of the simulator using the File-New ScreenShot option of the simulator. Upload this image (saved onto your desktop and named "Simulator Screen Shot") into the review metadata for each of the product definitions in App Store Connect:
It is also a good idea to add in a description of how the App Store tester can access the payment screen in your app, to make it easier for them to test payments.
Lastly, you need to make sure the products you are using for your tip jar are added to your next App Store submission for review! Go to the App Store tab in App Store Connect for your app, then click on the prepare for submission item:
Scroll down to find the In-App Purchases section:
Click on "+" and add your products.
Now when you are ready to submit your app, the App Store reviewer will know they need to test these products and they can be added properly to your app on the App Store.
That's it! Now you have a path for your application community to provide you with support to help make your application even better.