Building A Salesforce Powered Call Center with Twilio TaskRouter

ThinkVoice gives businesses the communications tools they need to create exceptional customer experiences. ThinkVoice CEO Brian Coyle knows that something as simple and powerful as making a phone ring can be difficult to do at a large scale. That’s where ThinkVoice comes in. To ensure they’re giving their customers reliable and scalable communication solutions, ThinkVoice uses Twilio.

After the launch of Twilio’s TaskRouter, ThinkVoice added a new tool to their tool belt that enables them to manage traditionally difficult aspects of call center data like agent state, queue information, and more.

In the following post, Bryan Coyle shows how to build a Salesforce powered call center with Twilio’s TaskRouter. Read the original blog post here.

Building A Salesforce Powered Call Center

This is a beginner’s guide to implementing an omnichannel call center directly into your Salesforce CRM using Salesforce Open CTI, Twilio TaskRouter and Twilio client.  The source code for the solution is available here. The tutorial is aimed at developers looking to build a call center within Salesforce or just looking to learn more about TaskRouter.  If you just want to check out the end product you can deploy it to Heroku straight away.  If you aren’t a developer but want to learn more give us a shout and we can give you a demo.

If you want to bring phone calls into your Salesforce CRM you are, in the best case scenario, integrating a stand alone cloud based call center product with prebuilt connectors, or at worst integrating an on premise legacy PBX through multiple layers of integration.  In either case you are managing your call center across multiple systems leaving you with a management headache that is extremely costly and error prone.  The following tutorial aims to solve this headache by reducing dependence on third party solutions and leaving as much configuration in Salesforce as possible.


The demo demonstrates the ability to handle multiple channels of communication using Twilio TaskRouter to manage a single queue of communications coming from different channels.  This has been a real struggle as point solutions are only able to handle one or two communication channels and few support SMS as a channel.

Brief Overview the Technologies Used

The tutorial is built on the fantastic demo of a Salesforce embeddable ACD using Twilio Client by Charles Oppenheimer of Twilio.  Many thanks to Charles for sharing that demo.  We have simply taken that demo and inserted TaskRouter to handle the distribution of calls and addition of text messages.

  • Salesforce Open CTI –Salesforce Open CTI is an open API to allow third party CTI vendors to connect telephony channels into the Salesforce CRM interface.  In our demo we use Open CTI to house our soft phone and drive the click to dial/text functionality.  The demo requires no plugins or installed software thanks to the design of Open CTI. For more info see the developer guide.
  • Twilio ClientTwilio Client is a WebRTC interface to Twilio.  In our demo we are using the javascript library which gives us an API and connection to Twilio to receive the call within our Salesforce browser delivering the call via WebRTC.  Twilio client also gives us the ability to control the call via our soft phone.
  • Twilio TaskRouter TaskRouter is the queue and state machine that we have our Salesforce users connect to through the Open CTI soft phone.  We route all of our calls and texts through TaskRouter which manages the queueing of those  communications.  TaskRouter also monitors the state of our Salesforce users sending them the calls and texts as they become available.  What differentiates TaskRouter from traditional cloud or on premise phone systems is it’s completely API driven so we can place all administrative functions within Salesforce.

Getting Started – Part 1 – Phone Calls

First I highly recommend going through the original client-acd project from Charles as he covers all the basic setup including Twilio setup.  Our README covers the additional setup steps of configuring the necessary TaskRouter components.  At a high level we have replaced any code that was managing agent state or call queueing with TaskRouter code including removing all the Mongo DB code.  Mind the twilio-gem version.  The TaskRouter stuff is in after 3.15.  The rest of the post is going to cover the implementation of TaskRouter.

 Call Routing With TaskRouter

Lets start with routing incoming calls to TaskRouter.  In our Sinatra app we are going to change the /voice action to send the call into our workflow via Twiml.  This will immediately route our incoming call into the queue that is now managed by TaskRouter and the workflow we defined.  With that we now have a call in queue waiting for agent.  Very simple!

Lets now hook up the agent state.

Salesforce Agent State Handling

Thanks to the work done in the original project it was really easy to plug the agent into TaskRouter.  As the softphone loads up within the Salesforce browser the softphone.js code was already pulling the agent id from the Salesforce API and registering as a Twilio Client.  Once we have a Twilio Client established we then go to register the agent with TasksRouter.  Much like registering a Twilio Client we need to get a token from the server with the proper permissions. In our code we pass the Salesforce user id in an ajax call so we can use that to match to the correct worker defined with TaskRouter.

On the server we use the Twilio REST API to create a client to TaskRouter. With the REST API we can loop through all the workers that are defined for our Workspace, find the worker that corresponds to our salesforce agent and generate a token for that worker. We return that token back to the client side where our javascript function instantiates a worker via the worker.js library.

Worker.js is the javascript SDK that gives us the ability to receive work from the queue and gives us the ability to manage agent state. In this example we register for the activity.update callback which will let our client know anytime this agent changes state and when it does we update the UI. Worker.js also allows us to retrieve a list of activities or states that an agent can be set to. Each activity (or state) is either Available or Unavailable meaning they can take work or not. In this demo we assume one activity is available and will store the sid of one Available activity and one Unavailable activity. We use these sids to set the agent state later.

So we now have a call in queue, and a salesforce agent able to register to the queue and manage their state. Lets see how work gets distributed to our agent.

Routing Calls to the Salesforce Agent

Back when we setup our inbound call handling in client-acd.rb /voice we simply redirected the call to the TaskRouter Workflow with Twiml. Because we did this there is a little magic baked into TaskRouter we can take advantage of. First lets understand how TaskRouter routes work. The call came into Twilio and was directed to a workflow. The workflow is aware of workers (agents) who have attributes that the workflow can use to determine who should take that work. In this demo the workflow is acting as a simple queue knowing who has been idle for the longest. When we log into salesforce and click the Ready button Worker.js tells TaskRouter that our worker/agent is available. TaskRouter assigns the activity (the call in this case) to the agent. The workflow is configured to POST that assignment to our Sinatra app at /assignment. When the app receives that POST we simply tell TaskRouter to dequeue the call to the agent’s Twilio Client ID which is configured on the worker’s attribute {contact_uri”: client:salesforce_login_id”}…magic!

Wrapping Up

TaskRouter has really simplified our code as we don’t need to manage agent state. We still keep a websocket connection and polling to push real time stats up to our soft phone giving our agent the number of logged in agents and number of items in the queue. We use the TaskRouter REST API to get that info.

In the next part of this demo we will add text message routing to our Salesforce Call Center. Stay tuned.

Learn more about ThinkVoice here

  • Jessica Olivia

    This sounds to be a very beneficial tool as it will help to reduce call time and agents effort to solve the query.the greatest advantage of using this tool is CSS scores will improve and this will help in growth of our business. I work with go4customer and we will definitely implement it in our call center.

  • boopathy

    We are trying to build a similar integration with PegaCRM and would like to discuss more on this,

    • Maverick Maniac

      Why are you building on Pega? It is no longer even a choice of call centers.

  • John Tailor

    Does this work with the new Lighting UI?

  • Nick Orlov

    Too hard for me :(