The Embed API offers a seamless integration between a Epicor CPQ configurator and your own website.
Embedding a configurator in your web site
Whether it is a public e-commerce site or an internal portal for your sales department, the most common requirement is to allow a user to create a configured product within your own website and come back to it later to make alterations, and to submit the filled in quote, all while keeping the end-user's experience consistent with the rest of your website or portal.
What you'll need
This is not an exhaustive list, and it may vary depending on your specific needs. These are generally the most common requirements to make a seamless end-user experience:
Putting it Together
The Embed API
Server-Side Processing
- A server-side application that can process and deliver HTTP calls. This application can be in PHP, Java, .NET, or any other server-side language and/or framework which can deliver HTTP calls and parse/serialize JSON. Note that if you have .NET, you can use our SDK for easy usage of our REST API.
- A server-side database, or a CRM which can persist data.
- Your production Epicor CPQ portal should allow anonymous users. Typically authentication is handled on the customer's side.
- Read up on the Embed API and REST API pages. If you are using .NET, check out our SDK.
Editing an Existing Configured Product
For this task, we will use the Javascript version of the Embed API. This gives us full flexibility for managing the configurator. We will also keep the fields within the embedded configurator to keep things simple. Hiding the fields and implementing them within your own page can be a complicated, as you will need to duplicate a lot of the logic that is already present in your configurator's value, validation, and visibility rules. In the end, this is what your bare-bones webpage's HTML should look like:
Your Page
<html>
<head>
<title>Embedded Configurator</title>
<!-- Replace subdomain with your company's subdomain -->
<scriptsrc="https://subdomain.kbmax.com/js/embed.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function() {
//start the embed
var config = new kbmax.ConfiguratorEmbed({
elementId: "viewer",
configuratorId: id, // Replace this with the actual ID of your configurator
showFields: true,
showHeader: false,
showConfigHeader: true,
showMove: false,
bindToFormSelector: "",
loadStyle: "none",
});
document.getElementById("btnSubmit").onclick = function() {
config.getConfiguredProduct(function(cp) {
// Store the configured product's JSON in the hidden input
document.getElementById("configuredProduct").value = JSON.stringify(cp);
document.getElementById("configuratorForm").submit();
});
}
});
</script>
</head>
<body>
<h1>Embedded Configurator</h1>
<div id="viewer"></div>
<form id="configuratorForm"action="path_to_submit_serverside_script"method="POST">
<input type="hidden"name="configuredProduct"id="configuredProduct"/>
</form>
<button id="btnSubmit">Submit Configuration</button>
</body>
</html>
Creating the ConfiguratorEmbed is the boilerplate code found in the Embed API page. The important part of the code is adding the click handler to the submit button. This populates the form with the full JSON-encoded representation of the configured product, including its field values, and then submits that form to a URL to your server-side endpoint to process this submission. An alternative way to send this information is through an AJAX call.
Your server-side framework will need to process this call. Because your server-side framework may vary in its language and syntax, we will use pseudocode which you will have to translate to your own language. If you have the .NET SDK, you can use its functionality to deliver the REST calls.
Your Server-Side (pseudocode)
var configuredProduct = parseJson(FORM_VALUES["configuredProduct"]);
var login = authenticateKBMaxAPI("username", "password");
// Replace callKBMaxAPI with a function of your choosing which makes an HTTP request to the API endpoint.
// If you are using the .NET SDK it comes bundled with a fully-functional API client.
// Similarly the Quote class is something you can create. Please see the API docs at
// https://kbmax.kbmax.com/help/index.html for a description of the endpoints and parameters.
var quote = callKBMaxAPI(login, "POST", "/api/quotes/submit", new Quote({
name: "My Quote",
products: [new QuoteProduct({
qty: 1,
idProduct: configuredProduct.idProduct,
isConfigured: true,
configuredProduct: configuredProduct
}),
currency: "USD"});
// Quote is now submitted with the configured product in the KBMax portal. The
// resulting quote contains its ID. Similarly, insertToDb is a pseudocode placeholder
// for whatever handling and processing of this data you would do for your individual
// business needs.
insertToDb(new KBMaxQuoteData({
user: yourWebsiteUserSessionData,
kbmaxQuoteId: quote.id
});
In this simple case, the Epicor CPQ REST API is called to submit the quote with the configured product. Note that this has to do be performed on the server-side because typically the embedded configurator is being created as an anonymous user, which is unable to submit quotes. The server-side authenticates with a special user that has permissions to submit quotes. After the quote has been submitted, you have its ID, which you can store in your database to map this quote ID to your own data, which is typically a user of your portal, but could also be mapped to a shopping cart. Note that because the quote is submitted, it is going through the workflow just as if you had clicked the submit button on a quote within the Epicor CPQ portal. In certain other use-cases you may want to instead save the quote without submitting it, deferring its submission until your user has performed another action, such as committing his/her changes or completing a purchase.
If you wish end-users to have the ability to make changes to a configured product they created, you can alter your page to have the embed receive a fully populated configuredProduct which would be retrieved from the server-side. Consider this server-side code to receive the configured product:
var login = authenticateKBMaxAPI("username", "password"); var quote = callKBMaxAPI(login, "GET", "/api/quotes/" + quoteID); // Assuming the quote has a single quote product inside with the proper configured product inside. var configuredProduct = quote.products[0].configuredProduct;
Note that with this flow, enforcing permissions would be performed on the customer's server-side. This is because of the anonymous nature of users using the embed in Epicor CPQ. You may need to add some logic to ensure the quoteID in question is actually accessible to whichever user is on this page.
<html>
<head>
<title>Embedded Configurator</title>
<scriptsrc="https://subdomain.kbmax.com/js/embed.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function() {
//start the embed
var config = new kbmax.ConfiguratorEmbed({
elementId: "viewer",
configuratorId: id,
configuredProduct: configuredProduct, // The same ID as the quote product id,
showFields: true, // typically attained by retrieving the
showHeader: false, // quote and calling quote.products[0].id
showConfigHeader: true,
showMove: false,
bindToFormSelector: "",
loadStyle: "none",
});
document.getElementById("btnSubmit").click = function() {
config.getConfiguredProduct(function(cp) {
// Store the configured product's JSON in the hidden input
document.getElementById("configuredProduct").value = JSON.stringify(cp);
document.getElementById("quoteId").value = quoteId;
document.getElementById("configuredProductId").value = configuredProduct.id;
document.getElementById("configuratorForm").submit();
});
}
});
</script>
</head>
<body>
<h1>Embedded Configurator</h1>
<div id="viewer"></div>
<form id="configuratorForm"action="path_to_submit_serverside_script"method="POST">
<input type="hidden"name="configuredProductId"id="configuredProductId"/>
<input type="hidden"name="quoteId"id="quoteId"/>
<input type="hidden"name="configuredProduct"id="configuredProduct"/>
</form>
<button id="btnSubmit">Submit Configuration</button>
</body>
</html>
After submittting the newly modified configured product. Your server-side code will then resemble this:
Your Server-side pseudocode
var configuredProduct = parseJson(FORM_VALUES["configuredProduct"]);
var configuredProductId = configuredProduct.id;
var quoteId = FORM_VALUES["quoteId"];
var login = authenticateKBMaxAPI("username", "password");
var quote = callKBMaxAPI(login, "PUT", "api/quotes/" + quoteId + "/product/" + configuredProductId, configuredProduct);
Editing quote products in a quote via the API are subject to the same permissions as in the portal. This call will fail if the quote is in a state that does not allow editing products.
Retrieving Files from a Built Quote
Once a quote has been saved and submitted into a workflow, some workflow stages can create documents. You can retrieve them to store in your own document repository, or perhaps transmit them directly to the customer. See the examples in the Accessing Quotes and Quote Products document.
What's Next
This represents the basic scenario of integrating your configurator into your website. Your specific needs may add more details to this flow, such as retrieving built files from a submitted quote, and you may wish to perform other workflow-related tasks as part of your integration. To expand on your integration, the REST API documentation and SDK (if applicable) can offer a wealth of information to perform those more specific needs.