Tutoriels

Automatiser l'envoi de conversions via l'API Google Ads

8 min de lecture LeadZen
Automatiser l'envoi de conversions via l'API Google Ads

L'import manuel de conversions ne passe pas à l'échelle. Pour automatiser, vous devez utiliser l'API Google Ads. Voici un guide technique pour développer votre propre intégration.

Prérequis

Avant de commencer, vous aurez besoin de :

  • Un compte Google Ads avec des conversions configurées
  • Un projet Google Cloud Platform avec l'API Google Ads activée
  • Un token développeur Google Ads (niveau Basic ou Standard)
  • Des credentials OAuth 2.0 pour l'authentification
  • Un refresh token pour l'authentification persistante

Étape 1 : Configurer l'accès API

Créer un projet GCP

  1. Allez sur console.cloud.google.com
  2. Créez un nouveau projet ou sélectionnez-en un existant
  3. Activez l'API Google Ads dans "APIs & Services"

Créer des credentials OAuth

  1. Dans GCP, allez dans APIs & Services > Credentials
  2. Créez un OAuth 2.0 Client ID de type "Web application"
  3. Notez le Client ID et Client Secret

Obtenir un token développeur

  1. Dans Google Ads, allez dans Outils > Configuration > Centre API
  2. Demandez un token développeur (niveau Basic suffit pour commencer)
  3. Notez le token une fois approuvé

Générer un refresh token

Utilisez l'outil OAuth Playground de Google ou le script fourni par la bibliothèque cliente :

// Avec la bibliothèque Python google-ads
pip install google-ads

// Exécuter le script d'authentification
python -m google_ads.client oauth2

Étape 2 : Structure de l'appel API

L'endpoint pour uploader des conversions offline est UploadClickConversions du service ConversionUploadService.

Format de la requête

{
  "customerId": "1234567890",
  "conversions": [
    {
      "gclid": "EAIaIQobChMI...",
      "conversionAction": "customers/1234567890/conversionActions/987654321",
      "conversionDateTime": "2025-11-20 14:30:00+01:00",
      "conversionValue": 1500.00,
      "currencyCode": "EUR"
    }
  ],
  "partialFailure": true
}

Champs obligatoires

  • customerId : ID du compte Google Ads (sans tirets)
  • gclid : L'identifiant du clic Google Ads (comment le capturer)
  • conversionAction : Resource name de l'action de conversion
  • conversionDateTime : Date/heure de la conversion (avec timezone)

Champs optionnels mais recommandés

  • conversionValue : Valeur de la conversion
  • currencyCode : Devise (EUR, USD, etc.)
  • orderId : ID unique pour éviter les doublons

Étape 3 : Implémentation en Python

from google.ads.googleads.client import GoogleAdsClient
from google.ads.googleads.errors import GoogleAdsException
from datetime import datetime
import pytz

# Configuration
CUSTOMER_ID = "1234567890"
CONVERSION_ACTION_ID = "987654321"

# Initialiser le client
client = GoogleAdsClient.load_from_storage("google-ads.yaml")

def upload_offline_conversion(gclid, conversion_time, value, currency="EUR"):
    """
    Upload une conversion offline vers Google Ads.

    Args:
        gclid: L'identifiant du clic Google Ads
        conversion_time: datetime de la conversion
        value: Valeur de la conversion
        currency: Devise (default EUR)
    """
    conversion_upload_service = client.get_service("ConversionUploadService")
    conversion_action_service = client.get_service("ConversionActionService")

    # Construire le resource name de l'action de conversion
    conversion_action_resource = conversion_action_service.conversion_action_path(
        CUSTOMER_ID, CONVERSION_ACTION_ID
    )

    # Créer l'objet conversion
    click_conversion = client.get_type("ClickConversion")
    click_conversion.gclid = gclid
    click_conversion.conversion_action = conversion_action_resource
    click_conversion.conversion_date_time = conversion_time.strftime("%Y-%m-%d %H:%M:%S%z")
    click_conversion.conversion_value = value
    click_conversion.currency_code = currency

    # Upload
    request = client.get_type("UploadClickConversionsRequest")
    request.customer_id = CUSTOMER_ID
    request.conversions.append(click_conversion)
    request.partial_failure = True

    try:
        response = conversion_upload_service.upload_click_conversions(request=request)

        # Vérifier les erreurs partielles
        if response.partial_failure_error:
            print(f"Erreur partielle: {response.partial_failure_error.message}")

        # Log les résultats
        for result in response.results:
            if result.gclid:
                print(f"Conversion uploadée pour GCLID: {result.gclid}")
            else:
                print("Conversion uploadée (sans GCLID retourné)")

        return True

    except GoogleAdsException as ex:
        print(f"Erreur Google Ads: {ex.failure.errors[0].message}")
        return False

# Exemple d'utilisation
if __name__ == "__main__":
    paris_tz = pytz.timezone("Europe/Paris")
    conversion_time = paris_tz.localize(datetime(2025, 11, 20, 14, 30, 0))

    upload_offline_conversion(
        gclid="EAIaIQobChMIwPLn5YXx9QIVhOvtCh2xGwKXEAAYASAAEgLwN_D_BwE",
        conversion_time=conversion_time,
        value=1500.00
    )

Fichier de configuration (google-ads.yaml)

developer_token: VOTRE_DEVELOPER_TOKEN
client_id: VOTRE_CLIENT_ID.apps.googleusercontent.com
client_secret: VOTRE_CLIENT_SECRET
refresh_token: VOTRE_REFRESH_TOKEN
login_customer_id: VOTRE_MCC_ID  # Si vous utilisez un MCC

Étape 4 : Implémentation en PHP

<?php

require 'vendor/autoload.php';

use Google\Ads\GoogleAds\Lib\V15\GoogleAdsClientBuilder;
use Google\Ads\GoogleAds\V15\Services\ClickConversion;
use Google\Ads\GoogleAds\V15\Services\UploadClickConversionsRequest;

$customerId = '1234567890';
$conversionActionId = '987654321';

// Initialiser le client
$googleAdsClient = (new GoogleAdsClientBuilder())
    ->fromFile('/path/to/google_ads_php.ini')
    ->build();

function uploadOfflineConversion(
    $client,
    $customerId,
    $conversionActionId,
    $gclid,
    $conversionTime,
    $value,
    $currency = 'EUR'
) {
    $conversionUploadService = $client->getConversionUploadServiceClient();

    // Resource name de l'action de conversion
    $conversionActionResource = sprintf(
        'customers/%s/conversionActions/%s',
        $customerId,
        $conversionActionId
    );

    // Créer la conversion
    $clickConversion = new ClickConversion();
    $clickConversion->setGclid($gclid);
    $clickConversion->setConversionAction($conversionActionResource);
    $clickConversion->setConversionDateTime($conversionTime->format('Y-m-d H:i:sP'));
    $clickConversion->setConversionValue($value);
    $clickConversion->setCurrencyCode($currency);

    // Requête d'upload
    $request = new UploadClickConversionsRequest();
    $request->setCustomerId($customerId);
    $request->setConversions([$clickConversion]);
    $request->setPartialFailure(true);

    try {
        $response = $conversionUploadService->uploadClickConversions($request);

        // Vérifier les erreurs partielles
        if ($response->hasPartialFailureError()) {
            echo "Erreur partielle: " . $response->getPartialFailureError()->getMessage();
        }

        foreach ($response->getResults() as $result) {
            echo "Conversion uploadée pour GCLID: " . $result->getGclid() . "\n";
        }

        return true;

    } catch (Exception $e) {
        echo "Erreur: " . $e->getMessage();
        return false;
    }
}

// Exemple d'utilisation
$conversionTime = new DateTime('2025-11-20 14:30:00', new DateTimeZone('Europe/Paris'));

uploadOfflineConversion(
    $googleAdsClient,
    $customerId,
    $conversionActionId,
    'EAIaIQobChMIwPLn5YXx9QIVhOvtCh2xGwKXEAAYASAAEgLwN_D_BwE',
    $conversionTime,
    1500.00
);

Étape 5 : Intégration avec votre CRM

L'idéal est de déclencher l'upload automatiquement quand un lead change de statut dans votre CRM.

Architecture recommandée

  1. Webhook CRM : Le CRM envoie un webhook quand un deal passe en "Gagné"
  2. Service d'upload : Reçoit le webhook, récupère le GCLID, envoie à Google Ads
  3. Queue : Utiliser une queue (Redis, RabbitMQ) pour gérer les erreurs et retries

Exemple avec webhook

# Endpoint Flask recevant le webhook
from flask import Flask, request
import json

app = Flask(__name__)

@app.route('/webhook/deal-won', methods=['POST'])
def handle_deal_won():
    data = request.json

    # Extraire les données nécessaires
    gclid = data.get('gclid')
    deal_value = data.get('deal_value')
    closed_at = data.get('closed_at')

    if not gclid:
        return {'status': 'skipped', 'reason': 'no_gclid'}, 200

    # Convertir la date
    conversion_time = datetime.fromisoformat(closed_at)

    # Upload vers Google Ads
    success = upload_offline_conversion(
        gclid=gclid,
        conversion_time=conversion_time,
        value=deal_value
    )

    if success:
        return {'status': 'success'}, 200
    else:
        return {'status': 'error'}, 500

Gestion des erreurs

Erreurs courantes

Erreur Cause Solution
INVALID_GCLID GCLID mal formaté ou expiré Vérifier le format, respecter les 90 jours
TOO_RECENT_CONVERSION Conversion uploadée trop tôt Attendre quelques heures après le clic
DUPLICATE_CONVERSION Même conversion déjà importée Utiliser orderId pour dédupliquer
EXPIRED_GCLID GCLID de plus de 90 jours Importer plus rapidement

Stratégie de retry

import time
from functools import wraps

def retry_on_failure(max_retries=3, delay=60):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            for attempt in range(max_retries):
                try:
                    return func(*args, **kwargs)
                except Exception as e:
                    if attempt < max_retries - 1:
                        time.sleep(delay * (attempt + 1))
                    else:
                        raise e
        return wrapper
    return decorator

@retry_on_failure(max_retries=3, delay=60)
def upload_with_retry(gclid, conversion_time, value):
    return upload_offline_conversion(gclid, conversion_time, value)

Monitoring et logging

Pour un système de production, implémentez :

  • Logging détaillé : Chaque tentative d'upload avec résultat
  • Métriques : Taux de succès, temps de réponse, erreurs par type
  • Alertes : Notification si taux d'erreur anormal
  • Dashboard : Vue en temps réel des conversions uploadées

LeadZen : l'API en mode SaaS

Pourquoi développer quand vous pouvez utiliser LeadZen ? Notre plateforme gère l'authentification, les retries, le monitoring et l'envoi vers Google Ads. Vous vous concentrez sur votre business.

Essayer gratuitement pendant 30 jours

Bonnes pratiques

1. Utilisez orderId pour la déduplication

Ajoutez un identifiant unique à chaque conversion pour éviter les doublons en cas de retry :

click_conversion.order_id = f"deal_{deal_id}"

2. Respectez les quotas

L'API Google Ads a des limites de requêtes. Pour des volumes importants :

  • Batchez les conversions (jusqu'à 2000 par requête)
  • Espacez les requêtes
  • Demandez une augmentation de quota si nécessaire

3. Gérez les timezones

La date de conversion doit inclure le timezone. Utilisez toujours un format avec offset :

"2025-11-20 14:30:00+01:00"  // Correct
"2025-11-20 14:30:00"         // Incorrect (timezone manquant)

4. Validez avant d'envoyer

Avant l'upload, vérifiez :

  • GCLID non vide et format valide (~100 caractères)
  • Date de conversion dans les 90 jours
  • Valeur numérique positive

Conclusion

L'API Google Ads permet d'automatiser complètement l'import de vos conversions offline. C'est un investissement technique initial, mais le gain en fiabilité et en temps est significatif.

Les 3 points clés :

  1. Configurez correctement l'authentification : C'est la partie la plus complexe
  2. Gérez les erreurs et retries : L'API peut échouer temporairement
  3. Utilisez orderId pour éviter les doublons

Pas envie de développer ? Essayez LeadZen pour automatiser l'envoi de vos conversions sans écrire une ligne de code.

Articles similaires

Prêt à optimiser vos conversions ?

Envoyez vos ventes réelles à Google Ads en quelques clics.

Essayer gratuitement

Sans engagement • Annulation à tout moment