Click To Call with PHP

Download the Code

Wish your users could get in touch as easily as they can surf? Today's your lucky day!

Let's go over the steps necessary to implement click-to-call in a PHP application.

Click to Call

  1. A website visitor submits a web form with a phone number.
  2. Your web application receives the submission and initiates an HTTP request to Twilio asking to initiate an outbound call.
  3. Twilio receives the request and initiates a call to the user's phone number.
  4. The user picks up the call.
  5. After the call connects, we provide TwiML instructions to connect the user to our sales or support teams.

* Check out how iAdvize uses Twilio Click-to-call to connect online shoppers with customer support representatives. *

What We Will Learn

This tutorial demonstrates how to initialize a call using the Twilio REST API and how to create a call using the TwiML Say verb.

Let's get started! Click the button below to move to the next step of the tutorial.

Setup a PHP Development Environment

To create our click-to-call application we need to setup our environment first.

Let's put our Twilio credentials in a place where our application can access them. For the purposes of this tutorial, we'll set them as environment variables that our application can read.

You can find your Twilio credentials in the console.

Retrieve Your Twilio Credentials

You will need to set the following environmental variables:

  • TWILIO_ACCOUNT_SID
  • TWILIO_AUTH_TOKEN
  • TWILIO_NUMBER

For more instructions on how to run the application refer to the app's readme file.

Next, let's work on the web form.

Make a Nice Web Form

The first step is to build the form that your user needs to fill out on the web.

No need to overthink this; the goal is to POST the User's name and phone number to your controller.

Loading Code Samples...
Language
<!DOCTYPE html>
<html lang="en">
<head>
	<title>Click To Call Tutorial</title>
	<!-- We use Twitter Bootstrap as the default styling for our page-->
	<link rel="stylesheet"
		href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
	<link rel="stylesheet"
		href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
	<!-- Include CSS for our third-party telephone input jQuery plugin-->
	<link rel="stylesheet" href="/vendor/intl-phone/css/intlTelInput.css">
</head>
<body>
	<div class="container">
		<h1>Click To Call</h1>
		<p>
			Click To Call converts your website's users into engaged customers by
			creating an easy way for your customers to contact your sales and
			support teams right on your website.
		</p>
		<p>Here's an example of how it's done!</p>
		<hr>

		<!-- C2C contact form-->
		<div class="row">
			<div class="col-md-12">
				<form id="contactForm" role="form">
					<div class="form-group">
						<h3>Call Sales</h3>
						<p class="help-block">
							Are you interested in impressing your friends and
							confounding your enemies? Enter your phone number
							below, and our team will contact you right away.
						</p>
					</div>
                    <label>Your number</label>
                    <div class="form-group">
                       <input class="form-control" type="text" name="userPhone" id="userPhone"
                              placeholder="(651) 555-7889">
                    </div>
                    <label>Sales team number</label>
                    <div class="form-group">
                       <input class="form-control" type="text" name="salesPhone" id="salesPhone"
                              placeholder="(651) 555-7889">
                     </div>
					<button type="submit" class="btn btn-default">
						Contact Sales
					</button>
				</form>
			</div>
		</div>
	</div>
	<!-- Include page dependencies -->
	<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
	<script src="/vendor/intl-phone/js/intlTelInput.min.js"></script>
	<script src="/app.js"></script>
</body>
</html>
app/views/home.php
Build a web form

app/views/home.php

What information does this form need?

  • An input for a phone number
  • A submit button

(And that's it!)

Since the page doesn't need to render new content after clicking Submit, we've decided to implement the POST action via AJAX using jQuery. Let's take a look at that next.

Submit the Form

To make the click to call feature more seamless we used AJAX to send the form asynchronously.

This code shows one way you could implement this functionality using jQuery:

  • Intercept the submission of the user's form
  • Submit the form data to our controller
  • Let the user know if the submission was successful or not

This is a common implementation of jQuery's $.ajax() method. Notice that we are returning the response message when the call has connected.

Loading Code Samples...
Language
// Execute JavaScript on page load
$(function() {
    // Initialize phone number text input plugin
    $('#userPhone, #salesPhone').intlTelInput({
        responsiveDropdown: true,
        autoFormat: true,
        utilsScript: '/vendor/intl-phone/libphonenumber/build/utils.js'
    });

    // Intercept form submission and submit the form with ajax
    $('#contactForm').on('submit', function(e) {
        // Prevent submit event from bubbling and automatically submitting the
        // form
        e.preventDefault();

        // Call our ajax endpoint on the server to initialize the phone call
        $.ajax({
            url: '/call',
            method: 'POST',
            dataType: 'json',
            data: {
                userPhone: $('#userPhone').val(),
                salesPhone: $('#salesPhone').val()
            }
        }).done(function(data) {
            // The JSON sent back from the server will contain a success message
            alert(data.message);
        }).fail(function(error) {
            alert(JSON.stringify(error));
        });
    });
});
public/app.js
Submit a web form with AJAX

public/app.js

Now that we have the front end done, let's build the back end that will receive this data and call the user.

Make a Phone Call

Next we initiate a Twilio\Rest\Client object with our Account SID and Auth Token.

This is essentially our PHP REST API handler, which we could use to send SMSes (or for a myriad of other things). Of course, for now we just need it to create phone calls.

We'll use the REST API to make an outgoing phone call which requires us to pass a To number, a From number and an array which contains a URL Parameter with instructions for Twilio. In a customer support case, Twilio needs to DIAL the Agent in once the call has been placed. (We'll discuss this more later.)

Loading Code Samples...
Language
<?php
/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It's a breeze. Simply tell Laravel the URIs it should respond to
| and give it the Closure to execute when that URI is requested.
|
*/

Route::get('/', function () {
    return View::make('home');
});

// POST URL to handle form submission and make outbound call
Route::post('/call', function () {
    // Get form input
    $userPhone = Input::get('userPhone');
    $encodedSalesPhone = urlencode(str_replace(' ','',Input::get('salesPhone')));
    // Set URL for outbound call - this should be your public server URL
    $host = parse_url(Request::url(), PHP_URL_HOST);

    // Create authenticated REST client using account credentials in
    // <project root dir>/.env.php
    $client = new Twilio\Rest\Client(
        getenv('TWILIO_ACCOUNT_SID'),
        getenv('TWILIO_AUTH_TOKEN')
    );

    try {
        $client->calls->create(
            $userPhone, // The visitor's phone number
            getenv('TWILIO_NUMBER'), // A Twilio number in your account
            array(
                "url" => "http://$host/outbound/$encodedSalesPhone"
            )
        );
    } catch (Exception $e) {
        // Failed calls will throw
        return $e;
    }

    // return a JSON response
    return array('message' => 'Call incoming!');
});

// POST URL to handle form submission and make outbound call
Route::post('/outbound/{salesPhone}', function ($salesPhone) {
    // A message for Twilio's TTS engine to repeat
    $sayMessage = 'Thanks for contacting our sales department. Our
        next available representative will take your call.';

    $twiml = new Twilio\Twiml();
    $twiml->say($sayMessage, array('voice' => 'alice'));
    $twiml->dial($salesPhone);

    $response = Response::make($twiml, 200);
    $response->header('Content-Type', 'text/xml');
    return $response;
});
app/routes.php
The application routes

app/routes.php

Let's look in greater detail at our TwiML commands to Twilio.

Generate Some Terrific TwiML

TwiML is a set of verbs and nouns written in XML that Twilio reads as instructions. For this simple app, our instructions inform Twilio to SAY something to the user and then DIAL the support agent's number so the customer can talk to him/her.

In order to make writing TwiML easy, many of the helper libraries have methods that generate TwiML for you. In this case we use twilio-php to create a TwiML response that will instruct Twilio to say something.

Loading Code Samples...
Language
<?php
/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It's a breeze. Simply tell Laravel the URIs it should respond to
| and give it the Closure to execute when that URI is requested.
|
*/

Route::get('/', function () {
    return View::make('home');
});

// POST URL to handle form submission and make outbound call
Route::post('/call', function () {
    // Get form input
    $userPhone = Input::get('userPhone');
    $encodedSalesPhone = urlencode(str_replace(' ','',Input::get('salesPhone')));
    // Set URL for outbound call - this should be your public server URL
    $host = parse_url(Request::url(), PHP_URL_HOST);

    // Create authenticated REST client using account credentials in
    // <project root dir>/.env.php
    $client = new Twilio\Rest\Client(
        getenv('TWILIO_ACCOUNT_SID'),
        getenv('TWILIO_AUTH_TOKEN')
    );

    try {
        $client->calls->create(
            $userPhone, // The visitor's phone number
            getenv('TWILIO_NUMBER'), // A Twilio number in your account
            array(
                "url" => "http://$host/outbound/$encodedSalesPhone"
            )
        );
    } catch (Exception $e) {
        // Failed calls will throw
        return $e;
    }

    // return a JSON response
    return array('message' => 'Call incoming!');
});

// POST URL to handle form submission and make outbound call
Route::post('/outbound/{salesPhone}', function ($salesPhone) {
    // A message for Twilio's TTS engine to repeat
    $sayMessage = 'Thanks for contacting our sales department. Our
        next available representative will take your call.';

    $twiml = new Twilio\Twiml();
    $twiml->say($sayMessage, array('voice' => 'alice'));
    $twiml->dial($salesPhone);

    $response = Response::make($twiml, 200);
    $response->header('Content-Type', 'text/xml');
    return $response;
});
app/routes.php
Handle a submission and make a call

app/routes.php

And with that, we've added Click-to-Call to our application which will make it easy for our website visitors to get in touch.  

Next, let's look at some other easy to add features for your application!

Where to Next?

If you're a PHP developer working with Twilio, you might enjoy these other tutorials:

Automated Survey

Instantly collect structured data from your users with a survey conducted over a voice or an SMS text messages.

Two-Factor Authentication with Authy

Improve the security of Laravel's built-in login functionality by adding two-factor authentication with Twilio's Authy

Did this help?

Thanks for checking this tutorial out! Tweet to us @twilio and let us know what you're building!

Mario Celi
Paul Kamp
Jose Oliveros
Agustin Camino
Andrew Baker

Need some help?

We all do sometimes; code is hard. Get help now from our support team, or lean on the wisdom of the crowd browsing the Twilio tag on Stack Overflow.

1 / 1
Loading Code Samples...
<!DOCTYPE html>
<html lang="en">
<head>
	<title>Click To Call Tutorial</title>
	<!-- We use Twitter Bootstrap as the default styling for our page-->
	<link rel="stylesheet"
		href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
	<link rel="stylesheet"
		href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
	<!-- Include CSS for our third-party telephone input jQuery plugin-->
	<link rel="stylesheet" href="/vendor/intl-phone/css/intlTelInput.css">
</head>
<body>
	<div class="container">
		<h1>Click To Call</h1>
		<p>
			Click To Call converts your website's users into engaged customers by
			creating an easy way for your customers to contact your sales and
			support teams right on your website.
		</p>
		<p>Here's an example of how it's done!</p>
		<hr>

		<!-- C2C contact form-->
		<div class="row">
			<div class="col-md-12">
				<form id="contactForm" role="form">
					<div class="form-group">
						<h3>Call Sales</h3>
						<p class="help-block">
							Are you interested in impressing your friends and
							confounding your enemies? Enter your phone number
							below, and our team will contact you right away.
						</p>
					</div>
                    <label>Your number</label>
                    <div class="form-group">
                       <input class="form-control" type="text" name="userPhone" id="userPhone"
                              placeholder="(651) 555-7889">
                    </div>
                    <label>Sales team number</label>
                    <div class="form-group">
                       <input class="form-control" type="text" name="salesPhone" id="salesPhone"
                              placeholder="(651) 555-7889">
                     </div>
					<button type="submit" class="btn btn-default">
						Contact Sales
					</button>
				</form>
			</div>
		</div>
	</div>
	<!-- Include page dependencies -->
	<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
	<script src="/vendor/intl-phone/js/intlTelInput.min.js"></script>
	<script src="/app.js"></script>
</body>
</html>
// Execute JavaScript on page load
$(function() {
    // Initialize phone number text input plugin
    $('#userPhone, #salesPhone').intlTelInput({
        responsiveDropdown: true,
        autoFormat: true,
        utilsScript: '/vendor/intl-phone/libphonenumber/build/utils.js'
    });

    // Intercept form submission and submit the form with ajax
    $('#contactForm').on('submit', function(e) {
        // Prevent submit event from bubbling and automatically submitting the
        // form
        e.preventDefault();

        // Call our ajax endpoint on the server to initialize the phone call
        $.ajax({
            url: '/call',
            method: 'POST',
            dataType: 'json',
            data: {
                userPhone: $('#userPhone').val(),
                salesPhone: $('#salesPhone').val()
            }
        }).done(function(data) {
            // The JSON sent back from the server will contain a success message
            alert(data.message);
        }).fail(function(error) {
            alert(JSON.stringify(error));
        });
    });
});
<?php
/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It's a breeze. Simply tell Laravel the URIs it should respond to
| and give it the Closure to execute when that URI is requested.
|
*/

Route::get('/', function () {
    return View::make('home');
});

// POST URL to handle form submission and make outbound call
Route::post('/call', function () {
    // Get form input
    $userPhone = Input::get('userPhone');
    $encodedSalesPhone = urlencode(str_replace(' ','',Input::get('salesPhone')));
    // Set URL for outbound call - this should be your public server URL
    $host = parse_url(Request::url(), PHP_URL_HOST);

    // Create authenticated REST client using account credentials in
    // <project root dir>/.env.php
    $client = new Twilio\Rest\Client(
        getenv('TWILIO_ACCOUNT_SID'),
        getenv('TWILIO_AUTH_TOKEN')
    );

    try {
        $client->calls->create(
            $userPhone, // The visitor's phone number
            getenv('TWILIO_NUMBER'), // A Twilio number in your account
            array(
                "url" => "http://$host/outbound/$encodedSalesPhone"
            )
        );
    } catch (Exception $e) {
        // Failed calls will throw
        return $e;
    }

    // return a JSON response
    return array('message' => 'Call incoming!');
});

// POST URL to handle form submission and make outbound call
Route::post('/outbound/{salesPhone}', function ($salesPhone) {
    // A message for Twilio's TTS engine to repeat
    $sayMessage = 'Thanks for contacting our sales department. Our
        next available representative will take your call.';

    $twiml = new Twilio\Twiml();
    $twiml->say($sayMessage, array('voice' => 'alice'));
    $twiml->dial($salesPhone);

    $response = Response::make($twiml, 200);
    $response->header('Content-Type', 'text/xml');
    return $response;
});
<?php
/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It's a breeze. Simply tell Laravel the URIs it should respond to
| and give it the Closure to execute when that URI is requested.
|
*/

Route::get('/', function () {
    return View::make('home');
});

// POST URL to handle form submission and make outbound call
Route::post('/call', function () {
    // Get form input
    $userPhone = Input::get('userPhone');
    $encodedSalesPhone = urlencode(str_replace(' ','',Input::get('salesPhone')));
    // Set URL for outbound call - this should be your public server URL
    $host = parse_url(Request::url(), PHP_URL_HOST);

    // Create authenticated REST client using account credentials in
    // <project root dir>/.env.php
    $client = new Twilio\Rest\Client(
        getenv('TWILIO_ACCOUNT_SID'),
        getenv('TWILIO_AUTH_TOKEN')
    );

    try {
        $client->calls->create(
            $userPhone, // The visitor's phone number
            getenv('TWILIO_NUMBER'), // A Twilio number in your account
            array(
                "url" => "http://$host/outbound/$encodedSalesPhone"
            )
        );
    } catch (Exception $e) {
        // Failed calls will throw
        return $e;
    }

    // return a JSON response
    return array('message' => 'Call incoming!');
});

// POST URL to handle form submission and make outbound call
Route::post('/outbound/{salesPhone}', function ($salesPhone) {
    // A message for Twilio's TTS engine to repeat
    $sayMessage = 'Thanks for contacting our sales department. Our
        next available representative will take your call.';

    $twiml = new Twilio\Twiml();
    $twiml->say($sayMessage, array('voice' => 'alice'));
    $twiml->dial($salesPhone);

    $response = Response::make($twiml, 200);
    $response->header('Content-Type', 'text/xml');
    return $response;
});