In your business’s customer operations, you know the importance of providing personalized experiences and building genuine connections with your customers. If you use Twilio Flex as your contact center, then you provide your customer support agents with a wealth of information about the customers they interact with. Specifically, you can provide them with information about how a customer has engaged with your channels, their purchase history, and their customer lifetime value.
All of that information, of course, comes from Twilio Engage, a growth platform available through Twilio Segment. In this recipe, we’ll walk through how to connect all of the pieces.
As an example, we want our customer support agents to know whether the customer they are interacting with has purchased a specific product (Espresso Roast coffee beans) in the last 30 days. Having this information will help the agent to build a connection and offer targeted support.
At a high level, here is what we will build:
In Twilio Engage, we’ll build an Audience of customers who have purchased the specific product in the last 30 days.
Then, we’ll build a Twilio Function that calls the Profile API, which is part of Segment Unify. This function will take the email address of a customer and query the API to see if the customer is part of the Audience we created.
Finally, we’ll build a plugin in Twilio Flex that updates an agent’s task information panel with this recent purchase information for the customer.
Recipe requirements
To follow along through this recipe, you will need access to the following:
A Twilio Segment account (sign up here for free), with access to Twilio Engage (contact your account representative for help with access to Engage). Segment is Twilio’s customer data platform. Engage is a growth platform offered as a product add-on for Business Plan users of Segment.
A Twilio account (sign up here for free)
A basic understanding of Node.js, for writing a Twilio Function. Twilio Functions are Serverless functions that you can write to give you programmatic access to Twilio data and assets.
An instance of Twilio Flex, which you can create from the Console within your Twilio account. Twilio Flex is a contact center that your customer support agents can use to engage with customers across various channels.
With all of your starting pieces in place, let’s begin putting them together.
Build an Audience with Twilio Engage
To keep our demo simple, we’ll work with a basic set of data.
In addition to these customers and products, we have a set of several orders placed by these customers over the last six months.
We loaded our customer data into Segment by creating an HTTP Tracking API source. Using this source, we made Identify calls to ensure Segment can associate actions with customers based on their ID or email. Then, we made Track calls to associate “Item Purchased” events (one per order) with our customers.
We’re interested in those customers that have purchased our “Espresso Roast, whole bean” product in the last 30 days. For this, we’ll build a customer Audience with Twilio Engage.
Create a space in Segment Unify
If you’re new to using Segment and Engage, then you’ll need to set up a few things first. After logging in, click on the Unify link in the navbar on the left side.
Then, click on Create Space for working with customer profiles and journeys. We’ll create a new Dev space called “Customer Purchase Flex Follow-Up.”
Connect Unify to a data source
Unify must connect to a source for its data. For our example, we will use the HTTP Tracking API source that we created. After connecting Unify to our source, we can view the Profile explorer to see our list of customers.
Create an Audience in Engage
With Unify set up, we can begin working with Twilio Engage. Click on the Engage link in the navbar on the left side.
In Engage, we click Audiences and then Create ➤ Audience. From there, we set up the conditions that would qualify a customer to be a part of our Audience. We want customers who performed the “Item Purchased” action where the product name was “Espresso Roast, whole bean.” And we only want to include those customers that performed this action in the last 30 days.
As we set up our criteria, we can preview which customers would presently be a part of this Audience.
Finally, we specify a name for our Audience and prepare to create it. We make sure to check the box labeled Compute without enabled destinations. Engage can compute your Audience and send that information downstream to destinations (such as a data warehouse or an email campaign platform). However, we simply want to access this information by making calls to the Profile API. We won’t need a dedicated destination, but we still want our audiences computed anyway.
Notice that Segment generates an “audiences key” for this Audience (in this case, it’s recently_purchased_espresso_roast
). This key will show up in a customer’s list of traits, as we’ll see in a later step.
Audiences in Engage are regularly updated and computed in real time. Engage doesn’t only compute the Audience for the present moment. Say goodbye to needing to get the “latest customer list CSV” from the sales or order fulfillment team. Whenever you need it, Engage will have the most up-to-date list of customers who have purchased this product in the last 30 days.
After we create our Audience, Engage begins to comb through its data to determine which customers make up the Audience.
Depending on the overall size of your dataset, and the criteria you specify, this initial computation may take anywhere from a few minutes to an hour. For our example, we soon see the present state of our Audience.
When we look at the Audience Explorer for more details, we see that among all of our customers, Alex Anderson and Charlie Cooper have purchased the Espresso Roast product within the last 30 days.
With our Engage Audience set up, it’s time to build a Twilio Function that can retrieve this information about any given customer.
Build a Twilio Function
Our Twilio Function will take a customer email address as a parameter, and then it will call the Profile API to query for that customer’s traits. Among those traits is a boolean called recently_purchased_espresso_roast
that tells us whether the customer is part of the Audience we created.
Obtain API access token and Unify space ID
To authenticate our calls to the Profile API, we need an API access token. Within Segment, we navigate to Unify ➤ Unify Settings.
In the API access tab, we click Generate token and provide a description for our token.
After generating our token, we make sure to copy the value. We’ll use it soon.
To authenticate our requests, we will also need our Unify space ID, which is also displayed for us on the API access page. We copy this value too.
Test Profile API access
Just to make sure that we have everything we need to access the Profile API, we’ll test out a simple curl call from our local command line. We’ll retrieve the traits for our customer with email alex@example.com.
$ curl -H "Content-type:application/json" \
-u INSERT-ACCESS-TOKEN-FOLLOWED-BY-A-COLON: \
https://profiles.segment.com/v1/spaces/INSERT-SPACE-ID/collections/users/profiles/email:alex@example.com/traits
{
"traits": {
"email": "alex@example.com",
"name": "Alex Anderson",
"recently_purchased_espresso_roast": true
},
"cursor": {
"url": "",
"has_more": false,
"next": "",
"limit": 10
}
}
Among the traits
for this customer, we see in the response that recently_purchased_espresso_roast
is true. This customer is part of the Audience we created (as we saw in the Audience Explorer above).
Note the -u
argument in our curl request. This value is formatted as username:password. Our access token is the username, and our password is blank. This means the value for the -u
flag must be the access token followed by a colon. Also, our Unify space ID makes up a part of our unique URL for calling the Profile API.
Write the Twilio Function
Now that we feel comfortable working with the Profile API, let’s write our Twilio Function. After logging into our Twilio account, we navigate to Twilio Functions and Assets. Then, we add a new function.
We will call our function customer_purchased_espresso
. Our function code is written with Node.js. It looks like this:
const axios = require('axios')
exports.handler = async (context, event, callback) => {
const profile = axios.create({
baseURL: `https://profiles.segment.com/v1/spaces/${context.SEGMENT_SPACE_ID}/collections/users/profiles`,
auth: {
username: `${context.SEGMENT_PROFILES_API_TOKEN}`,
password: '',
}
});
const response = new Twilio.Response();
response
.appendHeader('Access-Control-Allow-Origin', '*')
.appendHeader('Access-Control-Allow-Methods', 'OPTIONS, POST, GET')
.appendHeader('Access-Control-Allow-Headers', 'Content-Type')
try {
const result = await profile.get(`/email:${event.email}/traits`);
const in_audience = result.data.traits['recently_purchased_espresso_roast'];
const data = {
has_purchased_espresso: (typeof(in_audience) === 'boolean' ? in_audience : false)
};
response
.appendHeader('Content-Type', 'application/json')
.setStatusCode(200)
.setBody(data);
return callback(null, response);
} catch (error) {
response
.appendHeader('Content-Type', 'plain/text')
.setStatusCode(500)
.setBody(error.message)
return callback(null, response);
};
};
Let’s walk through what our function code will do.
Require the axios package, which we will use to send an HTTP request to the Profile API.
Configure axios with our base URL and authentication information. These settings will need our
SEGMENT_PROFILES_API_TOKEN
andSEGMENT_SPACE_ID
, both of which we will specify as environment variables (see below).Prepare the Twilio Response object that will be returned by our function. Because our Twilio Function will be called by Twilio Flex, we need to enable CORS between the two.
Call the Profile API, looking specifically at the
recently_purchased_espresso_roast
trait for the given customer.Return a data payload with our response, with
has_purchased_espresso
set to true or false depending on the customer’s trait value.
We save our function. However, before we can use it, we need to set up dependencies and environment variables.
Add axios as a dependency
Under the Settings for our Twilio Functions, we click Dependencies, making sure to add the axios package to our list.
Add API credentials as environment variables
Next, we need to set up our API credentials as environment variables. This is a safer practice than hardcoding the credentials into our function code. Under Settings, we click Environment Variables. We create two variables to correspond to our Profile API access token and our Unify space ID.
Deploy function and get URL
With our function saved, we click Deploy All.
After our function has been deployed, we get our function’s unique URL. This is the URL that our Twilio Flex plugin will call.
Call Twilio Function from Twilio Flex Plugin
We’re ready to connect our last piece of the puzzle: Twilio Flex. For this, we will build a Flex UI plugin that calls our Twilio Function. Here are some helpful resources for this step:
Our basic plugin will do the following:
Upon initialization, add a new section to the Task Information Panel. This is where we’ll display whether the customer has recently purchased the Espresso Roast product.
When a Flex agent selects a task, the plugin will get the email attribute in the task, which represents the customer’s email.
Update the Task Information Panel to show this email address for the customer.
Call our Twilio Function, passing the email value as a parameter. Update the Task Information Panel with the result of the call.
For our plugin, we need to write code for two files. First, we have src/RecentPurchase.js
, which simply houses the basic JSX for our additional section in the Task Information Panel. The code looks like this:
import React from 'react';
const RecentPurchase = () => (
<div id="has-purchased-espresso">
<span class="Twilio">
<hr />
<h1>Has purchased espresso roast in last 30 days?</h1>
<span class="value"></span>
</span>
</div>
);
export default RecentPurchase;
Then, we have the main code for our plugin, in src/CustomerAudienceLookupPlugin.js
:
import React from 'react';
import { VERSION } from '@twilio/flex-ui';
import { FlexPlugin } from '@twilio/flex-plugin';
import axios from 'axios'
import RecentPurchase from './RecentPurchase';
const PLUGIN_NAME = 'CustomerAudienceLookupPlugin';
const displayEmailAddress = (email) => {
document.querySelector('[data-test="customer-name-number"]').textContent = `Email: ${email}`
}
const displayPurchaseValue = (value) => {
document.querySelector('#has-purchased-espresso .value').textContent = value
}
const hasPurchasedEspresso = async (email) => {
try {
// MAKE SURE TO USE YOUR UNIQUE TWILIO FUNCTION URL BELOW
const url = 'https://demo-9864.twil.io/customer_purchased_espresso'
const response = await axios.get(`${url}?email=${email}`,
{
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
}
}
);
return response.data.has_purchased_espresso
} catch (ignore) {
return false
}
}
export default class CustomerAudienceLookupPlugin extends FlexPlugin {
constructor() {
super(PLUGIN_NAME);
}
async init(flex, manager) {
flex.TaskInfoPanel.Content.add(<RecentPurchase key="espresso"/>);
flex.Actions.addListener('afterSelectTask', async (payload) => {
const email = payload.task.attributes.email;
displayPurchaseValue('')
displayEmailAddress(email)
displayPurchaseValue(await hasPurchasedEspresso(email) ? 'YES' : 'NO')
})
}
}
The plugin’s implementation is straightforward. Let’s walk through the init
function.
Add the
RecentPurchase
component to the Task Information Panel.Add a listener for the SelectTask action. We want to trigger code after that occurs, so we add an event listener to afterSelectTask.
Within the triggered code, retrieve the email that is part of a task’s attributes.
Clear the text displayed for whether a customer has purchased the product in question.
Update the Task Information Panel to display the email address for the customer.
Call
hasPurchasedEspresso(email)
, which is our subfunction that calls our Twilio Function. Update theRecentPurchase
component based on the function result.
On our local machine, we run twilio flex:plugins:build
to build our plugin. Then, we run twilio flex:plugins:start
to start up a local instance of Twilio Flex that includes our plugin.
In our main Twilio Flex instance, we have created four tasks (one for each of our customers). Our local development instance of Flex taps into this cloud data. As we click on each of these tasks, we see our plugin in action by looking at the Task Information Panel. The email address of the customer is updated, and we also see YES or NO to indicate whether this customer has purchased the Espresso Roast product in the last 30 days.
Summary and Next Steps
Congratulations! As you’ve followed along in this recipe, you’ve learned how to connect several different technologies within the Twilio ecosystem—Twilio Segment with Engage, Twilio Functions, and Twilio Flex. By building integrations that piece these tools together, you can provide rich and personalized customer experiences and build deeper customer connections. Consider the possibilities…
With Segment tracking customer behaviors and actions on your website, you can build smarter call routing. When they call into your support center, you no longer need to provide them with an overwhelming menu of options. Instead, your contact center could access that Engage data and say, “We noticed you’ve been searching for information about obtaining a refund. Is that why you’re calling?”
By leveraging Engage to automatically pull up data on products related to a specific customer (whether recently purchased or recently viewed), Twilio Flex can provide quick-pick options for support agents to reduce the time they would need to spend on wrap-up documentation.
Going in the other direction, Twilio Flex can wrap up a customer interaction by sending a transcript to Segment as a data source. Data from that interaction can be used to sift customers into Engage Audiences or move them along in a Customer Journey.
As you can see, you have endless possibilities for what you can build to take advantage of the entire Twilio ecosystem!
Getting started is easy
Start connecting your data with Segment.