arrow-left

All pages
gitbookPowered by GitBook
1 of 1

Loading...

In-App Purchase Blocks (with RevenueCat)

Offer extra content and features your users can purchase — including digital goods, subscriptions, and premium content — directly within your app.

circle-info

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

hashtag
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.

hashtag
Prerequisites

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

hashtag
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.

hashtag
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 . 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.

hashtag
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.

hashtag
Old IAP Blocks

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

hashtag
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!

hashtag
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. Click Delete.

hashtag
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.

hashtag
1. RevenueCat Account Setup

hashtag
What is 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.

circle-info

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: .

hashtag
RevenueCat Setup

  1. Create a . Additional instructions are available here: .

  2. Configure your RevenueCat project and apps. Instructions are available here: .

hashtag
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.

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

hashtag
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.

hashtag
Publish Your App

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

circle-info

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

hashtag
4. Configure Products

hashtag
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.

hashtag
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.

hashtag
Google Play Product Setup

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

  1. Log into your 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.

.

hashtag
Apple App Store

hashtag
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.

hashtag
iOS Product Setup

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

hashtag
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.

hashtag
Features available for you to add on RevenueCat:

  • Offerings - only create one

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

  • Entitlements

hashtag
Features available on RevenueCat but not supported by Thunkable:

  • Metadata

  • Paywalls

circle-info

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

hashtag
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.

hashtag
Block: In App Purchase Offerings

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

hashtag
Output: Offerings

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

chevron-rightOfferings - JSON Output Examplehashtag

This information is primarily used to:

  • Display products on the screen

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

hashtag
Sample Block Combination

hashtag
Block: Buy In App Purchase Package

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

hashtag
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: .

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”:

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

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”.

hashtag
Block: In App Purchase Customer Info

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

hashtag
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.

chevron-rightCustomer Info - JSON Output Examplehashtag

hashtag
Sample Block Combination

hashtag
Block: Restore In App Purchases

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

hashtag
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.

chevron-rightCustomer Info - JSON Output Examplehashtag

hashtag
Sample Block Combination

hashtag
7. Publish Project

hashtag
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.

circle-exclamation

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.

hashtag
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 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.

hashtag
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: .

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").

hashtag
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.

hashtag
Android Subscription Management

hashtag
Cancel, pause, or change a subscription on Google Play

circle-exclamation

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

  1. Open the Google Play app .

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

  3. Tap Payments & subscriptions Subscriptions.

circle-info

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 .

hashtag
iOS Subscription Management

hashtag
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. Tap or your profile picture at the top right, then tap Subscriptions.

Read more about managing your iOS subscriptions .

Proceed with the
below to implement new IAP blocks.
  • Click API Keys in the sidebar menu.

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

  • Click Show key associated with your iOS app.

  • Copy the provided iOS key.

  • Navigate to your Thunkable tab.

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

  • Paste the copied iOS key into the Public IOS SDK Key field.

  • Return to your RevenueCat tab.

  • Click Show key associated with your Android app.

  • Copy the provided Android key.

  • Navigate to your Thunkable tab.

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

  • Drag and drop the "in app purchase offerings" block into your workspace.

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

  • Create in-app products or subscriptions.

  • - not necessary, but you can create an entitlement if you wish
    Drag and drop the required blocks into your workspace.
  • If they don't look like the blocks below, right-click on the block and select Show advanced block.

  • Select the subscription you want to cancel.
  • Tap Cancel subscription.

  • Follow the instructions.

  • Choose a subscription, then do any of the following:

    • Change or cancel an existing subscription.

    • Resubscribe to an expired subscription.

    • with other family members in your Family Sharing group.

    {
      "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": {}
    }
    "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"
        }
      ]
    
    
    "availablePackages": [
        Package_1,
        Package_2
     ]
    {
      "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
    }
    {
      "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"
    }
    Apple Developerarrow-up-right
    Google Play Consolearrow-up-right
    RevenueCatarrow-up-right
    RevenueCatarrow-up-right
    RevenueCat Account Setup
    Connect Thunkable and RevenueCat
    Add an IAP Block to Your Thunkable Project and Publish
    RevenueCatarrow-up-right
    RevenueCat Pricingarrow-up-right
    RevenueCat Accountarrow-up-right
    Revenue Cat SDK Quickstartarrow-up-right
    Revenue Cat SDK Quickstartarrow-up-right
    Publish to the Apple App Storechevron-right
    Publish to Google Play Storechevron-right
    Google Play Consolearrow-up-right
    Revenue Cat Google Play Product Setuparrow-up-right
    RevenueCat iOS Product Setuparrow-up-right
    Offerings - JSON Output Example
    Publish to the Apple App Storechevron-right
    Publish to Google Play Storechevron-right
    TestFlight Overviewarrow-up-right
    Set up an open, closed, or internal testarrow-up-right
    herearrow-up-right
    herearrow-up-right
    order of operations
    Configure your products.
    Google Play Store (Android)
    Apple App Store (iOS)
    Map Products in RevenueCat
    Add In-App Purchase Blocks
    Publish Project
    Test App
    Share an eligible App Store subscriptionarrow-up-right
    Google Play
    and then
    the My Account button