---
title: "Importer des contacts Google Sheets dans Brevo avec Apps Script"
description: "Un exemple Google Apps Script reproductible qui vérifie le consentement, associe les champs, respecte les désabonnements et signale les erreurs de l’API Brevo."
url: https://tajo.io/fr/blog/import-google-sheet-contacts-to-brevo-apps-script/
markdown: https://tajo.io/fr/blog/import-google-sheet-contacts-to-brevo-apps-script.md
lang: fr-FR
author: "Set Noa"
author_url: https://tajo.io/fr/set-noa/
published: 2026-04-30
updated: 2026-10-09
alternates: {en-US: /blog/import-google-sheet-contacts-to-brevo-apps-script.md, bg-BG: /bg/blog/import-google-sheet-contacts-to-brevo-apps-script.md, cs-CZ: /cz/blog/import-google-sheet-contacts-to-brevo-apps-script.md, de-DE: /de/blog/import-google-sheet-contacts-to-brevo-apps-script.md, da-DK: /dk/blog/import-google-sheet-contacts-to-brevo-apps-script.md, es-ES: /es/blog/import-google-sheet-contacts-to-brevo-apps-script.md, el-GR: /gr/blog/import-google-sheet-contacts-to-brevo-apps-script.md, hi-IN: /hi/blog/import-google-sheet-contacts-to-brevo-apps-script.md, id-ID: /in/blog/import-google-sheet-contacts-to-brevo-apps-script.md, hr-HR: /hr/blog/import-google-sheet-contacts-to-brevo-apps-script.md, hu-HU: /hu/blog/import-google-sheet-contacts-to-brevo-apps-script.md, it-IT: /it/blog/import-google-sheet-contacts-to-brevo-apps-script.md, ja-JP: /jp/blog/import-google-sheet-contacts-to-brevo-apps-script.md, ko-KR: /kr/blog/import-google-sheet-contacts-to-brevo-apps-script.md, ar-SA: /ar/blog/import-google-sheet-contacts-to-brevo-apps-script.md, nl-NL: /nl/blog/import-google-sheet-contacts-to-brevo-apps-script.md, no-NO: /no/blog/import-google-sheet-contacts-to-brevo-apps-script.md, pl-PL: /pl/blog/import-google-sheet-contacts-to-brevo-apps-script.md, pt-BR: /pt/blog/import-google-sheet-contacts-to-brevo-apps-script.md, ro-RO: /ro/blog/import-google-sheet-contacts-to-brevo-apps-script.md, ru-RU: /ru/blog/import-google-sheet-contacts-to-brevo-apps-script.md, sv-SE: /se/blog/import-google-sheet-contacts-to-brevo-apps-script.md, zh-CN: /zh-cn/blog/import-google-sheet-contacts-to-brevo-apps-script.md, sl-SI: /sl/blog/import-google-sheet-contacts-to-brevo-apps-script.md, sr-Latn-RS: /sr/blog/import-google-sheet-contacts-to-brevo-apps-script.md, th-TH: /th/blog/import-google-sheet-contacts-to-brevo-apps-script.md, tr-TR: /tr/blog/import-google-sheet-contacts-to-brevo-apps-script.md, ur-PK: /ur/blog/import-google-sheet-contacts-to-brevo-apps-script.md, vi-VN: /vi/blog/import-google-sheet-contacts-to-brevo-apps-script.md, sk-SK: /sk/blog/import-google-sheet-contacts-to-brevo-apps-script.md}
---

[Synchronisation des données](https://tajo.io/fr/blog/?category=data-sync)

# Importer des contacts Google Sheets dans Brevo avec Apps Script

Un exemple Google Apps Script reproductible qui vérifie le consentement, associe les champs, respecte les désabonnements et signale les erreurs de l’API Brevo.

google apps script brevo

Comment importer des contacts Sheets dans Brevo ?

Ajoutez les colonnes email, firstName, lastName et consent dans une feuille. Définissez BREVO\_API\_KEY dans les propriétés du script et l’identifiant de liste dans le code, puis lancez syncSheetToBrevo. Le script ne traite que les lignes consenties, vérifie les désabonnements dans Brevo, élimine les doublons et s’arrête en cas d’erreur API. Vous entretenez ce script Apps Script : ce n’est pas un connecteur natif.

[En savoir plus](https://tajo.io/fr/blog/import-google-sheet-contacts-to-brevo-apps-script/#pr%C3%A9parer-la-feuille-et-la-liste)

| Champ source | Champ de destination | Valeur d’exemple |
| --- | --- | --- |
| `email` | `email` | `alex@example.com` |
| `firstName` | `FNAME` | `Alex` |
| `lastName` | `LNAME` | `Example` |

Une feuille de douze inscriptions à un événement s’exporte facilement une fois. À la deuxième importation, une adresse est en double et une autre personne s’est désabonnée dans Brevo. Un import reproductible doit tenir compte de ces deux faits.

Le script ci-dessous utilise [les endpoints Brevo de lecture, création et mise à jour des contacts](https://developers.brevo.com/reference/create-contact). Il vise une petite importation planifiée, pas un chargement massif ni un connecteur Google Sheets natif. Il n’envoie aucun e-mail. Vous êtes responsable des preuves de consentement et de l’exploitation du script.

## Préparer la feuille et la liste

Créez un onglet `Contacts` avec exactement ces en-têtes. Utilisez des cases à cocher pour `consent` et réservez `TRUE` aux personnes ayant autorisé l’usage marketing prévu.

| email | firstName | lastName | consent |
| --- | --- | --- | --- |
| [jane@example.com](mailto:jane@example.com) | Jane | Doe | TRUE |
| [alex@example.com](mailto:alex@example.com) | Alex | Lee | FALSE |

Créez ou choisissez une liste Brevo et placez son identifiant numérique dans `LIST_ID` ci-dessous. Vérifiez que les attributs de contact `FNAME` et `LNAME` existent dans Brevo. Ce sont les seuls champs associés. Conservez ailleurs la preuve de la date et du mode de recueil du consentement si la feuille ne le permet pas. Une cellule `TRUE` ne constitue pas une preuve.

Dans **Extensions → Apps Script → Paramètres du projet → Propriétés du script**, ajoutez `BREVO_API_KEY`. Les propriétés du script sont partagées avec les utilisateurs du script ; limitez les droits de modification. Ne placez jamais la clé dans une cellule ni dans le code source. Consultez les [règles d’accès de Google](https://developers.google.com/apps-script/guides/properties).

## Le script

Remplacez `Code.gs` par cet exemple. Définissez `LIST_ID` avant la première exécution.

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

Enregistrez, sélectionnez `syncSheetToBrevo`, puis cliquez sur **Exécuter**. Google demande les autorisations d’accès à Sheets et aux requêtes externes. Dans **Exécutions**, consultez le journal final `{written, skipped}`. Une lecture qui renvoie 404 entraîne une création ; une réponse 200 entraîne une mise à jour. Les autres erreurs de lecture arrêtent l’exécution. Une écriture réussie confirme la requête de contact, pas l’envoi d’une campagne.

Le script élimine les adresses en double pendant une exécution et interroge à nouveau Brevo lors de la suivante. Il ne définit jamais `emailBlacklisted` à `false` et ne change pas l’adresse e-mail. Si Brevo signale un blocage global ou un désabonnement de cette liste, la ligne est ignorée même si la feuille indique `TRUE`. N’utilisez pas le script pour annuler un désabonnement. [Brevo prévient](https://developers.brevo.com/reference/update-contact) que le changement d’adresse d’un contact bloqué peut lever ce blocage.

## Vérifier une exécution avant la planification

Utilisez une liste de test et des contacts de test sous votre contrôle. Exécutez le script avec une ligne `TRUE`, une ligne `FALSE` et une adresse en double : attendez-vous à une écriture et deux lignes ignorées. Désabonnez le contact de test dans Brevo, puis relancez : aucune écriture ne doit le concerner. Pour vérifier un échec, définissez provisoirement un `LIST_ID` invalide, contrôlez l’erreur HTTP dans **Exécutions**, restaurez l’identifiant et relancez. Ne faites pas ces essais sur des données clientes réelles. Le code de cet article a aussi été vérifié localement avec des réponses Brevo simulées, sans écriture réelle.

Pour la planification, ouvrez **Apps Script → Déclencheurs → Ajouter un déclencheur**, choisissez `syncSheetToBrevo`, puis un intervalle temporel. [Un déclencheur installable s’exécute sous le compte qui l’a créé](https://developers.google.com/apps-script/guides/triggers/installable) ; ce compte doit conserver l’accès à la feuille. Commencez par un lancement quotidien et contrôlez les échecs. Google [limite la durée des exécutions et les appels URL Fetch](https://developers.google.com/apps-script/guides/services/quotas). Divisez les sources plus volumineuses en tâches bornées.

Pour un code 429, le script lit `x-sib-ratelimit-reset`, réessaie au plus deux fois et renvoie 429 pour une exécution ultérieure si l’attente nécessaire dépasse 60 secondes. Les autres erreurs arrêtent l’exécution. Le prochain lancement manuel ou planifié reprend depuis le début. Un contact peut se désabonner entre la lecture et l’écriture : cet exemple convient seulement si ce bref intervalle est acceptable. Pour une garantie plus stricte, prévoyez une réconciliation par événements, une source de consentement faisant autorité et une dernière vérification avant l’envoi.

Pour les feuilles plus grandes, [l’endpoint d’import asynchrone de Brevo](https://developers.brevo.com/reference/import-contacts) renvoie un `processId`. Celui-ci confirme l’acceptation d’une tâche, pas son achèvement. Vérifiez le résultat du processus avant d’annoncer un import massif réussi. La voie par contact présentée ici rend l’erreur visible sur la ligne concernée.

## Questions fréquemment posées

**Faut-il un connecteur Google Sheets natif ?**

Non. Cet exemple s’exécute dans un projet Google Apps Script lié à la feuille et appelle l’API des contacts Brevo. Vous entretenez le script, sa clé API et son déclencheur planifié.

**Quelles lignes sont envoyées à Brevo ?**

Seules les lignes dont la colonne consent vaut TRUE et dont l’adresse e-mail est valide. Le script élimine les doublons pendant chaque exécution et interroge Brevo avant chaque écriture.

**Une nouvelle exécution réabonne-t-elle un contact désabonné ?**

Le script ignore les contacts que Brevo signale comme emailBlacklisted ou désabonnés de la liste cible. Il n’envoie jamais emailBlacklisted: false et ne modifie pas leur adresse e-mail. Vérifiez les autres sources de consentement avant la production.

**Comment relancer une exécution en échec ?**

Consultez l’erreur dans les exécutions Apps Script, corrigez sa cause, puis relancez la même fonction. Les écritures reprennent la même adresse et le même identifiant de liste ; une ligne déjà traitée ne crée donc pas un deuxième contact.

## Articles connexes

### [Comment importer des contacts CSV ou Excel dans Brevo avec un script (Python, Node.js, cURL)](https://tajo.io/fr/blog/import-csv-contacts-to-brevo-with-a-script/)

30 avr. 2026 · 6 min de lecture

CSV → Brevo

### [Comment pousser des contacts Excel vers Brevo avec une macro VBA (et l’alternative Office Scripts)](https://tajo.io/fr/blog/import-excel-contacts-to-brevo-with-vba-macro/)

30 avr. 2026 · 7 min de lecture

Microsoft Excel → Brevo

### [Intégrations Brevo : choisir une connexion vérifiable](https://tajo.io/fr/blog/brevo-connector-guide/)

19 août 2026 · 4 min de lecture

6 sections
