Building Your Auto Attendant

After you have designed your auto attendant, there are three things you need to do to make it work properly:

We will start by talking about recordings.

Recording Prompts

Recording prompts for a telephone system is a critical task. This is what your callers will hear when they interact with your system, and the quality and professionalism of these prompts will reflect on your organization.

Asterisk is very flexible in this regard and can work with many different audio formats. We have found that, in general, the most useful format to use is WAV. Files saved in this format can be of many different kinds, but only one type of WAV file will work with Asterisk: files must be encoded in 16-bit, 8000 Hz, mono format.

There are essentially two ways to get prompts into a system. One is to record sound files in a studio or on a PC, and then move those files into the system. A second way is to record the prompts directly onto the system using a telephone set. We prefer the second method.

Our advice is this: don’t get hung up on the complexities of recording audio through a PC or in a studio.[137] It is generally not necessary. A telephone set will produce excellent-quality recordings, and the reasons are simple: the microphone and electronics in a telephone are carefully designed to capture the human voice in a format that is ideal for transmission on telephone networks, and therefore a phone set is also ideal for doing prompts. The set will capture the audio in the correct format, and will filter out background noise and normalize the decibel level.

Note

Yes, a properly produced studio prompt will be superior to a prompt recorded over a telephone, but if you don’t have the equipment or experience, take our advice and use a telephone to do your recordings, because a poorly produced studio prompt will be much worse.

Using the dialplan to create recordings

The simplest method of recording prompts is to use the Record() application. For example:

[context_for_my_handset]
exten => 101,1,Playback(vm-intro)
exten => 101,n,Record(maingreeting.wav)
exten => 101,n,Wait(2)
exten => 101,n,Playback(maingreeting)
exten => 101,n,Hangup

This extension plays a prompt, issues a beep, makes a recording, and plays that recording back.[138] It’s notable that the Record() application takes the entire filename as its argument, while the Playback() application excludes the filetype extension (.wav, .gsm, etc.). This is because the Record() application needs to know which format the recording should be made in, while the Playback() application does not. Instead, Playback() automatically selects the best audio format available, based upon the codec your handset is using and the formats available in the sounds folder (for example, if you have a maingreeting.wav and a maingreeting.gsm file in your sounds folder, Playback() will select the one that requires the least CPU to play back to the caller).

You’ll probably want a separate extension for recording each of the prompts, possibly hidden away from your normal set of extensions, to avoid a mistyped extension from wiping out any of your current menu prompts. If the number of prompts that you have is large, repeating this extension with slight modifications for each will get tedious, but there are ways around that. We’ll show you how to make your prompt recording more intelligent in Chapter 17, Interactive Voice Response, but for now, this method will suffice.

The Dialplan

Here is the code required to create the auto attendant that we designed earlier. We will often use blank lines before labels within an extension in order to make the dialplan easier to read, but note that just because there is a blank line does not mean there is a different extension:

[main_menu]

exten => s,1,Verbose(1, Caller ${CALLERID(all)} has entered the auto attendant)
    same => n,Answer()

; this sets the inter-digit timer
    same => n,Set(TIMEOUT(digit)=2)

; wait one second to establish audio
    same => n,Wait(1)

; If Mon-Fri 9-5 goto label daygreeting
    same => n,GotoIfTime(9:00-17:00,mon-fri,*,*?daygreeting:afterhoursgreeting)

    same => n(afterhoursgreeting),Background(after-hours) ; AFTER HOURS GREETING
    same => n,Goto(menuprompt)

    same => n(daygreeting),Background(daytime)   ; DAY GREETING
    same => n,Goto(menuprompt)

    same => n(menuprompt),Background(main-menu) ; MAIN MENU PROMPT
    same => n,WaitExten(4)                      ; more than 4 seconds is probably
                                                ; too much
    same => n,Goto(0,1)                         ; Treat as if caller has pressed '0'

exten => 1,1,Verbose(1, Caller ${CALLERID(all)} has entered the sales queue)
    same => n,Goto(Queues,7002,1)     ; Sales Queue - see Chapter 13 for details

exten => 2,1,Verbose(1, Caller ${CALLERID(all)} has entered the service queue)
    same => n,Goto(Queues,7001,1)     ; Service Queue - see Chapter 13 for details

exten => 3,1,Verbose(1, Caller ${CALLERID(all)} has requested address and fax info)
    same => n,Background()            ; Address and fax info
    same => n,Goto(s,menuprompt)      ; Take caller back to main menu prompt

exten => #,1,Verbose(1, Caller ${CALLERID(all)} is entering the directory)
    same => n,Directory(default)   ; Send the caller to the directory.
                                   ; Use InternalSets as the dialing context

exten => 0,1,Verbose(1, Caller ${CALLERID(all)} is calling the operator)
    same => n,Dial(SIP/operator)      ; Operator extension/queue

exten => i,1,Verbose(1, Caller ${CALLERID(all)} has entered an invalid selection)
    same => n,Playback(invalid)
    same => n,Goto(s,menuprompt)

exten => t,1,Verbose(1, Caller ${CALLERID(all)} has timed out)
    same => n,Goto(0,1)


; You will want to have a pattern match for the various extensions
; that you'll allow external callers to dial
; BUT DON'T JUST INCLUDE THE LocalSets CONTEXT
; OR EXTERNAL CALLERS WILL BE ABLE TO MAKE CALLS OUT OF YOUR SYSTEM

; WHATEVER YOU DO HERE, TEST IT CAREFULLY TO ENSURE EXTERNAL CALLERS
; WILL NOT BE ABLE TO DO ANYTHING BUT DIAL INTERNAL EXTENSIONS

exten => _1XX,1,Verbose(1,Call to an extension starting with '1'
    same => n,Goto(InternalSets,${EXTEN},1)

Delivering Incoming Calls to the Auto Attendant

Any call coming into the system will enter the dialplan in the context defined for whatever channel the call arrives on. In many cases this will be a context named incoming, or from-pstn, or something similar. The calls will arrive either with an extension (as would be the case with a DID) or without one (which would be the case with a traditional analog line).

Whatever the name of the context, and whatever the name of the extension, you will want to send each incoming call to the menu. Here are a few examples:

[from-pstn] ; an analog line that has context=from-pstn (typically a DAHDI channel)
exten => s,1,Goto(main_menu,s,1)

[incoming] ; a DID coming in on a channel with context=incoming (PRI, SIP, or IAX)
exten => 4169671111,1,Goto(main_menu,s,1)

Depending on how you configure your incoming channels, you will generally want to use the Goto() application if you want to send the call to an auto attendant. This is far neater than just coding everything in the incoming context.

IVR

We’ll cover Interactive Voice Response (IVR) in more depth in Chapter 17, Interactive Voice Response but before we do that, we’re going to talk about something that is essential to any IVR: database integration is the subject of the next chapter.



[137] Unless you are an expert in these areas, in which case go for it!

[138] The vm-intro prompt isn’t perfect (it asks you to leave a message), but it’s close enough for our purposes. The usage instructions at least are correct: press pound to end the recording. Once you’ve gotten the hang of recording prompts, you can go back, record a custom prompt, and change priority 1 to reflect more appropriate instructions for recording your own prompts.