Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Para mejorar el rendimiento de los scripts y el de la plataforma, revise y siga las prácticas recomendadas que se describen a continuación.
Trabajar con selectores
Usar filtros
Use los filtros de un selector en lugar de filtrar las entidades usted mismo. Los selectores te permiten filtrar por identificadores y condiciones. Por ejemplo, puedes filtrar por el rendimiento de una entidad (las campañas de devolución con un CPC medio superior a 10), su estado (las campañas que están en pausa), el nombre del objeto principal de la entidad, etc.
Ventajas de usar filtros:
Limita el número de entidades que devuelve el selector solo a las entidades que necesite.
Permite que el script se ejecute más rápido (menos entidades para devolver y procesar)
Reduce la posibilidad de toparse con los límites de lectura de entidades (consulte Límites de ejecución de scripts).
Camino correcto
var adGroups = AdsApp.adGroups()
.withCondition('Status = PAUSED')
.get();
while (adGroups.hasNext()) {
var adGroup = adGroups.next();
// Do something with paused ad group.
}
Forma incorrecta
var adGroups = AdsApp.adGroups().get();
while (adGroups.hasNext()) {
var adGroup = adGroups.next();
if (adGroup.isPaused() == true) {
// Do something with paused ad group.
}
}
No atraviese la jerarquía de entidades
Si desea obtener las entidades secundarias de una entidad o la entidad principal de la entidad, no atraviese la jerarquía de entidades para obtenerlas.
Para obtener entidades secundarias, use la colección de la entidad secundaria en el nivel que desee.
Camino correcto
// Get all ads.
var ads = AdsApp.ads().get();
while (ads.hasNext()) {
var ad = ads.next();
// Do something with ad.
}
O bien, si quieres anuncios de una campaña específica:
// Get all ads in the campaign, 'mycampaign'.
var ads = AdsApp.ads()
.withCondition("CampaignName = 'mycampaign'")
.get();
while (ads.hasNext()) {
var ad = ads.next();
// Do something with ad.
}
O bien, obtener los anuncios de una campaña si tienes el objeto de campaña:
// Get all ads in the campaign.
var ads = campaign.ads().get();
while (ads.hasNext()) {
var ad = ads.next();
// Do something with ad.
}
Forma incorrecta
var campaigns = AdsApp.campaigns().get();
while (campaigns.hasNext()) {
var adGroups = campaigns.next().adGroups().get();
while (adGroups.hasNext()) {
var ads = adGroups.next().ads().get();
while (ads.hasNext()) {
var ad = ads.next();
// Do something with ad.
}
}
}
Lo mismo se aplica si desea obtener el padre de una entidad. En lugar de atravesar la jerarquía para obtener el elemento primario, use el método de descriptor de acceso principal de la entidad secundaria.
Camino correcto
// Get all ads.
var ads = AdsApp.ads()
.withCondition('Clicks > 5')
.forDateRange('LAST_7_DAYS')
.get();
while (ads.hasNext()) {
var ad = ads.next();
// Do something with campaign and adGroup.
var adGroup = ad.adGroup();
var campaign = ad.campaign();
}
Forma incorrecta
var campaigns = AdsApp.campaigns().get();
while (campaigns.hasNext()) {
var campaign = campaigns.next();
var adGroups = campaign.adGroups().get();
while (adGroups.hasNext()) {
var adGroup = adGroups.next();
var ads = adGroup.ads().get();
while (ads.hasNext()) {
var ad = ads.next();
if ('<some condition is met>') {
// Do something with campaign and adGroup.
}
}
}
}
Usar identificadores de entidad cuando sea posible
El uso de identificadores para filtrar entidades proporciona el mejor rendimiento.
Esto
var adGroups = AdsApp.adGroups()
.withIds(["123456"])
.get();
while (adGroups.hasNext()) {
var adGroup = adGroups.next();
// Do something with adGroup.
}
Proporciona un rendimiento mejor que esto
var adGroups = AdsApp.adGroups()
.withCondition("Name = 'myadgroup'")
.get();
while (adGroups.hasNext()) {
var adGroup = adGroups.next();
// Do something with adGroup.
}
Evite bucles estrechos con selectores y un número innecesario de gets
Evite los bucles con solicitudes get que obtienen una sola entidad. Por ejemplo, supongamos que ejecutas un informe de rendimiento de palabras clave y quieres actualizar las palabras clave del informe. En lugar de obtener una fila del informe, obtener la palabra clave y luego actualizarla, debes crear una lista de los identificadores de palabras clave a medida que avanzas por cada fila del informe. A continuación, pase la lista de identificadores al selector para obtener todas las palabras clave en una única solicitud get. A continuación, puede recorrer la lista de palabras clave y actualizarlas.
Camino correcto
var report = AdsApp.report('<report query goes here>');
var rows = report.rows();
var idLists = []; // an array where each element contains an array of IDs.
var idList = []; // array of IDs that's limited to maxCount.
var maxCount = 10000;
while (rows.hasNext()) {
var row = rows.next();
if (idList.length < maxCount) {
idList.push(row['id']);
}
else {
idLists.push(idList);
idList = [];
}
}
for (idList of idLists) {
var keywords = AdsApp.keywords()
.withIds(idList)
.get();
while (keywords.hasNext()) {
var keyword = keywords.next();
// update the keyword
}
}
Forma incorrecta
var report = AdsApp.report('<report query goes here>');
var rows = report.rows();
while (rows.hasNext()) {
var row = rows.next();
var keyword = AdsApp.keywords()
.withIds([row['id']])
.get()
.next();
// update the keyword
}
Solo incluya el método forDateRange si tiene previsto llamar al método getStats de la entidad
Llamar a un método del forDateRange selector hace que el selector obtenga los datos de rendimiento de la entidad. Obtener los datos de rendimiento de una entidad es costoso, por lo que solo consígalos si planea llamar al método de getStats la entidad y usar los datos.
El intervalo de fechas que especifique para una entidad no se aplica a las entidades principales o secundarias a las que obtenga acceso desde esa entidad. Por ejemplo, si obtiene un grupo de anuncios y, a continuación, obtiene su campaña principal e intenta acceder a las métricas de rendimiento de la campaña, se produce un error en la llamada.
Se campaignStats.getReturnOnAdSpend() produce un error en la llamada del ejemplo siguiente porque el intervalo de fechas se aplica al grupo de anuncios y no a la campaña.
var myAdGroups = AdsApp.adGroups().
.withCondition("CampaignName CONTAINS 'gen'")
.forDateRange("LAST_7_DAYS")
.get();
while (myAdGroups.hasNext()) {
var adGroup = myAdGroups.next();
var campaign = adGroup.getCampaign();
var campaignStats = campaign.getStats();
var campaignROAS = campaignStats.getReturnOnAdSpend();
}
Para que esto funcione, debe crear un selector para la campaña.
var myAdGroups = AdsApp.adGroups().
.withCondition("CampaignName CONTAINS 'gen'")
.forDateRange("LAST_7_DAYS")
.get();
while (myAdGroups.hasNext()) {
var adGroup = myAdGroups.next();
var campaign = AdsApp.campaigns()
.withIds([adGroup.getCampaign().getId()])
.forDateRange("LAST_7_DAYS")
.get()
.next();
var campaignStats = campaign.getStats();
var campaignROAS = campaignStats.getReturnOnAdSpend();
}
No cambie la propiedad de una entidad que se usa como condición en el selector
Los iteradores reducen la presión de memoria cargando solo un elemento a la vez en lugar del conjunto completo de elementos. Por este motivo, cambiar una propiedad que usó como condición en el selector puede provocar un comportamiento inesperado.
Camino correcto
var adGroups = [];
var iterator = AdsApp.adGroups()
.withCondition('Status = ENABLED')
.get();
while (iterator.hasNext()) {
adGroups.push(iterator.next());
}
for (var adGroup of adGroups) {
adGroup.pause();
}
Forma incorrecta
var adGroups = AdsApp.adGroups()
.withCondition('Status = ENABLED')
.get();
while (adGroups.hasNext()) {
var adGroup = adGroups.next();
adGroup.pause();
}
Actualizaciones de procesamiento por lotes
Para mejorar el rendimiento, Scripts procesa las solicitudes de compilación por lotes. Si llama al método de operación de una solicitud de compilación, se obliga a los scripts a procesar las solicitudes de compilación en cola inmediatamente, lo que anula cualquier ganancia de rendimiento. Si va a crear más de una entidad, no ejecute los métodos de operación en el mismo bucle que usa para generar la entidad. Esto lleva a un rendimiento deficiente porque solo se procesa una entidad a la vez. En su lugar, cree una matriz de las operaciones y procéselas después del bucle de compilación.
Camino correcto
// An array to hold the operations, so you
// can process them after all the entities are queued.
var operations = [];
// Create all the new entities.
for (var i = 0; i < keywords.length; i++) {
var keywordOperation = AdsApp.adGroups().get().next()
.newKeywordBuilder()
.withText(keywords[i])
.build();
operations.push(keywordOperation);
}
// Now call the operation method so the build requests
// get processed in batches.
for (var i = 0; i < operations.length; i++) {
var newKeyword = operations[i].getResult();
}
Forma incorrecta
for (var i = 0; i < keywords.length; i++) {
var keywordOperation = AdsApp.adGroups().get().next() // Get the first ad group
.newKeywordBuilder() // Add the keyword to the ad group
.withText(keywords[i])
.build();
// Don't get results in the same loop that creates
// the entity because Scripts then only processes one
// entity at a time.
var newKeyword = keywordOperation.getResult();
}
Ocurre lo mismo si actualiza una entidad y obtiene la misma propiedad que ha actualizado. No lo hagas:
var bidAmount = 1.2;
while (keywords.hasNext()) {
var keyword = keywords.next();
keyword.bidding().setCpc(bidAmount);
if (keyword.bidding().getCpc() != bidAmount) {
Logger.log(`Failed to update bid amount for keyword, ${keyword.getText()} (${keyword.getId()})`);
}
}
Use la palabra clave yield cuando obtenga grandes conjuntos de entidades
Recuperar un gran número de entidades y cargarlas en una sola lista que se procesa en un bucle tiene un par de desventajas:
Según el tamaño de la solicitud, puede ser necesario n número de solicitudes de back-end para capturar todas las entidades antes de que se inicie el bucle. Si no los procesa todos, se desperdicia el tiempo y la potencia informática utilizados para obtener las entidades no procesadas. Por ejemplo, si recuperas 10 000 palabras clave y el bucle se interrumpe después de procesar solo 2 mil palabras clave, se desperdicia el tiempo y la potencia de cálculo usados para obtener las 8 mil palabras clave restantes.
Para crear la lista se necesita más memoria para contener todas las entidades a la vez.
Para solucionar estos problemas, use la palabra clave yield , que permite que el script obtenga entidades a pedido o, en cierto sentido, las obtenga "perezosamente" solo cuando sean necesarias. Esto significa que el script no está realizando más llamadas de las que necesita en este momento y no está pasando grandes listas de objetos.
En este ejemplo se incluye el registro para ilustrar el flujo de control al usar la palabra clave yield .
function main() {
const keywords = getKeywords();
//@ts-ignore <-- suppresses iterator error
for (const keyword of keywords) {
Logger.log("in for loop\n\n");
}
}
// Note that you must use the yield keyword in a generator function - see the
// '*' at the end of the function keyword.
function* getKeywords() {
const keywords = AdsApp.keywords()
.withCondition("Status = ENABLED")
.withCondition("CombinedApprovalStatus = APPROVED")
.withLimit(10)
.get();
Logger.log(`total keywords in account: ${keywords.totalNumEntities()} \n\n`);
while (keywords.hasNext()) {
Logger.log("before next()\n\n");
yield keywords.next();
Logger.log("after next\n\n");
}
}
Patrón de llamada para evitar los límites de la entidad
Hay un límite en el número de entidades que los scripts pueden devolver para una cuenta. Si la solicitud devuelve más de este límite, Scripts genera un error con el mensaje Hay demasiadas entidades. En el ejemplo siguiente se muestra el patrón de llamada que debe usar al obtener un gran número de entidades. En el ejemplo se intentan capturar primero todas las palabras clave en el nivel de cuenta. Si se produce un error, intenta realizar varias llamadas para capturar palabras clave por campaña, ya que normalmente hay menos entidades en el nivel de campaña. Por lo general, puedes continuar este patrón hasta el nivel de grupo de anuncios si es necesario.
Para obtener información sobre el uso de la palabra clave yield , consulte Use la palabra clave yield cuando obtenga grandes conjuntos de entidades.
function* getEntities() {
const applyConditions = _ => _
.withCondition('CampaignStatus = ENABLED')
.withCondition('AdGroupStatus = ENABLED')
.withCondition('Status = ENABLED')
.withCondition("CombinedApprovalStatus = DISAPPROVED");
try {
// Get the account's keywords.
const keywords = applyConditions(AdsApp.keywords()).get();
while (keywords.hasNext()) {
yield keywords.next();
}
} catch (e) {
if (!e.message.startsWith('There are too many entities')) {
throw e;
}
// If there are too many keywords at the account level,
// get keywords by campaigns under the account.
const campaigns = AdsApp.campaigns().get();
while (campaigns.hasNext()) {
const campaign = campaigns.next();
const keywords = applyConditions(campaign.keywords()).get();
while (keywords.hasNext()) {
yield keywords.next();
}
}
}
}