Asterisk IVR: Looping IVR menu (Latest Versions)
Updated guide for modern Asterisk (PJSIP era): looping ivr menu with real configs, common mistakes, and troubleshooting steps.
A looping IVR menu is a common requirement in real business phone systems. If the caller does not press any key, or presses an invalid key, the IVR should repeat the menu instead of disconnecting immediately.
But looping must be done carefully: infinite loops frustrate callers and can overload queues and trunks. A production IVR needs controlled looping with limits and a fallback path.
This guide shows how to build a clean
looping IVR menu in modern Asterisk (PJSIP)
using safe retry counters, proper handling of i and t,
and a final fallback to operator/queue/voicemail.
What Does “Looping IVR” Mean?
Looping IVR means:
- Caller hears menu prompt
- If no input → replay menu
- If invalid input → replay menu
- After N attempts → route to fallback (operator/queue/voicemail)
This improves the customer experience because callers are guided, not dropped.
Why Looping Needs Limits
An IVR without limits causes problems:
- Callers get trapped and hang up
- Inbound trunks stay occupied longer
- Queues get overloaded with “stuck” calls
- Agent availability becomes harder to manage
Best practice: loop only 2–3 times, then route to help.
Core Dialplan Events: i and t
- i → invalid input (caller pressed wrong key)
- t → timeout (caller pressed nothing)
These two extensions are the key to looping behavior.
Production-Safe Looping IVR Template
This template loops a maximum of 3 times and then routes to fallback.
[main-ivr]
exten => s,1,Answer()
same => n,Set(TIMEOUT(digit)=3)
same => n,Set(TIMEOUT(response)=6)
; Initialize / increment loop counter
same => n,Set(IVR_TRIES=${IF($["${IVR_TRIES}"=""]?1:$[${IVR_TRIES}+1])})
same => n,NoOp(IVR_TRIES=${IVR_TRIES})
; If exceeded max tries, go to fallback
same => n,GotoIf($[${IVR_TRIES} > 3]?fallback,1)
; Play menu and wait for digits
same => n,Background(custom/ivr/main-menu)
same => n,WaitExten(6)
; Valid options
exten => 1,1,Playback(custom/ivr/connecting-sales)
same => n,Queue(sales,tT)
same => n,Hangup()
exten => 2,1,Playback(custom/ivr/connecting-support)
same => n,Queue(support,tT)
same => n,Hangup()
exten => 0,1,Goto(fallback,1)
; Invalid input → replay menu
exten => i,1,Playback(custom/ivr/invalid)
same => n,Goto(main-ivr,s,1)
; No input → replay menu
exten => t,1,Playback(custom/ivr/no-input)
same => n,Goto(main-ivr,s,1)
; Final fallback after too many loops
exten => fallback,1,Playback(custom/ivr/please-hold-operator)
same => n,Dial(PJSIP/1000,20)
same => n,Voicemail(1000@default,u)
same => n,Hangup()
Why Background() + WaitExten() Is Used
- Background() plays the menu prompt
- It listens for DTMF while audio plays
- WaitExten() waits after prompt ends
This combination ensures callers can press keys at any time.
Alternative Looping Style: Use a Separate “menu” Extension
Some dialplans are cleaner when menu playback is isolated.
[main-ivr]
exten => s,1,Answer()
same => n,Goto(menu,1)
exten => menu,1,Set(IVR_TRIES=${IF($["${IVR_TRIES}"=""]?1:$[${IVR_TRIES}+1])})
same => n,GotoIf($[${IVR_TRIES} > 3]?fallback,1)
same => n,Background(custom/ivr/main-menu)
same => n,WaitExten(6)
exten => i,1,Playback(custom/ivr/invalid)
same => n,Goto(menu,1)
exten => t,1,Playback(custom/ivr/no-input)
same => n,Goto(menu,1)
This keeps the loop logic in one place.
Common Looping IVR Problems and Fixes
IVR Loops Forever
- No IVR_TRIES counter
- Counter resets incorrectly
- Fix: Set counter once per call and increment safely
Caller Cannot Press Keys During Prompt
- Using Playback() instead of Background()
- DTMF mode mismatch on trunk
Looping Works Internally But Not From Provider
- External DTMF not reaching Asterisk (RFC4733/INFO/inband issue)
- Codec mismatch affecting inband DTMF
Best Practices for Looping IVRs
- Loop max 2–3 times, then route to help
- Always include
iandthandlers - Provide operator/queue fallback after max tries
- Keep prompts short to reduce call duration
- Test from external numbers, not only internal phones
A looping IVR should guide callers, not trap them.
Key Takeaway
A safe looping IVR in Asterisk is built using:
Background(), WaitExten(),
and controlled routing from i (invalid)
and t (timeout).
Always limit loops using a counter like IVR_TRIES,
and provide a final fallback path so every caller
reaches a helpful destination.
Want to see API-driven CRM + Telecom workflows in action? Try the WhatsApp bot or explore the demos.
Comments (0)
Be the first to comment.