Eedesy
Book Demo
HomeProductsContact
AI Voice Agent
  • Introduction
  • Quick Start
  • Architecture
  • Core Concepts
  • Configuration
  • Creating an Agent
  • Using Templates
  • System Prompt Configuration
  • Language Selection
  • Settings Reference
  • Overview
  • Upload Files (PDF, DOCX)
  • Web Crawling (URLs & Sitemaps)
  • Document Processing
  • RAG Integration
  • Troubleshooting
  • Creating a Campaign
  • CSV Upload & Variables
  • Scheduling & Retry Logic
  • Campaign Analytics
  • Contact Management
  • Uploading Contacts
  • Managing Contacts
  • Call History Enrichment
  • Trial Numbers
  • Purchasing Numbers
  • BYOP Setup
  • Exotel Setup
  • Telephony Providers Guide
  • Credits System
  • Provider Costs Breakdown
  • Usage Analytics
  • Credit Packs
  • Overview
  • Finding Your Workspace ID
  • Common Issues
  • Audio Quality
  • Latency Optimization
  • Error Codes
  • Overview
  • Twilio
  • Exotel
  • Plivo
  • Telnyx
  • WhatsApp
  • WebRTC Browser
  • Overview
  • Deepgram
  • Google Chirp
  • Azure Speech
  • ElevenLabs Scribe
  • AssemblyAI
  • OpenAI Whisper
  • Overview
  • Cartesia
  • ElevenLabs
  • Google TTS
  • Azure Neural
  • OpenAI TTS
  • Deepgram Aura
  • Sarvam Bulbul
  • HeyPixa Luna
  • Overview
  • OpenAI GPT-4o
  • Gemini 2.0/2.5 Flash
  • Gemini Live (Native Audio)
  • OpenAI Realtime
  • Anthropic Claude
  • Azure OpenAI
  • Overview
  • VAD (Voice Activity Detection)
  • Interruption Handling
  • Turn Detection
  • Audio Processing
  • Function Calling
  • Call Transfer
  • DTMF Handling
  • Call Recording
  • Exporting Recordings
  • Transcripts
  • Webhooks
  • Variables & Templates
  • Multi-Language Support
  • Hindi
  • Tamil
  • Assamese
  • Other Indian Languages
  • Latency Optimization
  • Scaling & Performance
  • Error Handling
  • Monitoring & Logging
  • Security Best Practices
  • Trigger Call via API
  • REST API
  • WebSocket Protocol
  • Webhooks
  • Webhook Subscriptions
  • SDKs
  • Overview
  • Financial Services
  • E-commerce
  • Logistics
  • Hyperlocal
  • Healthcare
  • Education
  • Overview
  • Customer Support
  • Sales & Lead Conversion
  • Marketing Campaigns
  • Debt Collection
  • Overview
  • Customer Support Bot
  • Order Status IVR
  • Appointment Booking
  • Lead Qualification
  • Outbound Sales
  • Recruitment Screening
  • Overview
  • Migrate from Vapi
  • Migrate from Retell AI
  • Migrate from Traditional IVR

Related Products

  • AI Voice Agent
  • AI Voice Assistant
  • Try Free
AI Voice Agent
  • Introduction
  • Quick Start
  • Architecture
  • Core Concepts
  • Configuration
  • Creating an Agent
  • Using Templates
  • System Prompt Configuration
  • Language Selection
  • Settings Reference
  • Overview
  • Upload Files (PDF, DOCX)
  • Web Crawling (URLs & Sitemaps)
  • Document Processing
  • RAG Integration
  • Troubleshooting
  • Creating a Campaign
  • CSV Upload & Variables
  • Scheduling & Retry Logic
  • Campaign Analytics
  • Contact Management
  • Uploading Contacts
  • Managing Contacts
  • Call History Enrichment
  • Trial Numbers
  • Purchasing Numbers
  • BYOP Setup
  • Exotel Setup
  • Telephony Providers Guide
  • Credits System
  • Provider Costs Breakdown
  • Usage Analytics
  • Credit Packs
  • Overview
  • Finding Your Workspace ID
  • Common Issues
  • Audio Quality
  • Latency Optimization
  • Error Codes
  • Overview
  • Twilio
  • Exotel
  • Plivo
  • Telnyx
  • WhatsApp
  • WebRTC Browser
  • Overview
  • Deepgram
  • Google Chirp
  • Azure Speech
  • ElevenLabs Scribe
  • AssemblyAI
  • OpenAI Whisper
  • Overview
  • Cartesia
  • ElevenLabs
  • Google TTS
  • Azure Neural
  • OpenAI TTS
  • Deepgram Aura
  • Sarvam Bulbul
  • HeyPixa Luna
  • Overview
  • OpenAI GPT-4o
  • Gemini 2.0/2.5 Flash
  • Gemini Live (Native Audio)
  • OpenAI Realtime
  • Anthropic Claude
  • Azure OpenAI
  • Overview
  • VAD (Voice Activity Detection)
  • Interruption Handling
  • Turn Detection
  • Audio Processing
  • Function Calling
  • Call Transfer
  • DTMF Handling
  • Call Recording
  • Exporting Recordings
  • Transcripts
  • Webhooks
  • Variables & Templates
  • Multi-Language Support
  • Hindi
  • Tamil
  • Assamese
  • Other Indian Languages
  • Latency Optimization
  • Scaling & Performance
  • Error Handling
  • Monitoring & Logging
  • Security Best Practices
  • Trigger Call via API
  • REST API
  • WebSocket Protocol
  • Webhooks
  • Webhook Subscriptions
  • SDKs
  • Overview
  • Financial Services
  • E-commerce
  • Logistics
  • Hyperlocal
  • Healthcare
  • Education
  • Overview
  • Customer Support
  • Sales & Lead Conversion
  • Marketing Campaigns
  • Debt Collection
  • Overview
  • Customer Support Bot
  • Order Status IVR
  • Appointment Booking
  • Lead Qualification
  • Outbound Sales
  • Recruitment Screening
  • Overview
  • Migrate from Vapi
  • Migrate from Retell AI
  • Migrate from Traditional IVR
  1. Docs
  2. AI Voice Agent
  3. Use Cases
  4. Marketing Campaigns

AI Voice Agents for Marketing Campaigns

Build intelligent voice agents for promotional calls, product announcements, survey collection, event invitations, and feedback campaigns with compliance-first design.

AI Voice Agents for Marketing Campaigns

Deploy AI-powered voice agents for scalable marketing campaigns that drive engagement, collect valuable customer insights, and convert prospects while maintaining full regulatory compliance.

Use Cases Overview

Use Case Description Typical Duration Best Time
Promotional Calls Share offers, discounts, limited-time deals 45-90 seconds 10 AM - 12 PM, 4-6 PM
Product Announcements Introduce new products/features to existing customers 60-120 seconds 11 AM - 1 PM
Survey Collection Gather feedback, NPS scores, market research 2-4 minutes 10 AM - 12 PM
Event Invitations Webinars, conferences, product launches 60-90 seconds 2-4 PM
Feedback Calls Post-purchase satisfaction, service reviews 2-3 minutes 24-48 hours post-interaction

Agent Configuration

Marketing Campaign Agent

{
  "agent": {
    "name": "Marketing Campaign Agent",
    "language": "en-US",

    "llmProvider": "gemini-2.5",
    "llmModel": "gemini-2.5-flash-lite",
    "llmTemperature": 0.7,

    "sttProvider": "deepgram",
    "sttModel": "nova-3",
    "sttConfig": {
      "endpointing": 400,
      "interimResults": true,
      "utteranceEndMs": 1200
    },

    "ttsProvider": "cartesia",
    "ttsVoice": "95856005-0332-41b0-935f-352e296aa0df",

    "greetingMessage": "Hi {{contactName}}! This is {{agentName}} from {{companyName}}. I'm calling with {{campaignHook}}. Do you have a quick moment?",

    "prompt": "...",

    "allowInterruptions": true,

    "endCallPhrases": ["not interested", "remove me", "do not call", "stop calling"],

    "maxDuration": 180,

    "webhooks": {
      "url": "https://your-server.com/webhooks/marketing",
      "events": ["call.started", "call.ended", "opt_out.requested"]
    }
  }
}

Multi-Language Campaign (Hindi)

{
  "agent": {
    "name": "Hindi Marketing Agent",
    "language": "hi-IN",

    "llmProvider": "gemini-2.5",
    "llmModel": "gemini-2.5-flash-lite",

    "sttProvider": "deepgram",
    "sttModel": "nova-3",
    "sttConfig": {
      "language": "hi"
    },

    "ttsProvider": "azure",
    "ttsVoice": "hi-IN-SwaraNeural",

    "greetingMessage": "{{contactName}} ji, namaste! Main {{agentName}} bol rahi hoon {{companyName}} se. {{campaignHook}} ke baare mein baat karni thi. Kya aapke paas ek minute hai?",

    "prompt": "..."
  }
}

System Prompt Templates

Promotional Campaign Prompt

You are a friendly marketing representative for {{companyName}}. Your goal is to share an exclusive offer with customers and gauge their interest.

## Campaign Details
- Campaign: {{campaignName}}
- Offer: {{offerDetails}}
- Valid Until: {{offerExpiry}}
- Promo Code: {{promoCode}}

## Customer Context
- Name: {{contactName}}
- Customer Since: {{customerSince}}
- Last Purchase: {{lastPurchase}}
- Segment: {{customerSegment}}

## Call Script

### Opening (10 seconds)
Get permission to continue. Be warm and respectful of their time.

"Hi {{contactName}}! This is {{agentName}} from {{companyName}}.
I'm reaching out with a special offer for our valued customers.
Do you have 30 seconds?"

### Value Proposition (20 seconds)
Share the offer clearly and concisely.

"As a thank you for being with us since {{customerSince}}, we're offering you
{{offerDetails}}. This is an exclusive offer just for customers like you."

### Interest Check
Ask if they're interested without being pushy.

"Does this sound like something you'd find useful?"

### Positive Response
If interested, provide clear next steps.

"Great! You can use code {{promoCode}} at checkout.
Shall I send the details to your registered email/phone?"

### Negative Response
Respect their decision and exit gracefully.

"No problem at all! Just wanted to make sure you knew about it.
Have a great day, {{contactName}}!"

## Key Rules
1. NEVER pressure or manipulate
2. Accept "no" gracefully on first decline
3. Keep total call under 90 seconds
4. Always offer opt-out if requested
5. Don't repeat the same pitch twice
6. Be conversational, not scripted
7. If they say "not interested" or "remove me", immediately offer opt-out

## DND Handling
If customer requests to be removed:
"Absolutely! I'll remove you from our call list right away.
My apologies for any inconvenience. Have a great day!"
-> Call opt_out_customer function immediately
-> End call gracefully

Survey Collection Prompt

You are conducting a customer satisfaction survey for {{companyName}}. Your goal is to collect honest feedback in a conversational manner.

## Survey Details
- Survey: {{surveyName}}
- Questions: {{questionCount}} questions
- Estimated Time: {{estimatedTime}}
- Incentive: {{surveyIncentive}}

## Customer Context
- Name: {{contactName}}
- Recent Interaction: {{recentInteraction}}
- Interaction Date: {{interactionDate}}

## Survey Flow

### Opening
"Hi {{contactName}}! This is {{agentName}} from {{companyName}}.
We value your feedback on {{recentInteraction}}.
Would you have {{estimatedTime}} for a quick survey? {{surveyIncentive}}"

### Questions
Ask each question naturally, acknowledging their responses.

{{surveyQuestions}}

### Rating Scale Explanation
For rating questions, explain the scale clearly:
"On a scale of 1 to 10, where 1 is very unsatisfied and 10 is extremely satisfied..."

### Follow-up on Low Scores
If score < 7: "I appreciate your honesty. Could you tell me what we could do better?"

### Closing
"Thank you so much for your time, {{contactName}}!
Your feedback helps us serve you better.
{{closingMessage}}"

## Guidelines
1. One question at a time
2. Acknowledge each response before moving on
3. Don't argue with negative feedback
4. If they want to elaborate, let them
5. Record all verbatim comments
6. Thank them regardless of feedback sentiment

Event Invitation Prompt

You are inviting customers to {{eventName}} for {{companyName}}.

## Event Details
- Event: {{eventName}}
- Date: {{eventDate}}
- Time: {{eventTime}}
- Format: {{eventFormat}} (webinar/in-person/hybrid)
- Topic: {{eventTopic}}
- Speakers: {{eventSpeakers}}
- Registration Link: {{registrationUrl}}

## Customer Context
- Name: {{contactName}}
- Interest Areas: {{interestAreas}}
- Past Event Attendance: {{pastAttendance}}

## Call Script

### Opening
"Hi {{contactName}}! This is {{agentName}} from {{companyName}}.
I'm calling about our upcoming {{eventFormat}} on {{eventTopic}}.
Given your interest in {{interestAreas}}, I thought you'd find it valuable.
Do you have a minute?"

### Event Pitch
"We're hosting {{eventName}} on {{eventDate}} at {{eventTime}}.
{{eventSpeakers}} will be covering {{eventTopic}}.
{{eventHighlight}}"

### Interest Check
"Would you be interested in joining us?"

### Registration
If interested:
"Great! I can register you right now. Can I confirm your email is {{customerEmail}}?"

OR

"I'll send you the registration link. You can sign up at your convenience."

### Not Interested
"No problem! Would you like me to keep you posted about future events on {{interestAreas}}?"

## Guidelines
1. Highlight relevance to their interests
2. Keep it brief - they can learn more online
3. Make registration easy
4. Offer calendar invite option
5. Respect time zones for event times

Function Tools

Campaign Management

{
  "type": "function",
  "function": {
    "name": "record_campaign_response",
    "description": "Record customer response to marketing campaign",
    "parameters": {
      "type": "object",
      "properties": {
        "contact_id": {
          "type": "string",
          "description": "Customer contact ID"
        },
        "campaign_id": {
          "type": "string",
          "description": "Campaign identifier"
        },
        "response": {
          "type": "string",
          "enum": ["interested", "not_interested", "callback", "already_purchased", "wrong_number"],
          "description": "Customer response"
        },
        "interest_level": {
          "type": "integer",
          "minimum": 1,
          "maximum": 10,
          "description": "Interest level 1-10"
        },
        "follow_up_needed": {
          "type": "boolean",
          "description": "Whether follow-up is needed"
        },
        "notes": {
          "type": "string",
          "description": "Additional notes from conversation"
        }
      },
      "required": ["contact_id", "campaign_id", "response"]
    }
  }
}

Opt-Out Handling

{
  "type": "function",
  "function": {
    "name": "opt_out_customer",
    "description": "Add customer to Do Not Call list and stop all marketing communications",
    "parameters": {
      "type": "object",
      "properties": {
        "contact_id": {
          "type": "string",
          "description": "Customer contact ID"
        },
        "phone_number": {
          "type": "string",
          "description": "Phone number to add to DNC"
        },
        "opt_out_type": {
          "type": "string",
          "enum": ["all_calls", "marketing_only", "specific_campaign"],
          "description": "Type of opt-out requested"
        },
        "reason": {
          "type": "string",
          "description": "Reason for opt-out if provided"
        },
        "campaign_id": {
          "type": "string",
          "description": "Campaign ID if specific campaign opt-out"
        }
      },
      "required": ["contact_id", "phone_number", "opt_out_type"]
    }
  }
}

Survey Response Collection

{
  "type": "function",
  "function": {
    "name": "record_survey_response",
    "description": "Record customer survey response",
    "parameters": {
      "type": "object",
      "properties": {
        "survey_id": {
          "type": "string",
          "description": "Survey identifier"
        },
        "contact_id": {
          "type": "string",
          "description": "Customer contact ID"
        },
        "question_id": {
          "type": "string",
          "description": "Question identifier"
        },
        "response_type": {
          "type": "string",
          "enum": ["rating", "multiple_choice", "open_text", "yes_no"],
          "description": "Type of response"
        },
        "response_value": {
          "type": "string",
          "description": "The actual response"
        },
        "sentiment": {
          "type": "string",
          "enum": ["positive", "neutral", "negative"],
          "description": "Detected sentiment"
        }
      },
      "required": ["survey_id", "contact_id", "question_id", "response_value"]
    }
  }
}

Event Registration

{
  "type": "function",
  "function": {
    "name": "register_for_event",
    "description": "Register customer for an event",
    "parameters": {
      "type": "object",
      "properties": {
        "event_id": {
          "type": "string",
          "description": "Event identifier"
        },
        "contact_id": {
          "type": "string",
          "description": "Customer contact ID"
        },
        "email": {
          "type": "string",
          "description": "Email for confirmation"
        },
        "send_calendar_invite": {
          "type": "boolean",
          "description": "Whether to send calendar invite"
        },
        "reminder_preference": {
          "type": "string",
          "enum": ["email", "sms", "both", "none"],
          "description": "Reminder notification preference"
        }
      },
      "required": ["event_id", "contact_id"]
    }
  }
}

Send Promotional SMS/Email

{
  "type": "function",
  "function": {
    "name": "send_follow_up",
    "description": "Send follow-up SMS or email with offer details",
    "parameters": {
      "type": "object",
      "properties": {
        "contact_id": {
          "type": "string",
          "description": "Customer contact ID"
        },
        "channel": {
          "type": "string",
          "enum": ["sms", "email", "whatsapp"],
          "description": "Communication channel"
        },
        "template": {
          "type": "string",
          "enum": ["offer_details", "event_registration", "survey_link", "promo_code"],
          "description": "Message template to use"
        },
        "personalization": {
          "type": "object",
          "description": "Custom variables for template"
        }
      },
      "required": ["contact_id", "channel", "template"]
    }
  }
}

Tool Handlers Implementation

package handlers

import (
    "context"
    "fmt"
    "time"
)

// OptOutHandler handles DNC requests with compliance logging
func OptOutHandler(params map[string]any) (string, error) {
    contactID := params["contact_id"].(string)
    phoneNumber := params["phone_number"].(string)
    optOutType := params["opt_out_type"].(string)

    // Add to internal DNC list immediately
    err := dncService.AddToDNCList(DNCEntry{
        PhoneNumber: phoneNumber,
        ContactID:   contactID,
        OptOutType:  optOutType,
        Timestamp:   time.Now(),
        Source:      "voice_agent",
    })
    if err != nil {
        log.Error("Failed to add to DNC", "error", err)
        return "I'll make sure to update our records.", err
    }

    // Log for compliance audit
    auditLog.Record(AuditEntry{
        Action:      "OPT_OUT",
        ContactID:   contactID,
        PhoneNumber: phoneNumber,
        Type:        optOutType,
        Timestamp:   time.Now(),
    })

    // Cancel any scheduled campaigns for this contact
    campaignService.CancelScheduledCalls(contactID)

    return "Done. I've removed you from our call list. You won't receive any more marketing calls from us. I apologize for any inconvenience.", nil
}

// RecordCampaignResponse tracks campaign engagement
func RecordCampaignResponse(params map[string]any) (string, error) {
    response := CampaignResponse{
        ContactID:      params["contact_id"].(string),
        CampaignID:     params["campaign_id"].(string),
        Response:       params["response"].(string),
        Timestamp:      time.Now(),
    }

    if interestLevel, ok := params["interest_level"].(float64); ok {
        response.InterestLevel = int(interestLevel)
    }
    if notes, ok := params["notes"].(string); ok {
        response.Notes = notes
    }
    if followUp, ok := params["follow_up_needed"].(bool); ok {
        response.FollowUpNeeded = followUp
    }

    err := campaignDB.SaveResponse(response)
    if err != nil {
        return "", err
    }

    // Update campaign metrics in real-time
    metrics.IncrementResponse(response.CampaignID, response.Response)

    // Trigger follow-up workflow if needed
    if response.FollowUpNeeded {
        workflowEngine.TriggerFollowUp(response)
    }

    return "Response recorded successfully.", nil
}

// RecordSurveyResponse handles survey data collection
func RecordSurveyResponse(params map[string]any) (string, error) {
    surveyResponse := SurveyResponse{
        SurveyID:      params["survey_id"].(string),
        ContactID:     params["contact_id"].(string),
        QuestionID:    params["question_id"].(string),
        ResponseValue: params["response_value"].(string),
        Timestamp:     time.Now(),
    }

    if responseType, ok := params["response_type"].(string); ok {
        surveyResponse.ResponseType = responseType
    }
    if sentiment, ok := params["sentiment"].(string); ok {
        surveyResponse.Sentiment = sentiment
    }

    err := surveyDB.SaveResponse(surveyResponse)
    if err != nil {
        return "", err
    }

    // For NPS surveys, trigger alerts on detractor scores
    if surveyResponse.ResponseType == "rating" {
        score := parseRating(surveyResponse.ResponseValue)
        if score <= 6 {
            alertService.NotifyDetractor(surveyResponse)
        }
    }

    return "Thank you for that feedback.", nil
}

Compliance Framework

Regulatory Requirements

India (TRAI/NCPR)

// TRAI Compliance for India
type TRAICompliance struct {
    // National Customer Preference Register
    NCPREnabled bool

    // Calling hours: 9 AM - 9 PM (customer's local time)
    CallingHoursStart int // 9
    CallingHoursEnd   int // 21

    // Maximum calls per day per number
    MaxCallsPerDay int // 3

    // Mandatory scrubbing against NCPR before campaign
    NCPRScrubRequired bool

    // Cool-off period after opt-out (days)
    OptOutCoolOffDays int // 0 (immediate)

    // Registration requirements
    HeaderRegistered bool
    TemplateApproved bool
}

func validateTRAICompliance(contact *Contact, campaign *Campaign) error {
    // Check NCPR registration
    if isOnNCPR(contact.Phone) {
        return errors.New("contact is registered on NCPR")
    }

    // Validate calling hours
    localTime := getLocalTime(contact.Timezone)
    if localTime.Hour() < 9 || localTime.Hour() >= 21 {
        return errors.New("outside permitted calling hours (9 AM - 9 PM)")
    }

    // Check daily call limit
    callsToday := getCallCountToday(contact.Phone)
    if callsToday >= 3 {
        return errors.New("daily call limit reached for this number")
    }

    // Verify sender header registration
    if !isHeaderRegistered(campaign.SenderID) {
        return errors.New("sender header not registered with TRAI")
    }

    return nil
}

United States (TCPA)

// TCPA Compliance for US
type TCPACompliance struct {
    // Prior express written consent required for marketing
    ConsentRequired bool

    // Calling hours: 8 AM - 9 PM (recipient's local time)
    CallingHoursStart int // 8
    CallingHoursEnd   int // 21

    // National Do Not Call Registry check
    DNDRegistryCheck bool

    // Internal DNC list maintenance (minimum 5 years)
    InternalDNCRetentionYears int // 5

    // Abandoned call rate < 3%
    MaxAbandonedCallRate float64 // 0.03

    // Caller ID requirements
    CallerIDRequired bool
    CallerIDAccurate bool
}

func validateTCPACompliance(contact *Contact, campaign *Campaign) error {
    // Verify prior express consent
    consent, err := getMarketingConsent(contact.ID)
    if err != nil || !consent.Valid {
        return errors.New("no valid marketing consent on file")
    }

    // Check National DNC Registry
    if isOnNationalDNC(contact.Phone) {
        return errors.New("contact is on National DNC Registry")
    }

    // Check internal DNC list
    if isOnInternalDNC(contact.Phone) {
        return errors.New("contact is on internal DNC list")
    }

    // Validate calling hours
    localTime := getLocalTime(contact.Timezone)
    if localTime.Hour() < 8 || localTime.Hour() >= 21 {
        return errors.New("outside permitted calling hours (8 AM - 9 PM)")
    }

    return nil
}

European Union (GDPR + ePrivacy)

// GDPR/ePrivacy Compliance for EU
type GDPRCompliance struct {
    // Explicit opt-in consent required
    ExplicitConsentRequired bool

    // Purpose limitation
    ConsentPurposeSpecific bool

    // Right to be forgotten
    DataDeletionSupported bool

    // Consent record retention
    ConsentRecordRetentionYears int // 7

    // Country-specific calling hours
    CallingHoursByCountry map[string]CallingHours
}

func validateGDPRCompliance(contact *Contact, campaign *Campaign) error {
    // Verify explicit opt-in consent
    consent, err := getGDPRConsent(contact.ID, campaign.Purpose)
    if err != nil || !consent.ExplicitOptIn {
        return errors.New("no explicit GDPR consent for this purpose")
    }

    // Verify consent hasn't been withdrawn
    if consent.Withdrawn {
        return errors.New("consent has been withdrawn")
    }

    // Check country-specific regulations
    if contact.Country == "DE" { // Germany - stricter rules
        if !consent.DoubleOptIn {
            return errors.New("double opt-in required for Germany")
        }
    }

    return nil
}

DND/DNC List Management

// Comprehensive DNC Management
type DNCManager struct {
    db           *sql.DB
    cache        *redis.Client
    ncprClient   *NCPRClient   // India
    ftcClient    *FTCDNCClient // US
}

// Pre-campaign scrubbing
func (m *DNCManager) ScrubCampaignList(contacts []Contact, region string) ([]Contact, []Contact) {
    var eligible, blocked []Contact

    for _, contact := range contacts {
        blocked_reason := m.checkDNCStatus(contact, region)
        if blocked_reason == "" {
            eligible = append(eligible, contact)
        } else {
            contact.BlockedReason = blocked_reason
            blocked = append(blocked, contact)
        }
    }

    return eligible, blocked
}

func (m *DNCManager) checkDNCStatus(contact Contact, region string) string {
    // Check internal DNC first (fastest)
    if m.isOnInternalDNC(contact.Phone) {
        return "internal_dnc"
    }

    // Check regional registries
    switch region {
    case "IN":
        if m.ncprClient.IsRegistered(contact.Phone) {
            return "ncpr_registered"
        }
    case "US":
        if m.ftcClient.IsOnRegistry(contact.Phone) {
            return "ftc_dnc_registry"
        }
    }

    // Check opt-out history
    if m.hasOptedOut(contact.ID) {
        return "previous_optout"
    }

    return ""
}

// Real-time opt-out processing
func (m *DNCManager) ProcessOptOut(request OptOutRequest) error {
    // Add to internal DNC immediately
    err := m.db.Exec(`
        INSERT INTO dnc_list (phone_number, contact_id, opt_out_type, source, created_at)
        VALUES ($1, $2, $3, $4, NOW())
        ON CONFLICT (phone_number) DO UPDATE SET
            opt_out_type = EXCLUDED.opt_out_type,
            updated_at = NOW()
    `, request.PhoneNumber, request.ContactID, request.OptOutType, request.Source)

    if err != nil {
        return err
    }

    // Invalidate cache
    m.cache.Del(context.Background(), "dnc:"+request.PhoneNumber)

    // Notify all campaign systems
    m.broadcastOptOut(request)

    return nil
}

Consent Management

// Consent tracking and validation
type ConsentRecord struct {
    ContactID     string
    Purpose       string      // "marketing", "surveys", "product_updates"
    ConsentType   string      // "explicit", "implicit", "double_optin"
    ConsentMethod string      // "web_form", "verbal", "written", "sms"
    ConsentText   string      // Exact consent language shown
    Timestamp     time.Time
    ExpiresAt     *time.Time  // Some jurisdictions require renewal
    Withdrawn     bool
    WithdrawnAt   *time.Time
    IPAddress     string      // For web consent
    CallRecording string      // For verbal consent (recording URL)
}

func validateConsent(contactID string, purpose string, region string) (*ConsentRecord, error) {
    consent, err := db.GetConsent(contactID, purpose)
    if err != nil {
        return nil, fmt.Errorf("no consent record found")
    }

    // Check if consent is still valid
    if consent.Withdrawn {
        return nil, fmt.Errorf("consent withdrawn on %v", consent.WithdrawnAt)
    }

    // Check expiration (if applicable)
    if consent.ExpiresAt != nil && time.Now().After(*consent.ExpiresAt) {
        return nil, fmt.Errorf("consent expired on %v", consent.ExpiresAt)
    }

    // Region-specific validation
    switch region {
    case "EU":
        if consent.ConsentType != "explicit" {
            return nil, fmt.Errorf("explicit consent required for EU")
        }
    case "US":
        if consent.ConsentMethod == "verbal" && consent.CallRecording == "" {
            return nil, fmt.Errorf("verbal consent requires call recording")
        }
    }

    return consent, nil
}

Campaign Metrics

Key Performance Indicators

type CampaignMetrics struct {
    // Reach Metrics
    TotalContacts       int
    ContactsAttempted   int
    ContactsReached     int
    ReachRate           float64 // ContactsReached / ContactsAttempted

    // Engagement Metrics
    CallsAnswered       int
    AnswerRate          float64
    AvgCallDuration     time.Duration
    ListenThroughRate   float64 // % who listened to full message

    // Response Metrics
    PositiveResponses   int
    NegativeResponses   int
    CallbacksRequested  int
    ResponseRate        float64

    // Conversion Metrics
    Conversions         int
    ConversionRate      float64 // Conversions / ContactsReached
    RevenueGenerated    float64
    CostPerConversion   float64

    // Compliance Metrics
    OptOuts             int
    OptOutRate          float64
    Complaints          int
    ComplianceViolations int

    // Survey-Specific (if applicable)
    SurveyCompletions   int
    CompletionRate      float64
    AverageNPS          float64
}

func calculateCampaignMetrics(campaignID string) *CampaignMetrics {
    calls := db.GetCampaignCalls(campaignID)

    metrics := &CampaignMetrics{
        TotalContacts: len(calls),
    }

    var totalDuration time.Duration
    for _, call := range calls {
        metrics.ContactsAttempted++

        if call.Status == "answered" {
            metrics.CallsAnswered++
            metrics.ContactsReached++
            totalDuration += call.Duration

            switch call.Outcome {
            case "interested", "converted":
                metrics.PositiveResponses++
            case "not_interested":
                metrics.NegativeResponses++
            case "callback":
                metrics.CallbacksRequested++
            case "opt_out":
                metrics.OptOuts++
            }

            if call.Converted {
                metrics.Conversions++
                metrics.RevenueGenerated += call.ConversionValue
            }
        }
    }

    // Calculate rates
    if metrics.ContactsAttempted > 0 {
        metrics.ReachRate = float64(metrics.ContactsReached) / float64(metrics.ContactsAttempted)
        metrics.AnswerRate = float64(metrics.CallsAnswered) / float64(metrics.ContactsAttempted)
    }
    if metrics.ContactsReached > 0 {
        metrics.ConversionRate = float64(metrics.Conversions) / float64(metrics.ContactsReached)
        metrics.OptOutRate = float64(metrics.OptOuts) / float64(metrics.ContactsReached)
        metrics.ResponseRate = float64(metrics.PositiveResponses+metrics.NegativeResponses) / float64(metrics.ContactsReached)
    }
    if metrics.CallsAnswered > 0 {
        metrics.AvgCallDuration = totalDuration / time.Duration(metrics.CallsAnswered)
    }
    if metrics.Conversions > 0 {
        campaignCost := getCampaignCost(campaignID)
        metrics.CostPerConversion = campaignCost / float64(metrics.Conversions)
    }

    return metrics
}

Real-Time Dashboard

// Streaming metrics for live dashboards
type LiveCampaignStats struct {
    CampaignID        string    `json:"campaign_id"`
    ActiveCalls       int       `json:"active_calls"`
    CallsThisHour     int       `json:"calls_this_hour"`
    AnswerRateToday   float64   `json:"answer_rate_today"`
    ConversionsToday  int       `json:"conversions_today"`
    OptOutsToday      int       `json:"opt_outs_today"`
    LastUpdated       time.Time `json:"last_updated"`
}

func streamCampaignMetrics(campaignID string, ch chan<- LiveCampaignStats) {
    ticker := time.NewTicker(5 * time.Second)
    defer ticker.Stop()

    for range ticker.C {
        stats := LiveCampaignStats{
            CampaignID:       campaignID,
            ActiveCalls:      getActiveCalls(campaignID),
            CallsThisHour:    getCallsInWindow(campaignID, time.Hour),
            AnswerRateToday:  calculateTodayAnswerRate(campaignID),
            ConversionsToday: getTodayConversions(campaignID),
            OptOutsToday:     getTodayOptOuts(campaignID),
            LastUpdated:      time.Now(),
        }
        ch <- stats
    }
}

Benchmark Targets

Metric Poor Average Good Excellent
Answer Rate < 15% 15-25% 25-35% > 35%
Listen-Through Rate < 40% 40-60% 60-80% > 80%
Conversion Rate < 1% 1-3% 3-5% > 5%
Opt-Out Rate > 5% 3-5% 1-3% < 1%
Avg Call Duration < 30s 30-60s 60-90s 90-120s
Survey Completion < 30% 30-50% 50-70% > 70%

Campaign Orchestration

Campaign Setup API

# Create a new marketing campaign
curl -X POST https://api.edesy.in/v1/campaigns \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Summer Sale 2025",
    "type": "promotional",
    "agent_id": "marketing_agent_v2",
    "schedule": {
      "start_date": "2025-06-01",
      "end_date": "2025-06-30",
      "calling_hours": {
        "start": "10:00",
        "end": "18:00",
        "timezone": "customer_local"
      },
      "days_of_week": ["monday", "tuesday", "wednesday", "thursday", "friday"],
      "calls_per_hour": 100,
      "max_attempts_per_contact": 3
    },
    "compliance": {
      "region": "IN",
      "scrub_dnc": true,
      "consent_required": true
    },
    "variables": {
      "campaignName": "Summer Sale",
      "offerDetails": "flat 30% off on all products",
      "promoCode": "SUMMER30",
      "offerExpiry": "June 30th"
    }
  }'

Upload Contact List

# Upload contacts with segmentation
curl -X POST https://api.edesy.in/v1/campaigns/camp_123/contacts \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contacts": [
      {
        "phone": "+919876543210",
        "name": "Rahul Sharma",
        "email": "[email protected]",
        "segment": "high_value",
        "language": "hi-IN",
        "timezone": "Asia/Kolkata",
        "custom_variables": {
          "lastPurchase": "May 15, 2025",
          "customerSince": "2023"
        }
      }
    ],
    "dedupe": true,
    "validate_phones": true
  }'

Start Campaign

# Launch campaign with rate limiting
curl -X POST https://api.edesy.in/v1/campaigns/camp_123/start \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "mode": "gradual",
    "ramp_up_minutes": 30,
    "initial_rate": 10,
    "target_rate": 100
  }'

Best Practices

1. Respect Customer Time

// Best calling windows by region and segment
var optimalCallingWindows = map[string]map[string]CallingWindow{
    "IN": {
        "professional": {Start: "10:00", End: "12:00", Days: []string{"Mon", "Tue", "Wed", "Thu"}},
        "homemaker":    {Start: "11:00", End: "13:00", Days: []string{"Mon", "Tue", "Wed", "Thu", "Fri"}},
        "senior":       {Start: "10:00", End: "11:30", Days: []string{"Mon", "Wed", "Fri"}},
    },
    "US": {
        "professional": {Start: "11:00", End: "13:00", Days: []string{"Tue", "Wed", "Thu"}},
        "consumer":     {Start: "17:00", End: "19:00", Days: []string{"Mon", "Tue", "Wed", "Thu"}},
    },
}

func getOptimalCallTime(contact *Contact) time.Time {
    window := optimalCallingWindows[contact.Region][contact.Segment]
    return findNextAvailableSlot(window, contact.Timezone)
}

2. Personalization

// Dynamic message personalization
func personalizeMessage(template string, contact *Contact, campaign *Campaign) string {
    // Basic variable replacement
    message := strings.ReplaceAll(template, "{{contactName}}", contact.FirstName)
    message = strings.ReplaceAll(message, "{{companyName}}", campaign.CompanyName)

    // Segment-specific messaging
    switch contact.Segment {
    case "high_value":
        message = strings.ReplaceAll(message, "{{exclusiveOffer}}", "as one of our VIP customers")
    case "at_risk":
        message = strings.ReplaceAll(message, "{{exclusiveOffer}}", "we miss you and wanted to share")
    default:
        message = strings.ReplaceAll(message, "{{exclusiveOffer}}", "we have something special")
    }

    // Time-aware greetings
    hour := time.Now().In(contact.Timezone).Hour()
    var greeting string
    switch {
    case hour < 12:
        greeting = "Good morning"
    case hour < 17:
        greeting = "Good afternoon"
    default:
        greeting = "Good evening"
    }
    message = strings.ReplaceAll(message, "{{greeting}}", greeting)

    return message
}

3. Graceful Exit Strategies

## Exit Scenarios

### Immediate Opt-Out Request
Customer: "Don't call me again" / "Remove me from your list"
Response: "Absolutely, I've removed you from our list. My apologies for the inconvenience. Have a great day!"
Action: Call opt_out_customer immediately, end call.

### Busy Customer
Customer: "I'm busy right now"
Response: "No problem! Would tomorrow around the same time work better, or would you prefer I don't call back?"
Action: If callback requested, schedule. If not, mark as "not_interested" and respect decision.

### Not the Right Person
Customer: "I'm not the right person for this"
Response: "My apologies! Could you point me to the right person, or would you prefer I don't call this number?"
Action: If referral given, note it. Otherwise, mark as "wrong_contact".

### Hostile Customer
Customer: [Angry/abusive]
Response: "I sincerely apologize for any inconvenience. I'll make sure you're not contacted again. Have a good day."
Action: Opt-out immediately, flag for review, end call gracefully.

4. A/B Testing

{
  "campaign": {
    "id": "summer_promo_2025",
    "ab_test": {
      "enabled": true,
      "variants": [
        {
          "id": "control",
          "weight": 34,
          "greeting": "Hi {{contactName}}! This is {{agentName}} from {{companyName}} with a special offer for you."
        },
        {
          "id": "urgency",
          "weight": 33,
          "greeting": "Hi {{contactName}}! This is {{agentName}} from {{companyName}}. I'm calling because we have a limited-time offer ending this week."
        },
        {
          "id": "social_proof",
          "weight": 33,
          "greeting": "Hi {{contactName}}! This is {{agentName}} from {{companyName}}. Thousands of customers are loving our summer sale - wanted to make sure you knew about it."
        }
      ],
      "success_metric": "conversion_rate",
      "minimum_sample_size": 1000,
      "statistical_significance": 0.95
    }
  }
}

5. Frequency Capping

// Prevent contact fatigue
type FrequencyCapConfig struct {
    MaxCallsPerDay    int           // Default: 1
    MaxCallsPerWeek   int           // Default: 3
    MaxCallsPerMonth  int           // Default: 6
    MinDaysBetweenCalls int         // Default: 2
    CooldownAfterOptOut time.Duration // Default: forever
}

func canContactToday(contactID string, config FrequencyCapConfig) (bool, string) {
    // Check daily cap
    callsToday := db.GetCallCountToday(contactID)
    if callsToday >= config.MaxCallsPerDay {
        return false, "daily_cap_reached"
    }

    // Check weekly cap
    callsThisWeek := db.GetCallCountThisWeek(contactID)
    if callsThisWeek >= config.MaxCallsPerWeek {
        return false, "weekly_cap_reached"
    }

    // Check minimum days between calls
    lastCall := db.GetLastCallTime(contactID)
    if lastCall != nil {
        daysSinceLastCall := time.Since(*lastCall).Hours() / 24
        if daysSinceLastCall < float64(config.MinDaysBetweenCalls) {
            return false, "too_soon_since_last_call"
        }
    }

    return true, ""
}

6. Quality Monitoring

// Automated quality checks
type QualityMetrics struct {
    SentimentScore    float64 // -1 to 1
    ComplianceScore   float64 // 0 to 100
    ScriptAdherence   float64 // 0 to 100
    CustomerSatisfaction float64 // 1 to 5
}

func analyzeCallQuality(callID string) *QualityMetrics {
    transcript := getTranscript(callID)

    metrics := &QualityMetrics{}

    // Sentiment analysis
    metrics.SentimentScore = nlp.AnalyzeSentiment(transcript)

    // Compliance check
    metrics.ComplianceScore = checkComplianceInTranscript(transcript)

    // Script adherence
    metrics.ScriptAdherence = compareToScript(transcript, expectedScript)

    // Flag calls that need review
    if metrics.SentimentScore < -0.3 || metrics.ComplianceScore < 80 {
        flagForReview(callID, metrics)
    }

    return metrics
}

Next Steps

  • Outbound Sales - Sales-focused campaigns
  • Lead Qualification - Qualify marketing leads
  • Function Calling - Tool integration
  • Webhooks - Campaign event handling
  • Multi-Language Support - Regional campaigns
Previous
Sales & Lead Conversion
Next
Debt Collection

On this page

  • Use Cases Overview
  • Agent Configuration
  • Marketing Campaign Agent
  • Multi-Language Campaign (Hindi)
  • System Prompt Templates
  • Promotional Campaign Prompt
  • Campaign Details
  • Customer Context
  • Call Script
  • Opening (10 seconds)
  • Value Proposition (20 seconds)
  • Interest Check
  • Positive Response
  • Negative Response
  • Key Rules
  • DND Handling
  • Survey Collection Prompt
  • Survey Details
  • Customer Context
  • Survey Flow
  • Opening
  • Questions
  • Rating Scale Explanation
  • Follow-up on Low Scores
  • Closing
  • Guidelines
  • Event Invitation Prompt
  • Event Details
  • Customer Context
  • Call Script
  • Opening
  • Event Pitch
  • Interest Check
  • Registration
  • Not Interested
  • Guidelines
  • Function Tools
  • Campaign Management
  • Opt-Out Handling
  • Survey Response Collection
  • Event Registration
  • Send Promotional SMS/Email
  • Tool Handlers Implementation
  • Compliance Framework
  • Regulatory Requirements
  • India (TRAI/NCPR)
  • United States (TCPA)
  • European Union (GDPR + ePrivacy)
  • DND/DNC List Management
  • Consent Management
  • Campaign Metrics
  • Key Performance Indicators
  • Real-Time Dashboard
  • Benchmark Targets
  • Campaign Orchestration
  • Campaign Setup API
  • Upload Contact List
  • Start Campaign
  • Best Practices
  • 1. Respect Customer Time
  • 2. Personalization
  • 3. Graceful Exit Strategies
  • Exit Scenarios
  • Immediate Opt-Out Request
  • Busy Customer
  • Not the Right Person
  • Hostile Customer
  • 4. A/B Testing
  • 5. Frequency Capping
  • 6. Quality Monitoring
  • Next Steps

Stay Updated

Get the latest updates on AI voice technology, product releases, and exclusive resources.

Get Started

Try our products for free
AI Voice Agent
Build voice AI for calls
WhatsApp AI Bot
Automate WhatsApp chats
Website Chatbot
AI chat for websites
Edesy CRM
Manage leads & customers
Book a DemoCall UsEmail Us
Eedesy

Your all-in-one platform for digital innovation. We build AI-powered solutions that transform how businesses operate.

[email protected]+91 95475 31359

Products

  • AI Voice Assistant
  • WhatsApp Voice AI
  • WhatsApp Bot Builder
  • AI Website Chatbot
  • AI-SDR
  • Number Masking
  • Shopify Apps
  • View All Products

Solutions

  • For E-commerce
  • For Healthcare
  • For Real Estate
  • For Restaurants
  • For Appointments
  • View All Use Cases

Services

  • AI Chatbot Development
  • Voice AI Development
  • Shopify Development
  • SaaS Development
  • WhatsApp API Integration
  • View All Services

Resources

  • Documentation
  • Voice Agent Docs
  • API Reference
  • Number Masking API Docs
  • Blog
  • Changelog
  • Book a Demo

Company

  • About Us
  • Contact
  • Careers
  • Privacy Policy
  • Terms of Service

Products

  • AI Voice Assistant
  • WhatsApp Voice AI
  • WhatsApp Bot Builder
  • AI Website Chatbot
  • AI-SDR
  • Number Masking
  • Shopify Apps
  • View All Products

Solutions

  • For E-commerce
  • For Healthcare
  • For Real Estate
  • For Restaurants
  • For Appointments
  • View All Use Cases

Services

  • AI Chatbot Development
  • Voice AI Development
  • Shopify Development
  • SaaS Development
  • WhatsApp API Integration
  • View All Services

Resources

  • Documentation
  • Voice Agent Docs
  • API Reference
  • Number Masking API Docs
  • Blog
  • Changelog
  • Book a Demo

Company

  • About Us
  • Contact
  • Careers
  • Privacy Policy
  • Terms of Service
  • AI Voice Assistant
  • WhatsApp Voice AI
  • WhatsApp Bot Builder
  • AI Website Chatbot
  • AI-SDR
  • Number Masking
  • Shopify Apps
  • View All Products
  • For E-commerce
  • For Healthcare
  • For Real Estate
  • For Restaurants
  • For Appointments
  • View All Use Cases
  • AI Chatbot Development
  • Voice AI Development
  • Shopify Development
  • SaaS Development
  • WhatsApp API Integration
  • View All Services
  • Documentation
  • Voice Agent Docs
  • API Reference
  • Number Masking API Docs
  • Blog
  • Changelog
  • Book a Demo
  • About Us
  • Contact
  • Careers
  • Privacy Policy
  • Terms of Service

Popular Free Tools

Compress PDFMerge PDFPDF to WordGST CalculatorEMI CalculatorSIP CalculatorJSON FormatterBase64 EncoderImage CompressorQR Code GeneratorVoice AI ROI CalculatorAmazon FBA CalculatorAI Email WriterVideo to GIFPrivacy Policy GeneratorCRM ROI CalculatorMeeting Cost Calculator
Categories:PDF ToolsDeveloper ToolsFinance CalculatorsImage ToolsVideo ToolsAI Writing ToolsAudio ToolsWhatsApp ToolsDocument GeneratorsVoice AI ToolsE-commerce ToolsView All Tools

© 2026 Edesy Technology Labs Pvt Ltd

SSL Secured
99.9% Uptime