Lesson 9: In-App Purchases & Monetization
Welcome back! Now that your mobile puzzle game has polished gameplay and engaging mechanics, it's time to implement monetization systems that generate revenue while maintaining a positive player experience. In this lesson, you'll learn how to integrate in-app purchases, design ethical monetization strategies, and create pricing models that work for both players and your business.
What You'll Learn
- Design ethical monetization strategies for puzzle games
- Implement Unity IAP (In-App Purchases) system
- Create consumable and non-consumable purchase items
- Set up store product catalogs for iOS and Android
- Implement purchase validation and receipt verification
- Design player-friendly monetization flows
- Test purchases in sandbox environments
Prerequisites
- Unity 2022.3 LTS or newer
- Completed Lesson 8: Performance & Battery Optimization
- Basic understanding of mobile app stores
- Unity IAP package (we'll install it in this lesson)
- Developer accounts for App Store and Google Play (for testing)
Why Monetization Matters
Monetization is essential for sustaining your game development business, but it must be done thoughtfully. The best mobile games balance revenue generation with player satisfaction:
- Ethical monetization builds trust and long-term player relationships
- Player-friendly pricing increases conversion rates and retention
- Multiple revenue streams provide stability and growth opportunities
- Transparent systems reduce player frustration and support requests
Step 1: Install Unity IAP Package
Let's start by installing the Unity In-App Purchases package:
- Open Package Manager: Window → Package Manager
- Switch to Unity Registry: Click the dropdown and select "Unity Registry"
- Search for IAP: Type "In App Purchasing" in the search bar
- Install Package: Click "Install" on the "In App Purchasing" package
- Wait for Installation: Unity will download and install the package
Pro Tip: The Unity IAP package supports both iOS App Store and Google Play Store purchases, making it perfect for cross-platform monetization.
Step 2: Design Your Monetization Strategy
Before implementing purchases, design your monetization model:
Common Monetization Models for Puzzle Games
1. Freemium Model
- Free to download and play
- Optional in-app purchases for power-ups, extra lives, or cosmetic items
- Best for: Casual puzzle games with broad appeal
2. Premium Model
- One-time purchase to unlock full game
- No additional purchases required
- Best for: High-quality puzzle games with strong gameplay
3. Hybrid Model
- Free base game with optional purchases
- Premium currency for convenience items
- Best for: Games with multiple content types
Recommended Purchase Items for Puzzle Games
Consumable Items (can be purchased multiple times):
- Extra lives or moves
- Hint coins or power-ups
- Energy refills
- Temporary boosters
Non-Consumable Items (purchased once, owned forever):
- Remove ads permanently
- Unlock premium levels
- Character skins or themes
- Premium features
Subscription Items (recurring purchases):
- Monthly premium pass
- Ad-free subscription
- Exclusive content access
Step 3: Create Purchase Manager Script
Create a purchase manager to handle all IAP functionality:
- Create Script: Create new C# script called
PurchaseManager.cs - Add IAP Namespace: Import Unity IAP libraries
using UnityEngine;
using UnityEngine.Purchasing;
using System;
public class PurchaseManager : MonoBehaviour, IStoreListener
{
private static IStoreController m_StoreController;
private static IExtensionProvider m_StoreExtensionProvider;
// Product IDs - must match store product IDs exactly
public const string PRODUCT_REMOVE_ADS = "remove_ads";
public const string PRODUCT_EXTRA_LIVES = "extra_lives";
public const string PRODUCT_HINT_PACK = "hint_pack_10";
public const string PRODUCT_PREMIUM_PASS = "premium_pass";
void Start()
{
if (m_StoreController == null)
{
InitializePurchasing();
}
}
public void InitializePurchasing()
{
if (IsInitialized())
{
return;
}
var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
// Add products
builder.AddProduct(PRODUCT_REMOVE_ADS, ProductType.NonConsumable);
builder.AddProduct(PRODUCT_EXTRA_LIVES, ProductType.Consumable);
builder.AddProduct(PRODUCT_HINT_PACK, ProductType.Consumable);
builder.AddProduct(PRODUCT_PREMIUM_PASS, ProductType.Subscription);
UnityPurchasing.Initialize(this, builder);
}
private bool IsInitialized()
{
return m_StoreController != null && m_StoreExtensionProvider != null;
}
public void BuyProductID(string productId)
{
if (IsInitialized())
{
Product product = m_StoreController.products.WithID(productId);
if (product != null && product.availableToPurchase)
{
Debug.Log($"Purchasing product: {product.definition.id}");
m_StoreController.InitiatePurchase(product);
}
else
{
Debug.LogError("Product not available for purchase");
}
}
else
{
Debug.LogError("Store not initialized");
}
}
public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
{
Debug.Log("IAP initialized successfully");
m_StoreController = controller;
m_StoreExtensionProvider = extensions;
}
public void OnInitializeFailed(InitializationFailureReason error)
{
Debug.LogError($"IAP initialization failed: {error}");
}
public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
{
string productId = args.purchasedProduct.definition.id;
Debug.Log($"Purchase successful: {productId}");
// Handle purchase based on product ID
switch (productId)
{
case PRODUCT_REMOVE_ADS:
HandleRemoveAds();
break;
case PRODUCT_EXTRA_LIVES:
HandleExtraLives();
break;
case PRODUCT_HINT_PACK:
HandleHintPack();
break;
case PRODUCT_PREMIUM_PASS:
HandlePremiumPass();
break;
}
return PurchaseProcessingResult.Complete;
}
public void OnPurchaseFailed(Product product, PurchaseFailureReason failureReason)
{
Debug.LogError($"Purchase failed: {product.definition.id}, Reason: {failureReason}");
}
// Purchase handlers
private void HandleRemoveAds()
{
PlayerPrefs.SetInt("AdsRemoved", 1);
Debug.Log("Ads removed permanently");
}
private void HandleExtraLives()
{
int currentLives = PlayerPrefs.GetInt("Lives", 5);
PlayerPrefs.SetInt("Lives", currentLives + 5);
Debug.Log("Extra lives added");
}
private void HandleHintPack()
{
int currentHints = PlayerPrefs.GetInt("Hints", 0);
PlayerPrefs.SetInt("Hints", currentHints + 10);
Debug.Log("Hint pack added");
}
private void HandlePremiumPass()
{
PlayerPrefs.SetInt("PremiumPass", 1);
Debug.Log("Premium pass activated");
}
}
Step 4: Set Up Store Product Catalogs
Configure products in both App Store Connect and Google Play Console:
iOS App Store Setup
- Log into App Store Connect: https://appstoreconnect.apple.com
- Navigate to Your App: Select your app or create a new one
- Go to In-App Purchases: Features → In-App Purchases
- Create Products: Add each product with:
- Product ID: Must match your script (e.g., "remove_ads")
- Type: Consumable, Non-Consumable, or Auto-Renewable Subscription
- Price: Set pricing tier
- Localization: Add descriptions and names
Google Play Console Setup
- Log into Google Play Console: https://play.google.com/console
- Navigate to Your App: Select your app
- Go to Monetize: Monetize → Products → In-app products
- Create Products: Add each product with:
- Product ID: Must match your script
- Name: Display name for players
- Description: What the product does
- Price: Set price in your currency
Pro Tip: Use consistent product IDs across both platforms to simplify your code. The Unity IAP package handles platform differences automatically.
Step 5: Create Purchase UI
Design user-friendly purchase interfaces:
Purchase Button Script
using UnityEngine;
using UnityEngine.UI;
public class PurchaseButton : MonoBehaviour
{
[Header("Purchase Settings")]
public string productId;
public string displayName;
public string displayPrice;
[Header("UI References")]
public Button purchaseButton;
public Text nameText;
public Text priceText;
private PurchaseManager purchaseManager;
void Start()
{
purchaseManager = FindObjectOfType<PurchaseManager>();
if (nameText != null)
nameText.text = displayName;
if (priceText != null)
priceText.text = displayPrice;
if (purchaseButton != null)
purchaseButton.onClick.AddListener(OnPurchaseClicked);
}
public void OnPurchaseClicked()
{
if (purchaseManager != null)
{
purchaseManager.BuyProductID(productId);
}
}
}
Best Practices for Purchase UI
- Clear Value Proposition: Show what players get
- Transparent Pricing: Display prices clearly
- Non-Intrusive: Don't force purchases on players
- Easy to Dismiss: Always provide a close button
- Visual Feedback: Show purchase progress and confirmation
Step 6: Implement Purchase Validation
Add server-side validation for security (recommended for production):
using UnityEngine;
using System.Collections;
public class PurchaseValidator : MonoBehaviour
{
private const string VALIDATION_URL = "https://your-server.com/validate-purchase";
public void ValidatePurchase(string receipt, string productId)
{
StartCoroutine(SendValidationRequest(receipt, productId));
}
private IEnumerator SendValidationRequest(string receipt, string productId)
{
// Create validation request
WWWForm form = new WWWForm();
form.AddField("receipt", receipt);
form.AddField("product_id", productId);
form.AddField("platform", Application.platform.ToString());
using (UnityEngine.Networking.UnityWebRequest www =
UnityEngine.Networking.UnityWebRequest.Post(VALIDATION_URL, form))
{
yield return www.SendWebRequest();
if (www.result == UnityEngine.Networking.UnityWebRequest.Result.Success)
{
Debug.Log("Purchase validated successfully");
// Grant product to player
}
else
{
Debug.LogError($"Validation failed: {www.error}");
}
}
}
}
Pro Tip: For indie developers, Unity IAP's built-in validation is sufficient for most games. Server-side validation is recommended for high-revenue games or when security is critical.
Step 7: Test Purchases in Sandbox
Test your purchase system before release:
iOS Sandbox Testing
- Create Sandbox Tester: App Store Connect → Users and Access → Sandbox Testers
- Sign Out of App Store: On your test device
- Test Purchase: Attempt purchase in your app
- Sign In: Use sandbox tester credentials when prompted
- Verify Purchase: Check that purchase is processed correctly
Android Testing
- Upload APK: Upload to Google Play Console (internal testing track)
- Add Testers: Add test accounts to internal testing
- Test Purchase: Use test card numbers provided by Google
- Verify Purchase: Check purchase processing
Step 8: Implement Ethical Monetization Practices
Design monetization that players appreciate:
Do's
- Offer Value: Ensure purchases provide real value
- Be Transparent: Clearly explain what players get
- Respect Player Choice: Never force purchases
- Fair Pricing: Price items reasonably
- Provide Free Content: Always offer free gameplay
Don'ts
- Don't Be Aggressive: Avoid constant purchase prompts
- Don't Hide Costs: Always show prices clearly
- Don't Create Paywalls: Don't block essential gameplay
- Don't Mislead: Be honest about what purchases do
- Don't Ignore Feedback: Listen to player concerns
Mini Challenge: Implement Three Purchase Items
Create three different purchase items for your puzzle game:
- Consumable Item: Extra lives or moves (can buy multiple times)
- Non-Consumable Item: Remove ads permanently (buy once)
- Subscription Item: Premium pass with monthly benefits
Test each purchase type in sandbox and verify they work correctly.
Troubleshooting Common Issues
Issue: Purchases Not Working
Symptoms: Purchase button does nothing or shows error Solutions:
- Verify product IDs match store catalogs exactly
- Check that IAP is initialized before purchase attempts
- Ensure test accounts are set up correctly
- Check device internet connection
Issue: Products Not Available
Symptoms: Products show as unavailable Solutions:
- Verify products are approved in store consoles
- Check product IDs match exactly (case-sensitive)
- Ensure app is properly configured in store consoles
- Wait for store propagation (can take hours)
Issue: Receipt Validation Fails
Symptoms: Purchases complete but validation fails Solutions:
- Check receipt format for your platform
- Verify server validation endpoint is working
- Check network connectivity
- Review receipt data structure
Pro Tips
- A/B Test Pricing: Test different price points to find optimal pricing
- Bundle Products: Offer product bundles for better value
- Seasonal Sales: Run limited-time promotions to boost sales
- Analytics Integration: Track purchase conversion rates
- Player Feedback: Monitor reviews for monetization concerns
What's Next?
Congratulations! You've implemented a complete in-app purchase system. In the next lesson, you'll learn how to integrate analytics to track player behavior, measure monetization effectiveness, and make data-driven decisions to optimize your game's revenue.
Next Lesson: Lesson 10: Analytics & User Tracking - Integrate analytics for user behavior tracking and implement A/B testing for game features.
Key Takeaways
- Unity IAP package simplifies cross-platform purchase implementation
- Design ethical monetization that provides value to players
- Test all purchases thoroughly in sandbox environments
- Multiple revenue streams provide stability and growth
- Transparent pricing and clear value propositions increase conversions
Related Resources
- Unity IAP Documentation
- App Store In-App Purchase Guide
- Google Play Billing Guide
- Mobile Game Monetization Best Practices
Ready to track your game's performance? Bookmark this lesson and move on to analytics integration to understand how players interact with your monetization systems and optimize your revenue strategy.