> For the complete documentation index, see [llms.txt](https://docs.digitalriver.com/digital-river-api/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.digitalriver.com/digital-river-api/integration-options/low-code-checkouts/offering-local-pricing.md).

# Offering local pricing

If you'd like to pair [Prebuilt Checkout](/digital-river-api/integration-options/low-code-checkouts/drop-in-checkout.md) with [local pricing](/digital-river-api/using-our-services/local-pricing.md), this page contains information on:

* [Setting up the shopping experience](#setting-up-the-shopping-experience)
* [How product prices are displayed throughout the shopping experience](#product-prices-during-the-shopping-experience)
* [Accessing price formatting rules](#access-price-formatting-rules)

All of the local pricing functionality exists within [DigitalRiverCheckout.js](/digital-river-api/developer-resources/digitalrivercheckout.js-reference.md).

## Setting up the shopping experience

When building your shopping experience, one possible solution is to wait until the document loads and then, at a minimum, define [`containerId`](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/initializing-digitalrivercheckout.js/digitalrivercheckout-configuration-object.md#containerid). Digital River needs this value to determine where to display the [local pricing selector](/digital-river-api/using-our-services/local-pricing.md#local-pricing-selector). Although it's not a hard requirement, you should also populate [`priceElement`](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/initializing-digitalrivercheckout.js/digitalrivercheckout-configuration-object.md#priceelement) so we know which of your [DOM](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Introduction) elements contain product prices.

You also have the option to define how you want to handle various [selector events](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/initializing-digitalrivercheckout.js/digitalrivercheckout-configuration-object.md#local-pricing-selector-events). These events can be useful for testing, analytics, and triggering redirections. For example, you might handle [`onSave`](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/initializing-digitalrivercheckout.js/digitalrivercheckout-configuration-object.md#onsave) by checking the value of `country`, and then, if it's `US` or `CA`, redirect to a customized experience or store for shoppers in those countries.

```javascript
document.addEventListener('DOMContentLoaded', () => {
  const config = {
    countrySelector: {
      containerId: 'country-selector',
      priceElement: ['div.price', 'span.price'],
      autoOpen: true,
      onReady: () => {},
      onOpen: () => {},
      onSelect: (data) => {},
      onSave: (data) => {},
      onCancel: () => {}
    }
  };
  ...
```

You can then use this [configuration object](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/initializing-digitalrivercheckout.js/digitalrivercheckout-configuration-object.md) to [initialize DigitalRiverCheckout.js](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/initializing-digitalrivercheckout.js.md).

```javascript
  ...
  const digitalRiverCheckout = new DigitalRiverCheckout('Your public API key', config);
  ...
```

If you want Digital River to create a checkout button, call [`renderButton()`](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/rendering-a-checkout-button.md).

<pre class="language-javascript"><code class="lang-javascript"><strong>  ...
</strong><strong>  digitalRiverCheckout.renderButton(buttonContainer, buttonOptions);
</strong><strong>  ...
</strong></code></pre>

The function's [first parameter](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/rendering-a-checkout-button.md#button-container) is the element's `id` where you want the button to display.

```javascript
 <div id="button-container"></div>
 ...
 const buttonContainer = '#button-container';
 ...
```

The [second parameter](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/rendering-a-checkout-button.md#button-options) is a configuration object that, among other things, allows you to (1) [style the button](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/rendering-a-checkout-button.md#style-the-button), (2) [modify its text](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/rendering-a-checkout-button.md#customize-the-buttons-text), and (3) [hide your elements](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/rendering-a-checkout-button.md#hide-elements).

```javascript
  ...
  const buttonOptions = {
    style: {
      backgroundColor: '#B52',
      borderRadius: '100px',
      color: '#5C6',
      fontSize: '2rem',
      fontWeight: '800',
      fontFamily: 'Montserrat,Arial,Helvetica,sans-serif',
      ':hover': {
        color: 'rgb(0, 167, 225)'
      }
    },
    buttonText: 'Proceed to checkout',
    hiddenElement: ['#checkout-btn'],
    afterRender: true,
    onInit: (actions) => {
      console.log('The button has rendered');
    },
    ...
    onCancel: () => {
      console.log('The checkout window has been closed');
    }
  };
  ...
});
```

This object also contains an [`onClick`](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/rendering-a-checkout-button.md#button-click-event) property to assign an [`async`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) event-handling procedure. One way to define it is by using a [`try...catch`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch) block that first calls [`actions.loading.start()`](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/rendering-a-checkout-button/performing-actions-on-the-checkout-button.md#start-and-stop-a-loading-spinner) and then your own create checkout-session function. Make sure to use [`await`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await) with this expression so that the handler pauses until a [promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) is returned.

```javascript
  ...
  const buttonOptions = {
    ...
    onClick: async (actions) => {
      console.log('The button has been clicked');
      try {
        actions.loading.start();
        const checkoutSessionId = await createCheckoutSession();
        actions.loading.stop();
        if (!checkoutSessionId) {
          return;
        }
        const config = getConfigObj();
        actions.checkout.modal.open(checkoutSessionId, config);
      } catch (error) {
        actions.loading.stop();
      }
    },
    ...
  };
  ...
});
```

On your front-end, in `onClick`, call [`actions.loading.stop()`](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/rendering-a-checkout-button/performing-actions-on-the-checkout-button.md#start-and-stop-a-loading-spinner) and then check the value of the promise. If it's [falsy](https://developer.mozilla.org/en-US/docs/Glossary/Falsy), your procedure should reject it and halt execution. Otherwise, pass the returned identifier and, optionally, a [configuration object](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/configuring-prebuilt-checkout.md) to [`actions.checkout.modal.open()`](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/rendering-a-checkout-button/performing-actions-on-the-checkout-button.md#open-a-checkout-modal).

## Configuring the checkout-session for local pricing

When defining the [checkout-session](https://docs.digitalriver.com/digital-river-api-reference/2021-12-13/drop-in-checkout-sessions/checkout-sessions-basics):

* Call [`digitalRiver.getCountry()`](https://docs.digitalriver.com/digital-river-api/integration-options/low-code-checkouts/pages/ZqmFekSL0GwsOtUOpP5s#digitalriverpricing.getcountry) and [`digitalRiver.getCurrency()`](https://docs.digitalriver.com/digital-river-api/integration-options/low-code-checkouts/pages/ZqmFekSL0GwsOtUOpP5s#digitalriverpricing.getcurrency) and then assign the returned values to the [`shoppingCountry` ](https://docs.digitalriver.com/digital-river-api-reference/2021-12-13/drop-in-checkout-sessions/checkout-sessions-basics#shopping-country)and [`currency` ](https://docs.digitalriver.com/digital-river-api-reference/2021-12-13/drop-in-checkout-sessions/checkout-sessions-basics#currency)parameters, respectively.
* For each product in the customer's cart, retrieve its original, unconverted price and assign it to [`items[].price`](https://docs.digitalriver.com/digital-river-api-reference/2021-12-13/drop-in-checkout-sessions/checkout-sessions-basics#product-data).
* If you're discounting an entire transaction or individual line items within that transaction, use `discount.percentOff` or `items[].discount.percentOff`. In both cases, don't define `amountOff`.

On your server side, send a [`POST /drop-in/checkout-sessions`](https://docs.digitalriver.com/digital-river-api-reference/2021-12-13/drop-in-checkout-sessions#drop-in-checkout-sessions) request and include your [secret API key](https://docs.digitalriver.com/digital-river-api-reference/digital-river-api-reference-guide/api-structure#confidential-keys).

## Product prices during the shopping experience

Digital River uses the [checkout-session's](https://docs.digitalriver.com/digital-river-api-reference/2021-12-13/drop-in-checkout-sessions/checkout-sessions-basics) `shoppingCountry`, `currency`, and `items[].price` to perform another currency conversion, apply the same [rounding](/digital-river-api/using-our-services/local-pricing.md#rounding-logic) and [formatting](#access-price-formatting-rules) rules used to display prices on your site. As a result, the currency-denominated prices customers see on your storefront and in your cart are identical to those in the checkout experience.

{% tabs %}
{% tab title="Storefront " %}

<div align="left"><figure><img src="/files/IYcqUk2dTkBRQJ807BnR" alt=""><figcaption></figcaption></figure></div>
{% endtab %}

{% tab title="Cart" %}

<div align="left"><figure><img src="/files/eOyYN8wnrpxfObVn2D9e" alt="" width="375"><figcaption></figcaption></figure></div>
{% endtab %}

{% tab title="Prebuilt Checkout" %}

<div align="left"><figure><img src="/files/LELvCB5uguBECc9l3xQh" alt=""><figcaption></figcaption></figure></div>
{% endtab %}

{% tab title="Components" %}

<div align="left"><figure><img src="/files/NhQsup6ZRMW2ifQUI01T" alt=""><figcaption></figcaption></figure></div>
{% endtab %}
{% endtabs %}

## Access price formatting rules

Once customers provide payment, complete their purchase, and Digital River converts the [checkout-session](https://docs.digitalriver.com/digital-river-api-reference/2021-12-13/drop-in-checkout-sessions) to an [order](https://docs.digitalriver.com/digital-river-api-reference/2021-12-13/orders), we add `pricingFormat` to the [event ](https://docs.digitalriver.com/digital-river-api-reference/2021-12-13/events)with a [`type`](/digital-river-api/order-management/events-and-webhooks-1/events-1.md#event-types) of [`checkout_session.order.created`](https://docs.digitalriver.com/digital-river-api/integration-options/low-code-checkouts/pages/okHqAQ9d1PaLPLjq6nZF#checkout_session.order.created).

{% code title="checkout\_session.order.created" %}

```json
{
    "id": "dacc88d7-3f88-469b-9764-35a15681e6c9",
    ...
            "pricingFormat": {
                "currencyNumberFormat": "#,###.##",
                "symbol": "₩",
                "decimalPlaces": 0,
                "currencySymbolBeforePrice": true,
                "useCurrencySymbolSpace": false
            },
            "liveMode": false
        }
    },
    ...
}
```

{% endcode %}

This object contains Digital River's rules for formatting prices throughout the [shopping experience](#product-prices-during-the-shopping-experience). To maintain a consistent format, you can apply these rules to the prices in your [customer notifications](/digital-river-api/order-management/customer-notifications.md) and your site's order management pages.

{% hint style="info" %}
You can also access `pricingFormat` by assigning a handler to [`onCheckoutComplete`](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/configuring-prebuilt-checkout.md#oncheckoutcomplete).
{% endhint %}

```json
{
    "id": "764ddbdd-0f7e-448d-b044-196f67dd1781",
    "type": "checkout_session.order.created",
    "data": {
        "object": {
            ...
            "pricingFormat": {
                "currencyNumberFormat": "#,###.##",
                "symbol": "¥",
                "decimalPlaces": 0,
                "currencySymbolBeforePrice": true,
                "useCurrencySymbolSpace": false
            },
            ...
        }
    },
    ...
}
```

{% hint style="success" %}
If you don't want to build your formatter, many server-side languages have pre-built functions that roughly approximate the formatter Digital River uses. Depending on your application, you might find some of the following pages useful:

* [Java: Numbers and currencies](https://docs.oracle.com/javase/tutorial/i18n/format/numberintro.html)
* [PHP: Number and currency formatter](https://www.php.net/manual/en/numberformatter.formatcurrency.php)
* [Python: Internationalization services](https://rubymoney.github.io/money/)
* [Ruby: Money](https://rubymoney.github.io/money/)
  {% endhint %}

The following objects are nested in `pricingFormat`:

* [`currencyNumberFormat`](#currencynumberformat)
* [`symbol`](#symbol)
* [`decimalPlaces`](#decimalplaces)
* [`currencySymbolBeforePrice`](#currencynumberformat)
* [`useCurrencySymbolSpace`](#usecurrencysymbolspace)

#### `currencyNumberFormat`

You can use `currencyNumberFormat` to determine how to display the integer and fractional parts of a price.

Its value indicates whether the character that groups digits in the integer part should be a comma (`,`), a point (`.`), an apostrophe (`'`), a whitespace( ), or some other character. It also dictates the correct spacing of this character.

Additionally, `currencyNumberFormat` allows you to determine whether the character that separates the price's integer part from its fractional part should be a point or a comma.

{% tabs %}
{% tab title="Example 1" %}
In the following example, `currencyNumberFormat` groups the digits in the integer part with a comma placed every third digit to the left of a point, which acts as the separator between the price's integer and fractional parts.

```json
"currencyNumberFormat": "#,###.##"
```

**Target output in UI**

<div align="left"><img src="/files/TKjaHKxMEcuvuOB7amUi" alt=""></div>
{% endtab %}

{% tab title="Example 2" %}
In the following example, `currencyNumberFormat` groups the digits in the integer part by a point placed every third digit to the left of a comma, which acts as the separator between the price's integer and fractional parts.

```json
"currencyNumberFormat": "#.###,##"
```

**Target output in UI**

<div align="left"><img src="/files/oIIljQRWAEtoeScq7wNF" alt=""></div>
{% endtab %}

{% tab title="Example 3" %}
In the following example, `currencyNumberFormat` groups the digits in the integer part first by a comma placed every third digit to the left of a point, which acts as the separator between the price's integer and fractional parts.

After that, digits in the integer part should follow a two-digit grouping pattern.

```json
"currencyNumberFormat": "#,##,###.##"
```

**Target output in UI**

<div align="left"><img src="/files/LrPkdGg9I3B4PcWiapZ1" alt=""></div>
{% endtab %}

{% tab title="Example 4" %}
In the following example, `currencyNumberFormat` groups the digits in the integer part by an apostrophe placed every third digit to the left of a point, which acts as the separator between the price's integer and fractional parts.

```json
"currencyNumberFormat": "#'###.##"
```

**Target output in UI**

<div align="left"><img src="/files/JnSIhsWxEqRWBv0Z4bhd" alt=""></div>
{% endtab %}
{% endtabs %}

#### `symbol`

Use the graphic `symbol` to denote the price's currency.

{% tabs %}
{% tab title="Example 1" %}
The following is the `symbol` for Swiss Francs:

```json
"symbol": "CHF"
```

**Target output in UI**

<div align="left"><img src="/files/1UPm8JEui4yIrPet2yew" alt=""></div>
{% endtab %}

{% tab title="Example 2" %}
The following is the `symbol` for Jordanian Dinars:

```json
"symbol": "د.ا"
```

**Target output in UI**

<div align="left"><img src="/files/YdgshkgwtUZzhziWTVxO" alt=""></div>
{% endtab %}
{% endtabs %}

#### `decimalPlaces`

This attribute stipulates the number of digits that should be displayed to the right of the character (whether it's a point or comma) that divides a price's integer part from its fractional part.

If `decimalPlaces` is `0` and [`currencyNumberFormat`](#currencynumberformat) indicates that a character should be placed between the integer and fractional parts, then that character shouldn't be displayed.

```json
{
    ...
    "pricingFormat": {
        "currencyNumberFormat": "#,###.##",
        ...
        "decimalPlaces": 0,
        ...
    },
    ...
}
```

| decimalPlaces value | Target output in UI                                                 |
| ------------------- | ------------------------------------------------------------------- |
| `0`                 | ![](/files/rvf9ZaFpxiIfqUvkVXR1)                                    |
| `2`                 | <img src="/files/0yvzyuFsktTAQzRq0bg5" alt="" data-size="original"> |
| `3`                 | ![](/files/coHwWE7Yx9WX5Mr1t3vp)                                    |

#### `currencySymbolBeforePrice`

The `currencySymbolBeforePrice` indicates whether [`symbol`](#symbol) should be placed before or after a price's numeric amount.

<table><thead><tr><th width="324.3333333333333">currencySymbolBeforePrice value</th><th>Target output in UI</th></tr></thead><tbody><tr><td><code>true</code></td><td><img src="/files/yZPorfs5Y7BoLusQNFdc" alt=""></td></tr><tr><td><code>false</code></td><td><img src="/files/mGtpQjz8IuMnxqx94xbO" alt=""></td></tr></tbody></table>

#### `useCurrencySymbolSpace`

The `useCurrencySymbolSpace` indicates whether or not to insert a space between [`symbol`](#symbol) and the price's numeric amount.

| useCurrencySymbolSpace value | Target output in UI              |
| ---------------------------- | -------------------------------- |
| `true`                       | ![](/files/Wmbsc18F1HdTXvMrGTjh) |
| `false`                      | ![](/files/e1IgW4cKkTBYtNaA4lgw) |
