WA Blast Automation & Scheduling
Cara setup WA blast automation dan scheduling. Auto-trigger, jadwal optimal, workflow automation. Blast yang jalan sendiri!
Set once, run forever!
WA blast automation berarti blast jalan otomatis tanpa kamu harus manually kirim setiap waktu. Hemat waktu, konsisten, dan scalable.
Jenis Automation
🤖 TIPE AUTOMATION:
TIME-BASED:
- Scheduled blast (tanggal & jam tertentu)
- Recurring blast (setiap hari/minggu/bulan)
- Time-zone aware
TRIGGER-BASED:
- Event trigger (order, signup, dll)
- Behavior trigger (abandoned cart, dll)
- Milestone trigger (X hari, X order, dll)
DRIP SEQUENCE:
- Onboarding series
- Nurture sequence
- Re-engagement seriesTime-Based Scheduling
One-Time Schedule:
📅 JADWAL SEKALI KIRIM
Contoh use case:
- Flash sale announcement
- Event invitation
- Product launch
Setup:
━━━━━━━━━━━━━━━━━━━━
Tanggal: 25 Feb 2026
Jam: 10:00 WIB
Template: flash_sale_announcement
Audience: All customers
━━━━━━━━━━━━━━━━━━━━
Blast akan terkirim otomatis
pada waktu yang ditentukan!Recurring Schedule:
📅 JADWAL BERULANG
Contoh use case:
- Weekly tips (setiap Rabu)
- Monthly newsletter
- Daily reminder
Setup:
━━━━━━━━━━━━━━━━━━━━
Frekuensi: Setiap Minggu
Hari: Rabu
Jam: 10:00 WIB
Template: weekly_tips
Audience: Tips subscribers
━━━━━━━━━━━━━━━━━━━━
Otomatis terkirim setiap Rabu!Optimal Time Scheduling:
📅 SMART SCHEDULING
Kirim di waktu optimal per customer:
OPTION 1: Fixed time per timezone
- WIB: 10:00
- WITA: 11:00
- WIT: 12:00
OPTION 2: Based on open history
- Analyze kapan customer biasa baca
- Send at their optimal time
OPTION 3: Based on activity
- Online sekarang? Kirim sekarang!
- Best hour berdasarkan engagement dataTrigger-Based Automation
Event Triggers:
javascript
const eventTriggers = {
// Customer lifecycle
'customer.created': {
template: 'welcome_message',
delay: 0 // Immediately
},
'customer.first_order': {
template: 'thank_you_first_order',
delay: 0
},
// Order events
'order.placed': {
template: 'order_confirmation',
delay: 0
},
'order.shipped': {
template: 'shipping_notification',
delay: 0
},
'order.delivered': {
template: 'delivery_confirmation',
delay: 0
},
// Post-purchase
'order.delivered': {
template: 'review_request',
delay: 3 * 24 * 60 * 60 * 1000 // 3 days after
},
'order.delivered': {
template: 'cross_sell',
delay: 7 * 24 * 60 * 60 * 1000 // 7 days after
}
};
// Event listener
eventEmitter.on('order.delivered', async (order) => {
const triggers = eventTriggers['order.delivered'];
for (const trigger of triggers) {
await scheduleBlast({
phone: order.customerPhone,
template: trigger.template,
data: order,
scheduledAt: new Date(Date.now() + trigger.delay)
});
}
});Behavior Triggers:
javascript
const behaviorTriggers = {
// Cart behavior
'cart.abandoned': {
sequence: [
{ delay: 1 * 60 * 60 * 1000, template: 'cart_reminder_1h' },
{ delay: 24 * 60 * 60 * 1000, template: 'cart_reminder_24h' },
{ delay: 48 * 60 * 60 * 1000, template: 'cart_incentive' }
]
},
// Browse behavior
'product.viewed_multiple': {
template: 'product_reminder',
delay: 2 * 60 * 60 * 1000,
condition: (data) => data.viewCount >= 3
},
// Engagement behavior
'customer.inactive': {
template: 're_engagement',
condition: (customer) => daysSinceLastOrder(customer) >= 30
}
};Milestone Triggers:
javascript
const milestoneTriggers = {
// Time milestones
'days_since_signup': {
7: 'week_1_checkin',
30: 'month_1_offer',
90: 'quarter_review',
365: 'anniversary_reward'
},
// Order milestones
'order_count': {
3: 'loyal_customer_thanks',
5: 'vip_invitation',
10: 'super_customer_reward'
},
// Spend milestones
'total_spent': {
500000: 'silver_status',
1000000: 'gold_status',
5000000: 'platinum_status'
}
};
// Check milestones daily
cron.schedule('0 10 * * *', async () => {
const customers = await db.customers.find({ status: 'active' });
for (const customer of customers) {
await checkMilestones(customer);
}
});Drip Sequences
Onboarding Sequence:
📧 WELCOME SERIES
Day 0: Welcome message
"Selamat datang di [BRAND]!"
Day 1: Brand story
"Kenalan yuk dengan [BRAND]..."
Day 3: Product highlights
"Best sellers yang wajib dicoba..."
Day 5: First purchase incentive
"Special 15% off untuk order pertama!"
Day 7: Social proof
"Apa kata customer lain..."
Day 14: Check-in
"Gimana, sudah coba belanja?"Post-Purchase Sequence:
📧 POST-PURCHASE SERIES
Day 0: Order confirmation
Day 1: Shipping update
Day 3: Delivery + usage tips
Day 5: Review request
Day 7: Cross-sell recommendations
Day 14: Replenishment reminder (if applicable)
Day 30: Re-engagement checkRe-engagement Sequence:
📧 WIN-BACK SERIES
Day 30 inactive: Soft reminder
"Hai, apa kabar?"
Day 45 inactive: Value reminder
"Ada yang baru nih..."
Day 60 inactive: Incentive
"Miss you, here's 20% off!"
Day 75 inactive: Last chance
"Final offer sebelum kami stop..."
Day 90 inactive: Goodbye/survey
"Boleh tau kenapa tidak aktif?"Implementation
Scheduler System:
javascript
const Queue = require('bull');
const blastQueue = new Queue('wa-blast', REDIS_URL);
// Schedule a blast
async function scheduleBlast(data) {
const { phone, template, scheduledAt, ...params } = data;
const delay = new Date(scheduledAt).getTime() - Date.now();
await blastQueue.add({
phone,
template,
params
}, {
delay: Math.max(0, delay),
attempts: 3,
backoff: {
type: 'exponential',
delay: 60000
}
});
}
// Process scheduled blasts
blastQueue.process(async (job) => {
const { phone, template, params } = job.data;
// Check if should still send
const shouldSend = await checkConditions(phone, template);
if (shouldSend) {
await sendWhatsApp(phone, renderTemplate(template, params));
await logBlast(phone, template, 'sent');
} else {
await logBlast(phone, template, 'skipped');
}
});Cron Jobs:
javascript
const cron = require('node-cron');
// Daily recurring blasts
cron.schedule('0 10 * * *', async () => {
// Birthday wishes
await sendBirthdayWishes();
// Milestone checks
await checkMilestones();
// Dormant customer check
await checkDormantCustomers();
});
// Weekly recurring blasts
cron.schedule('0 10 * * 3', async () => {
// Wednesday tips
await sendWeeklyTips();
});
// Monthly recurring blasts
cron.schedule('0 10 1 * *', async () => {
// Monthly newsletter
await sendMonthlyNewsletter();
});Automation Dashboard:
javascript
async function getAutomationStats() {
return {
scheduled: {
pending: await db.scheduledBlasts.count({ status: 'pending' }),
today: await db.scheduledBlasts.count({
status: 'pending',
scheduledAt: { $lte: endOfDay(new Date()) }
})
},
sequences: {
active: await db.sequences.count({ status: 'active' }),
completed: await db.sequences.count({ status: 'completed' })
},
performance: {
lastWeek: await getBlastPerformance(7),
lastMonth: await getBlastPerformance(30)
}
};
}Automation Rules
Condition Checks:
javascript
const conditions = {
// Don't send if already purchased
'cart_recovery': async (phone) => {
const recentOrder = await db.orders.findOne({
customerPhone: phone,
createdAt: { $gte: hoursAgo(24) }
});
return !recentOrder; // Only send if no recent order
},
// Don't send if unsubscribed
'promotional': async (phone) => {
const customer = await db.customers.findOne({ phone });
return customer?.preferences?.promotional !== false;
},
// Don't exceed daily limit
'any': async (phone) => {
const todayCount = await db.blastLogs.count({
phone,
sentAt: { $gte: startOfDay(new Date()) }
});
return todayCount < 3; // Max 3 per day
}
};Rate Limiting:
javascript
const rateLimits = {
perCustomer: {
daily: 3,
weekly: 10,
monthly: 30
},
overall: {
perSecond: 10,
perMinute: 100
}
};
async function checkRateLimits(phone) {
const counts = await db.blastLogs.aggregate([
{ $match: { phone } },
{ $group: {
_id: null,
today: { $sum: { $cond: [{ $gte: ['$sentAt', startOfDay()] }, 1, 0] } },
thisWeek: { $sum: { $cond: [{ $gte: ['$sentAt', startOfWeek()] }, 1, 0] } },
thisMonth: { $sum: { $cond: [{ $gte: ['$sentAt', startOfMonth()] }, 1, 0] } }
}}
]);
const { today, thisWeek, thisMonth } = counts[0] || {};
return (
today < rateLimits.perCustomer.daily &&
thisWeek < rateLimits.perCustomer.weekly &&
thisMonth < rateLimits.perCustomer.monthly
);
}Best Practices
DO ✅
- Start simple, add complexity gradually
- Test automation thoroughly before launch
- Monitor and adjust based on data
- Have kill switch for emergencies
- Respect customer preferences
- Document your automationsDON'T ❌
- Over-automate (too many messages)
- Forget to update stale content
- Ignore unsubscribe requests
- No testing before launch
- Set and forget (never review)
- Complex dependencies without docsFAQ
Berapa banyak automation yang ideal?
Start dengan 3-5 core automations (welcome, post-purchase, abandoned cart). Tambah gradually.
Bagaimana test automation?
Staging environment dengan test phone numbers. Verify sequence dan timing sebelum live.
Perlu monitoring?
Yes! Dashboard untuk track pending, sent, failed. Alerts untuk issues.
Kesimpulan
Automate for scale!
| Manual Blast | Automated Blast |
|---|---|
| Time-consuming | Set once |
| Inconsistent | Always on-time |
| Limited scale | Unlimited scale |
| Human error | Reliable |
Build your automation engine!