Headless with Intershop

As we all know, to be successful in commerce we have to make it easy for the customer to make business with us. That’s why it is not just about the classic web shop anymore, it is of course about mobile, but also about all the other nice and innovative touch points like Microsoft HoloLens, the self-ordering smart shelf or voice assistants.

From the customer’s point of view this is easy: Provide a frictionless and personalized digital purchasing and services experience, wherever and whenever it is requested or initiated by a customer or device. 

From the architecture point of view, this has a dramatic impact. It is not sufficient anymore that the server renders web pages and transfers them to the web browser. Instead, every functionality must be exposed as API so that it can be consumed by any touch point. This approach is often called headless because the front end (or the “head”) is decoupled and in some cases completely removed. For Intershop I prefer the term API-based commerce platform with a decoupled front end because Intershop does not just provide the APIs, but also a progressive web app based on Angular

Hey, but that’s enough theory, let’s put the APIs into use. For my last webinar (German audio, English subtitles), I built a small showcase using voice commerce with Cortana. I used our inTRONCIS blueprint store. It sells mostly electronic products, but also printer paper. So please imagine the following scenario:

Patricia: “Hey Cortana, we are out of printer paper!”
Cortana: “Last time you ordered Epson Glossy Photo Paper. Do you want to order that again? The price is $9.20”
Patricia: “Yes, please.”
Cortana: “Ok, I am ordering printer paper at inTRONCIS for you.”

To realize this, we need the following ingredients:

  • Cortana
  • Azure Bot Services
  • Microsoft LUIS Language Understaning
  • Intershop

First I created a Bot Service using the Azure Portal. I used a NodeJS Functions Bot with the “Language understanding” bot template. With Function Bots, the bot code is implemented as an Azure function and you only have to pay if the bot is used – perfect for our little test bot. The only disadvantage, you get a huge function monster with over 200000 lines of JS code. But the monster couldn’t scare me and I simply added my piece of code for the dialog:

bot.dialog('BuyPrinterPaperDialog',[
(session) => {

session.dialogData.productInfo = getLastOrderedPrinterPaper();
let text = 'Last time you ordered ' + session.dialogData.productInfo.name;
session.say(text, text);
text = 'The current price is ' + session.dialogData.productInfo.price;
session.say(text,text);
text = 'Do you want to order it again?'; session.say(text,text);
builder.Prompts.choice(session, "Do you want to order it again?","Yes|No",{listStyle:3});
},
(session,results) => {

session.send(results.response.entity );
if( results.response.entity == "Yes" )
{
let text = 'Ok, I am ordering printer paper at inTRONICS for you.';
session.say(text,text);

if( createIntershopOrder(session.dialogData.productInfo.sku) ){
text = 'Order completed successfully.';
session.say(text,text);
}
else{
text = 'Order could not be placed.';
session.say(text,text);
}

text = 'Is there anything else I can do for you?';
session.say(text,text);
builder.Prompts.choice(session, "Is there anything else I can do for you?","Yes|No",{listStyle:3});
}
else
{
let text = 'Ok, let me know, if you change your mind.';
session.say(text, text);
}

},
(session,results) => {

let text = 'You are welcome! Thank you for buying at Intershop inTRONICS! Good bye and have a nice day.';
session.say(text, text);

session.endDialogWithResult(results);
}]
).triggerAction({
matches: 'BuyPrinterPaper'
})

Note the trigger action “BuyPrinterPaper” at the end of the code example. That is where AI comes into play with Microsoft LUIS natural language. In the LUIS portal, I defined the “intent” that printer paper is needed. That means, in my bot code I do not have to check for a hard-coded set of phrases, instead I can rely on LUIS to understand the intent of the customer, even if different words and phrases are used.  

Ok, now most importantly the Bot must be able to order printer paper at inTRONCIS on behalf of the customer. That’s pretty easy because Intershop provides the commerce functionality as a convenient REST API. This way developers do not need any special Intershop skills and they can also use any programming language they like. For the showcase I used Javascript to call the following Intershop REST API endpoints:

GET customer - login and get preferred ship-to address
GET basket - get the current basket
POST basket/{id}/items - add a product to the basket
PUT basket - set the ship-to address
POST basket/{id}/payments - add a payment method
POST orders - place the order

Here you can find the complete JS code to place the order for a registered customer:

// login and get customer details
let headersWithAuth = new Headers();
headersWithAuth.append('Content-Type', 'application/json');
headersWithAuth.append('Authorization', 'Basic ' + base64.encode("patricia@test.intershop.de" + ":" + "password"));
result = await fetch(baseUrl + "customers/-",
{ method: "GET", headers: headersWithAuth} )
.then(response=>{intershopAuthenticationToken = response.headers.get('authentication-token'); return response.json()});
let commonShipToAddressURN = result.preferredShipToAddress.urn;
defaultHeaders.append('authentication-token', intershopAuthenticationToken);

// get current basket
result = await fetch(baseUrl + "baskets/-", { method: "GET", headers: defaultHeaders} )
.then(response=>{return response.json()});
let basketId = result.id;

// add product to basket: EPSON GLOSSY PHOTO PAPER
bodyData = JSON.stringify({"elements":[{"sku":"821811","quantity":{"value":1}}]});
result = await fetch(baseUrl + "baskets/" + basketId + "/items",
{ method: "POST", body : bodyData, headers: defaultHeaders} )
.then(response=>{return response});

// set ship-to address
bodyData = JSON.stringify({
"commonShipToAddress" : {
"urn" : commonShipToAddressURN
}
});
result = await fetch(baseUrl + "baskets/" + basketId,
{ method: "PUT", body : bodyData, headers: defaultHeaders} )
.then(response=>{return response});

// set payment method
bodyData = JSON.stringify({"name":"ISH_INVOICE", "type":"Payment"});
result = await fetch(baseUrl + "baskets/" + basketId + "/payments",
{ method: "POST", body : bodyData, headers: defaultHeaders} )
.then(response=>{return response});

// final basket calculation
result = await fetch(baseUrl + "baskets/-", { method: "GET", headers: defaultHeaders} )
.then(response=>{return response});

// place order
bodyData = JSON.stringify({"basketID":basketId,"acceptTermsAndConditions":true});
result = await fetch(baseUrl + "orders",
{ method: "POST", body : bodyData, headers: defaultHeaders} )
.then(response=>{return response.json()});

Now let’s put the code into action. By default you get a Web Chat channel with your Chat Bot,  ideal to test the bot. However, we want voice commerce so I also added a Cortana channel to actually realize a conversation. The Cortana channel is connected to your Microsoft account and the Cortana skill for the Bot is automatically added to your Cortana. It can also be shared with a group of test users.  

That’s basically all that’s necessary to build conversational commerce with Intershop and you can see the final result here:

Headless with Intershop
Tagged on: