Bot Jualan dengan Promo & Kode Diskon

Cara buat bot jualan WhatsApp dengan fitur kode diskon. Voucher, promo, auto apply discount. Boost conversion!

Bot Jualan dengan Promo
Bot Jualan dengan Promo

Promo = Conversion booster!

Tapi kelola kode diskon manual itu ribet. Buat bot yang handle promo otomatis!


Jenis Promo yang Bisa Di-automate

💰 Kode Diskon:
- Persentase (10%, 20%)
- Nominal (Rp 50.000)
- Free ongkir

🎁 Bundling:
- Buy 2 get 1
- Paket hemat

🎯 Conditional:
- Min. order Rp X
- Produk tertentu
- Customer tertentu (VIP)

⏰ Time-based:
- Flash sale
- Happy hour
- Weekend promo

Flow Promo Bot

Customer: "Pakai kode DISKON20"
    ↓
Bot: Validate kode
    ↓
Valid? → Apply discount
Invalid? → Show error + suggestion
    ↓
Bot: "✅ Kode DISKON20 berhasil!
     Diskon 20% applied.
     Total: Rp 200k → Rp 160k"

Template Response Promo

Kode Valid:

✅ KODE PROMO BERHASIL!

Kode: [KODE]
Diskon: [DESKRIPSI]

Subtotal: Rp [HARGA_ASLI]
Diskon: -Rp [POTONGAN]
━━━━━━━━━━━━━━━━━
Total: Rp [HARGA_FINAL]

Lanjut checkout? Ketik BAYAR

Kode Invalid:

❌ KODE TIDAK VALID

Kode "[KODE]" tidak bisa digunakan.

Kemungkinan:
- Kode salah ketik
- Kode sudah expired
- Kode sudah pernah dipakai
- Belum memenuhi syarat

💡 Promo yang sedang berlaku:
- WELCOME10 - Diskon 10% new customer
- FREEONGKIR - Free ongkir min. Rp 200k

Coba kode lain?

Kode Expired:

⏰ KODE SUDAH EXPIRED

Kode "[KODE]" sudah tidak berlaku.
Periode: [TANGGAL_MULAI] - [TANGGAL_SELESAI]

Promo aktif saat ini:
- [PROMO 1]
- [PROMO 2]

Gunakan kode lain!

Minimum Not Met:

⚠️ BELUM MEMENUHI SYARAT

Kode "[KODE]" butuh minimum order.

Syarat: Min. pembelian Rp [MIN]
Order kamu: Rp [CURRENT]
Kurang: Rp [SELISIH]

Tambah belanjaan untuk pakai kode ini!
Atau checkout tanpa kode.

Sudah Dipakai:

⚠️ KODE SUDAH DIGUNAKAN

Kode "[KODE]" hanya bisa dipakai 1x 
dan kamu sudah pernah memakainya.

Coba promo lain:
- [PROMO ALTERNATIF]

Implementasi

Database Schema:

javascript

// Promo codes collection
{
    code: 'DISKON20',
    type: 'percentage', // percentage, fixed, freeShipping
    value: 20, // 20% atau Rp 20000
    minOrder: 100000,
    maxDiscount: 50000, // cap untuk percentage
    startDate: '2026-01-01',
    endDate: '2026-01-31',
    usageLimit: 100, // total usage
    usagePerUser: 1, // per customer
    applicableProducts: [], // empty = all
    applicableCategories: [],
    usedBy: ['628xxx', '628yyy'], // track usage
    usedCount: 25,
    active: true
}

Validate Promo Code:

javascript

async function validatePromoCode(code, customerId, orderTotal, products) {
    const promo = await db.promos.findOne({ 
        code: code.toUpperCase(),
        active: true 
    });
    
    // Check exists
    if (!promo) {
        return { valid: false, error: 'Kode tidak ditemukan' };
    }
    
    // Check date
    const now = new Date();
    if (now < new Date(promo.startDate) || now > new Date(promo.endDate)) {
        return { valid: false, error: 'Kode sudah expired' };
    }
    
    // Check total usage
    if (promo.usedCount >= promo.usageLimit) {
        return { valid: false, error: 'Kuota promo sudah habis' };
    }
    
    // Check per user usage
    if (promo.usedBy.includes(customerId)) {
        return { valid: false, error: 'Kamu sudah pernah pakai kode ini' };
    }
    
    // Check minimum order
    if (orderTotal < promo.minOrder) {
        return { 
            valid: false, 
            error: `Minimum order Rp ${promo.minOrder.toLocaleString()}`,
            shortBy: promo.minOrder - orderTotal
        };
    }
    
    // Check applicable products
    if (promo.applicableProducts.length > 0) {
        const hasApplicable = products.some(p => 
            promo.applicableProducts.includes(p.id)
        );
        if (!hasApplicable) {
            return { valid: false, error: 'Kode tidak berlaku untuk produk ini' };
        }
    }
    
    return { valid: true, promo };
}

Calculate Discount:

javascript

function calculateDiscount(promo, orderTotal) {
    let discount = 0;
    
    switch (promo.type) {
        case 'percentage':
            discount = orderTotal * (promo.value / 100);
            if (promo.maxDiscount) {
                discount = Math.min(discount, promo.maxDiscount);
            }
            break;
            
        case 'fixed':
            discount = promo.value;
            break;
            
        case 'freeShipping':
            // Handled separately
            discount = 0;
            break;
    }
    
    return Math.round(discount);
}

Apply Promo:

javascript

async function applyPromo(code, customerId, cart) {
    const orderTotal = cart.reduce((sum, item) => sum + item.subtotal, 0);
    
    const validation = await validatePromoCode(code, customerId, orderTotal, cart);
    
    if (!validation.valid) {
        return { success: false, message: validation.error };
    }
    
    const discount = calculateDiscount(validation.promo, orderTotal);
    const finalTotal = orderTotal - discount;
    
    // Mark as used (akan di-confirm saat checkout berhasil)
    // Atau reserve dulu, confirm setelah payment
    
    return {
        success: true,
        originalTotal: orderTotal,
        discount: discount,
        finalTotal: finalTotal,
        promoDescription: formatPromoDescription(validation.promo)
    };
}

Bot Handler:

javascript

client.on('message', async msg => {
    const text = msg.body.toUpperCase();
    
    if (text.startsWith('KODE ') || text.startsWith('PROMO ')) {
        const code = text.replace(/^(KODE|PROMO)\s+/, '');
        const cart = await getCart(msg.from);
        
        if (cart.length === 0) {
            await msg.reply('Keranjang masih kosong! Belanja dulu ya.');
            return;
        }
        
        const result = await applyPromo(code, msg.from, cart);
        
        if (result.success) {
            await msg.reply(formatPromoSuccess(result));
        } else {
            await msg.reply(formatPromoError(result.message, code));
        }
    }
});

Jenis Promo Lanjutan

Buy X Get Y:

javascript

const promo = {
    type: 'buyXgetY',
    buyQuantity: 2,
    getQuantity: 1,
    getProduct: 'same', // atau product ID spesifik
};

// Customer beli 3 → bayar 2
// Customer beli 6 → bayar 4

Tiered Discount:

javascript

const promo = {
    type: 'tiered',
    tiers: [
        { minOrder: 100000, discount: 10 },
        { minOrder: 200000, discount: 15 },
        { minOrder: 500000, discount: 25 }
    ]
};

First Order:

javascript

async function isFirstOrder(customerId) {
    const orders = await db.orders.count({ customerId });
    return orders === 0;
}

// Auto apply WELCOME discount untuk first order

Best Practices

1. Clear Terms

Selalu tampilkan syarat promo:
- Minimum order
- Periode berlaku
- Produk yang applicable
- Limit penggunaan

2. Prevent Abuse

- 1x per customer
- Limit total usage
- Blacklist suspicious accounts
- Track IP/device (jika bisa)

3. Easy Discovery

Customer tanya "promo"
→ Tampilkan semua promo aktif

Jangan sembunyikan promo!

FAQ

Bagaimana track usage?

Simpan di database: siapa yang pakai, kapan, untuk order apa. Update usedBy dan usedCount.

Bisa stack multiple promo?

Tergantung kebijakan. Biasanya tidak boleh stack. Pilih promo terbaik atau manual pilih satu.

Bagaimana handle refund?

Jika order di-refund, kembalikan kuota promo supaya customer bisa pakai lagi.


Kesimpulan

Promo bot = Automated conversion booster!

ManualDengan Bot
Validate manualAuto validate
Sering errorAkurat
SlowInstant

Boost sales dengan promo otomatis!

Setup Promo Bot →


Artikel Terkait