SIGN UP

IVR module usage example: multi-level menu

IVR module usage example: multi-level menu

Most of IVRs nowadays provide caller with the number of options that can be chosen in a multi-level menu. While this kind of IVR can be built using vanilla VoxEngine javascript code, it's better to use helper module (Modules.IVR) we created to simplify the process. It lets developers build IVR menus in scenarios much faster and write less code for that. Let's build the following IVR using the module:

IVR scheme

It's rather simple, but have many input types: noinput, select, inputfixed and inputunknown. VoxEngine scenario for this IVR menu:

require(Modules.IVR); // enable IVR module

let inboundCall;
let outboundCall;
let introState;
let menuState;
let timeState;
let extState;
let fwdState;
let fwdNumber = null;

// Splice function for String class
String.prototype.splice = function (idx, rem, s) {
  return (this.slice(0, idx) + s + this.slice(idx + Math.abs(rem)));
};

function initIVR() {
  const now = new Date();
  /**
   * State that just says current UTC time
   */
  const timeState = new IVRState('time', {
    type: 'noinput',
    prompt: {
      say: `Current time in UTC time zone is ${now.getUTCHours()}:${now.getUTCMinutes()}`,
      lang: Language.US_ENGLISH_FEMALE
    }
  });

  /**
   * State that waits for 3-digit extension number
   * If 100 was entered - make a call to some employee
   */
  const extState = new IVRState('extension', {
    type: 'inputfixed',
    inputLength: 3,
    prompt: {
      say: 'Please enter the extension of the person you are trying to reach',
      lang: Language.US_ENGLISH_FEMALE
    }
  }, (data) => {
    // Extension has been entered
    if (data === '100') {
      inboundCall.say('Forwarding your call to John Connor, please wait', Language.US_ENGLISH_FEMALE);
      inboundCall.addEventListener(CallEvents.PlaybackFinished, handleFwdPlaybackFinished);
    } else {
      inboundCall.say(`There is no person with extension ${data}.`, Language.US_ENGLISH_FEMALE);
      inboundCall.addEventListener(CallEvents.PlaybackFinished, handleFwdPlaybackFinished2);
    }
  }, (data) => {
    // Timeout
    extState.enter(inboundCall);
  });

  /**
   * State that waits for US phone number and #
   * if valid US phone number was specified it forwards call to this number
   */
  const fwdState = new IVRState('callforward', {
    type: 'inputunknown',
    terminateOn: '#',
    prompt: {
      say: 'Please specify US phone number in internation format and press pound',
      lang: Language.US_ENGLISH_FEMALE
    }
  }, (data) => {
    // Input finished
    const number = data.replace('#', '');
    // Check if the specified number is valid US phone number
    Net.httpRequest(`http://api.phone-validator.net/api/v2/verify?PhoneNumber=${number}&CountryCode=us`,
      (e) => {
        if (e.code === 200) {
          const result = JSON.parse(e.text);
          if (result.status === 'VALID_CONFIRMED') {
            fwdNumber = number;
            inboundCall.say('Forwarding your call to specified phone number, please wait', Language.US_ENGLISH_FEMALE);
            inboundCall.addEventListener(CallEvents.PlaybackFinished, handleFwdPlaybackFinished);
          } else {
            inboundCall.say('You have specified wrong phone number.', Language.US_ENGLISH_FEMALE);
            inboundCall.addEventListener(CallEvents.PlaybackFinished, handleFwdPlaybackFinished3);
          }
        } else {
          inboundCall.say('Something went wrong, please try again.', Language.US_ENGLISH_FEMALE);
          inboundCall.addEventListener(CallEvents.PlaybackFinished, handleFwdPlaybackFinished3);
        }
      });
  }, (data) => {
    // Timeout
    fwdState.enter(inboundCall);
  });

  /**
   * Menu state - 3 options
   */
  const menuState = new IVRState('menu', {
    type: 'select',
    prompt: {
      say: 'Press 1 to say time, press 2 enter extension number, press 3 to forward call to specified US number.',
      lang: Language.US_ENGLISH_FEMALE
    },
    nextStates: {
      '1': timeState,
      '2': extState,
      '3': fwdState
    },
  }, null, () => {
    // Timeout
    menuState.enter(inboundCall);
  });

  /**
   * Intro state
   */
  introState = new IVRState('intro', {
    type: 'noinput',
    prompt: {
      say: 'Hello, welcome to VoxImplant demo!',
      lang: Language.US_ENGLISH_FEMALE
    },
    nextState: menuState
  });

  timeState.settings.nextState = menuState;

}

// Forwards call to phone number
function handleFwdPlaybackFinished(e) {
  inboundCall.removeEventListener(CallEvents.PlaybackFinished, handleFwdPlaybackFinished);
  if (fwdNumber == null) {
    // Calling John
    outboundCall = VoxEngine.callPSTN('John\'s number');
  } else {
    // Calling specified phone number
    outboundCall = VoxEngine.callPSTN(fwdNumber);
  }
  outboundCall.addEventListener(CallEvents.Connected, (e) => {
    VoxEngine.sendMediaBetween(e.call, inboundCall);
  });
  outboundCall.addEventListener(CallEvents.Failed, VoxEngine.terminate);
  outboundCall.addEventListener(CallEvents.Disconnected, VoxEngine.terminate);
}

// Wrong input - return to extState
function handleFwdPlaybackFinished2(e) {
  inboundCall.removeEventListener(CallEvents.PlaybackFinished, handleFwdPlaybackFinished2);
  extState.enter(inboundCall);
}

// Wrong input - return to fwdState
function handleFwdPlaybackFinished3(e) {
  inboundCall.removeEventListener(CallEvents.PlaybackFinished, handleFwdPlaybackFinished3);
  fwdState.enter(inboundCall);
}

// Init IVR states after the session start
VoxEngine.addEventListener(AppEvents.Started, (e) => {
  initIVR();
});

// Handle incoming call
VoxEngine.addEventListener(AppEvents.CallAlerting, (e) => {
  inboundCall = e.call;
  // add event listeners
  inboundCall.addEventListener(CallEvents.Connected, handleCallConnected);
  inboundCall.addEventListener(CallEvents.Disconnected, handleCallDisconnected);
  inboundCall.answer(); // answer the call
});

// After call connected enter introState
function handleCallConnected(e) {
  introState.enter(inboundCall);
}

function handleCallDisconnected(e) {
  // Just finish the session
  VoxEngine.terminate();
}

Save the scenario, create new or use some existing application and create the application rule to forward inbound calls to this scenario.

Tags:ivrcall centermenu
B6A24216-9891-45D1-9D1D-E7359CEB8282 Created with sketchtool.

Comments(0)

Add your comment

To leave a comment, first confirm that you are not a robot. It's free

Recommend

Get your free developer account or talk with our sales team to learn more about Voximplant solutions
SIGN UP
Contact sales

Please complete this field.

Please complete this field.

Please complete this field.

Choose the solution

Please complete this field.

Please complete this field.