Master both agent-initiated and campaign-level scheduled callbacks in ViciDial, including database configuration, Asterisk dialplan setup, and production troubleshooting.
Prerequisites
Before implementing scheduled callbacks, ensure you have:
- ViciDial v2.14 or later installed and running
- Asterisk 13+ with proper SIP configuration
- MySQL/MariaDB access with direct database privileges
- Administrator access to
/vicidial/admin.phpweb interface - SSH access to the ViciDial server for file editing
- Basic understanding of ViciDial call flow and campaign structure
- At least one active campaign and inbound group configured
- Asterisk CLI access via
asterisk -rxcommands - Daily cron jobs already configured for callback processing (
/usr/share/astguiclient/)
Understanding ViciDial Callback Types
ViciDial supports two primary callback mechanisms:
Agent-Level Scheduled Callbacks
Callbacks initiated by agents during live calls via the agent screen (/agc/vicidial.php). The agent sets a callback time, and the system attempts to reach the lead at the scheduled time.
Campaign-Level Scheduled Callbacks
Callbacks triggered automatically by campaign rules, IVR results, or system events. These run on a larger scale and respect campaign-wide settings.
Both types store data in the vicidial_log and vicidial_closer_log tables but follow different processing workflows.
Section 1: Database Configuration for Callbacks
Step 1.1: Verify Core Tables Exist
Log into your ViciDial MySQL database and confirm callback-related tables:
mysql -u root -p asterisk -e "SHOW TABLES LIKE '%vicidial%';" | grep -E "(log|callback)"
You should see tables including:
vicidial_log(main call log)vicidial_closer_log(agent notes and callbacks)vicidial_list(lead records)vicidial_callbacks(scheduled callback queue)
Step 1.2: Create or Verify Vicidial_Callbacks Table
If the vicidial_callbacks table doesn't exist, create it:
CREATE TABLE `vicidial_callbacks` (
`callback_id` int(11) NOT NULL AUTO_INCREMENT,
`lead_id` int(11) NOT NULL,
`campaign_id` varchar(8) NOT NULL,
`callback_time` datetime NOT NULL,
`callback_type` varchar(10) DEFAULT 'AGENT',
`user_id` varchar(20) DEFAULT NULL,
`phone_number` varchar(20) NOT NULL,
`notes` text,
`status` varchar(20) DEFAULT 'PENDING',
`created_date` datetime DEFAULT CURRENT_TIMESTAMP,
`processed_date` datetime DEFAULT NULL,
`attempt_count` int(11) DEFAULT 0,
`max_attempts` int(11) DEFAULT 3,
PRIMARY KEY (`callback_id`),
KEY `idx_campaign_time` (`campaign_id`, `callback_time`),
KEY `idx_lead_campaign` (`lead_id`, `campaign_id`),
KEY `idx_status` (`status`),
KEY `idx_callback_time` (`callback_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Step 1.3: Add Callback Fields to Vicidial_List
Ensure the vicidial_list table has callback-related columns:
ALTER TABLE `vicidial_list` ADD COLUMN IF NOT EXISTS `callback_date` datetime DEFAULT NULL;
ALTER TABLE `vicidial_list` ADD COLUMN IF NOT EXISTS `callback_type` varchar(10) DEFAULT 'AGENT';
ALTER TABLE `vicidial_list` ADD COLUMN IF NOT EXISTS `last_callback_attempt` datetime DEFAULT NULL;
CREATE INDEX idx_callback_date ON vicidial_list(callback_date);
Step 1.4: Extend Vicidial_Closer_Log for Callback Tracking
Add callback metadata to agent notes table:
ALTER TABLE `vicidial_closer_log` ADD COLUMN IF NOT EXISTS `scheduled_callback` datetime DEFAULT NULL;
ALTER TABLE `vicidial_closer_log` ADD COLUMN IF NOT EXISTS `callback_phone` varchar(20) DEFAULT NULL;
ALTER TABLE `vicidial_closer_log` ADD COLUMN IF NOT EXISTS `callback_notes` text;
CREATE INDEX idx_scheduled_callback ON vicidial_closer_log(scheduled_callback);
Section 2: Campaign-Level Callback Configuration
Step 2.1: Access Campaign Settings
Log into the ViciDial admin panel:
https://YOUR_VICIDIAL_IP/vicidial/admin.php
Navigate to: Admin → Manage Campaigns
Select your target campaign and scroll to the "Callback Settings" section.
Step 2.2: Configure Campaign Callback Parameters
Set the following fields:
| Parameter | Value | Description |
|---|---|---|
| Callback Enabled | YES | Activates callback feature for the campaign |
| Callback Attempt Limit | 3 | Maximum retry attempts |
| Callback Time Window | 09:00-17:00 | Hours when callbacks should be attempted |
| Callback Interval | 300 | Seconds between retry attempts (300 = 5 min) |
| Callback Lead Status | CBHOLD | Lead status after callback is scheduled |
| Callback Dial Timeout | 45 | Seconds to wait for answer before hanging up |
Step 2.3: Update Campaign in Database
Alternatively, update directly via SQL:
UPDATE vicidial_campaigns
SET
use_callbacks = 'Y',
callback_attempts = 3,
callback_interval = 300,
callback_leadstatus = 'CBHOLD'
WHERE campaign_id = 'YOUR_CAMPAIGN_ID';
Verify the update:
SELECT campaign_id, use_callbacks, callback_attempts, callback_interval, callback_leadstatus
FROM vicidial_campaigns
WHERE campaign_id = 'YOUR_CAMPAIGN_ID';
Section 3: Agent-Level Callback Setup via Agent Screen
Step 3.1: Understanding the Agent Screen Callback Button
When an agent is on a live call in /agc/vicidial.php, they can click the "Schedule Callback" button. This triggers a JavaScript modal for entering callback details.
Step 3.2: Modify Agent Screen for Callback Display
Edit the agent application configuration file:
sudo nano /var/www/html/agc/vicidial.php
Locate the callback button section (typically around line 800-1200) and ensure this code block exists:
function schedule_callback_form() {
var callback_time = prompt("Enter callback time (YYYY-MM-DD HH:MM:SS):", new Date().toISOString().slice(0, 19));
if (callback_time) {
var callback_phone = prompt("Callback phone number:", document.getElementById('phone_number').value);
var callback_notes = prompt("Callback notes:", "");
var xhr = new XMLHttpRequest();
xhr.open("POST", "/agc/schedule_callback.php", true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.onload = function() {
if (xhr.status === 200) {
alert("Callback scheduled successfully!");
log_callback_in_notes(callback_time, callback_notes);
}
};
xhr.send("lead_id=" + encodeURIComponent(lead_id) +
"&callback_time=" + encodeURIComponent(callback_time) +
"&callback_phone=" + encodeURIComponent(callback_phone) +
"&callback_notes=" + encodeURIComponent(callback_notes) +
"&campaign_id=" + encodeURIComponent(campaign_id) +
"&user_id=" + encodeURIComponent(user_id));
}
}
Step 3.3: Create Callback Processing PHP Script
Create a new file for handling agent callback submissions:
sudo nano /var/www/html/agc/schedule_callback.php
Add the following code:
<?php
// ViciDial Agent Callback Submission Handler
error_reporting(E_ALL);
ini_set('display_errors', 0);
// Security: Verify session
session_start();
if (!isset($_SESSION['user_id'])) {
http_response_code(401);
echo json_encode(['error' => 'Unauthorized']);
exit;
}
// Database connection
$DB_host = 'localhost';
$DB_user = 'vicidial';
$DB_pass = 'VICIDIAL_DB_PASSWORD'; // Change this
$DB_name = 'asterisk';
$mysqli = new mysqli($DB_host, $DB_user, $DB_pass, $DB_name);
if ($mysqli->connect_error) {
http_response_code(500);
echo json_encode(['error' => 'Database connection failed']);
exit;
}
// Input validation
$lead_id = intval($_POST['lead_id']);
$campaign_id = $mysqli->real_escape_string($_POST['campaign_id']);
$callback_time = $mysqli->real_escape_string($_POST['callback_time']);
$callback_phone = preg_replace('/[^0-9]/', '', $_POST['callback_phone']);
$callback_notes = $mysqli->real_escape_string($_POST['callback_notes']);
$user_id = $mysqli->real_escape_string($_SESSION['user_id']);
// Validate callback time is in the future
$callback_timestamp = strtotime($callback_time);
if ($callback_timestamp <= time()) {
http_response_code(400);
echo json_encode(['error' => 'Callback time must be in the future']);
exit;
}
// Insert into vicidial_callbacks table
$query = "INSERT INTO vicidial_callbacks
(lead_id, campaign_id, callback_time, callback_type, user_id, phone_number, notes, status)
VALUES
($lead_id, '$campaign_id', '$callback_time', 'AGENT', '$user_id', '$callback_phone', '$callback_notes', 'PENDING')";
if ($mysqli->query($query)) {
// Update vicidial_list to mark callback pending
$update_query = "UPDATE vicidial_list
SET callback_date = '$callback_time',
callback_type = 'AGENT',
last_callback_attempt = NOW()
WHERE lead_id = $lead_id";
$mysqli->query($update_query);
// Log to closer log for agent reference
$closer_query = "INSERT INTO vicidial_closer_log
(lead_id, campaign_id, call_date, user_id, scheduled_callback, callback_phone, callback_notes)
VALUES
($lead_id, '$campaign_id', NOW(), '$user_id', '$callback_time', '$callback_phone', '$callback_notes')";
$mysqli->query($closer_query);
http_response_code(200);
echo json_encode(['success' => true, 'callback_id' => $mysqli->insert_id]);
} else {
http_response_code(500);
echo json_encode(['error' => $mysqli->error]);
}
$mysqli->close();
?>
Section 4: Asterisk Dialplan Configuration
Step 4.1: Create Callback Processing Extension
Edit your Asterisk extensions configuration:
sudo nano /etc/asterisk/extensions-vicidial.conf
Add a dedicated context for callback processing:
[callback-outbound]
exten => _.,1,NoOp(ViciDial Callback Processing - Leg: ${CALLLEG})
same => n,Set(TIMEOUT(absolute)=3600)
same => n,Log(NOTICE, Processing callback for lead: ${lead_id})
same => n,Dial(SIP/${callback_phone}@callback-carrier,45,tTkKwW)
same => n,GoTo(callback-result-${DIALSTATUS},1)
exten => callback-result-ANSWER,1,NoOp(Callback answered successfully)
same => n,Set(DB(vicidial/callback/${lead_id})=ANSWERED)
same => n,Set(callback_status=ANSWERED)
same => n,Hangup()
exten => callback-result-BUSY,1,NoOp(Callback line busy - will retry)
same => n,Set(DB(vicidial/callback/${lead_id})=BUSY)
same => n,Hangup()
exten => callback-result-NOANSWER,1,NoOp(No answer on callback)
same => n,Set(DB(vicidial/callback/${lead_id})=NOANSWER)
same => n,Hangup()
exten => callback-result-CHANUNAVAIL,1,NoOp(Channel unavailable for callback)
same => n,Set(DB(vicidial/callback/${lead_id})=FAILED)
same => n,Hangup()
exten => h,1,NoOp(Hangup handler for callback)
same => n,Log(NOTICE, Callback hangup - Status: ${callback_status})
Step 4.2: Update SIP Configuration for Callback Carrier
Edit the SIP configuration to allow callback outbound routing:
sudo nano /etc/asterisk/sip-vicidial.conf
Add or modify the callback carrier section:
[callback-carrier]
type=peer
host=YOUR_CARRIER_IP_OR_HOSTNAME
port=5060
secret=YOUR_SIP_SECRET
username=YOUR_SIP_USERNAME
fromuser=YOUR_SIP_USERNAME
fromdomain=YOUR_SIP_DOMAIN
dtmfmode=rfc2833
context=from-internal
disallow=all
allow=ulaw
allow=gsm
canreinvite=no
nat=force_rport,comedia
qualify=yes
qualifyfreq=60
Step 4.3: Reload Asterisk Configuration
After editing configuration files, reload Asterisk:
sudo asterisk -rx "sip reload"
sudo asterisk -rx "dialplan reload"
sudo asterisk -rx "core reload"
Verify the changes:
sudo asterisk -rx "sip show peers" | grep callback
sudo asterisk -rx "dialplan show callback-outbound"
Section 5: Cron Jobs and Scheduled Processing
Step 5.1: Create Callback Processing Script
Create the main callback processor script:
sudo nano /usr/share/astguiclient/vicidial_callbacks_processor.pl
Add the following Perl script:
#!/usr/bin/perl
# ViciDial Scheduled Callbacks Processor
# Runs every 60 seconds via cron
# Usage: /usr/share/astguiclient/vicidial_callbacks_processor.pl
use strict;
use warnings;
use DBI;
use DateTime;
use DateTime::Format::MySQL;
my $DB_host = 'localhost';
my $DB_user = 'vicidial';
my $DB_pass = 'VICIDIAL_DB_PASSWORD'; # Change this
my $DB_name = 'asterisk';
my $dbh = DBI->connect("DBI:mysql:$DB_name:$DB_host", $DB_user, $DB_pass)
or die "Cannot connect to database: $DBI::errstr";
my $now = DateTime->now();
my $now_mysql = DateTime::Format::MySQL->format_datetime($now);
# Query pending callbacks due within the next 60 seconds
my $query = "SELECT cb.callback_id, cb.lead_id, cb.campaign_id, cb.phone_number,
cb.callback_time, cb.attempt_count, cb.max_attempts, vl.phone_number as lead_phone
FROM vicidial_callbacks cb
JOIN vicidial_list vl ON cb.lead_id = vl.lead_id
WHERE cb.status = 'PENDING'
AND cb.callback_time <= DATE_ADD(NOW(), INTERVAL 60 SECOND)
AND cb.callback_time > NOW()
AND cb.attempt_count < cb.max_attempts
ORDER BY cb.callback_time ASC
LIMIT 50";
my $sth = $dbh->prepare($query);
$sth->execute() or die "Query failed: $DBI::errstr";
my $callback_count = 0;
while (my $row = $sth->fetchrow_hashref()) {
my $callback_id = $row->{callback_id};
my $lead_id = $row->{lead_id};
my $campaign_id = $row->{campaign_id};
my $phone_number = $row->{phone_number};
my $attempt_count = $row->{attempt_count};
my $max_attempts = $row->{max_attempts};
# Execute Asterisk originate command
my $asterisk_cmd = qq{
Originate(SIP/$phone_number\@callback-carrier,exten,callback-outbound,$phone_number,1,,)
};
system("/usr/sbin/asterisk -rx \"$asterisk_cmd\"");
# Update attempt count
my $update_query = "UPDATE vicidial_callbacks
SET attempt_count = attempt_count + 1,
processed_date = NOW()
WHERE callback_id = $callback_id";
$dbh->do($update_query) or warn "Failed to update callback: $DBI::errstr";
# Log the callback attempt
system("logger -t vicidial_callbacks 'Callback initiated: lead_id=$lead_id, phone=$phone_number, attempt=" . ($attempt_count + 1) . "/$max_attempts'");
$callback_count++;
}
# Mark expired callbacks as EXPIRED
my $expire_query = "UPDATE vicidial_callbacks
SET status = 'EXPIRED'
WHERE status = 'PENDING'
AND callback_time < DATE_SUB(NOW(), INTERVAL 24 HOUR)";
$dbh->do($expire_query);
# Mark max-attempt callbacks as FAILED
my $fail_query = "UPDATE vicidial_callbacks
SET status = 'FAILED'
WHERE status = 'PENDING'
AND attempt_count >= max_attempts";
$dbh->do($fail_query);
$dbh->disconnect();
exit(0);
Make the script executable:
sudo chmod 755 /usr/share/astguiclient/vicidial_callbacks_processor.pl
Step 5.2: Add Cron Job for Callback Processing
Edit the crontab:
sudo crontab -e
Add the following line to run callback processor every minute:
* * * * * /usr/share/astguiclient/vicidial_callbacks_processor.pl >> /var/log/asterisk/vicidial_callbacks.log 2>&1
Step 5.3: Monitor Callback Processing Logs
Create a log file and monitor it:
sudo touch /var/log/asterisk/vicidial_callbacks.log
sudo chown asterisk:asterisk /var/log/asterisk/vicidial_callbacks.log
sudo chmod 644 /var/log/asterisk/vicidial_callbacks.log
Monitor in real-time:
tail -f /var/log/asterisk/vicidial_callbacks.log
Section 6: Testing and Verification
Step 6.1: Manual Callback Test via SQL
Insert a test callback 5 minutes in the future:
INSERT INTO vicidial_callbacks
(lead_id, campaign_id, callback_time, callback_type, user_id, phone_number, notes, status, max_attempts)
VALUES
(12345, 'TESTCAMP', DATE_ADD(NOW(), INTERVAL 5 MINUTE), 'AGENT', 'testuser', '15551234567', 'Test callback', 'PENDING', 3);
Verify the insert:
SELECT callback_id, lead_id, callback_time, status, attempt_count
FROM vicidial_callbacks
WHERE lead_id = 12345;
Step 6.2: Monitor Asterisk During Callback
In one terminal, watch Asterisk logs:
tail -f /var/log/asterisk/messages | grep -i callback
In another terminal, trigger the callback processor manually:
/usr/share/astguiclient/vicidial_callbacks_processor.pl
Step 6.3: Verify Callback Status in Database
Check the status after callback attempt:
SELECT callback_id, lead_id, status, attempt_count, processed_date
FROM vicidial_callbacks
WHERE lead_id = 12345
ORDER BY processed_date DESC;
Step 6.4: Check Agent Screen Integration
Log into the agent screen at /agc/vicidial.php with a test agent account. During a test call, click "Schedule Callback" and verify:
- Modal appears with time and phone fields
- Callback is inserted into database
- Entry appears in agent's call notes
- Callback time displays correctly in lead history
Section 7: Production Optimization
Step 7.1: Database Indexing for Performance
Add strategic indexes to improve callback query performance:
CREATE INDEX idx_callbacks_status_time ON vicidial_callbacks(status, callback_time);
CREATE INDEX idx_callbacks_campaign_time ON vicidial_callbacks(campaign_id, callback_time);
CREATE INDEX idx_callbacks_lead ON vicidial_callbacks(lead_id);
CREATE INDEX idx_list_callback ON vicidial_list(callback_date, callback_type);
Step 7.2: Rate Limiting for Callback Dialout
Modify the callback processor to respect concurrent call limits:
# Add to vicidial_callbacks_processor.pl
my $max_concurrent_callbacks = 10;
my $concurrent_query = "SELECT COUNT(*) as active_callbacks
FROM asterisk.vicidial_callbacks
WHERE status = 'PROCESSING'";
my $concurrent_sth = $dbh->prepare($concurrent_query);
$concurrent_sth->execute();
my $concurrent = $concurrent_sth->fetchrow_hashref()->{active_callbacks};
if ($concurrent >= $max_concurrent_callbacks) {
exit(0); # Skip this run if limit reached
}
Step 7.3: Callback Time Zone Handling
Ensure callbacks respect agent/lead time zones:
ALTER TABLE vicidial_callbacks ADD COLUMN timezone_offset varchar(10) DEFAULT '+00:00';
UPDATE vicidial_callbacks cb
JOIN vicidial_list vl ON cb.lead_id = vl.lead_id
SET cb.timezone_offset = vl.state -- Assumes state field maps to timezone
WHERE cb.timezone_offset = '+00:00';
Update callback processor to account for timezone:
my $callback_time_utc = $row->{callback_time};
my $tz_offset = $row->{timezone_offset};
my $callback_time_local = DateTime->from_epoch(epoch => time(), time_zone => $tz_offset);
Section 8: Troubleshooting
Issue 1: Callbacks Not Triggering
Symptom: Callbacks scheduled but never attempt to dial.
Diagnosis:
# Check if cron job is running
sudo ps aux | grep vicidial_callbacks_processor
# Check cron logs
sudo grep CRON /var/log/syslog | tail -20
Solution:
Ensure the cron job is active and check file permissions:
sudo crontab -l | grep vicidial_callbacks_processor
sudo ls -la /usr/share/astguiclient/vicidial_callbacks_processor.pl
If missing, re-add to crontab as shown in Section 5.2.
Issue 2: Database Connection Errors
Symptom: Cannot connect to database errors in callback logs.
Diagnosis:
Verify database credentials in the Perl script match your installation:
sudo grep -i "DB_pass\|DB_user" /usr/share/astguiclient/*.pl | head -5
Solution:
Update credentials in /usr/share/astguiclient/vicidial_callbacks_processor.pl:
sudo nano /usr/share/astguiclient/vicidial_callbacks_processor.pl
# Edit the DB connection variables at the top
Test connection manually:
mysql -h localhost -u vicidial -p asterisk -e "SELECT COUNT(*) FROM vicidial_callbacks;"
Issue 3: Asterisk Originate Command Fails
Symptom: Callbacks attempted but SIP channels fail to originate.
Diagnosis:
Check Asterisk SIP peer status:
sudo asterisk -rx "sip show peers" | grep callback-carrier
sudo asterisk -rx "core show channels"
Check for SIP authentication errors:
sudo asterisk -rx "sip set debug on"
# Wait for callback to attempt
tail -f /var/log/asterisk/messages | grep -i "401\|403\|authentication"
Solution:
Verify SIP credentials in /etc/asterisk/sip-vicidial.conf:
sudo asterisk -rx "sip show peer callback-carrier"
Test SIP connectivity:
sudo sipsak -U -s sip:YOUR_CARRIER_IP
Issue 4: Callback Phone Numbers Formatted Incorrectly
Symptom: Callbacks dial incomplete or malformed numbers.
Diagnosis:
Check stored phone numbers in database:
SELECT callback_id, phone_number, LENGTH(phone_number) as len
FROM vicidial_callbacks
WHERE status IN ('PENDING', 'PROCESSING')
LIMIT 5;
Solution:
Standardize phone number formatting in the schedule_callback.php script:
function format_phone($phone) {
$digits = preg_replace('/[^0-9]/', '', $phone);
if (strlen($digits) == 10) {
return '1' . $digits; // Add country code if missing
}
return $digits;
}
$callback_phone = format_phone($_POST['callback_phone']);
Issue 5: High Database Query Load from Callback Processing
Symptom: Database CPU spikes every minute during callback processor runs.
Diagnosis:
Check query execution time:
sudo mysql -u vicidial -p -e "SET GLOBAL log_queries_not_using_indexes=ON; SET GLOBAL long_query_time=1;"
tail -f /var/log/mysql/slow.log | grep callback
Solution:
Add batch processing and limit queries in the Perl script:
# Modify the query in vicidial_callbacks_processor.pl to add LIMIT
LIMIT 50 # Process max 50 callbacks per run
Increase cron interval from 1 minute to 5 minutes if needed:
*/5 * * * * /usr/share/astguiclient/vicidial_callbacks_processor.pl
Issue 6: Agents Report Callback Button Not Working
Symptom: Agent screen loads but callback scheduling fails silently.
Diagnosis:
Check browser console for JavaScript errors:
- Open agent screen in browser
- Press F12 (Developer Tools)
- Go to Console tab
- Attempt to schedule callback
- Look for POST request failures
Check PHP error logs:
tail -f /var/log/apache2/error.log | grep schedule_callback
sudo grep -i "php error\|warning" /var/log/apache2/error.log | tail -20
Solution:
Verify schedule_callback.php exists and has correct permissions:
sudo ls -la /var/www/html/agc/schedule_callback.php
sudo chown www-data:www-data /var/www/html/agc/schedule_callback.php
Check if session is properly initialized in agent screen code:
grep -n "session_start" /var/www/html/agc/vicidial.php | head -3
Section 9: Monitoring and Reporting
Step 9.1: Callback Success Rate Report
Generate a callback success report:
SELECT
DATE(callback_time) as callback_date,
campaign_id,
COUNT(*) as total_callbacks,
SUM(CASE WHEN status = 'ANSWERED' THEN 1 ELSE 0 END) as answered,
SUM(CASE WHEN status = 'FAILED' THEN 1 ELSE 0 END) as failed,
SUM(CASE WHEN status = 'PENDING' THEN 1 ELSE 0 END) as pending,
ROUND(SUM(CASE WHEN status = 'ANSWERED' THEN 1 ELSE 0 END) / COUNT(*) * 100, 2) as success_rate_pct
FROM vicidial_callbacks
WHERE callback_time >= DATE_SUB(NOW(), INTERVAL 7 DAY)
GROUP BY DATE(callback_time), campaign_id
ORDER BY callback_date DESC, campaign_id;
Step 9.2: Agent Callback Activity
Track agent callback scheduling activity:
SELECT
user_id,
campaign_id,
COUNT(*) as callbacks_scheduled,
AVG(TIMESTAMPDIFF(MINUTE, callback_time, NOW())) as avg_lead_time_minutes
FROM vicidial_callbacks
WHERE callback_type = 'AGENT'
AND created_date >= DATE_SUB(NOW(), INTERVAL 1 DAY)
GROUP BY user_id, campaign_id
ORDER BY callbacks_scheduled DESC;
Summary
You now have a complete, production-ready ViciDial scheduled callback system spanning both agent-initiated and campaign-level callbacks. Here's what you've implemented:
Key Components:
- Database schema with callback tracking tables and indexes
- Campaign configuration for automatic callback rules and retry logic
- Agent screen integration with PHP form handler for manual callback scheduling
- Asterisk dialplan with callback-specific contexts and SIP routing
- Automated processing via Perl script and cron job for periodic callback attempts
- Monitoring and logging for tracking callback performance and troubleshooting
Best Practices Applied:
- Database indexing on frequently queried fields
- Rate limiting to prevent overwhelming carriers
- Time zone awareness for accurate callback scheduling
- Comprehensive error handling and retry logic
- Separation of agent and campaign callback workflows
- Detailed logging for audit trails and debugging
Next Steps:
- Deploy in a test environment first
- Validate all database queries execute without errors
- Monitor callback success rate for 1-2 weeks
- Adjust retry intervals and time windows based on results
- Train agents on callback scheduling via
/agc/vicidial.php - Set up monitoring alerts for callback processor failures
Use the troubleshooting section to resolve environment-specific issues. Monitor /var/log/asterisk/vicidial_callbacks.log and Asterisk CLI output regularly to ensure callbacks are processing as expected.