Un script de AdWords para hacer una coincidencia exacta, bueno … Exacto

Muchos de ustedes habrán escuchado sobre la decisión de Google de cancelar la coincidencia exacta (al mismo tiempo que nos dice que es por nuestro propio bien). Es un movimiento claro para obtener más dólares en publicidad, y los expertos en SEM han recibido la noticia con furia. La mayoría de los niños de dos años saben que existe una diferencia semántica entre singular y plural […]

scripts-de-adwords-concordancia-exacta

Muchos de ustedes habrán oído hablar La decisión de Google de cancelar la concordancia exacta (al mismo tiempo que nos dice que es por nuestro propio bien). Es un movimiento claro para obtener más dólares publicitarios, y la noticia ha sido recibido con furia por los expertos en SEM.

Más los niños de dos años saben que existe una diferencia semántica entre las formas singular y plural, y cualquiera con el más mínimo dominio del idioma inglés sabrá que hay una diferencia entre [photographer] y [photography]. Si bien un fotógrafo profesional puede querer gastar dinero en [photographer], probablemente no querrían aparecer para [photography] ya que es más probable que se trate de una búsqueda de fotos que los usuarios pueden descargar.

En lugar de firmar el petición en change.org pidiéndole a Google que revierta este cambio, acabamos de escribir un script para hacer automáticamente una coincidencia exacta, bueno… exacta.

La secuencia de comandos de AdWords ejecuta informes de términos de búsqueda y agrega términos de «variante cercana» como negativos exactos si no son la palabra clave original exacta.

Puede ejecutar esta secuencia de comandos en el nivel de MCC para todas sus cuentas o elegir cuentas, campañas o grupos de anuncios individuales. Simplemente copie el código a continuación, inicie sesión en AdWords, vaya a Operaciones masivas (columna de la izquierda)> Secuencias de comandos> Nuevo. Pegue el código en el cuadro y haga clic en Vista previa para ver los cambios que hará el script si lo ejecuta. Configure un programa para ejecutar este script diariamente y su concordancia de palabras clave se comportará de manera similar a como lo hacía antes. Si nunca ha ejecutado un script antes, puede leer nuestro Introducción a las secuencias de comandos de AdWords.

Dos advertencias: hemos visto que aparecen muchos términos de búsqueda en «Otros términos de búsqueda» en los informes de consultas de búsqueda. Estos no se pueden excluir ya que Google no nos dice cuáles son. En segundo lugar, los datos del informe de términos de búsqueda no aparecen el mismo día, por lo que siempre estaremos un día por detrás de las variantes cercanas de Google.

/**
 *
 * Adds as campaign or AdGroup negatives search queries which have triggered exact keywords
 * Version: 1.0 - maintained AdWords script on brainlabsdigital.com
 * Authors: Visar Shabi & Daniel Gilbert
 * brainlabsdigital.com
 *
 **/
function main() {
  
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
  //Options
  
  //Choose whether to add your negative exact keywords at campaign or AdGroup level.
  //Set variable as "true" to add or as "false" to not add.
  var AddAdGroupNegative = true;  // true or false
  var AddCampaignNegative = true; // true of false
  
  //Parameters for filtering by campaign name and AdGroup name. The filtering is case insensitive.
  //Leave blank, i.e. "", if you want this script to run over all campaigns and AdGroups.
  var campaignNameContains = "";
  var adGroupNameContains = "";
  
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
  
  var campaigns = {};
  var adGroups = {};
   
  var exactKeywords = [];
  
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
  //Pull a list of all exact match keywords in the account
  
  var report = AdWordsApp.report(
    "SELECT AdGroupId, Id " +
    "FROM KEYWORDS_PERFORMANCE_REPORT " +
    "WHERE Impressions > 0 AND KeywordMatchType = EXACT " +
    "DURING LAST_7_DAYS");
  
  var rows = report.rows();
  while (rows.hasNext()) {
    var row = rows.next();
    var keywordId = row['Id'];
    var adGroupId = row['AdGroupId'];
    exactKeywords.push(adGroupId + "https://searchengineland.com/#" + keywordId);
  }
  
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
  //Pull a list of all exact (close variant) search queries
  
  var report = AdWordsApp.report(
    "SELECT Query, AdGroupId, CampaignId, KeywordId, KeywordTextMatchingQuery, Impressions, MatchType " +
    "FROM SEARCH_QUERY_PERFORMANCE_REPORT " +
    "WHERE CampaignName CONTAINS_IGNORE_CASE '" + campaignNameContains + "' " +
    "AND AdGroupName CONTAINS_IGNORE_CASE  '" + adGroupNameContains + "' " +
    "DURING LAST_7_DAYS");
  
  var rows = report.rows();
  while (rows.hasNext()) {
    var row = rows.next();
    var adGroupId = parseInt(row['AdGroupId']);
    var campaignId = parseInt(row['CampaignId']);
    var keywordId = parseInt(row['KeywordId']);
    var searchQuery = row['Query'];
    var keyword = row['KeywordTextMatchingQuery'];
    var matchType = row['MatchType'].toLowerCase();
    if(keyword !== searchQuery && matchType.indexOf("exact (close variant)") !== -1){
      
      if(!campaigns.hasOwnProperty(campaignId)){
        campaigns[campaignId] = [[], []];
      }
      
      campaigns[campaignId][0].push(searchQuery);
      campaigns[campaignId][1].push(adGroupId + "https://searchengineland.com/#" + keywordId);
      
      if(!adGroups.hasOwnProperty(adGroupId)){
        adGroups[adGroupId] = [[], []];
      }
      
      adGroups[adGroupId][0].push(searchQuery);
      adGroups[adGroupId][1].push(adGroupId + "https://searchengineland.com/#" + keywordId);
    }
  }
  
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
  //Parse data correctly
  
  var adGroupIds = [];
  var campaignIds = [];
  var adGroupNegatives = [];
  var campaignNegatives = [];
  
  for(var x in campaigns){
    campaignIds.push(parseInt(x));
    campaignNegatives.push([]);
    for(var y = 0; y < campaigns[x][0].length; y++){
      var keywordId = campaigns[x][1][y];
      var keywordText = campaigns[x][0][y];
      if(exactKeywords.indexOf(keywordId) !== -1){
        campaignNegatives[campaignIds.indexOf(parseInt(x))].push(keywordText);
      }
    }
  }
  
  for(var x in adGroups){
    adGroupIds.push(parseInt(x));
    adGroupNegatives.push([]);
    for(var y = 0; y < adGroups[x][0].length; y++){
      var keywordId = adGroups[x][1][y];
      var keywordText = adGroups[x][0][y];
      if(exactKeywords.indexOf(keywordId) !== -1){
        adGroupNegatives[adGroupIds.indexOf(parseInt(x))].push(keywordText);
      }
    }
  }
  
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
  //Create the new negative exact keywords
  
  var campaignResults = {};
  var adGroupResults = {};
  
  if(AddCampaignNegative){
    var campaignIterator = AdWordsApp.campaigns()
    .withIds(campaignIds)
    .get();
    while(campaignIterator.hasNext()){
      var campaign = campaignIterator.next();
      var campaignId = campaign.getId();
      var campaignName = campaign.getName();
      var campaignIndex = campaignIds.indexOf(campaignId);
      for(var i = 0; i < campaignNegatives[campaignIndex].length; i++){
        campaign.createNegativeKeyword("[" + campaignNegatives[campaignIndex][i] + "]")
        if(!campaignResults.hasOwnProperty(campaignName)){
          campaignResults[campaignName] = [];
        }
        campaignResults[campaignName].push(campaignNegatives[campaignIndex][i]);
      }
    }
  }
  
  if(AddAdGroupNegative){
    var adGroupIterator = AdWordsApp.adGroups()
    .withIds(adGroupIds)
    .get();
    while(adGroupIterator.hasNext()){
      var adGroup = adGroupIterator.next();
      var adGroupId = adGroup.getId();
      var adGroupName = adGroup.getName();
      var adGroupIndex = adGroupIds.indexOf(adGroupId);
      for(var i = 0; i < adGroupNegatives[adGroupIndex].length; i++){
        adGroup.createNegativeKeyword("[" + adGroupNegatives[adGroupIndex][i] + "]");
        if(!adGroupResults.hasOwnProperty(adGroupName)){
          adGroupResults[adGroupName] = [];
        }
        adGroupResults[adGroupName].push(adGroupNegatives[adGroupIndex][i]);
      }
    }
  }
  
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
  //Format the results
  
  var resultsString = "The following negative keywords have been added to the following campaigns:";

  for(var x in campaignResults){
    resultsString += "nn" + x + ":n" + campaignResults[x].join("n");
  }
  
  resultsString += "nnnnThe following negative keywords have been added to the following AdGroups:";
  
  for(var x in adGroupResults){
    resultsString += "nn" + x + ":n" + adGroupResults[x].join("n");
  }
  
  Logger.log(resultsString);
  
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
  
}

Cómo funciona el guión

Para aquellos lo suficientemente valientes, ahora desglosaremos el guión en más detalles.

Elegir su configuración

Hemos hecho que el script sea flexible para que funcione con diferentes estructuras de cuentas. Por ejemplo, puede decidir si desea agregar sus palabras clave negativas exactas a nivel de campaña o de grupo de anuncios. Hemos incorporado una funcionalidad para excluir ciertas campañas o grupos de anuncios mientras se ejecuta el script.

 //Choose whether to add your negative exact keywords at campaign or AdGroup level.
  //Set variable as "true" to add or as "false" to not add.
  var AddAdGroupNegative = true;  // true or false
  var AddCampaignNegative = true; // true of false
  
  //Parameters for filtering by campaign name and AdGroup name. The filtering is case insensitive.
  //Leave blank, i.e. "", if you want this script to run over all campaigns and AdGroups.
  var campaignNameContains = "";
  var adGroupNameContains = "";

Empezando

Comenzamos extrayendo un informe de consulta de búsqueda de los últimos siete días (o cualquier otro período de tiempo que desee). Almacenamos toda esta información en matrices, con una matriz para los identificadores de grupo de anuncios, identificadores de campaña, identificadores de palabras clave, consultas de búsqueda, palabras clave y tipos de concordancia. Es importante tener en cuenta que todos los datos asociados con una consulta de búsqueda se encuentran en la misma posición en cada una de las matrices.

   var report = AdWordsApp.report(
 "SELECT Query, AdGroupId, CampaignId, KeywordId, KeywordTextMatchingQuery, Impressions, MatchType " +
 "FROM SEARCH_QUERY_PERFORMANCE_REPORT " +
 "WHERE CampaignName CONTAINS_IGNORE_CASE '" + campaignNameContains + "' " +
 "AND AdGroupName CONTAINS_IGNORE_CASE '" + adGroupNameContains + "' " +
 "DURING LAST_7_DAYS");
 
 var rows = report.rows();
 while (rows.hasNext()) {
 var row = rows.next();
 var adGroupId = parseInt(row['AdGroupId']);
 var campaignId = parseInt(row['CampaignId']);
 var keywordId = parseInt(row['KeywordId']);
 var searchQuery = row['Query'];
 var keyword = row['KeywordTextMatchingQuery'];
 var matchType = row['MatchType'].toLowerCase();

La parte importante

El siguiente es el paso crucial: el Si la siguiente declaración toma todos los términos de búsqueda que no coinciden exactamente con la palabra clave que activaron Y tienen un tipo de concordancia de palabra clave exacto (variante cercana). Esto nos da exactamente lo que buscamos: todos esos molestos términos de búsqueda que se han creado como resultado del cambio de Google.

if(keyword !== searchQuery &amp;&amp; matchType.indexOf("exact (close variant)") !== -1)

Almacenamos todas estas consultas de búsqueda con la identificación de la campaña, la identificación del grupo de anuncios y la identificación de la palabra clave con la que están asociadas.

Finalmente agregando los negativos

Todo lo que queda por hacer ahora es agregar elementos negativos de campaña (o grupo de anuncios) a las campañas relevantes (o grupos de anuncios). Parece complicado, pero en realidad es bastante sencillo.

Primero tomamos todas las campañas a las que necesitamos agregar negativos, junto con su identificación y nombre. Repitiendo cada campaña, a continuación creamos todas las palabras clave negativas asociadas con esta campaña haciendo coincidir los identificadores. Y finalmente, todo lo que queda por hacer es agregar estas palabras clave negativas a la campaña correcta.

  var campaignResults = {};
  var adGroupResults = {};
  
  if(AddCampaignNegative){
    var campaignIterator = AdWordsApp.campaigns()
    .withIds(campaignIds)
    .get();
    while(campaignIterator.hasNext()){
      var campaign = campaignIterator.next();
      var campaignId = campaign.getId();
      var campaignName = campaign.getName();
      var campaignIndex = campaignIds.indexOf(campaignId);
      for(var i = 0; i < campaignNegatives[campaignIndex].length; i++){
        campaign.createNegativeKeyword("[" + campaignNegatives[campaignIndex][i] + "]")
        if(!campaignResults.hasOwnProperty(campaignName)){
          campaignResults[campaignName] = [];
        }
        campaignResults[campaignName].push(campaignNegatives[campaignIndex][i]);
      }
    }
  }

Comprobación de las nuevas palabras clave negativas

Para nuestro acto final, registramos todos los cambios que hemos realizado para comprobar que estamos satisfechos con las nuevas palabras clave negativas exactas.

var resultsString = "The following negative keywords have been added to the following campaigns:";

  for(var x in campaignResults){
    resultsString += "nn" + x + ":n" + campaignResults[x].join("n");
  }

Y luego terminamos. ¡Lo siento, Google!


Las opiniones expresadas en este artículo pertenecen al autor invitado y no necesariamente a El Blog informatico. Los autores del personal se enumeran aquí.


Deja un comentario