Importér kontakter fra Google Sheets til Brevo med Apps Script

Et gentageligt Google Apps Script, der tjekker samtykke, kortlægger felter, respekterer afmeldinger og viser API-fejl.

google apps script brevo

Hvad er det korte svar?

Tilføj kolonnerne email, firstName, lastName og consent til et ark. Gem BREVO_API_KEY i scriptegenskaberne og liste-id i koden, og kør syncSheetToBrevo. Scriptet behandler kun rækker med samtykke, tjekker afmeldinger i Brevo, fjerner dubletter og stopper ved API-fejl. Det er et Apps Script, du selv vedligeholder, ikke en indbygget forbindelse.

Læs mere
På denne side

Et ark med tolv tilmeldinger til et arrangement er nemt at eksportere én gang. Ved næste import står én adresse der to gange, og en anden person har afmeldt sig i Brevo. En gentagelig import skal håndtere begge dele.

Scriptet bruger Brevos endepunkter til at læse, oprette og opdatere kontakter. Det er til små, planlagte importer, ikke masseindlæsning eller som en indbygget Google Sheets-forbindelse. Det sender ikke e-mails. Du har ansvaret for samtykkedokumentation og drift.

Forbered arket og listen

Opret fanen Contacts med præcis disse overskrifter. Brug afkrydsningsfelter i consent, og sæt kun TRUE, når du har lov til den tiltænkte markedsføring.

emailfirstNamelastNameconsent
[email protected]JaneDoeTRUE
[email protected]AlexLeeFALSE

Opret eller vælg en Brevo-liste, og indsæt dens numeriske id i LIST_ID. Kontroller, at kontaktattributterne FNAME og LNAME findes i Brevo. Kun disse felter er knyttet til arket. Gem dokumentation for hvornår og hvordan samtykket blev givet, hvis arket ikke kan vise det. En TRUE-celle er ikke bevis.

Under Udvidelser → Apps Script → Projektindstillinger → Scriptegenskaber tilføjer du BREVO_API_KEY. Egenskaberne deles af scriptets brugere. Begræns derfor hvem der kan redigere projektet. Læg ikke nøglen i en celle eller i kildekoden. Læs Googles adgangsregler.

Scriptet

Erstat Code.gs med eksemplet, og sæt LIST_ID før første kørsel.

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

Gem projektet, vælg syncSheetToBrevo, og klik Kør. Google beder om adgang til Sheets og eksterne forespørgsler. Under Kørsler finder du slutloggen {written, skipped}. Et 404 ved læsning fører til oprettelse; 200 fører til opdatering. Andre læsefejl stopper kørslen. En vellykket skrivning bekræfter kontaktforespørgslen, ikke en sendt kampagne.

Scriptet fjerner dublerede adresser i samme kørsel og spørger Brevo igen ved næste. Det sætter aldrig emailBlacklisted til false og ændrer ikke e-mailadressen. Hvis Brevo viser global blokering eller afmelding fra listen, springes rækken over, selv om arket viser TRUE. Brug ikke scriptet til at omgøre en afmelding. Brevo advarer om, at ændring af en blokeret kontakts adresse kan fjerne blokeringen.

Kontroller én kørsel før planlægning

Brug en testliste og kontakter, du styrer. Kør med én TRUE-række, én FALSE-række og en dublet: forvent én skrivning og to oversprungne rækker. Afmeld testkontakten i Brevo, og kør igen: den må ikke skrives. Test en fejl ved midlertidigt at sætte LIST_ID til en ugyldig værdi. Se HTTP-fejlen under Kørsler, gendan id’et, og prøv igen. Brug ikke rigtige kundedata til testen. Koden er også testet lokalt med simulerede Brevo-svar uden live-skrivning.

For en tidsplan åbner du Apps Script → Udløsere → Tilføj udløser, vælger syncSheetToBrevo og et tidsinterval. Installerbare udløsere kører under kontoen, som oprettede dem. Kontoen skal bevare adgang til arket. Begynd dagligt for et lille ark og gennemgå fejl. Google begrænser køretid og URL Fetch-kald; del større kilder i afgrænsede jobs.

Ved 429 læser scriptet x-sib-ratelimit-reset og prøver højst to gange mere. Hvis nødvendig ventetid overstiger 60 sekunder, returnerer det 429 til en senere kørsel. Andre fejl stopper kørslen; den næste begynder fra toppen. En kontakt kan afmelde sig mellem læsning og skrivning. Brug kun eksemplet, hvis det korte tidsvindue er acceptabelt. Strammere garantier kræver afstemning via hændelser, en autoritativ samtykkekilde og en sidste kontrol før udsendelse.

For større ark returnerer Brevos asynkrone importendepunkt en processId. Den bekræfter modtagelse af jobbet, ikke færdiggørelse. Kontroller resultatet, før du kalder en større import vellykket. Her er en fejl synlig ved den berørte kontakt.

Ofte Stillede Spørgsmål

Kræver det en indbygget Google Sheets-forbindelse?

Nej. Eksemplet kører i et Google Apps Script-projekt knyttet til arket og kalder Brevos kontakt-API. Du vedligeholder selv scriptet, API-nøglen og den planlagte udløser.

Hvilke rækker sendes til Brevo?

Kun rækker med TRUE i consent og en gyldig e-mailadresse. Scriptet fjerner dubletter i hver kørsel og tjekker Brevo før skrivning.

Tilmeldes en afmeldt kontakt igen ved næste kørsel?

Scriptet springer kontakter over, som Brevo markerer som emailBlacklisted eller afmeldt fra mållisten. Det sender aldrig emailBlacklisted: false og ændrer ikke e-mailadressen. Tjek andre samtykkekilder før produktion.

Hvordan gentager jeg en mislykket kørsel?

Læs fejlen under Apps Script-kørsler, ret årsagen, og kør samme funktion igen. Skrivningerne bruger samme adresse og liste-id, så en tidligere behandlet række opretter ikke en ekstra kontakt.

Bed om tidlig adgang til Tajo

Indtast dit fornavn og din arbejds-e-mailadresse. Vi sender dig et link til at bekræfte din anmodning om adgang til Tajo.

Få Brevo