This article was originally posted on the Telestax blog as “How I Became a Rockstar Thanks to Telestax and Voxbone Part 2”. Part 1 of this series which introduces the Smart Dispatch application is available here.

Assuming you’ve read part 1, you now know what Smart Dispatch is and what is it for. So let’s dive into the code! Below, I’ve created a simple diagram that explains how the app works.

diagram

Workflow:

  1. User lands on webpage and authenticates using LinkedIn
  2. Webpage launches LinkedIn authentication and retrieves the user info to store in context variable
  3. Webpage uses location info from user to query Agent API based on user location
  4. SIP call to Restcomm instance with context header passed
  5. Restcomm directs call to Agent’s SIP client, records call, and sends information gathered to agent on hangup

Here is how the different parts are built:

1. Setting up the Dashboard & API

The dashboard serves as a way for the user to configure his agents with relevant information. It also acts as an API for the WebRTC Call client to consult to know which agent it should call based on the contextual information. I set up the dashboard and API using NodeJS. Just a few routes are needed:

A. Create user

This route is essentially to create the agent based on the appropriate data format.
/* POST to Add User Service */
router.post('/adduser', function(req, res) {

    // Set our internal DB variable
    var db = req.db;

    // Get our form values. These rely on the "name" attributes
    var userFirstName = req.body.firstname;
    var userLastName = req.body.lastname;
    var userSegment = req.body.segment;
    var userPhone = req.body.number;
    var userDid = req.body.did;
    var userEmail = req.body.email;


    // Set our collection
    var collection = db.get('usercollection');

    // Submit to the DB
    collection.insert({
        "firstname" : userFirstName,
        "lastname" : userLastName,
        "segment" : userSegment,
        "number" : userPhone,
        "did" : userDid,
        "email" : userEmail


    }, function (err, doc) {
        if (err) {
            // If it failed, return error
            res.send("There was a problem adding the information to the database.");
        }
        else {
            // If it worked, set the header so the address bar doesn't still say /adduser
            res.location("userlist");
            // And forward to success page
            res.redirect("/dashboard");
        }
    });
});

B. Display user (JSON API)

This route essentially accepts a URL-encoded parameter (segment) and searches the database based on the segment passed.
router.get('/userlist:location', function(req, res) {
    var db = req.db;
    var urlParts = url.parse(req.url, true, true);
    var pathname = urlParts.pathname;
    var location = pathname.slice(10);
    console.log(segment);
    var collection = db.get('usercollection');
    collection.findOne({location: location},function(e,docs){
        res.send({
            "userlist" : docs
        });
    });
});
For instance, the WebRTC Call Client will send http://where-the-api-is-hosted.com/userlist:be and will receive the information returned from the agent database/API for the first available Belgian agent. Example:
{"userlist":{"_id":"552a70de61817d46c06b162d","firstname":"Agent","lastname":"Man","location":"be","number":"32479810399","did":"+883510080047","email":"agent.man@gmail.com"}}

C. Other routes

You can also include other routes such as displaying the /dashboard, remove users, modifying users, etc. My dashboard looks like:
dashboard (1)

2. Setting up the WebRTC Call Client

Again, I used NodeJS and here only a few routes and functions are needed:

A. Authenticate with Linkedin, I use passport for that (more info here)

Don’t forget to set the appropriate permissions in order to access all the profile info you will need. I used:

scope: ['r_emailaddress', 'r_basicprofile', 'r_contactinfo’],
profileFields: ['id', 'first-name', 'last-name', 'email-address', 'headline', 'phone-numbers', 'location', 'positions']

Then you can set all your context variables to the profile info like so:

var showprofile = profile,
    displayName = profile.name.givenName + ' ' + profile.name.familyName,
    phoneNumber = profile._json.phoneNumbers.values[0].phoneNumber,
    location = profile._json.location.country.code,
    email = profile._json.emailAddress,
    position = profile._json.positions.values[0].title,
    company = profile._json.positions.values[0].company.name;

B. Set up the getData() function called when authentication is done:

function  getData(location){
        request("http://where-your-api-is-hosted.com/userlist:"+location, function(error, response, body) {
        body = JSON.parse(body);
        var did = body.userlist.did;
        var agentNumber = body.userlist.number;
        var agentEmail = body.userlist.email;
      });
};
This function sets your context information (agent phone number, DID to call through the WebRTC SDK, and agent email to send the summary to) by passing the location detected from the authenticated LinkedIn user

C. Set up the Voxbone WebRTC-SIP SDK to call

Here’s where you can download the Voxbone WebRTC-SIP SDK which will link the browser to the Restcomm instance’s IP.
In your init() function, you can now pass all the data taken from LinkedIn and the userlist API to build a context variable:
 var context = {'clientName': userName, 'clientPhone': userPhone, 'agentNum': agentNum, 'userEmailAddress': userEmailAddress, 'userPos': userPos, 'userCo': userCo, 'userLoc': userLoc, 'pageurl': pageurl, 'agentEmailAddress': agentEmailAddress}
You can then set all parameters of the SIP call that are passed to Restcomm:
//Caller ID
 voxbone.WebRTC.configuration.uri =  userPhone + "@voxbone.com";
 
//Display Name
 voxbone.WebRTC.configuration.display_name = userName;
 
//Context info
voxbone.WebRTC.context = JSON.stringify(context);
 
//And finally call the right agent’s SIP URI
 
voxbone.WebRTC.call(agentNum);

3. Setting up Restcomm

Now that you can send a call with context using a Voxbone phone number to a SIP URI, just link the phone number to your Restcomm’s instance URI (How to configure SIP URI with Voxbone). Here’s what my Restcomm App look like:

restcommapp
Module 1 receives the call echoes the context header to a REST service (see 3a.) then assigns all context variables to Restcomm variables, sends the call to the SIP client of the agent. On hang up, the flow is transfered to Module 2 where you can hook up any service you want to send the emails and SMS .
You make the magic, so play around with Restcomm.

3a. Setting up a context parser

At the time of this write-up Restcomm was not able to parse the JSON of the context object sent in the SIP call into multiple variables. Therefore, I set up an additional REST service that receives the context object from Restcomm (using their Hook URL) and echoes the content of the object into different variable for easy parsing. Hopefully Restcomm will integrate this feature soon!

Code available on the Voxbone Github page.
Restcomm App Available here.