How to Build Call Tracking with Google Analytics, Twilio and PHP

“Half the money I spend on advertising is wasted. The trouble is, I don’t know which half.”
– John Wanamaker

Dear Saul Goodman, Esq.,

First off, my compliments on your phenomenally effective advertising. I can’t drive down the streets of Albuquerque, sit at a bus stop or watch my favorite shows on AMC without seeing one of your ubiquitous “Better Call Saul” ads.

Judging from the, shall we say, “economical” production quality of your ads, you seem to be a man who wants to squeeze every drop of value from your marketing budget. You’ve probably wondered things like, “Do those billboards actually generate leads, or would I be better off buying another late-night TV spot instead?”

It must be frustrating, given that you use the same phone number for all your ads, to be unable to answer those questions. This is why call tracking is important — to help you decide how to best spend your limited marketing budget. Fortunately, with Twilio and a few dozen lines of code, you can track phone numbers for marketing with Google Analytics in less than ten minutes.

Now, if you want to take a deep dive into call tracking and build your own dashboard, you should check out these in depth tutorials:

But if you just want to get something rudimentary up and running in ten minutes with Google Analytics, keep on reading. All you need to get started is a free Twilio account and a server where you can host a PHP file.

How Twilio Call Tracking Works

Twilio call tracking works by associating unique phone numbers to each advertisement (or type of advertisement) you want to track.

For instance, let’s say you want to know which provides a higher ROI: your billboard ads or your late night TV spot. You would put unique call tracking numbers on each of the two, log when a call came into that number, then forward inbound phone calls to your office landline.

At a lower level, a cal tracking system built with Twilio and Google Analytics looks like this:

  1. A lead calls the Twilio number on the ad.
  2. Twilio makes an HTTP request to a script you’ve set up in the account dashboard.
  3. Your script extracts the phone number that was called from the parameter of Twilio’s HTTP request, then matches that number to the ad type (in our case, we’ll hard code these pairings).
  4. Your script makes its own HTTP request to Google Analytics via the Measurement Protocol API to register the offline event of “Phone Call from X advertisement.”
  5. Your script returns three lines of XML to Twilio to forward the incoming call to your main landline.

To implement this, we’ll work backwards and first look at how to forward a Twilio number to a landline. Then we’ll log that incoming call as an event in Google Analytics.

How To Forward a Call from a Twilio Number

I saw on a billboard that your office number is (505) 503-4455*.

Head over to your Twilio Dashboard and buy two phone numbers in the 505 area code. And don’t worry, Twilio’s inventory includes many easy to remember numbers since I know that many of your clients a) are working with diminished cognitive capacity and b) don’t exactly have access to Google at the time in which they most desperately need you.

For instance, check out this number I found:

Screen Shot 2015-09-21 at 10.54.44 PM

See the box that says (Voice) Request URL? When someone calls your shiny new number, Twilio makes an HTTP request to that URL looking for instructions on what to do next.

Let’s write a simple script to return the XML to forward a call.

Forward a Twilio phone call with PHP

I’m going to write this code in PHP only because it’s easiest to deploy. I’m not sure what stack you’re into, but if you want to set up call tracking in Javascript, Ruby or Python, I’m sure you’ll find it pretty easy to translate these steps into your language of choice.

When a call comes into your Twilio number, Twilio makes an HTTP request to the voice request URL you defined on your dashboard. The script at that URL will respond with Twilio flavored XML that we call TwiML.

Create a new file called call_tracking.php , then add this code:

Save the file, then update the Voice Request URL for both of your shiny new Twilio numbers with your script’s publicly accessible URL, such as (By the way, if you’d like to give your local development environment a publicly accessible URL so that you can play around with this script without deploying to the cloud, check out ngrok).

With your script in place, call one of your Twilio numbers and listen to your favorite voicemail message.

Retrieve the inbound phone number

Paste the following array above the header  line to associate your Twilio phone numbers with their advertising source. In fact, any code you see from now ’til the end of this letter should be pasted above that line.

Make sure that your numbers keep the format of +1XXXYYYZZZZ.

So Saul, you’re probably asking yourself, “But how do we know which Twilio number the lead called?” Good question. When Twilio makes an HTTP request to your script, it passes in a bunch of parameters. The full list can be found here, but the one we’re most interested in is stored in   $_POST['To'] .

Paste these two lines below the array declaration to grab the inbound Twilio number and its corresponding ad source:

Now that we know the source of the inbound call, we can pass it along to Google Analytics using the Measurement Protocol API.

Log Custom Events with the Measurement Protocol API

I took a look at the source code of and saw that you’re already using Google Analytics. This is unsurprising given your marketing savvy and penchant for saving money.

Last year Google released the Google Analytics Measurement Protocol API which, among other things, allows us to log offline events. According to the Measurement Protocol developer’s guide, you log an offline event by making a POST request to the API and including at least these six required fields:

The version of the measurement protocol.
field: v
value: “1”
As of today (September 2015), this is version “1” and will likely stay that way for sometime.

The tracking ID
field: tid
value: “UA-XXXXXX-X”
This is the unique ID of your Google Analytics account. It takes the format of UA-XXXXXX-X and can be found on your Analytics dashboard.


field: t
value: “event”
You can use the Measurement Protocol to track events, clicks, impressions, page views, ecommerce and so on. A phone call is best described as an “event”.

Event Category
field: ec
value: “phonecall”
The Measurement Protocol docs say, “A category is a name that you supply as a way to group objects that you want to track.” Our category will be “phonecall”.

Event Action
field: ea
value: either “billboard” or “tv” as defined in $source.
You can think of these “actions” as shorthand for “made a call from a (billboard|tv).”

A unique anonymous client ID
field: cid
value: a unique UUID

This is the unique identifier for the client. You’ll be tempted to use the caller’s phone number as a unique identifier, which can be found in $_POST['From'] . Unfortunately the docs say that the CID “must not itself be PII (personally identifiable information)” but should take the form of a UUID.

Now Saul, I know that you’re okay with occasionally bending the rules, but there’s really no need here when generating an ID is as easy as pasting this code of Roger Stringer into your call_tracking.php : 

Make a POST request to the Measurement Protocol API

To make your POST request, first make an array with the six required fields and their corresponding values:

Convert that array into a URL encoded string:

Initiate a POST request by creating a new curl session:

Set the URL of the POST request to the Google Analytics endpoint:

Set the number of fields that you’ll be passing along — six right now case, but we’ll calculate it dynamically in case you’d like to log more information later:

Include the field string:

Turn on the Return Transfer option to prevent the curl response from being outputted in our HTTP response along with our TwiML:

Execute your POST request:

And close your session:

Save your file, open up the Real Time Reports in Google Analytics and redial that Twilio number. You’ll see a new event pop up registering the call event. To track your calls over a period of time, click Behavior on the left hand navigation, then Events -> Top Events. Then add Event Action as a secondary metric. You may want to set up a custom report with this selection for easy access. 

Screen Shot 2015-09-22 at 10.57.45 PM


Next Steps

Nice work, Saul. You’ve setup basic advertising call tracking and will soon have a much better idea how to spend the next $100 of your marketing budget. In the United States your call tracking costs will come in at $1 per month for the phone number and $0.03 cents per minute of voice time ($0.01 for the inbound call and $0.02 for the outbound forwarding call). For more on this, check out the Twilio voice pricing page.  

If you want to measure additional form of advertising, such as website call tracking or call tracking on PPC campaigns, simply:

  • Buy another Twilio number
  • Set the Voice Request URL to your call_tracking.php
  • Add a line to the phone number array

If you’d like to learn the ins and outs of the Google Analytics Measurement Protocol, these resources might help:

And again, if you want to dive deep into the world of call tracking, check out these in-depth tutorials. If you’d like to chat more about call tracking and Google Analytics, hit me up at @greggyb or

*I punched your office number into our new Phone Number Lookup and saw that, tragically, it’s a landline. You could port that number over to Twilio and make the experience a whole lot more engaging — think IVR, SMS and MMS. Have your people call us.

  • Xperience

    Hi Greg, thanks for the very helpful tutorial. How can we setup Google Analytics “Goals” instead of “Events”? I need to track phone calls for Google AdWords conversion purposes. Let me know and thanks in advance! R

    • Xperience

      Also – you’re missing a “;” on this snippet, just in case others get a PHP error:

      $twilioNumber = $_POST[‘To’] // closing “;” missing here
      $source = $numbers[$twilioNumber];

      • Great catch! Updated. Thank you.
        I’ll have to dig a bit to get you an answer about goals.

        • Xperience

          Awesome! I did a bit of research, and I think it is as simple as creating a new Goal, select goal type = event, enter event category = “phone call” and event action = “billboard” (for example)

  • Joshua Sharp

    This was brilliant and helpful. Well done. …that said, having a file ready to download and just replace the variables on (instead of cutting/pasting lots of lines to assemble it myself) would be nice. Eliminate wasted time / source of error.

  • Hi @baugues:disqus what would be awesome if there was something we could do that the events generated are tagged as adwords conversion related, you see even if you import the GA goal to AdWords, unless the event was tagged somehow as adwords traffic it wil not show up as conversion in AdWords and only a goal in GA

    • Was wondering that myself, how to setup a dynamic insertion by visitor source.

  • Ignatius

    Great tutorial. Im not a developer. Can you give us the complete code as a file for download so we can just replace the variables and be done?