# 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)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.digitalriver.com/digital-river-api/integration-options/low-code-checkouts/implementing-a-components-checkout.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
