DOCS

Custom integration

/

Custom integration

Build an end-to-end Checkout integration into your custom site.

This guide covers the technical aspects of completing a full integration of Zonos Checkout into your custom site or platform. It is intended for developers who are comfortable working with JavaScript and have experience with frontend development. All steps are required unless otherwise noted.

Prerequisites


Install the Zonos JS script 

Your custom integration will need to include the Zonos JavaScript snippet. This script is responsible for rendering the Checkout UI, Zonos Hello, handling payment processing, and handling visitor geo-IP detection.

1

Install the Zonos JS snippet

The Zonos Elements script is available at the following URL:

Zonos JS snippet

1
<script src="https://js.zonos.com/dist/scripts/loadZonos.js" />

Handling browser caching

We also typically recommend appending a timestamp or other unique identifier to the URL to ensure that the script is not cached by the browser. This will ensure that the latest version of the script is always loaded. For example:

Zonos JS snippet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<script>
  (async function () {
    const timestamp = new Date().getTime();
    const zonosScript = document.querySelector(
      `script[src*="https://js.zonos.com/dist/scripts/loadZonos.js"]`,
    );

    if (!zonosScript) {
      const script = document.createElement('script');
      script.src = `https://js.zonos.com/dist/scripts/loadZonos.js?timestamp=${timestamp}`;
      script.addEventListener(
        'load',
        () => {
          // Initialize the script here (instructions in next section)
        },
        false,
      );
      document.head.appendChild(script);
    }
  })();
</script>
2

Authenticate the Zonos JS snippet

Once you have loaded the Zonos JS script, you need to authenticate it by passing a Zonos API key and store ID into Zonos.init function. The API keys used to authenticate Checkout are designed to be publishable, meaning they can be safely used in frontend code without exposing any sensitive information.

Zonos JS snippet

1
2
3
4
5
6
Zonos.init({
  // ... other fields
  zonosApiKey: 'API KEY', // Replace with your actual API key (found in Dashboard)
  storeId: 'STORE ID', // Replace with your actual store ID (found in Dashboard)
  // ... other fields
});
3

Set allowed domains

In order to ensure that the Zonos JS script is only loaded on allowed sites, we filter requests based on a list of "allowed domains". This list is configured in Dashboard. Without this configuration, the Zonos JS script will return permission errors instead of loading properly.

To update your allowed domains:

  1. Go to Dashboard -> Settings -> Checkout settings.
  2. Under the Allowed domains section, add the domain(s) where you will be integrating Checkout.
  3. Click Save.

Set up Zonos Hello 

Once you have set up the Zonos JS script, you need to configure Hello to work with your site. Hello is responsible for detecting the visitor's location, language, and currency, and displaying the appropriate information to them. Hello is required when using Checkout.

You can configure all Hello settings in both Dashboard and the Zonos JS script. If you have already configured Hello in Dashboard, the script will load those settings and use them. If you specify any values in the helloSettings property of the Zonos.init function, the script will use those values instead.

1

Configure currency conversion

Hello uses CSS selectors to identify elements on your site that display currency information. You will need to pass these selectors to the helloSettings.currencyElementSelector property of the Zonos.init function.

You can use any valid CSS selector here, for example #price, .price to select multiple different elements.

Zonos JS snippet

1
2
3
4
5
6
7
Zonos.init({
  // ... other fields
  helloSettings: {
    // ... other fields
    currencyElementSelector: '#price, .price', // Replace with your actual selector
  },
});
2

Configure item restrictions

Hello has the ability to check for restricted items as the shopper browsers and prevent them from being added to the cart. In order for this to work, Hello needs to know about additional item information such as the name and description, as well as the "add to cart button". You can pass CSS selectors to Hello to allow it to scrape this information from the page.

Zonos JS snippet

1
2
3
4
5
6
7
8
9
10
Zonos.init({
  // ... other fields
  helloSettings: {
    // ... other fields
    productAddToCartElementSelector: '.add-to-cart',
    productDescriptionElementSelector: '.description',
    productPriceElementSelector: '.price',
    productTitleElementSelector: '.title',
  },
});

Optional — Automatically open Hello on page load

By default, Hello will only open when the visitor clicks on the flag button. If you would like to automatically open Hello when the page loads, you can call the Zonos.openHelloDialog() function once the Zonos script has loaded.

Zonos JS snippet

1
2
3
4
5
Zonos.init({
  // ... other fields
});

Zonos.openHelloDialog();

Set up Zonos Checkout 

Once Hello has been configured, you need to set up Checkout to work with your site. Checkout is responsible for allowing the customer to enter their shipping information, calculate landed cost, and complete the order.

Checkout will share contextual data with Hello, such as the visitor's location, language, and currency. This ensures that the customer's experience is consistent across the whole shopping process.

You can configure all Checkout settings in both Dashboard and the Zonos JS script. If you have already configured Checkout in Dashboard, the script will load those settings and use them. If you specify any values in the checkoutSettings property of the Zonos.init function, the script will use those values instead.

1

Configure the 'place order' button

The Zonos JS script will automatically recognize international shoppers and direct them to the Checkout flow. However, you will need to configure the 'place order' button on your platform to open Checkout when clicked. This can be done by passing a CSS selector to the checkoutSettings.placeOrderButtonSelector property of the Zonos.init function.

If you have multiple buttons that can be used to place an order, make sure to pass in a selector that will match all of them. For example, #placeOrder, .place-order will match both #placeOrder and .place-order.

Zonos JS snippet

1
2
3
4
5
6
7
Zonos.init({
  // ... other fields
  checkoutSettings: {
    // ... other fields
    placeOrderButtonSelector: '#placeOrder', // Replace with your actual selector(s)
  },
});
2

Pass cart view-only cart details in Checkout

The buildCartDetail callback is responsible for returning cart details in a format that the Checkout interface can understand and display. This function is called as soon as the customer arrives at the checkout page, ensuring that the cart details are displayed accurately on the first page of Checkout. Please note that this is not used for calculations - that is handled in the next step.

Zonos JS snippet

1
2
3
4
5
6
7
8
9
10
Zonos.init({
  // ... other fields
  checkoutSettings: {
    // ... other fields
    buildCartDetail: async () => {
      // ... Your existing buildCartDetail implementation
      // This should return cart details for UI display
    },
  },
});

Cart item schema

The buildCartDetail function should return an array of cart items. Below is a table detailing the structure of each CartItem object:

Field NameTypeRequiredDescription
amountNumberYesThe price amount of the item.
countryOfOriginStringNoThe country of origin of the item.
currencyCodeStringYesThe currency code for the amount.
descriptionStringNoDescription of the item.
hsCodeStringNoThe Harmonized System code for the item.
imageUrlStringNoURL of the item's image.
measurementsItemMeasurement[]NoArray of item measurements.
metadataObject (string/number pairs)NoAdditional metadata about the item.
nameStringYesName of the item.
productIdStringNoThe product ID.
quantityNumberYesQuantity of the item in the cart.
skuStringNoStock Keeping Unit identifier.
3

Securely pass landed cost to Checkout

The buildLandedCost function handles securely calculating the landed cost. It is invoked after the customer enters their shipping information. This function calculates the shipping rates and other necessary costs, which are then displayed on the subsequent page of Checkout.

It is important that you handle the landed cost calculation logic on the server-side, as this is the only way to ensure that the cart details are not exposed to the customer's browser. If you are using a serverless architecture, you can use a serverless function to handle the landed cost calculation. The buildLandedCost function should simply call the serverless function/API endpoint and return the result.

On the server-side, you can use the Zonos Checkout API to calculate the landed cost by using the following POST request. You will need to pass the API key you've been using for the Zonos JS script in the credentialToken header.

Request URL

1
https://v1.route.js.zonos.com/api/zonos-elements/calculate-landed-cost

Request body

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
{
  "billingAddress": {
    "addressLine1": "789 King Street",
    "city": "London",
    "country": "GB",
    "postalCode": "SW1A 1AA",
    "state": "England"
  },
  "billingContact": {
    "firstName": "John",
    "lastName": "Doe",
    "phone": "+44-20-7946-0958"
  },
  "checkoutSessionId": "xyz789",
  "contact": {
    "firstName": "John",
    "lastName": "Doe",
    "phone": "+44-20-7946-0958"
  },
  "items": [
    {
      "amount": 150,
      "currencyCode": "USD",
      "name": "Product Name",
      "quantity": 2
    }
  ],
  "shippingAddress": {
    "addressLine1": "789 King Street",
    "city": "London",
    "country": "GB",
    "postalCode": "SW1A 1AA",
    "state": "England"
  }
}

Zonos JS snippet

1
2
3
4
5
6
7
8
9
Zonos.init({
  // ... other fields
  checkoutSettings: {
    // ... other fields
    buildLandedCost: async (checkoutSessionId, contact, shippingAddress) => {
      // This should return the landed cost calculation
    },
  },
});

Was this page helpful?