Resep: Broadcast WhatsApp dengan Google Spreadsheet
Panduan ini menunjukkan cara mengirim pesan WhatsApp massal ke daftar nomor yang tersimpan di Google Spreadsheet. Sangat berguna untuk broadcast promosi, pengumuman, atau pengingat ke banyak pelanggan sekaligus.
๐ฏ Yang Akan Anda Capai
Setelah mengikuti panduan ini:
- Membaca daftar nomor dan data dari Google Spreadsheet
- Mengirim pesan WhatsApp personal (dengan variabel seperti nama) ke setiap nomor
- Mencatat status pengiriman kembali ke spreadsheet
๐ Prasyarat
Sebelum memulai, pastikan Anda memiliki:
- Google Spreadsheet dengan daftar penerima
- API Key Kirem (live key) โ dapatkan dari Dasbor Kirem
- Templat pesan disetujui untuk broadcast (kategori
MARKETING) - Nomor WhatsApp terdaftar di Kirem yang sudah aktif
- Akses Google Apps Script (bawaan Google Sheets)
๐ง Langkah 1: Siapkan Spreadsheet
Buat Google Spreadsheet baru dengan struktur berikut:
| A: No HP | B: Nama | C: Kode Promo | D: Status | E: WA ID | F: Waktu Kirim |
|---|---|---|---|---|---|
| 62812345678 | Budi | PROMO10 | |||
| 62898765432 | Ani | PROMO10 | |||
| 62811122233 | Cici | PROMO10 |
- Kolom AโC: Data penerima dan variabel untuk personalisasi pesan
- Kolom DโF: Akan diisi otomatis oleh script (status, ID pesan, waktu)
๐ง Langkah 2: Siapkan Templat Pesan di Kirem
Buat templat pesan untuk broadcast:
Endpoint: POST /v1/templates
{
"name": "broadcast_promo",
"category": "MARKETING",
"language": "id",
"components": [
{
"type": "HEADER",
"format": "TEXT",
"text": "Promo Spesial!"
},
{
"type": "BODY",
"text": "Halo {{1}},\n\nJangan lewatkan promo spesial kami! ๐\nGunakan kode *{{2}}* untuk mendapatkan diskon di seluruh produk.\n\nKlik di sini: https://kirem.co.id/promo"
},
{
"type": "BUTTONS",
"buttons": [
{
"type": "URL",
"text": "Lihat Promo",
"url": "https://kirem.co.id/promo"
}
]
}
]
}
Variabel:
{{1}}โ Nama penerima (dari kolom B){{2}}โ Kode promo (dari kolom C)
Tunggu hingga status templat menjadi APPROVED sebelum melanjutkan.
๐ง Langkah 3: Buka Google Apps Script
- Di spreadsheet yang sudah disiapkan, buka menu Extensions > Apps Script
- Hapus kode default yang ada
- Salin dan tempel kode berikut:
// ============================================
// KONFIGURASI โ Ubah sesuai pengaturan Anda
// ============================================
const KIREM_API_KEY = 'kirem_live_xxxxxxxxxxxxxxxx';
const KIREM_API_URL = 'https://api.kirem.co/v1/messages';
const TEMPLATE_NAME = 'broadcast_promo';
const DELAY_MS = 2000; // Jeda 2 detik antar pengiriman
/**
* Menu kustom di Google Sheets
*/
function onOpen() {
const ui = SpreadsheetApp.getUi();
ui.createMenu('๐ฑ Kirem Broadcast')
.addItem('Kirim Broadcast', 'sendBroadcast')
.addItem('Reset Status', 'resetStatus')
.addToUi();
}
/**
* Fungsi utama: Membaca spreadsheet dan mengirim broadcast
*/
function sendBroadcast() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
const data = sheet.getDataRange().getValues();
const total = data.length - 1; // Kurangi header
const ui = SpreadsheetApp.getUi();
const response = ui.alert(
'Konfirmasi Broadcast',
`Anda akan mengirim broadcast ke ${total} nomor. Lanjutkan?`,
ui.ButtonSet.YES_NO
);
if (response !== ui.Button.YES) {
return;
}
let successCount = 0;
let failCount = 0;
// Mulai dari baris 2 (baris 1 adalah header)
for (let i = 1; i < data.length; i++) {
const row = data[i];
const phone = String(row[0]).trim();
const name = row[1] || 'Pelanggan';
const promoCode = row[2] || '';
// Lewati baris kosong
if (!phone) {
continue;
}
// Bersihkan nomor telepon
const cleanPhone = cleanPhoneNumber(phone);
try {
const result = sendWhatsAppMessage(cleanPhone, name, promoCode);
const messageId = result.data.messages[0].id;
// Update status di spreadsheet
sheet.getRange(i + 1, 4).setValue('SUKSES');
sheet.getRange(i + 1, 5).setValue(messageId);
sheet.getRange(i + 1, 6).setValue(new Date().toISOString());
successCount++;
console.log(`โ
${cleanPhone} โ ${messageId}`);
} catch (error) {
// Update status error di spreadsheet
sheet.getRange(i + 1, 4).setValue('GAGAL: ' + error.message);
sheet.getRange(i + 1, 6).setValue(new Date().toISOString());
failCount++;
console.log(`โ ${cleanPhone} โ ${error.message}`);
}
// Jeda antar pengiriman (rate limiting)
Utilities.sleep(DELAY_MS);
}
// Tampilkan ringkasan
ui.alert(
'Broadcast Selesai',
`Total: ${total}\nSukses: ${successCount}\nGagal: ${failCount}`,
ui.ButtonSet.OK
);
}
/**
* Membersihkan format nomor telepon ke format internasional
*/
function cleanPhoneNumber(phone) {
// Hapus semua karakter non-digit
let cleaned = phone.replace(/[^0-9]/g, '');
// Konversi 08xx โ 628xx
if (cleaned.startsWith('0')) {
cleaned = '62' + cleaned.substring(1);
}
// Konversi 8xx โ 628xx (jika pendek)
if (cleaned.startsWith('8') && cleaned.length < 12) {
cleaned = '62' + cleaned;
}
return cleaned;
}
/**
* Mengirim pesan WhatsApp via Kirem API
*/
function sendWhatsAppMessage(to, name, promoCode) {
const payload = {
messaging_product: 'whatsapp',
recipient_type: 'individual',
to: to,
type: 'template',
template: {
name: TEMPLATE_NAME,
language: {
code: 'id'
},
components: [
{
type: 'body',
parameters: [
{ type: 'text', text: name },
{ type: 'text', text: promoCode }
]
}
]
}
};
const options = {
method: 'post',
contentType: 'application/json',
headers: {
'Authorization': 'Bearer ' + KIREM_API_KEY
},
payload: JSON.stringify(payload),
muteHttpExceptions: true
};
const response = UrlFetchApp.fetch(KIREM_API_URL, options);
const responseCode = response.getResponseCode();
const responseBody = JSON.parse(response.getContentText());
if (responseCode !== 200 && responseCode !== 201) {
throw new Error(
responseBody.message || `HTTP ${responseCode}`
);
}
return responseBody;
}
/**
* Reset kolom status, WA ID, dan waktu
*/
function resetStatus() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
const data = sheet.getDataRange().getValues();
const ui = SpreadsheetApp.getUi();
const response = ui.alert(
'Reset Status',
'Ini akan menghapus semua status, WA ID, dan waktu kirim. Lanjutkan?',
ui.ButtonSet.YES_NO
);
if (response !== ui.Button.YES) {
return;
}
for (let i = 1; i < data.length; i++) {
sheet.getRange(i + 1, 4).setValue('');
sheet.getRange(i + 1, 5).setValue('');
sheet.getRange(i + 1, 6).setValue('');
}
ui.alert('Status berhasil direset!', ui.ButtonSet.OK);
}
๐ง Langkah 4: Simpan dan Jalankan
- Klik Save (ikon disket) dan beri nama project, misal:
Kirem Broadcast - Kembali ke spreadsheet dan refresh halaman
- Menu baru "๐ฑ Kirem Broadcast" akan muncul di menu bar
- Klik Kirim Broadcast untuk memulai pengiriman
Catatan: Pertama kali menjalankan, Google akan meminta izin akses. Klik Review Permissions dan izinkan akses ke spreadsheet Anda.
๐งช Uji Coba
- Isi 2โ3 baris pertama dengan nomor WhatsApp Anda sendiri dan teman
- Jalankan Kirim Broadcast
- Periksa WhatsApp โ pesan akan masuk dengan jeda 2 detik antar pengiriman
- Periksa spreadsheet โ kolom D, E, F akan terisi otomatis
๐จ Kustomisasi Lanjutan
Alternatif: Menggunakan n8n dengan Google Sheets Node
Jika Anda lebih nyaman dengan n8n:
- Google Sheets Node โ membaca data dari spreadsheet
- Loop Node โ iterasi setiap baris
- Kirem Node โ mengirim pesan ke setiap nomor
- Google Sheets Node (Update) โ menulis status kembali
Keuntungan menggunakan n8n: visual workflow, retry otomatis, dan scheduling.
Menambahkan Penjadwalan
Gunakan Google Apps Script Triggers:
- Di editor Apps Script, klik ikon jam โฐ Triggers
- Tambahkan trigger baru:
- Function:
sendBroadcast - Event source:
Time-driven - Type:
Day timer - Time: pilih jam pengiriman
- Function:
Menangani Opt-Out
Tambahkan pengecekan kata kunci STOP di kolom terpisah:
// Tambahkan kolom "Opt-Out" (G)
// Sebelum mengirim, cek:
if (row[6] === 'STOP') {
sheet.getRange(i + 1, 4).setValue('DILEWATI (Opt-Out)');
continue; // Lewati nomor ini
}
๐ Batasan Google Apps Script
| Batasan | Nilai |
|---|---|
| Waktu eksekusi maksimal | 6 menit per eksekusi |
| Panggilan URL Fetch per hari | 20.000 (akun Google Workspace) |
| Ukuran spreadsheet maksimal | 10 juta sel |
Untuk broadcast dengan lebih dari ~180 nomor (6 menit รท 2 detik jeda), pertimbangkan menggunakan n8n atau script backend (Node.js/Python) yang tidak memiliki batasan waktu eksekusi.
โ ๏ธ Best Practices & Peringatan
- Gunakan templat yang disetujui Meta: Jangan kirim pesan teks bebas secara massal โ ini melanggar kebijakan WhatsApp dan dapat menyebabkan pemblokiran akun.
- Hormati opt-out: Sediakan mekanisme bagi pelanggan untuk berhenti menerima broadcast. Pantau kata kunci "STOP" dan hapus nomor tersebut dari daftar.
- Rate limiting: WhatsApp memiliki batasan pengiriman per detik. Atur jeda minimal 1โ2 detik antar pesan. Untuk volume sangat besar, konsultasikan batasan tier akun Anda dengan tim Kirem.
- Jangan spam: Kirim hanya pesan yang relevan dan bermanfaat. Pengiriman spam dapat mengakibatkan pemblokiran akun WhatsApp Anda secara permanen.
- Uji dengan nomor sendiri terlebih dahulu: Selalu uji broadcast dengan nomor Anda sendiri sebelum mengirim ke pelanggan sebenarnya.