View as Markdown

Products, Prices, and Paid Access

A product is the paid thing visitors can buy — a subscription, or a one-time purchase. Each product has a product handle and one or more prices, and each price has a price handle. Those two handles drive the onsite integration: you check the product handle with ezsubscriptions.hasAccess(...), and you open checkout with either ezsubscriptions.showPaywall({ product }) or ezsubscriptions.openCheckout({ price }).

Products

You create products in the Ezoic dashboard. A product has:

  • A public name, such as Remove Ads or Premium.
  • An optional description shown on the paywall.
  • A product handle your site code uses.
  • One or more prices.

Suppose you create a product named Remove Ads with the product handle remove-ads. On your site, your template checks access with ezsubscriptions.hasAccess("remove-ads"). If the visitor has access, you show the subscriber-only experience. If they do not, you call ezsubscriptions.showPaywall({ product: "remove-ads" }), which opens Ezoic's pre-built paywall and checkout experience for that product's prices.

You can create more than one product on a site — for example, a remove-ads subscription site-wide and a separate poll-access product on results pages — and open whichever one fits the page.

Product Handles

The product handle is the stable identifier your site passes to hasAccess(...) and showPaywall({ product }). Pick a handle when you create the product in your Ezoic dashboard.

Product handles are:

  • Domain-scoped and unique per site.
  • Case-insensitive and stored lowercase.
  • Limited to letters, numbers, hyphens, and underscores.

Examples: remove-ads, premium, poll-access.

Use handles that describe the access level, not the current price or promotion. Avoid changing a product handle after your site is using it unless you also update the site code that references it.

Prices

A price is a way to buy a product. Each price has:

  • A label, such as Monthly, Annual, or Lifetime.
  • An amount and billing interval.
  • A price handle your site code can use for custom checkout buttons.

showPaywall({ product }) presents all of a product's active prices and lets the visitor choose. When you want a button that charges one specific price directly — skipping price selection — pass its price handle to ezsubscriptions.openCheckout({ price }).

Price handles follow the same rules as product handles: domain-scoped, unique per site, case-insensitive, and limited to letters, numbers, hyphens, and underscores. Examples: remove-ads-monthly, remove-ads-annual.

One-Time Per-Item Purchases

A one-time price can sell access to a specific item, such as a single article or download. Pass a publisher-chosen item key alongside the price:

await ezsubscriptions.openCheckout({
  price: "article-unlock",
  item: "article-12345",
});

Check it later with ezsubscriptions.hasPurchased({ item: "article-12345", price: "article-unlock" }). The item value is stored verbatim and matched exactly, so keep it stable per item.

Example Product Structures

Simple Subscription

  • Product name: Premium
  • Product handle: premium
  • Price: Monthly$9.99 / month — price handle premium-monthly

Use this when one paid product unlocks all subscriber-only content.

Subscription With Multiple Prices

  • Product handle: premium
  • Price: Monthly$9.99 / month — price handle premium-monthly
  • Price: Annual$99.00 / year — price handle premium-annual

Use this when you want to offer the same product at more than one billing interval. showPaywall({ product: "premium" }) lets the visitor choose; a custom button can call openCheckout({ price: "premium-annual" }) to sell a specific price.

Donations Are Separate

Donations are a separate domain-level support option. They do not grant products and do not unlock subscriber-only content. Use Donations if you want readers to contribute without buying a product.

After Creating a Product

After your product is live:

  1. Add the onsite script to your site.
  2. Use the product handle in ezsubscriptions.hasAccess(...).
  3. Use the product handle in ezsubscriptions.showPaywall({ product }), or a price handle in ezsubscriptions.openCheckout({ price }).
  4. Add paywalled-content SEO markup to gated articles.
  5. Verify checkout as a new visitor.