WA Blast Automation & Scheduling

Cara setup WA blast automation dan scheduling. Auto-trigger, jadwal optimal, workflow automation. Blast yang jalan sendiri!

WA Blast Automation & Scheduling
WA Blast Automation & Scheduling

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 series

Time-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 data

Trigger-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 check

Re-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 automations

DON'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 docs

FAQ

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 BlastAutomated Blast
Time-consumingSet once
InconsistentAlways on-time
Limited scaleUnlimited scale
Human errorReliable

Build your automation engine!

Setup Automation →


Artikel Terkait