Skip to main content

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​

KeyMeaning
1–5Menu options
9Next page / More
0Back / Exit
00Return to main menu

Keeping these consistent across screens lets users navigate without reading every prompt.

💡 Best Practices​

  • Reuse one navigation convention everywhere (0 back, 9 more).
  • Paginate at 5 items rather than overflowing a screen.
  • Confirm before committing money-moving actions.
  • End with END the moment the task completes.
  • Keep option labels to one or two words.

Last Updated: May 2026