Search code examples
twiliovoicetwilio-twiml

Interactive voice menu on Twilio/TwiML


I need to get an interactive menu going with TwiML and had a few questions about it:

  1. Can I do it purely in TwiML or do I need a server-side installation with form processing?
  2. I need to basically pick up a call, ask the user a couple of options (Press 1 for yada yada, press 2 for blah blah), and based on the response need to call one or another number. Kind of like an interactive switchboard

Is the above possible? Any indication on how I might go about it?


Solution

  • Twilio developer evangelist here.

    You cannot produce an interactive menu with static TwiML, you need something that can react to the choice taken and that requires a server side component.

    Thankfully, you have some options here.

    As Alex points out in the comments, Twilio Studio is a visual builder for Twilio which lets you create a flow like this and leave the server side component to Twilio. There's a video tutorial and guide which show you how to build an IVR with Studio.

    On the other hand, if you're happy writing the code to create this sort of thing, but you'd rather not host it, then Twilio Functions might be what you're looking for. Twilio Functions is a serverless environment for running code. You can write your initial TwiML with a TwiML Bin as it can be static TwiML, something like the following, which uses <Gather> to collect user input:

    <Response>
      <Gather action="FUNCTION_URL" numDigits="1">
        <Say>Welcome to my menu, please press 1 for sales or 2 for support</Say>
      </Gather>
    </Response>
    

    Then in the Function you need to write some Node.js to respond to the incoming Digits parameter that <Gather> will send to the action URL once the user enters them. You could respond to that with a function that looks a bit like this:

    exports.handler = function(context, event, callback) {
      const twiml = new Twilio.twiml.VoiceResponse();
      if (event.Digits === '1') {
        twiml.dial(SALES_NUMBER);
      } else if (event.Digits === '2') {
        twiml.dial(SUPPORT_NUMBER);
      } else {
        const gather = twiml.gather({ action: 'FUNCTION_URL', numDigits: '1' })
        gather.say('That was not an option, please dial 1 for sales and 2 for support')
      }
      callback(null, twiml);
    }
    

    There is also a guide that goes into a bit more depth in taking user input using <Gather>.

    Let me know if that helps at all.