Práticas recomendadas

Esta página aborda várias práticas recomendadas para o desenvolvimento com scripts do Google Ads.

Seletores

Filtre com seletores

Quando possível, use filtros para solicitar somente as entidades de que você precisa. A aplicação de filtros adequados proporciona estas vantagens:

  • O código é mais simples e mais fácil de entender.
  • O script é executado muito mais rápido.

Compare os snippets de código a seguir:

Abordagem de codificação Snippet de código
Filtrar usando seletores (recomendado)
var keywords = AdsApp.keywords()
    .withCondition('Clicks > 10')
    .forDateRange('LAST_MONTH')
    .get();
while (keywords.hasNext()) {
  var keyword = keywords.next();
  // Do work here.
}
Filtrar código (não recomendado)
var keywords = AdsApp.keywords().get();

while (keywords.hasNext()) {
  var keyword = keywords.next();
  var stats = keyword.getStatsFor(
      'LAST_MONTH');
  if (stats.getClicks() > 10) {
    // Do work here.
  }
}

A segunda abordagem não é recomendada porque tenta recuperar a lista de todas as palavras-chave da sua conta apenas para aplicar um filtro a ela.

Evite atravessar a hierarquia de campanhas

Quando você quiser recuperar entidades em um nível específico, use um método de coleta naquele nível em vez de percorrer toda a hierarquia da campanha. Além de ser mais simples, isso também vai melhorar o desempenho: o sistema não vai precisar ler todas as campanhas e grupos de anúncios de forma desnecessária.

Compare os snippets de código a seguir que recuperam todos os anúncios da sua conta:

Abordagem de codificação Snippet de código
Usar o método de coleta adequado (recomendado)

var ads = AdsApp.ads();

Percorrer a hierarquia (não recomendado)
var campaigns = AdsApp.campaigns().get();
while (campaigns.hasNext()) {
  var adGroups = campaigns.next().
      adGroups().get();
  while (adGroups.hasNext()) {
    var ads = adGroups.next().ads().get();
    // Do your work here.
  }
}

A segunda abordagem não é recomendada, porque tenta buscar hierarquias inteiras de objetos (campanhas, grupos de anúncios), enquanto apenas anúncios são necessários.

Use métodos do assistente de acesso pai específicos

Às vezes você precisa obter a entidade mãe de um objeto recuperado. Nesse caso, use um método do acessador fornecido em vez de buscar hierarquias inteiras.

Compare os seguintes snippets de código que recuperam os grupos de anúncios que têm anúncios de texto com mais de 50 cliques no mês passado:

Abordagem de codificação Snippet de código
Usar o método de acesso pai apropriado (recomendado)
var ads = AdsApp.ads()
    .withCondition('Clicks > 50')
    .forDateRange('LAST_MONTH')
    .get();

while (ads.hasNext()) {
  var ad = ads.next();
  var adGroup = ad.getAdGroup();
  var campaign = ad.getCampaign();
  // Store (campaign, adGroup) to an array.
}
Percorrer a hierarquia (não recomendado)
var campaigns = AdsApp.campaigns().get();
while (campaigns.hasNext()) {
  var adGroups = campaigns.next()
      .adGroups()
      .get();
  while (adGroups.hasNext()) {
    var ads = adGroups.ads()
       .withCondition('Clicks > 50')
       .forDateRange('LAST_MONTH')
       .get();
    if (ads.totalNumEntities() > 0) {
      // Store (campaign, adGroup) to an array.
    }
  }
}

A segunda abordagem não é recomendada, porque busca toda a campanha e as hierarquias de grupos de anúncios na sua conta, enquanto você precisa apenas de um subconjunto de campanhas e grupos de anúncios associado ao seu conjunto de anúncios. A primeira abordagem se restringe a buscar apenas a coleção de anúncios relevante e usa um método adequado para acessar os objetos pai.

Use filtros pai específicos

Para acessar entidades em uma campanha ou um grupo de anúncios específico, use um filtro específico no seletor em vez de buscar e percorrer uma hierarquia.

Compare os seguintes snippets de código que recuperam a lista de anúncios de texto em uma campanha e um grupo de anúncios especificados com mais de 50 cliques no mês passado.

Abordagem de codificação Snippet de código
Usar filtros de nível pai adequados (recomendado)
var ads = AdsApp.ads()
    .withCondition('CampaignName = "Campaign 1"')
    .withCondition('AdGroupName = "AdGroup 1"')
    .withCondition('Clicks > 50')
    .forDateRange('LAST_MONTH')
    .get();

while (ads.hasNext()) {
  var ad = ads.next();
  var adGroup = ad.getAdGroup();
  var campaign = ad.getCampaign();
  // Store (campaign, adGroup, ad) to
  // an array.
}
Percorrer a hierarquia (não recomendado)
var campaigns = AdsApp.campaigns()
    .withCondition('Name = "Campaign 1"')
    .get();

while (campaigns.hasNext()) {
  var adGroups = campaigns.next()
      .adGroups()
      .withCondition('Name = "AdGroup 1"')
      .get();
  while (adGroups.hasNext()) {
    var ads = adGroups.ads()
       .withCondition('Clicks > 50')
       .forDateRange('LAST_MONTH')
       .get();
    while (ads.hasNext()) {
      var ad = ads.next();
      // Store (campaign, adGroup, ad) to
      // an array.
    }
  }
}

A segunda abordagem não é recomendada, porque ela faz iterações na hierarquia de campanhas e grupos de anúncios na sua conta, enquanto você precisa apenas de um conjunto selecionado de anúncios, além das campanhas e dos grupos de anúncios principais deles. A primeira abordagem limita a iteração à lista de anúncios aplicando um filtro específico para entidades mães no seletor.

Use IDs para filtrar quando possível

Ao filtrar entidades, é preferível filtrar por IDs em vez de outros campos.

Considere os snippets de código a seguir que selecionam uma campanha.

Abordagem de codificação Snippet de código
Filtrar por ID (recomendado)
var campaign = AdsApp.campaigns()
    .withIds([12345])
    .get()
    .next();
Filtrar por nome (menos ideal)
var campaign = AdsApp.campaigns()
    .withCondition('Name="foo"')
    .get()
    .next();

A segunda abordagem é menos ideal, pois estamos filtrando por um campo que não é o ID.

Filtre por IDs parentais quando possível

Ao selecionar uma entidade, filtre por IDs pai sempre que possível. Isso vai tornar suas consultas mais rápidas, limitando a lista de entidades que estão sendo recuperadas pelos servidores ao filtrar os resultados.

Considere o snippet de código a seguir, que recupera um grupo de anúncios pelo ID. Suponha que o ID da campanha principal seja conhecido.

Abordagem de codificação Snippet de código
Filtrar por IDs de campanhas e grupos de anúncios (recomendado)
var adGroup = AdsApp.adGroups()
    .withIds([12345])
    .withCondition('CampaignId="54678"')
    .get()
    .next();
Filtrar apenas pelo ID do grupo de anúncios (menos ideal)
var adGroup = AdsApp.adGroups()
    .withIds([12345])
    .get()
    .next();

Embora os dois snippets de código apresentem resultados idênticos, a filtragem adicional no snippet de código 1 usando um ID pai (CampaignId="54678") torna o código mais eficiente, restringindo a lista de entidades que o servidor precisa iterar ao filtrar os resultados.

Use rótulos quando existirem muitas condições de filtragem

Quando você tem muitas condições de filtragem, convém criar um rótulo para as entidades processadas e usá-lo para filtrar as entidades.

Considere o snippet de código a seguir, que recupera uma lista de campanhas pelo nome.

Abordagem de codificação Snippet de código
Usar um rótulo (recomendado)
var label = AdsApp.labels()
    .withCondition('Name = "My Label"')
    .get()
    .next();
var campaigns = label.campaigns.get();
while (campaigns.hasNext()) {
  var campaign = campaigns.next();
  // Do more work
}
Criar seletores complexos (não recomendado)
var campaignNames = [‘foo’, ‘bar’, ‘baz’];

for (var i = 0; i < campaignNames.length; i++) {
  campaignNames[i] = '"' + campaignNames[i] + '"';
}

var campaigns = AdsApp.campaigns
    .withCondition('CampaignName in [' + campaignNames.join(',') + ']')
    .get();

while (campaigns.hasNext()) {
  var campaign = campaigns.next();
  // Do more work.
}

Embora os dois snippets de código ofereçam um nível de desempenho semelhante, a segunda abordagem tende a gerar um código mais complexo à medida que o número de condições no seletor aumenta. Também é mais fácil aplicar o rótulo a uma nova entidade do que editar o script para incluir uma nova entidade.

Limite o número de condições na sua cláusula IN

Ao executar scripts, um caso de uso comum é gerar um relatório para uma lista de entidades. Os desenvolvedores geralmente fazem isso construindo uma consulta AWQL muito longa que filtra os IDs de entidade usando uma cláusula IN. Essa abordagem funciona bem quando o número de entidades é limitado. No entanto, à medida que o comprimento da consulta aumenta, a performance do script se deteriora por dois motivos:

  • A análise de uma consulta mais longa demora mais.
  • Cada ID adicionado a uma cláusula IN é uma condição extra a ser avaliada e, portanto, leva mais tempo.

Nessas condições, é preferível aplicar um rótulo às entidades e filtrar por LabelId.

Abordagem de codificação Snippet de código
Aplicar um rótulo e filtrar por labelID (recomendado)
// The label applied to the entity is "Report Entities"
var label = AdsApp.labels()
    .withCondition('LabelName contains "Report Entities"')
    .get()
    .next();

var report = AdsApp.report('SELECT AdGroupId, Id, Clicks, ' +
    'Impressions, Cost FROM KEYWORDS_PERFORMANCE_REPORT ' +
    'WHERE LabelId = "' + label.getId() + '"');
Criar uma consulta longa usando a cláusula IN (não recomendada)
var report = AdsApp.report('SELECT AdGroupId, Id, Clicks, ' +
    'Impressions, Cost FROM KEYWORDS_PERFORMANCE_REPORT WHERE ' +
    'AdGroupId IN (123, 456) and Id in (123,345, 456…)');

Atualizações da conta

Alterações em lote

Quando você faz alterações em uma entidade do Google Ads, os scripts do Google Ads não executam a alteração imediatamente. Em vez disso, ele tenta combinar várias mudanças em lotes para emitir uma única solicitação que faz várias mudanças. Essa abordagem acelera seus scripts e reduz a carga nos servidores do Google Ads. No entanto, há alguns padrões de código que forçam os scripts do Google Ads a limpar o lote de operações com frequência, fazendo com que o script seja executado lentamente.

Considere o script a seguir que atualiza os lances de uma lista de palavras-chave.

Abordagem de codificação Snippet de código
Acompanhar os elementos atualizados (recomendado)
var keywords = AdsApp.keywords()
    .withCondition('Clicks > 50')
    .withCondition('CampaignName = "Campaign 1"')
    .withCondition('AdGroupName = "AdGroup 1"')
    .forDateRange('LAST_MONTH')
    .get();

var list = [];
while (keywords.hasNext()) {
  var keyword = keywords.next();
  keyword.bidding().setCpc(1.5);
  list.push(keyword);
}

for (var i = 0; i < list.length; i++) {
  var keyword = list[i];
  Logger.log('%s, %s', keyword.getText(),
      keyword.bidding().getCpc());
}
Recuperar elementos atualizados em um loop apertado (não recomendado)
var keywords = AdsApp.keywords()
    .withCondition('Clicks > 50')
    .withCondition('CampaignName = "Campaign 1"')
    .withCondition('AdGroupName = "AdGroup 1"')
    .forDateRange('LAST_MONTH')
    .get();

while (keywords.hasNext()) {
  var keyword = keywords.next();
  keyword.bidding().setCpc(1.5);
  Logger.log('%s, %s', keyword.getText(),
      keyword.bidding().getCpc());
}

A segunda abordagem não é recomendada, já que a chamada para keyword.bidding().getCpc() força os scripts do Google Ads a limpar a operação setCpc() e executar apenas uma operação por vez. A primeira abordagem, embora semelhante à segunda, tem o benefício adicional de oferecer suporte a lotes, já que a chamada getCpc() é feita em um loop separado do que é chamado setCpc().

Use criadores quando possível

Os scripts do Google Ads são compatíveis com duas maneiras de criar novos objetos: criadores e métodos de criação. Os criadores são mais flexíveis do que os métodos de criação, porque eles fornecem acesso ao objeto criado a partir da chamada de API.

Considere estes snippets de código:

Abordagem de codificação Snippet de código
Usar builders (recomendado)
var operation = adGroup.newKeywordBuilder()
    .withText('shoes')
    .build();
var keyword = operation.getResult();
Usar métodos de criação (não recomendado)
adGroup.createKeyword('shoes');
var keyword = adGroup.keywords()
    .withCondition('KeywordText="shoes"')
    .get()
    .next();

A segunda abordagem não é a preferida devido à operação de seleção extra envolvida na recuperação da palavra-chave. Além disso, os métodos de criação também foram descontinuados.

No entanto, lembre-se de que os criadores, quando usados incorretamente, podem impedir que os scripts do Google Ads façam operações em lote.

Considere os seguintes snippets de código que criam uma lista de palavras-chave e imprimem o ID das palavras-chave recém-criadas:

Abordagem de codificação Snippet de código
Acompanhar os elementos atualizados (recomendado)
var keywords = [‘foo’, ‘bar’, ‘baz’];

var list = [];
for (var i = 0; i < keywords.length; i++) {
  var operation = adGroup.newKeywordBuilder()
      .withText(keywords[i])
      .build();
  list.push(operation);
}

for (var i = 0; i < list.length; i++) {
  var operation = list[i];
  var result = operation.getResult();
  Logger.log('%s %s', result.getId(),
      result.getText());
}
Recuperar elementos atualizados em um loop apertado (não recomendado)
var keywords = [‘foo’, ‘bar’, ‘baz’];

for (var i = 0; i < keywords.length; i++) {
  var operation = adGroup.newKeywordBuilder()
      .withText(keywords[i])
      .build();
  var result = operation.getResult();
  Logger.log('%s %s', result.getId(),
      result.getText());
}

A segunda abordagem não é a preferida porque chama operation.getResult() no mesmo loop que cria a operação, forçando os scripts do Google Ads a executar uma operação por vez. A primeira abordagem, embora semelhante, permite agrupamento, já que chamamos operation.getResult() em um loop diferente de onde ele foi criado.

Considere usar uploads em massa para atualizações grandes

Uma tarefa comum que os desenvolvedores realizam é gerar relatórios e atualizar propriedades de entidade, como lances de palavras-chave, com base nos valores de performance atuais. Quando você precisa atualizar um grande número de entidades, os uploads em massa tendem a oferecer melhor desempenho. Por exemplo, considere os seguintes scripts que aumentam o MaxCpc das palavras-chave com TopImpressionPercentage > 0.4 no último mês:

Abordagem de codificação Snippet de código
Usar o upload em massa (recomendado)

var report = AdsApp.report(
  'SELECT AdGroupId, Id, CpcBid FROM KEYWORDS_PERFORMANCE_REPORT ' +
  'WHERE TopImpressionPercentage > 0.4 DURING LAST_MONTH');

var upload = AdsApp.bulkUploads().newCsvUpload([
  report.getColumnHeader('AdGroupId').getBulkUploadColumnName(),
  report.getColumnHeader('Id').getBulkUploadColumnName(),
  report.getColumnHeader('CpcBid').getBulkUploadColumnName()]);
upload.forCampaignManagement();

var reportRows = report.rows();
while (reportRows.hasNext()) {
  var row = reportRows.next();
  row['CpcBid'] = row['CpcBid'] + 0.02;
  upload.append(row.formatForUpload());
}

upload.apply();
Selecionar e atualizar as palavras-chave por ID (menos ideal)
var reportRows = AdsApp.report('SELECT AdGroupId, Id, CpcBid FROM ' +
    'KEYWORDS_PERFORMANCE_REPORT WHERE TopImpressionPercentage > 0.4 ' +
    ' DURING LAST_MONTH')
    .rows();

var map = {
};

while (reportRows.hasNext()) {
  var row = reportRows.next();
  var adGroupId = row['AdGroupId'];
  var id = row['Id'];

  if (map[adGroupId] == null) {
    map[adGroupId] = [];
  }
  map[adGroupId].push([adGroupId, id]);
}

for (var key in map) {
  var keywords = AdsApp.keywords()
      .withCondition('AdGroupId="' + key + '"')
      .withIds(map[key])
      .get();

  while (keywords.hasNext()) {
    var keyword = keywords.next();
    keyword.bidding().setCpc(keyword.bidding().getCpc() + 0.02);
  }
}

Embora a segunda abordagem ofereça uma performance muito boa, a primeira é a preferida neste caso, porque

  • Os scripts do Google Ads têm um limite no número de objetos que podem ser recuperados ou atualizados em uma única execução, e as operações de seleção e atualização na segunda abordagem contam para esse limite.

  • Os uploads em massa têm limites mais altos em termos do número de entidades que podem ser atualizadas e do tempo de execução geral.

Agrupe seus uploads em massa por campanhas

Ao criar seus uploads em massa, tente agrupar as operações pela campanha mãe. Isso aumenta a eficiência e diminui a chance de alterações conflitantes / erros de simultaneidade.

Considere duas tarefas de upload em massa executadas em paralelo. Uma pausa os anúncios em um grupo de anúncios, e a outra ajusta os lances de palavras-chave. Mesmo que as operações não estejam relacionadas, elas podem ser aplicadas a entidades do mesmo grupo de anúncios (ou dois grupos de anúncios diferentes na mesma campanha). Quando isso acontece, o sistema bloqueia a entidade pai (o grupo de anúncios ou a campanha compartilhada), causando o bloqueio das tarefas de upload em massa.

Os scripts do Google Ads podem otimizar a execução em uma única tarefa de upload em massa. Portanto, o mais simples é executar apenas uma tarefa de upload em massa por conta por vez. Se você decidir fazer mais de um upload em massa por conta, verifique se os uploads em massa funcionam em uma lista de campanhas mutuamente exclusivas (e entidades filhas) para uma performance ideal.

Relatórios

Use relatórios para buscar estatísticas

Quando você quer recuperar grandes quantidades de entidades e as estatísticas delas, é melhor usar relatórios em vez de métodos padrão do AdsApp. O uso de relatórios é preferido pelos seguintes motivos:

  • Os relatórios têm melhor desempenho em consultas grandes.
  • Os relatórios não atingem cotas de busca normais.

Compare os seguintes snippets de código que buscam os cliques, as impressões, o custo e o texto de todas as palavras-chave que receberam mais de 50 cliques no mês passado:

Abordagem de codificação Snippet de código
Usar relatórios (recomendado)
  report = AdsApp.search(
      'SELECT ' +
      '   ad_group_criterion.keyword.text, ' +
      '   metrics.clicks, ' +
      '   metrics.cost_micros, ' +
      '   metrics.impressions ' +
      'FROM ' +
      '   keyword_view ' +
      'WHERE ' +
      '   segments.date DURING LAST_MONTH ' +
      '   AND metrics.clicks > 50');
  while (report.hasNext()) {
    var row = report.next();
    Logger.log('Keyword: %s Impressions: %s ' +
        'Clicks: %s Cost: %s',
        row.adGroupCriterion.keyword.text,
        row.metrics.impressions,
        row.metrics.clicks,
        row.metrics.cost);
  }
Usar iteradores de AdsApp (não recomendado)
var keywords = AdsApp.keywords()
    .withCondition('metrics.clicks > 50')
    .forDateRange('LAST_MONTH')
    .get();
while (keywords.hasNext()) {
  var keyword = keywords.next();
  var stats = keyword.getStatsFor('LAST_MONTH');
  Logger.log('Keyword: %s Impressions: %s ' +
      'Clicks: %s Cost: %s',
      keyword.getText(),
      stats.getImpressions(),
      stats.getClicks(),
      stats.getCost());
}

A segunda abordagem não é a preferida porque itera as palavras-chave e recupera as estatísticas uma entidade por vez. Os relatórios são mais rápidos nesse caso, porque extraem todos os dados em uma única chamada e os transmitem conforme necessário. Além disso, as palavras-chave recuperadas na segunda abordagem são contabilizadas na cota do script com relação ao número de entidades recuperadas usando uma chamada get().

Usar a pesquisa em vez do relatório

O método de relatório foi criado para a infraestrutura antiga e vai gerar resultados em um formato simples, mesmo que você esteja usando o GAQL. Isso significa que é necessário transformar os resultados da consulta para corresponder ao estilo antigo, que não é aceito em todos os campos e adiciona sobrecarga a cada chamada.

Sugerimos que você use a pesquisa em vez de aproveitar todos os recursos dos novos relatórios da Google Ads API.

Dar preferência ao GAQL em vez do AWQL

Embora o AWQL ainda tenha suporte em consultas de relatórios e chamadas withCondition, ele é executado em uma camada de tradução que não tem compatibilidade total com o AWQL verdadeiro. Para ter controle total sobre suas consultas, use o GAQL.

Se você tiver consultas AWQL existentes que gostaria de traduzir, temos uma Ferramenta de migração de consultas para ajudar.

Não selecionar mais linhas do que o necessário

A velocidade de execução dos relatórios (e seletores) é baseada no número total de linhas que seriam retornadas pelo relatório, independentemente de você iterar por elas. Isso significa que você precisa sempre usar filtros específicos para minimizar ao máximo o conjunto de resultados de acordo com seu caso de uso.

Por exemplo, digamos que você queira encontrar grupos de anúncios com lances fora de um intervalo específico. Seria mais rápido fazer duas consultas separadas, uma para lances abaixo do limite inferior e outra para lances acima do limite superior, do que buscar todos os grupos de anúncios e ignorar aqueles em que você não tem interesse.

Abordagem de codificação Snippet de código
Usar duas consultas (recomendado)
var adGroups = []
var report = AdsApp.search(
    'SELECT ad_group.name, ad_group.cpc_bid_micros' +
    ' FROM ad_group WHERE ad_group.cpc_bid_micros < 1000000');

while (report.hasNext()) {
  var row = report.next();
  adGroups.push(row.adGroup);
}
var report = AdsApp.search(
    'SELECT ad_group.name, ad_group.cpc_bid_micros' +
    ' FROM ad_group WHERE ad_group.cpc_bid_micros > 2000000');

while (report.hasNext()) {
  var row = report.next();
  adGroups.push(row.adGroup);
}
Filtrar de uma consulta genérica (não recomendado)
var adGroups = []
var report = AdsApp.search(
    'SELECT ad_group.name, ad_group.cpc_bid_micros' +
    ' FROM ad_group');

while (report.hasNext()) {
  var row = report.next();
  var cpcBidMicros = row.adGroup.cpcBidMicros;
  if (cpcBidMicros < 1000000 || cpcBidMicros > 2000000) {
    adGroups.push(row.adGroup);
  }
}

Scripts do Ad Manager (MCC)

Prefira executar em paralelo em vez de em série

Ao escrever scripts para contas de administrador, use executeInParallel() em vez da execução em série quando possível. executeInParallel() dá ao seu script mais tempo de processamento (até uma hora) e até 30 minutos por conta processada, em vez de 30 minutos combinados para execução em série. Consulte nossa página de limites para mais detalhes.

Planilhas

Use operações em lote ao atualizar planilhas

Ao atualizar planilhas, tente usar os métodos de operação em massa (por exemplo, getRange()) em vez de métodos que atualizam uma célula por vez.

Considere o snippet de código abaixo, que gera um padrão fractal em uma planilha.

Abordagem de codificação Snippet de código
Atualizar um intervalo de células em uma única chamada (recomendado)
var colors = new Array(100);
for (var y = 0; y < 100; y++) {
  xcoord = xmin;
  colors[y] = new Array(100);
  for (var x = 0; x < 100; x++) {
    colors[y][x] = getColor_(xcoord, ycoord);
    xcoord += xincrement;
  }
  ycoord -= yincrement;
}
sheet.getRange(1, 1, 100, 100).setBackgroundColors(colors);
Atualizar uma célula por vez (não recomendado)
var cell = sheet.getRange('a1');
for (var y = 0; y < 100; y++) {
  xcoord = xmin;
  for (var x = 0; x < 100; x++) {
    var c = getColor_(xcoord, ycoord);
    cell.offset(y, x).setBackgroundColor(c);
    xcoord += xincrement;
  }
  ycoord -= yincrement;
  SpreadsheetApp.flush();
}

Enquanto as Planilhas Google tentam otimizar o segundo snippet de código armazenando valores em cache, elas ainda apresentam um desempenho ruim em comparação com o primeiro snippet por causa do número de chamadas de API feitas.