> For the complete documentation index, see [llms.txt](https://developer.paddle.com/llms.txt).

# Build a pricing page

Get a step-by-step overview of how to build a pricing page that displays localized prices, including taxes and discount calculation. Open a checkout when a prospect wants to sign up.

---

Pricing pages show prospects the subscription plans, addons, or one-time charges that you offer and how much they cost. They're one of the most important pages on your website, and typically [play a key part in customer conversion](https://www.paddle.com/resources/pricing-page-examples).

You can use [Paddle.js](https://developer.paddle.com/paddlejs/overview.md) to build pricing pages that show prospects prices that are [relevant for their country](https://developer.paddle.com/build/products/offer-localized-pricing.md), displayed in their local currency with estimated taxes. If you're running a sale or promo, you can calculate discounts too.

[Explore the code for this tutorial and test right away using our pricing page pen.](https://codepen.io/heymcgovern/pen/VwgvgNb)

## How it works

[Paddle Checkout](https://developer.paddle.com/concepts/sell/self-serve-checkout.md) automatically shows the correct prices for a customer using geolocation to estimate where a customer is buying from. Customers see prices in their local currency, with taxes estimated for their country or region.

You can use the [`Paddle.PricePreview()`](https://developer.paddle.com/paddlejs/methods/paddle-pricepreview.md) method in Paddle.js to get localized prices for pricing pages or other pages on your website. This means you can show the same information on your pricing page that a customer sees when they open checkout to subscribe.

You don't need to do any calculations yourself or manipulate returned data. Paddle returns totals formatted for the country or region you're working with, including the currency symbol.

## What are we building?

In this tutorial, we'll create a simple, three-tier pricing page. It includes a toggle to switch between monthly and annual plans.

We'll learn how to:

- Include and set up Paddle.js using a client-side token
- Build an items list that we can send to `Paddle.PricePreview()`
- Present and update prices on our page
- Toggle between monthly and annual prices for products
-

If you like, you can [view on CodePen](https://codepen.io/heymcgovern/pen/VwgvgNb) and follow along.

## Before you begin

### Choose a pricing page

This tutorial walks through creating a simple pricing page. You can also create a cart-style pricing page for more advanced implementations using transaction previews.

{% collapsible title="Types of pricing page" %}

{% feature-comparison level=4 %}

{% feature-column title="Simple pricing page" %}

{% feature-item %}
Pass a batch of price IDs and location information to Paddle.js. Paddle returns localized pricing for each item.
{% /feature-item %}
{% feature-item %}
**Recommended for most pricing pages.** Simply returns localized prices.
{% /feature-item %}
{% feature-item %}
Uses [`Paddle.PricePreview()`](https://developer.paddle.com/paddlejs/methods/paddle-pricepreview.md).
{% /feature-item %}
{% feature-item %}
Requests and responses mirror the [preview prices operation](https://developer.paddle.com/api-reference/pricing-preview/preview-prices.md).
{% /feature-item %}
{% feature-item %}
Returns item totals formatted for the currency and region, including currency code.
{% /feature-item %}
{% feature-item %}
Response only includes calculations for each item included in the request.
{% /feature-item %}
{% feature-item %}
You can send prices with different billing periods and trial periods.
{% /feature-item %}

{% /feature-column %}

{% feature-column title="Cart-style pricing page" %}

{% feature-item %}
Send a batch of price IDs and location information to Paddle.js. Paddle returns a preview of a transaction.
{% /feature-item %}
{% feature-item %}
Recommended for more advanced pricing pages where users can build their own plans.
{% /feature-item %}
{% feature-item %}
Uses [`Paddle.TransactionPreview()`](https://developer.paddle.com/paddlejs/methods/paddle-transactionpreview.md).
{% /feature-item %}
{% feature-item %}
Requests and responses mirror the [preview a transaction operation](https://developer.paddle.com/api-reference/transactions/preview-transaction.md).
{% /feature-item %}
{% feature-item %}
Returns item totals in the lowest denomination for a currency (for example, cents for `USD`).
{% /feature-item %}
{% feature-item %}
Response includes calculations for line items and grand totals.
{% /feature-item %}
{% feature-item %}
Requests mirror creating a transaction, so billing and trial periods must match for all items.
{% /feature-item %}

{% /feature-column %}

{% /feature-comparison %}

{% /collapsible %}

### Create products and prices

You'll need to [create a product and at least one related price](https://developer.paddle.com/build/products/create-products-prices.md) for the items that you want to include on your pricing page.

### Localize prices

To show localized prices, [turn on automatic currency conversion or add price overrides](https://developer.paddle.com/build/products/offer-localized-pricing.md) to your prices.

## Overview

To build a pricing page:

1. [**Include and initialize Paddle.js**](#include-paddle-js)  
   Add Paddle.js to your app or website, so you can securely work with your product catalog.
2. [**Pass prices to Paddle.js**](#pricing-preview)  
   Build a pricing preview request body and pass to `Paddle.PricePreview()`.
3. [**Update your page based on the response**](#update-page)  
   Present information returned by Paddle.js to a customer on your page.

## Include and initialize Paddle.js {% step=true %}

[Paddle.js](https://developer.paddle.com/paddlejs/overview.md) is a lightweight JavaScript library that lets you build rich, integrated subscription billing experiences using Paddle. We can use Paddle.js to securely work with products and prices in our Paddle system, as well as opening checkouts and capturing payment information.

### Include Paddle.js script

Start with a blank webpage, or an existing page on your website. Then, [include Paddle.js](https://developer.paddle.com/paddlejs/include-paddlejs.md) by adding this script to the `<head>`:

```html
<script src="https://cdn.paddle.com/paddle/v2/paddle.js"></script>
```

### Set environment {% badge label="Optional" /%}

We recommend [signing up for a sandbox account](https://sandbox-login.paddle.com/signup?utm_source=dx&utm_medium=dev-docs) to test and build your integration, then switching to a live account later when you're ready to go live.

If you're testing with the [sandbox](https://developer.paddle.com/sdks/sandbox.md), call [`Paddle.Environment.set()`](https://developer.paddle.com/paddlejs/methods/paddle-environment-set.md) and set your environment to `sandbox`:

```html {% highlightLines="3" %}
<script src="https://cdn.paddle.com/paddle/v2/paddle.js"></script>
<script type="text/javascript">
  Paddle.Environment.set("sandbox");
</script>
```

### Pass a client-side token

Next, go to **Paddle > Developer tools > Authentication** and create a client-side token. [Client-side tokens](https://developer.paddle.com/paddlejs/client-side-tokens.md) let you interact with the Paddle platform in frontend code, like webpages or mobile apps. They have limited access to the data in your system, so they're safe to publish.

In your page, call [`Paddle.Initialize()`](https://developer.paddle.com/paddlejs/methods/paddle-initialize.md) and pass your client-side token as `token`. For best performance, do this just after calling `Paddle.Environment.set()`, like this:

```html {% highlightLines="4-6" %}
<script src="https://cdn.paddle.com/paddle/v2/paddle.js"></script>
<script type="text/javascript">
  Paddle.Environment.set("sandbox");
  Paddle.Initialize({ 
    token: "test_7d279f61a3499fed520f7cd8c08" // replace with a client-side token
  });
</script>
```

{% callout type="info" %}
Client-side tokens are separate for your [sandbox and live accounts](https://developer.paddle.com/paddlejs/client-side-tokens#sandbox-vs-live-tokens.md). You'll need to [create a new client-side token](https://developer.paddle.com/paddlejs/client-side-tokens#create-client-side-token.md) for your live account. Sandbox tokens start with `test_` to make them easy to distinguish.
{% /callout %}

## Pass prices to Paddle.js {% step=true %}

Next, we'll pass prices to Paddle.js so that we can get localized prices for them. When previewing prices, Paddle returns calculated totals for line items only — it doesn't include grand totals. This means that we can include prices with different billing cycles and trial periods in our request, unlike when [opening a checkout](https://developer.paddle.com/build/checkout/pass-update-checkout-items.md) or [creating a transaction](https://developer.paddle.com/build/transactions/create-transaction.md).

### Define lists of prices

Our page includes four prices:

```mermaid
graph TD
  Starter["Starter"]
  Pro["Pro"]
  Starter_Monthly["Starter (monthly)"]
  Starter_Yearly["Starter (yearly)"]
  Pro_Monthly["Pro (monthly)"]
  Pro_Yearly["Pro (yearly)"]

  Starter --> Starter_Monthly
  Starter --> Starter_Yearly
  Pro --> Pro_Monthly
  Pro --> Pro_Yearly
```

In Paddle, we've set these up as two products called 'Starter' and 'Pro,' each with two prices for monthly and annual.

{% collapsible title="See an example of how these are modeled" %}

This is an example from the [list products operation](https://developer.paddle.com/api-reference/products/list-products.md) in the Paddle API. It shows the two products we're using, including an array of prices for each.

```json
{
  "data": [
    {
      "id": "pro_01gsz4t5hdjse780zja8vvr7jg",
      "name": "ChatApp Pro",
      "tax_category": "standard",
      "description": "Everything in starter, plus access to a suite of powerful tools and features designed to take your team's productivity to the next level.",
      "image_url": "https://paddle-sandbox.s3.amazonaws.com/user/10889/2nmP8MQSret0aWeDemRw_icon1.png",
      "custom_data": null,
      "status": "active",
      "created_at": "2023-02-23T12:43:46.605Z",
      "prices": [
        {
          "id": "pri_01gsz8z1q1n00f12qt82y31smh",
          "product_id": "pro_01gsz4t5hdjse780zja8vvr7jg",
          "description": "Annual (per seat)",
          "name": null,
          "billing_cycle": {
            "interval": "year",
            "frequency": 1
          },
          "trial_period": null,
          "tax_mode": "account_setting",
          "unit_price": {
            "amount": "30000",
            "currency_code": "USD"
          },
          "unit_price_overrides": [],
          "custom_data": null,
          "status": "active",
          "quantity": {
            "minimum": 1,
            "maximum": 999
          }
        },
        {
          "id": "pri_01gsz8x8sawmvhz1pv30nge1ke",
          "product_id": "pro_01gsz4t5hdjse780zja8vvr7jg",
          "description": "Monthly (per seat)",
          "name": null,
          "billing_cycle": {
            "interval": "month",
            "frequency": 1
          },
          "trial_period": null,
          "tax_mode": "account_setting",
          "unit_price": {
            "amount": "3000",
            "currency_code": "USD"
          },
          "unit_price_overrides": [],
          "custom_data": null,
          "status": "active",
          "quantity": {
            "minimum": 1,
            "maximum": 999
          }
        }
      ]
    },
    {
      "id": "pro_01gsz4s0w61y0pp88528f1wvvb",
      "name": "ChatApp Starter",
      "tax_category": "standard",
      "description": "Ideal for small teams who want to stay connected and organized. Access to all the essential features, including unlimited messaging, file sharing, and integrations with your favorite tools.",
      "image_url": "https://paddle-sandbox.s3.amazonaws.com/user/10889/2nmP8MQSret0aWeDemRw_icon1.png",
      "custom_data": null,
      "status": "active",
      "created_at": "2023-02-23T12:43:09.062Z",
      "prices": [
        {
          "id": "pri_01gsz8s48pyr4mbhvv2xfggesg",
          "product_id": "pro_01gsz4s0w61y0pp88528f1wvvb",
          "description": "Annual (per seat)",
          "name": null,
          "billing_cycle": {
            "interval": "year",
            "frequency": 1
          },
          "trial_period": null,
          "tax_mode": "account_setting",
          "unit_price": {
            "amount": "10000",
            "currency_code": "USD"
          },
          "unit_price_overrides": [],
          "custom_data": null,
          "status": "active",
          "quantity": {
            "minimum": 1,
            "maximum": 100
          }
        },
        {
          "id": "pri_01gsz8ntc6z7npqqp6j4ys0w1w",
          "product_id": "pro_01gsz4s0w61y0pp88528f1wvvb",
          "description": "Monthly (per seat)",
          "name": null,
          "billing_cycle": {
            "interval": "month",
            "frequency": 1
          },
          "trial_period": null,
          "tax_mode": "account_setting",
          "unit_price": {
            "amount": "1000",
            "currency_code": "USD"
          },
          "unit_price_overrides": [],
          "custom_data": null,
          "status": "active",
          "quantity": {
            "minimum": 1,
            "maximum": 100
          }
        }
      ]
    }
  ],
  "meta": {
    "request_id": "a920d367-69af-453b-a602-a49a2db92527",
    "pagination": {
      "per_page": 50,
      "next": "https://api.paddle.com/products?after=pro_01gsz4s0w61y0pp88528f1wvvb&id=pro_01gsz4t5hdjse780zja8vvr7jg&id=pro_01gsz4s0w61y0pp88528f1wvvb&include=prices",
      "has_more": false,
      "estimated_total": 2
    }
  }
}
```

{% /collapsible %}

To define these, create variables for the products in your script section and set them to the Paddle IDs for the products. We'll use these later to determine which products returned prices are for.

Then, create arrays for your prices. Each array should contain an object that includes the Paddle ID for a price (`priceId`) and a `quantity`. We've created two arrays:

- `monthItems`, which contains monthly prices for our products.
- `yearItems`, which contains yearly prices for our products.

We'll present localized prices for `monthItems` when the monthly toggle is selected, and `yearItems` when the yearly toggle is selected.

```html {% highlightLines="7-27" collapse=true %}
<script type="text/javascript">
  Paddle.Environment.set("sandbox");
  Paddle.Initialize({ 
    token: 'test_7d279f61a3499fed520f7cd8c08' // replace with a client-side token
  });
  
  // define products and prices
  var starterProduct = 'pro_01gsz4s0w61y0pp88528f1wvvb';
  var proProduct = 'pro_01gsz4t5hdjse780zja8vvr7jg';
  var monthItems = [{
      quantity: 1,
      priceId: 'pri_01gsz8ntc6z7npqqp6j4ys0w1w',
    },
    {
      quantity: 1,
      priceId: 'pri_01gsz8x8sawmvhz1pv30nge1ke',
    }
  ];
  var yearItems = [{
      quantity: 1,
      priceId: 'pri_01gsz8s48pyr4mbhvv2xfggesg',
    },
    {
      quantity: 1,
      priceId: 'pri_01gsz8z1q1n00f12qt82y31smh',
    }
  ];
</script>
```

### Get prices

Next, we'll create a function to get prices. This should pass our list of monthly or yearly items to Paddle.js.

In our sample, we've created a function called `getPrices()` that takes a parameter called `cycle`. Here's how it works:

1. We create a variable called `billingCycle` and set this to `year`. This is the billing cycle that we'd like to show when customers first visit our page.
2. We check to see if `cycle` is `month`, then set a variable called `itemsList` to either `monthItems` or `yearItems`. We also set a variable called `billingCycle` to the value of `cycle` for later.
3. We define a variable called `request`. This is what we're going to send to Paddle.js. It includes an object with an `items` key. The format of our request should match the request body for the pricing preview operation in the Paddle API, except with `camelCase` names for fields.
4. We call `Paddle.PricePreview()`, passing in `request` as a parameter.
5. `Paddle.PricePreview()` returns a promise that contains a pricing preview object. We use the `.then()` method to attach a callback that logs the resolved value to the console, and the `.catch()` method to log errors to the console.

```html {% highlightLines="29-47" collapse=true %}
<script type="text/javascript">
  Paddle.Environment.set("sandbox");
  Paddle.Initialize({ 
    token: 'test_7d279f61a3499fed520f7cd8c08' // replace with a client-side token
  });
  
  // define products and prices
  var starterProduct = 'pro_01gsz4s0w61y0pp88528f1wvvb';
  var proProduct = 'pro_01gsz4t5hdjse780zja8vvr7jg';
  var monthItems = [{
      quantity: 1,
      priceId: 'pri_01gsz8ntc6z7npqqp6j4ys0w1w',
    },
    {
      quantity: 1,
      priceId: 'pri_01gsz8x8sawmvhz1pv30nge1ke',
    }
  ];
  var yearItems = [{
      quantity: 1,
      priceId: 'pri_01gsz8s48pyr4mbhvv2xfggesg',
    },
    {
      quantity: 1,
      priceId: 'pri_01gsz8z1q1n00f12qt82y31smh',
    }
  ];
  
  // set initial billing cycle
  var billingCycle = 'year'
  
  // get prices
  function getPrices(cycle) {
    var itemsList = cycle === "month" ? monthItems : yearItems;  
    var billingCycle = cycle;
    var request = {
      items: itemsList
    }
    
    Paddle.PricePreview(request)
      .then((result) => {
        console.log(result);
      })
      .catch((error) => {
        console.error(error);
      });
  }
</script>
```

### Test your work

Save your page, then [open your browser console](https://developer.chrome.com/docs/devtools/console/) and type `getPrices('year')` or `getPrices('month')`. You should see a promise that contains a pricing preview object from Paddle returned the console.

{% callout type="info" %}
Use `⌘ Command` + `⌥ Option` + `J` (Mac) or `Ctrl` + `⇧ Shift` + `J` (Windows) to quickly open your browser console in Google Chrome.
{% /callout %}

## Update page {% step=true %}

Our function doesn't do anything to our page yet. We'll update `getPrices()` so that it displays pricing information returned by Paddle.js on our page.

### Create HTML for pricing table

First, we need to add some HTML for a simple pricing table with options for monthly and yearly. We'll add some CSS to the `<head>` of the page, too.

{% accordion %}
{% accordion-item title="HTML" %}

Add this to the `<body>` of your page.

In this sample, there are radio buttons for our pricing toggle, then a `<div>` with three `<div>` elements for each product that we offer. The radio buttons have an `onclick` attribute that runs our `getPrices()` function when clicked, passing either `month` or `year` as the parameter for `cycle`.

It sets `id`s `<p>` elements that contain prices. We'll use these IDs to replace the contents of these elements with returned prices from Paddle.js later.

```html {% collapse=true %}
<div class="pricing-page-container">
  <h1>Choose your plan</h1>
  <div class="pricing-toggle">
    <input type="radio" name="plan" value="month" id="month" onclick="getPrices('month')"><label for="month">Monthly</label>
    <input type="radio" name="plan" value="year" id="year" onclick="getPrices('year')" checked><label for="year">Yearly  <sup>save 20%</sup></label>
  </div>
  <div class="pricing-grid">
    <div class="starter-plan">
      <h3>Starter</h3>
      <p id="starter-price">$100.00</p>
      <p><small>per user</small></p>
      <button>Sign up now</button>
    </div>
    <div class="pro-plan">
      <h3>Pro</h3>
      <p id="pro-price">$300.00</p>
      <p><small>per user</small></p>
      <button>Sign up now</button>
    </div>
    <div class="enterprise-plan">
      <h3>Enterprise</h3>
      <p>Contact us</p>
      <p><small>bespoke pricing</small></p>
      <button>Inquire now</button>
    </div>
  </div>
</div>
```

{% /accordion-item %}
{% accordion-item title="CSS" %}

Add this to the `<head>` of your page. It applies some styling to the HTML so that the `<div>` elements are arranged in three columns.

For this sample, we also include [MVP.css](https://andybrewer.github.io/mvp/), which applies light styling to HTML elements. You don't need to do this if you're updating an existing page in your app or website that already has its own styling.

```html {% collapse=true %}
<style>
  .pricing-page-container {
    max-width: 900px;
    margin: auto;
    text-align: center;
    margin-top: 2em;
    padding-left: 1em;
    padding-right: 1em;
  }
  .pricing-grid {
    display: block;
    margin-bottom: 1em;
  }
  .pricing-grid .starter-plan {
    background-color: AliceBlue
  }
  .pricing-grid .pro-plan {
    background-color: HoneyDew
  }
  .pricing-grid .enterprise-plan {
    background-color: LavenderBlush
  }
  .pricing-grid > * {
    padding: 1rem;
  }
  @media (min-width: 768px) {
    .pricing-grid {
      display: grid;
      grid-auto-rows: 1fr;
      grid-template-columns: 1fr 1fr 1fr;
    }
  }
</style>
<!-- MVP.css: https://andybrewer.github.io/mvp/ -->
<link rel="stylesheet" href="https://unpkg.com/mvp.css@1.12.0/mvp.css" media="print" onload="this.media='all'">
```

{% /accordion-item %}
{% /accordion %}

### Update elements using JavaScript

Next, we'll change our script to update the `starter-price` and `pro-price` elements so they return pricing from Paddle.

First, we'll get elements in our pricing table using their `id` and assign them to variables that we can use later.

Then, we'll update our `getPrices()` function to iterate through `result.data.details.lineItems`. This array contains calculated totals for the prices that we passed to Paddle.js.

To make sure we show the correct prices for our products, we check to see if the Paddle ID of the related product of a price matches the product IDs we defined earlier:

- If the product for a returned price is `starterProduct`, we replace the contents of the `starter-price` element with `item.formattedTotals.subtotal`
- If the product for a returned price is `proProduct`, we replace the contents of the `pro-price` element with `item.formattedTotals.subtotal`.

For this sample, we also log `item.formattedTotals.subtotal` to console. This can be useful for debugging.

```html {% highlightLines="[29,30,31,47,48,49,50,51,52,53,54,55,56]" collapse=true %}
<script type="text/javascript">
  Paddle.Environment.set("sandbox");
  Paddle.Initialize({ 
    token: 'test_7d279f61a3499fed520f7cd8c08' // replace with a client-side token
  });
  
  // define products and prices
  var starterProduct = 'pro_01gsz4s0w61y0pp88528f1wvvb';
  var proProduct = 'pro_01gsz4t5hdjse780zja8vvr7jg';
  var monthItems = [{
      quantity: 1,
      priceId: 'pri_01gsz8ntc6z7npqqp6j4ys0w1w',
    },
    {
      quantity: 1,
      priceId: 'pri_01gsz8x8sawmvhz1pv30nge1ke',
    }
  ];
  var yearItems = [{
      quantity: 1,
      priceId: 'pri_01gsz8s48pyr4mbhvv2xfggesg',
    },
    {
      quantity: 1,
      priceId: 'pri_01gsz8z1q1n00f12qt82y31smh',
    }
  ];
  
  // DOM queries
  var starterPriceLabel = document.getElementById("starter-price");
  var proPriceLabel = document.getElementById("pro-price");
  
  // set initial billing cycle
  var billingCycle = 'year'
  
  // get prices
  function getPrices(cycle) {
    var itemsList = cycle === "month" ? monthItems : yearItems;  
    var billingCycle = cycle;
    var request = {
      items: itemsList
    }
    Paddle.PricePreview(request)
      .then((result) => {
        console.log(result);
    
        var items = result.data.details.lineItems;
        for (item of items) {
          if (item.product.id === starterProduct) {
            starterPriceLabel.innerHTML = item.formattedTotals.subtotal
            console.log('starter ' + item.formattedTotals.subtotal)
          } else if (item.product.id === proProduct) {
            proPriceLabel.innerHTML = item.formattedTotals.subtotal
            console.log('pro ' + item.formattedTotals.subtotal)
          }
        }
      })
      .catch((error) => {
        console.error(error);
      });
  }
</script>
```

### Set getPrices() to run on page load

Right now, our function only runs when the monthly or annual radio buttons are clicked.

We can add `onLoad` to our `<body>` tag to run our `getPrices()` function immediately after the page has loaded:

```html
<body onLoad="getPrices(billingCycle)">
```

### Test your work

Save your page, then open it in your browser. You should see prices from Paddle.js in your pricing table. Selecting the monthly or annual toggle should change the prices that you see.

{% callout type="note" %}
Paddle.js automatically detects visitor location using their IP address and returns localized prices. To see localization in action, see the [get started](https://developer.paddle.com/build/onboarding/overview.md) demo. We don't recommend including a country selector in real implementations.
{% /callout %}

## Next steps

That's it. Now we've built a simple pricing page, you might like to add other fields to your page, pass a discount, or open a checkout.

### Add other fields to your pricing page

[`Paddle.PricePreview()`](https://developer.paddle.com/paddlejs/methods/paddle-pricepreview.md) returns a pricing preview object for the prices and location passed. We show `details.lineItems.formattedTotals.subtotal` in our sample. This is the calculated total for an item before estimated 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.

{% collapsible title="Useful fields in the response" %}

Here are some fields in the response that you might like to use on your page:

|                                                   |                                                                                                                            |
|---------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------|
| `details.address.countryCode`                     | Country code for the pricing preview. If you sent an IP address, Paddle returns the detected country.                      |
| `details.line_items[].formattedTotals`            | Totals for a particular line item, formatted as a string for the currency you're working with.                             |
| `details.line_items[].formattedUnitTotals`        | Totals for one unit of a particular line item, formatted as a string for the currency you're working with.                 |
| `details.line_items[].price.trialPeriod`          | Details of the trial period for a price.                                                                                   |
| `details.line_items[].discounts[].formattedTotal` | Total amount discounted for a discount applied to a line item, formatted as a string for the currency you're working with. |

For a full list of values, see [Pricing preview object](https://developer.paddle.com/api-reference/pricing-preview/overview.md)

{% /collapsible %}

{% card-group cols=2 %}
{% card title="Preview prices operation" url="/api-reference/pricing-preview/preview-prices" /%}
{% card title="Paddle.PricePreview() method" url="/paddlejs/methods/paddle-pricepreview" /%}
{% /card-group %}

### Pass a discount {% id="next-steps-discount" %}

Extend your pricing page by passing `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.

{% card-group cols=2 %}
{% card title="Discount entity overview" url="/api-reference/discounts/overview" /%}
{% card title="Create or update a discount" url="/build/products/offer-discounts-promotions-coupons" /%}
{% /card-group %}

### Open a checkout {% id="next-steps-open-checkout" %}

Pass items to [`Paddle.Checkout.open()`](https://developer.paddle.com/paddlejs/methods/paddle-checkout-open.md) or use [HTML data attributes](https://developer.paddle.com/paddlejs/html-data-attributes.md) to open a checkout.

{% card-group cols=2 %}
{% card title="Build an inline checkout" url="/build/checkout/build-branded-inline-checkout" /%}
{% card title="Build an overlay checkout" url="/build/checkout/build-overlay-checkout" /%}
{% /card-group %}