RevenueCat Web SDK Quickstart (@revenuecat/purchases-js)

Overview

The RevenueCat Web SDK, published as @revenuecat/purchases-js, powers RevenueCat Web Billing: it lets you sell subscriptions and one-time products directly in the browser, with the same offerings, entitlements, and customer model you already use on mobile. You configure it once, load your offerings, read the user's entitlements through CustomerInfo, and start a hosted checkout flow with a single purchase(...) call.

If you have used the mobile SDKs, two differences matter most on the web:

  • A web-specific public API key. Web Billing uses its own key that starts with rcb_ (sandbox keys start with rcb_sb_). It is not your Apple or Google platform key.
  • You provide the app user id. The Web SDK does not silently mint an anonymous id the way the mobile SDKs do. You normally pass your own signed-in user id; if you genuinely need an anonymous id, you generate and persist it yourself.
Prerequisites: A RevenueCat project with a Web Billing app configured, products and an Offering set up in the dashboard, and a Web Billing public API key (rcb_). See the official Web SDK docs and the purchases-js API reference for the full surface.

Install the SDK

Add @revenuecat/purchases-js to your web project with your package manager of choice:

bash
npm install --save @revenuecat/purchases-js
# or: yarn add @revenuecat/purchases-js
# or: pnpm add @revenuecat/purchases-js

The package ships TypeScript types, so you get autocompletion for the Purchases class and the Offering, Package, and CustomerInfo models out of the box.

Configure

Import the Purchases class and call the static configure(...) method exactly once when your app starts. The current API takes an options object with your Web Billing public API key and the app user id:

typescript
import { Purchases } from '@revenuecat/purchases-js';

// Your Web Billing public API key from the RevenueCat dashboard.
// Production keys start with "rcb_"; sandbox keys start with "rcb_sb_".
const WEB_BILLING_PUBLIC_API_KEY = 'rcb_xxxxxxxxxxxxxxxxxxxxxxxx';

// Your own signed-in user id (from your auth system).
const appUserId = authentication.getAppUserId();

// Call configure ONCE. It returns the shared Purchases instance.
const purchases = Purchases.configure({
  apiKey: WEB_BILLING_PUBLIC_API_KEY,
  appUserId: appUserId,
});
Use a real user id. The Web SDK expects an appUserId. It does not create anonymous ids automatically like the mobile SDKs do. If you have no signed-in user yet and still want to start, generate an anonymous id explicitly and persist it so the same customer is reused on the next visit:
typescript
// Only if you have no signed-in user. Persist this id yourself
// (for example in localStorage) so the customer is stable.
const anonId =
  localStorage.getItem('rc_app_user_id') ??
  Purchases.generateRevenueCatAnonymousAppUserId();
localStorage.setItem('rc_app_user_id', anonId);

Purchases.configure({
  apiKey: WEB_BILLING_PUBLIC_API_KEY,
  appUserId: anonId,
});

After configuring, access the singleton anywhere with Purchases.getSharedInstance() instead of passing the instance around. See the Configure the SDK guide for the cross-platform key and app user id model.

Get Offerings & Packages

Offerings are the sets of products you configured in the RevenueCat dashboard. Fetch them and read the current Offering's available packages:

typescript
const offerings = await Purchases.getSharedInstance().getOfferings();

if (offerings.current !== null) {
  // Packages available in the "current" Offering.
  const packages = offerings.current.availablePackages;

  for (const pkg of packages) {
    // pkg.identifier is the package identifier (see reserved ids below).
    // pkg.webBillingProduct carries the price and product details.
    console.log(pkg.identifier, pkg.webBillingProduct.currentPrice.formattedPrice);
  }
}

You can also request prices in a specific currency by passing an options object, for example getOfferings({ currency: 'EUR' }).

Reserved vs custom package identifiers. RevenueCat defines reserved package identifiers such as $rc_monthly, $rc_annual, $rc_weekly, $rc_six_month, $rc_three_month, $rc_two_month, and $rc_lifetime. You can also create your own custom package identifiers; both reserved and custom packages are configured per Offering in the dashboard and surface here as pkg.identifier.

For more on modeling products and reading prices across platforms, see Get products and prices.

Get Customer Info

CustomerInfo is the source of truth for what the user currently owns. Fetch it and check entitlements.active to gate premium features:

typescript
const customerInfo = await Purchases.getSharedInstance().getCustomerInfo();

// entitlements.active maps entitlement id -> active EntitlementInfo.
const isPro = typeof customerInfo.entitlements.active['premium'] !== 'undefined';

if (isPro) {
  unlockPremiumUI();
} else {
  showPaywall();
}

See Get CustomerInfo for the full entitlement model and how it stays in sync after purchases and renewals.

Make a Purchase

Pass a Package from an Offering to purchase(...). The SDK presents the Web Billing checkout flow and resolves with the updated CustomerInfo:

typescript
async function buy(pkg) {
  try {
    const { customerInfo, redemptionInfo } = await Purchases
      .getSharedInstance()
      .purchase({ rcPackage: pkg });

    if (typeof customerInfo.entitlements.active['premium'] !== 'undefined') {
      unlockPremiumUI();
    }
  } catch (e) {
    // The user may have cancelled, or the purchase may have failed.
    console.error('Purchase did not complete', e);
  }
}

The resolved object contains the updated customerInfo (use it to unlock features immediately) and redemptionInfo. Always gate access on customerInfo.entitlements.active rather than on the fact that the call returned.

Signatures can change between versions. This guide reflects the current @revenuecat/purchases-js API. For the exact, version-pinned type signatures (optional purchase parameters, error codes, and the CustomerInfo shape), check the purchases-js API reference.

FAQ

What is @revenuecat/purchases-js?
It is the RevenueCat Web SDK. You import the Purchases class, configure it once with a Web Billing public API key, then load offerings, read CustomerInfo, and run checkout in the browser.

What API key does the Web SDK use?
A web-specific public key that starts with rcb_ (sandbox: rcb_sb_). It is separate from your Apple and Google platform keys and is created under your Web Billing app in the RevenueCat dashboard.

How do I get customer info with purchases-js?
Call await Purchases.getSharedInstance().getCustomerInfo() after configuring, then read customerInfo.entitlements.active to see the user's active entitlements.

Does the Web SDK require an app user id?
Yes. It does not create anonymous ids automatically like the mobile SDKs. Pass your own signed-in user id, or generate one explicitly with Purchases.generateRevenueCatAnonymousAppUserId() and persist it yourself.

Related Guides