Bot WA AI untuk Order Tracking

Cara membuat bot AI WhatsApp untuk tracking pesanan. Real-time status, proactive updates, smart notifications. Tutorial lengkap!

Bot WA AI untuk Order Tracking
Bot WA AI untuk Order Tracking

AI Order Tracking = Customer peace of mind!

Bot AI bisa handle pertanyaan tracking secara natural, proactive update, dan predict masalah sebelum customer komplain.


Fitur Order Tracking

📦 FITUR TRACKING:

1. NATURAL QUERY
   "Pesanan saya sudah sampai mana?"
   → AI pahami dan cek status

2. PROACTIVE UPDATES
   Status berubah
   → Auto notify customer

3. PREDICTIVE ALERTS
   Detect delay
   → Notify sebelum customer tanya

4. MULTI-CARRIER SUPPORT
   JNE, J&T, SiCepat, dll
   → Unified tracking

5. SMART ESCALATION
   Stuck > 3 hari
   → Auto alert CS team

System Prompt

javascript

const ORDER_TRACKING_PROMPT = `Kamu adalah AI assistant untuk tracking pesanan [BRAND].

CAPABILITIES:
- Cek status pesanan dari nomor order atau nama
- Lacak posisi paket dari nomor resi
- Estimasi waktu sampai
- Handle pertanyaan seputar pengiriman

INFORMASI KURIR:
- JNE: Regular (2-3 hari), YES (1-2 hari), OKE (3-5 hari)
- J&T: Express (1-2 hari), EZ (2-4 hari)
- SiCepat: BEST (1-2 hari), REG (2-4 hari)
- Anteraja: Same Day, Next Day, Regular

STATUS PENGIRIMAN:
- pending: Menunggu pickup
- picked_up: Sudah diambil kurir
- in_transit: Dalam perjalanan
- out_for_delivery: Sedang diantar
- delivered: Sudah diterima
- returned: Dikembalikan
- failed: Gagal kirim

CARA RESPONSE:
- Selalu tunjukkan status terkini dengan jelas
- Berikan estimasi realistis
- Jika delay, jelaskan kemungkinan penyebab
- Tawarkan bantuan jika ada masalah
- Gunakan emoji untuk status visual`;

Implementation

Track Order Function:

javascript

const trackingTools = [
    {
        type: 'function',
        function: {
            name: 'get_order_status',
            description: 'Get order status by order ID or customer phone',
            parameters: {
                type: 'object',
                properties: {
                    order_id: { type: 'string' },
                    phone: { type: 'string' }
                }
            }
        }
    },
    {
        type: 'function',
        function: {
            name: 'track_shipment',
            description: 'Track shipment by tracking number',
            parameters: {
                type: 'object',
                properties: {
                    tracking_number: { type: 'string' },
                    courier: { type: 'string' }
                },
                required: ['tracking_number']
            }
        }
    }
];

async function getOrderStatus(params) {
    let order;
    
    if (params.order_id) {
        order = await db.orders.findOne({ orderId: params.order_id });
    } else if (params.phone) {
        order = await db.orders.findOne({ 
            customerPhone: params.phone,
            status: { $ne: 'delivered' }
        }).sort({ createdAt: -1 });
    }
    
    if (!order) {
        return { found: false };
    }
    
    // Get shipping details if shipped
    let shippingDetails = null;
    if (order.trackingNumber) {
        shippingDetails = await trackShipment({
            tracking_number: order.trackingNumber,
            courier: order.courier
        });
    }
    
    return {
        found: true,
        order: {
            orderId: order.orderId,
            status: order.status,
            items: order.items,
            total: order.total,
            createdAt: order.createdAt,
            trackingNumber: order.trackingNumber,
            courier: order.courier,
            estimatedDelivery: order.estimatedDelivery
        },
        shipping: shippingDetails
    };
}

Multi-Carrier Tracking:

javascript

async function trackShipment({ tracking_number, courier }) {
    // Auto-detect courier if not provided
    if (!courier) {
        courier = detectCourier(tracking_number);
    }
    
    const trackers = {
        jne: trackJNE,
        jnt: trackJNT,
        sicepat: trackSiCepat,
        anteraja: trackAnteraja,
        ninja: trackNinja
    };
    
    const tracker = trackers[courier.toLowerCase()];
    if (!tracker) {
        return { error: 'Courier not supported' };
    }
    
    try {
        const result = await tracker(tracking_number);
        return normalizeTrackingResult(result, courier);
    } catch (error) {
        return { error: 'Tracking failed', message: error.message };
    }
}

function detectCourier(trackingNumber) {
    // JNE: starts with specific patterns
    if (/^(JN|JP|JD)\d+/.test(trackingNumber)) return 'jne';
    // J&T: usually starts with J
    if (/^J[A-Z]\d+/.test(trackingNumber)) return 'jnt';
    // SiCepat: starts with specific patterns
    if (/^\d{12}$/.test(trackingNumber)) return 'sicepat';
    // Default
    return 'unknown';
}

// Normalize different courier responses to standard format
function normalizeTrackingResult(result, courier) {
    return {
        courier,
        trackingNumber: result.tracking_number || result.awb,
        status: mapStatus(result.status, courier),
        currentLocation: result.current_location || result.last_position,
        history: (result.history || result.manifest || []).map(h => ({
            timestamp: h.timestamp || h.date,
            status: h.status || h.description,
            location: h.location || h.city
        })),
        estimatedDelivery: result.estimated_delivery,
        recipient: result.receiver_name,
        deliveredAt: result.delivered_at
    };
}

Natural Language Handler

javascript

async function handleTrackingQuery(userId, userMessage) {
    const response = await openai.chat.completions.create({
        model: 'gpt-4o',
        messages: [
            { role: 'system', content: ORDER_TRACKING_PROMPT },
            { role: 'user', content: userMessage }
        ],
        tools: trackingTools,
        tool_choice: 'auto'
    });
    
    const message = response.choices[0].message;
    
    if (message.tool_calls) {
        const toolResults = [];
        
        for (const toolCall of message.tool_calls) {
            const args = JSON.parse(toolCall.function.arguments);
            let result;
            
            switch (toolCall.function.name) {
                case 'get_order_status':
                    // If no order_id, use user's phone
                    if (!args.order_id && !args.phone) {
                        args.phone = userId.replace('@s.whatsapp.net', '');
                    }
                    result = await getOrderStatus(args);
                    break;
                case 'track_shipment':
                    result = await trackShipment(args);
                    break;
            }
            
            toolResults.push({
                tool_call_id: toolCall.id,
                role: 'tool',
                content: JSON.stringify(result)
            });
        }
        
        // Get final response with tracking data
        const finalResponse = await openai.chat.completions.create({
            model: 'gpt-4o',
            messages: [
                { role: 'system', content: ORDER_TRACKING_PROMPT },
                { role: 'user', content: userMessage },
                message,
                ...toolResults
            ]
        });
        
        return finalResponse.choices[0].message.content;
    }
    
    return message.content;
}

Proactive Updates

javascript

// Webhook from courier atau internal status change
async function onOrderStatusChange(orderId, newStatus, trackingData) {
    const order = await db.orders.findOne({ orderId });
    const customer = await db.customers.findOne({ oderId
oderId
userId: order.userId });
    
    const statusMessages = {
        picked_up: `📦 Pesanan Diambil Kurir!

Order #${orderId} sudah diambil ${order.courier}.

🔢 Resi: ${order.trackingNumber}
📍 Posisi: ${trackingData.currentLocation}
📅 Estimasi: ${trackingData.estimatedDelivery}

Track: ${getTrackingLink(order.courier, order.trackingNumber)}`,

        in_transit: `🚚 Pesanan Dalam Perjalanan!

Order #${orderId} sedang dikirim.

📍 Posisi terakhir: ${trackingData.currentLocation}
📅 Estimasi tiba: ${trackingData.estimatedDelivery}`,

        out_for_delivery: `🎉 Pesanan Sedang Diantar!

Order #${orderId} sedang dalam pengantaran!

📍 Kurir sedang menuju alamat kakak
⏰ Estimasi: Hari ini

Pastikan ada yang terima ya kak! 📱`,

        delivered: `✅ Pesanan Diterima!

Order #${orderId} sudah sampai!

📍 Diterima oleh: ${trackingData.recipient}
⏰ Waktu: ${trackingData.deliveredAt}

Terima kasih sudah belanja di [BRAND]! 💕

Puas dengan pesanannya? Reply dengan rating 1-5 ⭐`
    };
    
    const message = statusMessages[newStatus];
    if (message) {
        await sendWhatsApp(customer.phone, message);
    }
    
    // Update order status in DB
    await db.orders.updateOne(
        { orderId },
        { $set: { status: newStatus, lastUpdate: new Date() } }
    );
}

Delay Detection & Alert

javascript

// Run every hour
async function checkForDelays() {
    const orders = await db.orders.find({
        status: { $in: ['picked_up', 'in_transit'] },
        estimatedDelivery: { $lt: new Date() }
    }).toArray();
    
    for (const order of orders) {
        const daysPastDue = Math.floor(
            (Date.now() - order.estimatedDelivery) / (1000 * 60 * 60 * 24)
        );
        
        if (daysPastDue >= 1 && !order.delayNotified) {
            // Notify customer
            await sendWhatsApp(order.customerPhone, 
                `⚠️ Update Pengiriman

Hai Kak! Order #${order.orderId} sepertinya mengalami keterlambatan.

📍 Status terakhir: ${order.lastTrackingStatus}
📅 Estimasi awal: ${formatDate(order.estimatedDelivery)}

Kami sudah follow up ke ${order.courier}.
Akan kami kabari perkembangannya ya!

Ada pertanyaan? Reply saja 🙏`
            );
            
            // Notify internal team
            await alertCSTeam({
                type: 'DELIVERY_DELAY',
                orderId: order.orderId,
                daysPastDue,
                courier: order.courier,
                trackingNumber: order.trackingNumber
            });
            
            // Mark as notified
            await db.orders.updateOne(
                { orderId: order.orderId },
                { $set: { delayNotified: true } }
            );
        }
    }
}

// Schedule
cron.schedule('0 * * * *', checkForDelays);

Example Conversations

👤: Pesanan saya sudah sampai mana ya?

🤖: Hai Kak! Aku cek dulu ya...

📦 Order #ORD-20260215-001

Status: 🚚 Dalam Perjalanan

📍 Posisi terakhir: 
   Hub Jakarta Selatan (15 Feb, 14:30)

📅 Estimasi tiba: 17 Feb 2026

Resi: JN123456789
Track langsung: https://jne.co.id/track/JN123456789

Ada pertanyaan lain kak?

---

👤: Kok lama banget ya, harusnya kemarin sampai

🤖: Aku cek lebih detail ya kak...

Benar kak, ada sedikit keterlambatan 😔

📋 Timeline:
- 14 Feb: Diambil kurir ✓
- 14 Feb: Hub Jakarta ✓
- 15 Feb: Transit Bandung ✓
- 16 Feb: Estimasi sampai ← delayed

Sepertinya ada backlog di hub Bandung
karena volume tinggi.

Yang bisa kami lakukan:
1️⃣ Follow up ke JNE (sudah kami lakukan)
2️⃣ Pantau terus dan kabari kakak

Mohon maaf atas ketidaknyamanannya 🙏
Biasanya 1-2 hari lagi sampai.

Mau aku kabari begitu ada update?

Best Practices

DO ✅

- Proactive updates setiap status change
- Detect delay early
- Multi-carrier support
- Natural language queries
- Clear timeline visualization
- Offer help for delays

DON'T ❌

- Only update when asked
- Ignore delays
- Single carrier only
- Rigid command format
- No status history
- Blame courier

FAQ

Perlu integrasi API semua kurir?

Ideal ya. Atau pakai aggregator seperti Shipper, Biteship untuk simplify.

Update seberapa sering?

Setiap status change. Plus proactive check untuk delay setiap jam.


Kesimpulan

AI Order Tracking = Happy customers!

Basic TrackingAI Tracking
Manual checkAuto update
ReactiveProactive
Single carrierMulti carrier

Setup AI Tracking →


Artikel Terkait