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. Aplicar filtros adequados tem os seguintes benefícios:
- 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 coleção nesse 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 precisará ler desnecessariamente todas as campanhas e grupos de anúncios.
Compare os seguintes snippets de código 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) quando apenas anúncios são necessários.
Usar métodos específicos de acesso ao elemento pai
Às vezes, é necessário extrair a entidade principal 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 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 do acessador 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 todas as hierarquias de campanhas e grupos de anúncios na sua conta, quando você só precisa 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 relevantes e usa um método apropriado 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 depois percorrer uma hierarquia.
Compare os snippets de código a seguir 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 programação | Snippet de código |
|---|---|
| Usar filtros apropriados 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 ela itera na hierarquia de campanhas e grupos de anúncios na sua conta, quando você só precisa 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 pai 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 as 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 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 um rótulo para as entidades que você processa e usá-lo 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 marcador (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 GAQL 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 diminui 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 as executam imediatamente. Em vez disso, ele tenta combinar várias mudanças em lotes para emitir uma única solicitação que faça várias mudanças. Essa abordagem torna os scripts mais rápidos e reduz a carga nos servidores do Google Ads. No entanto, existem alguns padrões de código que forçam os scripts do Google Ads a limpar o lote de operações com frequência, o que faz 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
seja 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, quando usados incorretamente, os builders 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 mostram 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 fechado (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 processamento em lote, já que chamamos operation.getResult() em um loop diferente de onde
ela foi criada.
Considere usar uploads em massa para atualizações grandes
Uma tarefa comum que os desenvolvedores realizam é gerar relatórios e atualizar propriedades de entidade (por exemplo, lances de palavra-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 uma performance melhor. Por exemplo, considere os seguintes scripts que aumentam o MaxCpc de 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 um desempenho muito bom, a primeira é preferível nesse caso, já que
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 em 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 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 fazer mais de um upload em massa por conta, verifique se eles operam em uma lista de campanhas (e entidades secundárias) mutuamente exclusivas para ter uma performance ideal.
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 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 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 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 é recomendada 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 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 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 gera resultados em um formato simples, mesmo que você esteja usando a GAQL. Isso significa que ele 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 dos novos relatórios da API Google Ads.
Dê preferência à GAQL em vez da AWQL
Embora a AWQL ainda funcione tecnicamente para consultas de relatórios e chamadas de withCondition, ela não é recomendada. Para ter controle total sobre suas consultas, use a GAQL.
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ê deve sempre usar filtros específicos para minimizar o conjunto de resultados o máximo possível para corresponder ao seu caso de uso.
Por exemplo, digamos que você queira encontrar grupos de anúncios com lances fora de um determinado intervalo. 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 são do seu interesse.
| 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 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 de contas de administrador do Google Ads (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. O executeInParallel() dá ao 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 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 Planilhas Google tente otimizar o segundo snippet de código armazenando em cache os valores, ele ainda oferece um desempenho ruim em comparação com o primeiro snippet, devido ao número de chamadas de API feitas.