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.

Bad: Slow synchronous processing
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!
});
Good: Fast response, async processing
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.

Good: Fallback after timeout
<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.

Comprehensive Logging
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.

Input Validation
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.

Bad: Too long
<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>
Good: Concise and clear
<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.

Confirmation Pattern
<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.