Call Routing Using Keypad Input

In this how-to guide, we will guide you through implementing a basic call routing application with FreeClimb that utilizes user DTMF (e.g. keypad) inputs to route users. This system will perform the following actions:

  • Receive an incoming call via a FreeClimb application
  • Get user DTMF (e.g. keypad) input
  • Redirect a user to the appropriate endpoint
You can also find the code for this sample app on GitHub

👍

You're ready for this how-to guide if you have:

Followed the IVR sample app set-up instructions


Step 1: Create the express server

The server will provide endpoints where user input can be captured. Create an index.js
file in your project directory, import the needed dependencies, and create/configure the Express application:

require('dotenv-safe').config()
const express = require('express')
const bodyParser = require('body-parser')
const app = express()
app.use(bodyParser.urlencoded({ extended: true }))
app.use(bodyParser.json())

const port = process.env.PORT || 3000

app.listen(port, () => {
  console.log(`Starting server on port ${port}`)
})

module.exports = { app }

Step 2: Handle an incoming call

The first step in our call routing application will be to handle incoming calls. To do this, add the following to index.js:

const {
    createConfiguration,
    DefaultApi,
    Say,
    Pause,
    Redirect,
    PerclScript,
    GetDigits,
    Hangup
} = require('@freeclimb/sdk')

const host = process.env.HOST
const accountId = process.env.ACCOUNT_ID
const apiKey = process.env.API_KEY
const freeclimbAPI = new DefaultApi(createConfiguration({ accountId, apiKey }))
 
let mainMenuErrCount = 0
 
app.post('/incomingCall', (req, res) => {
    const percl = new PerclScript({
        commands: [
            new Say({ text: 'Welcome to the Node IVR Sample app baseline.' }),
            new Pause({ length: 100 }),
            new Redirect({ actionUrl: `${host}/mainMenuPrompt` })
        ]
    })
    res.status(200).json(percl.build())
})

Step 3: Collect digits via a main menu

Next we'll collect DTMF input from the user to direct them to their next destination. To do this, we'll create endpoints for both DTMF collection and menu routing and add them to your index.js file:

app.post('/mainMenuPrompt', (req, res) => {
    const percl = new PerclScript({
        commands: [
            new GetDigits({
                actionUrl: `${host}/mainMenu`,
                prompts: [
                    new Say({
                        text:
                            'Press 1 for existing orders, 2 for new orders, or 0 to speak to an operator'
                    })
                ],

                maxDigits: 1,
                minDigits: 1,
                flushBuffer: true
            })
        ]
    })
    res.status(200).json(percl.build())
})

Next we'll add the logic for how the app will handle user input to index.js:

app.post('/mainMenu', (req, res) => {
    const getDigitsResponse = req.body
    const digits = getDigitsResponse.digits
    const menuOpts = new Map([
        [
            '1',
            {
                script: 'Redirecting your call to existing orders.',
                redirect: `${host}/endCall`
            }
        ],
        [
            '2',
            {
                script: 'Redirecting your call to new orders.',
                redirect: `${host}/endCall`
            }
        ],
        ['0', { script: 'Redirecting you to an operator', redirect: `${host}/transfer` }]
    ])
    if ((!digits || !menuOpts.get(digits)) && mainMenuErrCount < 3) {
        // error counting keeps bad actors from cycling within your applications
        mainMenuErrCount++
        const percl = new PerclScript({
            commands: [
                new Say({ text: 'Error, please try again' }),
                new Redirect({ actionUrl: `${host}/mainMenuPrompt` })
            ]
        })
        res.status(200).json(percl.build())
    } else if (mainMenuErrCount >= 3) {
        // we recommend giving your customers 3 tries before ending the call
        mainMenuErrCount = 0
        const percl = new PerclScript({
            commands: [
                new Say({ text: 'Max retry limit reached' }),
                new Pause({ length: 100 }),
                new Redirect({ actionUrl: `${host}/endCall` })
            ]
        })
        res.status(200).json(percl.build())
    } else {
        mainMenuErrCount = 0
        const percl = new PerclScript({
            commands: [
                new Say({ text: menuOpts.get(digits).script }),
                new Redirect({ actionUrl: menuOpts.get(digits).redirect })
            ]
        })
        res.status(200).json(percl.build())
    }
})

Step 4: Transfer and end call

Finally we'll add in appropriate endpoints for simulating a call transfer and ending a call. Do so by adding the following to your index.js file:

app.post('/transfer', (req, res) => {
    const percl = new PerclScript({
        commands: [
            new Say({ text: 'Please wait while we transfer you to an operator' }),
            new Redirect({ actionUrl: `${host}/endCall` })
        ]
    })
    res.status(200).json(percl.build())
})

app.post('/endCall', (req, res) => {
    const percl = new PerclScript({
        commands: [
            new Say({
                text: 'Thank you for calling the Node IVR sample app baseline, have a nice day!'
            }),
            new Hangup({})
        ]
    })
    res.status(200).json(percl.build())
})

Step 5: Run your app

To hear your DTMF call routing app in action, run the following command at the command line:

yarn start

Once you do this, call the FreeClimb number associated with your application. From there you should be able to experience your call routing application.

Congrats! You can now build your own custom DTMF call routing application. 🥳🥳

Or, to add voice-enabled capabilities, try our Call Routing Using Voice Input how-to guide.