Bot Jualan dengan Promo & Kode Diskon
Cara buat bot jualan WhatsApp dengan fitur kode diskon. Voucher, promo, auto apply discount. Boost conversion!
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 promoFlow 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 BAYARKode 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 4Tiered 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 orderBest Practices
1. Clear Terms
Selalu tampilkan syarat promo:
- Minimum order
- Periode berlaku
- Produk yang applicable
- Limit penggunaan2. 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!
| Manual | Dengan Bot |
|---|---|
| Validate manual | Auto validate |
| Sering error | Akurat |
| Slow | Instant |
Boost sales dengan promo otomatis!