XML Best Practices
Build robust, scalable, and user-friendly voice applications with these proven patterns and recommendations for Vobiz XML development.
Performance Optimization
Fast Webhook Responses
Return XML within 1-2 seconds. Slow webhooks create dead air and frustrated callers.
app.post('/answer', async (req, res) => {
// DON'T: Heavy processing blocks the response
await sendEmail(req.body.From);
await logToDatabase(req.body);
await fetchCustomerHistory(req.body.From);
res.send(xml); // Too slow!
});app.post('/answer', (req, res) => {
// DO: Return XML immediately
res.send(xml);
// Process heavy tasks asynchronously
processCallWebhook(req.body).catch(err => log(err));
});Cache Frequently Used Data
Cache business hours, routing rules, audio URLs, and other static data. Don't query the database on every webhook—use Redis, memcached, or in-memory caching.
Optimize Audio Files
Use 8kHz mono MP3 files. Serve from a CDN. Higher quality doesn't improve telephony audio but increases latency and bandwidth costs.
Reliability & Error Handling
Always Provide Fallback Paths
Every Gather and Dial should have a fallback for timeouts or failures.
<Response>
<Gather numDigits="1" timeout="10" action="/menu">
<Speak>Press 1 for sales, 2 for support.</Speak>
</Gather>
<!-- Fallback if no input received -->
<Speak>We didn't receive your selection. Transferring to operator.</Speak>
<Dial>+14155550000</Dial>
</Response>Validate XML Syntax
Use XML validators in development and automated tests. Malformed XML causes call failures.
- • Ensure all tags are properly closed
- • Escape special characters (&, <, >, ", ')
- • Use UTF-8 encoding declaration
- • Test with real XML parsers, not string validation
Handle Network Failures Gracefully
If Vobiz can't reach your webhook URL (timeout, DNS failure, SSL error), the call will drop. Use monitoring tools, health checks, and load balancers to ensure high availability.
Log Everything
Log all incoming webhooks, generated XML, and errors. Use CallUUID to trace call flows.
app.post('/answer', (req, res) => {
const callId = req.body.CallUUID;
logger.info('Incoming call', {
callId,
from: req.body.From,
to: req.body.To
});
const xml = generateXML(req.body);
logger.info('Returning XML', { callId, xml });
res.send(xml);
});Security
Validate Webhook Signatures
Verify that webhook requests actually come from Vobiz by checking signatures or IP whitelist. This prevents spoofed requests.
Use HTTPS
All webhook URLs must use HTTPS. HTTP webhooks expose call data and may be blocked.
Sanitize User Input
Don't trust DTMF digits, caller IDs, or other webhook data. Validate and sanitize before using in database queries or business logic.
app.post('/menu', (req, res) => {
const digit = req.body.Digits;
// Validate input is a single digit
if (!/^[0-9]$/.test(digit)) {
return res.send(errorXML);
}
// Safe to use now
routeToQueue(digit);
});Protect Sensitive Data
Never speak credit card numbers, passwords, or SSNs in TTS. Don't log PII without encryption. Use secure storage for call recordings containing sensitive information.
User Experience
Keep Prompts Concise
Callers lose attention after 15-20 seconds. Break long messages into chunks.
<Speak>
Welcome to ABC Company, provider of enterprise software solutions
since 1995. We offer 24/7 support, training, consulting, and managed
services. For sales press 1, for support press 2, for billing press 3...
</Speak><Speak>
Welcome to ABC Company. Press 1 for sales, 2 for support, or 0 for operator.
</Speak>Provide Clear Instructions
Tell callers exactly what to do. "Press pound when done" or "Say yes or no" is better than assuming they know.
Allow Menu Repetition
Offer a "Press 9 to repeat this menu" option. Callers often miss options the first time.
Set Appropriate Timeouts
For simple menus, 10 seconds is reasonable. For account numbers or complex input, allow 15-20 seconds. Too short frustrates users; too long wastes time.
Confirm Critical Actions
Before processing payments, canceling services, or other important actions, read back the input and ask for confirmation.
<Response>
<Speak>You entered account number 1-2-3-4-5-6. Press 1 to confirm or 2 to re-enter.</Speak>
<Gather numDigits="1" action="/confirm"/>
</Response>Test with Real Users
Have colleagues or beta users call your IVR. You'll discover confusing prompts, unclear options, and timing issues that aren't obvious during development.