NEW Try Dasha in your browser with Dasha Playground!

Skyrocket your shopping cart conversion rate with a simple conversational AI app

Today we’ll be taking a look at how to create a conversational AI app that calls customers who’ve added an item to the cart but haven’t checked out. This app will be most applicable to online tech stores. Yet by following the logic of this demo, you can easily adjust the conversational flow to fit your business.

Set up your conversational AI workplace

You will need VSCode (Visual Studio Code), NPM, and Node.js, all the latest versions. As the next step, join Dasha developer community so that you can get your API key and be able to get assistance from our developers every step of the way.

To ease your coding process, you’ll need to download the Dasha Studio extension right from the VSCode extensions tab.

Once done, download Dasha Blank Slate App, open the folder in VSCode, and install Dasha CLI (command line interface by typing npm i -g "@dasha.ai/cli" in the VSCode terminal. For more on Dasha CLI usage, refer to this post.

In case you need assistance, ask in our developer community, and here is a step-by-step tutorial on getting started.

Now, clone and open a project with this cart checkout app source code here.

Once done with setting everything up you can move on to the coding part itself.

Get to know what you’ll use to create a cart checkout conversational AI app

There are 3 files you’ll be using: main.dsl, data.json, and index.js. Let’s take a quick look at the functions of these three.

Main.dsl - this is where you’ll write your DashaScript Language code to create the workflow of your conversational AI app. With Dasha Studio extension on and with the directions in this post, it’ll be an easy job for you. Data.json - this is where you set the intents and entities(AKA NER, AKA Named Entity Recognition). The neural network will use intents and entities you’ll create to learn. Index.js - it’s the NodeJS file that launches the Dasha SDK. Here you’ll be adding any external functions you deem necessary once adapting the code to your hotel’s needs.

Build your conversational AI app

The most important point to mention is that this app relies heavily on the intents and entities we set in the data.json file. Wherever you see #messageHasIntent(“name of intent”) is what triggers the intent from the data.json file, intents section.

When you open the data.json file, you see the following:

{ "version": "v2", "intents": { "yes": { "includes": [ "yes", "correct", "sure", "absolutely", "yes siree bob", "right", "yep", "you got it", "I would", "yeah", "I would", "I'd like that", "I wouldn't mind", "I would not mind", "sure thing", "yeah", "yea", "certainly", "absolutely", "totally", "mhm" ], "excludes": [ "fuck off" ] }, "no": { "includes": [ "no", "definitely not", "wrong", "incorrect", "I do not", "I don't", "I would not", "I wouldn't", "nope", "no, I'm okay", "not right now", "not this time", "nah", "not this moment", "not now" ], "excludes": [ "yes" ] }, "price_too_high": { "includes": [ "cost too much", "price was too high", "the price was too high", "way too high of a price", "cost was too high", "price was too much", "pay that much", "pay so much", "too expensive", "expensive", "price was a deal breaker", "cost too much", "cost way too much", "costs a lot", "couldn't afford", "couldn't afford at this price" ] }, "free_delivery_sounds_good": { "includes": [ "free delivery sounds good", "free delivery sounds lovely", "free delivery sounds fantastic", "free delivery sounds awesome", "free delivery sounds great", "love free delivery", "wouldn't mind a free delivery", "like not having to pay for the delivery", "love not having to pay for the delivery" ] }, "found_it_elsewhere": { "includes": [ "found it elsewhere", "found another place", "found a better place", "found a new place", "found another website", "found a new website", "found a better site", "found a better company", "found it at another company", "founding it at another website" ] },

The list of intents goes on and on. You write the intents down yourself based on what you think the user might say or what they have historically said in similar situations.

Entities come into play when you write down #messageHasData(“entity name”) (or #messageGetData(“entity name”). Here’s an example:

"entities": { "laptop_model": { "open_set": true, "values": [ { "value": "A11", "synonyms": [ "A 11", "A eleven", "the A 11 model", "A11 model", "model A11", "2011 model", "year two thousand eleven model" ] }, { "value": "A12", "synonyms": [ "A 12", "A twelve", "A twelve model", "model from two thousand twelve", "the 2012 model", "year 2012 model" ] }, { "value": "A13", "synonyms": [ "A 13", "A thirteen", "A thirteen model", "model from two thousand thirteen", "the 2013 model", "year 2013 model" ] }, { "value": "A14", "synonyms": [ "A 14", "A fourteen", "A fourteen model", "model from two thousand fourteen", "the 2014 model", "year 2014 model" ] }, { "value": "A15", "synonyms": [ "A 15", "A fifteen", "A fifteen model", "model from two thousand fifteen", "two thousand fifteen model", "the 2015 model", "year 2015 model" ] } ], "includes": [ "I'm looking for the (A 14)[laptop_model] model", "I'd like an (A twenty)[laptop_model] model", "I want to get an (A seventeen)[laptop_model] laptop model", "buy the (two thousand fifteen model)[laptop_model]" ] } } }

At this point, go to the main.dsl file and delete everything from there. Then, just follow the instructions to create the cart checkout AI app!

Now that you have your main.dsl file empty, it’s time to take a step forward and import the common libraries. Then, set your variables. In this case, we’ll have one input variable, which is the user’s phone number.

Right after that write a start node named root. It’s where you’ll establish a connection with the user’s phone, say the welcome message, and go from there.

After you’ve written out the start node, we can move forward with the nodes and digressions that can appear throughout the conversation with the user. At this point, we want to make sure the user has enough time to talk about their cart checkout. If the call was made at a convenient time and the user lets us know so, we transition to node how_can_i_assist. If Dasha called at an inconvenient time, the conversation will move to the node bye where we thank the user for the time and end the call.

// Import the commonReactions library so that you don't have to worry about coding the pre-programmed replies import "commonReactions/all.dsl"; context { // Declare the input variable - phone. It's your hotel room phone number and it will be used at the start of the conversation. input phone: string; // Storage variables. You'll be referring to them across the code. new_model: string=""; } // A start node that always has to be written out. Here we declare actions to be performed in the node. start node root { do { #connectSafe($phone); // Establishing a safe connection to the user's phone. #waitForSpeech(1000); // Waiting for 1 second to say the welcome message or to let the user say something #sayText("Hi, this is Dasha with JJC Group. I see you have the latest model of the Pear laptop in your cart and haven't completed the order on our website. Is it a good time to talk?"); // Welcome message wait *; // Wating for the user to reply } transitions // Giving directions to which nodes the conversation will go to { how_can_i_assist: goto how_can_i_assist on #messageHasIntent("yes"); bye: goto bye on #messageHasIntent("no"); } } node how_can_i_assist { do { #sayText("Wonderful! This won't take too long. I was just wondering if you have any concerns regarding the purchase of the laptop that's in your cart?"); wait*; } transitions { } } node bye { do { #sayText("Thanks for your time. We're looking forward to you shopping with us! Have a great day. Bye!"); exit; } }

If the user decides to continue the conversation regarding their cart checkout, we need to consider the possible reasons why the user hasn’t checked out in the first place. For the purpose of this demo, let’s consider the following reasons:

the price of the wanted item might have been too high; the item was found elsewhere, where the price/delivery/etc was more appealing; the user decided he needed to get some other item instead; they decided to get a different model of the item; the user might not have had enough money to complete the purchase for various reasons (waiting for a paycheck, not enough money in the bank account, etc); the delivery price was too high; the company doesn’t ship to their country; they might have been simply browsing your website, considering their options.

These are just a few reasons. However, when you adjust this code to your business’s needs, you should thoroughly think about all the possible reasons for your user not going through the funnel till the very end.

Now, let’s take a look at each of these in detail and write down the ways to change the user’s mind and help him decide to go complete the cart checkout process.

Say the user found the price to be too high, in this case scenario we could offer them a discount on the current or the next purchase. If they don’t accept this offer, we can program the conversation to go to the node where we ask if they have any other issues or concerns. If they do accept it, we go to the node complete_purchase.

digression offer_discount { conditions {on #messageHasIntent("price_too_high");} do { #sayText("I totally understand your concern and I have a sweet offer for you to consider! How would you feel about a 3 percent discount on this purchase?"); wait*; } transitions { any_other_concern: goto any_other_concern on #messageHasIntent("no"); complete_purchase: goto complete_purchase on #messageHasIntent("yes"); } } node complete_purchase { do { #sayText("Fantastic, glad you liked it! I've added the discount for the purchase to your account, hope you enjoy your shopping experience with us! Bye bye!"); exit; } }

Let’s say the user says they’ve found the same item elsewhere. We can ask about what made the user want to look for the item they wanted at another place, and then go from there:

digression found_it_elsewhere { conditions {on #messageHasIntent("found_it_elsewhere");} do { #sayText("Well, that happens! I'm glad you were able to find what you were looking for, even if it wasn't with us. But could I ask you what made you decide to look at another place?"); wait*; } transitions { ask_if_purchased: goto ask_if_purchased on #messageHasIntent("cheaper_elsewhere"); free_delivery_elsewhere: goto free_delivery_elsewhere on #messageHasIntent("free_delivery_elsewhere") or #messageHasIntent("delivery_price_too_high"); more_options_elsewhere: goto more_options_elsewhere on #messageHasIntent("more_options_elsewhere") or #messageHasIntent("another_option_elsewhere"); future_discount: goto future_discount on #messageHasIntent("price_too_high"); } } node more_options_elsewhere { do { #sayText("Ah, I understand. JJC group has lots of different options of various laptops you can choose from. I just sent a selection of different laptop models you might like. It's now available on your web account. I hope you like the seleciton and find some options you like most. Does this sound good?"); wait*; } transitions { bye: goto bye on #messageHasIntent("sounds_good") or #messageHasIntent("free_delivery_sounds_good"); final_offer_bye: goto final_offer_bye on #messageHasIntent("no") or #messageHasIntent("need_to_consider") or #messageHasIntent("unsure") or #messageHasIntent("sounds_bad"); } } node future_discount { do { #sayText("I totally understand your concern. What I can do for you is offer a 5 percent discount on your next purchase. I hope this improves your shopping experience with us! Would you be okay with this future discount?"); wait*; } transitions { bye: goto bye on #messageHasIntent("sounds_good") or #messageHasIntent("yes"); final_offer_bye: goto final_offer_bye on #messageHasIntent("no") or #messageHasIntent("need_to_consider") or #messageHasIntent("unsure") or #messageHasIntent("sounds_bad"); } }

In case the user only said they’ve found the item elsewhere but said nothing about purchasing it, we can ask whether the item was actually bought:

node ask_if_purchased { do { #sayText("Uh-huh, understood. May I ask if you've bought it at that other place?"); wait*; } transitions { offer_new_item_discount: goto offer_new_item_discount on #messageHasIntent("yes") or #messageHasIntent("purchased_elsewhere"); offer_discount: goto offer_discount on #messageHasIntent("no") or #messageHasIntent("didn't_purchase_elsewhere"); } } node offer_new_item_discount { do { #sayText("Gotcha. I hope you enjoy your new purchase! And just as a small gift from us I'd like to offer you a 5 percent discount on all the laptop accessories we have."); wait*; } transitions { bye: goto bye on #messageHasIntent("no") or #messageHasIntent("sounds_bad"); offer_expires_soon_bye: goto offer_expires_soon_bye on #messageHasIntent("yes") or #messageHasIntent("sounds_good"); } }

Now let’s write down the way the conversation should go in case the user says they need another model of the laptop:

digression ask_another_model { conditions {on #messageHasIntent("another_model");} do { #sayText("Do you have a specific model in mind?"); wait*; } transitions { other_models: goto other_models on #messageHasIntent("no") or #messageHasIntent("unsure"); another_model: goto another_model on #messageHasData("laptop_model"); } } digression other_models { conditions {on #messageHasIntent("unsure") or #messageHasIntent("models_available");} do { #sayText("I just sent a link to all the similar models we have to your email. You'll find all the features, price, and all the other info you need right there. It's gonna be a pretty useful link for you! Now, do you have any other concerns regarding your purchase?"); wait*; } transitions { how_may_i_help: goto how_may_i_help on #messageHasIntent("yes"); email_sent_bye: goto email_sent_bye on #messageHasIntent("no"); } } node how_may_i_help { do { #sayText("What may I help you with?"); wait*; } transitions { } } digression how_may_i_help { conditions {on #messageHasIntent("no") or #messageHasIntent("need_to_consider") or #messageHasIntent("unsure");} do { #sayText("Is there anything I can do to improve your shopping experience with us or help you in any kind of way?"); wait*; } } node email_sent_bye { do { #sayText("Awesome. The email must have reached you by now, so check it out! Thank you for taking the time to talk, have an awesome day! Bye!"); exit; } } node other_models { do { #sayText("I just sent a link to all the similar models we have to your email. You'll find all the features, price, and all the other info you need right there. It's gonna be a pretty useful link for you! Now, do you have any other concerns regarding your purchase?"); wait*; } transitions { how_may_i_help: goto how_may_i_help on #messageHasIntent("yes"); email_sent_bye: goto email_sent_bye on #messageHasIntent("no"); } } digression another_model { conditions {on #messageHasData("laptop_model");} do { set $new_model = #messageGetData("laptop_model")[0]?.value??""; #sayText("We have " + $new_model + " available! I've just added to your cart. And as a small gift I'll added a 3 percent discount coupon to your next purchase. Does this offer sound good to you?"); wait *; } transitions { send_link_to_purchase: goto send_link_to_purchase on #messageHasIntent("yes") or #messageHasIntent("sounds_good"); final_offer_bye: goto final_offer_bye on #messageHasIntent("no") or #messageHasIntent("need_to_consider") or #messageHasIntent("unsure"); } } node send_link_to_purchase { do { #sayText("Perfect, I'm glad to hear that! You'll see the laptop added to your cart and also I'm about to send a link to your email which will let you complete the purchase in one click. Thank you for taking the time to talk, have an awesome day! Bye!"); exit; } } node another_model { do { set $new_model = #messageGetData("laptop_model")[0]?.value??""; #sayText("We have " + $new_model + " available! I've just added to your cart. And as a small gift I'll added a 3 percent discount coupon to your next purchase. Does this offer sound good to you?"); wait *; } transitions { send_link_to_purchase: goto send_link_to_purchase on #messageHasIntent("yes") or #messageHasIntent("sounds_good"); final_offer_bye: goto final_offer_bye on #messageHasIntent("no") or #messageHasIntent("need_to_consider") or #messageHasIntent("unsure"); } }

Note that in this part of the code we have nodes and digressions with the same name. It’s not a mistake - nodes and digressions serve different purposes. Digressions exist to enter the conversation once the conversation goes off on a tangent. You can read more about digressions in this post.

Let’s consider the reason being the user not having enough money to fund complete the cart checkout process:

digression payment_options { conditions {on #messageHasIntent("waiting_for_salary") or #messageHasIntent("not_enough_money");} do { #sayText("Gotcha. I wanted to let you know that we have an installment plan you can take advantage of. Is it something you feel like considering?"); wait*; } transitions { confirm_installment: goto confirm_installment on #messageHasIntent("yes") or #messageHasIntent("agreed_installment"); trade_in: goto trade_in on #messageHasIntent("no") or #messageHasIntent("need_to_consider") or #messageHasIntent("unsure"); } } digression installment_plan { conditions {on #messageHasIntent("installment_plan");} do { #sayText("That's right, we have an installment plan you can take advantage of. Is it something you feel like considering?"); wait*; } transitions { confirm_installment: goto confirm_installment on #messageHasIntent("yes") or #messageHasIntent("agreed_installment"); trade_in: goto trade_in on #messageHasIntent("no") or #messageHasIntent("need_to_consider") or #messageHasIntent("unsure"); } } node confirm_installment { do { #sayText("Alright, you can now use the installment plan option for your purchase! Is there anything else I can help you with?"); wait*; } transitions { bye: goto bye on #messageHasIntent("no"); how_may_i_help: goto how_may_i_help on #messageHasIntent("yes") or #messageHasIntent("something_else_to_ask"); } } node trade_in { do { #sayText("Oh, by the way, there's also a trade in option. You can bring your old laptop to us and have a heavy discount for a new one. Does this sound like a plan?"); wait*; } transitions { confirm_trade_in: goto confirm_trade_in on #messageHasIntent("yes") or #messageHasIntent("agreed_trade_in") or #messageHasIntent("sounds_good"); final_offer_bye: goto final_offer_bye on #messageHasIntent("no") or #messageHasIntent("need_to_consider") or #messageHasIntent("unsure") or #messageHasIntent("sounds_bad"); } } digression trade_in { conditions {on #messageHasIntent("trade_in");} do { #sayText("Absolutely! We do have a trade in option. You can bring your old laptop to us and have a heavy discount for a new one. Does this sound like a plan?"); wait*; } transitions { confirm_trade_in: goto confirm_trade_in on #messageHasIntent("yes") or #messageHasIntent("agreed_trade_in") or #messageHasIntent("sounds_good"); final_offer_bye: goto final_offer_bye on #messageHasIntent("no") or #messageHasIntent("need_to_consider") or #messageHasIntent("unsure") or #messageHasIntent("sounds_bad"); } } node confirm_trade_in { do { #sayText("Alright, I've made a note of this. You can come to any convenient location for the trade-in, or send your laptop to us via mail and do the rest online. Is there anything else I can help you with?"); wait*; } transitions { bye: goto bye on #messageHasIntent("no"); how_may_i_help: goto how_may_i_help on #messageHasIntent("yes") or #messageHasIntent("something_else_to_ask"); } } node final_offer_bye { do { #sayText("As a final offer I would like to give you a 5 percent discount coupon, I just added it to your account. It expires in two weeks so make sure you don't lose the opportunity to use the discount! Thank you for taking the time to chat, bye bye!"); exit; } }

The following digressions and nodes follow the same logic at the previous ones, so it will be easy for you to navigate. Let’s now write out the way the conversation should go in case the user has concerns regarding the delivery/shipping:

digression delivery_price_too_high { conditions {on #messageHasIntent("delivery_price_too_high");} do { #sayText("I'm sorry you feel that way! What I can do for you this time is offer you a one-time free delivery. How does that sound?"); wait*; } transitions { offer_expires_soon_bye: goto offer_expires_soon_bye on #messageHasIntent("yes") or #messageHasIntent("sounds_good"); final_offer_bye: goto final_offer_bye on #messageHasIntent("no") or #messageHasIntent("need_to_consider") or #messageHasIntent("unsure"); } } digression country_delivery { conditions {on #messageHasIntent("my_country_delivery");} do { #sayText("I apologize for the inconvenience! We can think of a way to send you your purchase. We have a USPS delivery option and it does deliver to your country. The delivery costs 57 dollars. How does this sound to you?"); wait*; } transitions { send_with_usps: goto send_with_usps on #messageHasIntent("yes") or #messageHasIntent("sounds_good"); no_dice_bye: goto no_dice_bye on #messageHasIntent("no") or #messageHasIntent("need_to_consider") or #messageHasIntent("sounds_bad") or #messageHasIntent("unsure"); } } node offer_expires_soon_bye { do { #sayText("Okay! Just to let you know this offer expires in 2 weeks, so make sure you use it before it expires. Is there anything else I could help you with?"); wait*; } transitions { bye: goto bye on #messageHasIntent("no"); how_may_i_help: goto how_may_i_help on #messageHasIntent("yes") or #messageHasIntent("something_else_to_ask"); } } node send_with_usps { do { #sayText("Perfect, you'll have an option in your account to check out and get your laptop delivered by USPS. Do you have any questions?"); wait*; } transitions { bye: goto bye on #messageHasIntent("no"); how_may_i_help: goto how_may_i_help on #messageHasIntent("yes") or #messageHasIntent("something_else_to_ask"); } } node free_delivery_elsewhere { do { #sayText("Got that. I understand what you mean. We care about our customers having the best experience possible, so I would like to offer you free delivery for your next purchase. How does that sound to you?"); wait*; } transitions { bye: goto bye on #messageHasIntent("sounds_good") or #messageHasIntent("free_delivery_sounds_good"); final_offer_bye: goto final_offer_bye on #messageHasIntent("no") or #messageHasIntent("need_to_consider") or #messageHasIntent("unsure") or #messageHasIntent("sounds_bad"); } }

Considering that the user might have simply been browsing the website, let’s write down a node for that:

digression was_just_browsing { conditions {on #messageHasIntent("was_just_browsing");} do { #sayText("Haha okay, that's fine too! Just so you know, we have a big sale coming up, so watch out for an email announcement! Thank you for taking the time to talk, have an awesome day! Bye!"); exit; } }

Don’t forget that the user might not be sure about something and have concerns or issues they haven’t spoken about yet:

node any_other_concern { do { #sayText("Do you have any other concerns regarding completing the purchase?"); wait*; } transitions { } } digression not_sure { conditions {on #messageHasIntent("unsure");} do { #sayText("In this case, may I ask what are you concerned about?"); wait*; } }

Here the transitions section is empty since the nature of the concern could be anything and the conversation would move to one of the digressions from here.

Almost done!

There are going to be times when there’s no way to convince the user to finish the cart checkout process. Let’s account for that with node no_dice_bye:

node no_dice_bye { do { #sayText("I'm sorry I couldn't be of help to you today. Thank you for taking the time to talk, have an awesome day! Bye!"); exit; } }

And done!

I suggest you adjust this conversational AI app to the needs of your business and to the industry your business is in. Don’t forget to join Dasha developer community for guidance throughout this exciting journey. It’s a great community to meet like-minded developers.

Enjoy the coding process and godspeed!

Related Posts