Práticas recomendadas

Esta página aborda várias práticas recomendadas para desenvolver com os 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 no 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 na sua conta apenas para aplicar um filtro a ela.

Evite atravessar a hierarquia de campanhas

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

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

Abordagem de programaçã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 de acesso fornecido em vez de buscar hierarquias inteiras.

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

Abordagem de programação Snippet de código
Usar o método de acesso principal adequado (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 hierarquia de campanhas e grupos de anúncios na sua conta, enquanto você precisa apenas de um subconjunto de campanhas e grupos de anúncios associados ao seu conjunto de anúncios. A primeira abordagem restringe a busca apenas à 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 específicos com mais de 50 cliques no mês passado.

Abordagem de programação Snippet de código
Usar filtros de nível principal 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 itera na hierarquia de campanhas e grupos de anúncios na sua conta, enquanto você precisa apenas de um conjunto selecionado de anúncios e das campanhas e grupos de anúncios principais. A primeira abordagem limita a iteração à lista de anúncios aplicando um filtro específico para entidades principais no seletor.

Use IDs para filtrar quando possível

Ao filtrar entidades, é preferível usar os 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 acelerar suas consultas, limitando a lista de entidades recuperadas pelos servidores ao filtrar os resultados.

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

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

Embora os dois snippets de código forneçam resultados idênticos, a filtragem adicional no snippet 1 usando um ID principal (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, é uma boa ideia criar um rótulo para as entidades que você processa e usar esse rótulo para filtrar suas entidades.

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

Abordagem de programaçã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 criando 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 tamanho da consulta aumenta, o desempenho do script piora 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 programação Snippet de código
Aplicar um marcador 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 recomendado)
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 mudanças em uma entidade do Google Ads, os scripts do Google Ads não executam a mudança 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 torna seus scripts mais rápidos 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 liberar 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 porque a chamada para keyword.bidding().getCpc() força os scripts do Google Ads a liberar 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 ao agrupamento em lotes já que a chamada getCpc() é feita em um loop separado daquele em que setCpc() é chamado.

Use criadores quando possível

Os scripts do Google Ads oferecem duas maneiras de criar novos objetos: builders e métodos de criação. Os builders são mais flexíveis que os métodos de criação, já que dão acesso ao objeto criado pela 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 é recomendada 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 agrupem as operações.

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

Abordagem de programaçã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 é recomendada 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 o agrupamento em lote, 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 realizada pelos desenvolvedores é executar relatórios e atualizar propriedades de entidades (por exemplo, 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 um desempenho melhor. Por exemplo, considere os scripts a seguir, que aumentam o MaxCpc das palavras-chave cujo TopImpressionPercentage > 0.4 no último mês:

Abordagem de programaçã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 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 é preferível neste caso porque

  • Os scripts do Google Ads têm um limite para o 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 maiores em termos de número de entidades que podem ser atualizadas e tempo total de execução.

Agrupe seus uploads em massa por campanhas

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

Considere duas tarefas de upload em massa executadas em paralelo. Um pausa anúncios em um grupo de anúncios, e o outro ajusta os lances de palavra-chave. Mesmo que as operações não estejam relacionadas, elas podem ser aplicadas a entidades no mesmo grupo de anúncios (ou dois grupos diferentes na mesma campanha). Quando isso acontece, o sistema bloqueia a entidade principal (o grupo de anúncios ou a campanha compartilhada), fazendo com que as tarefas de upload em massa se bloqueiem mutuamente.

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 de cada vez. Se você decidir executar mais de um envio em massa por conta, verifique se eles operam em uma lista de campanhas (e entidades filhas) mutuamente exclusiva para otimizar a performance.

Relatórios

Use relatórios para buscar estatísticas

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

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

Compare os snippets de código a seguir, 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 programaçã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 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 é recomendada porque itera as palavras-chave e recupera as estatísticas uma entidade por vez. Os relatórios são executados mais rápido nesse caso porque buscam 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 contadas na cota do script para o 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 GAQL. Isso significa que ele precisa transformar os resultados da consulta para corresponder ao estilo antigo, o que não é compatível com todos os campos e adiciona sobrecarga a cada chamada.

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

Prefira a GAQL à AWQL

Embora a AWQL ainda seja compatível com consultas de relatórios e chamadas withCondition, ela é executada em uma camada de tradução que não tem compatibilidade total com a AWQL verdadeira. Para ter controle total sobre suas consultas, use a GAQL.

Se você tiver consultas AWQL que gostaria de traduzir, use a Ferramenta de migração de consultas.

Não selecione 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, independente de você iterar por elas. Isso significa que você sempre deve usar filtros específicos para minimizar o conjunto de resultados o máximo possível e corresponder ao 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 que não interessam.

Abordagem de programaçã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 Gerenciador de anúncios (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 serial sempre que 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 serial). 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 a seguir, que gera um padrão fractal em uma planilha.

Abordagem de programaçã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();
}

Embora o Google Sheets tente otimizar o segundo snippet de código armazenando valores em cache, ele ainda oferece uma performance ruim em comparação com o primeiro snippet devido ao número de chamadas de API feitas.