Interactive Voice Response (IVR) System - Node.js

Overview

In this guide, we'll explore how to create a simple Interactive Voice Response (IVR) system in Node.js. We'll be doing this by creating a Consumer that will function as a long-running pipeline of communication to SignalWire Cloud through the use of SignalWire's Communication APIs and WebSocket technology. By the end of this, you too will have an easily-scalable IVR that functions in real-time!

Being the geeks we are and acknowledging that Star Wars will always be better than Star Trek, we will be using the Tosche Station from the desert planet of Tatooine, from the Star Wars movie franchise for this example. Once you have modified this code to point it at the correct phone numbers and departments, you should only then need to link the server that this lives on to the main phone number in your SignalWire Space and let it go from there.

What Do I Need to Run This?

Well, I'm glad you asked! This being a foundational IVR (and a very common use case we get plenty of time), there really isn't much in terms of packages and dependencies. You will need to install SignalWire's Node.js Relay SDK and you're ready to build!

You will also need to have a SignalWire phone number, and have your SignalWire Space credentials ready to go (API Token, Space URL, and Project ID). You can find all of these credentials in an easily-copyable format under the API tab of your SignalWire Space. For more information on where to find this stuff, check out our Navigating your SignalWire Space section!

Getting Started and Connecting to SignalWire's APIs


This code example utilizes Node.js, so you will need SignalWire's Node.js SDK, which you can easily install by using NPM and entering npm install @signalwire/node. The key takeaway here is that you will need to create a Consumer that is a long-running process allowing you to communicate with the SignalWire Cloud, and respond to incoming requests and events in real time. Consumers are great for automating much of the requests for the API, allowing you to focus on building your code. View the code snippet below to see how to connect and build a consumer. The only other items of information you will need is yourProjectId and yourApiToken, both of which can be found in your SignalWire Space. Below, you can see how to do this. You'll also notice that the latter part of the code snippet creates an instance, telling the API what to do should an inbound call come through to your SignalWire Space.

const {RelayConsumer} = require('@signalwire/node') 
const consumer = new RelayConsumer({ 
    project: 'yourProjectId',
    token: 'yourApiToken',
    onIncomingCall: async (call) => {
        const {successful} = await call.answer()
        if (!successful) {
            console.error('Answer Error')
            return
        })

The next thing you want to do is configure your application to welcome the inbound customer verbally and instruct the API to collect the caller's response via digits. You can see that snippet below:

const collect = {
      type: 'digits',
      digits_max: 1,
      text: 'Hello and Welcome to the Tatooine Tosche Station. If you are a new customer, please press one. If you are a returning customer and your power converter needs to be replaced, please press two. If a Jawa has stolen your power converter and you need it back, please press three.'
        }
const prompt = await call.promptTTS(collect)

You now have your user input that was collected from the initial welcome script. From here, all you have to do is set up a phone tree that dials a specific department based on what digit the caller input through an if/else statement or switch. In this example, we utilized the former. You will also want to change mainOfficeNumber to the phone number that the caller initially called into and the departmentNumber to the phone number of the department that you wish the call to be directed to. Phone numbers can be purchased, both through SignalWire's Communication APIs in bulk or through your SignalWire Space individually. Although not necessary, we've added an if statement to the end of each leg of this snippet which will report to the console in the event of a failed call.

        if (prompt == 1) {
            const dialResult = await consumer.client.calling.dial({
                type: 'phone',
                from: 'mainOfficeNumber',
                to: 'departmentNumber',
            })
            const { successful, call} = dialResult
            if (!successful) {
                console.error('Dial Error')
                return
            }
        }
        else if (prompt == 2) {
            const dialResult = await consumer.client.calling.dial({
                type: 'phone',
                from: 'mainOfficeNumber',
                to: 'deparmentNumber',
            })
            const { successful, call} = dialResult
            if (!successful) {
                console.error('Dial Error')
                return
            }
        }
        else if (prompt == 3) {
            const dialResult = await consumer.client.calling.dial({
                type: 'phone',
                from: 'mainOfficeNumber',
                to: 'departmentNumber',
            })
            const { successful, call} = dialResult
            if (!successful) {
                console.error('Dial Error')
                return
            }
        } 
    }
})

This code example is simply the foundation of an IVR in SignalWire Communication APIs at its most basic form, however, the IVR itself can be scaled up or down depending on the needs of your business easily and efficiently.

Running the Application

If you wish to run the application locally, first load the .env file with set -o allexport; source.env; set +o allexport, and then run npm install followed by npm start.

We recommend running the application via Docker, by first building the image with docker build -t relayivr and then docker run -it --rm -v ``pwd``/.node-persist:/app.node-persist --name relayivr --env.file .env relayivr.

You can just run sh run_docker.sh in your shell and the container will be built and started for you.

You may need to use a SSH tunnel for testing this code if running on your local machine. – we recommend ngrok. You can learn more about how to use ngrok here.

Wrap Up

IVRs are a staple of any business's inbound call handling and have been proven to decrease customer wait times and phone agents' efficiency towards the resolution of a given problem. With this guide, you can quickly deploy a low-level IVR without any headaches and only with a few lines of code!

Sign Up Here

If you would like to test this example out, you can create a SignalWire account and space here.

Please feel free to reach out to us on our Community Slack or create a Support ticket if you need guidance!


Did this page help you?