Accueil | Portfolio | Référencement SEO et SEA | Lexique SEO | SEA | Script Quality Score Google Ads

par | 06 / 2026

Piloter le quality score Google Ads avec un script

Pourquoi la moyenne simple de votre Quality Score est un indicateur menteur, et comment automatiser un suivi macro ultra-fiable basé sur la donnée réelle de vos impressions.

La boîte noire de Google Ads, au-delà de la note globale

Suivre l’évolution du Quality Score (QS) sur Google Ads est un réflexe de base. Savoir exactement quel levier actionner pour optimiser ses campagnes et faire baisser son coût par clic (CPC), c’est une tout autre expertise.

Pour rappel, l’algorithme de Google évalue vos mots-clés sur une échelle de 1 à 10 via trois piliers distincts :

  • Le CTR attendu (Taux de clic prédit)
  • La pertinence de l’annonce (Alignement sémantique)
  • L’expérience sur la page de destination (Signaux UX & Tech)

Lorsque votre note globale s’effondre, diagnostiquer la cause exacte relève souvent du parcours du combattant si vous vous fiez uniquement à l’interface native. Est-ce la faute d’une Landing Page dont les performances faiblissent, ou d’un Ad Copy qui fatigue ?

Le piège absolu, la moyenne simple et les mots-clés « zombies »

La majorité des scripts et des rapports tiers commettent une erreur méthodologique majeure : ils calculent une moyenne simple du Quality Score de vos mots-clés.

Imaginez un compte doté de deux mots-clés :

  • Le mot-clé A possède un QS de 3/10 mais génère 100 000 impressions.
  • Le mot-clé B possède un QS de 10/10 mais ne génère que 10 impressions (un mot-clé « zombie »).

Une moyenne simple vous donnera un score flatteur de 6,5/10. En réalité, votre compte souffre de performances médiocres sur la quasi-totalité de son trafic. C’est pourquoi seule une approche statistique pondérée par les impressions réelles permet d’obtenir une vision macro rigoureuse de la santé technique de votre compte.

Le script 

Le script Google Ads ci-dessous automatise cette pondération. Il interroge l’API Google Ads via le langage GAQL, extrait les performances des mots-clés actifs, convertit les métriques textuelles de Google (Below Average, Average, Above Average) en valeurs numériques de 1 à 3, et consigne le tout quotidiennement dans une feuille Google Sheets.


 /**
 * @name Quality Score Tracker & Historical Logger
 */
const CONFIG = {
  // Collez l'URL d'une Google Sheet VIERGE créée sur votre Drive
  'spreadsheet_url': 'VOTRE URL ICI GOOGLE SHEETS',
  
  // Nom de la feuille qui stockera l'historique
  'sheet_name': 'QS_History',
  
  // Plage de dates pour l'analyse (Options supportées : 'YESTERDAY' ou 'LAST_30_DAYS')
  'date_range': 'LAST_30_DAYS'
};

function main() {
  const spreadsheet = SpreadsheetApp.openByUrl(CONFIG.spreadsheet_url);
  let sheet = spreadsheet.getSheetByName(CONFIG.sheet_name);
  
  // Création de la feuille et des en-têtes si elle n'existe pas
  if (!sheet) {
    sheet = spreadsheet.insertSheet(CONFIG.sheet_name);
    sheet.appendRow([
      'Date', 
      'Total Impressions', 
      'Weighted Quality Score', 
      'Avg Expected CTR (1-3)', 
      'Avg Ad Relevance (1-3)', 
      'Avg Landing Page Exp (1-3)'
    ]);
  }

  // Validation de la configuration des dates
  if (CONFIG.date_range !== 'YESTERDAY' && CONFIG.date_range !== 'LAST_30_DAYS') {
    throw new Error("Plage de dates non supportée par ce script. Utilisez 'YESTERDAY' ou 'LAST_30_DAYS'.");
  }

  // Requête GAQL moderne utilisant la clause native DURING et les Template Literals
  const query = `
    SELECT 
      keyword_view.criterion_id, 
      metrics.impressions, 
      ad_group_criterion.quality_info.quality_score, 
      ad_group_criterion.quality_info.search_predicted_ctr, 
      ad_group_criterion.quality_info.creative_quality_score, 
      ad_group_criterion.quality_info.post_click_quality_score 
    FROM keyword_view 
    WHERE ad_group_criterion.status = 'ENABLED' 
      AND ad_group.status = 'ENABLED' 
      AND campaign.status = 'ENABLED' 
      AND metrics.impressions > 0 
      AND segments.date DURING ${CONFIG.date_range}
  `;

  const searchResults = AdsApp.search(query);
  
  let totalImpressions = 0;
  let totalWeightedQS = 0;
  
  let weightedCtrSum = 0, ctrImpressions = 0;
  let weightedAdRelevanceSum = 0, relevanceImpressions = 0;
  let weightedLandingPageSum = 0, lpImpressions = 0;

  const scoreMap = {
    'BELOW_AVERAGE': 1,
    'AVERAGE': 2,
    'ABOVE_AVERAGE': 3
  };

  while (searchResults.hasNext()) {
    const row = searchResults.next();
    const impressions = parseInt(row.metrics.impressions, 10);
    const qs = row.adGroupCriterion.qualityInfo.qualityScore;
    
    if (qs) {
      totalImpressions += impressions;
      totalWeightedQS += (qs * impressions);
      
      const ctrStatus = row.adGroupCriterion.qualityInfo.searchPredictedCtr;
      const relevanceStatus = row.adGroupCriterion.qualityInfo.creativeQualityScore;
      const lpStatus = row.adGroupCriterion.qualityInfo.postClickQualityScore;

      if (scoreMap[ctrStatus]) {
        weightedCtrSum += (scoreMap[ctrStatus] * impressions);
        ctrImpressions += impressions;
      }
      if (scoreMap[relevanceStatus]) {
        weightedAdRelevanceSum += (scoreMap[relevanceStatus] * impressions);
        relevanceImpressions += impressions;
      }
      if (scoreMap[lpStatus]) {
        weightedLandingPageSum += (scoreMap[lpStatus] * impressions);
        lpImpressions += impressions;
      }
    }
  }

  if (totalImpressions > 0) {
    const finalWeightedQS = parseFloat((totalWeightedQS / totalImpressions).toFixed(2));
    const finalAvgCtr = ctrImpressions > 0 ? parseFloat((weightedCtrSum / ctrImpressions).toFixed(2)) : 0;
    const finalAvgRelevance = relevanceImpressions > 0 ? parseFloat((weightedAdRelevanceSum / relevanceImpressions).toFixed(2)) : 0;
    const finalAvgLp = lpImpressions > 0 ? parseFloat((weightedLandingPageSum / lpImpressions).toFixed(2)) : 0;
    
    // Récupération de la date du jour selon le fuseau horaire du compte Google Ads
    const timeZone = AdsApp.currentAccount().getTimeZone();
    const logDate = Utilities.formatDate(new Date(), timeZone, 'yyyy-MM-dd');
    
    sheet.appendRow([
      logDate, 
      totalImpressions, 
      finalWeightedQS,
      finalAvgCtr,
      finalAvgRelevance,
      finalAvgLp
    ]);
    
    console.log(`Données enregistrées pour le ${logDate} | QS : ${finalWeightedQS} | CTR : ${finalAvgCtr} | Rel : ${finalAvgRelevance} | LP : ${finalAvgLp}`);
  } else {
    console.log("Aucune impression enregistrée sur les mots-clés actifs pour calculer le QS.");
  }
}

Interprétation des résultats

Une fois le script configuré en exécution quotidienne (Fréquence : Tous les jours), vous obtiendrez un historique de données propres et parfaitement quantifiées sous forme numérique (de 1.00 à 3.00 pour les sous-composants). Voici la grille de lecture chirurgicale à adopter :

La note ‘Avg Landing Page Exp’ stagne proche de 1.00

Le diagnostic :

Il s’agit d’un problème d’UX, de pertinence technique ou de SEO on-page. Votre page de destination repousse l’utilisateur ou ne répond pas immédiatement à l’intention de recherche.

L’action :

Optimisez la vitesse de chargement (Core Web Vitals), retravaillez l’arborescence de l’information et assurez-vous que la promesse sémantique de l’annonce est immédiatement visible au-dessus de la ligne de flottaison.

La note ‘Avg Ad Relevance’ s’effondre

Le diagnostic :

Le problème réside dans votre structure de compte ou votre copywriting. Vos annonces textuelles manquent de spécificité par rapport aux requêtes réelles des utilisateurs.

L’action :

Scindez vos groupes d’annonces trop larges en structures plus granulaires (thématiques ultra-ciblées). Réinjectez les mots-clés exacts dans les titres 1 et 2 de vos annonces responsives (RSA).

Guide de déploiement en 3 étapes

  1. Préparer la feuille : créez une nouvelle Google Sheet vierge sur votre Drive et copiez son URL complète.
  2. Intégrer le script : rendez-vous sur votre compte Google Ads, ouvrez l’onglet Outils et action groupée > Scripts. Créez un nouveau script et collez l’intégralité du code ci-dessus à la place du contenu existant.
  3. Configurer & Autoriser : remplacez la valeur de spreadsheet_url par l’URL de votre feuille, cliquez sur « Autoriser », effectuez un test à blanc via le bouton « Aperçu », puis configurez une exécution de routine quotidienne.
script Google Ads pour automatiser la recherche des pages à optimiser

On maximise votre visibilité ?

En tant que consultant freelance en référencement et acquisition, je vous propose des solutions sur-mesure pour développer votre marketing digital.

Basé à Béthune, je travaille avec des entreprises de toute la France pour les aider à atteindre leurs objectifs.

Prêt à discuter de votre projet ?

Contactez-moi dès maintenant !

Formulaire de contact | LinkdIn 

Matthieu Brunel

Matthieu Brunel

Consultant SEO, SEA, UX, CRO & acquisition de trafic

Passionné par le digital et spécialisé en référencement, j’ai développé une solide expertise dans l’analyse et l’optimisation du parcours client. Mon expérience s’étend de la consultance en référencement à la gestion de trafic, en passant par la création et l’optimisation de sites e-commerce.