quest_sgtm_bigquery_export_direct.exe
_
×

Export GA4 BigQuery : passer la limite du 1 M avec sGTM

L'export GA4 BigQuery se suspend au-delà d'1 M d'événements par jour. Écrivez vos hits directement depuis sGTM vers BigQuery : méthode, coût, décision.

bigquery sgtm ga4 guide

Si votre export GA4 vers BigQuery s’est arrêté sans prévenir un matin, ce n’est pas un bug : c’est le plafond. L’export quotidien natif se suspend au-delà d’un million d’événements par jour, et Google ne rattrape pas les données perdues. Vous ne les récupérez jamais. La bonne nouvelle : depuis que Google a ouvert l’API BigQuery dans le conteneur serveur, on peut contourner cette limite en écrivant les hits directement depuis sGTM vers BigQuery, en streaming, sans plafond. Voici comment, combien ça coûte, et surtout quand ça ne vaut pas le coup.

Les deux plafonds de l’export GA4 BigQuery que personne n’anticipe

Tout le monde connaît l’export natif GA4 vers BigQuery. C’est gratuit, c’est en deux clics dans l’admin, et c’est très bien pour la majorité des sites. Le problème, c’est qu’il a deux limites qu’on ne découvre qu’en les heurtant.

Le plafond du million. L’export quotidien est plafonné à 1 million d’événements par jour. Au-delà, Google ne met pas les événements en file d’attente pour plus tard : il suspend purement et simplement l’export du jour. Vos données de la journée sont perdues, sans rattrapage possible. Pour un site à fort trafic ou un e-commerce en période de soldes, c’est un trou dans l’historique que rien ne vient combler.

Le délai. Même sous le plafond, l’export quotidien arrive avec 24 à 48 h de retard, et Google back-fille les événements en retard jusqu’à trois jours après. Concrètement : la table de la veille (events_YYYYMMDD) n’est pas fiable si vous l’interrogez trop tôt. Vos chiffres bougeront encore. Si vous construisez un dashboard intraday là-dessus, vous racontez des histoires.

Je détaille l’export natif et son exploitation dans le guide de l’export GA4 BigQuery : cet article-ci part du principe que vous le connaissez et se concentre sur le différentiel.

Trois façons d’alimenter BigQuery : le comparatif

Avant de bricoler quoi que ce soit, posons les options sur la table. Il y en a trois, et la troisième est celle que peu de monde utilise encore.

CritèreExport quotidienExport streaming GA4Écriture directe sGTM
Fraîcheur24 à 48 h~15 minQuasi temps réel
Plafond d’événements1 M/jour (suspend au-delà)Aucun plafond durAucun plafond dur
CoûtGratuit~0,05 $/Go (streaming)~0,05 $/Go + Cloud Run
SchémaSchéma export GA4Schéma export GA4Le vôtre (à définir)
Enrichissement serveurNonNonOui (avant insertion)
Immunité ad blockerPartiellePartielleOui (côté serveur)
Effort de mise en placeDeux clicsDeux clicsÉlevé (template, IAM, schéma)

L’export streaming GA4 lève le plafond du million et réduit le délai à un quart d’heure, pour un coût de l’ordre de 0,05 $ par Go streamé. C’est souvent la réponse suffisante, et honnêtement, si votre seul problème est le plafond, commencez par là. L’écriture directe depuis sGTM devient intéressante quand vous voulez autre chose que ce que GA4 sait faire : un schéma à vous, un enrichissement au niveau serveur, ou une fraîcheur que même le streaming GA4 ne garantit pas.

Écrire depuis sGTM vers BigQuery : l’implémentation

Depuis que le sandbox du conteneur serveur expose l’API BigQuery, un tag serveur peut insérer des lignes dans une table BigQuery via BigQuery.insert. La fonction prend les informations de connexion (projet, dataset, table), un tableau de lignes, et renvoie une promesse qui se résout à l’insertion ou se rejette avec la liste des erreurs par ligne. Il vous faut un conteneur serveur opérationnel : si vous n’en avez pas, commencez par le guide de migration vers GTM server-side.

1. Le service account et le rôle IAM. Créez un service account dédié et donnez-lui le rôle BigQuery Data Editor, scopé au dataset, pas au projet entier. Le principe du moindre privilège vaut ici aussi : ce compte n’a besoin d’écrire que dans une table. Si votre conteneur tourne sur Cloud Run avec un service account attaché, l’API peut s’authentifier automatiquement, sans clé à balader.

2. Le schéma de table. C’est le piège numéro un, donc je le répète : le schéma que vous définissez n’est pas celui de l’export natif GA4. Pas de event_params en RECORD répété, pas de structure imbriquée héritée de Google. Vous partez d’une feuille blanche. Un schéma minimal ressemble à ça :

CREATE TABLE `projet.dataset.events_direct` (
  event_name    STRING,
  event_ts      TIMESTAMP,
  client_id     STRING,
  user_id       STRING,
  page_location STRING,
  value         NUMERIC,
  currency      STRING,
  consent_state STRING,
  params        JSON
);

3. Le tag serveur. Dans un tag personnalisé (ou via le template du repo google/sgtm-ga4-to-bigquery), on récupère les données de l’événement, on construit la ligne, et on appelle l’insertion :

const BigQuery = require('BigQuery');
const getAllEventData = require('getAllEventData');

const event = getAllEventData();
const connection = {
  projectId: 'projet',
  datasetId: 'dataset',
  tableId: 'events_direct'
};
const rows = [{
  event_name: event.event_name,
  event_ts: (new Date()).toISOString(),
  client_id: event.client_id,
  value: event['x-ga-mp1-ev'] || 0,
  params: JSON.stringify(event)
}];

BigQuery.insert(connection, rows, {ignoreUnknownValues: true})
  .then(data.gtmOnSuccess, data.gtmOnFailure);

4. Le repo Google, à utiliser en connaissance de cause. Google publie un template prêt à l’emploi (google/sgtm-ga4-to-bigquery) qui gère les événements batchés, le Consent Mode v2 et l’attribution Google Ads. Il vous fait gagner un temps fou. Mais son README le dit noir sur blanc : ce n’est pas un produit supporté par Google. Pas de SLA, pas de support officiel. Vous l’adoptez, vous le maintenez. C’est un choix parfaitement raisonnable, à condition de l’assumer et de ne pas le poser sur un pipeline critique sans surveillance.

Ce que l’écriture directe permet, et que l’export ne permettra jamais

Si c’était juste pour contourner le plafond, l’export streaming GA4 suffirait. Le vrai intérêt de l’écriture directe est ailleurs.

L’enrichissement avant insertion. Au niveau serveur, vous avez la main sur la donnée avant qu’elle ne touche BigQuery. Vous pouvez joindre une valeur de commande corrigée, injecter un segment CRM, résoudre une géo, nettoyer un paramètre pourri, tout ça avant l’écriture. L’export natif prend ce que GA4 a reçu, point. Pour aller plus loin sur la boucle serveur vers CRM, voyez le Measurement Protocol GA4 côté serveur.

L’immunité aux ad blockers. Le hit part du serveur, pas du navigateur. Un bloqueur qui aurait tué la requête client ne peut rien contre une insertion serveur. Vous récupérez des événements que l’export natif, dépendant du tag client, n’a jamais vus.

La fraîcheur. Quasi temps réel, sans les 15 minutes du streaming GA4 ni les 24-48 h du quotidien. Pour un dashboard opérationnel qui doit refléter l’instant, ça change tout.

Les pièges à connaître avant de basculer

Je ne vais pas vous vendre du rêve. Cette approche a un coût, au sens propre et au sens figuré.

Le schéma vous appartient, donc vos requêtes existantes ne marchent plus. Toutes les requêtes calibrées sur le schéma de l’export GA4 (celles du guide des requêtes BigQuery GA4 indispensables, par exemple) visent event_params, user_properties, la structure imbriquée maison de Google. Sur votre table directe, elles renvoient une erreur. Vous réécrivez, ou vous reproduisez le schéma GA4 à l’identique, ce qui est fastidieux.

Le coût du streaming insert. L’API BigQuery.insert passe par le streaming insert legacy, facturé autour de 0,05 $ par Go inséré, en plus du stockage et du Cloud Run qui fait tourner le conteneur. Ce n’est pas cher au Go, mais à fort volume ça s’additionne. Faites le calcul complet, streaming insert plus infrastructure serveur, en vous appuyant sur le vrai coût du GTM server-side.

Le consentement, toujours. Écrire en base ne vous dispense de rien. Si l’utilisateur n’a pas consenti, vous n’écrivez pas ses données personnelles, ou vous les écrivez anonymisées. Le Consent Mode v2 doit être respecté côté serveur exactement comme côté client. Un pipeline direct qui ignore le consentement, c’est une non-conformité, pas une optimisation.

Arbre de décision : qui doit basculer, qui doit rester

Voici comment je tranche en mission.

Restez sur l’export natif si vous êtes sous le million d’événements par jour et que la fraîcheur J-1 vous suffit. C’est gratuit, c’est robuste, le schéma est standard, et toute la communauté sait l’interroger. Ne complexifiez pas pour le plaisir.

Passez à l’export streaming GA4 si vous dépassez le million ou si vous voulez une fraîcheur à 15 minutes, mais que le schéma GA4 vous convient et que vous n’avez pas besoin d’enrichir la donnée. C’est le meilleur rapport effort/résultat pour la plupart des cas de dépassement.

Écrivez directement depuis sGTM si vous cumulez au moins deux de ces besoins : volume massif, quasi temps réel strict, enrichissement serveur avant insertion, immunité ad blocker. C’est là que l’effort de mise en place se rentabilise. En dessous, vous vous compliquez la vie pour rien.

Vérifier que ça marche

Ne faites jamais confiance à un pipeline sur parole. Une fois en place, comparez trois volumes sur une même journée : ce que sGTM a écrit, ce que l’export GA4 a reçu, et ce que l’interface GA4 affiche. La requête de contrôle est simple :

SELECT
  DATE(event_ts) AS jour,
  COUNT(*) AS events_directs
FROM `projet.dataset.events_direct`
WHERE DATE(event_ts) = CURRENT_DATE() - 1
GROUP BY jour;

Un écart est normal (l’immunité ad blocker et l’enrichissement font que le pipeline direct capte plus), mais il doit être explicable. Un écart que vous ne savez pas justifier, c’est un bug qui se cache.

L’écriture directe sGTM vers BigQuery n’est pas la solution par défaut, et c’est très bien comme ça. C’est l’outil du praticien qui a heurté un vrai plafond ou qui a un vrai besoin d’enrichissement. Si vous êtes dans ce cas, vous venez de récupérer un pipeline sans limite, en quasi temps réel, que vous maîtrisez de bout en bout. Si vous n’y êtes pas, gardez l’export natif et dormez tranquille.