Best practice

Questa pagina illustra varie best practice per lo sviluppo con gli script Google Ads.

Selettori

Filtrare con i selettori

Se possibile, utilizza i filtri per richiedere solo le entità di cui hai bisogno. L'applicazione di filtri appropriati offre i seguenti vantaggi:

  • Il codice è più semplice e facile da comprendere.
  • Lo script verrà eseguito molto più velocemente.

Confronta i seguenti snippet di codice:

Approccio di programmazione Snippet di codice
Filtrare utilizzando i selettori (opzione consigliata)
var keywords = AdsApp.keywords()
    .withCondition('Clicks > 10')
    .forDateRange('LAST_MONTH')
    .get();
while (keywords.hasNext()) {
  var keyword = keywords.next();
  // Do work here.
}
Filtra nel codice (opzione non consigliata)
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.
  }
}

Il secondo approccio non è consigliato perché tenta di recuperare l'elenco di tutte le parole chiave nel tuo account solo per applicare un filtro all'elenco.

Evita di attraversare la gerarchia delle campagne

Quando vuoi recuperare entità a un determinato livello, utilizza un metodo di raccolta a quel livello anziché attraversare l'intera gerarchia della campagna. Oltre a essere più semplice, questa soluzione offrirà anche un rendimento molto migliore: il sistema non dovrà leggere inutilmente tutte le campagne e i gruppi di annunci.

Confronta i seguenti snippet di codice che recuperano tutti gli annunci nel tuo account:

Approccio di programmazione Snippet di codice
Utilizza il metodo di raccolta appropriato (consigliato)

var ads = AdsApp.ads();

Attraversare la gerarchia (non consigliato)
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.
  }
}

Il secondo approccio non è consigliato perché tenta di recuperare intere gerarchie di oggetti (campagne, gruppi di annunci) quando sono richiesti solo gli annunci.

Utilizzare metodi di accesso ai genitori specifici

A volte è necessario ottenere l'entità principale di un oggetto recuperato. In questo caso, devi utilizzare un metodo di accesso fornito anziché recuperare intere gerarchie.

Confronta i seguenti snippet di codice che recuperano i gruppi di annunci che contengono annunci di testo con più di 50 clic nell'ultimo mese:

Approccio di programmazione Snippet di codice
Utilizzare il metodo di accesso al genitore appropriato (consigliato)
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.
}
Attraversa la gerarchia (opzione non consigliata)
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.
    }
  }
}

Il secondo approccio non è consigliato perché recupera le intere gerarchie di campagne e gruppi di annunci nel tuo account, quando hai bisogno solo di un sottoinsieme di campagne e gruppi di annunci associati al tuo insieme di annunci. Il primo approccio si limita a recuperare solo la raccolta di annunci pertinenti e utilizza un metodo appropriato per accedere agli oggetti padre.

Utilizzare filtri genitori specifici

Per accedere alle entità all'interno di una campagna o di un gruppo di annunci specifico, utilizza un filtro specifico nel selettore anziché recuperare e poi attraversare una gerarchia.

Confronta i seguenti snippet di codice che recuperano l'elenco degli annunci di testo all'interno di una campagna e di un gruppo di annunci specifici che hanno ricevuto più di 50 clic il mese scorso.

Approccio di programmazione Snippet di codice
Utilizzare filtri a livello di genitore appropriati (opzione consigliata)
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.
}
Attraversare la gerarchia (opzione non consigliata)
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.
    }
  }
}

Il secondo approccio non è consigliato perché esegue l'iterazione della gerarchia di campagne e gruppi di annunci nel tuo account, quando hai bisogno solo di un insieme selezionato di annunci e delle relative campagne e gruppi di annunci principali. Il primo approccio limita l'iterazione all'elenco degli annunci applicando un filtro specifico per le entità principali nel selettore.

Se possibile, utilizza gli ID per i filtri

Quando filtri le entità, è preferibile filtrarle in base ai relativi ID anziché ad altri campi.

Considera i seguenti snippet di codice che selezionano una campagna.

Approccio di programmazione Snippet di codice
Filtra per ID (consigliato)
var campaign = AdsApp.campaigns()
    .withIds([12345])
    .get()
    .next();
Filtra per nome (meno ottimale)
var campaign = AdsApp.campaigns()
    .withCondition('Name="foo"')
    .get()
    .next();

Il secondo approccio è meno ottimale perché filtriamo in base a un campo non ID.

Filtra per ID principali, se possibile

Quando selezioni un'entità, filtra per ID genitore, se possibile. In questo modo, le query saranno più veloci perché l'elenco delle entità recuperate dai server durante il filtraggio dei risultati sarà limitato.

Considera il seguente snippet di codice che recupera un gruppo di annunci in base al relativo ID. Supponi che l'ID campagna principale sia noto.

Approccio di programmazione Snippet di codice
Filtra in base agli ID campagna e gruppo di annunci (consigliato)
var adGroup = AdsApp.adGroups()
    .withIds([12345])
    .withCondition('CampaignId="54678"')
    .get()
    .next();
Filtrare solo per ID gruppo di annunci (meno ottimale)
var adGroup = AdsApp.adGroups()
    .withIds([12345])
    .get()
    .next();

Anche se entrambi gli snippet di codice danno risultati identici, il filtro aggiuntivo nello snippet di codice 1 che utilizza un ID principale (CampaignId="54678") rende il codice più efficiente limitando l'elenco delle entità che il server deve scorrere durante il filtraggio dei risultati.

Utilizza le etichette quando sono presenti troppe condizioni di filtro

Se hai troppe condizioni di filtro, è consigliabile creare un'etichetta per le entità che elabori e utilizzarla per filtrare le entità.

Considera il seguente snippet di codice che recupera un elenco di campagne in base al nome.

Approccio di programmazione Snippet di codice
Utilizza un'etichetta (opzione consigliata)
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
}
Crea selettori complessi (non consigliato)
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.
}

Sebbene entrambi gli snippet di codice offrano un livello di prestazioni simile, il secondo approccio tende a generare un codice più complesso man mano che aumenta il numero di condizioni nel selettore. È anche più facile applicare l'etichetta a una nuova entità che modificare lo script per includere una nuova entità.

Limita il numero di condizioni nella clausola IN

Quando esegui gli script, un caso d'uso comune è creare un report per un elenco di entità. Gli sviluppatori in genere lo fanno creando una query GAQL molto lunga che filtra gli ID entità utilizzando una clausola IN. Questo approccio funziona bene quando il numero di entità è limitato. Tuttavia, con l'aumentare della lunghezza della query, le prestazioni dello script peggiorano per due motivi:

  • L'analisi di una query più lunga richiede più tempo.
  • Ogni ID che aggiungi a una clausola IN è una condizione aggiuntiva da valutare e richiede quindi più tempo.

In queste condizioni, è preferibile applicare un'etichetta alle entità e poi filtrare in base a LabelId.

Approccio di programmazione Snippet di codice
Applicare un'etichetta e filtrare per ID etichetta (consigliato)
// 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() + '"');
Creare una query lunga utilizzando la clausola IN (opzione non consigliata)
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…)');

Aggiornamenti sull'account

Modifiche collettive

Quando apporti modifiche a un'entità Google Ads, gli script Google Ads non eseguono immediatamente la modifica. Tenta invece di combinare più modifiche in batch, in modo da poter inviare una singola richiesta che esegue più modifiche. Questo approccio rende gli script più veloci e riduce il carico sui server Google Ads. Tuttavia, esistono alcuni pattern di codice che forzano gli script Google Ads a svuotare spesso il batch di operazioni, causando l'esecuzione lenta dello script.

Considera il seguente script che aggiorna le offerte di un elenco di parole chiave.

Approccio di programmazione Snippet di codice
Tieni traccia degli elementi aggiornati (opzione consigliata)
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());
}
Recuperare gli elementi aggiornati in un ciclo stretto (opzione non consigliata)
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());
}

Il secondo approccio non è consigliato, poiché la chiamata a keyword.bidding().getCpc() forza gli script Google Ads a svuotare l'operazione setCpc() ed eseguire una sola operazione alla volta. Il primo approccio, sebbene simile al secondo, offre l'ulteriore vantaggio di supportare il raggruppamento in batch, poiché la chiamata getCpc() viene eseguita in un ciclo separato da quello in cui viene chiamato setCpc().

Utilizza i builder quando possibile

Gli script Google Ads supportano due modi per creare nuovi oggetti: generatori e metodi di creazione. I builder sono più flessibili dei metodi di creazione, in quanto consentono di accedere all'oggetto creato dalla chiamata API.

Considera i seguenti snippet di codice:

Approccio di programmazione Snippet di codice
Utilizzare i generatori (opzione consigliata)
var operation = adGroup.newKeywordBuilder()
    .withText('shoes')
    .build();
var keyword = operation.getResult();
Utilizza i metodi di creazione (non consigliato)
adGroup.createKeyword('shoes');
var keyword = adGroup.keywords()
    .withCondition('KeywordText="shoes"')
    .get()
    .next();

Il secondo approccio non è preferibile a causa dell'operazione di selezione aggiuntiva coinvolta nel recupero della parola chiave. Inoltre, anche i metodi di creazione sono stati ritirati.

Tuttavia, tieni presente che i builder, se utilizzati in modo errato, possono impedire agli script Google Ads di raggruppare le operazioni.

Considera i seguenti snippet di codice che creano un elenco di parole chiave e stampano l'ID delle parole chiave appena create:

Approccio di programmazione Snippet di codice
Tieni traccia degli elementi aggiornati (opzione consigliata)
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());
}
Recuperare gli elementi aggiornati in un ciclo ristretto (non consigliato)
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());
}

Il secondo approccio non è preferibile perché chiama operation.getResult() all'interno dello stesso ciclo che crea l'operazione, forzando così gli script Google Ads a eseguire un'operazione alla volta. Il primo approccio, sebbene simile, consente il raggruppamento in batch, poiché chiamiamo operation.getResult() in un ciclo diverso da quello in cui è stato creato.

Valuta la possibilità di utilizzare i caricamenti collettivi per gli aggiornamenti di grandi dimensioni

Un'attività comune svolta dagli sviluppatori è l'esecuzione di report e l'aggiornamento delle proprietà delle entità (ad esempio, le offerte per parola chiave) in base ai valori di rendimento correnti. Quando devi aggiornare un numero elevato di entità, i caricamenti collettivi tendono a offrire un rendimento migliore. Ad esempio, considera i seguenti script che aumentano il MaxCpc delle parole chiave il cui TopImpressionPercentage > 0.4 nell'ultimo mese:

Approccio di programmazione Snippet di codice
Utilizzare il caricamento collettivo (opzione consigliata)

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();
Selezionare e aggiornare le parole chiave per ID (meno ottimale)
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);
  }
}

Sebbene il secondo approccio offra prestazioni piuttosto buone, il primo approccio è preferibile in questo caso poiché

  • Gli script Google Ads hanno un limite al numero di oggetti che possono essere recuperati o aggiornati in una singola esecuzione e le operazioni di selezione e aggiornamento nel secondo approccio vengono conteggiate ai fini di questo limite.

  • I caricamenti collettivi hanno limiti più elevati sia in termini di numero di entità che possono aggiornare sia in termini di tempo di esecuzione complessivo.

Raggruppa i caricamenti collettivi per campagna

Quando crei i caricamenti collettivi, prova a raggruppare le operazioni in base alla campagna principale. In questo modo, l'efficienza aumenta e diminuisce la probabilità di modifiche in conflitto / errori di concorrenza.

Considera due attività di caricamento collettivo in esecuzione in parallelo. Uno mette in pausa gli annunci in un gruppo di annunci, l'altro modifica le offerte per parola chiave. Anche se le operazioni non sono correlate, possono essere applicate a entità nello stesso gruppo di annunci (o in due gruppi di annunci diversi nella stessa campagna). In questo caso, il sistema blocca l'entità principale (il gruppo di annunci o la campagna condivisi), causando il blocco reciproco delle attività di caricamento collettivo.

Gli script Google Ads possono ottimizzare l'esecuzione all'interno di una singola attività di caricamento collettivo, quindi la cosa più semplice da fare è eseguire una sola attività di caricamento collettivo per account alla volta. Se decidi di eseguire più di un caricamento collettivo per account, assicurati che i caricamenti collettivi operino su un elenco di esclusione di campagne (e delle relative entità secondarie) reciprocamente esclusivo per un rendimento ottimale.

Rapporti

Utilizza i report per recuperare le statistiche

Quando vuoi recuperare grandi quantità di entità e le relative statistiche, spesso è meglio utilizzare i report anziché i metodi AdsApp standard. L'utilizzo dei report è preferibile per i seguenti motivi:

  • I report offrono prestazioni migliori per le query di grandi dimensioni.
  • I report non raggiungeranno le normali quote di recupero.

Confronta i seguenti snippet di codice che recuperano i clic, le impressioni, il costo e il testo di tutte le parole chiave che hanno ricevuto più di 50 clic il mese scorso:

Approccio di programmazione Snippet di codice
Utilizza i report (opzione consigliata)
  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);
  }
Utilizza gli iteratori AdsApp (non consigliato)
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());
}

Il secondo approccio non è preferibile perché itera le parole chiave e recupera le statistiche un'entità alla volta. In questo caso, i report vengono eseguiti più velocemente, poiché recuperano tutti i dati in un'unica chiamata e li trasmettono in streaming in base alle esigenze. Inoltre, le parole chiave recuperate nel secondo approccio vengono conteggiate nella quota dello script per il numero di entità recuperate utilizzando una chiamata get().

Utilizza la ricerca anziché il report

Il metodo report è stato creato per la vecchia infrastruttura e restituirà i risultati in un formato semplice anche se utilizzi GAQL. Ciò significa che deve trasformare i risultati della query in modo che corrispondano al vecchio stile, che non è supportato per tutti i campi e aggiunge overhead a ogni chiamata.

Ti consigliamo di utilizzare la ricerca per sfruttare tutte le funzionalità dei nuovi report dell'API Google Ads.

Preferire GAQL a AWQL

Sebbene AWQL funzioni ancora tecnicamente per le query dei report e le chiamate withCondition, non è consigliato. Per avere il controllo completo sulle query, assicurati di utilizzare GAQL.

Non selezionare più righe del necessario

La velocità di esecuzione dei report (e dei selettori) si basa sul numero totale di righe che verrebbero restituite dal report, indipendentemente dal fatto che tu le scorra. Ciò significa che devi sempre utilizzare filtri specifici per ridurre al minimo il set di risultati in modo che corrisponda al tuo caso d'uso.

Ad esempio, supponiamo che tu voglia trovare gruppi di annunci con offerte al di fuori di un intervallo specifico. Sarebbe più veloce eseguire due query separate, una per le offerte al di sotto della soglia minima e un'altra per le offerte al di sopra della soglia massima, rispetto al recupero di tutti i gruppi di annunci e all'ignorare quelli che non ti interessano.

Approccio di programmazione Snippet di codice
Utilizzare due query (opzione consigliata)
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);
}
Filtrare i risultati di una query generica (opzione non consigliata)
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);
  }
}

Script di Ads Manager (Centro clienti)

Preferisci executeInParallel all'esecuzione seriale

Quando scrivi script per gli account amministratore, utilizza executeInParallel() anziché l'esecuzione seriale, quando possibile. executeInParallel() offre allo script più tempo di elaborazione (fino a un'ora) e fino a 30 minuti per account elaborato (anziché 30 minuti combinati per l'esecuzione seriale). Per ulteriori dettagli, consulta la nostra pagina dei limiti.

Fogli di lavoro

Utilizza le operazioni batch quando aggiorni i fogli di lavoro

Quando aggiorni i fogli di lavoro, prova a utilizzare i metodi di operazione collettiva (ad esempio getRange()) anziché i metodi che aggiornano una cella alla volta.

Considera il seguente snippet di codice che genera un pattern frattale in un foglio di lavoro.

Approccio di programmazione Snippet di codice
Aggiorna un intervallo di celle in una singola chiamata (consigliato)
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);
Aggiorna una cella alla volta (opzione non consigliata)
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();
}

Sebbene Fogli Google cerchi di ottimizzare il secondo snippet di codice memorizzando nella cache i valori, le prestazioni sono comunque inferiori rispetto al primo snippet, a causa del numero di chiamate API effettuate.