Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Connect Your Alexa Skills and Google Home Actions With Hubspot CRM

DZone's Guide to

Connect Your Alexa Skills and Google Home Actions With Hubspot CRM

Want to be able to connect customers to your CRM using intents for Alexa skills and Google Home actions? Here's how to do it with Hubspot.

· IoT Zone
Free Resource

Download Red Hat’s blueprint for building an open IoT platform—open source from cloud to gateways to devices.

You need CRM to make your business more efficient and increase your revenue by creating repeatable, successful processes. Your Hubspot CRM would be a great addition to your conversational applications. Your Amazon Alexa skills, Google Home actions, and Facebook messenger bots could be a great source of customer data and can utilize the data you collect to provide a better service to your customers.

In this tutorial, we will learn how you can update your Hubspot CRM data directly from your conversational application, focusing on how we can fetch the user data from Hubspot CRM and use it to personalize the response. We will demonstrate how the application can react when users ask to get in touch with the sales department. The application will try to identify the user in the CRM, will create a new lead if needed, and if possible, will offer to connect the user immediately to an agent.

Conversation.one is a free build-once-deploy-anywhere platform where your app can be deployed as an Alexa skill, Google Home action, Facebook Messenger bot, or a chatbot on your website. For this tutorial, you will need a Conversation.one account. If you have an account, log in, otherwise sign up for free.

You can download this tutorial code from  here. Later, just import it to a new app using the Import button.

Create New Intents

  1. Add a new intent named “ContactSales”
    • Add the sample “Please ask sales to contact me” to the “User says”
    • Add the following entities:
      • “FirstName” – “US First Name”
      • “Email” – “Email”
      • “PhoneNumber” – “Phone Number”
    • Add a script response with the following code. We will add the code later to the “business logic” tab.
    return ContactSales(context, req, res);
  2. Add a new intent named “EnterEmail”
    • Add the samples to the “User says”:
      • “(|My email is|My address is|My email address is) {Email}”
    • Add the following entities:
      • “Email” – “Email”
    • Add a script response with the following code.
    return sdk.conversationHelper.FillEntity([{
        "name": "Email"
    }], context, req, res);
  3. Add a new intent named “EnterPhoneNumber”
    • Add the samples to the “User says”:
      • “My (phone|mobile|telephone|) number is {PhoneNumber}”
      • {PhoneNumber}
    • Add the following entities:
      • “PhoneNumber” – “Phone Number”
    • Add a script response with the following code.
    return sdk.conversationHelper.FillEntity([{
        "name": "PhoneNumber"
    }], context, req, res);
To make sure you properly identify the users’ intent, you need to configure 10-30 different samples.

Business Logic

The code below will collect the needed lead information from the user, will track the lead’s activity in Hubspot, and will offer the lead to get a phone call from an agent. If the user agrees, the system will initiate a phone call immediately.

function ContactSales(context, req, res) {
    return GetLeadInfo(context, req, res, ["phoneNumber", "firstName"]).then(function(leadInfo) {
        if (!leadInfo) {
            return;
        }
        req.getSession().set('onYes', JSON.stringify({
            callback: 'CallSales',
            data: {
                phone: leadInfo.phoneNumber,
            }
        }));
        req.getSession().set('onNo', JSON.stringify({
            callback: 'whatHappenedTodayOnNo',
            data: {}
        }));
        var url = "https://track.hubspot.com/v1/event?_n=ChatContactSales&_a=2452897&email=" + leadInfo.email;
        return fetch(url)
            .then(function(result) {
                res.say("Do you want me to connect you now on the phone?");
            });
    }).catch(function(err) {
        res.say(err);
    });
}

function CallSales(context, req, res, data) {
    sdk.twilloCall(data.phone, "+16467080983");
}


  • The function “GetLeadInfo” (we will see the details later) will get the lead’s phone number and first name.
  • We will ask the user if they want to get connected to an agent on the phone. You can learn more about developing a contextual application here.
  • If the user says “Yes”, the system will initiate a call using the “sdk.twilloCall” method.

Collect User Information

The function GetLeadInfo will make sure to collect all the needed properties from the user, or from saved data in Hubspot. The key for each lead is its email, so we will start by collecting that. Notice that once we have some lead information, we will save it in the session file to make sure we don’t need to ask the user for same data again and again:

function GetLeadInfo(context, req, res, properties) {
    var origLeadInfo = {};
    var leadInfo = {};
    if (req.getSession().get("LeadInfo")) {
        leadInfo = JSON.parse(req.getSession().get("LeadInfo"));
        origLeadInfo = JSON.parse(JSON.stringify(leadInfo));
    }
    var wait = [];
    if (!leadInfo.email || leadInfo.email === "") {
        if (!req.slot("Email")) {
            sdk.conversationHelper.askForEntity(context, req, res, [
                [{
                    "name": "Email",
                    "target": "Email"
                }]
            ], "What is your email address?", "For example you can say, My email address is john.smith@gmail.com");
            return Promise.resolve(false);
        }
        leadInfo.email = req.slot("Email");
    }
    return GetLeadFromCRM(context, req, res, leadInfo.email).then(function(result) {
        if (result && result.firstName && result.firstName !== "") {
            leadInfo.firstName = result.firstName;
        } else if (req.slot("FirstName")) {
            leadInfo.firstName = req.slot("FirstName");
        }
        if (result && result.lastName && result.lastName !== "") {
            leadInfo.lastName = result.lastName;
        } else if (req.slot("LastName")) {
            leadInfo.lastName = req.slot("LastName");
        }
        if (result && result.phoneNumber && result.phoneNumber !== "") {
            leadInfo.phoneNumber = result.phoneNumber.replace(/\D/g, '');
        } else if (req.slot("PhoneNumber")) {
            leadInfo.phoneNumber = req.slot("PhoneNumber").replace(/\D/g, '');
        }
        if ((properties.indexOf("firstName") != -1) && (!leadInfo.firstName || leadInfo.firstName === "")) {
            sdk.conversationHelper.askForEntity(context, req, res, [
                [{
                    "name": "FirstName",
                    "target": "FirstName"
                }]
            ], "What is your name?", "For example you can say, my name is John Smith.");
            return Promise.resolve(false);
        }
        if ((properties.indexOf("lastName") != -1) && (!leadInfo.lastName || leadInfo.lastName === "")) {
            sdk.conversationHelper.askForEntity(context, req, res, [
                [{
                    "name": "LastName",
                    "target": "LastName"
                }]
            ], "What is your last name?", "For example you can say, my last name is Smith.");
            return Promise.resolve(false);
        }
        if ((properties.indexOf("phoneNumber") != -1) && (!leadInfo.phoneNumber || leadInfo.phoneNumber === "")) {
            sdk.conversationHelper.askForEntity(context, req, res, [
                [{
                    "name": "PhoneNumber",
                    "target": "PhoneNumber"
                }]
            ], "What is your phone number?", 'For example you can say, my phone number is <say-as interpret-as="telephone">6467080983</say-as interpret-as>.');
            return Promise.resolve(false);
        }
        if (JSON.stringify(leadInfo) !== JSON.stringify(origLeadInfo)) {
            UpdateCRM(leadInfo);
        }
        req.getSession().set("LeadInfo", JSON.stringify(leadInfo));
        return Promise.resolve(leadInfo);
    });
}


  • We will start by looking for saved lead information. You can read more about storing and getting session data here.
  • If we do not have any stored email information, we need to ask the user to provide us with that information first. We collect that information using the method “sdk.conversationHelper.askForEntity” You can learn how to collect information from your user here.
  • Once we have the user’s email address, we will use it to get the CRM data using “GetLeadFromCRM” (we will see the details later)
  • Now that we have the CRM data, we will see if we are missing some of the needed properties. If something is missing, we will collect it from the user.

Connecting to Hubspot CRM

You can connect to Hubspot CRM using the integrated Node.js Hubspot module.

To initialize the Hubspot module, call the following code. You must use your own apiKey.

const Hubspot = require('hubspot');
const hubspot = new Hubspot({
    apiKey: '',
    maxUsePercent: 0
});


Fetching Lead Data From Hubspot CRM

We will use the method hubspot.contacts.getByEmail to fetch the CRM data. Notice that we will store the CRM data in the session to avoid multiple calls to Hubspot:

function CRMtoLeadInfo(result) {
    var leadInfo = {};
    try {
        if (result.properties["email"] && result.properties["email"].value) {
            leadInfo.email = result.properties["email"].value;
        }
        if (result.properties["firstname"] && result.properties["firstname"].value) {
            leadInfo.firstName = result.properties["firstname"].value;
        }
        if (result.properties["lastname"] && result.properties["lastname"].value) {
            leadInfo.lastName = result.properties["lastname"].value;
        }
        if (result.properties["phone"] && result.properties["phone"].value) {
            leadInfo.phoneNumber = result.properties["phone"].value;
        }
    } catch (err) {}
    return leadInfo;
}

function GetLeadFromCRM(context, req, res, email) {
    if (req.getSession().get("CRM")) {
        var crmInfo = JSON.parse(req.getSession().get("CRM"));
        return Promise.resolve(CRMtoLeadInfo(crmInfo));
    }
    return hubspot.contacts.getByEmail(email).then(result => {
        req.getSession().set("CRM", JSON.stringify(result));
        return Promise.resolve(CRMtoLeadInfo(result));
    }).catch(err => {
        return Promise.resolve(false);
    });
}
  • The function CRMtoLeadInfo helps us to convert the CRM lead format to our own JSON object.

Updating the Lead in Hubspot CRM

We will update the lead information using the method hubspot.contacts.createOrUpdate.

function UpdateCRM(leadInfo) {
    if (!leadInfo.email || leadInfo.email === "") return;
    var data = {
        "properties": []
    };
    if (leadInfo.firstName && leadInfo.firstName !== "") {
        data.properties.push({
            "property": "firstname",
            "value": leadInfo.firstName
        });
    }
    if (leadInfo.lastName && leadInfo.lastName !== "") {
        data.properties.push({
            "property": "lastname",
            "value": leadInfo.lastName
        });
    }
    if (leadInfo.phoneNumber && leadInfo.phoneNumber !== "") {
        data.properties.push({
            "property": "phone",
            "value": leadInfo.phoneNumber
        });
    }
    if (data.properties.length === 0) return;
    return hubspot.contacts.createOrUpdate(leadInfo.email, data).then(results => {}).catch(err => {});
}


Test Your New Application

Now that your app can collect and update CRM data, try out what you have so far.

In the chat console, type the request “Please ask sales to contact me”. After you type the request, hit “Send”.

The chatbot will collect your contact information and will offer to connect you with the sales department.

Build an open IoT platform with Red Hat—keep it flexible with open source software.

Topics:
alexa skills ,google home actions ,chatbot app development ,crm developer ,iot ,tutorial

Published at DZone with permission of Rachel Batish, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}