Simple Phone Menu

Twilio makes it easy to create automated phone menus. This HowTo shows you how to write a simple menu that a caller can navigate using the keypad on almost any phone.


A user calls and is greeted with a list of choices. For example, "For location, press 1". The user enters his/her choice on the telephone keypad, and the next list of choices or information is read. Rinse, repeat.


This HowTo demonstrates creating TwiML call logic, with focus on the <Gather> verb.



  • 1

    • Twilio receives a phone call to the menu's phone number, sending call data to the Voice URL you configured for that number. The script below handles requests to that URL.
  • 2

    • The phone menu system relies on the use of nested <Say> verbs inside a <Gather> verb. This setup allows the caller to make a menu selection before listening to all of the options. For more information, see Example 2 in the <Gather> documentation.

      Each menu list has a name and a certain number of connections to other menu lists. These connections are represented via arrays. The key press associated with the menu item represents the index of the node name in the menu node array. For example, pressing 2 in the default node selects the location node. We can see that "location" has an index of 2 in the default array.

      • howtos/phonemenu/phonemenu.php
        /* Define Menu */
        $web = array();
        $web['default'] = array('receptionist','hours', 'location', 'duck');
        $web['location'] = array('receptionist','east-bay', 'san-jose', 'marin');
        /* Get the menu node, index, and url */
        $node = $_REQUEST['node'];
        $index = (int) $_REQUEST['Digits'];
        $url = 'http://'.dirname($_SERVER["SERVER_NAME"].$_SERVER['PHP_SELF']).'/phonemenu.php';
        /* Check to make sure index is valid */
        if(isset($web[$node]) || count($web[$node]) >= $index && !is_null($_REQUEST['Digits']))
        	$destination = $web[$node][$index];
        	$destination = NULL;

      The TwiML for each node lives in a large switch statement.

      • howtos/phonemenu/phonemenu.php
        /* Render TwiML */
        header("content-type: text/xml");
        echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Response>\n";
        switch($destination) {
        	case 'hours': ?>
        		<Say>Initech is open Monday through Friday, 9am to 5pm</Say>
        		<Say>Saturday, 10am to 3pm and closed on Sundays</Say>
        		<?php break;
        	case 'location': ?>
        		<Say>Initech is located at 101 4th St in San Francisco California</Say>
        		<Gather action="<?php echo 'http://' . dirname($_SERVER["SERVER_NAME"] .  $_SERVER['PHP_SELF']) . '/phonemenu.php?node=location'; ?>" numDigits="1">
        			<Say>For directions from the East Bay, press 1</Say>
        			<Say>For directions from San Jose, press 2</Say>
        		<?php break;
        	case 'east-bay': ?>
        		<Say>Take BART towards San Francisco / Milbrae. Get off on Powell Street. Walk a block down 4th street</Say>
        		<?php break;
        	case 'san-jose': ?>
        		<Say>Take Cal Train to the Milbrae BART station. Take any Bart train to Powell Street</Say>
        		<?php break;
        	case 'duck'; ?>
        		<?php break;
        	case 'receptionist'; ?>
        		<Say>Please wait while we connect you</Say>
        		<?php break;
        	default: ?>
        		<Gather action="<?php echo 'http://' . dirname($_SERVER["SERVER_NAME"] .  $_SERVER['PHP_SELF']) . '/phonemenu.php?node=default'; ?>" numDigits="1">
        			<Say>Hello and welcome to the Initech Phone Menu</Say>
        			<Say>For business hours, press 1</Say>
        			<Say>For directions, press 2</Say>
        			<Say>To hear a duck quack, press 3</Say>
        			<Say>To speak to a receptionist, press 0</Say>

      Unless otherwise specified, each menu item ends in TwiML that redirects back to the main menu, ensuring that the user does not leave the menu unless he or she hangs up the phone.

      • howtos/phonemenu/phonemenu.php
        if($destination && $destination != 'receptionist') { ?>
        	<Say>Main Menu</Say>
        	<Redirect><?php echo 'http://' . dirname($_SERVER["SERVER_NAME"] .  $_SERVER['PHP_SELF']) . '/phonemenu.php' ?></Redirect>
        <?php }
  • 3

    • Twilio processes the TwiML we sent.
  • 4

    • Step 2 now repeats until the user is finished using the phone menu. The menu will also exit if the user presses "0" to connect to a receptionist, in which case Twilio will try to connect the caller to the number specified in the <Dial> verb.