This recipe was originally published on the Twilio Blog. It uses material from the following blog posts:
For brevity, sections of the resources above will be referenced in the build section below.
Putting it together
This project will be in three sections: one for setting up IBM, one for setting up Segment, and one for setting up Twilio.
Setting up your IBM account
First we will set up a Watson Natural Language Service in your IBM account. Follow the instructions for the section Make a Watson Natural Language Service in this blog post. You can stop after you have set up your Watson Natural Language Service and have your Watson URL and API key. Save the API key and URL, we will use these when we set up our Twilio Functions later.
Setting up Segment
Navigate to your Segment dashboard and create a new Source Function by following Segment’s documentation here. Copy and paste the following code into your newly created Source Function code editor and name it “Twilio Sentiment Record.” Click “Save & Deploy” to save this Function.
asyncfunctiononRequest(request, settings){
const body = request.json();
Segment.identify({
userId: body.userid,
traits:{
phoneNumber: body.phoneNumber
}});
Segment.track({
event: body.event_name,
userId: body.userid,
properties:{
phoneNumber: body.phoneNumber,
sentiment: body.sentiment
}});
}
Once this Function is deployed, copy the URL and save it. We will use this URL as a webhook in our Twilio Studio Flow later. When the Studio Flow posts to the webhook, Segment will track an event that records the user’s sentiment as positive, negative, or neutral.
Next, set up your Destination Function by following Segment’s documentation here. Then, copy and paste the following code below to the code editor in your newly created Destination Function and name it “Send Twilio SMS.”
This code requires a few dependencies from Twilio, including your Account SID, Auth Token, and a Twilio phone number.
If you’re familiar with Twilio and know the phone number you’d like to use, go ahead and set those values in the Function settings with four variables named `twilioAccountId`, `twilioToken`, and `twilioFrom`– if not then hold off until we set up our Twilio environment in the next section.
async function onTrack(event, settings){
let Body ='Here is a 10% off code just for you! Use SPRING10 at check out on your next order';
if(event.properties.sentiment =='negative '){
Body ='We appreciate your business and recognize today's experience may not have been ideal. We would value your feedback on how we can improve your experience.';
}
// const product = event.properties.products[0];
// const itemPurchased = `${product.brand} ${product.name}`;
const To = event.properties.phoneNumber;
// settings.twilioDestinationNumber;
if(settings.twilioFrom){awaitsendText({
From: settings.twilioFrom,
To,
Body
},
settings
);
}
if(settings.twilioWhatsAppFrom){
// Learn more at: https://www.twilio.com/docs/whatsapp
awaitsendText({
To:'whatsapp:'+ To,
From: settings.twilioWhatsAppFrom,
Body
},
settings);
}
}
/**
* Sends SMS or WhatsApp message with Twilio
*
* https://www.twilio.com/docs/sms
*
*/
async function sendText(params, settings){
const endpoint =`https://api.twilio.com/2010-04-01/Accounts/${settings.twilioAccountId}/Messages.json`;
await fetch(endpoint,{
method:'POST',
headers:{
Authorization:`Basic ${btoa(settings.twilioAccountId +':'+ settings.twilioToken)}`,'Content-Type':'application/x-www-form-urlencoded;charset=UTF-8'},
body:toFormParams(params)
});
}
function toFormParams(params){
return Object.entries(params).map(([key, value])=>{
const paramName =encodeURIComponent(key);
const param=encodeURIComponent(value);
return`${paramName}=${param}`;
}).join('&');
}
Click “Save” to save this Function, we will deploy this later once we have all of our Twilio dependencies.
This code will send an SMS to the user once they have recorded a ‘Contacted Support’ event. The message body they receive depends on the event property ‘Sentiment’; if the value is `negative` then they will receive a request for feedback, otherwise, they will receive a discount for their next purchase.
Next, we will sync our newly created Source Function to our Destination Function. Navigate to your Source Function by clicking into “Connections”, then “Sources”, and then your Source Function named “Twilio Sentiment Record.” Then, click “Add Destination” and select your Destination Function named “Send Twilio SMS” from the “Functions” tab.
By linking this Source and Destination Function, every time a user records an event, an SMS will be sent out automatically. In a real-world example, we may want to delay this or set up an Audience in Segment to target when exactly those users should receive a text.
Setting up Twilio
Dependencies for Segment
Navigate to your Twilio console and copy your Account SID and Auth Token; we will use these in our Segment Destination Function. Next, purchase a phone number (or choose a phone number you already own) that you would like to use for this project. This number will be used as the support line which users can call and text.
Once you have these three things, navigate back to your Segment Destination Function named “Send Twilio SMS”, click into “Settings, add your Account SID to the variable `twilioAccountId.` Continue to add your Auth Token to `twilioToken` and your phone number to `twilioFrom.` Save and deploy this Function.
Setting up the Twilio Function
Next, we will set up a Twilio Function to look up the sentiment of a user when they call into your IVR. Navigate back to your Twilio account and click into “Functions”, then “Services”, and “Create Service.” Name this Service “sentiment-analyzer.”
On the next screen, click “Add +” and select “Add a Function.” Then add the following code to the code editor:
const NaturalLanguageUnderstandingV1 = require('ibm-watson/natural-language-understanding/v1');
const { IamAuthenticator } = require('ibm-watson/auth');
exports.handler = function(context, event, callback) { console.log(event.Body, event.speech_result);
const analyzeParams = {
'text': event.speech_result,
'features': {
"sentiment": {},
"categories": {},
"concepts": {},
"entities": {},
"keywords": {}
}
};
const naturalLanguageUnderstanding = new NaturalLanguageUnderstandingV1({
version: '2020-06-12',
authenticator: new IamAuthenticator({
apikey: context.watson_apikey,
}),
url: context.watson_url,
});
naturalLanguageUnderstanding.analyze(analyzeParams)
.then(analysisResults => {
const score = analysisResults.result.sentiment.document.score;
const label = analysisResults.result.sentiment.document.label;
let categories = analysisResults.result.categories;
let keywords = analysisResults.result.keywords;
categories = categories.filter(item => item.score > 0.8).map(item => item.label).join(', ').replace(/\\|\//g,', ');
categories = categories.substring(1).split(','); //remove initial comma
keywords = keywords.reduce((a,v,i) => {return a + (i===0?"":", ") + v.text}, "");
const sentiment = label
console.log("this is the sentiment", sentiment)
return callback(null, sentiment)
})
.catch(err => {
callback(null, 'Error: ' + err);
});
};
Once that code is added, make sure to save your work.
Next we will add our IBM Watson dependencies to our Function. Click on “Environment Variables” and add the following:
Next click on “Dependencies” and make sure that you have the following libraries installed:
Next click on “Dependencies” and make sure that you have the following libraries installed:
Here is where you will paste it into your Studio Flow:
Finally, click “Publish” to save these changes.
Once your Studio Flow is completed, navigate to your Phone Number and select your Studio Flow “Support Line” for when a call comes in. Click “Save” to save your changes.
Testing it out
Now that your IVR is set up, go ahead and call your number and say something. You can try saying “I’m having issues with the app” or “I had a frustrating experience I’d like to report”, and see what text message you get.
You can also check your Segment event debugger to see your events come in live and see the different sentiment recorded for different phrases.
Taking it to the next level
To recap, we built an IVR in Twilio that takes what a user says, analyzes the sentiment using IBM’s Watson API, and records the sentiment in Segment as an event. Segment then uses Twilio’s messaging API to send that user a personalized message based on their sentiment.
Matching the tone of your communications with what your customer is experiencing is a great way to foster trust with them, and using sentiment analysis is one of the many ways you can personalize your messages.
Here are some ways you can expand on this project:
Use a different sentiment analysis tool, or instead of using natural language machine learning, flag certain phrases like “returns”, “delayed shipping”, or “order issues” to offer those audiences a form for feedback instead of a marketing message.
Rather than creating a direct link from the Source and Destination functions which automatically sends a message when a “Contacted Support Line” event is tracked, create a Segment audience that checks to see if a user did the event “Contacted Support” and what the sentiment was. Audiences can be synced to a destination.
By now, we hope you’re ready to personalize your customer communications. Sign up for your Twilio Account and Segment account today!
Getting started is easy
Start connecting your data with Segment.