Whatever method you use to obtain the various prompts and messages that you'll use in your IVR menus, you should lay out a picture of the IVR Attendant menu tree and identify all of the sounds that you'll use at each step of the way. This will help you in obtaining the needed sounds and building the actual dialplan that implements the IVR Attendant. Here is an example of a simple IVR Attendant that we use:
Daytime (09:00-18:59) --> play: thank-you-for-calling if-you-know-dial-any-time P1-for-dir-or-stay-on wait for dialed digits --> 0 --> ring the operator 1 --> goto IVR Directory invalid --> play: not-valid-extension retry timeout --> play: transfer-to-operator ring the operator 6XX --> ring the extension Nights/Weekend (19:00-08:59) --> play: thank-you-for-calling at-present-closed if-you-know-dial-any-time party-no-answer-voicemail if-dont-know-P1-for-dir wait for dialed digits --> 1 --> goto IVR Directory invalid --> play: not-valid-extension retry timeout --> play: hasta-la-vista hang up 6XX --> ring the extension Vacation (July 4) --> play: thank-you-for-calling at-present-vacation if-you-know-dial-any-time party-no-answer-voicemail if-dont-know-P1-for-dir wait for dialed digits --> 1 --> goto IVR Directory invalid --> play: not-valid-extension retry timeout --> play: hasta-la-vista hang up 6XX --> ring the extension Mental Health Hotline --> play: mental-health-hotline wait for dialed digits --> 1 --> goto IVR Directory invalid --> play: not-valid-extension retry timeout --> play: hasta-la-vista hang up 6XX --> ring the extension IVR Directory --> play: dir-dial-three-letters wait for dialed digits --> invalid --> play: dir-dont-recognize-name retry timeout --> play: goodbye hang up 2XX --> play: transfer-to-norm-cole ring extension 601 9XX --> play: transfer-to-ed-wilson ring extension 600
The messages, shown in the menus above, have the following texts:
at-present-closed - At present, we are closed. at-present-vacation - At present, we are taking some time off and are closed for vacation. dir-dial-three-letters - Please dial the first three letters of your party's last name. dir-dont-recognize-name - I'm sorry. I don't recognize that person's name. Please try again. goodbye - Goodbye. hasta-la-vista - Hasta la vista, baby. if-you-know-dial-any-time - If you know the extension of the party you wish to reach, you may dial it at any time. if-dont-know-P1-for-dir - If you don't know your party's extension, press 1 for directory assistance mental-health-hotline - Hello and welcome to The Mental Health Hotline. If you are obsessive/compulsive, press 1 repeatedly. If you are co-dependant, ask someone to press 2 for you. If you have multiple personalities, press 3, 4, 5 and 6. If you are paranoid, we know what you are and what you want, stay on the line and we'll trace your call. If you are delusional, press 7 and your call will be transferred to The Mother Ship. If you are schizophrenic, listen carefully and a small voice will tell which number to press. If you are depressive, it doesn't matter which number you press, no-one will answer you. If you are dyslexic, press 69, 69, 69, 69. If you have a nervous disorder, please fidget with the hash key until the beep. After the beep, please wait for the beep. If you have a short-term memory loss, please try your call again later, and if you have low self-esteem, hang up, all our operators are too busy to talk. not-valid-extension - I'm sorry. That is not a valid extension. Please try again. P1-for-dir-or-stay-on - Press 1 for directory assistance or stay on the line for the operator. party-no-answer-voicemail - If your party does not answer, you will be able to leave a voicemail message. thank-you-for-calling - Thank-you for calling. transfer-to-ed-wilson - Transferring to Ed Wilson at extension 600. transfer-to-norm-cole - Transferring to Norm Cole at extension 601. transfer-to-operator - Transferring to the operator.
The IVR Attendant's messages are actually stored in the local "ivr" subdirectory that we added under the Asterisk "sounds" directory (i.e. /var/lib/asterisk/sounds/ivr). This being the case, we must prefix the name of each message name with "ivr/", when we use it in the dial plan.
We prefer to build the IRV Attendant portion of the dial plan in a separate file, in the local directory, where it can be conveniently changed, if need be. This file can then be included in the exetensions.conf file and the "ivrmenutree" macro referenced in the appropriate place in the CO lines file.
/etc/asterisk/local/ivr-menutree.conf:
; local/ivr-menutree.conf - Local IVR menu tree. ; ; This module is contains a macro that defines the IVR menu tree used by the ; local CO lines. Once this module is included in the CO lines file, the ; macro may be invoked to answer the phone and play the IVR menu. ; ; It also defines all of the sub-menus, including special sub-menus for ; off hours and holidays, as well as a sub-menu for doing a directory search ; by last name. ; ; Note that, before this module is included, you should define the global ; variable EXTPATTERN, which is used to define the pattern used to match ; extension numbers. Typically, it is set to something like "6XX" or ; "5XXX". ; ; ; IVR attendant macro. This starts up the IVR menu tree. It checks the ; time and branches to the appropriate sub-menu for the date/time. There ; is a special sub-menu for Dale. ; [macro-ivrmenutree] ; Answer the phone. exten => s,1,Answer() ; Dale always gets special treatment -- The Mental Health Hotline. exten => s,n,Gotoif($[${CALLERID(num)} = 1234567890]?ivrmental,s,1:) ; Check for the holidays first. These override the regular hours. exten => s,n,GotoIfTime(*,*,4,jul?ivrholiday,s,1) ; If the office is closed, go to the closed greeting. exten => s,n,GotoIfTime(19:00-08:59,*,*,*?ivrclosed,s,1) ; Fall through to the regular, working hours greeting. exten => s,n,Goto(ivrworking,s,1) ; ; This is the regular, working hours menu. ; [ivrworking] exten => s,1,Background(ivr/thank-you-for-calling&\ ivr/if-you-know-dial-any-time&\ ivr/P1-for-dir-or-stay-on) exten => s,2,WaitExten(10) ; The user can press 0 for the operator. This will make Dale happy. exten => 0,1,Goto(from-internal,0,1) ; The user can press 1 for the directory. exten => 1,1,Goto(ivrdirectory,s,1) ; If they don't press a valid key, give them an error. exten => i,1,Playback(ivr/not-valid-extension) exten => i,n,Goto(ivrworking,s,2) ; If the wait for a digit times out, transfer to the operator. exten => t,1,Playback(ivr/transfer-to-operator) exten => t,n,Goto(from-internal,0,1) ; Ring the extension that the user dialed (we do this by jumping to the ; from-internal context, as if one of the internal lines dialed an ; extension, so that we can use the same extension definitions found ; therein). exten => _${EXTPATTERN},1,Goto(from-internal,${EXTEN},1) ; We optionally enable the virtual extensions from outside lines, if the ; virtual outside switch is on. exten => _${VIRTPATTERN},1,Gotoif($[${EXISTS(${VIRTOUTSIDE})}]?\ virtual-extensions,${EXTEN},1:) exten => _${VIRTPATTERN},n,Playback(sorry2) exten => _${VIRTPATTERN},n,Hangup() ; Define an extension that will get us into voicemail so that we can ; check it from outside. exten => ${EXTVMAIL},1,VoicemailMain() exten => ${EXTVMAIL},n,Hangup() ; ; This is the after hours menu. ; [ivrclosed] exten => s,1,Background(ivr/thank-you-for-calling&\ ivr/at-present-closed&\ ivr/if-you-know-dial-any-time&\ ivr/party-no-answer-voicemail&\ ivr/if-dont-know-P1-for-dir) exten => s,2,WaitExten(10) ; The user can press 1 for the directory exten => 1,1,Goto(ivrdirectory,s,1) ; If they don't press a valid key, give them an error. exten => i,1,Playback(ivr/not-valid-extension) exten => i,n,Goto(ivrclosed,s,2) ; If the wait for a digit times out, say goodbye and hang up. exten => t,1,Playback(ivr/hasta-la-vista) exten => t,n,Hangup() ; Ring the extension that the user dialed. exten => _${EXTPATTERN},1,Goto(from-internal,${EXTEN},1) ; We optionally enable the virtual extensions from outside lines, if the ; virtual outside switch is on. exten => _${VIRTPATTERN},1,Gotoif($[${EXISTS(${VIRTOUTSIDE})}]?\ virtual-extensions,${EXTEN},1:) exten => _${VIRTPATTERN},n,Playback(sorry2) exten => _${VIRTPATTERN},n,Hangup() ; Define an extension that will get us into voicemail so that we can ; check it from outside. exten => ${EXTVMAIL},1,VoicemailMain() exten => ${EXTVMAIL},n,Hangup() ; ; This is the holiday menu. ; [ivrholiday] exten => s,1,Background(ivr/thank-you-for-calling&\ ivr/at-present-vacation&\ ivr/if-you-know-dial-any-time&\ ivr/party-no-answer-voicemail&\ ivr/if-dont-know-P1-for-dir) exten => s,2,WaitExten(10) ; The user can press 1 for the directory exten => 1,1,Goto(ivrdirectory,s,1) ; If they don't press a valid key, give them an error. exten => i,1,Playback(ivr/not-valid-extension) exten => i,n,Goto(ivrholiday,s,2) ; If the wait for a digit times out, say goodbye and hang up. exten => t,1,Playback(ivr/hasta-la-vista) exten => t,n,Hangup() ; Ring the extension that the user dialed. exten => _${EXTPATTERN},1,Goto(from-internal,${EXTEN},1) ; We optionally enable the virtual extensions from outside lines, if the ; virtual outside switch is on. exten => _${VIRTPATTERN},1,Gotoif($[${EXISTS(${VIRTOUTSIDE})}]?\ virtual-extensions,${EXTEN},1:) exten => _${VIRTPATTERN},n,Playback(sorry2) exten => _${VIRTPATTERN},n,Hangup() ; Define an extension that will get us into voicemail so that we can ; check it from outside. exten => ${EXTVMAIL},1,VoicemailMain() exten => ${EXTVMAIL},n,Hangup() ; ; This is The Mental Health Hotline menu. ; [ivrmental] exten => s,1,Background(ivr/mental-health-hotline) exten => s,2,WaitExten(10) ; The user can press 0 for the operator. This will make Dale happy. exten => 0,1,Goto(from-internal,0,1) ; The user can press 1 for the directory. exten => 1,1,Goto(ivrdirectory,s,1) ; If they don't press a valid key, give them an error. exten => i,1,Playback(ivr/not-valid-extension) exten => i,n,Goto(ivrmental,s,2) ; If the wait for a digit times out, say goodbye and hang up. exten => t,1,Playback(ivr/hasta-la-vista) exten => t,n,Hangup() ; Ring the extension that the user dialed (we do this by jumping to the ; from-internal context, as if one of the internal lines dialed an ; extension, so that we can use the same extension definitions found ; therein). exten => _${EXTPATTERN},1,Goto(from-internal,${EXTEN},1) exten => _${EXTPATTERN},n,Hangup() ; ; This is the IVR directory, where we look up the party's name and return ; their extension. We'll ask the caller to enter the first three letters ; of the party's last name. ; [ivrdirectory] exten => s,1,Background(ivr/dir-dial-three-letters) exten => s,2,WaitExten(20) ; If they don't dial a valid name, give them an error. exten => i,1,Playback(ivr/dir-dont-recognize-name) exten => i,n,Goto(ivrdirectory,s,2) ; If the wait for a name times out, say goodbye and hang up. exten => t,1,Playback(ivr/goodbye) exten => t,n,Hangup() ; Here, we can use a pattern match to match the first three letters of ; the party's last name. If the first one or two letters makes it unique, ; you can use the anymatch digit to blow away whatever else they type. ; Alternately, there's no need to listen for more digits, if you don't ; want to but it gives the impression we're a big-time organization. exten => _2XX,1,Playback(ivr/transfer-to-norm-cole) exten => _2XX,n,Goto(from-internal,601,1) exten => _9XX,1,Playback(ivr/transfer-to-ed-wilson) exten => _9XX,n,Goto(from-internal,600,1)