Skip to main content

Twilio

Purpose: Operational tool for phone numbers, call handling, and call data processing.

Last verified: December 2025


Account Details

  • Notes: Developer tool used to buy, manage and build phone numbers, dialling systems etc
  • Category: OPERATIONAL_TOOLS
  • Account type: CLIENT_OWNED, INTERNAL, CLIENT_ACCESS
  • Monthly cost: 5.00 GBP
  • Created: December 2025
  • Account owner: Ben Power

Phone Systems Overview

We have built three custom phone systems using Twilio:

  1. Simple Phone System - IVR menu with time-based routing, voicemail, and SMS
  2. Phone System with ElevenLabs AI - Same as simple system but includes AI assistant option
  3. Call Tracking System - Complex PPC attribution system with dynamic number insertion (needs work for client use)

GitHub Repository: https://github.com/automatestech/ppc-call-tracking

Scripts: See scripts/resources/twilio/ for account information fetching scripts and current phone system configuration.


1. Simple Phone System

Location: /Users/benpower/VSC/twilio voicemail/voicemail-project/

Purpose: Basic IVR system with time-based call routing, voicemail recording, and SMS website link delivery.

Features

  • IVR Menu: 3-option menu (DTMF input only)
    • Option 1: Speak to a human (time-based routing)
    • Option 2: Chat with AI assistant (placeholder)
    • Option 3: Receive website link via SMS
  • Business Hours Routing: Automatically forwards to personal phone during business hours, goes to voicemail after hours
  • Voicemail Recording: Records messages up to 120 seconds, sends SMS notification with recording link
  • SMS Integration: Sends website link via SMS with alphanumeric sender ID fallback
  • Whisper Messages: Plays message to recipient only when forwarding calls
  • Timezone Support: Automatic GMT/BST handling via moment-timezone

Architecture

Incoming Call

voicemail.protected.js (IVR Menu)

User Input (1, 2, or 3)

handle-user-input.protected.js

┌─────┴─────┬─────────┬──────────┐
│ │ │ │
1: Human 2: Robot 3: Website
│ │ │
├─Business? │ │
│ Yes│ No │ │
│ ↓ ↓ ↓ ↓
📞 📧 🤖 📱
Dial VM AI SMS

Functions

FunctionTypePurpose
voicemail.protected.jsProtectedEntry point - presents IVR menu
handle-user-input.protected.jsProtectedRoutes based on user selection
recording.jsPublicProcesses voicemail recordings, sends SMS
dial-status.jsPublicHandles no-answer scenarios
whisper.jsProtectedPlays whisper message to recipient

Configuration

Required Environment Variables (.env):

# Twilio Credentials
ACCOUNT_SID=ACxxxxx
AUTH_TOKEN=xxxxx

# Your personal phone (where calls forward to)
MY_PHONE_NUMBER=+447882002414

# Business Hours (optional, defaults shown)
TIMEZONE=Europe/London
WORK_WEEK_START=1 # Monday
WORK_WEEK_END=5 # Friday
WORK_HOUR_START=10 # 10:00 AM
WORK_HOUR_END=17 # 5:00 PM (exclusive)

# IVR Menu Text (optional, has defaults)
MENU_GREETING=Welcome to Pacing Agency, your marketing team.
MENU_OPTION_1=Press 1 to speak with someone. We are available Monday to Friday, 10 AM to 5 PM.
MENU_OPTION_2=Press 2 to chat with our AI assistant.
MENU_OPTION_3=Press 3 to receive a text message with a link to our website.
MENU_NO_INPUT=Sorry, we did not receive your selection. Please try again.
MENU_INVALID=We are sorry, we did not recognize your selection. Please try again.

# Call Routing Messages
CONNECTING_HUMAN=Connecting you now. Please hold.
VOICEMAIL_GREETING=Sorry, it's outside of our business hours. Please leave your name, details, and query, and we'll get back to you. Or visit us online at pacing dot agency and fill in our web form. Thanks.

# SMS Configuration
ALPHANUMERIC_SENDER_ID=MaxLocksmith # Optional, falls back to phone number
WEBSITE_SMS_BODY=Thanks for your interest in Pacing Agency! Visit us at: https://pacing.agency\n\nWe look forward to working with you!
WEBSITE_MESSAGE=Perfect! We will send you a text message with a link to our website in just a moment. Thank you for your interest in Pacing Agency!

Call Flow

During Business Hours (Option 1):

  1. Caller presses 1
  2. System says "Connecting you now. Please hold."
  3. Plays whisper message to recipient (if configured)
  4. Dials MY_PHONE_NUMBER
  5. If no answer after 24 seconds → goes to voicemail

Outside Business Hours (Option 1):

  1. Caller presses 1
  2. System says voicemail greeting
  3. Records message (max 120 seconds)
  4. Sends SMS to MY_PHONE_NUMBER with recording link

Option 2 (AI Assistant):

  • Currently dials a phone number (placeholder for ElevenLabs integration)
  • Configured via AI_PHONE_NUMBER environment variable

Option 3 (Website SMS):

  1. Caller presses 3
  2. System says website message
  3. Hangs up
  4. Sends SMS with website link to caller

Deployment

cd /Users/benpower/VSC/twilio\ voicemail/voicemail-project
npm install
twilio serverless:deploy

Configure phone number webhook:

twilio phone-numbers:update +447830303029 \
--voice-url="https://your-domain.twil.io/voicemail"

Testing

# Local testing
twilio serverless:start --ngrok=""

# View logs
twilio serverless:logs --tail

2. Phone System with ElevenLabs AI Option

Location: Same as Simple Phone System (/Users/benpower/VSC/twilio voicemail/voicemail-project/)

Purpose: Extends the simple phone system with ElevenLabs AI assistant integration.

Features

All features from Simple Phone System, plus:

  • ElevenLabs AI Assistant: Option 2 connects to ElevenLabs AI agent
  • AI Phone Number: Configured via AI_PHONE_NUMBER environment variable
  • Seamless Integration: AI option works alongside human and SMS options

Configuration

Additional Environment Variable:

# ElevenLabs AI Agent Phone Number
AI_PHONE_NUMBER=+447846895635

# Optional: Custom message when connecting to AI
CONNECTING_AI=Connecting you to our AI assistant now.

Implementation Details

In handle-user-input.protected.js:

case '2':
// Option 2: Talk to AI robot (ElevenLabs Agent)
twiml.say({ language }, connectingAI);

// Dial ElevenLabs agent number
const dial = twiml.dial({ timeout: 30 });
dial.number(aiPhoneNumber);
break;

How It Works

  1. Caller presses 2 in IVR menu
  2. System says "Connecting you to our AI assistant now."
  3. Dials the ElevenLabs AI agent phone number
  4. Caller speaks with AI assistant
  5. AI handles conversation using ElevenLabs Conversation API

Note: The ElevenLabs agent must be configured separately in the ElevenLabs dashboard. The phone number provided is the Twilio number that connects to the ElevenLabs agent.

Future Enhancement

The system is designed to support Twilio's ConversationRelay for direct WebSocket integration:

case '2':
twiml.connect()
.conversationRelay({
url: 'wss://your-websocket-server.com',
ttsProvider: 'ElevenLabs',
voice: 'zNsotODqUhvbJ5wMG7Ei'
});
break;

This would require:

  • WebSocket server setup
  • ElevenLabs API integration
  • Conversation logic implementation

3. Call Tracking System (Complex - Needs Work)

Location: /Users/benpower/VSC/twilio calltracking/

Purpose: Enterprise-grade PPC call tracking with dynamic number insertion (DNI), full attribution tracking, and IVR system.

Status: ⚠️ Needs work before using for clients - Complex system requiring careful setup and testing.

Features

  • Dynamic Number Insertion (DNI): Unique tracking numbers per website visitor
  • PPC Attribution: Captures gclid, UTM parameters, user ID from every ad click
  • Silent Call Forwarding: Routes calls through IVR without "connecting" messages
  • Complete Tracking: Every call event (IVR menu, selections, voicemail) includes ad attribution
  • n8n Integration: Real-time webhooks to automation workflows
  • Multi-Client Support: Manage multiple clients with separate number pools
  • IVR System: Professional menu with business hours routing and voicemail
  • Admin Dashboard: Call reports and analytics with password protection
  • Cloudflare Integration: Edge API for number pool management
  • R2 Storage: Permanent call record storage

Architecture

Website Visitor (Google Ad Click)
↓ [gclid captured]
Call Tracking Script (JavaScript)
↓ [requests tracking number]
Cloudflare Worker (Edge API)
↓ [allocates number from pool]
Visitor Calls Tracking Number
↓ [silent forward]
Twilio Functions (/call-forward)
↓ [forwards to main business number]
IVR Menu (Main Business Number)
↓ [Press 1 for human]
Your Personal Phone
|
└──> n8n Webhooks (every step)
└──> Google Sheets
└──> CRM Updates
└──> Analytics

Components

ComponentTechnologyPurpose
Client-SideVanilla JavaScriptDNI script, captures visitor data
API LayerCloudflare WorkersSecure number pool management
Call HandlingTwilio FunctionsCall forwarding, IVR, voicemail
Session StorageCloudflare KVActive sessions (30 min TTL)
Call RecordsCloudflare R2Permanent call history
Integrationn8n WebhooksReal-time event notifications

Key Innovation: Attribution Persistence

The Challenge: When tracking number forwards to main business number, Twilio creates a NEW call with a different CallSid.

The Solution: Dual-key storage strategy

  • Store attribution by CallSid (for immediate lookup)
  • Store attribution by caller number (for forwarded call lookup)
  • Attribution persists across call forwards!

n8n Webhook Events

All events sent to configured webhook URL with full attribution:

EventTriggerAttribution Included?
call_initiatedTracking number called✅ YES
ivr_menu_presentedIVR menu starts✅ YES (via caller lookup)
ivr_selectionUser presses 1/2/3✅ YES (via caller lookup)
call_dial_statusCall status changes✅ YES
voicemail_recordedVoicemail left✅ YES (via caller lookup)

Example Webhook Payload:

{
"event": "ivr_selection",
"data": {
"callSid": "CA1234567890",
"from": "+15551234567",
"to": "+1111111111",
"selection": "1_human",
"gclid": "ABC123",
"userId": "user_xyz",
"utmSource": "google",
"utmMedium": "cpc",
"utmCampaign": "summer_sale",
"utmTerm": "marketing agency",
"landingPage": "https://yoursite.com/page",
"referrer": "https://google.com",
"clientId": "your_client_id"
},
"timestamp": "2025-11-17T21:30:00Z"
}

Configuration

Cloudflare Worker (wrangler.toml):

  • KV namespaces: SESSIONS, CLIENTS, POOL
  • R2 bucket: call records storage
  • Secrets: ADMIN_API_KEY, WHITELISTED_DOMAINS

Twilio Functions (.env):

# Twilio Credentials
ACCOUNT_SID=ACxxxxx
AUTH_TOKEN=xxxxx

# Cloudflare Worker
CLOUDFLARE_WORKER_URL=https://your-worker-name.workers.dev
CF_API_TOKEN=your_cloudflare_api_token

# Client Configuration
CLIENT_YOUR_CLIENT_NUMBERS=+1111111111,+2222222222,+3333333333
CLIENT_YOUR_CLIENT_FORWARD_TO=+4444444444
CLIENT_YOUR_CLIENT_CONNECTING_MESSAGE=SILENT

# n8n Webhook
N8N_WEBHOOK_URL=https://your-n8n.com/webhook/your-webhook-id

# Admin Dashboard
DASHBOARD_PASSWORD=YourSecurePassword123!
DASHBOARD_SECRET=your_generated_secret_key
DOMAIN_NAME=https://your-project-name.twil.io

Deployment

Step 1: Deploy Cloudflare Worker

cd cloudflare-worker
wrangler login
wrangler kv namespace create "SESSIONS"
wrangler kv namespace create "CLIENTS"
wrangler kv namespace create "POOL"
wrangler r2 bucket create your-call-records
wrangler secret put ADMIN_API_KEY
wrangler deploy

Step 2: Configure Client in KV

wrangler kv key put \
--namespace-id=YOUR_CLIENTS_KV_ID \
"client:your_client_id" \
'{
"clientId": "your_client_id",
"name": "Your Business Name",
"numbers": ["+1111111111", "+2222222222", "+3333333333"],
"forwardTo": "+4444444444",
"n8nWebhookUrl": "https://your-n8n.com/webhook/your-id",
"active": true
}'

Step 3: Deploy Twilio Functions

cd voicemail-project
cp ENV-TEMPLATE.txt .env
# Edit .env with your credentials
npm install
twilio serverless:deploy

Step 4: Configure Phone Numbers

# Tracking numbers → call-forward
twilio phone-numbers:update +1111111111 --voice-url="https://YOUR-DOMAIN.twil.io/call-forward"

# Main business number → IVR
twilio phone-numbers:update +4444444444 --voice-url="https://YOUR-DOMAIN.twil.io/voicemail"

Step 5: Add Script to Website

<script src="https://your-worker-name.workers.dev/call-tracking.js"></script>
<script>
PacingCallTracking.init({
clientId: 'your_client_id',
apiEndpoint: 'https://your-worker-name.workers.dev',
phoneSelector: '.phone-number',
enableGTM: true
});
</script>

Admin Dashboard

Access: https://your-project-name.twil.io/admin-dashboard

Features:

  • Password-protected (24-hour token sessions)
  • Real-time pool status
  • Active sessions monitoring
  • Campaign performance analytics
  • Auto-refresh every 30 seconds

Configuration:

  • Dashboard file: admin-dashboard.js (NOT .protected.js)
  • Cloudflare Worker CORS must allow Authorization header
  • DOMAIN_NAME must be set in Twilio .env file

Cost Breakdown

ServiceCost/MonthNotes
Twilio Numbers (3-5)£3-5£1/number/month
Twilio Voice Minutes£15-30£0.013/min (UK)
Twilio SMS£1-2£0.04/SMS (UK)
Cloudflare WorkersFREEFree tier: 100k req/day
Cloudflare KVFREEFree tier: 1GB storage
Cloudflare R2FREEFree tier: 10GB storage
Total~£20-40/moScales with usage

Commercial call tracking alternatives: £300-500/month 💸

Documentation

Complete documentation available in /Users/benpower/VSC/twilio calltracking/:

  • README.md - Overview and quick start
  • ARCHITECTURE.md - System architecture deep dive
  • DEPLOYMENT-GUIDE.md - Step-by-step deployment
  • INTEGRATION-DOCUMENTATION.md - Complete API reference
  • ADMIN-DASHBOARD-SETUP.md - Dashboard configuration
  • TWILIO-REFERENCE.md - Twilio patterns and best practices

Known Issues / Needs Work

⚠️ Before using for clients, address:

  1. Error Handling: Add comprehensive error handling for edge cases
  2. Rate Limiting: Test and tune rate limits for production traffic
  3. Number Pool Exhaustion: Implement better handling when pool is full
  4. Client Onboarding: Create streamlined client setup process
  5. Testing: Comprehensive test suite for all call flows
  6. Monitoring: Enhanced logging and alerting
  7. Documentation: Client-facing setup guide
  8. Support: Support process and escalation paths

n8n Automations

Call Data Processing Workflows

Two active workflows process Twilio call data for MTL client:

WorkflowIDPurpose
Process Call Data LIVE TWILIOBr8hV6MAxI3ZqR2JProcesses Twilio call recordings with full transcription and AI analysis
Process Call Data LIVETsmCwp84TKbHa62oProcesses call data from Google Sheets

Process Call Data LIVE TWILIO Workflow:

This workflow automates comprehensive call analysis:

  1. Call Recording Download: Downloads call recordings from Twilio
  2. Transcription: Uses ElevenLabs API to transcribe audio to text
  3. AI Analysis: Uses Google Vertex AI (Gemini) to analyze call transcription and extract:
    • Service category and specific service needed
    • Call quality issues (connection problems, audio quality)
    • Likelihood of booking (1-10 scale)
    • Caller name and address
    • Reason for call (detailed summary)
    • Spam detection and likelihood
    • Whether call is about existing booking
    • Estimated service price quoted
    • Referral information (if caller referred elsewhere)
    • Appointment booking details (date, time, address)
    • Follow-up actions required
  4. Data Storage: Results stored in Google Sheets for review and further processing
  5. Google Ads Integration: Processed calls can trigger offline conversion uploads to Google Ads

Key Features:

  • Automated transcription of call recordings
  • AI-powered call classification and analysis
  • Extraction of structured data from unstructured call conversations
  • Integration with Google Sheets for data review
  • Supports locksmith service call analysis with specific business logic

Workflow Tags: MTL (client assignment)

See tools/n8n.md for complete workflow documentation and scripts/resources/n8n/workflows/ for workflow backups.


Twilio Reference & Best Practices

For complete Twilio patterns, code examples, and best practices, see:

/Users/benpower/VSC/twilio calltracking/TWILIO-REFERENCE.md

This comprehensive reference includes:

  • Twilio Functions basics and structure
  • TwiML patterns (Say, Gather, Dial, Record, etc.)
  • REST API patterns
  • Call recording and status callbacks
  • SMS/Messaging patterns
  • Error handling
  • Common patterns and best practices
  • Testing and debugging