240 anunciantes en línea
240 anunciantes en línea
Conoce las mejores practicas para el uso del Editor de AdWords e intercambia consejos y trucos acerca de cómo administrar mejor tus campaña y gestionar todos los distintos tipos de anuncios.
Guiame
favorite_border
Responder

2 AdWords Scripts para excluir Ubicaciones de Display SPAM y de bajo rendimiento

[ Editado ]
Estudiante ✭ ✭ ✭
# 1
Estudiante ✭ ✭ ✭

Hola a toda la Comunidad,

 

El mes pasado, encontré la publicación de @NachoG en la que publicaba un AdWords script para excluir las ubicaciones de Display que terminen en determinados TLDs (.info, .ru, .edu, etc.). Desde entonces, estuve dándole vueltas a otras variantes y mejoras que se pudieran hacer.

 

Hoy, quiero compartir con vosotros 2 scripts que he desarrollado inspirado en el publicado por Nacho.

 

La idea es la siguiente: Recorrer todas las campañas (ya sea a nivel cuenta o a nivel MCC) y excluir aquellas ubicaciones de Display que cumplan "X" condiciones. Lo que diferencia entre ambos scripts, es la condición que deben cumplir. Para cada script, he desarrollado 5 versiones, de menos a más complejidad (y funcionalidades)

 

Script 1: Detectar, recopilar y excluir ubicaciones de Display con bajo rendimiento

 

Versión 1: Script a nivel de cuenta

 

Busca, a nivel de cuenta, las ubicaciones de Display que tengan al menos un nº de impresiones y, como máximo, un nº de clics, conversiones y conversiones post-impresión. Todos estos valores son editables.

 

Por ejemplo, los valores por defecto son:

  • Impresiones: 1000
  • Clics: 0
  • Conversiones: 0
  • Conversiones post-impresión: 0

 

var impressionsMinimum = 1000; // Select Display placements which have at least that number of impressions 
var clicksLimit = 0; // Select Display placements which have no more than that number of clicks 
var conversionsLimit = 0; // Select Display placements which have no more than that number of conversions 
var ViewThroughConversionsLimit = 0; // Select Display placements which have no more than that number of post-impression conversions
var timePeriod = "ALL_TIME"; // Period of time to analyze. You can choose another value according to https://developers.google.com/adwords/scripts/docs/reference/adwordsapp/adwordsapp_campaignselector?hl=es-419#forDateRange_1

 

 

De esta manera, el script excluirá aquellas ubicaciones de Display que tengan, al menos, 1000 impresiones acumuladas y no hayan recibido clics ni hayan producido conversiones ni conversiones post-impresión.

 

 

AdWordsApp.display().placements()
 	.withCondition("Clicks <= "+clicksLimit)
	.withCondition("Impressions >= "+impressionsMinimum)
        .withCondition("Conversions <= "+conversionsLimit)
	.withCondition("ViewThroughConversions <= "+ViewThroughConversionsLimit)
	.withCondition("CampaignStatus != REMOVED")
	.forDateRange(timePeriod);

 

 

Enlace del código completo en GitHub

 

Versión 2: Script a nivel de MCC

 

Versión del script ejecutado a nivel MCC.

 

 

function executeInSequence (sequentialIds, executeSequentiallyFunc) {
 // Logger.log('Executing in sequence : ' + sequentialIds);
  sequentialIds.forEach(function (accountId) {
    var account = MccApp.accounts().withIds([accountId]).get().next();
    MccApp.select(account);
    executeSequentiallyFunc();
  });
} // End of executeInSequence function


function main () {
  try {
    var accountIterator = MccApp.accounts().orderBy('Name').get();
    var accountIds = [];
    var accountId;

    while (accountIterator.hasNext()) {
      accountIds.push(accountId);
      accountId = accountIterator.next().getCustomerId();
    }
    accountIds.push(accountId);
  
  var sequentialIds = accountIds.slice(0);

  if (accountIds.length > 0) {
    executeInSequence(sequentialIds, run);
  }
} catch (exception) {
    // not an Mcc
    Logger.log('Running on non-MCC account.');
    run();
  }

 

Además, se comprueba antes de excluir cada ubicación, si coincide con 'anonymous.google'. Si coincide, NO lo excluye.

 

 

	if (placementUrl != 'anonymous.google') {
 
      newRow = sheet.getRange(3,1).getValue() + 1; // Get the last row with data from the spreadsheet and goes to the next one
placementStats = placement.getStatsFor('ALL_TIME');
campaign = placement.getCampaign();
adGroup = placement.getAdGroup();
excludeOperation = adGroup.display().newPlacementBuilder().withUrl(placementUrl).exclude(); // Exclude Display placement detected

if (!excludeOperation.isSuccessful()) { Logger.log("Could not exclude : " + placementUrl); } } else { Logger.log("Don't exclude anonymous.google.com !"); }

 

Enlace del código completo en GitHub

 

Versión 3: Filtro por etiqueta a nivel MCC

 

Hablando con @DanielJurado, me dio una idea que me pareció muy interesante: permitir filtrar la ejecución del script por etiqueta (de cuenta) a nivel MCC. Dicho y hecho.

 

La variable auxiliar:

 

var mccLabelText = "no label"; // Filter AdWords accounts which have a MCC Account label
                              // If you don't want to filter by any MCC label, DO NOT make any change in this text

Y el código de filtrado:

 

	if (mccLabelText != "no label") { // Filter accounts by MCC label
		accountIterator = MccApp.accounts().withCondition("LabelNames CONTAINS '" + mccLabelText +"'").orderBy('Name').get();
	} else { // Execute script for all accounts
		accountIterator = MccApp.accounts().orderBy('Name').get();
	}

Enlace del código completo en GitHub

 

Versión 4: Recopilación de ubicaciones en un spreadsheet

 

En este caso, fue @enriquedelvalle quien me dio otra genial idea: añadir todas las ubicaciones detectadas en un spreadsheet. Esto tiene 2 principales ventajas: 

 

  1. Poder revisar fácilmente las ubicaciones excluidas y, si detectamos alguna que no queramos que sea excluida, podamos saber de forma rápida en qué campaña se excluyó, y así poder restaurarla.
  2. Obtener un listado único de todas las ubicaciones de Display detectadas y excluidas en TODAS las cuentas en las que el script se ejecutó. Esto puede ser muy útil si creamos una campaña nueva de Display y queremos excluir en ella de inicio todas esas ubicaciones.

 

Para ello, creé estas variables auxiliares:

 

var SPREADSHEET_URL = "INSERT YOUR SPREADSHEET URL HERE"; // Make a copy from https://docs.google.com/spreadsheets/d/1QM25rhifHLN6xElLyMPgeJVtx5hz4qI9415aNnyhmmA/
var SHEET_NAME = "LowPerformance placements"; // Name of the specific sheet in the spreadsheet.
var ss = SpreadsheetApp.openByUrl(SPREADSHEET_URL);
var sheet = ss.getSheetByName(SHEET_NAME);
var lastRow = sheet.getLastRow(); // Last row from the spreadsheet which have a placement registered
var newRow = lastRow;

Para que esta versión funcione correctamente, debéis crear una copia de este spreadsheet

 

La parte del código donde se añade la información de cada ubicación en el spreadsheet es esta:

 

// Add the Display placement excluded to the spreadsheet
sheet.getRange(newRow,2).setValue(placementUrl);
sheet.getRange(newRow,3).setValue(placementStats.getClicks());
sheet.getRange(newRow,4).setValue(placementStats.getImpressions());
sheet.getRange(newRow,5).setValue(accountIdAux);
sheet.getRange(newRow,6).setValue(accountName);
sheet.getRange(newRow,7).setValue(campaign.getName());
sheet.getRange(newRow,8).setValue(campaign.getId());
sheet.getRange(newRow,9).setValue(adGroup.getName());
sheet.getRange(newRow,10).setValue(adGroup.getId());
sheet.getRange(3,1).setValue(newRow);

Si quisierais recopilar otro tipo de información de cada ubicación, es aquí donde debéis modificar el script.

 

 

Enlace del código completo en GitHub

 

Versión 5: Sitema de control de ejecución de más de 30 minutos

 

Al introducir la funcionalidad del spreadsheet, empecé a tener muchos problemas con la ejecución en paralelo, ya que se solapaban los registros del spreadsheet y se perdía información. Por tanto, renuncié a esta opción y desarrollé el script para que ejecutase todas las cuentas en secuencia, una por una. 

 

La desventaja es que, al perder la ejecución en paralelo, la duración del script se multiplica y, en el caso de durar más de 30 minutos, automáticamente la ejecución se verá interrumpida. En ese caso, la siguiente ejecución del script comenzaría de nuevo por la primera cuenta.

 

Por eso, y siguiendo el consejo de @jrsanfeliu , decidí aprovechar el propio spreadsheet e incluir un campo de control, en el que guardara la posición del array de la última cuenta en la que que fue ejecutado el script.   

 

var lastExecutedAccount;  // If the script is executed for more than 30 minutes, AdWords will interrupt the execution. 
                          // In that case, this variable saves the last AdWords account executed and the script will start from this account at the next execution
var accountIds, accountId, accountIdAux, accountName;
function executeInSequence (sequentialIds, executeSequentiallyFunc) {
 // Logger.log('Executing in sequence : ' + sequentialIds);
  sequentialIds.forEach(function (accountId) {
    var account = MccApp.accounts().withIds([accountId]).get().next();
    lastExecutedAccount++; 
	sheet.getRange(5,1).setValue(lastExecutedAccount); // Updating lastExecutedAccount value in the spreadsheet
    MccApp.select(account);
accountIdAux = account.getCustomerId();
accountName = account.getName(); executeSequentiallyFunc(); }); } // End of executeInSequence function

Por otro lado, si el script termina su ejecución sin interrupciones, 'reseteará' el valor de la última cuenta ejecutada a cero:

 

lastExecutedAccount = 0; // If script execution finishes correctly, then reset lastExecutedAccount to default value
  sheet.getRange(5,1).setValue(lastExecutedAccount); // Updating lastExecutedAccount value in the spreadsheet

Por último, en la siguiente ejecución del script, extraerá ese valor del spreadsheet.

 

lastExecutedAccount = sheet.getRange(5,1).getValue() + 1; // lastExecutedAccount get the number of AdWords accounts executed at the last script execution.

Y comenzará a ejecutarse desde la posición de la última cuenta ejecutada o desde el comienzo, si el valor extraído era cero.

 

    if (lastExecutedAccount != 1){ // If the last script execution was interrupted, then subtract 1 to lastExecutedAccount (start script execution from the account where script was interrupted)
      lastExecutedAccount--;
    }
  
  var sequentialIds = accountIds.slice(lastExecutedAccount);

 

Enlace del código completo en GitHub

 

 

Script 2: Detectar, recopilar y excluir ubicaciones de Display SPAM

 

 

 

¿Cuántas veces has entrado en páginas en las que, al hacer clic en cualquier sitio, hacen que te salte un banner? Seguro que muchas. Pues bien, si no tenemos cuidado en nuestras campañas de AdWords, parte de nuestro presupuesto lo estaremos tirando en este tipo de clics forzados

 

 

Si nos preguntamos qué es lo que caracteriza a este tipo de ubicaciones 'spam', nos daremos cuenta de que tienen como factor común su exageradamente alto CTR.

 

Por ello, para hacer este segundo script, hay que modificar la condición que excluya (o no) a una ubicación. En este caso, el script busca las ubicaciones de Display que tengan al menos un nº de impresiones y, como mínimo, un CTR concreto. Además, también limita las ubicaciones de Display a aquellas que hayan tenido como máximo un nº conversiones y conversiones post-impresión. Todos estos valores son editables.

 

Por ejemplo, los valores por defecto son:

 

  • Impresiones: 2
  • CTR mínimo: 49%
  • Conversiones: 0
  • Conversiones post-impresión: 0

 

var impressionsMinimum = 2; // Select Display placements which have at least that number of impressions 
var maxCtr = 0.49; // Select Display placements which have at least that Click Through Rate percentage 
var conversionsLimit = 0; // Select Display placements which have no more than that number of conversions 
var ViewThroughConversionsLimit = 0; // Select Display placements which have no more than that number of post-impression conversions
var timePeriod = "ALL_TIME"; // Period of time to analyze. You can choose another value according to https://developers.google.com/adwords/scripts/docs/reference/adwordsapp/adwordsapp_campaignselector?hl=es-419#forDateRange_1

De esta manera, el script excluirá aquellas ubicaciones de Display que tengan, al menos, 2 impresiones acumuladas, un CTR superior al 49% y que no han producido conversiones ni conversiones post-impresión.

 

AdWordsApp.display().placements()
 	.withCondition("Ctr > "+maxCtr)
	.withCondition("Impressions >= "+impressionsMinimum)
        .withCondition("Conversions <= "+conversionsLimit)
	.withCondition("ViewThroughConversions <= "+ViewThroughConversionsLimit)
	.withCondition("CampaignStatus != REMOVED")
	.forDateRange(timePeriod)

 

Como comentaba al principio, este script únicamente difiere del anterior en la condición para excluir la ubicación, por lo que pongo directamente los enlaces a cada una de las 5 versiones:

 

 

Versión 1: script a nivel de cuenta Enlace a GitHub 

Versión 2: script a nivel de MCC Enlace a GitHub 

Versión 3: Filtro por etiqueta a nivel MCC Enlace a GitHub 

Versión 4: Recopilación de ubicaciones en spreadsheet Enlace a GitHub 

Versión 5: Control de ejecución de 30 minutos Enlace a GitHub 

 

Enlace a la plantilla de spreadsheet.

 

 

Hasta aquí la entrada. Estoy seguro de que se puede hacer de mil formas más eficientes y añadir funcionalidades mucho más interesantes, por lo que os animo a darle vueltas, trastear con ello y dejar en los comentarios vuestras preguntas, sugerencias o ideas.

 

 

ACTUALIZACIÓN 21/10/2016:

 

Tras recoger el feedback de los primeros usuarios, he realizado las siguientes modificaciones:

 

  1. Cambiado el nivel de exclusión de cada ubicación: antes se excluía a nivel de campaña, ahora se excluye a nivel de grupo de anuncios para tener un mayor control de dónde se excluye cada ubicación.
  2. Modificado, tanto el script como la plantilla del spreadSheet, para incluir en la información recopilada, los IDs y nombres de la cuenta publicitaria, campaña y grupo de anuncios a los que pertenece la ubicación excluida. De esta manera, identificaremos de manera aún más rápida y sin equívocos, donde se produjo cada exclusión.
  3.  Añadida variable global "timePeriod" para facilitar la edición del periodo de tiempo a analizar. Por defecto, la opción elegida es ALL_TIME, pero para cuentas con mucho histórico, puede llegar a ser un problema. También se indica el enlace a la página de Google Developers donde indica qué valores son compatibles.

 

Expertos respondieronverified_user

2 AdWords Scripts para excluir Ubicaciones de Display SPAM y de bajo rendimiento

Colaborador Principal
# 2
Colaborador Principal

Gran trabajo, desde luego que nos hemos movilizado bastante con todo esto, yo ya sabía que este tema generaría gran interés porque todo aquel que ha hecho una campaña de display tarde o temprano se ha visto afectado por el gran problema del fraude en display tema sobre el que he investigando mucho por necesidad.

 

Lo primero que yo pensé cuando salieron los scripts fueron en usarlos para excluir en display pero mi decepción fue grande cuando vi que no se permitía todavía trabajar a ese nivel, por suerte todo evoluciona y cada vez tenemos mas control y mas herramientas para mejorar nuestro trabajo.

 

Ahora ya es cuestión de ponerse con ello y automatizar esta tarea tan laboriosa de excluir ubicaciones.

 

2 AdWords Scripts para excluir Ubicaciones de Display SPAM y de bajo rendimiento

Colaborador Principal Alumni
# 3
Colaborador Principal Alumni

Fenómeno Alberto

 

Gran aporte. 

 

Saludos,

 

Re: 2 AdWords Scripts para excluir Ubicaciones de Display SPAM y de bajo rendimiento

Colaborador Principal
# 4
Colaborador Principal

Muy completo y útil @Alberto Esteves, muchas gracias!

Carlos David López

Responsable de Marketing Online en Idento

2 AdWords Scripts para excluir Ubicaciones de Display SPAM y de bajo rendimiento

Colaborador Principal
# 5
Colaborador Principal

Muy bueno, enhorabuena Alberto y gracias por compartir

 

oscar abad