Intermediate60 minutesUpdated October 2025

How to Add In-App Purchases to Your Next.js App

Monetize your Next.js mobile app with in-app purchases and subscriptions using RevenueCat. This guide covers setup, implementation, and testing for both iOS and Android.

📋 Prerequisites

  • Next.js app with Capacitor configured
  • App published on App Store Connect (iOS) or Google Play Console (Android)
  • RevenueCat account (free tier available)
  • Understanding of app monetization basics

🎯 What You'll Learn

  • Set up RevenueCat for your app
  • Create products in App Store Connect and Google Play
  • Install and configure RevenueCat SDK
  • Display available products
  • Handle purchase flows
  • Verify purchase receipts
  • Restore purchases

Step-by-Step Guide

1

Create RevenueCat Account

Sign up for a free RevenueCat account at revenuecat.com. RevenueCat handles the complexity of in-app purchases across platforms.

💡 Note: RevenueCat is free for up to $10k monthly tracked revenue.

2

Configure App in RevenueCat

Add your iOS and Android apps in the RevenueCat dashboard.

1. Go to RevenueCat Dashboard → Projects
2. Click "Add App"
3. Enter your iOS Bundle ID and Android Package Name
4. Upload App Store Connect API key (iOS)
5. Upload Google Play service account JSON (Android)
3

Create Products in App Stores

Create your in-app purchase products in App Store Connect and Google Play Console.

💡 Note: Product IDs should be the same across both platforms for easier management (e.g., 'premium_monthly').

4

Configure Products in RevenueCat

Set up your products and offerings in RevenueCat dashboard.

1. Go to Products → Add Product
2. Enter product ID from app stores
3. Create an Offering (e.g., "premium")
4. Add products to the offering
5. Make offering the default
5

Install RevenueCat SDK

Install the RevenueCat Capacitor plugin in your Next.js project.

npm install @revenuecat/purchases-capacitor
npx cap sync
6

Initialize RevenueCat

Configure RevenueCat in your app with your API keys.

lib/revenuecat.ts
import { Purchases } from '@revenuecat/purchases-capacitor';
import { Capacitor } from '@capacitor/core';

export async function initializeRevenueCat() {
  if (!Capacitor.isNativePlatform()) {
    return; // RevenueCat only works on native platforms
  }

  const platform = Capacitor.getPlatform();
  const apiKey = platform === 'ios' 
    ? process.env.NEXT_PUBLIC_REVENUECAT_IOS_KEY!
    : process.env.NEXT_PUBLIC_REVENUECAT_ANDROID_KEY!;

  await Purchases.configure({ apiKey });
  
  console.log('RevenueCat initialized');
}
7

Call Initialization on App Start

Initialize RevenueCat when your app launches.

app/layout.tsx
'use client';
import { useEffect } from 'react';
import { initializeRevenueCat } from '@/lib/revenuecat';

export default function RootLayout({ children }) {
  useEffect(() => {
    initializeRevenueCat();
  }, []);
  
  return (
    <html>
      <body>{children}</body>
    </html>
  );
}
8

Fetch Available Products

Create a component to display available in-app purchases.

components/PremiumUpgrade.tsx
'use client';
import { useState, useEffect } from 'react';
import { Purchases } from '@revenuecat/purchases-capacitor';

export default function PremiumUpgrade() {
  const [packages, setPackages] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    async function fetchOfferings() {
      try {
        const offerings = await Purchases.getOfferings();
        if (offerings.current) {
          setPackages(offerings.current.availablePackages);
        }
      } catch (error) {
        console.error('Error fetching offerings:', error);
      } finally {
        setLoading(false);
      }
    }
    fetchOfferings();
  }, []);

  async function handlePurchase(pkg: any) {
    try {
      const result = await Purchases.purchasePackage({ 
        aPackage: pkg 
      });
      
      if (result.customerInfo.entitlements.active['premium']) {
        alert('Purchase successful! You now have premium access.');
      }
    } catch (error: any) {
      if (!error.userCancelled) {
        alert('Purchase failed: ' + error.message);
      }
    }
  }

  if (loading) return <div>Loading...</div>;

  return (
    <div>
      <h2>Upgrade to Premium</h2>
      {packages.map((pkg: any) => (
        <button 
          key={pkg.identifier}
          onClick={() => handlePurchase(pkg)}
        >
          {pkg.product.title} - {pkg.product.priceString}
        </button>
      ))}
    </div>
  );
}
9

Check User Subscription Status

Create a utility to check if the user has an active subscription.

lib/checkPremium.ts
import { Purchases } from '@revenuecat/purchases-capacitor';

export async function checkPremiumStatus(): Promise<boolean> {
  try {
    const customerInfo = await Purchases.getCustomerInfo();
    return customerInfo.customerInfo.entitlements.active['premium'] !== undefined;
  } catch (error) {
    console.error('Error checking premium status:', error);
    return false;
  }
}
10

Implement Restore Purchases

Add a button to restore previous purchases (required by Apple).

async function restorePurchases() {
  try {
    const customerInfo = await Purchases.restorePurchases();
    
    if (customerInfo.customerInfo.entitlements.active['premium']) {
      alert('Purchases restored! You have premium access.');
    } else {
      alert('No previous purchases found.');
    }
  } catch (error) {
    alert('Failed to restore purchases');
  }
}

🚀 Next Steps

  • Add subscription management UI
  • Implement promotional offers
  • Set up webhook for backend verification
  • Add analytics tracking for purchases
  • Test subscription lifecycle

Ready to Build Your Mobile App?

Get NextNative and start converting your Next.js website to a mobile app in minutes.

🎁50% off for the first 40 customers, 5 left

Related Tutorials

Compare Mobile Frameworks

Still deciding on your tech stack? Check out these comparisons

📚 Further Reading

Explore our comprehensive documentation to learn more about NextNative features and capabilities.