In-App Purchase Blocks (with RevenueCat)

This feature may only be available for Creators on certain Thunkable plans. Please refer to our pricing page for more information: Thunkable pricing.

Overview

In-app purchases (IAP) refer to the ability to offer additional content or features within a mobile app for users to buy using real money. This provides a monetization strategy for app developers, allowing them to generate revenue from their apps. It's a way to offer users the option to enhance their app experience by purchasing extra items or features, such as digital goods, subscriptions, and premium content.

Prerequisites

Publishing an app to the App Store and Google Play Store with in-app purchase blocks requires accounts with the following:

Compatibility

  • In-app purchases are supported on the Android and iOS platforms.

  • In-app purchases are not supported in web apps.

  • You cannot test in-app purchases with the Thunkable Live app.

Migrating to the New IAP Blocks

If your app utilized the old in-app purchase (IAP) blocks, you’ll need to remove the keys from the old IAP component, remove the old blocks, replace them with the new IAP blocks, and create and configure an account with RevenueCat. These updates are needed before you publish an app with IAP functionality. If you currently have a published app with IAP capabilities, it will remain active. However, you cannot re-publish your app until the IAP blocks have been updated.

Which IAP Blocks do I have?

If you don’t know which version of the blocks you’ve used, we can help! Look at the IAP blocks in your project and compare them to the images below.

Old IAP Blocks

Each of the old IAP blocks has dropdown options. If your app has these blocks, you’ll need to update them.

New IAP Blocks

All of the new versions of the IAP blocks are purple and do not have dropdown options. If your app has these blocks, no block update is needed!

Migrate to Improved IAP Blocks

To migrate from the old in-app purchase blocks to the improved in-app purchase blocks:

  1. Delete the old in-app purchase blocks.

  2. Under the Advanced heading, click the gear icon associated with your existing IAP component.

  3. Proceed with the order of operations below to implement new IAP blocks.

    You may be able to skip step 4 in the order of operations below if your products are correctly configured in the Google Play Store and/or Apple App Store.

Order of Operations

You must follow the steps outlined below in the order they're listed.

This documentation assumes that you are publishing to both the Apple App Store and Google Play Store. If this isn't accurate, ignore the platform-specific instructions for the other platform.

1. RevenueCat Account Setup

What is RevenueCat?

RevenueCat is a platform that is used to manage in-app subscriptions and purchases. It provides tools and services to handle subscription billing, manage user entitlements, and analyze revenue data. This platform simplifies implementing and managing in-app purchases and subscriptions, making it easier for you to monetize your apps effectively.

RevenueCat allows you to start for free with everything you need to build, maintain, and grow your subscription app. Once you surpass their defined earning threshold ($2,500 USD at the time of publishing), you will be required to pay. More information is available here: RevenueCat Pricing.

RevenueCat Setup

  1. Create a RevenueCat Account. Additional instructions are available here: Revenue Cat SDK Quickstart.

  2. Configure your RevenueCat project and apps. Instructions are available here: Revenue Cat SDK Quickstart.

2. Connect Thunkable and RevenueCat

Connecting your Thunkable and RevenueCat accounts requires copying and pasting API keys between the two accounts. We recommend having two tabs open concurrently, one signed in to RevenueCat and the other to Thunkable with your project open.

To connect your Thunkable and RevenueCat accounts:

  1. Navigate to your RevenueCat tab.

  2. Click Projects in the header.

  3. Select your project from the dropdown.

  4. Click API Keys in the sidebar menu.

  5. Your project's public API keys are created automatically and appear under the heading Public app-specific API keys.

  6. Click Show key associated with your iOS app.

  7. Copy the provided iOS key.

  8. Navigate to your Thunkable tab.

  9. Click the gear icon in the sidebar to access the project's App Settings.

  10. Return to your RevenueCat tab.

  11. Click Show key associated with your Android app.

  12. Copy the provided Android key.

  13. Navigate to your Thunkable tab.

  14. Paste the copied Android key into the Public Android SDK Key field.

3. Add an IAP Block to Your Thunkable Project and Publish

Add One IAP Block to Your Thunkable Project

To access the in-app purchase blocks:

  1. Navigate to the Blocks tab.

  2. Under the App Features heading, click In-App Purchase.

  3. A drawer of in-app purchase blocks opens.

Publish Your App

For more on publishing your app, please see these docs:

pagePublish to the App Store (iOS)pagePublish to Play Store (Android) with AAB

The first time you upload the AAB, you can select any of the available testing tracks.

4. Configure Products

Store Configuration

Products are what your app's users purchase. They are the individual SKUs (stock-keeping units) used to identify and track your inventory or stock. The stores (Apple and Google) process these SKUs and charge the user.

Your products must be configured for each store you intend to sell with. This is done within the respective stores.

Google Play Store

Product configuration for Android devices is done in the Google Play Console, Google's central hub for managing app releases, testing, in-app purchases, and more.

Google Play Product Setup

To set up your in-app purchases in your Google Play Console:

  1. Log into your Google Play Console account.

  2. Click Products under the Monetize heading in the sidebar.

  3. Select In-app products or Subscriptions depending on what your app offers. We'll provide instructions for each below.

  4. You must create a Google Play Payments profile if you haven't already done so. Follow the on-screen instructions.

  5. Create in-app products or subscriptions.

Revenue Cat Google Play Product Setup.

Apple App Store

Agreements, Tax, and Banking

To sell iOS products, you must sign Apple's most recent Paid Applications Agreement and fill out your bank and tax information. This is located at App Store Connect > Agreements, Tax, and Banking. This needs to be completed before you can test any purchases.

iOS Product Setup

Follow these instructions to set up your in-app purchases in App Store Connect: RevenueCat iOS Product Setup.

5. Map Products in RevenueCat

RevenueCat uses an Entitlements system to control access to premium features and Offerings to manage the set of products you offer customers.

Entitlements are the level of access that a customer is "entitled" to after purchasing a specific product. Offerings are a simple way to organize the in-app products you wish to "offer" and configure them remotely.

Features available for you to add on RevenueCat:

  • Offerings - only create one

  • Products - select either a subscription or a one-time purchase

  • Entitlements - not necessary, but you can create an entitlement if you wish

Features available on RevenueCat but not supported by Thunkable:

  • Metadata

  • Paywalls

The RevenueCat dashboard shows figures in USD. It is not currently possible to change the display currency in RevenueCat.

6. Add In-App Purchase Blocks

To access the in-app purchase blocks:

  1. Navigate to the Blocks tab.

  2. Under the App Features heading, click In-App Purchase.

  3. A drawer of in-app purchase blocks opens.

  4. Drag and drop the required blocks into your workspace.

  5. If they don't look like the blocks below, right-click on the block and select Show advanced block.

Block: In App Purchase Offerings

The "in app purchase offerings" block has two outputs: the standard error output and offerings.

Output: Offerings

The "offerings" output block returns information about the products users can purchase.

Offerings - JSON Output Example
{
  "lifetime": {
    "packageType": "LIFETIME",
    "product": {
      "priceString": "$0.99",
      "productCategory": "NON_SUBSCRIPTION",
      "price": 0.99,
      "subscriptionPeriod": null,
      "introPrice": null,
      "identifier": "clicker_0.99_chef_skin",
      "description": "Give the beaver a chef outfit",
      "productType": "NON_CONSUMABLE",
      "discounts": [],
      "currencyCode": "USD",
      "title": "Chef skin"
    },
    "identifier": "$rc_lifetime",
    "offeringldentifier": "default"
  },
  "identifier": "default",
  "availablePackages": [
    {
      "identifier": "$rc_lifetime",
      "product": {
        "title": "Chef skin",
        "introPrice": null,
        "identifier": "clicker_0.99_chef_skin",
        "productType": "NON_CONSUMABLE",
        "discounts": [],
        "description": "Give the beaver a chef outfit",
        "currencyCode": "USD",
        "productCategory": "NON_SUBSCRIPTION",
        "subscriptionPeriod": null,
        "price": 0.99,
        "priceString": "$0.99"
      },
      "offeringldentifier": "LIFETIME"
    }
  ],
  "serverDescription": "Default Offering",
  "metadata": {}
}

This information is primarily used to:

  • Display products on the screen

  • Make purchases with the "buy in app purchase package" block

Sample Block Combination

Block: Buy In App Purchase Package

The "buy in app purchase package" block has three outputs: the standard error output, purchase, and user cancelled.

Sample Block Combination

In the block combination below, the "in app purchase offerings" block retrieves the "offerings" output. You can see the contents of this block's output here: Offerings - JSON Output Example.

Within the "offerings" output, the content you need is within “availablePackages”, an array that holds one or multiple packages. This is an example of multiple packages within “availablePackages”:

"availablePackages": [
    {
      "identifier": "$rc_lifetime",
      "product": {
        "title": "Chef skin",
        "introPrice": null,
        "identifier": "clicker_0.99_chef_skin",
        "productType": "NON_CONSUMABLE",
        "discounts": [],
        "description": "Give the beaver a chef outfit",
        "currencyCode": "USD",
        "productCategory": "NON_SUBSCRIPTION",
        "subscriptionPeriod": null,
        "price": 0.99,
        "priceString": "$0.99"
      },
      "offeringldentifier": "LIFETIME"
    },
{
      "identifier": "$rc_lifetime",
      "product": {
        "title": "Chef skin 2",
        "introPrice": null,
        "identifier": "clicker_0.99_chef_skin_2",
        "productType": "NON_CONSUMABLE",
        "discounts": [],
        "description": "Give the beaver a second chef outfit",
        "currencyCode": "USD",
        "productCategory": "NON_SUBSCRIPTION",
        "subscriptionPeriod": null,
        "price": 0.99,
        "priceString": "$0.99"
      },
      "offeringldentifier": "LIFETIME"
    }
  ]

It can be viewed and understood in the simplified way below.

"availablePackages": [
    Package_1,
    Package_2
 ]

To purchase Package_1, you must get that package from the offering’s object using the “get property of object” block. Then, you can direct it with the string “availablePackages” followed by the index of the package we want purchased. In this case, we want Package_1, which has an index of 0 in an array. The final string will be “availablePackages.0”. For Package_2, it would be “availablePackages.1”.

Block: In App Purchase Customer Info

The "in app purchase customer info" block has two outputs: the standard error output and customer info.

Output: Customer Info

The "customer info" output block returns information on the items the user has purchased. This information can be used within the Thunkable app to check for and give the corresponding purchased item/feature.

Customer Info - JSON Output Example
{
  "allPurchasedProductldentifiers": [
    "clicker_0.99_chef_skin"
  ],
  "firstSeen": "2023-08-15T00:58:48Z",
  "originalApplicationVersion": "1.0",
  "activeSubscriptions": [],
  "allExpirationDatesMillis": {
    "clicker_0.99_chef_skin": null
  },
  "requestDateMillis": 1702083929000,
  "originalPurchaseDateMillis": 1375340400000,
  "latestExpirationDate": null,
  "allPurchaseDates": {
    "clicker_0.99_chef_skin": "2023-08-16T01:40:14Z"
  },
  "managementURL": null,
  "nonSubscriptionTransactions": [
    {
      "purchaseDateMillis": 1692150014000,
      "productidentifier": "clicker_0.99_chef_skin",
      "transactionldentifier": "78da6c4bfa",
      "productld": "clicker_0.99_chef_skin",
      "purchaseDate": "2023-08-16T01:40:14Z",
      "revenueCatld": "78da6c4bfa"
    }
  ],
  "originalPurchaseDate": "2013-08-01T07:00:00Z",
  "originalAppUserld": "$RCAnonymouslD:ba8c53a4bd5a4c318a3f340aef7c1320",
  "allExpirationDates": {
    "clicker_0.99_chef_skin": null
  },
  "latestExpirationDateMillis": null,
  "entitlements ": {
    "all": {
      "default": {
        "originalPurchaseDate": "2023-08-16T01:40:14Z",
        "ownershipType": "PURCHASED",
        "willRenew": false,
        "expirationDateMillis": null,
        "latestPurchaseDate": "2023-08-16T01:40:14Z",
        "store": "APP_STORE",
        "periodType": "NORMAL",
        "unsubscribeDetectedAt": null,
        "identifier": "default",
        "isActive": true,
        "latestPurchaseDateMillis": 1692150014000,
        "isSandbox": true,
        "productidentifier": "clicker_0.99_chef_skin",
        "expirationDate": null,
        "unsubscribeDetectedAtMillis": null,
        "billingIssueDetectedAt": null,
        "originalPurchaseDateMillis": 1692150014000,
        "billingIssueDetectedAtMillis": null
      }
    },
    "active": {
      "default": {
        "billingIssueDetectedAtMillis": null,
        "expirationDateMillis": null,
        "ownershipType": "PURCHASED",
        "willRenew": false,
        "expirationDate": null,
        "isActive": true,
        "unsubscribeDetectedAt": null,
        "identifier": "default",
        "store": "APP_STORE",
        "periodType": "NORMAL",
        "productidentifier": "clicker_0.99_chef_skin",
        "originalPurchaseDateMillis": 1692150014000,
        "unsubscribeDetectedAtMillis": null,
        "billingIssueDetectedAt": null,
        "isSandbox": true,
        "latestPurchaseDateMillis": 1692150014000,
        "originalPurchaseDate": "2023-08-16T01:40:14Z",
        "latestPurchaseDate": "2023-08-16T01:40:14Z"
      }
    }
  },
  "requestDate": "2023-12-09T01:05:29Z",
  "allPurchaseDatesMillis": {
    "clicker_0.99_chef_skin": 1692150014000
  },
  "firstSeenMillis": 1692061128000
}

Sample Block Combination

Block: Restore In App Purchases

The "restore in app purchases" block has two outputs: the standard error output and customer info.

Output: Customer Info

The "customer info" output block returns information on the items the user has purchased. This information can be used within the Thunkable app to check for and give the corresponding purchased item/feature.

Customer Info - JSON Output Example
{
  "allPurchasedProductldentifiers": [
    "clicker_0.99_chef_skin"
  ],
  "allPurchaseDatesMillis": {
    "clicker_0.99_chef_skin": 0
  },
  "originalAppUserld": "$RCAnonymousID:ba8c53a4bd5a4c318a3f340aef7c1320",
  "allExpirationDates": {
    "clicker_0.99_chef_skin": null
  },
  "originalApplicationVersion": "1.0",
  "activeSubscriptions": [],
  "allExpirationDatesMillis": {
    "clicker_0.99_chef_skin": null
  },
  "requestDateMillis": 1702086506000,
  "originalPurchaseDateMillis": 1375340400000,
  "latestExpirationDate": null,
  "allPurchaseDates": {
    "clicker_0.99_chef_skin": "2023-08-16T01:40:14Z"
  },
  "managementURL": null,
  "firstSeen": "0-0-0",
  "latestExpirationDataMills": null,
  "requestDate": "2023-12-09T01:48:26Z",
  "entitlements": {
    "active": {
      "default": {
        "productldentifier": "clicker_0.99_chef_skin",
        "originalPurchaseDate": "2023-08-16T01:40:14Z",
        "expirationDateMillis": null,
        "latestPurchaseDateMillis": 1692150014000,
        "isSandbox": true,
        "willRenew": false,
        "ownershipType": "PURCHASED",
        "billingIssueDetectedAt": null,
        "unsubscribeDetectedAtMillis": null,
        "billingIssueDetectedAtMillis": null,
        "originalPurchaseDateMillis": 1692150014000,
        "expirationDate": null,
        "latestPurchaseDate": "2023-08-16T01:40:14Z",
        "periodType": "NORMAL",
        "unsubscribeDetectedAt": null,
        "isActive": true,
        "store": "APP_STORE",
        "identifier": "default"
      }
    },
    "all": {
      "default": {
        "billingIssueDetectedAt": null,
        "unsubscribeDetectedAtMillis": null,
        "expirationDateMillis": null,
        "latestPurchaseDate": "2023-08-16T01:4",
        "productIdentifier": "clicker_0.99_chef_skin",
        "identifier": "default",
        "isActive": true,
        "periodType": "NORMAL",
        "store": "APP_STORE",
        "unsubscribeDetectedAt": null,
        "latestPurchaseDateMillis": 1692150014000,
        "isSandbox": true,
        "originalPurchaseDateMillis": 1692150014000,
        "billingIssueDetectedAtMillis": null,
        "willRenew": false,
        "ownershipType": "PURCHASED",
        "expirationDate": null,
        "originalPurchaseDate": "2023-08-16T01:40:14Z"
      }
    }
  },
  "firstSeenMillis": 1692061128000,
  "nonSubscriptionTransactions": [
    {
      "productld": "clicker_0.99_chef_skin",
      "transactionldentifier": "78da6c4bfa",
      "purchaseDate": "2023-08-16T01:40:14Z",
      "revenueCatld": "78da6c4bfa",
      "purchaseDateMillis": 1692150014000,
      "productidentifier": "clicker_0.99_chef_skin"
    }
  ],
  "originalPurchaseDate": "2013-08-01T07:00:00Z"
}

Sample Block Combination

7. Publish Project

pagePublish to the App Store (iOS)pagePublish to Play Store (Android) with AAB

8. Test App

To test the IAP blocks you must publish your app to the Google Play Store or Apple App Store. You cannot test IAP with web preview or the Thunkable Live app.

Be mindful to leave extra time for testing in your app development cycle to allow time for each respective store to review your apps. Depending on your stage of app development, a review could take anywhere from an hour to four days.

App Store (iOS)

On iOS, you must submit to the App Store via TestFlight to test the features. You can read more about TestFlight here: TestFlight Overview.

TestFlight creates a sandbox environment automatically. When you send your update to the app store, you can test it without having it go to the live version.

Play Store (Android)

On Android, publish to the Play Store via internal beta testing. You can read more about internal beta testing in the Play Store here: Set up an open, closed, or internal test.

You have to upload the APK or AAB file to the Play Store console before you can add any In-App Purchases.

There are two ways you can test how a pre-release app functions on the Google Play store: You can publish an app to the alpha or beta distribution channels. This makes the app available on the Google Play store, but only to the testers you put on a "whitelist."

In a few cases, you can test Google Play functionality with an unpublished app. For example, you can test an unpublished app's in-app billing support by using static responses, special reserved product IDs that always return a specific result (like "purchased" or "refunded").

Managing Subscriptions

At this time, there are no blocks to support in-app subscription management by the user.

Users can manage their own subscriptions in the Google Play Store or Apple App Store.

We recommend including instructions in your app or app’s website that outline the processes below.

Android Subscription Management

Cancel, pause, or change a subscription on Google Play

Subscriptions on Google Play renew automatically unless you unsubscribe through the Google Play app. Uninstalling an app won't automatically cancel your subscription.

  1. At the top right, tap the profile icon.

  2. Select the subscription you want to cancel.

  3. Tap Cancel subscription.

  4. Follow the instructions.

If you have a subscription with an app and the app gets removed from Google Play, your future subscription will be canceled. Your past subscriptions will not be refunded.

Read more about managing your Android subscriptions here.

iOS Subscription Management

Change or cancel your App Store subscriptions

  1. Open the App Store app on your iOS device or on a computer

    • Sign in to the App Store if necessary

  2. Choose a subscription, then do any of the following:

Read more about managing your iOS subscriptions here.

Last updated