Skip to main content

Configurator UI API

Summary

  1. Overview

  2. Include the Zakeke IFrame

  3. Communicate with the IFrame
    3.1 Workflow
    3.2 Authentication and authorization
    3.3 IFrame configuration
    3.4 Product price and availability
    3.5 Add to cart

1. Overview

The Configurator UI is the visual gateway that empowers users to personalize and modify products interactively. This dynamic and interactive interface will be loaded within an IFrame to be hosted within an ecommerce page. Communication between the IFrame and the hosting page will take place via an exchange of messages, managed with JavaScript code.

JavaScript provides the capability for communication with an IFrame's content through the use of the postMessage method. This allows secure messaging across different origins by enabling scripts to programmatically send and receive messages between the parent page (the hosting page) and the embedded IFrame. The postMessage method facilitates this interaction, ensuring data exchange is conducted safely and efficiently.

The data exchange between the hosting page and IFrame concerns the following fundamental aspects:

  • initialize the product configuration
  • obtain the correct price and availability of the configurable product
  • add the configured product to the shopping cart

The integration of the Zakeke Configurator UI will then basically consist of including the aforementioned IFrame and managing the exchange of messages between the host page and this IFrame.

2. Include the Zakeke IFrame

Add the following HTML tag to include the configurator IFrame to your system:


<iframe id="zakeke-frame" src="https://portal.zakeke.com/Configurator/index.html" allowfullscreen></iframe>

The Zakeke UI is fully responsive, and it's up to you to set the IFrame css styling.

3. Communicate with the IFrame

Other than adding the IFrame tag, your system will have to handle the communication between the Zakeke IFrame and hosting page.

3.1 Workflow

The following diagram illustrates the dialogue between the various components of the integrated system (ecommerce - Zakeke configurator) based on the actions performed by the site visitor.

Zakeke UI

Let's go through the steps:

  1. The end-user visit the ecommerce site page.
  2. The code present on the ecommerce page requests an authentication token from the Zakeke backend to be passed to the IFrame.
  3. The Zakeke backend authenticates the merchant and issues an authorization token.
  4. The code present on the ecommerce page send configuration information (setup) to the IFrame.
  5. Zakeke displays the product to be configured within the IFrame
  6. The end-user configures the product by choosing from the various possibilities offered by the user interface.
  7. During the configuration phase, Zakeke requests the information necessary from the e-commerce site to determine the right price for the customized product.
  8. The ecommerce responds by providing the price and availability of the configured product.
  9. Zakeke shows the price of the product configured in the user interface inside the IFrame.
  10. The end user decides to add the configured product to the cart.
  11. Zakeke provides the ecommerce with an identifier assigned to the configuration.
  12. The ecommerce redirects the end-user to the cart page.

In the next sections we will analyze in more detail the phases of the dialogue between the IFrame and the hosting page that require implementation on the ecommerce side.

Please Note

In the following explanation we will refer to a configuration, i.e. the set of values chosen for the various attributes that identify the configurable features of the product, also with the term composition.

3.2 Authentication and authorization

In order to establish secure communication between the hosting page and the configurator IFrame, the first fundamental step is to authenticate with Zakeke and obtain an authorization token.

For every detail go to Authentication and Authorization section)

warning

The authentication must be C2S type and among the information passed to obtain the token there must be the Visitor Code or the Customer Code.

Security Best Practice

Important: The API call for obtaining an OAuth 2.0 token using Client Credentials should be performed strictly in server-to-server contexts. This approach ensures that client_id and client_secret are not exposed to clients or transmitted over less secure channels. Implementing this call from client-side applications or exposing sensitive credentials to the public can lead to serious security vulnerabilities. Always ensure that such API calls and the handling of credentials are securely managed within server-side environments.

3.3 IFrame configuration

To initialize the Zakeke IFrame so that it loads the configurator for the desired product, the ecommerce JavaScript code must send via postMessage an object with the following structure to the IFrame:

{
"type": "load",
"parameters": {
"integrationVersion": 2,
"name": "Woman handbag",
"token": "tXyHtJgiZK11yUQm7amGwTn7",
"ecommerce": "api",
"currency": "USD",
"culture": "en",
"modelCode": "242422342",
"compositionId": "315-e4848045-91c2-44b2",
"qty": 1,
"attributes": [
[{"id": "34523"},{"id": "537564567"}],
[{"id": "12986"},{"id": "114588521"}],
[{"id": "90871"},{"id": "109771119"}],
],
"customAddToCartButtonText": ""
}
}

where:

PropertyData typeDescription
typestringMessage type
propertiesobjectMessage content

The properties property is an object with the folling properties:

PropertyData typeDescription
integrationVersionintegerThe version of the protocol to use for the integration. It must be 2.
namestringThe name of the product.
tokenstringC2S authorization token with a valid customer code or a visitor code.
ecommercestringAlways set to "api".
currencystringThe three-letter ISO code for the currency is used to format the prices.
culturestringThe two letter language code (ISO 639-1).
modelCodestringThe unique identifier for the product to load. For products uploaded via CSV it corresponds to the value of the MasterProductID field
compositionIdstringUnique identifier of the configuration. Used to change the configuration of a product already configured and added to cart (Optional)
qtyintegerNumber of products that the user has chosen to purchase.
attributesarrayThe list of attributes and respective values to start the configuration with. Each value is an array of two objects, containing respectively the id of the attribute and the id of the option.
customAddToCartButtonTextstringAlternate text for the "add to cart" button displayed within the IFrame. Optional
warning

In order to handle cases where you send the message before the Zakeke code inside the iframe loaded, you must continue to post this message until the IFrame post to you a message with type loaded.

Please Note

It is possible to modify a previously created product configuration ("composition") by passing the property compositionId to the Zakeke IFrame configuration object.

Below is an example of JavaScript code that initializes the IFrame of the Zakeke configurator.

// Retrieve the Zakeke IFrame
const iframe = document.querySelector("#zakeke-frame");

// Function that sends the initialization message to the Zakeke IFrame
function zakekeLoad() {
iframe.contentWindow.postMessage({
type: "load",
parameters: {
"name": "Woman handbag",
"token": "tXyHtJgiZK11yUQm7amGwTn7",
"ecommerce": "api",
"integrationVersion": 2,
"currency": "USD",
"culture": "us",
"modelCode": "242422342",
"qty": 1,
"attributes": [
[{"id": "34523"}, {"id": "537564567"}]
]
}
}, '*');
}

// Repeat the initialization at a timed interval...
const zakekeLoadInterval = setInterval(zakekeLoad, 500);

// ...until we receive the 'loaded' message from the IFrame
window.addEventListener('message', event => {

if (event.origin !== new URL(iframe.src).origin) {
return;
}

if (event.data.zakekeType === 'loaded') {
clearInterval(zakekeLoadInterval);
}

}, false);

3.4 Product price and availability

Each time that a product configuration is changed by a customer, Zakeke will ask to the hosting page about the price and stock availability of that specific product configuration, passing the list of attributes with the respective values chosen and the global unit price (mark-up price) given as the sum of any prices assigned in the back-office for those chosen values.

The monetary values passed in the request by Zakeke are always in the base currency set in the API settings of your Zakeke account. The response value must be converted in the currency indicated by the "currency" property of the IFrame configuration.

Depending on the settings of your system, product, and logged customer, the tax settings and any applicable discount must be calculated for the response value.

Again, communication occurs via message exchange via the postMessage JavaScript function.

3.4.1 Request message from IFrame

The request message that Zakeke sends to the hosting page has the following structure:

{
"zakekeMessageType": "Price",
"messageId": 2,
"message": {
"compositionPrice": 13.45,
"quantity": 1,
"attributes": [
{
"attributeCode": "{\"id\":\"242422342\",\"label\":\"Color\",\"zakekePlatform\":true}",
"attributeName": "Color",
"attributeIsEnabled": true,
"selectedOptionCode": "{\"id\":\"537564567\",\"label\":\"White\",\"zakekePlatform\":true}",
"selectedOptionName": "White",
"optionIsEnabled": true
}
]
}
}

where:

PropertyData typeDescription
zakekeMessageTypestring"Price" is used for price requests.
messageIdintegerThe message identifier that must be present in the response. It acts as a correlation id between the request and the response.
messageobjectThe message content

The object specified for the message property is an object which represents the actual content of the message and which has the following structure:

{
"compositionPrice": 13.45,
"quantity": 1,
"attributes": [
{
"attributeCode": "{\"id\":\"242422342\",\"label\":\"Color\",\"zakekePlatform\":true}",
"attributeName": "Color",
"attributeIsEnabled": true,
"selectedOptionCode": "{\"id\":\"537564567\",\"label\":\"White\",\"zakekePlatform\":true}",
"selectedOptionName": "White",
"optionIsEnabled": true
}
]
}

where:

PropertyData typeDescription
compositionPricemoneyThe sum of all the unit price of the chosen attribute options. The value is always in the base currency.
quantityintegerProduct quantity to be added to the cart.
attributesarrayThe list of chosen attributes and respective values.

The attributes property contains the list of all the attributes provided in the configuration with the respective values selected by the user. Specifically, for each attribute the array will contain an object of the following type:

{
"attributeCode": "{\"id\":\"242422342\",\"label\":\"Color\",\"zakekePlatform\":true}",
"attributeName": "Color",
"attributeIsEnabled": true,
"selectedOptionCode": "{\"id\":\"537564567\",\"label\":\"White\",\"zakekePlatform\":true}",
"selectedOptionName": "White",
"optionIsEnabled": true
}

For attributes that are linked to attributes on the store, the attributeCode and selectedOptionName properties each contain a JSON serialized with the sentinel zakekePlatform property and the id that the attribute or option has in the ecommerce system.

What is the meaning of the attributeIsEnabled and optionIsEnabled properties? When you define the attributes and their related options that will guide the end user in configuring the product in Zakeke, it is also possible to define rules that relate attributes and options to each other in order to indicate that, for example, an attribute makes no sense (it must be disabled) if for another attribute it is a certain option is selected, or that a particular option does not make sense (it should be disabled) if a specific option is selected for another attribute. In the Zakeke back-office we called these rules "links" between attributes and options. Therefore the meaning of the aforementioned attributeIsEnabled and optionIsEnabled properties is precisely that of indicating if whether the particular attribute and the particular attribute option are enabled or not based on the "links" defined.

3.4.2 Response message from Hosting Page

The page hosting the Zakeke IFrame must respond to the previous message with a message having the following structure:

{
"zakekeMessageType": "Price",
"messageId": 2,
"message": {
"price": 149.99,
"isOutOfStock": false
}
}

where:

PropertyData typeDescription
zakekeMessageTypestring"Price" is used for price requests.
messageIdintegerThe message identifier. Must be the same messageId as the request.
messageobjectThe message content

The object specified for the message property is an object which represents the actual content. The object contains the final price to be shown in the configurator UI and a flag indicating if the selected configuration is out of stock. The price property must be in the same currency as the "currency" property of the Zakeke IFrame configuration object. If the product can't be sold for the requested attributes and quantity, the message the property isOutOfStock must be false.

Below is an example of JavaScript code inserted in the page that hosts the IFrame for managing the request to calculate the price of the configured product:


// Handle the price request
function handlePriceRequest(request) {
var iframe = document.querySelector("#zakeke-frame");

// Send the response
iframe.contentWindow.postMessage({
messageId: request.messageId,
zakekeMessageType: "Price",
message: {
price: calculateFinalPrice(request.message.attributes,
request.message.quantity,
request.message.compositionPrice),
isOutOfStock: checkStock(request.message.attributes)
}, "*");
}
}


// Intercept the price request
window.addEventListener("message", function (event) {
if (event.data.zakekeMessageType === "Price") {
handlePriceRequest(event.data);
}
}, false);

3.5 Add to Cart

When the end user confirms that he wants to purchase the configured product, the Zakeke IFrame sends a message to the hosting page containing the composition identifier, a preview image of the product and the requested quantity.

For security reasons, information on the attributes selected by the user and the mark-up price managed by Zakeke is not passed via message to the hosting page, but must necessarily be obtained via a server to server API call (Cart API).

The request message that Zakeke sends to the hosting page has the following structure:

{
"zakekeMessageType": "AddToCart",
"message": {
"composition": "315-e4848045-91c2-44b2",
"preview": "https://....",
"quantity": 1
}
}

The property zakekeMessageType has the value "AddToCart" and the property message has the real content of the message with an object of the following structure:

{
"composition": "315-e4848045-91c2-44b2",
"preview": "https://....",
"quantity": 1
}

where:

PropertyData typeDescription
compositionstringUnique identifier generated by Zakeke for the composition (product configuration).
previewstringUrl to image preview of the configured product.
quantityintegerProduct quantity to be added to the cart.

Below is an example of JavaScript code inserted in the page that hosts the IFrame for handling the "AddToCart" message:

// Handle the AddToCart message
function handleAddToCartRequest(compositionId, previewUrl, quantity) {
// ...
// Invoke code to be executed server side (on the ecommerce system) for calling the Zakeke Cart API (S2S).
// ...
}

// Intercept the price request
window.addEventListener("message", function (event) {
if (event.data.zakekeMessageType === "AddToCart") {
handleAddToCartRequest(event.data.message.composition, event.data.message.preview, event.data.message.quantity);
}
}, false);

9. CONFIGURE button

In the standard Zakeke flow, the Configurator UI is opened from the product page through the 'Configure' call to action. This button becomes visible when a product is configured as configurable in the Zakeke back-office. Here's a summary of the standard flow: Configure > Zakeke UI > Add to Cart > Cart.

It's essential to note that this flow is optional, as long as you implement an alternative system to open the iframe. However, if you choose to implement the 'Configure' button, follow these steps:

Product-Page

9.1 Adding Configure Button

This is usually an HTML button to be placed next to the "ADD TO CART" button:

<button id="btnConfigure" type="button">Configure<button>

Clearly you can use any HTML element as long as it has as btnConfigure identifier.

9.2 HTML FORM

Before closing the body tag, you will need to add the following html FORM:

<form id="frmConfigurator" action="{Customizer URL}">
<input type="hidden" name="quantity" />
<input type="hidden" name="productid" />
<input type="hidden" name="{attributeKey1}" />
..
<input type="hidden" name="{attributeKeyn}" />
</form>

Where:

AttributeDescription
ConfiguratorURL of the created configurator page (refer to the reference section of the URL documentation).
quantityQuantity to add to cart.
productidUnique product ID.
attributeKeyProduct attribute key (e.g. "color", "size", etc.).
N.B. Attribute keys must match those defined in the imported products CSV. Go to how to import products for more details.

9.3 Javascript to Send the Product Selection to the Configurator

After the HTML form and before closing the body, enter the following script. It allows you to send the product selection to the configurator after clicking the "configure" button:

<script>

var btnConfigurer = document.getElementById('btnConfigure');
btnConfigurer.addEventListener('click',
function(evt) {

evt.preventDefault();
var formCustomizer = document.getElementById("frmConfigurator");
var formProductPage = document.getElementById("{idFormProduct}");
formCustomizer.elements["productid"].value = { productid };
formCustomizer.elements["quantity"].value = formProductPage.elements["quantity"].value;
formCustomizer.elements["attributeKey1"].value = formProductPage.["attributeKey1"].value;
...
formCustomizer.elements["attributeKeyn"].value = formProductPage.elements["attributeKeyn"].value;
formCustomizer.submit();

});

</script>

Where:

AttributeDescription
idFormProductFORM tag ID of the product page
productidUnique product I

9.4 Full HTML code Example

Below the sample code of a product page with the "configurator" button integrated:

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>Custom Shoe</title>
</head>
<body>
<div class="content">
<div class="foto">
<img alt="Customizable T-Shirt" src="http://your.store.com/images/product.jpg" />
</div>
<div class="details">
<h1>Custom Shoe - sku: 00001</h1>
<p>Description product.....</p>
<form id="frmAddToCart" action="https://your.store.com/shopping-cart.html">
<select name="quantity">
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</select>
<select name="color">
<option value="0">Black</option>
<option value="1">Red</option>
<option value="2">White</option>
<option value="3">Green</option>
</select>
<select name="size">
<option value="0">38</option>
<option value="1">39</option>
<option value="2">40</option>
<option value="3">41</option>
</select>
<button id="addToCart" type="submit">Add to shopping cart</button>
<button id="btnConfigure" type="button">Configure</button>
</form>
</div>
</div>
<form id="frmConfigurator" action="https://your.store.com/customizer.html">
<input type="hidden" name="sku" />
<input type="hidden" name="quantity" />
<input type="hidden" name="color" />
<input type="hidden" name="size" />
</form>
<script>

var btnConfigurer = document.getElementById('btnConfigure');
btnConfigurer.addEventListener('click',
function(evt)
{
evt.preventDefault();
var formCustomizer = document.getElementById("frmConfigurator");
var formProductPage = document.getElementById("frmAddToCart");
formCustomizer.elements["productid"].value = '00001';
formCustomizer.elements["quantity"].value = formProductPage.elements["quantity"].value;
formCustomizer.elements["color"].value = formProductPage.elements["color"].value;
formCustomizer.elements["size"].value = formProductPage.elements["size"].value;
formCustomizer.submit();
});

</script>
</body>
</html>