1.3K anunciantes en línea
1.3K anunciantes en línea
Bienvenidos a la Comunidad Oficial de Google AdWords
favorite_border

Script contra dominios usados para fraudes !

 

article_nacho1.png

 

Una de las funcionalidades de Google Display que más echo de menos es sin duda poder elegir ubicaciones por Top Level-Domain (TLD). Es decir, igual que seleccionamos ubicaciones (periódicos, foros, páginas…) pudiéramos hacerlo y decir que queremos aparecer solo en .com, .edu, .es...que sin duda son una forma muy grande de segmentar. Con los nuevos dominios (.store, .barcelona, .berlin, .run…) esta segmentación se puede volver más apetitosa pero la realidad, en el año 2016, es diferente.

 

Son muchos que se están aprovechando de los nuevos dominios para adquirir nombres Exact Match y hacer páginas para engañar en Display. En concreto, he detectado algunos nuevos dominios como los .xyz y .tv que básicamente siempre son sitios que perjudican a las campañas display.

 

En honor a la verdad, también el dominio .info, quizá por su bajo precio, es un dominio elegido por muchos webmasters para hacer páginas de phishing, virales y anuncios escondidos en vídeos.

 

Un ejemplo fueron estos sitios, todos registrados por el mismo usuario, y que ya no existen:

viral.jpg

 

Un ejemplo de esta situación son estas webs donde han aparecido anuncios de un cliente:

Screen Shot 2016-09-01 at 9.18.51 PM.png

Muchas de estas webs desaparecen ante de 6 meses - de hecho tenía una lista pero todos están ya eliminados y no puedo enseñarla-, probablemente porque usan los trucos que ya denunció @enriquedelvalle en este otro post de la Comunidad.

 

Un Script reactivo contra las extensiones más fraudulentas

 

Por desgracia, proactivamente no se puede hacer nada y hasta ahora había que estar haciendo un barrido de ubicaciones automáticas casi a diario para no malgastar dinero.

 

Lo que sí podemos es ser reactivos y, navegando por la red, he descubierto este script que permite agregar como Exclusión de Ubicaciones a las urls con los dominios que digamos una vez que nuestro anuncio ha aparecido en una de estas webs.

 

 

/**
 * Removes placements ending in the tlds xyz, tk, and download.
 * @author Dawson Reid
 * @author Andrew Breen
 */

// Top Level Domains to exclude

var TLDs = '.xyz, .tk, .download';

// -------------------------------------------------------

function removePlacementByDomain (domain) {
  var placementSelector = AdWordsApp.display().placements()
  .withCondition("PlacementUrl CONTAINS '" + domain + "'")
  .withCondition("CampaignStatus != REMOVED");

  var placementIterator = placementSelector.get();
  while (placementIterator.hasNext()) {
    var placement = placementIterator.next();
    var placementUrl = placement.getUrl();
    //Logger.log(placementUrl);

    var campaign = placement.getCampaign();
    var excludeOperation = campaign.display().newPlacementBuilder().withUrl(placementUrl).exclude();
    if (!excludeOperation.isSuccessful()) {
      Logger.log("Could not exclude : " + placementUrl);
    }
  }
}

function run () {
  TLDs.split(',').map(function (tld) {
    return tld.trim();
  }).forEach(function (domain) {
    removePlacementByDomain(domain);
  });
}

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();
  });
}

function main () {
  try {
    var accountIterator = MccApp.accounts().orderBy('Name').get();
    Logger.log('Total number of accounts under MCC : ' + accountIterator.totalNumEntities());

    var accountIds = [];
    while (accountIterator.hasNext()) {
      var account = accountIterator.next();
      accountIds.push(account.getCustomerId());
    }
    var parallelIds = accountIds.slice(0, 50);
    var sequentialIds = accountIds.slice(50);
    // execute accross accounts
    MccApp.accounts()
      .withIds(parallelIds)
      .executeInParallel('run');
    if (sequentialIds.length > 0) {
      executeInSequence(sequentialIds, run);
    }
  } catch (exception) {
    // not an Mcc
    Logger.log('Running on non-MCC account.');
    run();
  }
}

 

El script funciona tanto a nivel individual como MCC, por lo que el poder reactivo puede ser exponencialmente grande.

 

El cambio que debemos de realizar es poner en esta línea:

var TLDs = '.xyz, .tk, .download'

Las extensiones de dominios que no queremos. Yo además de los que vienen por defecto he añadido otros como .sexy, .info, .top, .ovh entre otros. Y además, por problemas que he tenido a pesar de señalar como segmentación el idioma español, también he tenido que añadir dominios territoriales como el .ro, .ru que no tienen contenido en nuestro idioma pero se han colado.

 

Web oficial de Outshine, autor

Github con el código

 

Mi recomendación es programarlo para que funcione cada hora. Semanalmente echo un ojo a los logs para ver qué dominios ha expulsado y, por ahora, no he encontrado ninguno interesante. Pero no por ello dejaré de revisar de vez en cuando, pero ahora pierdo menos tiempo en estos dominios, mucho menos tiempo.

 

Espero que os funcione. 

Acerca de Nacho G.Bengoetxea

Especialista en Campañas Adwords, experiencia internacional (España, México, Colombia, Francia y Portugal)

Comentarios
por enriquedelvalle Colaborador Principal
septiembre 2016

Alucinante descubrimiento, he soñado muchas veces con que AdWords pudiera hacer algo así.

 

Gran aporte !!!

por MarceloFdez Usuario Destacado
septiembre 2016

Gracias ;-)

por EnriqueClemente
septiembre 2016

Genial!

por Santi Ureta
septiembre 2016

Bloquear los sitios fraudulentos nuevos que se cuelan prácticamente a diario en GDN va a ser más sencillo con esta Excelente Aportación. Gracias!

por J Carlos Díaz
septiembre 2016

Nacho Grandisimo aporte!!!

Gracias por compartirlo. 

por Carmen_alGenio
septiembre 2016

¡Muchísimas gracias, Nacho!

por enriquedelvalle Colaborador Principal
septiembre 2016

Yo lo estoy probando con una gran lista que incluye prácticamente todos los dominios menos el .es y .com y estoy teniendo fallos me bloquea también estos dominios. Si lo se que soy un poco bruto pero estuve analizando en una de las cuentas mas grandes que tengo y mis conversiones al 99% vienen del .es y .com y no me vale la pena por un 1% de conversiones que tenga comerme todo el spam que hay en otros dominios.

El problema que pienso que tiene el script es que el .co excluye también al .com , no lo se con certeza estoy todavía haciendo pruebas.

 

Otra de las pegas que le he encontrado al script es que se pone a funcionar para todo el periodo de la cuenta y como la cuenta sea grande o lleve años al script no le va a dar tiempo a realizar la tarea porque los scripts tienen una limitación de 30 minutos y pasado ese tiempo se paran. Lo bueno es que si lo vuelves a lanzar los dominios que ya ha añadido no los tiene que volver a añadir y en lo que mas tarda es en ese proceso de añadir los dominios.

 

La exclusión se realiza a nivel de campaña por lo que si tienes 15 campañas y hay un dominio que que el sistema determina que debe de excluir lo hará en las campañas que hallan generado al menos un clic y tendrá que hacerlo en todas si es que se genero tráfico

 

Al script por tanto le veo dos pegas la primera es que siempre te comes el primer clic y con esto no bloqueamos las ubicaciones tipo 1 impresion 1 clic CTR 100% que es la gran lacra del display, si se pudiera configurar para excluir por impresiones sería excelente, y si se pudiera decidir para que periodo de tiempo queremos que actúe el script mejor porque en una cuenta grande o que tenga varios años te toca pasar el script muchas veces hasta que le da tiempo a añadir todos los dominios a bloquear. Sería también muy interesante que se pudiera trabajar con listas de exclusiones en vez de añadir las ubicaciones campaña a campaña, si alguien sabe modificarlo se podría hacer algo muy chulo.

 

Por si a alguien le interesa he encontrado esta lista que contiene todos los gTLDs que existen, no sabía que hubieran tantos.

 

http://www.iana.org/domains/root/db

por MarceloFdez Usuario Destacado
septiembre 2016

Aclarar que el Script funciona con dominios o palabras incluidas en la url. Ej: "juegos, games, loquesea". No es obligatorio el uso de un dominio.

 

var placementSelector = AdWordsApp.display().placements()
  .withCondition("PlacementUrl CONTAINS '" + domain + "'")

 

Por otro lado, y con unas pequeñas modificaciones, se puede aplicar a una cuenta y campaña determinada. Es logico tener varios anunciantes o campañas que no compartan urls exclusidas. Para ello debeis modificar la funcion main con:

 

MccApp.accounts().withIds([id_cliente]).executeInParallel('run');

 

De este modo el script solo revisara una cuenta o cuentas selecionadas. Para reviar una campaña en concreto debeis remplazar la siguiente linea de la funcion removePlacementByDomain

 

.withCondition("CampaignName = 'Nombre de la Campaña'");

 

 

Un salu2 ;-)

por enriquedelvalle Colaborador Principal
septiembre 2016

Hola Marcelo muchas gracias por darnos mas códigos.

 

He estado probando la exclusion de palabras y me funciona si pongo una pero si pongo mas separadas por comas no va.

He hecho varias combinaciones con espacios incluso con ; pero nada, este es el primer código que use basándome en el ejemplo que comentabas tu.

 

.withCondition("PlacementUrl CONTAINS 'juego,game,forex" + domain + "'")

por MarceloFdez Usuario Destacado
septiembre 2016

Hola Enrique,

 

Tienes que incluir las palabras en la variable, igual que los dominios ;-)

 

var TLDs = '.xyz, .tk, .download, juegos, games, loquesea';

 

Un saludo.

por enriquedelvalle Colaborador Principal
septiembre 2016

Ahh, yo probe en esa linea y me funcionó poniendo solo una por lo que pense que funcionaría poniendo mas, gracias por el dato.

 

Sigo analizando y llego a la conclusión del que el script no funciona bien porque no diferencia entre palabras clave y dominios pongo un ejemplo:

 

Me esta excluyendo los dominios: 

runshoes.es porque tengo excluido .ru

campercontact.com porque tengo excluido el dominio .contact 

La lista que tengo es interminable de dominios que me esta bloqueando y no debería.

 

Por lo que el script es un auténtico peligro, puedes bloquear dominios que no desees, para mi el úso que le veo es para excluir por nombres tipo: forex, juego, game ... porque ahí el tema esta muy claro. Imagino que se trata de un error de programación o de que no esta pensado para trabajar con dominios sino para palabras clave. Pienso que por algun motivo ignora el punto.

 

¿ Alguien esta probando el script y ha observado algo así ?

por NachoG Colaborador Principal
septiembre 2016

Hola Enrique,

 

A mí eso que comentas no me ha pasado, he sacado de una campaña los datos y mira:

 

Se trata de una campaña focalizada en cuatro ciudades españolas, y no hay ningún com ni es entre 136 resultados.

dominios.PNG

Y en otra sobre 1000 hay 3 .com y 0 .es:

 

dominios 2.PNG 

 

Es decir, me está dando un margen de error de 0,002% en com y 0% en es .

Llevaba probando este script en una cuenta durante un mes y no vi esto que comentas, echaré el ojo de nuevo a ver si me pasó pero los datos ahora mismo son estos.

por enriquedelvalle Colaborador Principal
septiembre 2016

Hola Nacho

Bueno es que depende de las exclusiones que hallas añadido estaras bloqueando dominios. El caso es que el sistema no excluye solo por dominio sino porque esas letras esten incluidas en el dominio, de esa forma .ru excluye dominios tipo: running.es

por MarceloFdez Usuario Destacado
septiembre 2016

Buenas chic@s,

 

El funcionamiento del Script basicamente es el siguiente.

 

1 - Selecciona todas las campañas Display de todas las cuentas. Esto se puede cambiar a una única cuenta y varias campañas o solo una campaña, dependiendo la condición que programemos, impresiones, estado, etc… Por defecto todas las cuentas todas las campañas.

 

2 - El sistema genera un bucle con las palabras especificadas en la variable, separadas por comas (,) el cual contrastara con las ubicaciones de las cuentas o campañas seleccionadas. Utilizara la condición de URL CONTIENE.

 

3 - Si las ubicaciones coinciden con las palabras especificadas se excluyen.

 

Ej: Var = '.tk, .com, juego'  es igual a URL contiene .tk or .com or juego

 

El Script funciona bastante bien una vez adapatado a nuestra necesidad ;-)

 

por AntoniSEM Usuario Destacado
septiembre 2016

Hola, gracias por el scritp.

 

¿Habeis probado la siguiente condición para que no elimine los .com?

 

.withCondition("PlacementUrl DOES_NOT_CONTAIN '.com' ")

 

Iría en la primera función.

 

Un saludo

 

 

por enriquedelvalle Colaborador Principal
septiembre 2016 - última edición septiembre 2016

Muy interesante porque cuando lance una lista larga de dominios me estaba excluyendo el .com imagino que al añadir el .co y me estuve volviendo loco para comprender porque eliminaba el .com, esa excepción puede ser muy interesante para evitarlo.

 

¿ podría quedar asi ? o mas arriba o abajo, cuando no entiendes perfectamente la programación puede resultar complicado cambiar simplemente una linea, entiendo que la sesion se cierra con ;

 

function removePlacementByDomain (domain) {
var placementSelector = AdWordsApp.display().placements()
.withCondition("PlacementUrl CONTAINS '" + domain + "'")
.withCondition("PlacementUrl DOES_NOT_CONTAIN '.com' ")
.withCondition("CampaignStatus != REMOVED");

 

Gracias por el aporte.

 

por AntoniSEM Usuario Destacado
septiembre 2016

Efectivamente Enrique, así debería funcionar.

 

Básicamente indicas que contenga .co y que no contenga .com. No lo he probado, pero así debería ir.

 

Un saludo

por enriquedelvalle Colaborador Principal
septiembre 2016

Si funciona !!!

 

Para los que controlais mas sobre scripts se me ocurren algunos cambios mas para el script.

 

- Por defecto funciona para todo el periodo, pero si es una cuenta grande con varios años es una locura entre otras cosas porque el script solo corre 30 minutos, luego se para, lo bueno es que lo que ha excluido ya esta excluido y no lo vuelve a excluir, en todo caso sería una opción interesante.

 

- Otros motivos de bloqueo:

  Poder excluir por ejemplo por métricas tipo: CTR,Clics, Coste,Conversiones, Coste / Conversión.

 

 1 impresión 1 clic es algo que sucede con frecuencia CTR 100% y nunca mas volvemos  a salir en esa ubicación, por lo que sería interesante para esto a nivel de agencia poder en el momento que descubres 1 impresion 1 clic de una ubicación añadirlo a exclusión en todas las demas cuentas y campañas de la agencia, porque una de las pegas que tiene estas exclusiones es que normalmente no vuelven a repetirse en esa misma cuenta, son únicas y bloquearlas no sirven de nada, sin embargo si lo identificas en una cuenta eso se puede aplicar a todas las demás para bloquearlo antes de que suceda, con el tiempo se puede tener una base de datos personal a nivel de agencia interesante.

 

Bueno ahí quedan las ideas para los que tenéis maña con esto de los scripts, seguro que entre todos podemos conseguir una herramienta útil para solucionar uno de los problemas mas grandes y graves del display que Google de momento a día de hoy no es capaz de solucionar ni darnos herramientas integradas en la interface para esta lucha, la primera vez que vi las reglas automáticas sufrí una gran decepción al ver que solo funcionan para ubicaciones administrada y no para ubicaciones automáticas porque de ser así ya tendríamos una herramienta casi excelente para bloquear ubicaciones, con el inconveniente de que solo se pueden programar para que se ejecuten una vez al día no como los scripts que podemos programarlos para que se ejecuten cada hora. Que también la solución con reglas es crear 24 reglas iguales que se lancen cada día a intervalos de una hora pero es un poco rollo el crearlas y luego cada cambio tener que multiplicarlo por 24.

 

 

por Albert Berlanga
octubre 2016

Buenas,

 

Para controlar el tiempo a tener en cuenta basta con añadir:

 

.forDateRange('YESTERDAY');

 

Por ejemplo:

 

var placementSelector = AdWordsApp.display().placements()
.withCondition("PlacementUrl CONTAINS '" + domain + "'")
.withCondition("PlacementUrl DOES_NOT_CONTAIN '.com' ")
.withCondition("CampaignStatus != REMOVED")
.forDateRange('YESTERDAY');

Donde YESTERDAY puede valer:

 

TODAY, YESTERDAY, LAST_7_DAYS, THIS_WEEK_SUN_TODAY, LAST_WEEK, LAST_14_DAYS, LAST_30_DAYS, LAST_BUSINESS_WEEK, LAST_WEEK_SUN_SAT, THIS_MONTH, LAST_MONTH, ALL_TIME.

 

Y para controlar clics, impresiones, etc.. tenemos prácticamente todas las métricas: cost, ctr, clic, impresiones, etc...

Por ejemplo:

 

  var placementSelector = AdWordsApp.display().placements()
  .withCondition("PlacementUrl CONTAINS '" + domain + "'")
  .withCondition("PlacementUrl DOES_NOT_CONTAIN '.com' ")
  .withCondition("CampaignStatus != REMOVED")
  .withCondition("Clicks = 1")
  .withCondition("Impressions = 1")
  .forDateRange('YESTERDAY');

Tendríamos las ubicaciones que tengan un clic y una impresión que coincidan los los dominios filtrados.

 

Si eliminamos la línea:  

  .withCondition("PlacementUrl CONTAINS '" + domain + "'")

tendíamos ese ansiado listado que comenta @enriquedelvalle  ;-)

 

Habilitando la línea (es decir, eliminando el comentarios de las dos barras) 

 Logger.log(placementUrl);

obtendremos un registro en la vista previa de todos las URLs que cumplen las condiciones con lo que podríamos engrosar la lista de ubicaciones fraudulentas.

 

Espero que todo esto os haya ayudado.

 

Saludos,

 

 

 

por enriquedelvalle Colaborador Principal
octubre 2016

Fantástico Albert, con esas funcionalidades se abre un nuevo horizonte con muchas mas posibilidades, en cuanto tenga un hueco me pongo a trastear Emoticono feliz

por Albert Berlanga
octubre 2016

Gracias Enrique. ;-)

 

OJO por que pueden pasar cosas como estas:

 

foro.jpg

 

Con lo que en este caso excluiríamos heraldo.es de TODAS las campañas que cumplan la condición de 1 clic 1 impresión, y ya vemos que nos estaría afectando más de la cuenta.


Tened en cuenta que las condiciones del script son AND con lo que deben cumplirse todas para excluir.

 

Saludos,

por enriquedelvalle Colaborador Principal
octubre 2016

Es el problema de automatizar acciones, hay que estar muy encima para detectar este tipo de variables que pueden cumplirse. En todo caso no es lo normal ese caso, pero lo que hay que tener en cuenta es como funciona el script.

 

Corrígeme si me equivoco:

 

- Detecta lo que le indiquemos a nivel de grupo de anuncios.

- Excluye a nivel de campaña.

 

Por lo que si detecta una ubicación fraudulenta y tenemos 10 campañas vamos a tener que generar tráfico en todas antes de ir excluyéndolas una a una. 

 

¿ Se podría modificar el script para poder añadir las exclusiones a una lista de ubicaciones para gestionar desde la bliblioteca compartida ?

¿ Como podríamos hacer para que las exclusiones fueran a nivel de grupo de anuncios ?

 

Realmente el tema de la exclusión automatizarlo es complejo porque falta el factor humano que decide racionalmente cuando algo es bueno o malo por lo que para poder automatizar estos procesos es necesario personalizar mucho la herramienta para que pueda tomar estas decisiones y aun nos podemos equivocar. Pero bueno al final cuenta también la balanza, ¿ cuando presupuesto recuperamos al realizar este tipo de acciones frente a lo que podamos perder por excluir algo que no se deba ?

 

Interesante debate el que estamos creando con el script Emoticono feliz

 

 

por Albert Berlanga
octubre 2016

Buenas,

 

Respecto a lo que comentas @enriquedelvalle es correcto. Detecta las ubicaciones cuando tienen tráfico y las excluye a nivel de campaña.

 

Si lo que queremos es que la exclusión sea a nivel de grupo debemos cambiar este bloque:

 

 

    var campaign = placement.getCampaign();
    var excludeOperation = campaign.display().newPlacementBuilder().withUrl(placementUrl).exclude();
    if (!excludeOperation.isSuccessful()) {
      Logger.log("Could not exclude : " + placementUrl);
    }

 

 

por este:

 

 

   var group = placement.getAdGroup();
   Logger.log("Grupo: " + group);
   var excludeOperation = group.display().newPlacementBuilder().withUrl(placementUrl).exclude();
   if (!excludeOperation.isSuccessful()) {
    Logger.log("Could not exclude : " + placementUrl);
   }

 

 

Respecto a las exclusiones en listas, si claro, también se puede.

 

Si queremos añadirlo a una lista nueva debemos cambiar este bloque:

 

 

    var campaign = placement.getCampaign();
    var excludeOperation = campaign.display().newPlacementBuilder().withUrl(placementUrl).exclude();
    if (!excludeOperation.isSuccessful()) {
      Logger.log("Could not exclude : " + placementUrl);
    }

 

 

por este:

 

 

  var PlacementList = 'nombre de la lista de exlusión';
  
  var placementIterator = placementSelector.get();
  while (placementIterator.hasNext()) {
    var placement = placementIterator.next();
    var placementUrl = placement.getUrl();
    Logger.log(placementUrl);
    
 var excludedPlacementListOperation =
     AdWordsApp.newExcludedPlacementListBuilder()
         .withName(PlacementList)
         .build();
   
   if (excludedPlacementListOperation.isSuccessful()) {
    var excludedPlacementList = excludedPlacementListOperation.getResult();
    excludedPlacementList.addExcludedPlacement(placementUrl);
   }

 

 

Y si queremos que añada la ubicación a una lista nueva el bloque anterior debe cambiarse por:

 

 

     var PlacementList = 'nombre de la lista de exclusión';
  
  var placementIterator = placementSelector.get();
  while (placementIterator.hasNext()) {
    var placement = placementIterator.next();
    var placementUrl = placement.getUrl();
    Logger.log(placementUrl);
    
   var excludedPlacementListIterator =
     AdWordsApp.excludedPlacementLists()
     .withCondition('Name = ' + PlacementList)
     .get();
   
    if (excludedPlacementListIterator.totalNumEntities() == 1) {
    var excludedPlacementList = excludedPlacementListIterator.next();
      Logger.log(excludedPlacementList);
    excludedPlacementList.addExcludedPlacement(placementUrl);
   }  

 

Como podéis ver, da mucho juego.

 

Saludos,

 

por ooscarabad Colaborador Principal
octubre 2016

Muchisimas gracias @Albert Berlanga por el aporte

 

Un abrazo

por enriquedelvalle Colaborador Principal
octubre 2016

Creo que ya no se me ocurre nada mas que implementar el script Emoticono feliz que maquina Albert y que envídia controlar el mundo del código.

 

Ahora ya es cosa de personalizarlo al gusto de cada uno, porque lo que esta claro es que por defecto no funciona bien.

 

Por cierto el script original tenía el fallo que yo comenté a la hora de excluir por dominios se lo comenté al autor y se supone que ya lo ha corregido y actualizado, la verdad que no tuve tiempo de probarlo, lo podéis ver en los comentarios.

 

http://outshine.ca/blog/2016/7/8/automate-negative-placement-in-google-display-with-this-script

 

 

 

 

por juan manuel m
octubre 2016

Hola, por falta de experiencia he generado algunas campañas con adwords, pero hay un anuncio que se muestra en los resultados google anuncio, y no encuentro el email con el genere esa campaña ya que he abierto varias en pocos dias , he cancelado todas peroa laguna se me ha quedado sin cerrar, serian tan amables de ayudarme, para ver como localizo ese email para entrar al acuenta y parar ese anuncio. gracias.


NachoG escribió:

 

article_nacho1.png

 

Una de las funcionalidades de Google Display que más echo de menos es sin duda poder elegir ubicaciones por Top Level-Domain (TLD). Es decir, igual que seleccionamos ubicaciones (periódicos, foros, páginas…) pudiéramos hacerlo y decir que queremos aparecer solo en .com, .edu, .es...que sin duda son una forma muy grande de segmentar. Con los nuevos dominios (.store, .barcelona, .berlin, .run…) esta segmentación se puede volver más apetitosa pero la realidad, en el año 2016, es diferente.

 

Son muchos que se están aprovechando de los nuevos dominios para adquirir nombres Exact Match y hacer páginas para engañar en Display. En concreto, he detectado algunos nuevos dominios como los .xyz y .tv que básicamente siempre son sitios que perjudican a las campañas display.

 

En honor a la verdad, también el dominio .info, quizá por su bajo precio, es un dominio elegido por muchos webmasters para hacer páginas de phishing, virales y anuncios escondidos en vídeos.

 

Un ejemplo fueron estos sitios, todos registrados por el mismo usuario, y que ya no existen:

viral.jpg

 

Un ejemplo de esta situación son estas webs donde han aparecido anuncios de un cliente:

Screen Shot 2016-09-01 at 9.18.51 PM.png

Muchas de estas webs desaparecen ante de 6 meses - de hecho tenía una lista pero todos están ya eliminados y no puedo enseñarla-, probablemente porque usan los trucos que ya denunció @enriquedelvalle en este otro post de la Comunidad.

 

Un Script reactivo contra las extensiones más fraudulentas

 

Por desgracia, proactivamente no se puede hacer nada y hasta ahora había que estar haciendo un barrido de ubicaciones automáticas casi a diario para no malgastar dinero.

 

Lo que sí podemos es ser reactivos y, navegando por la red, he descubierto este script que permite agregar como Exclusión de Ubicaciones a las urls con los dominios que digamos una vez que nuestro anuncio ha aparecido en una de estas webs.

 

 

/**
 * Removes placements ending in the tlds xyz, tk, and download.
 * @author Dawson Reid
 * @author Andrew Breen
 */

// Top Level Domains to exclude

var TLDs = '.xyz, .tk, .download';

// -------------------------------------------------------

function removePlacementByDomain (domain) {
  var placementSelector = AdWordsApp.display().placements()
  .withCondition("PlacementUrl CONTAINS '" + domain + "'")
  .withCondition("CampaignStatus != REMOVED");

  var placementIterator = placementSelector.get();
  while (placementIterator.hasNext()) {
    var placement = placementIterator.next();
    var placementUrl = placement.getUrl();
    //Logger.log(placementUrl);

    var campaign = placement.getCampaign();
    var excludeOperation = campaign.display().newPlacementBuilder().withUrl(placementUrl).exclude();
    if (!excludeOperation.isSuccessful()) {
      Logger.log("Could not exclude : " + placementUrl);
    }
  }
}

function run () {
  TLDs.split(',').map(function (tld) {
    return tld.trim();
  }).forEach(function (domain) {
    removePlacementByDomain(domain);
  });
}

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();
  });
}

function main () {
  try {
    var accountIterator = MccApp.accounts().orderBy('Name').get();
    Logger.log('Total number of accounts under MCC : ' + accountIterator.totalNumEntities());

    var accountIds = [];
    while (accountIterator.hasNext()) {
      var account = accountIterator.next();
      accountIds.push(account.getCustomerId());
    }
    var parallelIds = accountIds.slice(0, 50);
    var sequentialIds = accountIds.slice(50);
    // execute accross accounts
    MccApp.accounts()
      .withIds(parallelIds)
      .executeInParallel('run');
    if (sequentialIds.length > 0) {
      executeInSequence(sequentialIds, run);
    }
  } catch (exception) {
    // not an Mcc
    Logger.log('Running on non-MCC account.');
    run();
  }
}

 

El script funciona tanto a nivel individual como MCC, por lo que el poder reactivo puede ser exponencialmente grande.

 

El cambio que debemos de realizar es poner en esta línea:

var TLDs = '.xyz, .tk, .download'

Las extensiones de dominios que no queremos. Yo además de los que vienen por defecto he añadido otros como .sexy, .info, .top, .ovh entre otros. Y además, por problemas que he tenido a pesar de señalar como segmentación el idioma español, también he tenido que añadir dominios territoriales como el .ro, .ru que no tienen contenido en nuestro idioma pero se han colado.

 

Web oficial de Outshine, autor

Github con el código

 

Mi recomendación es programarlo para que funcione cada hora. Semanalmente echo un ojo a los logs para ver qué dominios ha expulsado y, por ahora, no he encontrado ninguno interesante. Pero no por ello dejaré de revisar de vez en cuando, pero ahora pierdo menos tiempo en estos dominios, mucho menos tiempo.

 

Espero que os funcione. 


 

por Luan Rodriguez
octubre 2016

Muchísimas gracias a todos por sus aportes!

Albert, me ha servido mucho los agregados que has compartido.

El de agregar a una lista compartida no me funcionaba ya que detectaba que la lista ya estaba creada, asique lo modifiqué para que esto no suceda:

 

  var PlacementList = 'Dominios Spam';
  
  var placementIterator = placementSelector.get();
  while (placementIterator.hasNext()) {
    var placement = placementIterator.next();
    var placementUrl = placement.getUrl();
    Logger.log(placementUrl);
    
 var excludedPlacementListOperation =
     AdWordsApp.newExcludedPlacementListBuilder()
         .withName(PlacementList);
   
   function agregarUbicaciones() {
    var excludedPlacementList = excludedPlacementListOperation;
    excludedPlacementList.addExcludedPlacement(placementUrl);
   }

Saludos!

por Luan Rodriguez
octubre 2016

Ok, no me está funcionando bien, si alguien quiere corregirlo es muy bienvenido Emoticono feliz


Gracias!

por Albert Berlanga
octubre 2016

Hola @Luan Rodriguez en mi post puse como añadirlo a una lista ya existente pero mi comentario no queda claro y al no poder editarlo...

 

Esta parte añade la ubicación a una lista ya creada. Lo probé cuando hice el post y me funcionaba ok. Alguien más ha podido probarlo?

 

    var PlacementList = 'nombre de la lista de exclusión';
  
  var placementIterator = placementSelector.get();
  while (placementIterator.hasNext()) {
    var placement = placementIterator.next();
    var placementUrl = placement.getUrl();
    Logger.log(placementUrl);
    
   var excludedPlacementListIterator =
     AdWordsApp.excludedPlacementLists()
     .withCondition('Name = ' + PlacementList)
     .get();
   
    if (excludedPlacementListIterator.totalNumEntities() == 1) {
    var excludedPlacementList = excludedPlacementListIterator.next();
      Logger.log(excludedPlacementList);
    excludedPlacementList.addExcludedPlacement(placementUrl);
   }  

Saludos,

por Luan Rodriguez
octubre 2016

@Albert Berlanga me da este error:

Parsing error. Please check your selector. (line 28)

 

Estoy utilizando este código entero: 

 

var TLDs = '.xyz, .tk, .download, jueg, empl, trabaj, game, gamin, curio, viral, .info';

// -------------------------------------------------------

function removePlacementByDomain (domain) {
  var placementSelector = AdWordsApp.display().placements()
  .withCondition("PlacementUrl CONTAINS '" + domain + "'")
  .withCondition("PlacementUrl DOES_NOT_CONTAIN 'host, servidor, domain, dominio, ssl, https' ")
  .withCondition("Conversions = 0")
  .withCondition("ViewThroughConversions = 0")
  .withCondition("CampaignStatus != REMOVED")
  .forDateRange('LAST_30_DAYS');

  var placementIterator = placementSelector.get();
  while (placementIterator.hasNext()) {
    var placement = placementIterator.next();
    var placementUrl = placement.getUrl();
    Logger.log(placementUrl);

       var PlacementList = 'Dominios Spam';
  
  var placementIterator = placementSelector.get();
  while (placementIterator.hasNext()) {
    var placement = placementIterator.next();
    var placementUrl = placement.getUrl();
    Logger.log(placementUrl);
    
   var excludedPlacementListIterator =
     AdWordsApp.excludedPlacementLists()
     .withCondition('Name = ' + PlacementList)
     .get();
   
    if (excludedPlacementListIterator.totalNumEntities() == 1) {
    var excludedPlacementList = excludedPlacementListIterator.next();
      Logger.log(excludedPlacementList);
    excludedPlacementList.addExcludedPlacement(placementUrl);
   }  
   }
   }
  }

function run () {
  TLDs.split(',').map(function (tld) {
    return tld.trim();
  }).forEach(function (domain) {
    removePlacementByDomain(domain);
  });
}

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();
  });
}

function main () {
  try {
    var accountIterator = MccApp.accounts().orderBy('Name').get();
    Logger.log('Total number of accounts under MCC : ' + accountIterator.totalNumEntities());

    var accountIds = [];
    while (accountIterator.hasNext()) {
      var account = accountIterator.next();
      accountIds.push(account.getCustomerId());
    }
    var parallelIds = accountIds.slice(0, 50);
    var sequentialIds = accountIds.slice(50);
    // execute accross accounts
    MccApp.accounts()
      .withIds([ID de la cuenta])
      .executeInParallel('run');
    if (sequentialIds.length > 0) {
      executeInSequence(sequentialIds, run);
    }
  } catch (exception) {
    // not an Mcc
    Logger.log('Running on non-MCC account.');
    run();
  }
}

Removí el ID de la cuenta para mantener la privacidad.


Muchísimas gracias por la ayuda!

por Albert Berlanga
noviembre 2016

Hola,

 

He copiado exactamente tu código cambiando

 

.withIds([ID de la cuenta])

por:

 

     .withIds(parallelIds)

y no da error. Yo lo estoy usando a nivel de cuenta, no de MCC. Pero vamos... que esa parte no debería influir. No soy campaz de reproducir tu error.

 

Saludos,