En esta página, se describen varias prácticas recomendadas para desarrollar con secuencias de comandos de Google Ads.
Selectores
Filtra con selectores
Cuando sea posible, usa filtros para solicitar solo las entidades que necesites. Aplicar los filtros adecuados tiene los siguientes beneficios:
- El código es más simple y fácil de entender.
- La secuencia de comandos se ejecutará mucho más rápido.
Compara los siguientes fragmentos de código:
Enfoque de programación | Fragmento de código |
---|---|
Cómo filtrar con selectores (recomendado) |
var keywords = AdsApp.keywords() .withCondition('Clicks > 10') .forDateRange('LAST_MONTH') .get(); while (keywords.hasNext()) { var keyword = keywords.next(); // Do work here. } |
Filtro en el código (no 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. } } |
No se recomienda el segundo enfoque porque intenta recuperar la lista de todas las palabras clave de tu cuenta solo para aplicar un filtro a la lista.
Evita recorrer la jerarquía de la campaña
Cuando quieras recuperar entidades en un nivel determinado, usa un método de colección en ese nivel en lugar de recorrer toda la jerarquía de la campaña. Además de ser más simple, también tendrá un mejor rendimiento: el sistema no tendrá que leer innecesariamente todas las campañas y los grupos de anuncios.
Compara los siguientes fragmentos de código que recuperan todos los anuncios de tu cuenta:
Enfoque de programación | Fragmento de código |
---|---|
Usa el método de recolección adecuado (recomendado) |
var ads = AdsApp.ads(); |
Recorre la jerarquía (no 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. } } |
No se recomienda el segundo enfoque, ya que intenta recuperar jerarquías completas de objetos (campañas, grupos de anuncios), mientras que solo se requieren anuncios.
Usa métodos de acceso para padres específicos
A veces, necesitas obtener la entidad principal de un objeto recuperado. En este caso, debes usar un método de acceso proporcionado en lugar de recuperar jerarquías completas.
Compara los siguientes fragmentos de código que recuperan los grupos de anuncios que tuvieron anuncios de texto con más de 50 clics el mes pasado:
Enfoque de programación | Fragmento de código |
---|---|
Usa el método de acceso principal adecuado (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. } |
Recorre la jerarquía (no 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. } } } |
No se recomienda el segundo enfoque, ya que recupera todas las jerarquías de campañas y grupos de anuncios de tu cuenta, mientras que solo necesitas un subconjunto de campañas y grupos de anuncios asociados con tu conjunto de anuncios. El primer enfoque se limita a recuperar solo la colección de anuncios pertinentes y usa un método adecuado para acceder a sus objetos superiores.
Usa filtros de elementos superiores específicos
Para acceder a entidades dentro de una campaña o un grupo de anuncios específicos, usa un filtro específico en el selector en lugar de recuperar y, luego, recorrer una jerarquía.
Compara los siguientes fragmentos de código que recuperan la lista de anuncios de texto en una campaña y un grupo de anuncios especificados que tuvieron más de 50 clics el mes pasado.
Enfoque de programación | Fragmento de código |
---|---|
Usa los filtros de nivel superior adecuados (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. } |
Recorre la jerarquía (no 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. } } } |
No se recomienda el segundo enfoque, ya que itera en la jerarquía de campañas y grupos de anuncios de tu cuenta, mientras que solo necesitas un conjunto seleccionado de anuncios, y sus campañas y grupos de anuncios principales. El primer enfoque limita la iteración a la lista de anuncios aplicando un filtro específico para las entidades principales en el selector.
Usa IDs para filtrar cuando sea posible
Cuando filtres entidades, es preferible que lo hagas por sus IDs en lugar de otros campos.
Considera los siguientes fragmentos de código que seleccionan una campaña.
Enfoque de programación | Fragmento de código |
---|---|
Filtrar por ID (recomendado) |
var campaign = AdsApp.campaigns() .withIds([12345]) .get() .next(); |
Filtrar por nombre (menos óptimo) |
var campaign = AdsApp.campaigns() .withCondition('Name="foo"') .get() .next(); |
El segundo enfoque es menos óptimo, ya que filtramos por un campo que no es un ID.
Filtra por IDs parentales siempre que sea posible
Cuando selecciones una entidad, filtra por IDs de elementos superiores siempre que sea posible. Esto hará que tus búsquedas sean más rápidas, ya que limitará la lista de entidades que recuperan los servidores cuando se filtran los resultados.
Considera el siguiente fragmento de código que recupera un AdGroup por su ID. Supón que se conoce el ID de la campaña principal.
Enfoque de programación | Fragmento de código |
---|---|
Filtrar por IDs de campaña y grupo de anuncios (recomendado) |
var adGroup = AdsApp.adGroups() .withIds([12345]) .withCondition('CampaignId="54678"') .get() .next(); |
Filtrar solo por ID de grupo de anuncios (menos óptimo) |
var adGroup = AdsApp.adGroups() .withIds([12345]) .get() .next(); |
Aunque ambos fragmentos de código arrojan resultados idénticos, el filtrado adicional en el fragmento de código 1 que usa un ID principal (CampaignId="54678")
hace que el código sea más eficiente, ya que restringe la lista de entidades que el servidor debe iterar cuando filtra los resultados.
Usa etiquetas cuando haya demasiadas condiciones de filtrado
Cuando tienes demasiadas condiciones de filtrado, es una buena idea crear una etiqueta para las entidades que procesas y usar esa etiqueta para filtrar tus entidades.
Considera el siguiente fragmento de código que recupera una lista de campañas por su nombre.
Enfoque de programación | Fragmento de código |
---|---|
Usa una etiqueta (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 } |
Cómo compilar selectores complejos (no 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. } |
Si bien ambos fragmentos de código te brindan un nivel de rendimiento similar, el segundo enfoque tiende a generar código más complejo a medida que aumenta la cantidad de condiciones en tu selector. También es más fácil aplicar la etiqueta a una entidad nueva que editar la secuencia de comandos para incluir una entidad nueva.
Limita la cantidad de condiciones en tu cláusula IN
Cuando se ejecutan secuencias de comandos, un caso de uso común es ejecutar un informe para una lista de entidades. Por lo general, los desarrolladores logran esto construyendo una consulta de AWQL muy larga que filtra los IDs de la entidad con una cláusula IN. Este enfoque funciona bien cuando la cantidad de entidades es limitada. Sin embargo, a medida que aumenta la longitud de tu consulta, el rendimiento de tu secuencia de comandos se deteriora por dos motivos:
- Una consulta más larga tarda más en analizarse.
- Cada ID que agregas a una cláusula IN es una condición adicional que se debe evaluar y, por lo tanto, lleva más tiempo.
En estas condiciones, es preferible aplicar una etiqueta a las entidades y, luego, filtrar por LabelId
.
Enfoque de programación | Fragmento de código |
---|---|
Aplica una etiqueta y filtra 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() + '"'); |
Cómo compilar una consulta larga con la cláusula IN (no 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…)'); |
Actualizaciones de la cuenta
Cambios por lotes
Cuando realizas cambios en una entidad de Google Ads, las secuencias de comandos de Google Ads no ejecutan el cambio de inmediato. En cambio, intenta combinar varios cambios en lotes para poder emitir una sola solicitud que realice varios cambios. Este enfoque hace que tus secuencias de comandos sean más rápidas y reduce la carga en los servidores de Google Ads. Sin embargo, existen algunos patrones de código que fuerzan a las secuencias de comandos de Google Ads a vaciar su lote de operaciones con frecuencia, lo que hace que la secuencia de comandos se ejecute lentamente.
Considera la siguiente secuencia de comandos que actualiza las ofertas de una lista de palabras clave.
Enfoque de programación | Fragmento de código |
---|---|
Haz un seguimiento de los elementos actualizados (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()); } |
Cómo recuperar elementos actualizados en un bucle ajustado (no 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()); } |
No se recomienda el segundo enfoque, ya que la llamada a keyword.bidding().getCpc()
obliga a las secuencias de comandos de Google Ads a vaciar la operación setCpc()
y ejecutar solo una operación a la vez. El primer enfoque, si bien es similar al segundo, tiene el beneficio adicional de admitir el procesamiento por lotes, ya que la llamada a getCpc()
se realiza en un bucle separado del que se llama a setCpc()
.
Usa compiladores cuando sea posible
Las secuencias de comandos de Google Ads admiten dos formas de crear objetos nuevos: los compiladores y los métodos de creación. Los compiladores son más flexibles que los métodos de creación, ya que te brindan acceso al objeto que se crea a partir de la llamada a la API.
Considera los siguientes fragmentos de código:
Enfoque de programación | Fragmento de código |
---|---|
Usa compiladores (recomendado) |
var operation = adGroup.newKeywordBuilder() .withText('shoes') .build(); var keyword = operation.getResult(); |
Usar métodos de creación (no recomendado) |
adGroup.createKeyword('shoes'); var keyword = adGroup.keywords() .withCondition('KeywordText="shoes"') .get() .next(); |
El segundo enfoque no es el preferido debido a la operación de selección adicional que implica recuperar la palabra clave. Además, los métodos de creación también dejaron de estar disponibles.
Sin embargo, ten en cuenta que los compiladores, cuando se usan de forma incorrecta, pueden impedir que las secuencias de comandos de Google Ads agrupen sus operaciones.
Considera los siguientes fragmentos de código que crean una lista de palabras clave y, luego, imprimen el ID de las palabras clave recién creadas:
Enfoque de programación | Fragmento de código |
---|---|
Haz un seguimiento de los elementos actualizados (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()); } |
Cómo recuperar elementos actualizados en un bucle ajustado (no 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()); } |
El segundo enfoque no es el preferido porque llama a operation.getResult()
dentro del mismo bucle que crea la operación, lo que obliga a las secuencias de comandos de Google Ads a ejecutar una operación a la vez. El primer enfoque, aunque es similar, permite el procesamiento por lotes, ya que llamamos a operation.getResult() en un bucle diferente del que se creó.
Considera usar cargas masivas para actualizaciones grandes
Una tarea común que realizan los desarrolladores es ejecutar informes y actualizar las propiedades de las entidades (por ejemplo, las ofertas de palabras clave) en función de los valores de rendimiento actuales. Cuando tienes que actualizar una gran cantidad de entidades, las cargas masivas suelen ofrecer un mejor rendimiento. Por ejemplo, considera los siguientes fragmentos de código que aumentan el MaxCpc de las palabras clave cuyo TopImpressionPercentage > 0.4
del último mes:
Enfoque de programación | Fragmento de código |
---|---|
Usar la carga masiva (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(); |
Selecciona y actualiza palabras clave por ID (menos óptimo) |
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); } } |
Si bien el segundo enfoque te brinda un rendimiento bastante bueno, en este caso, se prefiere el primer enfoque, ya que
Los secuencias de comandos de Google Ads tienen un límite en la cantidad de objetos que se pueden recuperar o actualizar en una sola ejecución, y las operaciones de selección y actualización del segundo enfoque se incluyen en ese límite.
Las cargas masivas tienen límites más altos en cuanto a la cantidad de entidades que pueden actualizar y el tiempo de ejecución general.
Agrupa tus cargas masivas por campañas
Cuando crees tus cargas masivas, intenta agrupar tus operaciones por la campaña principal. Esto aumenta la eficiencia y disminuye la posibilidad de cambios conflictivos o errores de simultaneidad.
Considera dos tareas de carga masiva que se ejecutan en paralelo. Una detiene los anuncios en un grupo de anuncios, y la otra ajusta las ofertas de palabras clave. Aunque las operaciones no estén relacionadas, pueden aplicarse a entidades del mismo grupo de anuncios (o a dos grupos de anuncios diferentes de la misma campaña). Cuando esto sucede, el sistema bloqueará la entidad principal (el grupo de anuncios o la campaña compartidos), lo que hará que las tareas de carga masiva se bloqueen entre sí.
Las secuencias de comandos de Google Ads pueden optimizar la ejecución dentro de una sola tarea de carga masiva, por lo que lo más sencillo es ejecutar solo una tarea de carga masiva por cuenta a la vez. Si decides ejecutar más de una carga masiva por cuenta, asegúrate de que las cargas masivas operen en una lista de campañas (y sus entidades secundarias) mutuamente exclusiva para obtener un rendimiento óptimo.
Informes
Usa informes para recuperar estadísticas
Cuando deseas recuperar grandes cantidades de entidades y sus estadísticas, suele ser mejor usar informes en lugar de los métodos estándar de AdsApp. Se prefiere el uso de informes por los siguientes motivos:
- Los informes te brindan un mejor rendimiento para las consultas grandes.
- Los informes no alcanzarán las cuotas de recuperación normales.
Compara los siguientes fragmentos de código que recuperan los clics, las impresiones, el costo y el texto de todas las palabras clave que recibieron más de 50 clics el mes pasado:
Enfoque de programación | Fragmento de código |
---|---|
Usa informes (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); } |
Cómo usar iteradores de AdsApp (no se recomienda) |
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()); } |
No se prefiere el segundo enfoque porque itera sobre las palabras clave y recupera las estadísticas de una entidad a la vez. En este caso, los informes se ejecutan más rápido, ya que recuperan todos los datos en una sola llamada y los transmiten según sea necesario. Además, las palabras clave recuperadas en el segundo enfoque se incluyen en la cuota de tu secuencia de comandos para la cantidad de entidades recuperadas con una llamada a get()
.
Usar la búsqueda en lugar del informe
El método de informes se creó para la infraestructura anterior y generará resultados en un formato sin formato, incluso si usas GAQL. Esto significa que tiene que transformar los resultados de la consulta para que coincidan con el estilo anterior, lo que no se admite para todos los campos y agrega una sobrecarga a cada llamada.
Te sugerimos que uses la búsqueda para aprovechar todas las funciones de los nuevos informes de la API de Google Ads.
Prefiere GAQL a AWQL
Si bien AWQL aún se admite en las consultas de informes y las llamadas a withCondition
, se ejecuta a través de una capa de traducción que no tiene compatibilidad total con AWQL real. Para tener un control total sobre tus consultas, asegúrate de usar GAQL.
Si tienes consultas en AWQL existentes que deseas traducir, tenemos una herramienta de migración de consultas para ayudarte.
No selecciones más filas de las que necesitas
La velocidad de ejecución de los informes (y los selectores) se basa en la cantidad total de filas que devolvería el informe, independientemente de si iteras por ellas. Esto significa que siempre debes usar filtros específicos para minimizar el conjunto de resultados tanto como sea posible y que coincida con tu caso de uso.
Por ejemplo, supongamos que deseas encontrar grupos de anuncios con ofertas fuera de un rango específico. Sería más rápido realizar dos consultas separadas, una para las ofertas por debajo del umbral inferior y otra para las ofertas por encima del umbral superior, que recuperar todos los grupos de anuncios y descartar los que no te interesan.
Enfoque de programación | Fragmento de código |
---|---|
Usa dos búsquedas (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 una búsqueda genérica (no 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); } } |
Secuencias de comandos de Ads Manager (MCC)
Prefiere executeInParallel a la ejecución en serie
Cuando escribas secuencias de comandos para cuentas de administrador, usa executeInParallel()
en lugar de la ejecución en serie siempre que sea posible. executeInParallel()
le da a tu secuencia de comandos más tiempo de procesamiento (hasta una hora) y hasta 30 minutos por cuenta procesada (en lugar de 30 minutos combinados para la ejecución en serie). Consulta nuestra página de límites para obtener más detalles.
Hojas de cálculo
Usa operaciones por lotes cuando actualices hojas de cálculo
Cuando actualices hojas de cálculo, intenta usar los métodos de operación masiva (por ejemplo, getRange()
) en lugar de los métodos que actualizan una celda a la vez.
Considera el siguiente fragmento de código que genera un patrón fractal en una hoja de cálculo.
Enfoque de programación | Fragmento de código |
---|---|
Actualiza un rango de celdas en una sola llamada (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); |
Actualiza una celda a la vez (no 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(); } |
Si bien Hojas de cálculo de Google intenta optimizar el segundo fragmento de código almacenando en caché los valores, sigue ofreciendo un rendimiento deficiente en comparación con el primer fragmento, debido a la cantidad de llamadas a la API que se realizan.