Click To Call Example For Twilio

Uncategorized

Twilio is a local company that has developed some very spiffy telephony technology that takes 99% of the pain out of integrating telephone calling capabilities into your application.

I’ve previously demoed some easy examples of getting your feet wet with the Twilio API. In this post I’ll take on a more challenging example: implementing a web-based click-to-call function.

What is click-to-call (aka C2C)? This is a feature that lets your customer flag you and say (for example) “Hey, I’m interested in talking to somebody about this product I’m looking at. Here’s my phone number; have a specialist call me as soon as one becomes available.”

This is a big win for the customer because they don’t have to wait on hold; it’s a big win for you, the application vendor, because you get a happier, less stressed out customer. Also, as we will see, you can use the magic of server-side programming to send important information to your agents, prepping them for the call. You can even route calls to the most knowledgeable agents based on which web page(s) your customer is viewing when they initiate the request!

Here’s a diagram that shows the sequence of events (click for larger version):

twilio-click-to-call-example

Click here to view my public Twilio Click-to-Call demo website to follow along as you read through this post.

The first thing to do is to build a page that your customer interacts with. We’ll call this first page in the process default.aspx and make it the default startup page for our web project. In our sample, we’ve dummied up this page to show fictional product details for the Jawbone Bluetooth headset. Featured prominently on the page is a big “Click to Call” button. When the customer clicks that button, we want to fire off the request to Twilio and get the ball moving.

There are two main parts to the code-behind: actually interacting with the Twilio API to make the outbound call to the customer, and setting up the handler that we want Twilio to use once the customer is connected.

Let’s take those in reverse order and talk about the handler first. This is a web page that serves up TwiML, a domain-specific XML dialect, that Twilio interprets and uses to run additional actions when a phone call is connected.

In our case, we’ll want the customer to hear something like “We’re connecting you now”, and then we’ll want to dial our customer service representative to connect them to the customer. TwiML provides two handy verbs, <Say> and <Dial>, that exactly serve our purpose.

A simplified version of our handler would return something like this as an XML response document:

<Response>
<Say>We’re connecting you now.</Say>
<Dial>206.555.1212</Dial>

For the purposes of our initial product page, default.aspx, we only need the URL to point Twilio to. So there is some code-behind that builds the URL, and passes along the product name (“Jawbone”), which we will take advantage of later.

1
2
3
4
5
6
7
8
9
10
11
12
13
protected virtual string GetBaseUrlPath()
{
string baseUrl = Request.Url.Scheme + "://" + Request.Url.Authority + Request.ApplicationPath.TrimEnd('/');
return baseUrl;
}
protected virtual string GetDialHandlerUri(string product)
{
string baseUrl = this.GetBaseUrlPath();
string handlerPath = "/c2c/user.aspx";
string url = baseUrl + handlerPath;
string qs = String.Format("?product={0}", product);
return url + qs;
}

There’s some plumbing code to make sure we’re getting the right URL base path, and then we construct the actual URL to our handler page – in this case, http://twilio.xidey.com/c2c/user.aspx?product=Jawbone.

Now let’s talk about initiating the outbound phone call to the customer. Twilio does this for us when we make a special request to their REST API. Specifically, we make a POST request to our “Calls” resource, with three parameters:

  1. The number we want to call
  2. The number we are calling from (for Caller ID purposes)
  3. The URL of our handler document, as described above

We’ll use the Twilio REST Helper Library that is provided for you on their website (need URL here Anthony). This library provides a ready-made Account class that you can use to make this POST request.

Here’s the code-behind in our product page to make the call:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// calls the customer at the phone number passed in as a parameter
protected void CallPhoneNumber(string phoneNumber)
{
string product = "Jawbone";  // product on current page
// construct our handler URL
string handler = this.GetDialHandlerUri(product);
string caller = "2064098427"; // use your caller ID here
// set up the POST parameters
Hashtable vars = new Hashtable();
vars.Add("Url", handler);
vars.Add("Caller", caller);
vars.Add("Called", phoneNumber);
// construct the URI to your “Calls” resource
string url = string.Format("{0}/Accounts/{1}/Calls", API_VERSION, ACCOUNT_SID);
string method = "POST";
Twilio.Vb.Api.Account a = new Account(ACCOUNT_SID, AUTH_TOKEN);
string result = a.Request(url, ref method, vars);
}

This is all pretty simple, right? Figure out what the customer is viewing; get their phone number; and make a special request to Twilio to call that customer. Our handler document will take care of the 2nd part – connecting the customer to a customer service representative so they can chat.

Let’s revisit our handler document, and extend our previous simple example. Twilio provides a neat facility that allows you to dial multiple phone numbers when trying to make a connection. For example, let’s say you had three Jawbone product experts manning the phones. You can instruct Twilio to call all three, and the first one to pick up “wins” and the other two connection attempts are cancelled. We can get customer service phone numbers from a simple DB lookup, as follows:

1
2
3
4
5
6
7
8
9
10
11
protected virtual IList<string> GetCustomerServicePhoneNumbers()
{
IList items = null;
string connString = ConfigurationManager.ConnectionStrings["twilio_demoConnectionString"].ConnectionString;
using (click_to_callDataContext dc = new click_to_callDataContext(connString))
{
items = (from csp in dc.customer_service_persons
select csp.phone_number).ToList();
}
return items;
}

Here we’re using LINQ-to-SQL to establish a connection to a SQL Server database and get a list of all the customer service representatives’ phone numbers.

Further, just like in our product page, we can specify an action that we want Twilio to take when we call the customer service representatives. In our case, we’ll probably want to give them detailed information about the customer, or the product they are viewing, or other essential details that may help the conversation. For now, it’s enough to know that we can specify an action URL for each <Dial> request.

Here’s the code to generate the URL for the handler document; it looks suspiciously like the code we used to generate the handler URL for the original POST to our Calls resource.

1
2
3
4
5
6
7
8
protected virtual string GetCsrUri(string product)
{
string baseUrl = this.GetBaseUrlPath();
string handlerPath = "/c2c/csr.aspx";
string url = baseUrl + handlerPath;
string qs = String.Format("?product={0}", product);
return url + qs;
}

Only the page name has changed: in this case, our handler will be csr.aspx instead of user.aspx.

Our extended handler document now looks more like this:

<Response>
<Say>Please wait; we’re connecting you now…</Say>
<Dial action="http://twilio.xidey.com/c2c/user.aspx?product=Jawbone" method="GET">206.555.1212</Dial>
<Dial action="http://twilio.xidey.com/c2c/user.aspx?product=Jawbone" method="GET">206.555.8989</Dial>
<!--—more DIAL entries here, if you want –-->
</Response>

* Note: I’m showing the URLs as unencoded for clarity. In real life you want to UrlEncode your URLs. *

That action attribute of the Dial element tells Twilio, “When you connect the customer service representative, use this URL as your handler document to tell you what to do next.” Note that the action handlers are the same in our sample – this isn’t necessary, however. You could have custom actions for each CSR in your database if you wanted.

How do we actually write out the handler document? We’ll use a simple .NET XMLDocument, as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
protected virtual XmlDocument CreateHandlerDocument(string product, IEnumerable phoneNumbers)
{
XmlDocument doc = new XmlDocument();
XmlNode documentElement = doc.AppendChild(doc.CreateElement("Response"));
XmlNode sayElement = documentElement.AppendChild(doc.CreateElement("Say"));
sayElement.AppendChild(doc.CreateTextNode("Please wait while we connect you to a customer service representative."));
foreach (string phoneNumber in phoneNumbers)
{
XmlNode dialElement = documentElement.AppendChild(doc.CreateElement("Dial"));
XmlNode actionAttribute = dialElement.Attributes.Append(doc.CreateAttribute("action"));
actionAttribute.Value = Server.UrlEncode(this.GetCsrUri(product));
XmlNode methodAttribute = dialElement.Attributes.Append(doc.CreateAttribute("method"));
methodAttribute.Value = "GET";
dialElement.AppendChild(doc.CreateTextNode(phoneNumber));
}
return doc;
}

To recap where we’re at: Our first page (default.aspx) told Twilio to call the customer, and when they answer, Twilio should use the contents of this handler page (user.aspx) to determine next actions. In this case, we’ll tell the user to wait, and then we’ll ask Twilio to dial our customer service representatives. When the CSR answers the phone, we’ll use a third page (csr.aspx) to tell Twilio what to do when the CSR answers.

Let’s get to the details of the CSR handler document. In our sample project, this is a TwiML document that informs the CSR what product the customer is looking at, so they can say something really smart and contextual like “Hi there! My name is John Smith. I’d be happy to answer any questions you may have about the Jawbone – and did you know that today only we’re offering 15% off?”

<Response>
<Say>You have a customer calling about the product Jawbone.</Say>
</Response>

The code to write out this handler document (csr.aspx) is essentially the same model as the code we used to write out the first handler document (user.aspx), and we’ll omit it here for clarity, but check out the attached source code for details.

Now we have an end-to-end solution. Recapping our original process diagram:

  1. Customer views a product page on your website.
  2. Customer clicks a “Call me!” button on your page, asking for a phone call.
  3. Your web application makes a POST request to Twilio, requesting an outbound call to the customer.
  4. When the customer answers, Twilio inspects your first handler document (user.aspx), says something to the customer, and then dials your CSRs.
  5. When the first CSR answers, Twilio inspects your second handler document (csr.aspx), and tells the CSR which product the customer is calling about.
  6. Twilio then connects the customer with the CSR, and they are off and running.

There are a few takeaways from this example that are worth highlighting:

  1. Learning TwiML and the Twilio REST API is easy. Really easy.
  2. You can “chain” requests to Twilio via a succession of handler documents.
  3. You can pass dynamic information in to your handler documents via request parameters (GET or POST). In our case, information about the product that the customer was looking at was carried along through two handler documents, to finally be repeated to the CSR when they picked up the phone.

However, not everything always goes as planned, so you have a few tools at your disposal, aside from the normal Visual Studio compilation and debugging environment:

First, there is the Twilio documentation website that provides lots of essential detail about TwiML, the REST API, and has sample code and helper libraries. On your Account page, Twilio provides a call log that lets you see what calls were made in response to your API requests. There’s also a Twilio debugger that lets you see any problems that Twilio encountered while making the outbound calls. Then there are the Twilio Get Satisfaction forums that are manned by Twilio developers and community representatives. There’s a Twilio help e-mail alias. Last but not least, you can find Twilio on Twitter at @twilio.

So, what’s stopping you from integrating telephony into your apps? Not much, not anymore. Jump into Twilio and get your feet wet!

Share and Enjoy:
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Furl
  • Ma.gnolia
  • Reddit
  • TwitThis
9 Comments

9 Comments

  1. James Wu  •  Jun 18, 2009 @10:19 am

    Thanks for the information. There seems to be a never ending supply of great information on the net. I love learning new stuff, and will be back to read your posts regularly !! Thanks again :)
    Thanks,
    Sandy

  2. Danielle Morrill  •  Jun 19, 2009 @6:12 pm

    Hey Anthony we just used your fantastic click-to-call diagram on our blog, and I’d love to get all the content you’ve created about Twilio feature on our blog and website.

    New blog post is here: http://blog.twilio.com/2009/06/magic-call-button-launches-simple-clicktocall-service-using-twilio.html

    I’ve been thinking a Twilio developer meetup here in Seattle could be a lot of fun, are you around these days?

    Best,
    Danielle Morrill
    Twilio Community Manager

  3. anthonyrstevens  •  Jun 19, 2009 @6:27 pm

    Danielle – A Twilio developer meetup would be very cool. Thanks to Twilio, there are a lot of novel ideas emerging about how to telephone-enable apps, and it would be great to share with others working with the technology your team has developed.

  4. Lav  •  Jun 30, 2009 @5:58 am

    Thanks for the useful information Anthony! The reason I even landed on this is because I saw a website for sale which does exactly this: http://www.callonclick.com. I wanted to do some research on this and figured the service had something to do with Twilio. The current bid for the website is $1500, and the Buy it Now price is $5000. But thanks to your article, I am going to build one of these myself. Thanks!

  5. Damon  •  Jul 22, 2009 @7:16 am

    Great article Anthony! I’ve been thinking about using twilio for Uncle Ross and now I’m not sure why I wouldn’t.

  6. Nico  •  Aug 18, 2009 @2:41 pm

    Good article. I think Twilio has done a great job with their platform, but I feel like it is still pretty complicated for the people who are supposed to buy this. Also, I don’t like Twilio (and Ribbit) getting their income from the phone traffic.

    For those who are looking for a sort of “point and click” Click to Call solution with a great reports interface and really good prices, go over to http://www.medularis.com. You’ll be surprised.

  7. Mark  •  Sep 24, 2009 @11:20 am

    Twilio is just fantastic. So easy to use, and yet offers such a wide variety of possibilities. I can’t wait to see how it evolves!

  8. Ansel Taft  •  Nov 10, 2009 @8:26 am

    Hi Anthony,

    Thank you for the article. I was trying to figure out why I was getting organic traffic from your website. It wasn’t until I read the comments…

    Anyhoo, let me address one of the comments above: it turns out CallOnClick.com was built on other technology. I bought the site from Flippa.com and can attest to that much. So, I can’t say it’s an example on how to implement Twilio’s technology.

  9. tony  •  Dec 19, 2009 @4:59 pm

    Hi all,
    the same widget is free http://www.clicktocalls.com

Leave a Reply

Allowed tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">