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. Industries
  4. E-commerce

AI Voice Agents for E-commerce

Deploy AI voice agents to automate order tracking, delivery updates, COD confirmation, cart recovery, and returns - reduce WISMO calls by 70% and recover 15-25% of abandoned carts.

AI Voice Agents for E-commerce

Deploy AI voice agents to transform your e-commerce customer experience. Handle order inquiries, delivery updates, COD confirmations, returns, and abandoned cart recovery at scale.

Industry Impact

Metric Before Voice AI After Voice AI Improvement
WISMO Calls 100% to agents 30% to agents 70% reduction
Abandoned Cart Recovery 2-5% (email) 15-25% (voice) 5-10x higher
COD Confirmation Rate 60-70% 85-95% 25% increase
Return Processing Time 24-48 hours Real-time Instant initiation
Customer Wait Time 3-5 minutes 0 seconds Instant response

Use Cases

1. Order Status Tracking (WISMO)

Automate "Where Is My Order?" calls - the #1 support inquiry for e-commerce.

{
  "agent": {
    "name": "Order Tracker",
    "language": "en-US",

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

    "sttProvider": "deepgram",
    "sttModel": "nova-3",
    "sttConfig": {
      "endpointing": 250,
      "interimResults": true,
      "keywords": ["order:2", "tracking:2", "delivered:2", "shipped:2"]
    },

    "ttsProvider": "cartesia",
    "ttsVoice": "95856005-0332-41b0-935f-352e296aa0df",
    "ttsConfig": {
      "speed": 1.1
    },

    "greetingMessage": "Hello! Thanks for calling {{storeName}}. I can help you track your order. What's your order number or the phone number you used to place the order?",

    "allowInterruptions": true,

    "prompt": "..."
  }
}

2. Delivery Updates (Outbound)

Proactively notify customers about their delivery status.

{
  "agent": {
    "name": "Delivery Notifier",
    "type": "outbound",
    "language": "en-US",

    "greetingMessage": "Hi {{customerName}}! This is {{storeName}} calling about your order {{orderId}}. {{deliveryUpdate}}. Would you like me to repeat that or do you have any questions?",

    "prompt": "..."
  }
}

3. COD Order Confirmation

Confirm Cash-on-Delivery orders to reduce RTO (Return to Origin).

{
  "agent": {
    "name": "COD Confirmation",
    "type": "outbound",
    "language": "hi-IN",

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

    "sttProvider": "google",
    "sttModel": "chirp",

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

    "greetingMessage": "Namaste {{customerName}} ji! Main {{storeName}} se bol rahi hoon. Aapne {{productName}} ka order diya hai, total amount {{orderTotal}} hai, aur delivery {{deliveryDate}} tak hogi. Kya aap is order ko confirm karte hain?",

    "prompt": "..."
  }
}

4. Cart Recovery

Re-engage customers who abandoned their shopping carts.

{
  "agent": {
    "name": "Cart Recovery",
    "type": "outbound",

    "greetingMessage": "Hi {{customerName}}! This is {{storeName}}. I noticed you left some items in your cart - the {{productName}}. Just wanted to check if you had any questions I could help with?",

    "prompt": "..."
  }
}

5. Return Initiation

Process return requests and schedule pickups automatically.

{
  "agent": {
    "name": "Returns Handler",

    "greetingMessage": "Hello! I can help you with returns and exchanges. What would you like to return today?",

    "prompt": "..."
  }
}

System Prompts

Order Status Agent

You are a customer service agent for {{storeName}}, an e-commerce store. Your primary job is to help customers track their orders.

## Core Responsibilities
1. Look up order status using order ID or phone number
2. Provide clear delivery estimates
3. Explain tracking information
4. Handle delivery issues (delayed, lost, damaged)

## Conversation Flow

### Step 1: Identification
Ask for order ID or phone number:
- Order ID format: {{orderIdFormat}}
- If they don't have order ID, ask for phone number used during purchase

### Step 2: Order Lookup
Use the get_order_status tool with the provided identifier.

### Step 3: Status Communication
Based on the order status, provide clear information:

**Processing:**
"Your order is being prepared by our warehouse team. It should ship within {{processingTime}}."

**Shipped:**
"Great news! Your order shipped on [date] via [carrier]. Your tracking number is [spell out]. Expected delivery is [date]."

**Out for Delivery:**
"Exciting! Your order is out for delivery today. You should receive it by [time window]."

**Delivered:**
"Your order was delivered on [date] at [time]. If you haven't received it, please check with neighbors or your building security."

**Delayed:**
"I apologize - your order has been delayed due to [reason]. The new expected delivery is [date]. Would you like me to send you updates?"

## Response Guidelines
- Keep responses under 3 sentences
- Spell out order IDs digit by digit: "A B C 1 2 3 4 5"
- Give specific dates, not vague timeframes
- Offer next steps proactively

## Escalation Triggers
Transfer to human agent if:
- Package marked delivered but customer didn't receive
- Customer wants to file a complaint
- Order is delayed more than 7 days
- Damaged product claim
- Customer requests human explicitly

## Sample Conversations

Customer: "Where's my order?"
Agent: "I'd be happy to help track that! Could you give me your order number or the phone number you used when ordering?"

Customer: "It's 1234567"
Agent: "Let me look that up... Your order 1 2 3 4 5 6 7 shipped yesterday via BlueDart. It's expected to arrive by Thursday, December 28th. Would you like the tracking number?"

Customer: "It shows delivered but I didn't get it"
Agent: "I'm sorry to hear that. Let me connect you with our support team who can help investigate this right away. Please hold."

COD Confirmation Agent (Hindi)

Aap {{storeName}} ke customer service agent hain. Aapka kaam COD orders confirm karna hai.

## Call Objective
Order confirm karwana aur delivery details verify karna.

## Call Script

### Opening
"Namaste {{customerName}} ji! Main {{storeName}} se bol rahi hoon."

### Order Details
"Aapne {{productName}} ka order diya hai:
- Order number: {{orderId}}
- Amount: {{orderTotal}} rupees (Cash on Delivery)
- Delivery address: {{deliveryAddress}}
- Expected delivery: {{deliveryDate}}"

### Confirmation
"Kya yeh sab details sahi hain aur aap delivery ke time available rahenge?"

### Responses

**If Confirmed:**
"Bahut dhanyavaad! Aapka order confirm ho gaya hai. Delivery se pehle aapko SMS milega. Koi aur madad chahiye?"

**If Wants to Modify:**
"Bilkul! Kya change karna hai - address, payment method, ya products?"

**If Wants to Cancel:**
"Koi baat nahi. Main aapka order cancel kar deti hoon. Kya main jaanu ki cancel karne ka reason kya hai?"
(Use cancel_order tool, then record_cancellation_reason)

**If Not Available:**
"Koi problem nahi. Aap kab available honge? Main delivery reschedule kar deti hoon."

## Important Rules
- Always speak respectfully (ji, aap)
- Don't pressure customers to confirm
- If they want to cancel, process it politely
- Record reason for any cancellation
- Maximum 2 call attempts if no answer

Cart Recovery Agent

You are a helpful shopping assistant for {{storeName}}. A customer left items in their cart without completing checkout.

## Objective
Help the customer complete their purchase OR understand why they didn't.

## Opening Line
"Hi {{customerName}}! This is {{storeName}} calling. I noticed you were looking at {{productName}} earlier. Just wanted to check if you had any questions I could help with?"

## Key Guidelines

### Be Helpful, Not Pushy
- This is NOT a sales call - it's a service call
- Focus on removing obstacles, not closing sales
- If they're not interested, respect that immediately

### Common Reasons & Responses

**Price Concern:**
"I totally understand. Actually, I can check if we have any active offers... [check_available_offers] Looks like you can use code SAVE10 for 10% off!"

**Shipping Cost:**
"Good point about shipping. Orders over {{freeShippingThreshold}} ship free. You're at {{cartTotal}} - adding {{suggestedItem}} would get you free shipping and it's something that goes well with what you picked."

**Payment Issues:**
"Sorry you had trouble checking out. We accept cards, UPI, net banking, and COD. Would you like me to help you complete the order over the phone?"

**Just Browsing:**
"No problem at all! I'll let you browse. Is there anything specific you're looking for that I could help find?"

**Found It Cheaper:**
"Thanks for letting me know. We do have a price match policy - could you share where you found it cheaper? I might be able to match it."

**Not Sure About Fit/Quality:**
"Great question! [provide_product_details] Also, we have easy 7-day returns if it doesn't work out."

### Closing
If interested: "Great! Shall I send you a checkout link via SMS?"
If not interested: "No problem! Thanks for letting me know. Have a great day!"

## NEVER Do This
- Call more than once for the same abandoned cart
- Offer discounts immediately without understanding the issue
- Push after they've said no
- Make them feel guilty about not purchasing

Function Definitions

Order Management Tools

{
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "get_order_status",
        "description": "Get order status, tracking information, and delivery estimate",
        "parameters": {
          "type": "object",
          "properties": {
            "order_id": {
              "type": "string",
              "description": "Order ID (e.g., ORD-123456)"
            },
            "phone_number": {
              "type": "string",
              "description": "Customer phone number to look up orders"
            }
          }
        }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "get_tracking_details",
        "description": "Get real-time tracking information from shipping carrier",
        "parameters": {
          "type": "object",
          "properties": {
            "tracking_number": {
              "type": "string",
              "description": "Carrier tracking number"
            },
            "carrier": {
              "type": "string",
              "enum": ["bluedart", "delhivery", "ecom_express", "fedex", "ups", "dhl"],
              "description": "Shipping carrier name"
            }
          },
          "required": ["tracking_number", "carrier"]
        }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "confirm_cod_order",
        "description": "Confirm a Cash-on-Delivery order",
        "parameters": {
          "type": "object",
          "properties": {
            "order_id": {
              "type": "string"
            },
            "confirmed": {
              "type": "boolean",
              "description": "Whether customer confirmed the order"
            },
            "modification_requested": {
              "type": "string",
              "description": "Any modifications requested (address, date, etc.)"
            }
          },
          "required": ["order_id", "confirmed"]
        }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "cancel_order",
        "description": "Cancel an order and process refund if applicable",
        "parameters": {
          "type": "object",
          "properties": {
            "order_id": {
              "type": "string"
            },
            "reason": {
              "type": "string",
              "enum": ["changed_mind", "found_cheaper", "delivery_too_slow", "wrong_item", "other"]
            },
            "reason_details": {
              "type": "string",
              "description": "Additional details about cancellation reason"
            }
          },
          "required": ["order_id", "reason"]
        }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "reschedule_delivery",
        "description": "Reschedule delivery to a different date or time",
        "parameters": {
          "type": "object",
          "properties": {
            "order_id": {
              "type": "string"
            },
            "new_date": {
              "type": "string",
              "description": "New preferred delivery date (YYYY-MM-DD)"
            },
            "time_slot": {
              "type": "string",
              "enum": ["morning", "afternoon", "evening"],
              "description": "Preferred time slot"
            }
          },
          "required": ["order_id", "new_date"]
        }
      }
    }
  ]
}

Return & Refund Tools

{
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "initiate_return",
        "description": "Start a return request for an order item",
        "parameters": {
          "type": "object",
          "properties": {
            "order_id": {
              "type": "string"
            },
            "items": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "sku": { "type": "string" },
                  "quantity": { "type": "integer" },
                  "reason": {
                    "type": "string",
                    "enum": ["damaged", "wrong_item", "not_as_described", "size_issue", "quality_issue", "changed_mind"]
                  }
                }
              },
              "description": "Items to return"
            },
            "refund_method": {
              "type": "string",
              "enum": ["original_payment", "store_credit", "bank_transfer"],
              "description": "Preferred refund method"
            }
          },
          "required": ["order_id", "items"]
        }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "schedule_pickup",
        "description": "Schedule a return pickup from customer address",
        "parameters": {
          "type": "object",
          "properties": {
            "return_id": {
              "type": "string"
            },
            "pickup_date": {
              "type": "string",
              "description": "Preferred pickup date (YYYY-MM-DD)"
            },
            "time_slot": {
              "type": "string",
              "enum": ["morning", "afternoon", "evening"]
            },
            "address": {
              "type": "string",
              "description": "Pickup address (if different from order address)"
            }
          },
          "required": ["return_id", "pickup_date"]
        }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "check_return_status",
        "description": "Check the status of a return request",
        "parameters": {
          "type": "object",
          "properties": {
            "return_id": {
              "type": "string"
            },
            "order_id": {
              "type": "string"
            }
          }
        }
      }
    }
  ]
}

Cart Recovery Tools

{
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "get_abandoned_cart",
        "description": "Get details of customer's abandoned cart",
        "parameters": {
          "type": "object",
          "properties": {
            "customer_id": {
              "type": "string"
            },
            "phone_number": {
              "type": "string"
            }
          }
        }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "check_available_offers",
        "description": "Check available discounts and offers for the cart",
        "parameters": {
          "type": "object",
          "properties": {
            "cart_id": {
              "type": "string"
            },
            "category": {
              "type": "string",
              "description": "Product category to check offers for"
            }
          },
          "required": ["cart_id"]
        }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "apply_discount",
        "description": "Apply a discount code to the cart",
        "parameters": {
          "type": "object",
          "properties": {
            "cart_id": {
              "type": "string"
            },
            "discount_code": {
              "type": "string"
            }
          },
          "required": ["cart_id", "discount_code"]
        }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "send_checkout_link",
        "description": "Send a direct checkout link via SMS",
        "parameters": {
          "type": "object",
          "properties": {
            "cart_id": {
              "type": "string"
            },
            "phone_number": {
              "type": "string"
            },
            "include_discount": {
              "type": "boolean",
              "description": "Include any discussed discount in the link"
            }
          },
          "required": ["cart_id", "phone_number"]
        }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "record_cart_abandonment_reason",
        "description": "Record why customer didn't complete purchase",
        "parameters": {
          "type": "object",
          "properties": {
            "cart_id": {
              "type": "string"
            },
            "reason": {
              "type": "string",
              "enum": ["price_too_high", "shipping_cost", "payment_issues", "found_cheaper", "just_browsing", "not_ready", "other"]
            },
            "notes": {
              "type": "string"
            }
          },
          "required": ["cart_id", "reason"]
        }
      }
    }
  ]
}

Tool Handlers (Go)

Order Status Handler

package tools

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

type Order struct {
    ID                string
    Status            string
    Items             []OrderItem
    TrackingNumber    string
    Carrier           string
    ShippedAt         *time.Time
    EstimatedDelivery *time.Time
    DeliveredAt       *time.Time
    CustomerName      string
    DeliveryAddress   string
}

type OrderItem struct {
    SKU      string
    Name     string
    Quantity int
    Price    float64
}

func HandleGetOrderStatus(ctx context.Context, params map[string]any) (any, error) {
    var order *Order
    var err error

    if orderID, ok := params["order_id"].(string); ok && orderID != "" {
        order, err = orderService.GetByID(ctx, orderID)
    } else if phone, ok := params["phone_number"].(string); ok && phone != "" {
        orders, err := orderService.GetByPhone(ctx, phone)
        if err != nil {
            return nil, err
        }
        if len(orders) == 0 {
            return map[string]any{
                "found":   false,
                "message": "No orders found for this phone number. Please verify the number or provide an order ID.",
            }, nil
        }
        if len(orders) == 1 {
            order = orders[0]
        } else {
            return formatMultipleOrders(orders), nil
        }
    }

    if err != nil || order == nil {
        return map[string]any{
            "found":   false,
            "message": "Order not found. Please verify the order number and try again.",
        }, nil
    }

    return formatOrderForSpeech(order), nil
}

func formatOrderForSpeech(order *Order) map[string]any {
    result := map[string]any{
        "found":    true,
        "order_id": spellOut(order.ID),
        "status":   order.Status,
    }

    switch order.Status {
    case "processing":
        result["message"] = fmt.Sprintf(
            "Your order %s is being prepared and will ship within 1-2 business days.",
            spellOut(order.ID),
        )

    case "shipped":
        result["message"] = fmt.Sprintf(
            "Your order %s shipped on %s via %s. Tracking number is %s. Expected delivery is %s.",
            spellOut(order.ID),
            order.ShippedAt.Format("January 2"),
            order.Carrier,
            spellOut(order.TrackingNumber),
            order.EstimatedDelivery.Format("Monday, January 2"),
        )
        result["tracking_number"] = order.TrackingNumber
        result["carrier"] = order.Carrier

    case "out_for_delivery":
        result["message"] = fmt.Sprintf(
            "Great news! Your order %s is out for delivery today and should arrive by evening.",
            spellOut(order.ID),
        )

    case "delivered":
        result["message"] = fmt.Sprintf(
            "Your order %s was delivered on %s.",
            spellOut(order.ID),
            order.DeliveredAt.Format("Monday, January 2 at 3:04 PM"),
        )

    case "delayed":
        result["message"] = fmt.Sprintf(
            "I apologize, your order %s has been delayed. The new expected delivery is %s. We're sorry for the inconvenience.",
            spellOut(order.ID),
            order.EstimatedDelivery.Format("Monday, January 2"),
        )
        result["requires_escalation"] = true
    }

    return result
}

func formatMultipleOrders(orders []*Order) map[string]any {
    orderList := make([]map[string]any, len(orders))

    for i, order := range orders {
        orderList[i] = map[string]any{
            "order_id": spellOut(order.ID),
            "status":   order.Status,
            "date":     order.ShippedAt.Format("January 2"),
        }
    }

    message := fmt.Sprintf("I found %d orders. ", len(orders))
    for i, order := range orders {
        message += fmt.Sprintf("Order %d: %s, status %s. ", i+1, spellOut(order.ID), order.Status)
    }
    message += "Which order would you like details on?"

    return map[string]any{
        "found":    true,
        "multiple": true,
        "count":    len(orders),
        "orders":   orderList,
        "message":  message,
    }
}

func spellOut(s string) string {
    // "ORD123456" -> "O R D 1 2 3 4 5 6"
    return strings.Join(strings.Split(s, ""), " ")
}

COD Confirmation Handler

func HandleConfirmCODOrder(ctx context.Context, params map[string]any) (any, error) {
    orderID := params["order_id"].(string)
    confirmed := params["confirmed"].(bool)

    order, err := orderService.GetByID(ctx, orderID)
    if err != nil {
        return nil, err
    }

    if confirmed {
        err = orderService.ConfirmCOD(ctx, orderID)
        if err != nil {
            return nil, err
        }

        // Update analytics
        metrics.Increment("cod.confirmed")

        return map[string]any{
            "success": true,
            "message": fmt.Sprintf(
                "Order confirmed. Your %s will be delivered by %s. Please keep %s rupees ready. You'll receive an SMS before delivery.",
                order.Items[0].Name,
                order.EstimatedDelivery.Format("Monday, January 2"),
                formatCurrency(order.Total),
            ),
        }, nil
    }

    // Handle non-confirmation
    if modRequest, ok := params["modification_requested"].(string); ok {
        return handleCODModification(ctx, order, modRequest)
    }

    return map[string]any{
        "success": false,
        "message": "I understand. Would you like to modify the order or cancel it?",
    }, nil
}

func handleCODModification(ctx context.Context, order *Order, modification string) (map[string]any, error) {
    switch {
    case strings.Contains(modification, "address"):
        return map[string]any{
            "action":  "collect_new_address",
            "message": "Sure, I can update the delivery address. What's the new address?",
        }, nil

    case strings.Contains(modification, "date"):
        return map[string]any{
            "action":  "collect_new_date",
            "message": "When would you prefer delivery? We can do any day this week.",
        }, nil

    case strings.Contains(modification, "payment"):
        return map[string]any{
            "action":  "change_payment",
            "message": "Would you like to switch to prepaid? I can send you a payment link.",
        }, nil
    }

    return map[string]any{
        "action":  "clarify",
        "message": "What would you like to modify - the delivery address, delivery date, or payment method?",
    }, nil
}

Cart Recovery Handler

type AbandonedCart struct {
    ID           string
    CustomerID   string
    CustomerName string
    Items        []CartItem
    Total        float64
    AbandonedAt  time.Time
    RecoveryAttempts int
}

type CartItem struct {
    SKU      string
    Name     string
    Quantity int
    Price    float64
    ImageURL string
}

func HandleGetAbandonedCart(ctx context.Context, params map[string]any) (any, error) {
    var cart *AbandonedCart
    var err error

    if customerID, ok := params["customer_id"].(string); ok {
        cart, err = cartService.GetAbandonedByCustomer(ctx, customerID)
    } else if phone, ok := params["phone_number"].(string); ok {
        cart, err = cartService.GetAbandonedByPhone(ctx, phone)
    }

    if err != nil || cart == nil {
        return map[string]any{
            "found": false,
            "message": "No abandoned cart found.",
        }, nil
    }

    // Format items for speech
    itemDescription := formatCartItemsForSpeech(cart.Items)

    return map[string]any{
        "found":       true,
        "cart_id":     cart.ID,
        "items":       cart.Items,
        "total":       cart.Total,
        "item_count":  len(cart.Items),
        "message":     fmt.Sprintf("You have %s in your cart, totaling %s.", itemDescription, formatCurrency(cart.Total)),
        "abandoned_hours_ago": time.Since(cart.AbandonedAt).Hours(),
    }, nil
}

func HandleCheckAvailableOffers(ctx context.Context, params map[string]any) (any, error) {
    cartID := params["cart_id"].(string)

    offers, err := promotionService.GetAvailableOffers(ctx, cartID)
    if err != nil {
        return nil, err
    }

    if len(offers) == 0 {
        return map[string]any{
            "has_offers": false,
            "message":    "I don't have any special offers available right now, but your cart items are already competitively priced!",
        }, nil
    }

    // Find best offer
    bestOffer := findBestOffer(offers)

    return map[string]any{
        "has_offers":  true,
        "best_offer":  bestOffer,
        "all_offers":  offers,
        "message":     fmt.Sprintf("Good news! I found a %s discount code '%s' you can use. This would save you %s.", bestOffer.Description, bestOffer.Code, formatCurrency(bestOffer.Savings)),
    }, nil
}

func HandleSendCheckoutLink(ctx context.Context, params map[string]any) (any, error) {
    cartID := params["cart_id"].(string)
    phone := params["phone_number"].(string)
    includeDiscount := params["include_discount"].(bool)

    // Generate checkout link
    link, err := cartService.GenerateCheckoutLink(ctx, cartID, includeDiscount)
    if err != nil {
        return nil, err
    }

    // Send SMS
    err = smsService.Send(ctx, phone, fmt.Sprintf(
        "Complete your order: %s\nThis link expires in 24 hours.",
        link,
    ))
    if err != nil {
        return map[string]any{
            "success": false,
            "message": "I had trouble sending the link. Can I try a different number?",
        }, nil
    }

    // Track conversion attempt
    metrics.Increment("cart_recovery.checkout_link_sent")

    return map[string]any{
        "success": true,
        "message": "I've sent you a checkout link via SMS. It should arrive in just a few seconds. The link is valid for 24 hours.",
    }, nil
}

func HandleRecordCartAbandonmentReason(ctx context.Context, params map[string]any) (any, error) {
    cartID := params["cart_id"].(string)
    reason := params["reason"].(string)
    notes := params["notes"].(string)

    err := analyticsService.RecordAbandonmentReason(ctx, cartID, reason, notes)
    if err != nil {
        return nil, err
    }

    // Track for analysis
    metrics.Increment("cart_abandonment.reason." + reason)

    return map[string]any{
        "recorded": true,
        "message":  "Thank you for the feedback! We really appreciate it.",
    }, nil
}

func formatCartItemsForSpeech(items []CartItem) string {
    if len(items) == 1 {
        return fmt.Sprintf("a %s", items[0].Name)
    }

    names := make([]string, len(items))
    for i, item := range items {
        names[i] = item.Name
    }

    if len(names) == 2 {
        return fmt.Sprintf("%s and %s", names[0], names[1])
    }

    return fmt.Sprintf("%s, and %s", strings.Join(names[:len(names)-1], ", "), names[len(names)-1])
}

Platform Integrations

Shopify Integration

package shopify

import (
    "context"
    "encoding/json"
    "fmt"
    "net/http"
)

type ShopifyClient struct {
    shopURL     string
    accessToken string
    httpClient  *http.Client
}

func NewShopifyClient(shopURL, accessToken string) *ShopifyClient {
    return &ShopifyClient{
        shopURL:     shopURL,
        accessToken: accessToken,
        httpClient:  &http.Client{Timeout: 10 * time.Second},
    }
}

// GetOrder fetches order details from Shopify
func (c *ShopifyClient) GetOrder(ctx context.Context, orderID string) (*Order, error) {
    url := fmt.Sprintf("https://%s/admin/api/2024-01/orders/%s.json", c.shopURL, orderID)

    req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
    if err != nil {
        return nil, err
    }

    req.Header.Set("X-Shopify-Access-Token", c.accessToken)
    req.Header.Set("Content-Type", "application/json")

    resp, err := c.httpClient.Do(req)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    var result struct {
        Order ShopifyOrder `json:"order"`
    }
    if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
        return nil, err
    }

    return convertShopifyOrder(&result.Order), nil
}

// GetOrderByPhone finds orders by customer phone
func (c *ShopifyClient) GetOrderByPhone(ctx context.Context, phone string) ([]*Order, error) {
    // First, find customer by phone
    customersURL := fmt.Sprintf(
        "https://%s/admin/api/2024-01/customers/search.json?query=phone:%s",
        c.shopURL, phone,
    )

    // ... fetch customer, then their orders

    ordersURL := fmt.Sprintf(
        "https://%s/admin/api/2024-01/orders.json?customer_id=%s&status=any",
        c.shopURL, customerID,
    )

    // ... fetch and return orders
}

// GetAbandonedCheckouts retrieves abandoned carts
func (c *ShopifyClient) GetAbandonedCheckouts(ctx context.Context) ([]*AbandonedCart, error) {
    url := fmt.Sprintf(
        "https://%s/admin/api/2024-01/checkouts.json?created_at_min=%s",
        c.shopURL,
        time.Now().Add(-72*time.Hour).Format(time.RFC3339),
    )

    // ... fetch abandoned checkouts
}

// GetFulfillment gets tracking info for an order
func (c *ShopifyClient) GetFulfillment(ctx context.Context, orderID string) (*Fulfillment, error) {
    url := fmt.Sprintf(
        "https://%s/admin/api/2024-01/orders/%s/fulfillments.json",
        c.shopURL, orderID,
    )

    // ... fetch fulfillment with tracking details
}

func convertShopifyOrder(so *ShopifyOrder) *Order {
    order := &Order{
        ID:              fmt.Sprintf("%d", so.ID),
        Status:          mapShopifyStatus(so.FulfillmentStatus),
        CustomerName:    so.Customer.FirstName + " " + so.Customer.LastName,
        CustomerPhone:   so.Customer.Phone,
        DeliveryAddress: formatAddress(so.ShippingAddress),
        Total:           so.TotalPrice,
        Currency:        so.Currency,
        CreatedAt:       so.CreatedAt,
    }

    for _, item := range so.LineItems {
        order.Items = append(order.Items, OrderItem{
            SKU:      item.SKU,
            Name:     item.Title,
            Quantity: item.Quantity,
            Price:    item.Price,
        })
    }

    if len(so.Fulfillments) > 0 {
        fulfillment := so.Fulfillments[0]
        order.TrackingNumber = fulfillment.TrackingNumber
        order.Carrier = fulfillment.TrackingCompany
        order.ShippedAt = &fulfillment.CreatedAt
    }

    return order
}

func mapShopifyStatus(status string) string {
    switch status {
    case "fulfilled":
        return "shipped"
    case "partial":
        return "partially_shipped"
    case "":
        return "processing"
    default:
        return status
    }
}

Shopify Webhook Handler

// Handle Shopify webhooks for real-time order updates
func HandleShopifyWebhook(w http.ResponseWriter, r *http.Request) {
    topic := r.Header.Get("X-Shopify-Topic")

    var payload json.RawMessage
    if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
        http.Error(w, "Invalid payload", http.StatusBadRequest)
        return
    }

    switch topic {
    case "orders/create":
        handleOrderCreated(payload)

    case "orders/fulfilled":
        handleOrderFulfilled(payload)

    case "fulfillments/update":
        handleFulfillmentUpdate(payload)

    case "checkouts/create":
        handleCheckoutCreated(payload)

    case "checkouts/update":
        handleCheckoutAbandoned(payload)
    }

    w.WriteHeader(http.StatusOK)
}

func handleOrderFulfilled(payload json.RawMessage) {
    var order ShopifyOrder
    json.Unmarshal(payload, &order)

    // Trigger outbound call for delivery notification
    if order.Customer.Phone != "" {
        triggerDeliveryNotificationCall(
            order.Customer.Phone,
            order.Customer.FirstName,
            fmt.Sprintf("%d", order.ID),
            order.Fulfillments[0].TrackingNumber,
        )
    }
}

func handleCheckoutAbandoned(payload json.RawMessage) {
    var checkout ShopifyCheckout
    json.Unmarshal(payload, &checkout)

    // Check if checkout was completed
    if checkout.CompletedAt != nil {
        return // Not abandoned
    }

    // Wait period before cart recovery (e.g., 1 hour)
    time.AfterFunc(1*time.Hour, func() {
        // Verify still abandoned
        current, _ := shopifyClient.GetCheckout(checkout.Token)
        if current.CompletedAt != nil {
            return // Was completed
        }

        // Trigger cart recovery call
        if checkout.Phone != "" {
            triggerCartRecoveryCall(
                checkout.Phone,
                checkout.Customer.FirstName,
                checkout.Token,
            )
        }
    })
}

WooCommerce Integration

package woocommerce

import (
    "context"
    "encoding/base64"
    "encoding/json"
    "fmt"
    "net/http"
)

type WooCommerceClient struct {
    siteURL        string
    consumerKey    string
    consumerSecret string
    httpClient     *http.Client
}

func NewWooCommerceClient(siteURL, consumerKey, consumerSecret string) *WooCommerceClient {
    return &WooCommerceClient{
        siteURL:        siteURL,
        consumerKey:    consumerKey,
        consumerSecret: consumerSecret,
        httpClient:     &http.Client{Timeout: 10 * time.Second},
    }
}

func (c *WooCommerceClient) authHeader() string {
    credentials := c.consumerKey + ":" + c.consumerSecret
    return "Basic " + base64.StdEncoding.EncodeToString([]byte(credentials))
}

// GetOrder fetches order from WooCommerce
func (c *WooCommerceClient) GetOrder(ctx context.Context, orderID string) (*Order, error) {
    url := fmt.Sprintf("%s/wp-json/wc/v3/orders/%s", c.siteURL, orderID)

    req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
    if err != nil {
        return nil, err
    }

    req.Header.Set("Authorization", c.authHeader())

    resp, err := c.httpClient.Do(req)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    var wooOrder WooOrder
    if err := json.NewDecoder(resp.Body).Decode(&wooOrder); err != nil {
        return nil, err
    }

    return convertWooOrder(&wooOrder), nil
}

// GetOrdersByPhone finds orders by billing phone
func (c *WooCommerceClient) GetOrdersByPhone(ctx context.Context, phone string) ([]*Order, error) {
    // WooCommerce doesn't support phone search directly
    // Use search or custom endpoint
    url := fmt.Sprintf(
        "%s/wp-json/wc/v3/orders?search=%s",
        c.siteURL, phone,
    )

    // ... fetch and filter orders
}

// UpdateOrderStatus updates order status
func (c *WooCommerceClient) UpdateOrderStatus(ctx context.Context, orderID, status string) error {
    url := fmt.Sprintf("%s/wp-json/wc/v3/orders/%s", c.siteURL, orderID)

    payload := map[string]string{"status": status}
    body, _ := json.Marshal(payload)

    req, err := http.NewRequestWithContext(ctx, "PUT", url, bytes.NewReader(body))
    if err != nil {
        return err
    }

    req.Header.Set("Authorization", c.authHeader())
    req.Header.Set("Content-Type", "application/json")

    resp, err := c.httpClient.Do(req)
    if err != nil {
        return err
    }
    defer resp.Body.Close()

    if resp.StatusCode != http.StatusOK {
        return fmt.Errorf("failed to update order: %d", resp.StatusCode)
    }

    return nil
}

// CreateRefund processes a refund
func (c *WooCommerceClient) CreateRefund(ctx context.Context, orderID string, amount float64, reason string) error {
    url := fmt.Sprintf("%s/wp-json/wc/v3/orders/%s/refunds", c.siteURL, orderID)

    payload := map[string]any{
        "amount": fmt.Sprintf("%.2f", amount),
        "reason": reason,
    }
    body, _ := json.Marshal(payload)

    req, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewReader(body))
    if err != nil {
        return err
    }

    req.Header.Set("Authorization", c.authHeader())
    req.Header.Set("Content-Type", "application/json")

    resp, err := c.httpClient.Do(req)
    if err != nil {
        return err
    }
    defer resp.Body.Close()

    return nil
}

func convertWooOrder(wo *WooOrder) *Order {
    order := &Order{
        ID:              fmt.Sprintf("%d", wo.ID),
        Status:          mapWooStatus(wo.Status),
        CustomerName:    wo.Billing.FirstName + " " + wo.Billing.LastName,
        CustomerPhone:   wo.Billing.Phone,
        CustomerEmail:   wo.Billing.Email,
        DeliveryAddress: formatWooAddress(wo.Shipping),
        Total:           parseFloat(wo.Total),
        Currency:        wo.Currency,
        CreatedAt:       wo.DateCreated,
        PaymentMethod:   wo.PaymentMethodTitle,
    }

    for _, item := range wo.LineItems {
        order.Items = append(order.Items, OrderItem{
            SKU:      item.SKU,
            Name:     item.Name,
            Quantity: item.Quantity,
            Price:    parseFloat(item.Total),
        })
    }

    // Get tracking from meta or shipment tracking plugin
    if trackingMeta := findMeta(wo.MetaData, "_tracking_number"); trackingMeta != "" {
        order.TrackingNumber = trackingMeta
    }

    return order
}

func mapWooStatus(status string) string {
    switch status {
    case "processing":
        return "processing"
    case "on-hold":
        return "on_hold"
    case "completed":
        return "delivered"
    case "pending":
        return "pending_payment"
    case "cancelled":
        return "cancelled"
    case "refunded":
        return "refunded"
    default:
        return status
    }
}

WooCommerce Webhook Handler

// Handle WooCommerce webhooks
func HandleWooCommerceWebhook(w http.ResponseWriter, r *http.Request) {
    topic := r.Header.Get("X-WC-Webhook-Topic")

    var payload json.RawMessage
    if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
        http.Error(w, "Invalid payload", http.StatusBadRequest)
        return
    }

    switch topic {
    case "order.created":
        handleWooOrderCreated(payload)

    case "order.updated":
        handleWooOrderUpdated(payload)
    }

    w.WriteHeader(http.StatusOK)
}

func handleWooOrderCreated(payload json.RawMessage) {
    var order WooOrder
    json.Unmarshal(payload, &order)

    // COD order - schedule confirmation call
    if order.PaymentMethod == "cod" {
        scheduleCallAfter(30*time.Minute, func() {
            triggerCODConfirmationCall(
                order.Billing.Phone,
                order.Billing.FirstName,
                fmt.Sprintf("%d", order.ID),
                order.Total,
                order.LineItems[0].Name,
            )
        })
    }
}

Analytics & Metrics

Key Performance Indicators

type EcommerceVoiceMetrics struct {
    // WISMO Metrics
    WISMOCallsTotal       int
    WISMOCallsHandledByAI int
    WISMOResolutionRate   float64
    WISMOAvgHandleTime    time.Duration

    // COD Confirmation
    CODCallsAttempted     int
    CODCallsConnected     int
    CODConfirmationRate   float64
    RTOReductionPercent   float64

    // Cart Recovery
    AbandonedCartsTargeted int
    RecoveryCallsMade      int
    CartsRecovered         int
    RecoveryRate           float64
    RevenueRecovered       float64

    // Returns
    ReturnRequestsHandled  int
    AutomatedPickupScheduled int
    ReturnProcessingTime   time.Duration

    // Customer Satisfaction
    CSAT                   float64
    NPS                    int
}

func CalculateEcommerceMetrics(startDate, endDate time.Time) *EcommerceVoiceMetrics {
    metrics := &EcommerceVoiceMetrics{}

    // WISMO metrics
    wismoStats := db.GetWISMOStats(startDate, endDate)
    metrics.WISMOCallsTotal = wismoStats.Total
    metrics.WISMOCallsHandledByAI = wismoStats.AIHandled
    metrics.WISMOResolutionRate = float64(wismoStats.Resolved) / float64(wismoStats.AIHandled)
    metrics.WISMOAvgHandleTime = wismoStats.TotalDuration / time.Duration(wismoStats.Total)

    // COD metrics
    codStats := db.GetCODStats(startDate, endDate)
    metrics.CODCallsAttempted = codStats.Attempted
    metrics.CODCallsConnected = codStats.Connected
    metrics.CODConfirmationRate = float64(codStats.Confirmed) / float64(codStats.Connected)

    // Calculate RTO reduction
    previousRTORate := db.GetRTORate(startDate.AddDate(0, -1, 0), startDate)
    currentRTORate := db.GetRTORate(startDate, endDate)
    metrics.RTOReductionPercent = (previousRTORate - currentRTORate) / previousRTORate * 100

    // Cart recovery metrics
    cartStats := db.GetCartRecoveryStats(startDate, endDate)
    metrics.AbandonedCartsTargeted = cartStats.Targeted
    metrics.RecoveryCallsMade = cartStats.CallsMade
    metrics.CartsRecovered = cartStats.Recovered
    metrics.RecoveryRate = float64(cartStats.Recovered) / float64(cartStats.CallsMade)
    metrics.RevenueRecovered = cartStats.TotalRecoveredValue

    return metrics
}

Dashboard Tracking

func trackOrderStatusCall(call *Call, order *Order, resolved bool) {
    // Call metrics
    metrics.Increment("ecommerce.wismo.calls.total")
    if resolved {
        metrics.Increment("ecommerce.wismo.calls.resolved")
    } else {
        metrics.Increment("ecommerce.wismo.calls.escalated")
    }

    // Order status distribution
    metrics.Increment("ecommerce.wismo.status." + order.Status)

    // Timing
    metrics.Histogram("ecommerce.wismo.duration", call.Duration.Seconds())

    // Track by carrier for shipping issues
    if order.Carrier != "" {
        metrics.Increment("ecommerce.wismo.carrier." + order.Carrier)
    }
}

func trackCartRecovery(cart *AbandonedCart, outcome string, revenue float64) {
    metrics.Increment("ecommerce.cart_recovery.calls.total")
    metrics.Increment("ecommerce.cart_recovery.outcome." + outcome)

    if outcome == "recovered" {
        metrics.Increment("ecommerce.cart_recovery.conversions")
        metrics.Gauge("ecommerce.cart_recovery.revenue", revenue)
    }

    // Track abandonment reasons
    if cart.AbandonmentReason != "" {
        metrics.Increment("ecommerce.cart_abandonment.reason." + cart.AbandonmentReason)
    }
}

func trackCODConfirmation(order *Order, confirmed bool, cancellationReason string) {
    metrics.Increment("ecommerce.cod.calls.total")

    if confirmed {
        metrics.Increment("ecommerce.cod.confirmed")
        metrics.Gauge("ecommerce.cod.confirmed_value", order.Total)
    } else {
        metrics.Increment("ecommerce.cod.cancelled")
        metrics.Increment("ecommerce.cod.cancellation_reason." + cancellationReason)
    }
}

ROI Calculator

type ROICalculation struct {
    // Costs
    VoiceAgentCost      float64
    CostPerMinute       float64
    TotalMinutes        float64

    // Savings
    AgentCostSaved      float64
    CallsDeflected      int
    CostPerHumanCall    float64

    // Revenue Impact
    CartsRecovered      float64
    RTOReduction        float64
    AverageOrderValue   float64

    // Totals
    TotalCost           float64
    TotalBenefit        float64
    ROI                 float64
}

func CalculateROI(metrics *EcommerceVoiceMetrics, config *PricingConfig) *ROICalculation {
    roi := &ROICalculation{}

    // Voice agent costs
    roi.TotalMinutes = float64(metrics.WISMOCallsHandledByAI) * 2.0 // avg 2 min per call
    roi.CostPerMinute = 0.15 // Example: $0.15/min
    roi.VoiceAgentCost = roi.TotalMinutes * roi.CostPerMinute

    // Agent cost savings
    roi.CallsDeflected = metrics.WISMOCallsHandledByAI
    roi.CostPerHumanCall = 5.0 // Example: $5 per human-handled call
    roi.AgentCostSaved = float64(roi.CallsDeflected) * roi.CostPerHumanCall

    // Cart recovery revenue
    roi.CartsRecovered = metrics.RevenueRecovered

    // RTO reduction savings (for COD)
    // Assume 5% RTO rate reduction saves $X per order
    ordersWithReducedRTO := int(metrics.RTOReductionPercent * float64(metrics.CODCallsConnected))
    rtoSavingsPerOrder := 15.0 // Example: $15 saved per avoided RTO
    roi.RTOReduction = float64(ordersWithReducedRTO) * rtoSavingsPerOrder

    // Calculate ROI
    roi.TotalCost = roi.VoiceAgentCost
    roi.TotalBenefit = roi.AgentCostSaved + roi.CartsRecovered + roi.RTOReduction
    roi.ROI = (roi.TotalBenefit - roi.TotalCost) / roi.TotalCost * 100

    return roi
}

Best Practices

1. Order Identification

Make it easy for customers to identify their orders:

// Support multiple identification methods
func identifyOrder(params map[string]any) (*Order, error) {
    // Try order ID first (most specific)
    if orderID, ok := params["order_id"].(string); ok {
        return orderService.GetByID(orderID)
    }

    // Try phone + recent order
    if phone, ok := params["phone_number"].(string); ok {
        orders, _ := orderService.GetRecentByPhone(phone, 30*24*time.Hour)
        if len(orders) == 1 {
            return orders[0], nil
        }
        // Multiple orders - need disambiguation
    }

    // Try email
    if email, ok := params["email"].(string); ok {
        return orderService.GetRecentByEmail(email)
    }

    return nil, errors.New("could not identify order")
}

2. Handle Delivery Issues Gracefully

## Delivery Issue Handling

### Package Shows Delivered But Customer Didn't Receive
"I'm sorry to hear that. This is concerning and I want to make sure we resolve it quickly.
Let me connect you with our delivery specialist who can investigate this right away."
→ Transfer to human agent with context

### Package Delayed Beyond Estimate
"I apologize for the delay with your order.
[If reason known] It looks like [reason - weather, carrier delay, etc.].
[If unknown] Let me check with our shipping team and have someone call you back within 2 hours with an update.
As a gesture of apology, I'm adding a {{discountAmount}} credit to your account for your next order."

### Wrong Item Delivered
"I'm so sorry about that mix-up! Let me start a return for the wrong item right away,
and we'll ship out the correct item today with express shipping at no extra charge."

3. COD Confirmation Best Practices

// Optimal timing for COD confirmation calls
func scheduleCODConfirmation(order *Order) {
    // Best conversion: 30-60 minutes after order
    delay := 30 * time.Minute

    // Adjust for time of day
    now := time.Now()
    callTime := now.Add(delay)

    // Don't call before 9 AM or after 8 PM
    if callTime.Hour() < 9 {
        callTime = time.Date(callTime.Year(), callTime.Month(), callTime.Day(), 9, 0, 0, 0, callTime.Location())
    } else if callTime.Hour() >= 20 {
        // Schedule for next morning
        callTime = time.Date(callTime.Year(), callTime.Month(), callTime.Day()+1, 10, 0, 0, 0, callTime.Location())
    }

    scheduler.Schedule(callTime, func() {
        triggerCODConfirmationCall(order)
    })
}

// Maximum 2 attempts for COD confirmation
func handleCODNoAnswer(order *Order, attemptNumber int) {
    if attemptNumber >= 2 {
        // Mark as unconfirmed, proceed with caution
        orderService.MarkUnconfirmed(order.ID)
        return
    }

    // Schedule retry after 2 hours
    scheduler.Schedule(time.Now().Add(2*time.Hour), func() {
        triggerCODConfirmationCall(order)
    })
}

4. Cart Recovery Timing

// Optimal timing for cart recovery calls
func scheduleCartRecoveryCall(cart *AbandonedCart) {
    // Timing based on cart value and abandonment pattern
    var delay time.Duration

    switch {
    case cart.Total > 500: // High-value cart
        delay = 1 * time.Hour // Call sooner
    case cart.Total > 100:
        delay = 2 * time.Hour
    default:
        delay = 4 * time.Hour
    }

    // Don't call on weekends for B2B
    if cart.CustomerType == "business" && isWeekend(time.Now().Add(delay)) {
        delay = timeUntilNextWeekday(time.Now().Add(delay))
    }

    scheduler.Schedule(time.Now().Add(delay), func() {
        // Verify cart still abandoned
        current, _ := cartService.Get(cart.ID)
        if current.Status == "completed" {
            return
        }
        triggerCartRecoveryCall(cart)
    })
}

// Only one recovery call per cart
func canAttemptRecovery(cartID string) bool {
    attempts := db.GetRecoveryAttempts(cartID)
    return attempts == 0
}

5. Multilingual Support for Indian E-commerce

// Language selection based on customer preference
func determineLanguage(customer *Customer) string {
    // Use customer's preferred language if set
    if customer.PreferredLanguage != "" {
        return customer.PreferredLanguage
    }

    // Infer from delivery state
    stateLanguageMap := map[string]string{
        "Maharashtra":    "mr-IN",
        "Tamil Nadu":     "ta-IN",
        "Karnataka":      "kn-IN",
        "Gujarat":        "gu-IN",
        "West Bengal":    "bn-IN",
        "Kerala":         "ml-IN",
        "Andhra Pradesh": "te-IN",
        "Telangana":      "te-IN",
    }

    if lang, ok := stateLanguageMap[customer.State]; ok {
        return lang
    }

    // Default to Hindi for North India, English otherwise
    northernStates := []string{"Delhi", "UP", "Bihar", "Rajasthan", "MP", "Punjab", "Haryana"}
    for _, state := range northernStates {
        if customer.State == state {
            return "hi-IN"
        }
    }

    return "en-IN"
}

Next Steps

  • Order Status Agent - Basic order tracking example
  • Customer Support - Full support agent
  • Function Calling - Tool integration guide
  • Multi-Language Support - Configure Indian languages
  • Webhooks - Real-time order event integration
Previous
Financial Services
Next
Logistics

On this page

  • Industry Impact
  • Use Cases
  • 1. Order Status Tracking (WISMO)
  • 2. Delivery Updates (Outbound)
  • 3. COD Order Confirmation
  • 4. Cart Recovery
  • 5. Return Initiation
  • System Prompts
  • Order Status Agent
  • Core Responsibilities
  • Conversation Flow
  • Step 1: Identification
  • Step 2: Order Lookup
  • Step 3: Status Communication
  • Response Guidelines
  • Escalation Triggers
  • Sample Conversations
  • COD Confirmation Agent (Hindi)
  • Call Objective
  • Call Script
  • Opening
  • Order Details
  • Confirmation
  • Responses
  • Important Rules
  • Cart Recovery Agent
  • Objective
  • Opening Line
  • Key Guidelines
  • Be Helpful, Not Pushy
  • Common Reasons & Responses
  • Closing
  • NEVER Do This
  • Function Definitions
  • Order Management Tools
  • Return & Refund Tools
  • Cart Recovery Tools
  • Tool Handlers (Go)
  • Order Status Handler
  • COD Confirmation Handler
  • Cart Recovery Handler
  • Platform Integrations
  • Shopify Integration
  • Shopify Webhook Handler
  • WooCommerce Integration
  • WooCommerce Webhook Handler
  • Analytics & Metrics
  • Key Performance Indicators
  • Dashboard Tracking
  • ROI Calculator
  • Best Practices
  • 1. Order Identification
  • 2. Handle Delivery Issues Gracefully
  • Delivery Issue Handling
  • Package Shows Delivered But Customer Didn't Receive
  • Package Delayed Beyond Estimate
  • Wrong Item Delivered
  • 3. COD Confirmation Best Practices
  • 4. Cart Recovery Timing
  • 5. Multilingual Support for Indian E-commerce
  • 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