Práticas recomendadas

Esta página aborda várias práticas recomendadas de desenvolvimento 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 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 uma coleção nesse nível, em vez de atravessar toda a hierarquia da campanha. Em além de ser mais simples, ele também terá um desempenho muito melhor: o sistema não precisará ler desnecessariamente todas as campanhas e grupos de anúncios.

Compare os seguintes snippets de código que extraem 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, você deve usar um método de acessador fornecido em vez de buscar hierarquias inteiras.

Compare os snippets de código a seguir que recuperam os grupos de anúncios que ter 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 hierarquias de grupos de anúncios na sua conta, enquanto você precisa de apenas um subconjunto campanhas e grupos de anúncios associados ao seu conjunto de anúncios. A primeira abordagem se limita 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 adequados no nível pai (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 as 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 mães no seletor.

Use IDs para filtrar quando possível

Ao filtrar entidades, é preferível filtrar por entidades por 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, é uma boa ideia criar uma para as entidades processadas e use 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 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.
}

Ambos os snippets de código oferecem um nível de desempenho semelhante, tende a gerar códigos mais complexos, pois o número de condições em seu seletor aumenta. Também é mais fácil aplicar o rótulo a uma nova entidade 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 conseguem isso construindo um Consulta AWQL 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 e filtre 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 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 lotes, para que seja possível emitir uma única solicitação que faça várias alterações. Essa abordagem torna seus scripts mais rápidos e reduz a carga no Google Ads servidores. No entanto, alguns padrões de código forçam os scripts do Google Ads a transferir 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 curto (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 limpar 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 criação métodos. Os builders são mais flexíveis do que os métodos de criação, já que oferecem 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 é 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 builders, quando usados incorretamente, podem impedir que os scripts do Google Ads façam a agrupamento de operações.

Considere os snippets de código a seguir 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());
}
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 a performance. Por exemplo, considere os scripts a seguir que aumentam o CPC máximo das palavras-chave com TopImpressionPercentage > 0.4 no último mês:

Abordagem de codificação Snippet de código
Usar 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 é 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 maiores em termos de número de entidades que podem atualização e o tempo total de execução.

Agrupe seus uploads em massa por campanhas

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

Considere duas tarefas de upload em massa executadas em paralelo. Um deles pausa anúncios em um anúncio group; o outro 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), fazendo com que as tarefas de upload em massa se bloqueiem.

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 operam em uma lista de campanhas mutuamente exclusivas (e as 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 snippets de código a seguir que buscam métricas de cliques, impressões e Custo e 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 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 preferida porque itera as palavras-chave e recupera as estatísticas uma entidade por vez. Os relatórios apresentam desempenho mais rápido nesse já que ele busca todos os dados em uma única chamada e os transmite como obrigatórios. Além disso, as palavras-chave recuperadas na segunda abordagem são contabilizadas 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 o GAQL. Isso significa que ele precisa transformar os resultados da consulta para corresponder ao estilo antigo, que não é tem suporte em todos os campos e adiciona sobrecarga a cada chamada.

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

Prefira GAQL a AWQL

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

Se você tiver consultas AWQL que gostaria de traduzir, temos uma 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) baseia-se no número total de linhas que seriam retornadas pelo relatório, independentemente de você iterar elas. Isso significa que você sempre deve usar filtros específicos para minimizar ao máximo o conjunto de resultados de acordo com seu caso de uso.

Por exemplo, suponha que você queira encontrar grupos de anúncios com lances fora de em um intervalo específico. Seria mais rápido fazer duas consultas separadas, uma para lances abaixo do limite mínimo e outra para lances acima do limite máximo, 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 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 criar scripts para contas de administrador, use executeInParallel() de execução em série quando possível. O executeInParallel() deixa o script mais tempo de processamento (até uma hora) e até 30 minutos por conta processada em vez de 30 minutos combinados para a execução em série. Veja nossos 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 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 do Google tentam otimizar o segundo snippet de código armazenando em cache valores, ainda assim você terá um desempenho ruim em comparação com o primeiro snippet, devido com o número de chamadas de API feitas.