USSD Menu Patterns
Most USSD services reuse a handful of menu shapes. This guide collects the common patterns — root menus, input capture, pagination, and confirmation — with copy-ready examples.
🧭 Root Menu
The entry screen when text is empty.
CON Welcome to Acme
1. Check balance
2. Buy airtime
3. Send money
0. Exit
def root():
return "CON Welcome to Acme\n1. Check balance\n2. Buy airtime\n3. Send money\n0. Exit"
⌨️ Input Capture
Prompt for a value, then act on the next request.
// step: ask
if (text === '2') return 'CON Enter amount to top up:';
// step: receive (text === '2*100')
const amount = text.split('*')[1];
return `END Topping up KES ${amount}. SMS confirmation to follow.`;
✅ Confirmation Pattern
Always confirm actions that move money or change data.
CON Send KES 500 to +254712345678?
1. Confirm
2. Cancel
def confirm_step(steps):
if steps[-1] == '1':
return "END Sent KES 500. Ref TX9281."
return "END Cancelled."
📃 Pagination
When a list exceeds ~5 items, page it with "More" and "Back".
CON Select a biller (1/2)
1. Water
2. Electricity
3. Internet
9. More
0. Back
function page(items, pageNum, size = 3) {
const start = pageNum * size;
const lines = items.slice(start, start + size).map((it, i) => `${i + 1}. ${it}`);
if (start + size < items.length) lines.push('9. More');
lines.push('0. Back');
return 'CON Select a biller\n' + lines.join('\n');
}
🔢 Numbered Navigation Convention
| Key | Meaning |
|---|---|
1–5 | Menu options |
9 | Next page / More |
0 | Back / Exit |
00 | Return to main menu |
Keeping these consistent across screens lets users navigate without reading every prompt.
💡 Best Practices
- Reuse one navigation convention everywhere (
0back,9more). - Paginate at 5 items rather than overflowing a screen.
- Confirm before committing money-moving actions.
- End with
ENDthe moment the task completes. - Keep option labels to one or two words.
📚 Related Resources
Last Updated: May 2026