ServicesÀ proposNotesContact Me contacter →
EN FR
Note

Maintenance du pipeline Meta Ads

Pratiques opérationnelles pour maintenir un pipeline Meta Ads en fonctionnement — monitoring de l'expiration des tokens, réconciliation des dépenses, gestion du cycle de vie des versions API, et patterns de circuit breaker.

Planté
bigquerydata engineeringdata quality

L’API de Meta change suffisamment souvent pour que la maintenance du pipeline soit un coût récurrent. Les trois pratiques qui maintiennent les pipelines fiables : le suivi de l’expiration des tokens, la réconciliation des dépenses, et un circuit breaker qui arrête l’extraction après des échecs consécutifs plutôt qu’épuiser les limites de débit sur un endpoint défaillant.

Monitoring de l’expiration des tokens

La défaillance silencieuse la plus courante dans les pipelines Meta est l’expiration des tokens. Quand un token utilisateur longue durée ou un token d’accès personnel expire, l’API commence à retourner des erreurs 401. À moins de surveiller spécifiquement les erreurs d’authentification, le pipeline s’arrête et rien ne vous alerte. Au moment où quelqu’un le remarque (généralement quand un tableau de bord devient obsolète), vous avez perdu des jours de données.

Utilisez des tokens d’accès System User. Contrairement aux tokens utilisateur qui expirent après ~60 jours, les tokens System User n’expirent pas. Configurez-les une fois dans Business Settings sous System Users, et ils restent valides jusqu’à ce que vous les révoquiez. Cela élimine entièrement la catégorie des défaillances silencieuses dues à l’expiration pour la plupart des pipelines.

Si vous êtes bloqué avec des tokens utilisateur (courant quand vous utilisez BigQuery Data Transfer Service pour Meta, qui nécessite un token utilisateur), construisez un monitoring de l’expiration :

import datetime
from facebook_business.api import FacebookAdsApi
from facebook_business.adobjects.user import User
def check_token_expiry(access_token: str) -> datetime.datetime:
api = FacebookAdsApi.init(access_token=access_token)
me = User(fbid='me', api=api)
fields = ['token_for_business']
result = me.api_get(fields=fields)
# L'endpoint de débogage de token donne l'expiration
debug = api.call(
'GET',
'/debug_token',
{'input_token': access_token, 'access_token': access_token}
).json()
expires_at = debug['data'].get('expires_at', 0)
return datetime.datetime.fromtimestamp(expires_at) if expires_at else None

Alertez une semaine avant la marque des 60 jours. Une semaine vous donne suffisamment de temps pour renouveler sans urgence. Un jour de préavis ne suffit pas.

Réconciliation des dépenses

La deuxième pratique opérationnelle qui se justifie rapidement : la comparaison hebdomadaire des totaux de dépenses de l’entrepôt contre Ads Manager.

Extrayez le total de votre entrepôt pour les 7 derniers jours :

SELECT
SUM(spend) AS warehouse_spend_7d,
CURRENT_DATE() AS report_date
FROM `your_project.meta_ads.ad_insights_daily`
WHERE date_start >= DATE_SUB(CURRENT_DATE(), INTERVAL 7 DAY)

Comparez cela contre l’interface Ads Manager (ou l’API) pour la même période. Une variance inférieure à 5 % est normale — les différences de fuseau horaire, l’arrondi des fenêtres d’attribution et l’incertitude de la modélisation contribuent toutes. Une variance supérieure à 10 % de façon constante signifie que quelque chose ne va pas avec votre pipeline.

Causes courantes de grandes variances :

  • Fenêtre de lookback trop courte : vous ne re-tirez pas les données que Meta a mises à jour rétroactivement
  • Incompatibilité de fenêtre d’attribution : votre appel API et Ads Manager utilisent des fenêtres différentes
  • Comptes publicitaires manquants : votre pipeline n’a pas accès à tous les comptes contribuant aux totaux d’Ads Manager
  • Bug de normalisation des devises : les dépenses dans des devises non primaires ne sont pas converties

Automatisez cette vérification. Exécutez-la comme un test dbt, une requête planifiée, ou un simple script avec alerte. La valeur réside dans la fréquence et la cohérence — détecter une variance tôt signifie résoudre un petit problème avant qu’il ne devienne un incident de qualité des données majeur.

-- Test singulier dbt : assert que la réconciliation des dépenses est dans les 10 %
-- tests/assert_meta_spend_reconciles.sql
WITH warehouse_spend AS (
SELECT SUM(spend) AS total_spend
FROM {{ ref('mrt__marketing__meta__campaign_performance') }}
WHERE date_day >= DATE_SUB(CURRENT_DATE(), INTERVAL 7 DAY)
),
-- Comparer contre une référence maintenue manuellement ou une vérification API
-- Ce pattern signale pour révision manuelle quand l'entrepôt semble incorrect
-- Ajustez le seuil selon la variance acceptable pour votre configuration
meta_reference AS (
SELECT SUM(spend) AS total_spend
FROM {{ source('meta_ads', 'spend_reference') }}
WHERE date_day >= DATE_SUB(CURRENT_DATE(), INTERVAL 7 DAY)
)
SELECT
warehouse_spend.total_spend AS warehouse_total,
meta_reference.total_spend AS reference_total,
ABS(warehouse_spend.total_spend - meta_reference.total_spend) /
NULLIF(meta_reference.total_spend, 0) AS variance_pct
FROM warehouse_spend
CROSS JOIN meta_reference
WHERE ABS(warehouse_spend.total_spend - meta_reference.total_spend) /
NULLIF(meta_reference.total_spend, 0) > 0.10

Gestion du cycle de vie des versions API

Meta publie environ deux versions majeures d’API par an, chacune supportée pendant environ deux ans. Cela signifie que vous devez mettre à niveau la version API de votre pipeline au moins une fois par an pour rester sur une version supportée.

Le processus ne consiste pas simplement à changer un numéro de version dans une URL. Les nouvelles versions d’API renomment parfois des champs, changent des types de données ou restructurent les réponses. L’endroit canonique pour trouver ces changements est le changelog API de Meta.

Construisez une discipline de suivi des versions :

  1. Notez la version actuelle quand vous déployez votre pipeline
  2. Abonnez-vous aux annonces du changelog développeur de Meta
  3. Planifiez les mises à niveau au moins six mois avant la date de fin de vie de la version
  4. Testez sur la nouvelle version dans un environnement de staging avant de basculer

Si vous utilisez un outil d’extraction managé (Fivetran, Airbyte), ils gèrent les mises à niveau de version API pour vous — c’est une grande partie de ce pour quoi vous payez. Si vous gérez une extraction personnalisée, la gestion des versions est votre responsabilité.

La défaillance à éviter : découvrir qu’une version est dépréciée parce que vos appels API commencent à retourner des erreurs en production. Vous effectuez alors une migration d’urgence sous pression. Le même travail fait de façon proactive, six mois plus tôt, est une tâche de maintenance planifiée.

Pattern circuit breaker

Un pipeline qui rencontre des erreurs doit s’arrêter, pas retenter indéfiniment. Chaque appel API échoué consomme du budget de limite de débit et retarde le diagnostic réel du problème.

Le pattern circuit breaker : suivez les échecs consécutifs et pausez l’extraction après avoir atteint un seuil.

import time
from enum import Enum
class CircuitState(Enum):
CLOSED = "closed" # Fonctionnement normal
OPEN = "open" # Arrêté après des échecs
HALF_OPEN = "half_open" # Test de récupération
class MetaApiCircuitBreaker:
def __init__(self, failure_threshold=5, recovery_timeout=300):
self.failure_threshold = failure_threshold
self.recovery_timeout = recovery_timeout
self.failure_count = 0
self.last_failure_time = None
self.state = CircuitState.CLOSED
def call(self, fn, *args, **kwargs):
if self.state == CircuitState.OPEN:
if time.time() - self.last_failure_time > self.recovery_timeout:
self.state = CircuitState.HALF_OPEN
else:
raise Exception("Circuit breaker ouvert — extraction en pause")
try:
result = fn(*args, **kwargs)
self._on_success()
return result
except Exception as e:
self._on_failure()
raise
def _on_success(self):
self.failure_count = 0
self.state = CircuitState.CLOSED
def _on_failure(self):
self.failure_count += 1
self.last_failure_time = time.time()
if self.failure_count >= self.failure_threshold:
self.state = CircuitState.OPEN

Après 5 échecs consécutifs, le circuit s’ouvre et l’extraction marque une pause de 5 minutes avant de réessayer. Cela empêche un endpoint défaillant d’épuiser votre budget de limite de débit tout en donnant au service le temps de récupérer.

Le circuit breaker a le plus de valeur en combinaison avec des alertes appropriées. Quand le circuit s’ouvre, déclenchez une alerte pour qu’un humain sache que quelque chose nécessite son attention. Ne pausez pas silencieusement — tout l’intérêt est de faire remonter les problèmes, pas de les dissimuler.

Stockage des données brutes

Stockez les réponses API brutes avant transformation. Cela semble coûteux mais ne l’est pas — le JSON brut compressé dans le stockage BigQuery est bon marché. La valeur est opérationnelle : quand quelque chose se passe mal dans votre logique de transformation, ou quand Meta change un champ que vous n’aviez pas anticipé, vous pouvez déboguer sans re-tirer depuis l’API.

-- Structure de table de stockage brut
CREATE TABLE raw_meta_ads.api_responses (
ingestion_timestamp TIMESTAMP,
ad_account_id STRING,
report_date DATE,
api_version STRING,
response_json JSON -- ou STRING si vous préférez
)
PARTITION BY report_date
OPTIONS (
require_partition_filter = false
);

Partitionnez par date de rapport afin que les requêtes sur des plages de dates spécifiques ne scannent pas la table entière. Conservez les réponses brutes pendant 90 jours — suffisamment pour investiguer tout problème qu’une fenêtre de lookback normale pourrait manquer.

Quand vous investiguez une divergence, la table brute vous permet d’inspecter exactement ce que l’API a retourné avant que votre transformation le touche. Cela élimine une catégorie entière de questions de débogage (« le bug est-il dans l’extraction ou la transformation ? »).

Ce qu’il faut surveiller

Un dispositif de monitoring minimal pour un pipeline Meta :

VérificationFréquenceSeuil d’alerte
Validité du token (si tokens utilisateur)QuotidienneExpiration dans moins de 7 jours
Réconciliation des dépenses vs Ads ManagerHebdomadaire>10 % de variance
Nombre de lignes pour hierQuotidienne>20 % de baisse par rapport à la moyenne des 7 derniers jours
Taux d’erreur APIPar exécution>5 échecs consécutifs
Fin de vie de la version APIMensuelle<6 mois jusqu’à la fin de vie

La vérification du nombre de lignes est un proxy simple pour « les données circulent-elles encore ». Une baisse de 20 % par rapport à la moyenne glissante est souvent le premier signal d’une défaillance silencieuse — le pipeline tourne mais retourne moins de données qu’attendu, ce qui signifie que l’API se comporte mal, qu’un compte a perdu l’accès, ou qu’une limite de débit est atteinte silencieusement.

Ces cinq vérifications couvrent la grande majorité des défaillances de production réelles. Un monitoring plus sophistiqué est possible — détection de dérive de schéma, vérifications de couverture sur les comptes, validation de complétude par campagne — mais commencez ici et n’ajoutez de la complexité que lorsque les bases sont stables.