Práticas recomendadas

Esta página aborda várias práticas recomendadas para 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 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 ela 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 determinado nível, use um método de coleta nesse nível em vez de percorrer toda a hierarquia da campanha. Além de ser mais simples, a performance é muito melhor: o sistema não precisa ler todas as campanhas e grupos de anúncios desnecessariamente.

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 apropriado (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 ela tenta buscar hierarquias inteiras de objetos (campanhas, grupos de anúncios), enquanto apenas os anúncios são obrigató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 snippets de código a seguir 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 do acessador pai 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 ela busca todas as hierarquias de campanha e grupo 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 se restringe a buscar apenas a coleção de anúncios relevante e usa um método apropriado para acessar os objetos pais.

Use filtros pai específicos

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

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

Abordagem de codificação Snippet de código
Usar filtros adequados no nível da mãe (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 da campanha e do grupo de anúncios na sua conta, enquanto você só precisa de um conjunto selecionado de anúncios e das campanhas e grupos de anúncios principais deles. A primeira abordagem limita a iteração à lista de anúncios aplicando um filtro específico para entidades pai no seletor.

Use IDs para filtrar quando possível

Ao filtrar entidades, é preferível filtrar por entidades pelos IDs delas em vez de por 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 torna 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 por ID do grupo de anúncios (menos ideal)
var adGroup = AdsApp.adGroups()
    .withIds([12345])
    .get()
    .next();

Mesmo que os dois snippets de código forneçam resultados idênticos, a filtragem extra no snippet 1 que usa 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 filtrá-las.

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. Geralmente, os desenvolvedores 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 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 a mais a ser avaliada e, portanto, leva mais tempo.

Nessas condições, é preferível aplicar um rótulo às entidades e, em seguida, 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 uma 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 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 alterações em lotes para emitir uma única solicitação que faz várias alterações. 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 transferir o lote de operações com frequência, fazendo com que a execução do script fique lenta.

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());
}
Extrair elementos atualizados em uma repetição curta (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 transferir a operação setCpc() e executar apenas uma operação por vez. A primeira abordagem, embora seja semelhante à segunda, tem a vantagem de oferecer suporte a 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 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 que os métodos de criação, já que eles dão acesso ao objeto criado com a 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 façam operações em lote.

Considere os seguintes snippets de código que criam uma lista de palavras-chave e imprime 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());
}
Extrair elementos atualizados em uma repetição curta (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 ideal porque ela 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 seja semelhante, permite o agrupamento em lote, já que chamamos "operation.getResult()" em um loop diferente daquele em que 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 entidades (por exemplo, lances de palavra-chave) com base nos valores de desempenho 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 CPC máx. de 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 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 um desempenho muito bom, a primeira é a preferida nesse caso porque

  • Os scripts do Google Ads têm um limite quanto ao número de objetos que podem ser recuperados ou atualizados em uma única execução, e as operações selecionar e atualizar na segunda abordagem são contabilizadas nesse limite.

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

Agrupe seus uploads em massa por campanhas

Ao criar seus uploads em massa, tente agrupar suas operações pela campanha principal. 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. 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 em dois grupos de anúncios diferentes na mesma campanha). Quando isso acontece, o sistema bloqueia a entidade pai (a campanha ou o grupo de anúncios compartilhado), fazendo com que as tarefas de upload em massa sejam bloqueadas.

Os scripts do Google Ads podem otimizar a execução em uma única tarefa de upload em massa. Assim, o mais simples a fazer é executar apenas uma tarefa de upload em massa por conta de cada vez. Se você decidir fazer mais de um upload em massa por conta, verifique se eles operam em uma lista de campanhas mutuamente exclusiva (e suas entidades filhas) para um desempenho ideal.

Relatórios

Use relatórios para buscar estatísticas

Para recuperar grandes quantidades de entidades e as estatísticas delas, geralmente é melhor usar relatórios em vez de métodos padrão do AdsApp. O uso de relatórios é preferível devido aos seguintes motivos:

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

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 último mês:

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 do 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 ideal porque ela faz iterações nas palavras-chave e recupera as estatísticas de uma entidade por vez. Os relatórios têm desempenho mais rápido nesse caso, já que 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 contabilizadas na cota do seu 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 gera resultados em um formato simples, mesmo que você use GAQL. Isso significa que ela precisa transformar os resultados da consulta para corresponder ao estilo antigo, 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 do novo relatório da Google Ads API.

Preferir GAQL a AWQL

Embora a AWQL ainda seja aceita em consultas de relatório 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 das suas consultas, use o GAQL.

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

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

A velocidade de execução de 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 o conjunto de resultados o máximo possível 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 a partir 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 Google Ads Manager (MCC)

Prefira executar em paralelo em vez de em série

Ao criar scripts para contas de administrador, use executeInParallel() em vez da execução em série, quando possível. executeInParallel() aumenta o tempo de processamento do script (até uma hora) e o processamento de até 30 minutos por conta (em vez de 30 minutos combinados para a 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 a seguir 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();
}

Embora as Planilhas Google tentem otimizar o segundo snippet de código armazenando valores em cache, elas ainda apresentam baixo desempenho em comparação com o primeiro snippet devido ao número de chamadas de API feitas.