Deploy a mobile checkout using Vercel

Get a step-by-step overview of how to deploy a flexible web checkout and landing page to Vercel for your iOS app, letting you establish a compliant external purchase flow to go direct to customers and unlock greater revenue potential.

With recent developments in legislation around the App Store, you can link users in the United States to an external checkout for purchases in iOS apps.

You can use the Paddle Web Monetization Kit to quickly create and deploy a Next.js app that includes Paddle Checkout, letting users securely make purchases outside your app. Customers tap a button in your app to open a checkout that you host on Vercel, then they're redirected to your app when they complete their purchase.

The app also comes with an out-of-the-box website, complete with marketing, pricing, and legal pages, so you can go live fast with a full go-to-market experience.

Grid of logos used in the Web Monetization Kit: Paddle, RevenueCat, Next.js, and Vercel.

What are we building?

In this tutorial, we'll deploy Paddle's Web Monetization Kit to Vercel in minutes, helping you build a seamless web checkout experience for your iOS app.

We'll walk through handling fulfillment using the RevenueCat x Paddle integration or webhooks.

What's not covered

This tutorial doesn't cover:

  • Handling authentication

    We assume you already have a way to identify your users, like Firebase or Sign in with Apple.

  • Native in-app purchases

    We'll launch Paddle Checkout in Safari then redirect users back to your app. Like the App Store, Paddle Checkout supports Apple Pay with no additional setup, plus other popular payment options.

  • Subscription lifecycle management

    You can use Paddle to handle all parts of the subscription lifecycle, including updating payment methods and canceling subscriptions using the prebuilt customer portal. We cover that elsewhere in our docs.

Before you begin

Sign up for Paddle

You'll need a Paddle account to get started. You can sign up for two kinds of account:

  • Sandbox — for testing and evaluation
  • Live — for selling to customers

For this tutorial, we recommend signing up for a sandbox account. You can transition to a live account later when you've built your integration and you're ready to start selling.

If you sign up for a live account, you'll need to complete account verification. This is where we ask for some information from you to make sure that we can work together. While we're verifying your account, you can't launch a checkout or sell on the Paddle platform.

Sign up for Vercel and a Git provider

As part of our tutorial, we're going to deploy our app to Vercel. Vercel is a developer platform that you can use to host and deploy web apps using serverless technology, designed for Next.js.

If you don't have a Vercel account, you'll need to sign up — it's free to get started.

You'll also need a Git provider to store the code that powers your app. When deploying to Vercel, the deployment screen walks you through setting up an account with GitHub (recommended), GitLab, or Bitbucket, if you don't already have one.

Prep your iOS development environment

As part of our tutorial, we're going to update our app to include a link to a hosted checkout for purchases. You'll need:

  • Some knowledge of iOS development, access to your iOS project, and Xcode on macOS.
  • A correctly configured URL scheme so you can redirect users back to your app.

You don't need to make changes to your iOS app to create a hosted checkout in Paddle, so you can return to this later if you're working with a developer.

Overview

Deploy a checkout and add it to your app to link out for in-app purchases in six steps:

  1. Start deploy to Vercel

    Clone the Git repository, configure environment variables, and deploy.

  2. Set up your product catalog

    Create products and prices in Paddle, then update your app to use them.

  3. Add your website

    Add your website to Paddle, then test your checkout to see how it works.

  4. Add a checkout button to your app

    Create a button that opens the checkout you deployed to Vercel when tapped.

  5. Handle fulfillment and provisioning

    Use RevenueCat or process webhooks to fulfill purchases after a customer completes a checkout.

  6. Take a test payment

    Make a test purchase to make sure your purchase flow works correctly.

1. Start deploy to Vercel

To create a Vercel project ready for us to set up, click the button to get started:

Create Git repo

First, create a clone of our starter kit repo. This creates a copy of the code in a repo in your Git provider account, so you can build your app on top of our project.

Click the Continue with GitHub, Continue with GitLab, or Continue with Bitbucket buttons to connect your Git provider to Vercel, if you haven't already. Then, enter a name for your repo.

Screenshot of the deploy to Vercel workflow, showing the Get started section. It shows three buttons to continue with GitHub, GitLab, and Bitbucket.

The repo name becomes the name of your project in Vercel, and it's also used for deploy preview URLs. If the name is taken, Vercel appends some characters to your project name when creating a deploy preview URL.

Configure environment variables

We need to supply some variables so that our checkout can work properly.

Screenshot of the deploy to Vercel workflow, showing the configure project section. It shows five required environment variables.

We need five variables:

VariableDescription
APPLE_TEAM_IDYour Apple Developer team ID, required for universal links so you can link back to your app.
NEXT_PUBLIC_BUNDLE_IDENTIFIERYour iOS app's bundle ID, for example com.example.myapp.
NEXT_PUBLIC_APP_REDIRECT_URLCustom URL scheme that bounces users back to your app when their purchase is completed, for example myapp://example-redirect.
NEXT_PUBLIC_PADDLE_CLIENT_TOKENA client-side token, used for securely opening Paddle Checkout.
NEXT_PUBLIC_PADDLE_ENVEnvironment for your Paddle account. Use sandbox for sandbox accounts; production for live accounts.

Get Apple team ID and bundle ID

You can find your Apple Developer team ID and your bundle ID in your Apple Developer account.

Copy and paste the values as APPLE_TEAM_ID and NEXT_PUBLIC_BUNDLE_IDENTIFIER.

Get a client-side token

Client-side tokens are for authenticating with Paddle in your frontend. We need one to securely open Paddle Checkout.

  1. Go Paddle > Developer tools > Authentication

  2. Click the Client-side tokens tab, then click New client-side token.

  3. Give your client-side token a name and description, then click Save.

  4. From the list of client-side tokens, click the action menu next to the client-side token you just created, then choose Copy token from the menu.

  5. Paste your token as NEXT_PUBLIC_PADDLE_CLIENT_TOKEN in the Deploy to Vercel screen.

Paddle's Authentication dashboard interface showing API management tools. The page header 'Authentication' appears at top left with a 'New client-side token' button at top right. Below is explanatory text: 'Securely manage your secret API keys and client-side tokens. Use API keys to interact with Paddle on the server side, or when working with trusted integrations. Use client-side tokens for working with Paddle.js in your frontend.' Navigation tabs show 'API keys' and 'Client-side tokens' (selected). A table displays existing keys with columns for Name, Token (showing masked values like 'live_******'), Status (showing 'Active' with green indicators), and Last used dates from September 20.

Set your environment

For NEXT_PUBLIC_PADDLE_ENV, enter:

  • sandbox if you're working with a sandbox account
  • production if you're working with a live account

We recommend working with a sandbox account for this tutorial. Sandbox accounts are designed for testing and evaluation. Live accounts must be approved by Paddle before you can open checkouts for them.

Review and deploy

At this point, we've done everything that we need to deploy. Review your settings, then click Deploy.

Wait for Vercel to build. If everything went well, our build should complete successfully.

Screenshot of the complete screen for the deploy to Vercel workflow. It says 'congratulations!' and there's a preview of our app.

However, while our our deploy link works and our marketing site is running, the pricing page and checkout flow won't work yet. We'll fix this in the next step.

2. Set up your product catalog

We now need to set up our product catalog in Paddle to match the in-app purchases we offer.

Model your pricing

A complete product in Paddle is made up of two parts:

  • A product entity that describes the item, like its name, description, and an image.
  • At least one related price entity that describes how much and how often a product is billed.

You can create as many prices for a product as you want to describe all the ways they're billed.

For this example, we'll create a product called Acme Guard with two prices for a monthly and annual subscription billing period.

Illustration of the product catalog in Paddle. It shows a product called Acme Guard with two prices: monthly and annually.

Create products and prices

You can create products and prices using the Paddle dashboard or the API.

  1. Go to Paddle > Catalog > Products.

  2. Click New product.

  3. Enter details for your new product, then click Save when you're done.

  4. Under the Prices section on the page for your product, click New price.

  5. Enter details for your new price. Set the billing period to Monthly to create a monthly price.

  6. Click Save when you're done.

  7. Create another price, setting the billing period to Annually and Save.

  8. Click the action menu next to each price in the list.

  9. Select Copy ID from the menu. You need these price IDs for the next steps.

Illustration showing the new product drawer in Paddle. It shows fields for product name, tax category, and description

Prices list in the Paddle dashboard, with the action menu open and copy ID selected.

Update prices in your app

Now we've created products and prices, we need to update our app with details of our new prices.

Clone your Git repo locally, then open src/components/pricing/plan-select.tsx in your IDE. If you're using GitHub, you can use GitHub Desktop to clone a repo locally if you're not familiar with Git.

You can also edit src/components/pricing/plan-select.tsx directly on your Git platform if you've not set up your local development environment.

plan-select.tsx contains a plans array that we use in our pricing page. Swap the Price IDs starting with pri_ with price IDs for the prices we just created. You can edit the tag with whichever information you'd like to display preceding the price. We use this to show a discount for annual plans, like Save 17%.

For example:

Add all your price IDs, then commit and push your changes to the main branch on Git.

Vercel automatically rebuilds your site at this point. You can go over to the Vercel dashboard to check on the build progress.

Screenshot of the project page in Vercel. It shows that our site is building.

When it's done, your pricing page should display prices, but you won't be able to checkout just yet. This is our next step.

3. Add your website to Paddle

To keep the Paddle platform safe for everyone, you must add your Vercel deploy link to Paddle before you can launch a checkout. This protects you as a seller, making sure that only you are able to sell your products.

Get your website approved

If you're using a sandbox account, website approval is instant. You'll need to add your domain, but our verification team don't check your website.

Website approval makes sure you own the domains where you use Paddle Checkout, and that the products sold meet the Paddle acceptable use policy.

Get your website approved using the Paddle dashboard:

  1. Go to Paddle > Checkout > Website approval.

  2. Click Add a new domain, enter your Vercel deploy link, then click Submit for Approval.

  3. Wait for approval.

If you're using a sandbox account, your website is automatically approved right away. You should see a green status symbol that says "Approved."

For live accounts, website approval may take a few days while the Paddle verification team check your website to make sure you're able to sell with Paddle. For more information, see: Website verification FAQs

Set your default payment link

Your default payment link is a quick way to open Paddle Checkout for a transaction. It's also used in emails from Paddle that let customers manage purchases that are recurring. You need to set a default payment link before you can launch a checkout.

We'll set our default payment link to the checkout page we just deployed.

  1. Go to Paddle > Checkout > Checkout settings.

  2. Enter your Vercel deploy link under the Default payment link heading.

  3. Click Save when you're done.

Checkout settings screen showing the Paddle dashboard. The default payment URL is set to https://example.com/

4. Add a checkout button to your app

Now, update your iOS app to add a button that:

  1. Checks to see if in-app purchases are allowed on the device.

  2. Checks to see if a user already purchased the item.

  3. Constructs a URL using your Vercel deploy URL, and a price_id query parameter taking a price ID as the value.

Here's an example using SwiftUI:

The price_id is hardcoded in this example, but you can set it dynamically based on the price the user is viewing or has selected.

Prefill information — recommended

To make for a more seamless user experience, you can use URL parameters to pass additional information to the checkout.

In this updated example, we pass the customer email address and a unique identifier for the customer in RevenueCat.

5. Handle fulfillment and provisioning

When a customer completes a purchase, they'll be redirected back to your app. At this point, you need to handle fulfillment and unlock the features they bought.

If you use the RevenueCat x Paddle integration to handle entitlements, you're all set!

Here's how it works:

  1. Paddle automatically sends data to RevenueCat about the completed checkout.

  2. RevenueCat grants the user an entitlement based on your product configuration.

  3. Use the RevenueCat SDK to check entitlement status in your iOS app.

Illustration of the new destination drawer in Paddle. It shows fields for description, type, URL, and version. Under those fields, there's a section called events with a checkbox that says 'select all events'

6. Test the complete flow

Mobile app screen with light blue background showing a lock icon with a green tick in a circular light blue container. Text reads 'Unlock Scam Protection, VPN, and more.' Below is a prominent blue button with white text saying 'Buy now for $60.00'.

Illustration of the Paddle checkout screen showing product details, price summary, and payment method options including Apple Pay.

Mobile app screen showing a success message with a mint green circular icon containing a yellow unlocked padlock. Text reads 'You unlocked access for 1 year. Enjoy!' Below is a bright green button with white text saying 'Start now'.

We're now ready to test the complete purchase flow end-to-end! If you're using a sandbox account, you can take a test payment using our test card details:

Email addressAn email address you own
CountryAny valid country supported by Paddle
ZIP code (if required)Any valid ZIP or postal code
Card number4242 4242 4242 4242
Name on cardAny name
Expiration dateAny valid date in the future.
Security code100

Before you go live, extend your Apple Pay integration by verifying your domain for Apple Pay. This lets you launch the Apple Pay modal directly from your checkout.

Next steps

That's it! Now you've deployed and built your initial website and web monetization purchase flow, you can customize the implementation and hook into other features of the Paddle platform.

Learn more about Paddle

When you use Paddle, we take care of payments, tax, subscriptions, and metrics with one unified platform. Customers can self-serve with the portal, and Paddle handles any order inquiries for you.

Add other fields to your pricing page

Our tutorial set up a pricing page using Paddle.PricePreview(). For each rendered tier, it shows the:

  • Name - details.line_items[].price.name
  • Interval - details.line_items[].price.billingCycle?.interval
  • Total - details.line_items[].formattedTotals

The total used is the calculated total for an item after taxes and discounts, formatted for a particular currency.

You might like to use another value for the price you show on your page, or include other values.

For a full list of values, see Pricing preview object

Customize your checkout experience

Our tutorial also set up an inline checkout where customers purchase your iOS products. When a customer interacts with the checkout, Paddle.js sends events which are used to show and update the order summary that customers see.

While the checkout flow is already set up to function with all Paddle prices and currencies out-of-the-box, you might like to customize its appearance and change its behavior.

Pass a discount

Extend your pricing page and checkout flow by passing a discount to reduce the amount a customer pays.

  • For your pricing page, add discountId in your request to Paddle.PricePreview(). The response includes a discount array that has information about the discount applied. Calculated totals in details.lineItems include discounts, where applicable.
  • For the checkout flow, add discount_id as a query parameter in the URL you use to open Paddle Checkout within your iOS app. The product summary shows the discount automatically, using totals.discount from the checkout event.

Build advanced subscription functionality

Paddle Billing is designed for subscriptions as well as one-time items. You can use Paddle to build workflows to pause and resume subscriptions, flexibly change billing dates, and offer trials.