← All Tutorials

How to Set Up ViciDial Auto-Dial (Predictive, Ratio & Progressive)

ViciDial Administration Intermediate 14 min read #90

Master ViciDial's three auto-dial modes with production-ready configurations, database tuning, and real-world troubleshooting for enterprise call centers

Prerequisites

Before proceeding, ensure you have:

Understanding ViciDial Auto-Dial Modes

ViciDial offers three fundamentally different calling strategies:

Each mode has different CPU, database, and channel requirements. Predictive uses the most resources but achieves highest contact rates.

Section 1: Database Configuration & Prerequisites

Create Your Campaign

Access the ViciDial admin interface:

# SSH into your ViciDial server
ssh -i your_key.pem [email protected]

# Verify MySQL connectivity
mysql -u root -p asterisk -e "SELECT * FROM vicidial_campaigns LIMIT 1;"

Insert a new campaign via admin panel (/vicidial/admin.php) or via MySQL:

USE asterisk;

INSERT INTO vicidial_campaigns (
  campaign_id,
  campaign_name,
  campaign_description,
  dial_method,
  phone_number_format,
  dispo_group_id,
  campaign_status,
  auto_dial_level,
  dial_timeout,
  call_volume_group,
  lead_recycle_method,
  drop_percentage,
  local_call_time,
  min_ingroup_agents,
  scheduled_callbacks,
  test_call_flag
)
VALUES (
  'PREDICTIVE_01',
  'Predictive Campaign Test',
  'High-volume predictive outbound campaign',
  'INBOUND',
  'US',
  '1',
  'ACTIVE',
  '0.8',
  '45',
  'default',
  'DISABLED',
  '5',
  'GMT',
  '1',
  'ENABLED',
  'N'
);

Key field explanations:

Configure Dialing Parameters

Update the vicidial_campaigns table with auto-dial specifics:

UPDATE vicidial_campaigns 
SET auto_dial_level = 0.8,
    dial_timeout = 45,
    drop_percentage = 8,
    scheduled_callbacks = 'ENABLED'
WHERE campaign_id = 'PREDICTIVE_01';

Verify the campaign is properly configured:

mysql -u root -p asterisk -e "SELECT campaign_id, campaign_name, dial_method, auto_dial_level, drop_percentage FROM vicidial_campaigns WHERE campaign_id = 'PREDICTIVE_01';"

Section 2: Asterisk SIP/Carrier Configuration

Configure Outbound Carrier Trunks

Edit the carrier configuration in /etc/asterisk/sip-vicidial.conf:

[CARRIER_OUTBOUND_01](!)
type=friend
host=123.45.67.89
port=5060
secret=YourSecretPassword123
fromuser=vicidial
fromdomain=123.45.67.89
dtmfmode=rfc2833
disallow=all
allow=ulaw,alaw
context=from-internal
qualify=yes
qualify_freq=60
maxcallbitrate=128
nat=no
canreinvite=no
directmedia=no
progressinband=yes

Create a production-safe carrier entry:

[carrier_sirius](CARRIER_OUTBOUND_01)
host=carrier.sirius.com
secret=SiriusCarrierSecret999
fromuser=vicidial_client_001
fromdomain=carrier.sirius.com

Configure Dial Plan Extensions

Edit /etc/asterisk/extensions-vicidial.conf to add outbound dialing routes:

[from-internal]
exten => _1NXXNXXXXXX,1,NoOp(ViciDial Outbound - ${EXTEN})
same => n,Set(CHANNEL(hangup_handler_push)=hangup,s,1)
same => n,Dial(SIP/${EXTEN}@carrier_sirius,45,TtKk)
same => n,Hangup()
same => n,Busy()
same => n,Unavailable()

Load and Verify Asterisk Configuration

# Backup current config
cp /etc/asterisk/extensions-vicidial.conf /etc/asterisk/extensions-vicidial.conf.backup

# Reload Asterisk dialplan
asterisk -rx "dialplan reload"

# Check for syntax errors
asterisk -rx "dialplan show from-internal" | head -20

# Verify carrier registration
asterisk -rx "sip show peers" | grep carrier_sirius

Expected output should show your carrier with UNREACHABLE or OK status (OK is ideal):

carrier_sirius/1234567890    123.45.67.89:5060      D   yes          yes     OK

Section 3: Predictive Dialing Setup

Understanding Predictive Algorithm

ViciDial's predictive dialer uses a dynamic pacing algorithm. The system:

  1. Monitors agent availability in real-time
  2. Dials calls ahead of agent availability
  3. Adjusts dial rate based on answer rates, talk time, and wrap-up time
  4. Aims to minimize agent idle time while staying within drop percentage limits

Set Campaign to Predictive Mode

Access /vicidial/admin.php → Campaigns → Select your campaign → Edit

Or update via SQL:

UPDATE vicidial_campaigns 
SET 
  dial_method = 'INBOUND',
  auto_dial_level = 0.85,
  drop_percentage = 8,
  scheduled_callbacks = 'ENABLED',
  lead_recycle_method = 'DISABLED',
  pause_dialing = 'N'
WHERE campaign_id = 'PREDICTIVE_01';

Configure Predictive Parameters in vicidial_settings

Edit the ViciDial system settings table:

UPDATE vicidial_settings 
SET 
  predictive_dialer_flag = '1',
  predictive_answer_rate = '45',
  predictive_drop_rate_threshold = '3',
  predictive_cpu_limit = '90',
  outbound_autodial = '1'
WHERE setting_name = 'ViciDial';

Parameter definitions:

Configure the Predictive Dialer Service

The ViciDial Predictive Dialer runs as a background service. Check if it's active:

# Check if vicidial_dialer.pl is running
ps aux | grep vicidial_dialer.pl | grep -v grep

# If not running, start it manually
/usr/share/astguiclient/vicidial_dialer.pl > /var/log/asterisk/vicidial_dialer.log 2>&1 &

# Make permanent via cron (check root crontab)
crontab -e

# Add this line to restart dialer if it crashes:
* * * * * /usr/share/astguiclient/check_vicidial_process.sh > /dev/null 2>&1

Create Campaign-Specific Lead Lists

Prepare your phone number list. Insert leads into the vicidial_list table:

USE asterisk;

INSERT INTO vicidial_list (
  lead_id,
  lead_phone_number,
  lead_phone_number_2,
  first_name,
  last_name,
  email,
  campaign_id,
  list_id,
  vendor_lead_code,
  status,
  phone_code,
  phone_number_formatted
)
VALUES
(NULL, '5551234567', '', 'John', 'Doe', '[email protected]', 'PREDICTIVE_01', '1', 'CODE001', 'NEW', '555', '555-123-4567'),
(NULL, '5559876543', '', 'Jane', 'Smith', '[email protected]', 'PREDICTIVE_01', '1', 'CODE002', 'NEW', '555', '555-987-6543'),
(NULL, '5552223333', '', 'Bob', 'Johnson', '[email protected]', 'PREDICTIVE_01', '1', 'CODE003', 'NEW', '555', '555-222-3333');

-- Verify insertion
SELECT COUNT(*) FROM vicidial_list WHERE campaign_id = 'PREDICTIVE_01' AND status = 'NEW';

Monitor Predictive Dialing

In real-time, check the dialer status:

# Monitor dialer queue
asterisk -rx "core show channels concise" | wc -l

# Check dial queue depth
mysql -u root -p asterisk -e "SELECT COUNT(*) as pending_dials FROM vicidial_list WHERE campaign_id = 'PREDICTIVE_01' AND status IN ('NEW', 'QUEUE');"

# Monitor predictive drops
mysql -u root -p asterisk -e "SELECT call_result, COUNT(*) as count FROM vicidial_log WHERE campaign_id = 'PREDICTIVE_01' AND call_date > DATE_SUB(NOW(), INTERVAL 1 HOUR) GROUP BY call_result;"

Section 4: Ratio-Based Dialing Setup

Understanding Ratio Dialing

Ratio (or Power) dialing maintains a fixed multiplier between agents and dials:

Formula: Dials Per Minute = (Available Agents) × (Ratio) × (Calls Per Agent Per Minute)

Configure Campaign for Ratio Dialing

Set the auto_dial_level to 0.5 for a moderate ratio approach:

UPDATE vicidial_campaigns 
SET 
  dial_method = 'INBOUND',
  auto_dial_level = 0.50,
  drop_percentage = 12,
  scheduled_callbacks = 'ENABLED',
  pause_dialing = 'N'
WHERE campaign_id = 'RATIO_01';

In the ViciDial admin panel, under "Dialer Settings," configure:

Adjust the Dialing Queue Script

Edit /usr/share/astguiclient/vicidial_dialer.pl (or create a wrapper):

# Around line 850, locate the ratio calculation:
# Example modification for stricter ratio control

my $available_agents = $dbh->selectrow_array(
  "SELECT COUNT(*) FROM vicidial_log WHERE campaign_id='$campaign_id' 
   AND call_date > DATE_SUB(NOW(), INTERVAL 10 SECOND)
   AND status IN ('QUEUE', 'INCALL')"
);

my $ratio = 3; # Set your ratio here
my $dials_to_queue = $available_agents * $ratio;

# Queue dials accordingly
for (my $i = 0; $i < $dials_to_queue; $i++) {
  queue_dial_for_agent($campaign_id);
}

Monitor Ratio Dialing Performance

# Check current agent count
mysql -u root -p asterisk -e "
  SELECT 
    COUNT(DISTINCT user) as active_agents,
    COUNT(*) as total_sessions
  FROM vicidial_log 
  WHERE campaign_id = 'RATIO_01' 
  AND call_date > DATE_SUB(NOW(), INTERVAL 5 MINUTE)
  AND status IN ('QUEUE', 'INCALL');
"

# Calculate real-time dial rate
mysql -u root -p asterisk -e "
  SELECT 
    COUNT(*) as calls_last_minute
  FROM vicidial_log 
  WHERE campaign_id = 'RATIO_01' 
  AND call_date > DATE_SUB(NOW(), INTERVAL 1 MINUTE);
"

Section 5: Progressive Dialing Setup

Understanding Progressive Dialing

Progressive dialing is the most conservative:

Configure Campaign for Progressive Mode

UPDATE vicidial_campaigns 
SET 
  dial_method = 'INBOUND',
  auto_dial_level = 0.15,
  drop_percentage = 0,
  scheduled_callbacks = 'ENABLED',
  pause_dialing = 'N'
WHERE campaign_id = 'PROGRESSIVE_01';

Configure Agent Macro for One-Click Dialing

Edit the agent's hotkey configuration in /agc/vicidial.php:

Agent users can assign a dial macro. In ViciDial admin, under "User Settings," set:

Dial Prefix: 0  (Agent dials 0 + number, or auto-fills from lead)
Dial Method: PROGRESSIVE
Auto Dial: Disabled

Or configure via database:

UPDATE vicidial_users 
SET 
  auto_dial_mode = 'PROGRESSIVE',
  auto_dial_level = 0.15,
  auto_call_override = 'OFF'
WHERE user = 'agent_001';

Enable Manual Dial Button in Agent Screen

The standard ViciDial agent screen (/agc/vicidial.php) already includes a DIAL button. Ensure it's enabled:

  1. Log in as an agent
  2. Lead information populates from the list
  3. Agent clicks DIAL button
  4. Call connects to that single lead

No additional configuration is required for basic progressive dialing.

Section 6: Performance Tuning & Optimization

Database Query Optimization

ViciDial relies on frequent database queries. Optimize with proper indexing:

-- Check existing indexes
SHOW INDEX FROM vicidial_log;

-- Add performance indexes if missing
ALTER TABLE vicidial_list 
ADD INDEX idx_campaign_status (campaign_id, status),
ADD INDEX idx_phone_number (lead_phone_number),
ADD INDEX idx_call_date (call_date);

ALTER TABLE vicidial_log 
ADD INDEX idx_campaign_call_date (campaign_id, call_date),
ADD INDEX idx_status_date (status, call_date),
ADD INDEX idx_user_date (user, call_date);

-- Optimize tables after adding indexes
OPTIMIZE TABLE vicidial_log;
OPTIMIZE TABLE vicidial_list;
OPTIMIZE TABLE vicidial_closer_log;

Asterisk Channel Configuration

Increase available channels based on your trunking:

; In /etc/asterisk/sip.conf
[general]
maxforwards=20
udpbindaddr=0.0.0.0
tcpenable=yes
tcpbindaddr=0.0.0.0
tlsenable=no
srvlookup=yes
pedantic=no
maxcallbitrate=256000
autocreatepeer=no
relaxdtmf=yes
rtpholdtimeout=300
rtpkeepalive=no
rtptimeout=7200

CPU and Memory Limits

Monitor resource usage:

# Real-time system monitor
top -p $(pidof asterisk)

# Check memory usage
free -h

# Limit ViciDial processes if needed
ulimit -m 2097152  # 2GB memory limit
ulimit -n 65536    # 65K file descriptors

Optimize vicidial_dialer.pl Performance

Edit /usr/share/astguiclient/vicidial_dialer.pl to reduce query frequency:

# Around line 250, adjust loop sleep interval
my $loop_sleep = 0.5;  # 500ms between dial checks (higher = less CPU)

# Reduce the number of campaigns processed per cycle
my $campaigns_per_cycle = 10;

# Increase batch dial size for efficiency
my $dial_batch_size = 50;

Section 7: Troubleshooting Common Issues

Issue 1: Dialer Not Making Calls

Symptoms: Campaign active but no calls initiated.

Diagnosis:

# Check if dialer process is running
ps aux | grep vicidial_dialer.pl

# Check error logs
tail -100 /var/log/asterisk/messages | grep -i "dial\|error"

# Verify database connection
mysql -u root -p asterisk -e "SELECT COUNT(*) FROM vicidial_list WHERE campaign_id='PREDICTIVE_01' AND status='NEW';"

# Check Asterisk core
asterisk -rx "core show channels concise" | wc -l

Solutions:

Issue 2: High Call Drop Rate

Symptoms: Drop percentage exceeding threshold; caller disconnect before agent connects.

Diagnosis:

# Check drop rate by call result
mysql -u root -p asterisk -e "
  SELECT 
    call_result,
    COUNT(*) as count,
    ROUND(COUNT(*) / (SELECT COUNT(*) FROM vicidial_log WHERE campaign_id='PREDICTIVE_01' AND call_date > DATE_SUB(NOW(), INTERVAL 1 HOUR)) * 100, 2) as percentage
  FROM vicidial_log 
  WHERE campaign_id='PREDICTIVE_01' 
  AND call_date > DATE_SUB(NOW(), INTERVAL 1 HOUR)
  GROUP BY call_result;
"

# Check agent availability
mysql -u root -p asterisk -e "SELECT user, COUNT(*) FROM vicidial_log WHERE campaign_id='PREDICTIVE_01' AND call_date > DATE_SUB(NOW(), INTERVAL 1 HOUR) GROUP BY user;";

Solutions:

Issue 3: SIP Carrier Errors / Registration Failures

Symptoms: Carrier shows UNREACHABLE; calls fail with SIP 503.

Diagnosis:

# Check SIP registration
asterisk -rx "sip show registry"

# Test carrier connectivity
asterisk -rx "sip show peer carrier_sirius"

# Check carrier logs
tail -50 /var/log/asterisk/messages | grep -i "sirius\|carrier"

Solutions:

Issue 4: Agent Screen Not Showing Leads

Symptoms: Agent sees blank lead information despite calls in queue.

Diagnosis:

# Check lead list status
mysql -u root -p asterisk -e "SELECT COUNT(*) FROM vicidial_list WHERE campaign_id='PREDICTIVE_01' AND status IN ('NEW', 'QUEUE');";

# Check user campaign assignment
mysql -u root -p asterisk -e "SELECT user, campaign_id FROM vicidial_users WHERE user='agent_001';";

# Verify vicidial.php logs
tail -50 /var/log/apache2/error.log | grep vicidial

Solutions:

Issue 5: Calls Dialing to Wrong Number or Format

Symptoms: Calls connecting to incomplete or malformed numbers.

Diagnosis:

# Check last 10 call attempts
mysql -u root -p asterisk -e "
  SELECT 
    lead_id,
    lead_phone_number,
    phone_number_formatted,
    call_result
  FROM vicidial_log 
  WHERE campaign_id='PREDICTIVE_01' 
  ORDER BY call_date DESC LIMIT 10;
";

# Check dial plan
asterisk -rx "dialplan show from-internal"

Solutions:

Section 8: Production Monitoring & Maintenance

Real-Time Dashboard Query

Create a monitoring script to check campaign health:

#!/bin/bash
# /usr/local/bin/vicidial_monitor.sh

CAMPAIGN="PREDICTIVE_01"
INTERVAL=60

while true; do
  echo "=== ViciDial Campaign Status: $CAMPAIGN ==="
  echo "Time: $(date)"
  
  mysql -u root -p asterisk -e "
    SELECT 
      'Active Agents' as metric, COUNT(DISTINCT user) as value 
    FROM vicidial_log 
    WHERE campaign_id='$CAMPAIGN' 
    AND call_date > DATE_SUB(NOW(), INTERVAL 5 MINUTE)
    AND status IN ('QUEUE', 'INCALL')
    UNION ALL
    SELECT 
      'Channels In Use', COUNT(*) 
    FROM vicidial_log 
    WHERE campaign_id='$CAMPAIGN' 
    AND call_date > DATE_SUB(NOW(), INTERVAL 5 MINUTE)
    UNION ALL
    SELECT 
      'Leads Pending', COUNT(*) 
    FROM vicidial_list 
    WHERE campaign_id='$CAMPAIGN' AND status='NEW'
    UNION ALL
    SELECT 
      'Avg Talk Time (sec)', ROUND(AVG(LENGTH_OF_CALL)) 
    FROM vicidial_log 
    WHERE campaign_id='$CAMPAIGN' 
    AND call_date > DATE_SUB(NOW(), INTERVAL 1 HOUR)
    AND call_result='SALE';
  "
  
  echo ""
  sleep $INTERVAL
done

Run the script:

chmod +x /usr/local/bin/vicidial_monitor.sh
/usr/local/bin/vicidial_monitor.sh

Regular Database Maintenance

#!/bin/bash
# /usr/local/bin/vicidial_maintenance.sh

# Backup database daily
mysqldump -u root -p asterisk > /backups/asterisk_$(date +%Y%m%d).sql

# Purge old logs (keep 90 days)
mysql -u root -p asterisk -e "
  DELETE FROM vicidial_log WHERE call_date < DATE_SUB(NOW(), INTERVAL 90 DAY);
  DELETE FROM vicidial_closer_log WHERE call_date < DATE_SUB(NOW(), INTERVAL 90 DAY);
  OPTIMIZE TABLE vicidial_log;
  OPTIMIZE TABLE vicidial_closer_log;
"

# Report on campaign performance
mysql -u root -p asterisk -e "
  SELECT 
    campaign_id,
    DATE(call_date) as date,
    COUNT(*) as total_calls,
    SUM(CASE WHEN call_result='SALE' THEN 1 ELSE 0 END) as sales,
    SUM(CASE WHEN call_result='DROPPED' THEN 1 ELSE 0 END) as dropped,
    ROUND(SUM(CASE WHEN call_result='DROPPED' THEN 1 ELSE 0 END) / COUNT(*) * 100, 2) as drop_rate_percent
  FROM vicidial_log
  WHERE call_date > DATE_SUB(NOW(), INTERVAL 7 DAY)
  GROUP BY campaign_id, DATE(call_date)
  ORDER BY campaign_id, date DESC;
" > /var/log/vicidial_daily_report.txt

Schedule in crontab:

crontab -e

# Add:
0 2 * * * /usr/local/bin/vicidial_maintenance.sh > /dev/null 2>&1

Summary

This tutorial covered the complete setup and tuning of ViciDial's three auto-dial modes:

Predictive Dialing provides the highest contact rate and throughput by predicting agent availability and dialing ahead. Ideal for high-volume campaigns where some call drops are acceptable. Requires careful monitoring of drop rates and CPU usage.

Ratio-Based Dialing maintains fixed dial multipliers (e.g., 3:1) per available agent. More predictable than predictive; suitable for mid-range campaigns. Requires less tuning but achieves lower contact rates than predictive.

Progressive Dialing offers zero abandonment by requiring manual agent dial actions. Best for compliance-heavy environments and new campaigns. Maximizes agent control but minimizes throughput.

Key implementation steps:

  1. Create campaigns and leads in the asterisk database
  2. Configure SIP carriers and Asterisk dialplan
  3. Enable the vicidial_dialer.pl background service
  4. Set auto_dial_level, drop_percentage, and dial_timeout per mode
  5. Optimize database indexes and Asterisk channel limits
  6. Monitor via SQL queries, Asterisk CLI, and real-time dashboards
  7. Troubleshoot using logs, database diagnostics, and SIP peer status checks
  8. Maintain via regular backups, log rotation, and performance reports

Production deployments benefit from starting conservative (lower dial rates, higher drop thresholds) and gradually increasing intensity while monitoring agent satisfaction, call quality, and network capacity. Always maintain backups and test configuration changes in a staging environment first.

For enterprise setups, consider implementing load balancing across multiple ViciDial servers and using dedicated trunk capacity with your carrier to ensure reliable, scalable operation.

Stuck on something specific?

Book a free 30-minute call. I run ViciDial centers across 3 countries and can usually unblock your setup in one session — or build it for you.

Book a Free Consultation