> 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/implementing-a-components-checkout.md).

# Implementing a Components checkout

[Components](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/components.md) are a [low-code checkout option](/digital-river-api/integration-options/low-code-checkouts.md) that consists of UI building blocks. They allow you to create customized checkout flows that connect to Digital River's address validation, [local pricing](/digital-river-api/using-our-services/local-pricing.md), [payment processing](/digital-river-api/payments/payment-integrations-1.md), [subscription](/digital-river-api/using-our-services/subscriptions.md), fraud detection, tax computation, and compliance services.

[Components](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/components.md) make it even easier to integrate with Digital River, reducing the time spent launching and managing your solution.

You can use all [available components](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/components.md#supported-component-types) to create traditional checkout flows. Alternatively, you might decide to use them selectively to construct specialized flows. For example, by pairing the [wallet component](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/components/wallet-component.md) with the [compliance component](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/components/compliance-component.md), you can offer customers an expedited checkout experience.

On this page, you'll find information on:

* [Building a cart and initiating checkout](#building-a-cart-and-initiating-checkout)
* [Designing the checkout experience](#designing-the-checkout-experience)
* [Executing a components checkout](#executing-a-components-checkout)
* [Handling front-end events](#handling-front-end-events)
* [Controlling the flow of the checkout](#controlling-the-checkout-flow)
* [Submitting data collected by components](#submitting-components)

After customers complete the checkout process, your application must also [handle completed checkout-sessions](/digital-river-api/integration-options/low-code-checkouts/handling-completed-checkout-sessions.md).

## Building a cart and initiating checkout

During the early stages of an eCommerce transaction, customers land on your storefront, review products, and build a cart. Digital River is typically not involved in these pre-checkout interactions unless you're engaging our [local pricing service](/digital-river-api/using-our-services/local-pricing.md). However, once customers initiate checkout, you must start interacting with [components](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/components.md).

## Designing the checkout experience

For each component you implement, your DOM needs to contain a unique HTML element to display it.

```html
...
<div id="address-container" style="display: block"></div>
<div id="shipping-container" style="display: block"></div>
<div id="tax-identifier-container" style="display: block"></div>
<div id="payment-container" style="display: block"></div>
<div id="wallet-container" style="display: block"></div>
<div id="compliance-container" style="display: block"></div>
<div id="order-summary-container" style="display: block"></div>
<div>
    <div>
        <button id="previousButton" onclick="onPreviousButtonClick()">Previous</button>
    </div>
    <div>
        <button id="nextButton" onclick="onNextButtonClick()">Next</button>
    </div>
</div>
<div id="order-confirmation-container" style="display: none"></div>
...

```

The following example uses all of the [available components](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/components.md#supported-component-types), but how you design your experience is highly customizable.

{% tabs %}
{% tab title="Address collection stage" %}

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

{% tab title="Shipping choice collection stage" %}

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

{% tab title="Tax identifier collection stage" %}

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

{% tab title="e-invoice collection stage" %}

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

{% tab title="Payment collection stage" %}

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

{% tab title="Order confirmation stage" %}

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

<div align="left"><figure><img src="/files/9LpCrHBWXfUgSyWyq6be" alt="" width="375"><figcaption></figcaption></figure></div>

If you implement multiple components that accept customer input, such as [address](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/components/address-component.md), [shipping](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/components/shipping-component.md), and [payment](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/components/payment-component.md), your experience should also contain buttons or some other type of navigational control that allows customers to move the checkout process forward and backward. These button-click events should activate your [checkout flow control](#controlling-the-checkout-flow) functionality.

## Executing a components checkout

On your checkout page, you should:

* [Add the necessary scripts and style sheets](#add-scripts-and-style-sheets)
* [Create a Digital River Checkout object](#create-a-digital-river-checkout-object)
* [Invoke a custom-built function that initializes components](#initialize-components)

### Add scripts and style sheets

In the `head` of your `html`, [add the DigitalRiverCheckout.js](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/including-digitalrivercheckout.js.md) script. If you'd like, you can also include a `link` to the `DigitalRiver.css` style sheet.

```html
<head>
    <title>Checkout Page</title>
    <script defer="defer" src="https://checkout.digitalriverws.com/v1/DigitalRiverCheckout.js"></script>
    <link rel="stylesheet" href="https://js.digitalriverws.com/v1/css/DigitalRiver.css" type="text/css"/>
</head>
```

### Create a Digital River Checkout object

Use your [public API key](/digital-river-api/administration/dashboard/developers/api-keys.md) to [create a `DigitalCheckoutRiver` object](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/initializing-digitalrivercheckout.js.md).

```javascript
let digitalRiverCheckout = new DigitalRiverCheckout("YOUR_PUBLIC_API_KEY");
```

### Initialize components

When your checkout page loads, invoke an asynchronous function that initializes components.

```javascript
...
initializeComponents();
...
```

The [async function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) you implement should:

* [Build a `components()` configuration object](#build-a-configuration-object)
* [Pass that object to `components()`](#create-the-components-object)
* [Create each individual component that you want to use](#create-individual-components)
* [Mount each of those components](#mount-individual-components)

```javascript
async function initializeComponents() {
    //Build a configuration object
    const configuration = {
        checkoutSessionId: await createComponentsCheckoutSession(),
        onReady: function (data) {
            //Handle event
        },
        onChange: function (data) {
            //Handle event
        },
        onSuccess: function (data) {
            //Handle event
        }
    }
    //Create components
    let components;
    components = digitalRiverCheckout.components(configuration);
    
    //Create the individual components
    paymentComponent = components.createComponent('payment');
    shippingComponent = components.createComponent('shipping');
    addressComponent = components.createComponent('address');
    walletComponent = components.createComponent('wallet');
    thankYouComponent = components.createComponent('thankyou');
    complianceComponent = components.createComponent('compliance');
    orderSummaryComponent = components.createComponent('ordersummary');
    
    //Mount the individual components
    paymentComponent.mount('payment-container');
    shippingComponent.mount('shipping-container');
    addressComponent.mount('address-container');
    walletComponent.mount('wallet-container');
    thankYouComponent.mount('order-confirmation-container');
    complianceComponent.mount('compliance-container');
    orderSummaryComponent.mount('order-summary-container');
}
```

#### Build a configuration object

To set `checkoutSessionId` in the [components configuration object](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/components/configuring-components.md), you should invoke an asynchronous function, wrapped by your [initialize components function](#initialize-components), that defines a [checkout-session](https://docs.digitalriver.com/digital-river-api-reference/2021-12-13/drop-in-checkout-sessions/checkout-sessions-basics) on your front end and then passes that data to your server so that it can [submit the create request](https://docs.digitalriver.com/digital-river-api-reference/2021-12-13/drop-in-checkout-sessions#drop-in-checkout-sessions).

Alternatively, before loading your checkout page, you could define and create a [checkout-session](https://docs.digitalriver.com/digital-river-api-reference/2021-12-13/drop-in-checkout-sessions/checkout-sessions-basics) completely server-side.

In either case, the function you implement needs to return the checkout-session's `id`.

```javascript
function createComponentsCheckoutSession() {
  //Creates checkout-session
  //Returns checkout-session identifier
}
```

In the configuration object, you'll also need to define how you want to [handle callback methods](#handling-front-end-events).

```javascript
async function initializeComponents() {
    //Build a configuration object
    const configuration = {
        checkoutSessionId: await createComponentsCheckoutSession(),
        onReady: function (data) {
            //Handle event
        },
        onChange: function (data) {
            //Handle event
        },
        onSuccess: function (data) {
            //Handle event
        }
    }
    ...
}
```

#### Create the components object

Pass your [configuration object](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/components/configuring-components.md) to [`components()`](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/components.md#creating-components).

```javascript
async function initializeComponents() {
    ...
    //Create components
    let components;
    components = digitalRiverCheckout.components(configuration);
    ...
}
```

#### Create individual components

Use the object returned by `components()` to [create the individual components](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/components.md#createcomponent-componenttype) that you want customers to interact with.

```javascript
async function initializeComponents() {
    ...
    //Create the individual components
    paymentComponent = components.createComponent('payment');
    shippingComponent = components.createComponent('shipping');
    addressComponent = components.createComponent('address');
    walletComponent = components.createComponent('wallet');
    thankYouComponent = components.createComponent('thankyou');
    complianceComponent = components.createComponent('compliance');
    orderSummaryComponent = components.createComponent('ordersummary');
    ...
}
```

#### Mount individual components

For each component, pass the `id` of its HTML container to [`mount()`](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/components.md#mount-elementid).

```javascript
async function initializeComponents() {
    ...
    //Mount the individual components
    paymentComponent.mount('payment-container');
    shippingComponent.mount('shipping-container');
    addressComponent.mount('address-container');
    walletComponent.mount('wallet-container');
    thankYouComponent.mount('order-confirmation-container');
    complianceComponent.mount('compliance-container');
    orderSummaryComponent.mount('order-summary-container');
}
```

## Handling front-end events

Ensure you define how you'd like to handle the [ready](#ready-events), [change](#change-events), and [success](#success-events) callback functions.

### Ready events

Some of the ways you might handle [`onReady`](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/components/configuring-components.md#onready) is by:

* Using [`data.requiresShipping`](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/components/configuring-components.md#requiresshipping) to set a boolean variable that controls whether the [shipping component](#shipping-component) needs to be displayed during the checkout process.
* Using [`data.showTaxIdentifiers`](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/components/configuring-components.md#showtaxidentifiers) to set a boolean that controls whether the [tax identifier component](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/components/tax-identifier-component.md) needs to be displayed.
* Calling a function that [controls the flow of the checkout experience](#controlling-the-checkout-flow).

```javascript
...
onReady: function (data) {
  if (data.requiresShipping === false) { 
    //Update the variable that controls whether to display the shipping component
  }
  if (data.showTaxIdentifiers === false) {
    //Update the variable that controls whether to display the tax identifier component
  }
  //Call a function that determines the correct component(s) to display
},
...
```

### Change events

If you're using the [tax identifier component](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/components/tax-identifier-component.md), handle [`onChange`](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/components/configuring-components.md#onchange) by determining whether `optionalTaxIdentifiers[]` or `requiredTaxIdentifiers[]` exists in the returned `data`. If either does, set a variable that controls whether that component is displayed during checkout.

```javascript
onChange: function (data) {
    ...
    if (('optionalTaxIdentifiers' in data) || ('requiredTaxIdentifiers' in data)){
      //Set a display tax identifier component boolean variable to true
      //At some point in the checkout process, display the tax identifier component
    };
},
...
```

If, for whatever reason, you decide not to use the [order summary component](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/components/order-summary-component.md), you can also use [`onChange`](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/components/configuring-components.md#onchange) to update your custom-built order summary section. There are a variety of ways to do this.

The example below retrieves `locale`, `currency`, `totalAmount`, `totalShipping`, `totalTax`, and `subTotal`, along with each `items[].amount`, from the `data` returned by `onChange` and then constructs [JavaScript Int.NumberFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat) objects which are then used to set the `innerText` of the appropriate HTML element.

In this example, the `sku.image` and `sku.name` of each `items[]` is also displayed.

```javascript
  ...
  onChange: function (data) {
    const locale = data.locale.replace('_', '-');
    document.getElementById('total').innerText =  new Intl.NumberFormat(locale, { style: 'currency', currency: data.currency }).format(data.totalAmount);
    document.getElementById('shipping').innerText =  new Intl.NumberFormat(locale, { style: 'currency', currency: data.currency }).format(data.totalShipping);
    document.getElementById('tax').innerText =  new Intl.NumberFormat(locale, { style: 'currency', currency: data.currency }).format(data.totalTax);
    document.getElementById('subtotal').innerText =  new Intl.NumberFormat(locale, { style: 'currency', currency: data.currency }).format(data.subtotal);
    document.getElementById('items').innerHTML = data.items.map( i => {
      return <div>
        <img style="height: 30px; width: 30px" src="${i.sku.image}"/> ${i.sku.name} - ${new Intl.NumberFormat(locale, { style: 'currency', currency: data.currency }).format(i.amount)}
      </div>
    });
  },
  ...
```

### Success events

One way to handle [`onSuccess`](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/components/configuring-components.md#onsuccess) is by passing an argument to your [control checkout flow function](#controlling-the-checkout-flow), instructing it to display the [thank you component](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/components/thank-you-component.md).

Alternatively, you could retrieve `order.id` (and whatever else you need) from `data` and use it to build your custom order confirmation page.

```javascript
  ...
  onSuccess: function (data) {
    // Display the thank you component or a customized order confirmation page
  },
  ...
```

## Controlling the checkout flow

To control the flow of the checkout experience, you'll need to implement asynchronous functionality.

One possible approach is to define a function that checks a position enumeration, each value of which corresponds to a stage in the checkout process, and then, depending on the value, uses [`document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) to access each HTML element in your experience that holds a component, displaying and hiding the appropriate ones.

As you progress through the various checkout stages, make sure you also call `done()` to ensure the customer's inputs are submitted and valid. For details, refer to [Submitting components](#submitting-components).

## Submitting components

Some of the [available components](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/components.md#supported-component-types) collect data from customers. Digital River handles submitting that data for a subset of these, but you must initiate the process for others.

For example, in the [payment component](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/components/payment-component.md), DigitalRiver.js handles the button click event by sending a create [source](/digital-river-api/payments/payment-sources.md) request, performing any required [SCA](/digital-river-api/payments/psd2-and-sca.md) or redirects to the payment provider, and then, assuming those processes are successful, requesting that the payment object be added to the [checkout-session's](https://docs.digitalriver.com/digital-river-api-reference/2021-12-13/drop-in-checkout-sessions) `sources[]`.

On the other hand, the [address](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/components/address-component.md), [shipping](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/components/shipping-component.md), [tax identifier](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/components/tax-identifier-component.md), and [invoice ](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/components/invoice-component.md)components require that you invoke a function that submits the data they collect and determines whether it's valid. Specifically, these components require that, inside of an [`async` function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function), you call `done()` using the [`await`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await) operator and then check the returned value to determine whether the checkout should advance to the next stage.

{% tabs %}
{% tab title="Address component" %}

<pre class="language-javascript"><code class="lang-javascript">...
<strong>const addressComponentStatus = await addressComponent.done();
</strong>if (!addressComponentStatus) {
  //Do not advance checkout to the next stage
  return;
} else {
  //Advance checkout to the next stage
}
...
</code></pre>

{% endtab %}

{% tab title="Tax identifier component" %}

```javascript
...
const taxIdentifierComponentStatus = await taxIdentifierComponent.done();
if (!taxIdentifierComponentStatus) {
  //Do not advance checkout to the next stage
  return;
} else {
  //Advance checkout to the next stage
}
...
```

{% endtab %}

{% tab title="Shipping component" %}

```javascript
...
const shippingComponentStatus = await shippingComponent.done();
if (!shippingComponentStatus) {
  //Do not advance checkout to the next stage
  return;
} else {
  //Advance checkout to the next stage
}
...
```

{% endtab %}

{% tab title="Invoice attribute component" %}

```javascript
...
const invoiceComponentStatus = await invoiceComponent.done();
if (!invoiceComponentStatus) {
  //Do not advance checkout to the next stage
  return;
} else {
  //Advance checkout to the next stage
}
...
```

{% endtab %}
{% endtabs %}

For details, refer to:

* [Submitting the address component](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/components/address-component.md#submitting-the-address-component)
* [Submitting the shipping component](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/components/shipping-component.md#submitting-the-shipping-component)
* [Submitting the tax identifier component](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/components/tax-identifier-component.md#submitting-the-tax-identifier-component)
* [Submitting the invoice attribute component](/digital-river-api/developer-resources/digitalrivercheckout.js-reference/digitalrivercheckout-object/components/invoice-component.md#submitting-the-invoice-component)
