How to Configure ViciDial Caller ID (CID) Settings Per Campaign

Master per-campaign Caller ID configuration in ViciDial/Asterisk to control outbound number presentation, dynamic CID routing, and compliance-driven number assignment across multiple campaigns.

Prerequisites

Before you begin configuring ViciDial Caller ID settings per campaign, ensure the following:

  • ViciDial 2.14+ installed and running (this tutorial covers 2.14-2.17)
  • Asterisk 11+ compiled with ViciDial patches
  • Direct database access (MySQL/MariaDB) to the asterisk database
  • SSH access to the ViciDial server with sudo privileges
  • Carrier/trunk configuration already established with available DID numbers
  • Understanding of basic ViciDial campaign structure and dialplan concepts
  • PHP web admin access (/vicidial/admin.php)

Verify your ViciDial version:

sudo -u asterisk cat /etc/asterisk/vici_domains.conf | head -20 

Check Asterisk is running:

sudo asterisk -rx "core show version" 

Understanding ViciDial Caller ID Architecture

ViciDial handles Caller ID assignment through a hierarchical system with multiple fallback points. Understanding this chain is critical for proper configuration.

The CID Assignment Priority Chain

When an agent dials a lead in ViciDial, the system determines which number to present in this order:

  1. Campaign-level CID (if configured in campaign settings)
  2. User/Agent-level CID (if assigned to the specific agent)
  3. Carrier CID (numbers assigned to the outbound carrier/trunk)
  4. Server default CID (fallback number configured at server level)
  5. Trunk/Channel default (last resort from Asterisk trunk config)

This hierarchy allows fine-grained control. A campaign can override agent settings, but agents can still have their own CID if the campaign isn't strict.

Key Database Tables

Three primary tables govern CID behavior:

  • vicidial_campaigns — campaign-wide CID settings
  • vicidial_users — agent-specific CID overrides
  • vicidial_carrier_log — outbound carrier trunk configurations

Accessing Campaign CID Settings via Web Admin

The quickest method for most ViciDial administrators is through the web interface.

Step 1: Navigate to Campaign Configuration

  1. Log in to /vicidial/admin.php as a user with campaign edit permissions
  2. Click Campaigns → Modify Campaign
  3. Select your target campaign from the dropdown
  4. Look for Caller ID Number field near the top of the form

Step 2: Set Campaign-Level CID

The Caller ID Number field accepts:

  • Static number: 15551234567 — all calls from this campaign present this number
  • Carrier default: Leave blank — use the trunk/carrier's assigned DID
  • Variable assignment: See dynamic section below

Example configuration:

Campaign Name: Sales_Outbound_US Caller ID Number: 15551234567 Caller ID Name: Acme Sales 

Step 3: Save and Verify

Click SUBMIT to save. The web interface commits directly to the vicidial_campaigns table.

Verify in MySQL:

SELECT campaign_id, campaign_name, outbound_cid, cid_name FROM vicidial_campaigns WHERE campaign_name='Sales_Outbound_US'\G 

Expected output:

 campaign_id: 1  campaign_name: Sales_Outbound_US outbound_cid: 15551234567 cid_name: Acme Sales 

Database-Level CID Configuration

For advanced scenarios or bulk updates, modify the database directly.

Direct Campaign CID Update

Update a single campaign:

UPDATE vicidial_campaigns SET outbound_cid='15551234567', cid_name='Acme Sales' WHERE campaign_id=1; 

Verify the change immediately:

SELECT campaign_id, campaign_name, outbound_cid, cid_name FROM vicidial_campaigns WHERE campaign_id=1; 

Bulk Update Multiple Campaigns

Update all campaigns with a specific status or prefix:

UPDATE vicidial_campaigns SET outbound_cid='16175550123', cid_name='Boston Office' WHERE campaign_name LIKE 'Boston_%' AND active='Y'; 

Check how many rows were affected:

SELECT COUNT(*) FROM vicidial_campaigns WHERE campaign_name LIKE 'Boston_%' AND active='Y'; 

Agent-Level CID Override

Override campaign CID for specific agents:

UPDATE vicidial_users SET outbound_cid='15559876543', cid_name='John Smith' WHERE user='john.smith' AND user_level >= 1; 

Verify:

SELECT user, user_name, outbound_cid, cid_name FROM vicidial_users WHERE user='john.smith'; 

Important: Agent-level CID only applies if the campaign doesn't have a strict CID policy. Check the campaign's outbound_cid field—if set, it overrides agents.

View Current CID Configuration Across Campaigns

Generate a report of all campaign CID settings:

SELECT campaign_id, campaign_name, outbound_cid, cid_name, active, campaign_type FROM vicidial_campaigns WHERE active='Y' ORDER BY campaign_name; 

Asterisk Dialplan Integration

The actual CID presentation happens in Asterisk dialplan. ViciDial uses extension contexts generated from database records.

Reviewing Generated Dialplan

ViciDial writes dialplan on each service restart. The outbound campaign dialplan is in:

cat /etc/asterisk/extensions-vicidial.conf | grep -A 20 "exten => 8,1" 

Look for Set(CALLERID(num)= statements:

exten => 8,1,Set(CALLERID(num)=15551234567) exten => 8,2,Set(CALLERID(name)=Acme Sales) exten => 8,3,Dial(...) 

Manual Dialplan Override (Advanced)

For custom CID logic, edit /etc/asterisk/extensions-custom.conf:

[from-internal-custom] exten => _91XXXXXXXXX,1,NoOp(Custom CID for campaign) exten => _91XXXXXXXXX,n,Set(CALLERID(num)=15551234567) exten => _91XXXXXXXXX,n,Set(CALLERID(name)=Acme Sales) exten => _91XXXXXXXXX,n,Goto(from-internal,${EXTEN},1) 

Reload the dialplan after edits:

sudo asterisk -rx "dialplan reload" 

Warning: Custom dialplan changes will be overwritten on next ViciDial service restart. Use only for testing or if you can regenerate extensions programmatically.

Dynamic CID Assignment per Campaign

For scenarios requiring different CID numbers based on area codes, time of day, or lead data, use Asterisk AstDB or a custom script.

Method 1: Using Asterisk AstDB

Store CID mappings in AstDB (Asterisk internal database):

sudo asterisk -rx "database put CAMPAIGN_CID campaign_1 15551234567" sudo asterisk -rx "database put CAMPAIGN_CID campaign_2 16175550123" sudo asterisk -rx "database put CAMPAIGN_CID campaign_3 12125559999" 

Verify storage:

sudo asterisk -rx "database show CAMPAIGN_CID" 

Expected output:

/CAMPAIGN_CID/campaign_1 : 15551234567 /CAMPAIGN_CID/campaign_2 : 16175550123 /CAMPAIGN_CID/campaign_3 : 12125559999 

Add to /etc/asterisk/extensions-custom.conf:

[from-internal-custom] exten => _91XXXXXXXXX,1,NoOp(Dynamic CID lookup for ${CAMPAIGN_ID}) exten => _91XXXXXXXXX,n,Set(CID_NUM=${DB(CAMPAIGN_CID/${CAMPAIGN_ID})}) exten => _91XXXXXXXXX,n,ExecIf($["${CID_NUM}" != ""]?Set(CALLERID(num)=${CID_NUM})) exten => _91XXXXXXXXX,n,Goto(from-internal,${EXTEN},1) 

Reload dialplan:

sudo asterisk -rx "dialplan reload" 

Method 2: Area Code-Based CID Routing

Route outbound CID based on the lead's area code:

-- Create a lookup table CREATE TABLE IF NOT EXISTS vicidial_cid_routing ( cid_route_id INT AUTO_INCREMENT PRIMARY KEY, campaign_id INT, area_code VARCHAR(3), outbound_cid VARCHAR(20), active CHAR(1) DEFAULT 'Y' ); -- Populate with examples INSERT INTO vicidial_cid_routing (campaign_id, area_code, outbound_cid, active) VALUES (1, '617', '16175551234', 'Y'), (1, '212', '12125559876', 'Y'), (1, '310', '13105554321', 'Y'); 

Add Asterisk logic:

[from-internal-custom] exten => _91XXXXXXXXX,1,NoOp(Area-code-based CID for ${EXTEN:2:3}) exten => _91XXXXXXXXX,n,Set(AREA_CODE=${EXTEN:2:3}) exten => _91XXXXXXXXX,n,Set(CID_NUM=${ODBC_LOOKUP(cid_lookup,${CAMPAIGN_ID},${AREA_CODE})}) exten => _91XXXXXXXXX,n,ExecIf($["${CID_NUM}" != ""]?Set(CALLERID(num)=${CID_NUM})) exten => _91XXXXXXXXX,n,Goto(from-internal,${EXTEN},1) 

Carrier/Trunk CID Configuration

ViciDial campaigns route through carriers (trunks). Each carrier can have specific DID pools or CID ranges.

Viewing Carrier Configuration

SELECT carrier_id, carrier_name, outbound_cid, outbound_cid_override, active FROM vicidial_carrier_log LIMIT 10; 

Assigning DIDs to Carriers

ViciDial manages DIDs through vicidial_did_log:

SELECT did_id, did_number, carrier_id, active, did_route FROM vicidial_did_log WHERE active='Y' ORDER BY carrier_id; 

Linking Campaign to Specific Carrier

Some ViciDial installations require explicit carrier assignment per campaign:

-- Check if your ViciDial version tracks carrier_id in campaigns DESCRIBE vicidial_campaigns | grep carrier; -- If present, assign campaign to carrier UPDATE vicidial_campaigns SET carrier_id=1 WHERE campaign_id=5; 

Note: Not all ViciDial versions have carrier_id in the campaign table. Check your schema first.

SIP Trunk Configuration for CID

The actual SIP trunk configuration in Asterisk determines whether CID is allowed, blocked, or modified by carriers.

Example SIP Trunk Configuration

Edit /etc/asterisk/sip-vicidial.conf:

[carrier_outbound_trunk](!) type=peer context=from-carriers disallow=all allow=alaw,ulaw,gsm nat=yes host=carrier.example.com port=5060 insecure=port,invite [carrier_outbound_trunk](carrier_outbound_trunk) accountcode=OUTBOUND_CARRIER_1 fromuser=customer_acct fromdomain=carrier.example.com defaultuser=customer_acct secret=your_sip_password_here 

Controlling CID Presentation in SIP INVITE

Add per-trunk CID settings:

[carrier_outbound_trunk](!) ; ... existing config ... setvar=OUTBOUND_CID=15551234567 setvar=OUTBOUND_CID_NAME=Acme Sales ; Allow or restrict CID override directmedia=no 

Pass CID to carrier via dialplan:

exten => _91XXXXXXXXX,1,Set(CALLERID(num)=15551234567) exten => _91XXXXXXXXX,2,Set(CALLERID(name)=Acme Sales) exten => _91XXXXXXXXX,3,Dial(SIP/${EXTEN}@carrier_outbound_trunk) 

Compliance and Call Recording CID Logging

ViciDial logs all calls with their CID in vicidial_log and vicidial_closer_log.

Verifying Logged CID

Check the call log for a specific campaign:

SELECT call_id, campaign_id, callerid_number, callerid_name, call_date, status FROM vicidial_log WHERE campaign_id=1 AND call_date >= DATE_SUB(NOW(), INTERVAL 24 HOUR) ORDER BY call_date DESC LIMIT 10; 

Example output:

call_id: 1700156234.142 campaign_id: 1 callerid_number: 15551234567 callerid_name: Acme Sales call_date: 2024-01-15 14:30:12 status: SALE 

Auditing CID Changes Over Time

Create an audit log of CID configuration changes:

SELECT campaign_id, campaign_name, outbound_cid, cid_name, modification_date FROM vicidial_campaigns_archive WHERE campaign_id=1 ORDER BY modification_date DESC; 

If vicidial_campaigns_archive doesn't exist, manually log critical changes:

sudo asterisk -rx "database put CAMPAIGN_CID_AUDIT campaign_1_change_$(date +%s) '15551234567|$(date)'" 

Troubleshooting CID Issues

Issue 1: CID Not Displaying Correctly to Called Party

Symptom: Outbound calls show wrong Caller ID or generic number.

Diagnosis:

  1. Check campaign CID setting:
SELECT outbound_cid, cid_name FROM vicidial_campaigns WHERE campaign_id=1\G 
  1. Verify agent CID doesn't override:
SELECT outbound_cid, cid_name FROM vicidial_users WHERE user='agent_name'\G 
  1. Check Asterisk dialplan generated:
grep -i "callerid" /etc/asterisk/extensions-vicidial.conf | head -20 
  1. Monitor live call in Asterisk:
sudo asterisk -rx "core show channels verbose" | grep OUTGOING 
  1. Check Asterisk logs:
sudo tail -100 /var/log/asterisk/messages | grep -i callerid 

Solution:

Regenerate dialplan:

sudo systemctl restart viciserver 

Or manually reload:

sudo asterisk -rx "dialplan reload" 

Issue 2: CID Rejected by Carrier

Symptom: Calls connect but caller ID shows as "Anonymous" or default carrier number.

Diagnosis:

  1. Verify carrier accepts the CID:
sudo asterisk -rx "sip show peer carrier_outbound_trunk" 
  1. Check SIP debug logs:
sudo asterisk -rx "sip set debug on" # Make a test call sudo asterisk -rx "sip set debug off" sudo tail -200 /var/log/asterisk/messages | grep -i "callerid\|from:" 
  1. Contact carrier to verify:
    • CID number is whitelisted
    • CID format is correct (E.164: +1NXXXXXXXXX)
    • Account permissions allow CID override

Solution:

  • Reformat CID to carrier's requirement
  • Request CID whitelist approval from carrier
  • Use carrier-assigned DID if available

Issue 3: Incorrect CID on Agent Transfers

Symptom: When an agent transfers a call, different CID presents.

Diagnosis:

Check if attended transfer preserves CID:

sudo asterisk -rx "core show function REDIRECTING" 

Verify in call logs:

SELECT call_id, callerid_number, transfer_to, transfer_from FROM vicidial_log WHERE campaign_id=1 AND call_date >= NOW() - INTERVAL 1 HOUR; 

Solution:

Configure transfer preservation in /etc/asterisk/extensions-custom.conf:

exten => _91XXXXXXXXX,1,Set(REDIRECTING(num)=${CALLERID(num)}) exten => _91XXXXXXXXX,2,Set(REDIRECTING(name)=${CALLERID(name)}) exten => _91XXXXXXXXX,3,Dial(SIP/extension@asterisk) 

Issue 4: Database Changes Not Reflecting in Calls

Symptom: Updated campaign CID in database, but old number still showing.

Cause: Asterisk dialplan is cached in memory.

Solution:

Fully restart ViciDial services:

sudo systemctl stop viciserver sudo systemctl stop vicidial-Apache sleep 5 sudo systemctl start viciserver sudo systemctl start vicidial-Apache 

Verify reload completed:

sudo asterisk -rx "dialplan show from-internal" | grep -i callerid | head -5 

Issue 5: CID Shows Campaign Name Instead of Number

Symptom: Caller ID displays campaign name (e.g., "Sales_Outbound") instead of phone number.

Diagnosis:

Check for misconfiguration in campaign CID field:

SELECT campaign_id, campaign_name, outbound_cid, cid_name FROM vicidial_campaigns WHERE campaign_name='Sales_Outbound'\G 

If outbound_cid contains non-numeric characters, it's misconfigured.

Solution:

Fix the field to contain only digits:

UPDATE vicidial_campaigns SET outbound_cid='15551234567' WHERE campaign_name='Sales_Outbound'; 

Verify the format matches E.164:

# Should match pattern: 1-15 digits, starting with 1 for US numbers echo "15551234567" | grep -E '^1[0-9]{10,14}$' && echo "Valid" || echo "Invalid" 

Debug CID in Real-Time

Enable verbose logging and run a test call:

# Terminal 1: Enable debug sudo asterisk -rx "core set verbose 5" sudo asterisk -rx "sip set debug on" # Terminal 2: Monitor logs sudo tail -f /var/log/asterisk/messages | grep -i callerid # Terminal 3: Run test call from agent screen (/agc/vicidial.php) # Monitor both logs 

Check both agent screen and logs for confirmation:

sudo grep "campaign_id=1" /var/log/asterisk/messages | tail -20 

Production Best Practices

1. Document CID Assignments

Maintain a spreadsheet or wiki of all campaign CID assignments:

Campaign ID Campaign Name Assigned CID CID Name Carrier Status
1 Sales_US 15551234567 Acme Sales Carrier A Active
2 Support_CA 14165559999 Acme Support Carrier B Active
3 Collections_Test 15559876543 Test CID Carrier A Testing

2. Use Staging Environment

Test CID changes in a staging ViciDial before production:

# Backup production campaign settings mysqldump -u asterisk -p asterisk vicidial_campaigns > campaigns_backup_$(date +%Y%m%d).sql # Test in staging first mysql -u asterisk -p asterisk_stage < test_campaign_cid.sql 

3. Implement Change Control

Log all manual CID changes:

# Create audit log echo "[$(date)] Changed campaign 1 CID from 15551111111 to 15551234567 - Admin: $(whoami)" >> /var/log/vicidial_cid_changes.log 

4. Validate CID Format

Before updating, validate CID numbers:

# Simple validation script validate_cid() { if [[ $1 =~ ^1[0-9]{10,14}$ ]] || [[ $1 =~ ^\+1[0-9]{10,14}$ ]]; then echo "Valid CID: $1" return 0 else echo "Invalid CID format: $1" return 1 fi } validate_cid "15551234567" && echo "OK" || echo "FAIL" 

5. Monitor CID Effectiveness

Regularly audit that CID is logging correctly:

-- Daily CID verification report SELECT DATE(call_date) as call_date, campaign_id, COUNT(*) as call_count, COUNT(DISTINCT callerid_number) as unique_cids FROM vicidial_log WHERE call_date >= DATE_SUB(NOW(), INTERVAL 7 DAY) GROUP BY DATE(call_date), campaign_id ORDER BY call_date DESC; 

Summary

Configuring Caller ID per ViciDial campaign requires understanding the CID assignment hierarchy, database configuration, and Asterisk dialplan integration. Key takeaways:

  1. Use the web admin (/vicidial/admin.php) for simple, one-off campaign CID changes
  2. Access the database directly for bulk updates or complex scenarios
  3. Understand the hierarchy: Campaign CID overrides agent CID, which overrides carrier default
  4. Verify in Asterisk: Monitor dialplan generation and reload to ensure changes take effect
  5. Test before production: Use staging environments and maintain change logs
  6. Audit regularly: Check vicidial_log to confirm CID is presenting correctly to called parties
  7. Handle carrier restrictions: Some carriers whitelist or restrict CID numbers; coordinate with your carrier
  8. Troubleshoot methodically: Check database → dialplan → Asterisk logs → carrier support

For dynamic CID assignment beyond static campaign settings, use AstDB lookups or custom dialplan logic tied to area codes, lead data, or other routing variables. Always maintain backups before bulk changes and test in a staging environment whenever possible.

The configuration is now complete and ready for production use. Monitor call logs regularly to ensure CID compliance and effectiveness.