Импорт на контакти от Google Sheets в Brevo с Apps Script

Повторяем пример с Google Apps Script: проверка на съгласие, съпоставяне на полета, запазване на откази и видими грешки на API.

google apps script brevo

Какъв е краткият отговор?

Добавете колони email, firstName, lastName и consent в таблицата. Задайте BREVO_API_KEY в свойствата на скрипта и ID на списъка в кода, после стартирайте syncSheetToBrevo. Скриптът обработва само редове със съгласие, проверява отказите в Brevo, премахва дубликати и спира при грешка на API. Това е Apps Script, който Вие поддържате, не вграден конектор.

Научете повече
На тази страница

Таблица с дванадесет регистрации за събитие се експортира лесно веднъж. При втория импорт един адрес се повтаря, а друг човек вече се е отписал в Brevo. Повторяемият импорт трябва да разпознае и двете ситуации.

Скриптът използва крайните адреси на Brevo за четене, създаване и обновяване на контакти. Той е за малки планирани импорти, не за масово зареждане или като вграден конектор за Google Sheets. Не изпраща имейли. Вие отговаряте за доказателството за съгласие и работата на скрипта.

Подгответе таблицата и списъка

Създайте раздел Contacts с точно тези заглавия. Използвайте квадратчета за consent и поставяйте TRUE само при съгласие за предвидения маркетинг.

emailfirstNamelastNameconsent
[email protected]JaneDoeTRUE
[email protected]AlexLeeFALSE

Създайте или изберете списък в Brevo и въведете числовия му ID в LIST_ID. Проверете дали атрибутите FNAME и LNAME съществуват в Brevo. Само те се съпоставят. Пазете отделно доказателство кога и как е дадено съгласието, ако таблицата не може да го установи. Клетка TRUE сама по себе си не е доказателство.

В Разширения → Apps Script → Настройки на проекта → Свойства на скрипта добавете BREVO_API_KEY. Свойствата се споделят между потребителите на скрипта, затова ограничете правото за редактиране. Не поставяйте ключа в клетка или код. Вижте правилата за достъп на Google.

Скриптът

Заменете Code.gs с примера и настройте 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);
}
}

Запазете, изберете syncSheetToBrevo и натиснете Изпълни. Google ще поиска достъп до Sheets и външни заявки. В Изпълнения вижте крайния запис {written, skipped}. Отговор 404 при четене води до създаване на контакт, 200 до обновяване. Други грешки спират изпълнението. Успешният запис потвърждава заявката за контакт, не изпращане на кампания.

Скриптът премахва повторените адреси в едно изпълнение и пита Brevo отново при следващото. Никога не задава emailBlacklisted като false и не променя имейла. Ако Brevo отчете блокиране или отписване от списъка, редът се пропуска дори при TRUE. Не използвайте скрипта за отмяна на отписване. Brevo предупреждава, че смяна на адреса на блокиран контакт може да премахне блокирането.

Проверете едно изпълнение преди график

Използвайте тестов списък и контакти под Ваш контрол. Стартирайте с един ред TRUE, един FALSE и повторен адрес: очаквайте един запис и два пропуснати реда. Отпишете тестовия контакт в Brevo и повторете: за него не трябва да има запис. За проверка на грешка задайте временно невалиден LIST_ID, вижте HTTP грешката в Изпълнения, възстановете ID и опитайте пак. Не тествайте с реални клиентски данни. Кодът е проверен локално и със симулирани отговори на Brevo, без реален запис.

За график отворете Apps Script → Тригери → Добави тригер, изберете syncSheetToBrevo и времеви интервал. Тригерите работят с акаунта на създателя; той трябва да запази достъп до таблицата. За малка таблица започнете всекидневно и преглеждайте грешките. Google ограничава времето за изпълнение и URL Fetch заявките; разделете големите източници на ограничени задачи.

При 429 скриптът чете x-sib-ratelimit-reset и опитва най-много още два пъти. Ако нужното изчакване надхвърля 60 секунди, връща 429 за по-късно изпълнение. Другите грешки спират работата; следващото изпълнение започва отначало. Контакт може да се отпише между четенето и записа. Използвайте примера само ако краткият прозорец е приемлив. По-строги гаранции изискват съгласуване по събития, надежден източник на съгласие и последна проверка преди изпращане.

За големи таблици асинхронният краен адрес за импорт на Brevo връща processId. Това потвърждава приемане на задачата, не завършване. Проверете резултата преди да отчетете успех. Пътят по отделни контакти показва грешката при съответния ред.

Често Задавани Въпроси

Нужен ли е вграден конектор за Google Sheets?

Не. Примерът работи в проект Google Apps Script, свързан с таблицата, и извиква API за контакти на Brevo. Вие поддържате скрипта, API ключа и планирания тригер.

Кои редове се изпращат към Brevo?

Само тези с TRUE в consent и валиден имейл адрес. Скриптът премахва дубликатите при всяко изпълнение и проверява Brevo преди запис.

Ново изпълнение записва ли отново отказал се контакт?

Скриптът пропуска контакти, които Brevo обозначава като emailBlacklisted или отписани от целевия списък. Никога не изпраща emailBlacklisted: false и не променя имейла. Преди продукция проверете и други източници на съгласие.

Как да повторя неуспешно изпълнение?

Прочетете грешката в изпълненията на Apps Script, отстранете причината и стартирайте същата функция отново. Записите използват същия адрес и ID на списъка, затова успешно обработен ред не създава втори контакт.

Заявете ранен достъп

Въведете собственото си име и служебен имейл адрес. Ще ви изпратим връзка за потвърждение на заявката за достъп до Tajo.

Вземете Brevo