Impor Kontak Google Sheets ke Brevo dengan Apps Script

Contoh Google Apps Script yang dapat diulang dengan pemeriksaan persetujuan, pemetaan kolom, perlindungan berhenti berlangganan, dan error API yang terlihat.

google apps script brevo

Apa jawaban singkatnya?

Buat kolom email, firstName, lastName, dan consent. Simpan BREVO_API_KEY di Script Properties, isi ID daftar dalam kode, lalu jalankan syncSheetToBrevo. Hanya baris dengan persetujuan diproses; skrip memeriksa blokir Brevo, menghapus duplikat, dan berhenti saat API gagal. Ini Apps Script yang Anda kelola, bukan konektor bawaan.

Pelajari selengkapnya
Di halaman ini

Mengekspor selusin pendaftar acara satu kali cukup mudah. Pada impor kedua, satu email mungkin berulang dan orang lain sudah berhenti berlangganan di Brevo. Impor yang dapat diulang harus mengenali keduanya.

Skrip ini memakai endpoint baca, buat, dan perbarui kontak Brevo. Ini untuk impor kecil terjadwal, bukan pemuat massal atau konektor Google Sheets bawaan. Skrip tidak mengirim email. Anda bertanggung jawab atas bukti persetujuan dan operasinya.

Siapkan Sheet dan daftar

Buat tab Contacts dengan header persis seperti ini. Pakai kotak centang untuk consent dan tetapkan TRUE hanya jika ada izin pemasaran yang dimaksud.

emailfirstNamelastNameconsent
[email protected]JaneDoeTRUE
[email protected]AlexLeeFALSE

Buat atau pilih daftar Brevo, lalu salin ID numeriknya ke LIST_ID. Pastikan atribut FNAME dan LNAME sudah ada di Brevo; hanya dua itu yang dipetakan. Simpan bukti kapan dan bagaimana persetujuan diberikan di luar Sheet jika Sheet tidak dapat membuktikannya. Sel TRUE saja bukan bukti.

Di Extensions → Apps Script → Project Settings → Script Properties, tambahkan BREVO_API_KEY. Properti dibagikan kepada pengguna skrip, jadi batasi hak edit. Jangan taruh kunci di sel atau kode. Lihat aturan akses Google.

Skrip

Ganti Code.gs dengan contoh berikut. Isi LIST_ID sebelum eksekusi pertama.

const LIST_ID = 42; // Replace with your existing Brevo list ID.
const TAB = 'Contacts';
const BASE = 'https://api.brevo.com/v3';
function syncSheetToBrevo() {
const key = PropertiesService.getScriptProperties().getProperty('BREVO_API_KEY');
if (!key) throw new Error('Set BREVO_API_KEY in Script Properties first');
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(TAB);
if (!sheet) throw new Error('Contacts tab missing');
const values = sheet.getDataRange().getValues();
const headers = values.shift().map(h => String(h).trim());
const columns = ['email', 'firstName', 'lastName', 'consent']
.map(name => headers.indexOf(name));
if (columns.includes(-1)) throw new Error('Required header missing');
const [emailCol, firstCol, lastCol, consentCol] = columns;
const seen = new Set();
const result = { written: 0, skipped: 0 };
for (const row of values) {
const email = String(row[emailCol] || '').trim().toLowerCase();
if (row[consentCol] !== true || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email) || seen.has(email)) {
result.skipped++;
continue;
}
seen.add(email);
const path = '/contacts/' + encodeURIComponent(email);
const current = brevo_(key, path, 'get');
if (current.code !== 200 && current.code !== 404) {
throw new Error(`Contact read failed (${current.code}) for row ${result.written + result.skipped + 2}`);
}
if (current.code === 200) {
const contact = JSON.parse(current.text);
if (contact.emailBlacklisted || (contact.listUnsubscribed || []).includes(LIST_ID)) {
result.skipped++;
continue;
}
}
const attributes = {};
if (row[firstCol] !== '') attributes.FNAME = String(row[firstCol]);
if (row[lastCol] !== '') attributes.LNAME = String(row[lastCol]);
const body = { attributes, listIds: [LIST_ID] };
const saved = current.code === 404
? brevo_(key, '/contacts', 'post', { email, ...body })
: brevo_(key, path, 'put', body);
if (![201, 204].includes(saved.code)) {
throw new Error(`Contact write failed (${saved.code}) for ${email}: ${saved.text.slice(0, 200)}`);
}
result.written++;
}
Logger.log(JSON.stringify(result));
return result;
}
function brevo_(key, path, method, body) {
for (let attempt = 0; attempt < 3; attempt++) {
const response = UrlFetchApp.fetch(BASE + path, {
method,
contentType: 'application/json',
headers: { 'api-key': key },
payload: body ? JSON.stringify(body) : undefined,
muteHttpExceptions: true,
});
const code = response.getResponseCode();
if (code !== 429) return { code, text: response.getContentText() };
if (attempt === 2) return { code, text: response.getContentText() };
const reset = Object.entries(response.getHeaders()).find(
([name]) => name.toLowerCase() === 'x-sib-ratelimit-reset'
);
const raw = Number(reset && reset[1]);
const seconds = Number.isFinite(raw) && raw > 0 ? raw : 2 ** attempt;
const waitSeconds = seconds + 2 ** attempt;
if (waitSeconds > 60) return { code, text: response.getContentText() };
Utilities.sleep(waitSeconds * 1000);
}
}

Simpan, pilih syncSheetToBrevo, lalu klik Run. Google meminta izin Sheets dan permintaan eksternal. Lihat catatan {written, skipped} di Executions. Respons baca 404 membuat kontak; 200 memperbaruinya. Error lain menghentikan eksekusi. Penulisan yang berhasil bukan bukti kampanye terkirim.

Skrip menghapus alamat duplikat dalam satu eksekusi dan memeriksa Brevo lagi di eksekusi berikutnya. Skrip tidak pernah mengatur emailBlacklisted ke false atau mengubah alamat. Jika Brevo melaporkan blokir global atau berhenti berlangganan pada daftar target, baris tetap dilewati meski Sheet berisi TRUE. Jangan pakai skrip untuk membatalkan penolakan. Brevo memperingatkan bahwa perubahan email kontak terblokir dapat menghapus blokir.

Periksa satu eksekusi sebelum menjadwalkan

Gunakan daftar uji dan kontak yang Anda kendalikan. Jalankan dengan satu baris TRUE, satu FALSE, dan satu email duplikat: harapkan satu penulisan dan dua dilewati. Hentikan langganan kontak uji di Brevo lalu jalankan ulang: tidak boleh ada penulisan untuknya. Untuk menguji kegagalan, isi sementara LIST_ID tidak valid, periksa error HTTP di Executions, pulihkan ID dan ulangi. Jangan uji pada data pelanggan asli. Kode ini diuji lokal dengan respons Brevo tiruan, tanpa penulisan langsung.

Untuk jadwal, buka Apps Script → Triggers → Add Trigger dan pilih syncSheetToBrevo dengan interval waktu. Pemicu berjalan memakai akun pembuatnya, jadi akun itu harus terus memiliki akses Sheet. Mulai sekali sehari untuk Sheet kecil dan pantau error. Google membatasi durasi dan pemakaian URL Fetch; pecah sumber besar menjadi tugas terbatas.

Pada 429, skrip membaca x-sib-ratelimit-reset dan mencoba ulang paling banyak dua kali. Jika waktu tunggu melebihi 60 detik, skrip mengembalikan 429 untuk eksekusi berikutnya, tanpa mencoba terlalu cepat. Kegagalan lain menghentikan eksekusi; jadwal berikutnya mulai dari awal. Kontak dapat berhenti berlangganan antara pembacaan dan penulisan. Gunakan contoh hanya jika celah pendek ini dapat diterima. Jaminan ketat memerlukan rekonsiliasi peristiwa, sumber izin tepercaya, dan pemeriksaan terakhir sebelum mengirim.

Untuk Sheet besar, impor asinkron Brevo mengembalikan processId. Itu menyatakan tugas diterima, bukan selesai. Periksa hasil sebelum menyatakan sukses. Jalur per kontak di sini menunjukkan baris yang gagal.

Pertanyaan yang sering diajukan

Apakah perlu konektor Google Sheets bawaan?

Tidak. Contoh berjalan pada proyek Apps Script yang terikat ke Sheet dan memanggil API kontak Brevo. Anda mengelola skrip, kunci API, dan pemicu terjadwal.

Baris mana yang dikirim ke Brevo?

Hanya baris dengan consent TRUE dan email valid. Skrip menghapus duplikat setiap kali berjalan dan memeriksa Brevo sebelum menulis.

Apakah menjalankan ulang akan berlangganan kembali kontak yang keluar?

Skrip melewati kontak yang menurut Brevo emailBlacklisted atau berhenti berlangganan dari daftar target. Skrip tidak mengirim emailBlacklisted: false atau mengganti email. Periksa sumber persetujuan dan penekanan lain sebelum produksi.

Bagaimana mengulang eksekusi yang gagal?

Baca error di eksekusi Apps Script, perbaiki penyebabnya, lalu jalankan fungsi yang sama lagi. Alamat dan ID daftar tetap, sehingga baris yang sudah berhasil tidak membuat kontak kedua.

Ajukan akses awal

Masukkan nama depan dan alamat email kerja Anda. Kami akan mengirim tautan untuk mengonfirmasi permintaan akses Tajo.

Dapatkan Brevo