7. Kampanye broadcast
Halaman Kampanye (/campaigns) adalah hub dua kartu:
- Broadcast template — kirim template Meta ke segmen sekarang ATAU jadwalkan untuk nanti (§7.1).
- Broadcast terjadwal — daftar broadcast yang sudah dijadwalkan + status pengirimannya, plus tombol batal (§7.2).
7.1 Broadcast template ke segmen (siap pakai)
Tombol “Broadcast template” di kanan atas halaman Kampanye → halaman /campaigns/broadcast. Cara kerjanya: pilih segmen (audiens), pilih template Meta, isi parameter (statis atau dari field kontak), konfirmasi, kirim. Pengiriman berjalan di latar belakang dengan throttle ~1 detik per pesan.
Prasyarat: Mode Resmi (Meta) tersambung (lihat §12 Profil & WhatsApp) + minimal 1 segmen (lihat §4.11 Segmen) + minimal 1 template approved Meta.
Langkah:
-
Pilih segmen tujuan — dropdown menampilkan semua segmen workspace dengan jumlah kontaknya. Karibin otomatis hanya mengirim ke kontak yang punya nomor WhatsApp. Cap audiens maksimal 5.000 kontak per broadcast (defensive limit; queue absorbs ribuan kontak tanpa blokir API). Broadcast dengan audience > 5.000 akan dipotong ke 5.000 pertama.
-
Pilih template — dropdown ambil dari WhatsApp Business Account Anda. Hanya status APPROVED yang bisa dipilih.
-
Personalisasi parameter — untuk tiap
{{N}}di body template, pilih sumber nilainya:- Teks tetap — nilai sama untuk semua kontak (mis. nama promo, kode kupon).
- Field kontak — diisi otomatis dari kontak: Nama, Nomor WhatsApp, atau Email. Cocok untuk personalisasi (mis.
"Halo {{1}}"→ “Halo Ibu Sari” / “Halo Pak Budi”).
-
Pratinjau body otomatis ter-update sesuai parameter — placeholder yang dari field kontak ditampilkan sebagai
[Nama kontak]dll. supaya jelas apa yang akan dipersonalisasi. -
Media header (jika template Anda punya HEADER bertipe IMAGE / VIDEO / DOCUMENT) — pemicu upload otomatis muncul. Pilih file:
- Image: JPG/PNG, maks 5 MB
- Video: MP4, maks 16 MB
- Document: PDF, maks 100 MB
Karibin upload file ini ke Meta sekali lalu re-use
media_iduntuk semua kontak (efisien — tidak upload ulang 5000 kali). File juga disalin keuploads/lokal supaya inbox menampilkan preview inline di bubble per kontak. -
Kapan dikirim? Pilih Sekarang (default, kirim seketika) atau Jadwalkan untuk nanti (datetime picker minimal 1 menit dari sekarang). Lihat §7.2 untuk detail scheduling.
-
Klik Pratinjau & lanjut → konfirmasi (warning kuning menampilkan ringkasan: nama template + jumlah audiens + jadwal kalau dijadwalkan) → Ya, kirim sekarang atau Ya, jadwalkan.
Setelah dikirim:
- Tiap pesan keluar muncul sebagai bubble di Percakapan masing-masing kontak (membuat percakapan baru kalau belum ada). Body bubble adalah ringkasan: nama template + parameter — bukan teks template yang sebenarnya, karena Meta yang mengganti placeholder di sisi server.
- Status centang ✓→✓✓→✓✓ teal akan ter-update otomatis lewat status webhook.
- Audit log mencatat siapa memulai broadcast, template + audiens-nya.
Bagaimana pengiriman bekerja (queue)
- Producer (API) menyiapkan tabel Message PENDING + meng-enqueue satu BullMQ job per kontak ke queue
broadcast-send. Operasi ini cepat (1–2 detik untuk 5000 kontak viaaddBulk). Anda dapat respon “Broadcast dimulai” segera. - Worker process (
karibin-worker) memproses jobs dengan throttle 1 kirim per ~1.1 detik (BullMQ rate limiter, global di seluruh tenant). Untuk 5000 kontak: ~91 menit total. - Tiap kirim sukses → Message status
PENDING→SENT(✓). Webhook Meta nanti flip keDELIVERED(✓✓) →READ(✓✓teal). - Tiap kirim gagal (mis. di luar 24h window) → status
FAILED. Anda bisa filter inbox per status untuk lihat semua yang gagal. - Restart backend / worker di tengah eksekusi: Aman. Jobs yang belum diproses tetap di Redis. Worker yang baru naik lanjut dari titik terakhir. Job yang sedang di-fetch saat crash di-retry 1× oleh BullMQ; status guard di handler (
PENDING-check) memastikan tidak double-send.
Batasan yang masih ada
- Header media: image (JPG/PNG), video (MP4), document (PDF) — sudah didukung (template harus punya HEADER bertipe IMAGE/VIDEO/DOCUMENT yang sudah di-approve Meta).
- Button URL dinamis + footer parameter masih belum.
- Tidak ada stop / pause setelah broadcast dimulai. Workaround sementara: kalau ingin batal di tengah eksekusi, bisa pause queue lewat
pm2 stop karibin-worker(semua broadcast di-pause sampai worker hidup lagi).
7.2 Broadcast terjadwal
Buka Kampanye → Terjadwal (/campaigns/scheduled) untuk lihat semua broadcast yang sudah dijadwalkan beserta statusnya:
| Status | Arti |
|---|---|
| Terjadwal | Belum waktunya — masih bisa dibatalkan dengan ikon 🗑 |
| Mengirim | Backend sudah enqueue jobs per kontak ke queue (delivery async di worker) — sudah tidak bisa dibatalkan |
| Terkirim | Selesai. Kolom Hasil menampilkan ✓ N (sukses) + ✗ M (gagal kalau ada) |
| Dibatalkan | Anda batalkan sebelum jadwal tiba |
| Gagal | Eksekusi error (mis. Meta credentials dicabut sebelum jadwal tiba, segmen dihapus). Pesan error muncul di kolom Status |
Cara kerja teknis
- Broadcast yang Anda jadwalkan masuk antrian (Redis + BullMQ). Worker process terpisah (
karibin-workerdi PM2) menunggu sampaischeduledForlewat, lalu klaim row + eksekusi. Resolusi: tepat — tidak ada polling delay (BullMQ delayed jobs). - Audiens dihitung ulang saat dikirim, bukan saat dijadwalkan — kontak yang join segmen setelah Anda dijadwalkan tetap dapat (selama belum melewati cap 5.000). Kalau Anda mau audiens “frozen”, buat segmen yang kondisinya tidak akan berubah (mis. snapshot via tag manual).
- Media header (kalau template butuh): di-upload ke Meta sekali saat scheduling —
media_id+ file lokal di-snapshot di row. Meta media_id expires ~30 hari — Karibin refuse schedule lebih dari 25 hari di depan kalau ada media header (errormedia_expiry_risk). Untuk schedule lebih jauh, broadcast tanpa header atau pakai template text-only. - Cap audiens 5.000 sama dengan instant broadcast (§7.1) — queue-backed, jadi backend tidak blokir untuk batch besar.
- Crash di tengah eksekusi: BullMQ retry job otomatis 1×. Kalau job pakai status guard (claim flip SCHEDULED → SENDING), retry yang ke-2 langsung skip karena status sudah bukan SCHEDULED — jadi tidak double-send. Row stuck di SENDING bisa diatasi manual (admin DB).
- Cancel hanya valid saat status
Terjadwal— kalau backend sudah claim keMengirim, tombol batal akan error “Sudah tidak bisa dibatalkan”.
Audit log mencatat: campaign.scheduled (saat dijadwalkan), campaign.broadcast_started (saat tick mulai eksekusi), campaign.cancelled (saat dibatalkan).
Catatan: tampilan mobile
- Halaman publik form (
/f/[slug]) dan halaman auth (/auth/login, register, dst.) sudah responsif untuk ponsel. Aman dibagi via WhatsApp ke pelanggan/calon anggota tim. - Bagian admin (Dasbor, Inbox, Kontak, dll.) didesain untuk desktop. Bisa dibuka di HP tapi layout tabel + 3-kolom inbox tidak ideal di layar kecil. Pakai laptop/tablet untuk operasional harian.