# Selectable Chat Messages (Flex UI 1.x.x)

> \[!NOTE]
>
> This guide is only for Flex UI 1.x.x, which [reached End of Life on June 30, 2024](/docs/flex/flex-ui-eol-reference). To build on a current version, we recommend you [upgrade to Flex UI 2.x.x](/docs/flex/developer/ui/migration-guide).

## Overview

> \[!WARNING]
>
> This solution features sample code that is provided "as is" and is not production grade. The featured code does not account for edge case handling, scalability, and reliability. It is not covered under Twilio's [Service Level Agreement (SLA)](https://www.twilio.com/en-us/legal/service-level-agreement) and [support plans](https://www.twilio.com/en-us/support-plans).

This solution provides the ability to have selectable messages with Web Chat in Flex. The goal behind this is to build a scripted experience to guide the customer through a "self-service" type of chat flow. The solution can be expanded into more robust self-service use cases for Web Chat.

![User selects and copies text from chat messages.](https://docs-resources.prod.twilio.com/b055fd42922985bf61e013a9cc35566cb3ac0a48daf74d44b892ad0db2cd8b11.gif)

## How It Works

Studio Flow passes attributes of the chat channel to a function, that we subscribe to from the web. Any time the attributes change, the `clickablemessage` object is pulled and then pushed this into a redux store. The buttons are then rendered based on what is contained within the object. As the customer progresses through the Studio Flow, it pushes the next set of scripted answers as clickable buttons on their end, thus providing a guided experience through the Studio Flow.

## Architecture

![Flowchart of customer interaction through web chat, chatbot, TaskRouter, and Flex to agents.](https://docs-resources.prod.twilio.com/00b47cd3cb6980cf2bc68afdfc79682ab38f438a4a619a9b44074bf220518763.png)

## Prerequisites

To deploy this solution, you will need:

* An active Twilio account. [Sign up](https://www.twilio.com/try-twilio) if you don't already have one
* npm version 6.0.0 installed (type `npm -v` in your terminal to check)
* A Node.js [long-term-support (LTS) version](https://nodejs.org/en/about/releases/) installed, 14 recommended (type `node -v` in your terminal to check)
* A Twilio Flex instance where you have admin permissions. See our [getting started guide](/docs/flex/admin-guide/setup/account-creation) to create one
* [Twilio CLI](/docs/twilio-cli/quickstart#install-the-twilio-cli) along with [Serverless Plugin](/docs/twilio-cli/plugins#available-plugins). Run the following in a command shell:

  ```bash
  # Install the Twilio CLI
  npm install twilio-cli@2.0 -g
  # Install the Serverless as Plugin
  twilio plugins:install @twilio-labs/plugin-serverless
  ```

> \[!NOTE]
>
> If you're running Linux, click on the Linux tab for the [Twilio CLI installation instructions](/docs/twilio-cli/quickstart#install-the-twilio-cli). If you're running Windows, make sure to run the Windows command prompt as an administrator to install the Serverles/Flex plugins for the Twilio CLI. The Windows commands in this guide use PowerShell (for Node.js/npm installation).

## Deployment Time

30-45 minutes

## Version Compatibility

Flex UI 1.29.0

## Configure your Flex Workspace

In order to use the solution, you need to prepare your **Flex Task Assignment** workspace.

### Retrieve your Flex settings

#### Step 1

Navigate to your Flex project in the [Twilio Console](https://www.twilio.com/console). Copy your **ACCOUNT SID** and **AUTH TOKEN**, and create a new Twilio CLI profile using those credentials:

```bash
twilio profiles:create
```

You will be prompted to enter your Twilio Account SID, Auth Token, and a shorthand identifier for your profile. When choosing a shorthand identifier, pick one that is meaningful and that you can remember. Once your profile has been created, activate it by running:

```bash
twilio profiles:use PROFILE_ID
```

Keep in mind that this account will be used for the rest of the deployment. In order to switch accounts, use the following command:

```bash
twilio profiles:use DIFFERENT_PROFILE_ID
```

### Step 2

Retrieve your Flex Task Assignment workspace SID:

```bash
twilio api:taskrouter:v1:workspaces:list
```

**Example Workspace SID**

```bash
SID                                      Friendly Name               Prioritize Queue Order
WSXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX       Flex Task Assignment        FIFO

```

## **Build the Flex Selectable Chat Messages Source Code**

Make sure you have Node.js ([https://nodejs.org](https://nodejs.org)) as well as npm ([https://npmjs.com](https://npmjs.com)) installed.

**Step 1:** In your browser, download the [source code](https://github.com/twilio-professional-services/flex-selectable-chat-messages) and extract the files in a local directory.

**Step 2:** Run npm install to install the plugin package dependencies.

## **Deploy your Twilio Function**

**Step 1:** From the root directory of your copy of the source code, change into `serverless` and rename `.env.example` to `.env`.

## MacOS/Linux

```bash
cd serverless && mv .env.example .env
```

## Windows

```bash
C:\Users\xxxxxx\flex-selectable-chat-messages> cd serverless && move .env.example .env
```

**Output**

```bash
1 file(s) moved.
```

**Step 2:** Open .env with your text editor and modify the following:

```bash
ACCOUNT_SID = Found at https://www.twilio.com/console
AUTH_TOKEN = Found at https://www.twilio.com/console
TWILIO_WORKSPACE_SID = WSXXXXXXXXXXXXXXXXXX
```

**Step 3:** Run the following to install the Function dependencies in serverless directory:

```bash
serverless $ npm install
```

**Step 4:** Deploy the Twilio function to your account using the Twilio CLI:

```bash
twilio serverless:deploy
```

**Step 5:** Copy the domain as you'll need this for the .env as you'll use this when you import the studio flow

**Step 6:** Import the Studio Flow located within /serverless/studio\_flow to [https://www.twilio.com/console/studio/dashboard](https://www.twilio.com/console/studio/dashboard).

Here is how to import a json within the console:

![User clicks to create a new flow in Twilio Studio's flow management interface.](https://docs-resources.prod.twilio.com/6e30a1a1c2e49e539fc7cea320b3096214a4c01a1a9d8369cbd14b42ed0b9697.gif)

**Step 7:** Update the Send-To-Flex widget with your Flex details:

* Workflow: Select preferred Workflow
* Channel: Programmable Chat
* Sample attributes for the required attributes field:

  ```bash
  {"name": "{{trigger.message.ChannelAttributes.from}}",
  "channelType": "{{trigger.message.ChannelAttributes.channel_type}}",
  "channelSid": "{{trigger.message.ChannelSid}}"}
  ```

**Step 8:** From the root directory of your copy of the source code, change into /public/assets and rename `webchat-appConfig.example.js` to `webchat-appConfig.js`

**Step 9:** In webchat-appConfig.js, change your Account SID and Flex Flow SID:

```bash
accountSID: "ACXXXXXXXXXXXXX"
FlexFlowSID: "FOXXXXXXXXXXXXXX"
```

Flex Flow corresponds to [the messaging](https://console.twilio.com/us1/develop/flex/channels/messaging) web flow which you will need to edit to point to your imported Studio Flow:

![Dialog box for updating Flex Flow with options for friendly name, integration type, and channel janitor.](https://docs-resources.prod.twilio.com/6a0e2122f6877ad0d021eade6d1d7de168f8981b667aaf99498e06bdb8e02e40.png)

## Develop Locally

To develop locally, you can use the Webpack Dev Server by running:

```bash
flex-selectable-chat-messages $ npm start
```

This starts up the Webpack Dev Server and open the browser for you. Your app runs on `http://localhost:3000`. If you want to change that you can do this by setting the *PORT* environment variable.

When you make changes to your code, the browser window refreshes.

## **Deploy the solution**

When you are ready to deploy your web chat widget, you'll need to run build:

```bash
flex-selectable-chat-messages $ npm run-script build
```

## **Test the Solution**

After you have uploaded your Web Chat build and deployed it to your website start a new chat from the web page.

This will trigger a new chat interaction that will flow through the previously published Studio Flow, pushing selectable chat messages as they are updated within the Studio Flow.

## **Appendix: Ways to Expand the Solution**

If you examine the Studio Flow widgets, you'll see how we continually update the `clickablemessage` object within the widgets. As these change, we are subscribing to these changes within our web chat widget from the front end. Any time those change, we push those changes to redux and render the "clickable" messages within the web chat widget front end.

### Example

#### The Studio Flow

![Twilio Studio flow showing validate\_name\_SM function with parameters for serviceSID and chatChannel.](https://docs-resources.prod.twilio.com/9bb623cf3fecbd9b43e57944dd3be1ef213a4847ad3db050ba486b145ea413c4.png)

#### The Object

```json
{
  "clickableMessages": [
    { "key": "yes{{flow.variables.count}}", "message": "yes" },
    { "key": "no{{flow.variables.count}}", "message": "no" }
  ]
}
```

#### The Web Chat Widget Code

We are going to get the channel, then add a channel listener (to subscribe to) anytime there are updates to the attributes of the channel. From there we will push the updated `clickableMessages` object into redux and that is how we are rendering button/component changes as the studio flow push new objects throughout the flow.

```bash
getChannelAttributes() {
   const dispatch = this.props.dispatch;

   FlexWebChat.manager.chatClient.getChannelBySid(this.props.channelSid)
   .then(channel => {
     channel.on('updated', ({ channel, updateReasons }) => {
       if ( updateReasons.indexOf('attributes') !== -1 &&channel.attributes.status === "INACTIVE") {
         FlexWebChat.Actions.invokeAction('RestartEngagement');
         return;
       }
       if (undefined !== channel.attributes.clickableMessages && (updateReasons.indexOf('attributes') !== -1)) {
         dispatch({
           type: 'SET_CLICKABLE_MESSAGES',
           payload: {
             clickableMessages: channel.attributes.clickableMessages
           }
         })
       }
     });
   })
 }
}
```
