In a field where you have to respond to messages from your customers, you would want to remove answered chats from your inbox or maybe add a sign to indicate that you have responded to this customer. Doing so helps you stay organized and prioritized. TalkJS allows you to add custom data to every message. This custom data can help filter conversations in your inbox.
This article aims to teach you how to automatically mark a conversation as “answered" and filter out answered conversations from your inbox or indicate with a label if it is answered. A good use case for this is in the field of customer service, where customers can create support tickets regarding any issues they might have or inquiries they might want to make about your product. Support wants to know which messages they have answered to stay prioritized.
Pre-requisites
To follow along, you need:
- A free TalkJS account.
- Familiarity with JavaScript
- Any code editor of your choice
Creating a conversation
Let’s add TalkJS to our application and start a conversation between a Support staff and two customers. Smith and John are customers chatting with Lynda, a support staff. Smith has a payment issue to resolve, while John wants to inquire about a product.
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Auto mark conversation as read</title>
</head>
<body>
<script>
(function(t,a,l,k,j,s){
s=a.createElement('script');s.async=1;s.src="https://cdn.talkjs.com/talk.js";a.head.appendChild(s)
;k=t.Promise;t.Talk={v:3,ready:{then:function(f){if(k)return new k(function(r,e){l.push([f,r,e])});l
.push([f])},catch:function(){return k&&new k()},c:l}};})(window,document,[]);
</script>
<div id="talkjs-container" style="width: 90%; margin: 30px; height: 500px">
<i>Loading chat...</i>
</div>
</body>
</html>
Let’s initialize TalkJS inside a JavaScript file.
Talk.ready.then(function() {
const support = new Talk.User({
id: '123456',
name: 'Lynda from Support',
email: 'lynda@test.app',
photoUrl: 'https://talkjs.com/images/avatar-1.jpg',
welcomeMessage: 'Hi! I am Lynda from support, how may I be of help!',
role: 'support'
});
window.talkSession = new Talk.Session({
appId: 'YOUR_APP_ID',
me: support,
});
const customer1 = new Talk.User({
id: '654321',
name: 'Smith',
email: 'smith@example.com',
photoUrl: 'https://talkjs.com/images/avatar-5.jpg',
welcomeMessage: 'Hey, I have some troubles with...',
role: 'customer'
});
const customer2 = new Talk.User({
id: '1000001',
name: 'John',
email: 'john@example.com',
photoUrl: 'https://talkjs.com/images/avatar-4.jpg',
welcomeMessage: 'Hey, I want to make an inquiry...',
role: 'customer'
});
Replace YOUR_APP_ID
with the App ID on your TalkJS dashboard. We added the customer and support roles we shall create in our dashboard shortly. The role attribute will help us determine whether a message is from support or a customer.
Creating a custom role and theme
Go to your TalkJS dashboard and create the two roles we assigned above.
At some point, we would want to display a label in the conversation list indicating whether a conversation is answered. To do this, we need to create a custom theme because we don’t want to modify the default theme.
Let’s create a custom theme and set our roles to use it. We will give it the name custom.
Set the customer and support roles to use the created custom theme.
Starting a conversation between support and customers
Let’s start a chat between our imaginary support staff, Lynda and Smith. And another chat between Lynda and John.
const conversation = talkSession.getOrCreateConversation(
Talk.oneOnOneId(support, customer1)
);
conversation.setAttributes({
subject: "Payment Issues"
})
conversation.setParticipant(support);
conversation.setParticipant(customer1);
const otherConversation = talkSession.getOrCreateConversation(Talk.oneOnOneId(support, customer2));
otherConversation.setAttributes({ subject: "Inquiry"});
otherConversation.setParticipant(support);
otherConversation.setParticipant(customer2);
The subject of the conversation between Lynda (support) and Smith (customer1) is “Payment Issues” while John (customer2) wants to make an “Inquiry.”
Create an inbox for the conversation between Lynda and Smith.
const inbox = talkSession.createInbox({ selected: conversation});
inbox.mount(document.getElementById('talkjs-container'));
Run your program! You should see something like this.
To display the conversation between Lynd and John, replace:
const inbox = talkSession.createInbox({ selected: conversation});
With
const inbox = talkSession.createInbox({ selected: otherConversation});
Now you have a conversation with John set up.
Listening to messages via webhooks
To know whether a message is from a customer or a support staff, we need to listen to it via the TalkJS webhooks. Integrate ngrok to test the webhooks locally. ngrok enables you to expose your local development server to the internet. Follow this guide to set up ngrok on your local machine.
Let’s spin up an Express.js server to use webhooks.
mkdir chat-backend
cd chat-backend
npm install express axios
We need axios to make API calls.
Create an index.js file inside your Express project and add the following code
const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);
app.use(express.json())
app.post('/talkjs', (req, res) => {
console.log(req.body)
res.status(200).send('OK')
});
server.listen(8080, () => {
console.log('listening on *:8080');
});
“/talkjs” is the route that will receive the webhooks request. Go ahead and run ngrok on your machine.
Go to your TalkJS dashboard, and add the forwarding address from ngrok as your webhook URL. Don’t forget to add the “/talkjs” suffix. You should also enable message.sent as that is the only hook we need.
Now, we can receive sent messages in our backend via the webhook. Let’s test it out!
Lynda (support) sends John (customer2) a message.
If you navigate to the ngrok address at localhost:4040
you will get the message object.
You can also see this message object in the console of your server running on port 8080 (or whatever port you specified). We will update the message data from the backend via TalkJS REST API
Updating a conversation via REST API
Whenever the backend receives the message object, we want to update it to include custom data. Ensure to do this on the backend so as not to expose your application’s secret token - that would be a big security risk.
If the sender is a customer, we want to add a custom property {answered: “false”}
to the conversation (custom property can also have string values hence the boolean in a string). But if the sender is Lynda, the support staff, we want to add a custom property {answered: “true”}
.
const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);
const axios = require("axios");
require('dotenv').config()
app.use(express.json())
const token = process.env.SECRET_TOKEN
const appId = process.env.APP_ID
async function UpdateConversationforSupport(conversationId){
const supportData= {
custom: {
answered: "true"
}
}
const config = {
headers : {
Authorization: `Bearer ${token}`
}
}
axios.put(
`https://api.talkjs.com/v1/${appId}/conversation/${conversationId}`,
supportData,
config
)
}
async function UpdateConversationforCustomer(conversationId){
const customerData= {
custom: {
answered: "false"
}
}
const config = {
headers : {
Authorization: `Bearer ${token}`
}
}
axios.put(
`https://api.talkjs.com/v1/${appId}/conversation/${conversationId}`,
customerData,
config
)
}
app.post('/talkjs', (req, res) => {
console.log(req.body)
res.status(200).send('OK')
const {role} = req.body.data.sender
const {conversationId} = req.body.data.message
if(role == "support"){
UpdateConversationforSupport(conversationId)
}else{
UpdateConversationforCustomer(conversationId)
}
});
server.listen(8080, () => {
console.log('listening on *:8080');
});
Ensure to put your application’s secret key and token inside a .env
file.
A custom data will be added to every message based on the sender's role. Let’s try it out.
Lynda sends another chat to John
If you go to our TalkJS dashboard, click on Activity, scroll down, and select the conversation.
You can see that the custom data was added to the conversation.
Filtering Inbox based custom data
As a support staff, you’d want to stay organized. You want every answered conversation to be automatically filtered out of your inbox so that you can easily prioritize the unanswered conversations.
To demonstrate the TalkJS FeedFilter
method for filtering our inbox, Smith and John (our customers) will each send Lynda a message.
You can go to another page of your application, set it up and send a message as John and another as Smith.
To display both conversations in your inbox, replace:
const inbox = talkSession.createInbox({ selected: otherConversation});
With
const inbox = talkSession.createInbox();
Now, we can see the messages from Smith and John.
Let’s make Lynda reply to John but not Smith.
We now have one answered conversation and one unanswered conversation. Let’s use the FeedFilter
method to remove the answered conversation from the inbox.
inbox.setFeedFilter({ custom: { answered: ["==", "false"] } })
Any conversation with custom property {answered: “true”}
is removed from your inbox.
The conversation with John has been filtered out of the list because it is answered.
Adding a label to answered conversation
Alternatively, you may want to add a label to every answered conversation instead of filtering it out of your inbox. Let’s add “✔✔” to every answered conversation.
To do this, we need to go inside our TalkJS dashboard to edit the ConversationListItem
subcomponent of our custom
theme.
We have access to the custom data inside the ConversationListItem
subcomponent. Let’s use it to display the “✔✔” label on answered conversations.
Scroll down to line 62. The next line after the following code
<span class="timestamp"><TimeAgo timestamp="{{lastMessage.timestamp}}"/></span>
Add
<span t:if="{{conversation.custom.answered == 'true'}}">✔✔ </span>
The above code adds “✔✔” to every answered conversation.
To see the effect, remove the FeedFilter to display all conversations inside the inbox.
Remove (or comment out)
inbox.setFeedFilter({ custom: { answered: ["==", "false"] } })
Now we have the double check mark beside John’s conversation (because it is answered).
The check mark seems too close to the timestamp. Let's add some padding to it.
Scroll down to the styling, locate the .timestamp
class and add a padding-right property.
.timestamp {
padding-right: 10px;
}
Take a look!
Summary
TalkJS lets you listen to incoming messages via its webhooks. You can also add custom data to conversations. This custom data can be useful for conditionally filtering out conversations from your inbox using the FeedFilter method.
Automatically marking a conversation as answered can be helpful in customer service. Support staff stays organized and prioritized while serving their customers.
Top comments (0)