Leveraging Twilio Engage Customer Data within Twilio Flex

When your support agents are interacting with customers, you want to set them up for success, providing all of the information and context they might need to create a genuine connection with the customer and provide a personalized experience. In this article, we’ll walk through the steps for seamlessly providing Twilio Flex support agents with data about customer traits from Twilio Engage.

Alvin Lee Made by Alvin Lee

What do you need?

  • Twilio Flex

  • Twilio Engage

Easily personalize customer experiences with first-party data

With a huge integration catalog and plenty of no-code features, Segment provides easy-to-maintain capability to your teams with minimal engineering effort. Great data doesn't have to be hard work!

On this page

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:

  • 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.

     

sf1

 

  • Twilio account (sign up here for free)

 

sf2
 
  • 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.

 

sf3

 

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.

 

sf4

 

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.

 

sf5

 

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.”

 

sf6

 

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.

 

sf7

 

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.

 

sf8

 

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.

 

sf9

 

As we set up our criteria, we can preview which customers would presently be a part of this Audience.

 

sf10

 

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.

 

sf11

 

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.

 

sf12

 

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.

 

sf13

 

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.

 

sf14

 

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.

 

sf15

 

In the API access tab, we click Generate token and provide a description for our token.

 

sf16

 

After generating our token, we make sure to copy the value. We’ll use it soon.

 

sf17

 

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.

 

sf18

 

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.

 

sf19

 

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.

  1. Require the axios package, which we will use to send an HTTP request to the Profile API.

  2. Configure axios with our base URL and authentication information. These settings will need our SEGMENT_PROFILES_API_TOKEN and SEGMENT_SPACE_ID, both of which we will specify as environment variables (see below).

  3. 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.

  4. Call the Profile API, looking specifically at the recently_purchased_espresso_roast trait for the given customer.

  5. 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.

 

sf20

 

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.

 

sf22

 

After our function has been deployed, we get our function’s unique URL. This is the URL that our Twilio Flex plugin will call.

 

sf23

 

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:

  1. 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.

  2. When a Flex agent selects a task, the plugin will get the email attribute in the task, which represents the customer’s email.

  3. Update the Task Information Panel to show this email address for the customer.

  4. 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.

  1. Add the RecentPurchase component to the Task Information Panel.

  2. Add a listener for the SelectTask action. We want to trigger code after that occurs, so we add an event listener to afterSelectTask.

  3. Within the triggered code, retrieve the email that is part of a task’s attributes.

  4. Clear the text displayed for whether a customer has purchased the product in question.

  5. Update the Task Information Panel to display the email address for the customer.

  6. Call hasPurchasedEspresso(email), which is our subfunction that calls our Twilio Function. Update the RecentPurchase 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.

 

sf24

 

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.