How to Add In-App Purchases: A Step-by-Step Setup

Table of Contents
Big thanks to our contributors those make our blogs possible.

Our growing community of contributors bring their unique insights from around the world to power our blog. 

Introduction

In-app purchases (IAPs) have become essential for monetizing mobile apps. Whether you offer premium content, digital goods, or subscription plans, integrating IAPs lets users buy features or content directly from within your app. This guide walks you through the entire setup process—covering both iOS (App Store) and Android (Google Play) platforms—so you can offer seamless, secure purchases to users. We’ll cover prerequisites, product configuration, code integration, receipt validation, and best practices to help you implement consumables, non-consumables, and subscriptions correctly.

1. Understand In-App Purchase Types

Before diving into implementation, it’s crucial to know the primary IAP categories:

  1. Consumable Purchases
    • Definition: Items that users purchase, consume, and may buy again.
    • Examples: In-game currency, extra lives, temporary power-ups.
    • Behavior: Once delivered, they expire or diminish after use.
  2. Non-Consumable Purchases
    • Definition: One-time purchases that unlock permanent features or content.
    • Examples: Unlocking a pro version, removing ads, purchasing a premium filter pack.
    • Behavior: Remains in the user’s purchase history; can be restored if reinstalled.
  3. Auto-Renewable Subscriptions
    • Definition: Recurring subscriptions that automatically renew at defined intervals (weekly, monthly, yearly).
    • Examples: Premium streaming service, magazine access, advanced app features.
    • Behavior: Charge recurs until the user cancels; includes free trial options.
  4. Non-Renewing Subscriptions
    • Definition: Time-bound access to content that does not auto-renew.
    • Examples: 6-month fitness program, seasonal content pass.
    • Behavior: Expires at the end of the period; user must repurchase.

2. Prerequisites and Setup

2.1 Developer Accounts

  • iOS (Apple Developer Program)
    • Enrollment: $99/year
    • Required to access App Store Connect, configure IAPs, and distribute apps.
  • Android (Google Play Developer Console)
    • Enrollment: One-time fee of $25
    • Grants access to Google Play Console for IAP configuration and app publishing.

2.2 Project Prerequisites

  • Development Environment
    • iOS: Xcode (latest stable version), Xcode Project with a valid Bundle ID.
    • Android: Android Studio (latest stable version), Gradle-based project with a valid Package Name and keystore for signing.
  • Testing Devices and Sandbox Accounts
    • iOS:
      • Use sandbox test accounts in App Store Connect → “Users and Access” → “Sandbox” tab.
      • Add a test user email (cannot be an Apple ID in use).
    • Android:
      • Add license-testing Gmail addresses in Play Console → “Setup” → “License testing.”
      • Install the app via internal testing track to test IAP flows.
  • External Libraries (Optional but Recommended)
    • For simplified IAP management, consider using wrappers like RevenueCat (supports both iOS and Android).
    • For manual integration, you’ll work directly with StoreKit (iOS) and Google Play Billing Library (Android).

3. Configure Products in App Store Connect (iOS)

3.1 Create Your App Record

  1. Log into App Store Connect.
  2. Navigate to “My Apps” and select your app or click “+” → New App.
  3. Fill in App Name, Bundle ID (matching Xcode), SKU, and other details.

3.2 Navigate to In-App Purchases Section

  1. In your app’s dashboard, click “Features”“In-App Purchases”.
  2. Click the “+” button to add a new product.

3.3 Define a New Product

  • Product ID (Reference Name): Unique string (e.g., com.yourcompany.app.premium_upgrade).
  • Type: Choose Consumable, Non-Consumable, or Auto-Renewable Subscription.
  • Reference Name: Internal name visible only to you.
  • Pricing: Select a price tier; you can adjust later.
  • Localization: Provide a Display Name and Description for each language you support.
  • Review Information: Upload screenshots or demo videos if required (for subscriptions with free trials).
  • Cleared for Sale: Toggle to “Yes” when ready.

Repeat for each IAP you plan to offer. Once “Waiting for Review,” you can still test in sandbox mode.

4. Configure Products in Google Play Console (Android)

4.1 Create Your App Record

  1. Log into Google Play Console.
  2. Click “Create app”, fill in App Name, Default Language, App Type, and Pricing Model.
  3. Set up your app’s store listing details (icon, screenshots) if not done already.

4.2 Navigate to In-App Products (Google Play Billing)

  1. In the left menu, go to “Monetize”“Products”“In-app products”.
  2. Click “Create product”.

4.3 Define a New Product

  • Product ID: Unique ID (e.g., premium_upgrade, coins_pack_100).
  • Product Type: Select Managed Product (i.e., consumable or non-consumable) or Subscription.
  • Title & Description: Provide a user-facing name and detailed description.
  • Pricing: Set the local price for each currency if desired.
  • Activate: Toggle to make the product active.
  • Save: Click “Save”. It appears under “Draft” until you publish an app version that references the product.

Repeat for each product or subscription. Only active products will appear to users.

5. Integrate In-App Purchase SDKs

5.1 iOS Integration with StoreKit

  1. Import StoreKit Framework
    In your Swift file: swiftCopyEditimport StoreKit
  2. Conform to SKProductsRequestDelegate and SKPaymentTransactionObserver swiftCopyEditclass IAPManager: NSObject, SKProductsRequestDelegate, SKPaymentTransactionObserver { static let shared = IAPManager() var products: [SKProduct] = [] func startObserving() { SKPaymentQueue.default().add(self) } func stopObserving() { SKPaymentQueue.default().remove(self) } // Fetch product information func fetchProducts() { let productIdentifiers: Set<String> = ["com.yourcompany.app.premium_upgrade"] let request = SKProductsRequest(productIdentifiers: productIdentifiers) request.delegate = self request.start() } // SKProductsRequestDelegate func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) { products = response.products // Now you can show products in UI } // Purchase a product func purchase(product: SKProduct) { let payment = SKPayment(product: product) SKPaymentQueue.default().add(payment) } // SKPaymentTransactionObserver func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) { for transaction in transactions { switch transaction.transactionState { case .purchased: // Deliver content and finish SKPaymentQueue.default().finishTransaction(transaction) case .failed: // Handle error SKPaymentQueue.default().finishTransaction(transaction) case .restored: // Restore purchases SKPaymentQueue.default().finishTransaction(transaction) default: break } } } }
  3. Initialize Observation
    In AppDelegate or at app launch: swiftCopyEditfunc application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { IAPManager.shared.startObserving() return true }
  4. Validate Receipts (Optional but Recommended)
    • For increased security, verify receipts either on your server or locally using Apple’s endpoint.
    • Send transaction.transactionReceipt to your backend and use Apple’s validation API (https://buy.itunes.apple.com/verifyReceipt).

5.2 Android Integration with Google Play Billing Library

  1. Add Billing Dependency
    In build.gradle (app module): gradleCopyEditimplementation 'com.android.billingclient:billing:5.0.0'
  2. Initialize BillingClient javaCopyEditBillingClient billingClient = BillingClient.newBuilder(context) .setListener(this) // PurchasesUpdatedListener .enablePendingPurchases() .build(); billingClient.startConnection(new BillingClientStateListener() { @Override public void onBillingSetupFinished(BillingResult billingResult) { if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) { // Query available products queryAvailableProducts(); } } @Override public void onBillingServiceDisconnected() { // Retry connection } });
  3. Query Available Products javaCopyEditList<String> skuList = new ArrayList<>(); skuList.add("premium_upgrade"); // For subscriptions, use BillingClient.SkuType.SUBS SkuDetailsParams params = SkuDetailsParams.newBuilder() .setSkusList(skuList) .setType(BillingClient.SkuType.INAPP) .build(); billingClient.querySkuDetailsAsync(params, (billingResult, skuDetailsList) -> { if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && skuDetailsList != null) { for (SkuDetails skuDetails : skuDetailsList) { // Save details for purchase flow } } });
  4. Launch Purchase Flow javaCopyEditBillingFlowParams flowParams = BillingFlowParams.newBuilder() .setSkuDetails(selectedSkuDetails) .build(); billingClient.launchBillingFlow(activity, flowParams);
  5. Handle Purchase Updates
    Implement PurchasesUpdatedListener in your activity: javaCopyEdit@Override public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) { if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && purchases != null) { for (Purchase purchase : purchases) { handlePurchase(purchase); } } else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.USER_CANCELED) { // Handle user cancelation } else { // Handle other errors } } private void handlePurchase(Purchase purchase) { // Acknowledge or consume purchase AcknowledgePurchaseParams acknowledgeParams = AcknowledgePurchaseParams.newBuilder() .setPurchaseToken(purchase.getPurchaseToken()) .build(); billingClient.acknowledgePurchase(acknowledgeParams, billingResult -> { if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) { // Grant entitlement } }); }
  6. Validate Purchases
    • Use Google Play Developer API on your server to verify purchase tokens.
    • Ensures purchase authenticity and prevents fraud.

6. Implement Purchase Restoration and Subscription Management

6.1 iOS: Restoring Purchases

  1. Invoke Restore swiftCopyEditfunc restorePurchases() { SKPaymentQueue.default().restoreCompletedTransactions() } // Handle restored transactions in paymentQueue(_:updatedTransactions:) case .restored: // Unlock content SKPaymentQueue.default().finishTransaction(transaction)
  2. Display Restore Button
    • Add a “Restore Purchases” button in your UI for non-consumable and subscriptions.

6.2 Android: Querying Purchase History

  1. Query Purchases javaCopyEditbillingClient.queryPurchasesAsync(BillingClient.SkuType.INAPP, (billingResult, purchasesList) -> { if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) { for (Purchase purchase : purchasesList) { // Check if purchase is acknowledged and grant entitlement if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED && !purchase.isAcknowledged()) { // Acknowledge or consume } } } });
  2. Subscriptions
    • For subscriptions, query SkuType.SUBS instead of INAPP and handle accordingly (grant access based on subscription status).

7. Best Practices and Tips

7.1 Maintain a Secure Back End

  • Always validate receipts (iOS) or purchase tokens (Android) on your server to prevent client-side exploits.
  • Store user purchase status (entitlements) securely in your database.

7.2 Implement Graceful Error Handling

  • User-Friendly Messages: Show clear error messages if a purchase fails (e.g., “Purchase didn’t go through; please try again.”).
  • Retry Logic: For transient errors like network timeouts, offer a retry button.

7.3 Optimize User Experience

  • Transparent Pricing: Clearly communicate what users get for their money—include screenshots or video previews for premium content.
  • Subscription Reminders: For auto-renewable subscriptions, inform users before charging (iOS notifications or in-app messages).
  • Restore Flow: Make the “Restore Purchases” option easy to find for users who reinstall or switch devices.

7.4 Monitor Analytics and Revenue

  • Use analytics tools (Firebase Analytics, Mixpanel) to track purchase events, churn rates, and lifetime value (LTV).
  • Analyze which products convert best and adjust pricing or packaging accordingly.

Conclusion

Adding in-app purchases to your app can unlock a powerful revenue stream while enhancing user experience. By understanding the different purchase types—consumable, non-consumable, and subscriptions—you can tailor offerings to fit your app’s needs. Follow these steps: set up developer accounts, configure products in App Store Connect and Google Play Console, integrate StoreKit or Google Play Billing in your code, validate purchases on your server, and implement restore flows. Finally, apply best practices—secure validation, clear messaging, and data-driven optimization—to ensure a seamless, trustworthy purchasing experience. With a properly implemented IAP system, you’ll be well-positioned to grow your app’s monetization and retain satisfied users.

Let's connect on TikTok

Join our newsletter to stay updated

Sydney Based Software Solutions Professional who is crafting exceptional systems and applications to solve a diverse range of problems for the past 10 years.

Share the Post

Related Posts