Utiliser la fonction AI.DETECT_ANOMALIES de BigQuery pour tester un dataset GA4
Quand une nouvelle fonction arrive dans BigQuery, je fais toujours la même chose : je lis la doc, je regarde les paramètres, je vérifie les limites, puis je la teste sur un vrai dataset.
C’est exactement ce que j’ai fait avec la fonction BigQuery AI.DETECT_ANOMALIES.
La fonction est simple à comprendre : elle détecte des anomalies dans une série temporelle en s’appuyant sur le modèle TimesFM intégré à BigQuery ML. Je lui donne un historique, une période cible, une colonne numérique et une colonne temporelle. BigQuery calcule une plage attendue, puis me renvoie la valeur observée, les bornes basse et haute, un booléen is_anomaly, une probabilité d’anomalie et un statut technique.
L’intérêt est immédiat. Je peux vérifier si mes données sont cohérentes.
- Est-ce qu’il manque du trafic ?
- Est-ce qu’un volume s’effondre brutalement ?
- Est-ce qu’un pic est plausible ou suspect ?
- Est-ce qu’un import a cassé ma série ?
Sur ce terrain-là, la fonction a une vraie valeur.
🚀 Maîtrisez SQL pour exploiter pleinement vos données BigQuery !
Découvrez nos formations BigQuery adaptées à tous les niveaux, du débutant à l’expert. Apprenez à interroger, analyser et optimiser vos données avec SQL dans BigQuery, et exploitez toute la puissance du cloud pour des analyses avancées. Du niveau 1, où vous explorerez et visualiserez vos données avec BigQuery et Looker Studio, au niveau 2, qui vous permettra de maîtriser les requêtes SQL pour trier, filtrer et structurer efficacement vos données, jusqu’au niveau 3, dédié aux techniques avancées d’optimisation et d’automatisation. Que vous soyez analyste, data scientist ou développeur, ces formations vous permettront de gagner en autonomie et en efficacité dans le traitement de vos données.🔍📊
Ce que fait réellement la fonction
La syntaxe tient en quelques lignes :
SELECT *
FROM AI.DETECT_ANOMALIES(
TABLE `mydataset.history_table`,
TABLE `mydataset.target_table`,
data_col => 'metric_value',
timestamp_col => 'metric_date'
);
La doc officielle précise les paramètres principaux :
| Paramètre | Obligatoire | Rôle |
|---|---|---|
history_table ou sous-requête | Oui | historique de référence |
target_table ou sous-requête | Oui | période à évaluer |
data_col | Oui | colonne numérique à surveiller |
timestamp_col | Oui | colonne temporelle |
model | Non | TimesFM 2.0 ou TimesFM 2.5 |
id_cols | Non | plusieurs séries en parallèle |
anomaly_prob_threshold | Non | seuil d’anomalie |
context_window | Non | longueur de contexte utilisée par le modèle |
BigQuery supporte INT64, NUMERIC, BIGNUMERIC et FLOAT64 pour data_col, et DATE, DATETIME ou TIMESTAMP pour timestamp_col. Si je ne renseigne pas context_window, BigQuery choisit automatiquement la plus petite fenêtre compatible avec la taille de la série.
Le principe de lecture est basique : une valeur est considérée comme anormale si elle passe sous lower_bound ou au-dessus de upper_bound.
Pourquoi la fonction AI.DETECT_ANOMALIES est utile ?
Je ne vois pas cette fonction comme un gadget “IA dans SQL”. Je la vois comme une brique de supervision.
Elle a toute sa place en production pour trois raisons.
La première, c’est la simplicité. Google positionne clairement l’approche TimesFM comme une voie légère, sans création ni maintenance de modèle, contrairement aux approches ARIMA qui demandent plus de pilotage.
La deuxième, c’est l’intégration naturelle dans une stack data. Je peux la lancer dans BigQuery, stocker les résultats, historiser les anomalies, alimenter un dashboard QA, déclencher une alerte, ou enrichir une logique de contrôle avant publication d’un reporting.
La troisième, c’est la couverture fonctionnelle. Dès que j’ai une série temporelle propre, la fonction devient exploitable.
Exemples de cas d’usage sur n’importe quel dataset
Le plus intéressant, ce n’est pas seulement la détection d’anomalies. C’est tout ce qu’on peut bâtir autour.
| Cas d’usage | Ce que je surveille | À quoi ça sert |
|---|---|---|
| QA de données | volumes journaliers, imports, exports | repérer un trou ou un pic suspect |
| Monitoring de pipelines | lignes importées, commandes, leads, coûts | voir si un flux décroche |
| Contrôle avant dashboard | KPIs du jour ou de la semaine | éviter de publier un chiffre cassé |
| Alertes métier | ventes, CA, taux de conversion, tickets | détecter vite une rupture |
| Supervision marketing | clics, dépenses, conversions | voir si un canal s’emballe ou s’effondre |
| Audit qualité | logs d’anomalies historisés | mesurer le bruit et ajuster les seuils |
Je peux l’utiliser sur des ventes quotidiennes, des données CRM, des dépenses média, des volumes de tickets support, des données produit, des métriques IoT, des imports backend ou des événements applicatifs. Tant que j’ai une table avec une date et une valeur, je peux tester.
Principaux paramètres de la fonction AI.DETECT_ANOMALIES
Tous les paramètres n’ont pas le même poids dans la pratique.
| Paramètre | Ce qu’il change concrètement |
|---|---|
id_cols | je surveille plusieurs séries segmentées au lieu d’un total global |
anomaly_prob_threshold | je rends la détection plus ou moins sensible |
model | je choisis TimesFM 2.0 ou TimesFM 2.5 selon la profondeur d’historique |
context_window | je contrôle combien de points récents le modèle utilise |
Google documente les fenêtres supportées : TimesFM 2.0 supporte jusqu’à 2 048 points, TimesFM 2.5 jusqu’à 15 360 points. En revanche, seuls les 1 024 points les plus récents sont évalués pour les anomalies. C’est un détail important pour les longues séries.
Réponse de la fonction AI.DETECT_ANOMALIES
Voici les colonnes vraiment utiles à exploiter :
| Colonne | Utilité |
|---|---|
time_series_timestamp | date ou timestamp observé |
time_series_data | valeur observée |
lower_bound | borne basse attendue |
upper_bound | borne haute attendue |
is_anomaly | drapeau principal |
anomaly_probability | intensité du signal |
ai_detect_anomalies_status | statut technique |
En clair, je peux non seulement savoir qu’un point est anormal, mais aussi mesurer à quel point il s’écarte du cadre attendu.
Premier exemple : contrôle simple sur un dataset générique
Prenons un cas classique : des ventes quotidiennes.
SELECT *
FROM AI.DETECT_ANOMALIES(
TABLE `sales.history_daily_sales`,
TABLE `sales.target_daily_sales`,
data_col => 'units_sold',
timestamp_col => 'sales_date'
);
Lecture type :
| Date | Ventes | Borne basse | Borne haute | Anomalie |
|---|---|---|---|---|
| 2026-04-01 | 420 | 360 | 510 | false |
| 2026-04-02 | 438 | 355 | 505 | false |
| 2026-04-03 | 190 | 350 | 500 | true |
Dans ce cas, je m’en sers pour vérifier un trou potentiel avant analyse. Est-ce une rupture de stock ? Un bug d’import ? Un incident logistique ? Une baisse réelle ? Peu importe à ce stade : la fonction m’a signalé qu’il faut regarder.
Deuxième exemple : plusieurs séries en parallèle
C’est souvent là que la fonction devient vraiment utile.
SELECT *
FROM AI.DETECT_ANOMALIES(
TABLE `marketing.history_daily_revenue`,
TABLE `marketing.target_daily_revenue`,
data_col => 'revenue',
timestamp_col => 'date',
id_cols => ['channel'],
anomaly_prob_threshold => 0.90
);
Lecture type :
| Date | Canal | Revenue | Anomalie |
|---|---|---|---|
| 2026-04-10 | organic | 8 500 | false |
| 2026-04-10 | paid_search | 12 900 | false |
| 2026-04-10 | 1 050 | true |
Sans id_cols, le total global peut masquer le problème. Avec id_cols, je vois immédiatement quel segment décroche.
Pourquoi le test sur un export GA4 est intéressant
Un export GA4 dans BigQuery est un très bon dataset de test.
Il est riche, granulaire, parfois bruité, sensible aux changements de tracking, aux effets marketing, aux variations de consentement et aux incidents de collecte. Bref, il ressemble à la vraie vie.
Google rappelle d’ailleurs que l’export GA4 alimente des tables quotidiennes events_YYYYMMDD, et recommande d’interroger ces tables plutôt que events_intraday_YYYYMMDD lorsqu’on veut un dataset stable sur la journée.
La conséquence est simple : si je veux exploiter AI.DETECT_ANOMALIES proprement sur un export GA4, je pars d’abord sur des agrégats stables.
Ce que je surveille dans un dataset GA4
Je ne branche pas la fonction directement sur events_*. Je construis d’abord des séries lisibles.
Les plus utiles sont souvent celles-ci :
| Série GA4 | Usage |
|---|---|
| sessions par jour | vérifier la stabilité globale de la collecte |
| achats par jour | repérer un incident checkout ou tracking |
| revenu par jour | détecter une rupture e-commerce |
| leads par jour | surveiller les formulaires et tunnels |
| sessions par canal | repérer un décrochage acquisition |
| revenu par canal | détecter une chute masquée dans le total |
| événements critiques | surveiller add_to_cart, begin_checkout, purchase, generate_lead |
Exemple GA4 1 : sessions quotidiennes
Les requêtes GA4 officielles montrent bien comment récupérer ga_session_id dans event_params.
Je peux donc construire une table de sessions quotidiennes comme ceci :
CREATE OR REPLACE TABLE `project.dataset.ga4_sessions_daily` AS
SELECT
PARSE_DATE('%Y%m%d', event_date) AS date,
COUNT(DISTINCT CONCAT(
user_pseudo_id,
CAST((SELECT value.int_value
FROM UNNEST(event_params)
WHERE key = 'ga_session_id') AS STRING)
)) AS sessions
FROM `project.analytics_123456789.events_*`
WHERE _TABLE_SUFFIX BETWEEN '20260101' AND '20260331'
GROUP BY 1
ORDER BY 1;
Puis je lance la détection :
SELECT *
FROM AI.DETECT_ANOMALIES(
(SELECT date, sessions
FROM `project.dataset.ga4_sessions_daily`
WHERE date < DATE '2026-03-01'),
(SELECT date, sessions
FROM `project.dataset.ga4_sessions_daily`
WHERE date >= DATE '2026-03-01'),
data_col => 'sessions',
timestamp_col => 'date'
);
Lecture typique :
| Date | Sessions | Anomalie | Lecture |
|---|---|---|---|
| 2026-03-02 | 18 240 | false | normal |
| 2026-03-03 | 18 510 | false | stable |
| 2026-03-04 | 11 980 | true | trou à vérifier |
Ici, la fonction me sert d’abord à valider mes données avant analyse.
Exemple GA4 2 : achats quotidiens
CREATE OR REPLACE TABLE `project.dataset.ga4_purchases_daily` AS
SELECT
PARSE_DATE('%Y%m%d', event_date) AS date,
COUNTIF(event_name = 'purchase') AS purchases
FROM `project.analytics_123456789.events_*`
WHERE _TABLE_SUFFIX BETWEEN '20260101' AND '20260331'
GROUP BY 1
ORDER BY 1;
SELECT *
FROM AI.DETECT_ANOMALIES(
(SELECT date, purchases
FROM `project.dataset.ga4_purchases_daily`
WHERE date < DATE '2026-03-01'),
(SELECT date, purchases
FROM `project.dataset.ga4_purchases_daily`
WHERE date >= DATE '2026-03-01'),
data_col => 'purchases',
timestamp_col => 'date',
anomaly_prob_threshold => 0.90
);
Lecture type :
| Date | Purchases | Anomalie | Lecture possible |
|---|---|---|---|
| 2026-03-05 | 412 | false | habituel |
| 2026-03-06 | 398 | false | normal |
| 2026-03-07 | 137 | true | incident possible sur le tunnel ou la collecte |
Exemple GA4 3 : revenu par canal
CREATE OR REPLACE TABLE `project.dataset.ga4_revenue_by_channel_daily` AS
SELECT
PARSE_DATE('%Y%m%d', event_date) AS date,
CONCAT(collected_traffic_source.manual_source, ' / ', collected_traffic_source.manual_medium) AS source_medium,
SUM(ecommerce.purchase_revenue) AS revenue
FROM `project.analytics_123456789.events_*`
WHERE event_name = 'purchase'
AND _TABLE_SUFFIX BETWEEN '20260101' AND '20260331'
GROUP BY 1, 2
ORDER BY 1, 2;
SELECT *
FROM AI.DETECT_ANOMALIES(
(SELECT date, source_medium, revenue
FROM `project.dataset.ga4_revenue_by_channel_daily`
WHERE date < DATE '2026-03-01'),
(SELECT date, source_medium, revenue
FROM `project.dataset.ga4_revenue_by_channel_daily`
WHERE date >= DATE '2026-03-01'),
data_col => 'revenue',
timestamp_col => 'date',
id_cols => ['source_medium'],
model => 'TimesFM 2.5',
anomaly_prob_threshold => 0.90
);
Lecture type :
| Date | Canal | Revenue | Anomalie |
|---|---|---|---|
| 2026-03-08 | google / organic | 8 420 | false |
| 2026-03-08 | google / cpc | 13 980 | false |
| 2026-03-08 | email / newsletter | 1 120 | true |
C’est typiquement le genre de contrôle que j’aime brancher en QA ou en alerte.
Comment je l’exploite réellement
Le vrai usage ne s’arrête pas à la requête. Je m’en sers pour bâtir des dispositifs simples.
| Dispositif | Ce que je fais |
|---|---|
| Log QA | j’enregistre toutes les anomalies dans une table |
| Alerte | j’envoie un Slack ou un email sur les cas critiques |
| Contrôle avant dashboard | j’affiche un warning si un KPI est suspect |
| Revue hebdo | je compare anomalies détectées et incidents réels |
| Supervision de tracking | je surveille les événements clés |
| Supervision business | je surveille ventes, leads, revenus, coûts |
Dit autrement, AI.DETECT_ANOMALIES n’est pas seulement une fonction d’analyse. C’est une brique de supervision data.
Je trouve cette fonction vraiment utile.
Elle ne remplace pas le métier, elle ne remplace pas une lecture humaine, et elle ne remplace pas la qualité des données. Mais elle ajoute quelque chose de très concret : un moyen simple, natif et SQL-first de détecter des écarts dans une série temporelle avant de bâtir une analyse ou un reporting dessus.
C’est valable sur des ventes, du CRM, des coûts, des tickets, des capteurs, des pipelines, et particulièrement sur des séries reconstruites à partir d’un export GA4 dans BigQuery. Sur ce terrain-là, la fonction n’est pas juste intéressante. Elle est directement exploitable.
⭐ Analytics engineer, Data Analyst et Automatisation IA indépendant ⭐
- Ref clients : Logis Hôtel, Yelloh Village, BazarChic, Fédération Football Français, Texdecor…
Mon terrain de jeu :
- Data Analyst & Analytics engineering : tracking avancé (GA4, Matomo, Piano, GTM server, Tealium, Commander Act, e-commerce, CAPI, RGPD), entrepôt de données (BigQuery, Snowflake, PostgreSQL, ClickHouse), modèles (Airflow, dbt, Dataform), dashboards décisionnels (Looker, Power BI, Metabase, SQL, Python).
- Automatisation IA des taches Data, Marketing, RH, compta etc : conception de workflows intelligents robustes (n8n, App Script, scraping) connectés aux API de vos outils et LLM (OpenAI, Mistral, Claude…).
- Engineering IA pour créer des applications et agent IA sur mesure : intégration de LLM (OpenAI, Mistral…), RAG, assistants métier, génération de documents complexes, APIs, backends Node.js/Python.







