Godot IAP: A Brutally Honest Guide to In-App Purchases

Posted by Gemma Ellison
./
July 13, 2025

Forget dragging your feet! In-app purchases (IAP) in Godot can feel intimidating, but it doesn’t have to be that way. Let’s tackle this head-on and get your game making money, the right way. This isn’t some fluffy tutorial. We’re diving into practical steps, real-world pitfalls, and the brutally honest truth about implementing IAP in Godot.

Platform Setup: Google Play’s Gauntlet

First, the boring but crucial part: platform setup. Let’s start with Google Play. This is often where developers get bogged down, so listen up!

Create a Google Play Developer account and a new application. Fill out all the required information - app details, store listing, content rating. This is painfully tedious but vital.

Next, create in-app products. Non-consumable items (like unlocking a level) are the easiest to start with. Define a product ID (e.g., unlock_level_2), a name, and a price.

Pitfall: Google Play Console loves to take its sweet time. Don’t expect your IAP to be ready immediately after creating it. Plan for delays, sometimes up to 24 hours.

Finally, generate a Google Play Licensing Key. You’ll need this in your Godot project. This key is found under “Development tools” -> “Services & APIs” in the Google Play Console.

iOS App Store Connect: Apple’s Ecosystem

Setting up IAP with Apple is a similar process, but with its own quirks. Create an application in App Store Connect, and navigate to Features > In-App Purchases.

Create a new non-consumable in-app purchase, providing a product ID (e.g., remove_ads), name, and price tier.

Challenge: Apple requires you to upload a build of your app with IAP functionality before you can fully configure the IAP. This can be frustrating. Create a basic placeholder build that contains the IAP code and upload it for review (even if the IAP functionality isn’t fully implemented yet).

Retrieve your Shared Secret from App Store Connect (App > General > App-Specific Shared Secret). This is crucial for verifying receipts and preventing fraud.

Godot IAP Plugin Integration: Bridging the Gap

Now, the fun part: integrating a Godot IAP plugin. I recommend using the “GodotIAP” plugin (available on the Asset Library). It’s actively maintained and well-documented.

Install the plugin through the Asset Library. Activate it in Project Settings -> Plugins.

Create a new scene (e.g., iap_manager.tscn). Add a script to this scene. This script will handle all IAP logic.

Here’s a basic example:

extends Node

signal purchase_successful(product_id)

var iap

func _ready():
    iap = GodotIAP.new()
    iap.connect("purchase_success", self, "_on_purchase_success")
    iap.connect("purchase_failed", self, "_on_purchase_failed")
    iap.connect("products_loaded", self, "_on_products_loaded")

    # Replace with your product IDs
    var product_ids = ["unlock_level_2", "remove_ads"]
    iap.init(product_ids)

func purchase(product_id):
    iap.purchase(product_id)

func _on_purchase_success(product_id):
    print("Purchase successful: " + product_id)
    emit_signal("purchase_successful", product_id)

func _on_purchase_failed(product_id, message):
    print("Purchase failed: " + product_id + " - " + message)

func _on_products_loaded(products):
    print("Products loaded: " + str(products))

Add this iap_manager.tscn scene as an Autoload singleton. This makes it accessible from anywhere in your game.

Implementing the Purchase Flow: Real-World Example

Let’s say you want to unlock level 2 of your game using an IAP. In the scene where level selection occurs:

extends Node2D

func _on_unlock_level_button_pressed():
    # Check if the level is already unlocked (e.g., using a save file)
    if SaveManager.is_level_unlocked(2):
        print("Level 2 already unlocked!")
        return

    # Purchase the level
    get_node("/root/IAPManager").purchase("unlock_level_2")

    # Connect to the purchase_successful signal to unlock the level
    get_node("/root/IAPManager").connect("purchase_successful", self, "_on_purchase_successful")

func _on_purchase_successful(product_id):
    if product_id == "unlock_level_2":
        print("Unlocking level 2!")
        SaveManager.unlock_level(2)
        # Disconnect the signal to prevent multiple unlocks
        get_node("/root/IAPManager").disconnect("purchase_successful", self, "_on_purchase_successful")

Common Mistake: Forgetting to disconnect signals after a purchase can lead to unintended behavior (e.g., unlocking the level multiple times). Always disconnect signals when they’re no longer needed.

Receipt Verification: Guarding Against Fraud

Don’t trust the client! Receipt verification is crucial to prevent fraud. Both Google Play and App Store provide mechanisms for verifying receipts server-side.

For Google Play, use the Google Play Developer API. Send the purchase token and product ID to your server. Your server then verifies the purchase with Google’s servers.

For App Store, send the receipt data to Apple’s verification endpoint. Apple will return a JSON response indicating the validity of the receipt.

Important: Never store your API keys or Shared Secret directly in your Godot project! This is a massive security risk. Store them on your server and access them through API calls.

Beyond the Basics: Considerations for Success

Implementing IAP is more than just code. Consider these points:

  • Pricing: Research competitor pricing. Don’t overprice your items.
  • User Experience: Make the purchase flow seamless. Don’t bombard users with IAP prompts.
  • Localization: Localize your IAP names and descriptions.

IAP implementation requires careful planning, meticulous coding, and constant vigilance against fraud. But, with the right approach, it can be a powerful way to monetize your Godot games. Don’t be afraid to experiment, learn from your mistakes, and most importantly, protect yourself from the dark side of in-app purchasing.