Import kontaktów z Google Sheets do Brevo przez Apps Script

Powtarzalny przykład Google Apps Script: sprawdzanie zgody, mapowanie pól, ochrona wypisanych kontaktów i widoczne błędy API.

google apps script brevo

Jaka jest krótka odpowiedź?

Dodaj w arkuszu kolumny email, firstName, lastName i consent. Ustaw BREVO_API_KEY we właściwościach skryptu i ID listy w kodzie, a potem uruchom syncSheetToBrevo. Skrypt uwzględnia tylko wiersze ze zgodą, sprawdza wypisanie w Brevo, usuwa duplikaty i zatrzymuje się przy błędzie API. To Apps Script, który utrzymujesz samodzielnie, a nie natywny konektor.

Dowiedz się więcej
Na tej stronie

Arkusz z dwunastoma zapisami na wydarzenie łatwo wyeksportować raz. Przy drugim imporcie jeden adres występuje dwukrotnie, a inna osoba wypisała się już w Brevo. Powtarzalny import musi uwzględnić oba przypadki.

Skrypt korzysta z endpointów Brevo do odczytu, tworzenia i aktualizacji kontaktów. Służy do małego, planowanego importu, nie do masowego ładowania ani jako natywny konektor Google Sheets. Nie wysyła wiadomości. Za dowód zgody i utrzymanie skryptu odpowiadasz Ty.

Przygotuj arkusz i listę

Utwórz kartę Contacts z dokładnie takimi nagłówkami. Użyj pól wyboru w kolumnie consent; ustaw TRUE tylko przy zgodzie na zamierzone działania marketingowe.

emailfirstNamelastNameconsent
[email protected]JaneDoeTRUE
[email protected]AlexLeeFALSE

Utwórz lub wybierz listę Brevo i wpisz jej numeryczne ID jako LIST_ID. Sprawdź, czy atrybuty FNAME i LNAME istnieją w Brevo; tylko te pola są mapowane. Zachowaj poza arkuszem informację, kiedy i jak uzyskano zgodę, jeśli arkusz tego nie dowodzi. Sama komórka TRUE nie jest dowodem.

W Rozszerzenia → Apps Script → Ustawienia projektu → Właściwości skryptu dodaj BREVO_API_KEY. Właściwości są wspólne dla użytkowników skryptu, więc ogranicz prawo edycji. Nie umieszczaj klucza w komórce ani w kodzie. Przeczytaj zasady dostępu Google.

Skrypt

Zastąp Code.gs tym przykładem. Przed uruchomieniem ustaw LIST_ID.

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);
}
}

Zapisz projekt, wybierz syncSheetToBrevo i kliknij Uruchom. Google poprosi o dostęp do Sheets i żądań zewnętrznych. W Wykonaniach zobaczysz końcowy zapis {written, skipped}. Odczyt 404 prowadzi do utworzenia kontaktu, a 200 do aktualizacji. Inne błędy odczytu zatrzymują proces. Udany zapis potwierdza żądanie kontaktowe, nie wysłanie kampanii.

Skrypt usuwa powtórzone adresy w obrębie jednego przebiegu i przy następnym ponownie odpytuje Brevo. Nigdy nie ustawia emailBlacklisted na false ani nie zmienia adresu. Jeśli Brevo zgłasza blokadę lub wypisanie z tej listy, wiersz jest pomijany nawet przy TRUE w arkuszu. Nie używaj tego kodu do cofania wypisania. Brevo ostrzega, że zmiana adresu zablokowanego kontaktu może usunąć blokadę.

Sprawdź przebieg przed zaplanowaniem

Użyj listy testowej i kontaktów pod Twoją kontrolą. Uruchom skrypt z wierszem TRUE, wierszem FALSE i powtórzonym adresem: oczekuj jednego zapisu i dwóch pominięć. Wypisz kontakt testowy w Brevo i uruchom ponownie: nie powinien być zapisany. Na próbę błędu ustaw chwilowo błędny LIST_ID, odczytaj błąd HTTP w Wykonaniach, przywróć ID i powtórz. Nie testuj na prawdziwych danych klientów. Kod sprawdzono także lokalnie na symulowanych odpowiedziach Brevo, bez zapisu live.

Aby zaplanować przebiegi, wybierz Apps Script → Wyzwalacze → Dodaj wyzwalacz, funkcję syncSheetToBrevo i interwał czasowy. Wyzwalacze działają z konta osoby, która je utworzyła. Konto musi zachować dostęp do arkusza. Zacznij od uruchomienia raz dziennie i przeglądaj błędy. Google ogranicza czas wykonania i wywołania URL Fetch; duże źródła dziel na mniejsze zadania.

Przy 429 skrypt czyta x-sib-ratelimit-reset, ponawia najwyżej dwa razy i zwraca 429 do późniejszego przebiegu, jeśli wymagane oczekiwanie przekracza 60 sekund. Inne błędy kończą przebieg; następny zaczyna od początku. Kontakt może wypisać się między odczytem a zapisem. Ten przykład nadaje się tylko wtedy, gdy akceptujesz to krótkie okno. Gdy wymagasz mocniejszej gwarancji, potrzebujesz uzgadniania zdarzeń, źródła prawdy o zgodzie i końcowej kontroli przed wysyłką.

Przy większych arkuszach asynchroniczny endpoint importu Brevo zwraca processId: oznacza przyjęcie zadania, nie jego zakończenie. Sprawdź wynik procesu przed ogłoszeniem sukcesu. W pokazanej ścieżce błędy są widoczne przy konkretnym kontakcie.

Najczęściej Zadawane Pytania

Czy potrzebujesz natywnego konektora Google Sheets?

Nie. Przykład działa w projekcie Google Apps Script powiązanym z arkuszem i wywołuje API kontaktów Brevo. Samodzielnie utrzymujesz skrypt, klucz API i zaplanowany wyzwalacz.

Które wiersze trafiają do Brevo?

Tylko te z wartością TRUE w kolumnie consent i poprawnym adresem e-mail. Skrypt usuwa duplikaty w każdym przebiegu i sprawdza Brevo przed zapisem.

Czy ponowny przebieg zapisze wypisaną osobę?

Skrypt pomija kontakty oznaczone w Brevo jako emailBlacklisted lub wypisane z listy docelowej. Nigdy nie wysyła emailBlacklisted: false ani nie zmienia adresu e-mail. Przed produkcją sprawdź także inne źródła zgody.

Jak wznowić nieudany przebieg?

Sprawdź błąd w wykonaniach Apps Script, usuń przyczynę i ponownie uruchom tę samą funkcję. Zapisy używają tego samego adresu i ID listy, więc wcześniej obsłużony wiersz nie tworzy drugiego kontaktu.

Poproś o wcześniejszy dostęp

Podaj imię i firmowy adres e-mail. Wyślemy Ci link potwierdzający prośbę o dostęp do Tajo.

Zdobądź Brevo