Orçamentos flexíveis: conta única

Ícone de ferramentas

O Google Ads permite definir um valor de orçamento diário para cada campanha. No entanto, algumas iniciativas de marketing têm um custo fixo associado a elas. Por exemplo, "Quero gastar US $5.000 até a nossa promoção de outono". A estratégia de lances dá algum controle sobre como o orçamento diário é gasto, mas não sobre como ele é consumido durante a campanha.

Por exemplo, se quisermos gastar apenas R $5.000 para anunciar nossa promoção de outono e quisermos anunciar por 10 dias, podemos definir um orçamento diário de R $500 para usar todo o orçamento. No entanto, isso pressupõe que vamos gastar o valor total todos os dias e que queremos gastá-lo de maneira uniforme. Não é possível informar ao Google Ads que você quer gastar a maior parte do orçamento nos últimos dias.

Este script ajustará dinamicamente o orçamento diário da sua campanha com um esquema personalizado de distribuição do orçamento.

Como funciona

Teste de estratégias de orçamento

O script inclui um código de teste para simular os efeitos da execução por vários dias. Assim, você tem uma ideia melhor do que pode acontecer quando o script é programado para ser executado diariamente por um período.

Por padrão, esse script simula uma distribuição uniforme de orçamento de R $500 gastos em 10 dias.

function main() {
  testBudgetStrategy(calculateBudgetEvenly, 10, 500);
  // setNewBudget(calculateBudgetEvenly, CAMPAIGN_NAME, TOTAL_BUDGET, START_DATE, END_DATE);
}

A chamada de função setNewBudget está comentada, indicando que ela só executará o código de teste. Aqui está a saída do exemplo:

Day 1.0 of 10.0, new budget 50.0, cost so far 0.0
Day 2.0 of 10.0, new budget 50.0, cost so far 50.0
Day 3.0 of 10.0, new budget 50.0, cost so far 100.0
Day 4.0 of 10.0, new budget 50.0, cost so far 150.0
Day 5.0 of 10.0, new budget 50.0, cost so far 200.0
Day 6.0 of 10.0, new budget 50.0, cost so far 250.0
Day 7.0 of 10.0, new budget 50.0, cost so far 300.0
Day 8.0 of 10.0, new budget 50.0, cost so far 350.0
Day 9.0 of 10.0, new budget 50.0, cost so far 400.0
Day 10.0 of 10.0, new budget 50.0, cost so far 450.0
Day 11.0 of 10.0, new budget 0.0, cost so far 500.0

Todos os dias, o script calcula um novo orçamento para garantir que o gasto seja distribuído de maneira uniforme. Quando o limite de orçamento alocado é atingido, o orçamento é definido como zero, interrompendo os gastos.

Para mudar a estratégia de orçamento, altere a função usada ou modifique a função em si. O script vem com duas estratégias pré-criadas: calculateBudgetEvenly e calculateBudgetWeighted. Para definir uma estratégia de orçamento de teste ponderado, mude testBudgetStrategy assim:

testBudgetStrategy(calculateBudgetWeighted, 10, 500);

Clique em Visualizar e verifique a saída do registro. Essa estratégia aloca menos orçamento no início do período e mais nos últimos dias.

Você pode usar esse método de teste para simular alterações feitas nas funções de cálculo do orçamento e testar sua própria abordagem na distribuição de um orçamento.

Alocação de um orçamento

A estratégia de orçamento calculateBudgetWeighted é implementada pela seguinte função:

function calculateBudgetWeighted(costSoFar, totalBudget, daysSoFar, totalDays) {
  const daysRemaining = totalDays - daysSoFar;
  const budgetRemaining = totalBudget - costSoFar;
  if (daysRemaining <= 0) {
    return budgetRemaining;
  } else {
    return budgetRemaining / (2 * daysRemaining - 1) ;
  }
}

Essa função usa os seguintes argumentos:

costSoFar
Custo acumulado da campanha de START_DATE até hoje.
totalBudget
Gasto alocado de START_DATE a END_DATE.
daysSoFar
Dias decorridos de START_DATE até hoje.
totalDays
Número total de dias entre START_DATE e END_DATE.

Você pode escrever sua própria função, desde que ela use esses argumentos. Usando esses valores, você pode comparar quanto gastou em dinheiro até agora com quanto deve gastar no geral e determinar em que ponto está no momento dentro do cronograma de todo o orçamento.

Em particular, essa estratégia de orçamento calcula quanto orçamento resta (totalBudget - costSoFar) e divide esse valor por duas vezes o número de dias restantes. Isso pondera a distribuição do orçamento para o final da campanha. Ao usar o custo desde START_DATE, ele também considera os "dias lentos", em que o orçamento definido não é totalmente gasto.

Criação de um orçamento de verdade

Depois de definir a estratégia de orçamento, faça algumas mudanças antes de programar a execução diária do script.

Primeiro, atualize as constantes no início do arquivo:

  • START_DATE: defina isso como o início da sua estratégia de orçamento. Deve ser a data atual ou um dia no passado.
  • END_DATE: defina esse valor como o último dia em que você quer anunciar com esse orçamento.
  • TOTAL_BUDGET: o valor total que você está tentando gastar. Esse valor está na moeda da conta e pode ser excedido dependendo do agendamento de execução do script.
  • CAMPAIGN_NAME: o nome da campanha a que a estratégia de orçamento será aplicada.

Em seguida, desative o teste e ative a lógica para alterar efetivamente o orçamento:

function main() {
  // testBudgetStrategy(calculateBudgetEvenly, 10, 500);
  setNewBudget(calculateBudgetWeighted, CAMPAIGN_NAME, TOTAL_BUDGET, START_DATE, END_DATE);
}

Agendamento

Agende este script para ser executado diariamente, à meia-noite ou pouco depois no fuso horário local, para que ele direcione o máximo possível o orçamento do dia seguinte. No entanto, os dados de relatórios recuperados, como custo, podem ter um atraso de cerca de três horas. Portanto, o parâmetro costSoFar pode estar fazendo referência ao total de ontem para um script programado para ser executado após a meia-noite.

Configuração

  • Clique no botão abaixo para criar o script na sua conta do Google Ads.

    Instalar o modelo de script

  • Salve o script e clique no botão Visualizar. Por padrão, esse script simula uma estratégia de orçamento com R $500 ao longo de 10 dias. A saída do logger reflete o dia simulado, o orçamento alocado para esse dia e o valor total gasto até o momento.

Código-fonte

// Copyright 2015, Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @name Flexible Budgets
 *
 * @overview The Flexible budgets script dynamically adjusts campaign budget for
 *     an advertiser account with a custom budget distribution scheme on a daily
 *     basis. See
 *     https://developers.google.com/google-ads/scripts/docs/solutions/flexible-budgets
 *     for more details.
 *
 * @author Google Ads Scripts Team [adwords-scripts@googlegroups.com]
 *
 * @version 2.1
 *
 * @changelog
 * - version 2.1
 *   - Split into info, config, and code.
 * - version 2.0
 *   - Updated to use new Google Ads scripts features.
 * - version 1.0.3
 *   - Add support for video and shopping campaigns.
 * - version 1.0.2
 *   - Use setAmount on the budget instead of campaign.setBudget.
 * - version 1.0.1
 *   - Improvements to time zone handling.
 * - version 1.0
 *   - Released initial version.
 */

/**
 * Configuration to be used for the Flexible Budgets script.
 */

CONFIG = {
  'total_budget': 500,
  'campaign_name': 'Special Promotion',
  'start_date': 'November 1, 2021 0:00:00 -0500',
  'end_date': 'December 1, 2021 0:00:00 -0500'
};

const TOTAL_BUDGET = CONFIG.total_budget;
const CAMPAIGN_NAME = CONFIG.campaign_name;
const START_DATE = new Date(CONFIG.start_date);
const END_DATE = new Date(CONFIG.end_date);

function main() {
  testBudgetStrategy(calculateBudgetEvenly, 10, 500);
//  setNewBudget(calculateBudgetEvenly, CAMPAIGN_NAME, TOTAL_BUDGET,
//      START_DATE, END_DATE);
}

function setNewBudget(budgetFunction, campaignName, totalBudget, start, end) {
  const today = new Date();
  if (today < start) {
    console.log('Not ready to set budget yet');
    return;
  }
  const campaign = getCampaign(campaignName);
  const costSoFar = campaign.getStatsFor(
        getDateStringInTimeZone('yyyyMMdd', start),
        getDateStringInTimeZone('yyyyMMdd', end)).getCost();
  const daysSoFar = datediff(start, today);
  const totalDays = datediff(start, end);
  const newBudget = budgetFunction(costSoFar, totalBudget, daysSoFar,
                                   totalDays);
  campaign.getBudget().setAmount(newBudget);
}

function calculateBudgetEvenly(costSoFar, totalBudget, daysSoFar, totalDays) {
  const daysRemaining = totalDays - daysSoFar;
  const budgetRemaining = totalBudget - costSoFar;
  if (daysRemaining <= 0) {
    return budgetRemaining;
  } else {
    return budgetRemaining / daysRemaining;
  }
}

function calculateBudgetWeighted(costSoFar, totalBudget, daysSoFar,
    totalDays) {
  const daysRemaining = totalDays - daysSoFar;
  const budgetRemaining = totalBudget - costSoFar;
  if (daysRemaining <= 0) {
    return budgetRemaining;
  } else {
    return budgetRemaining / (2 * daysRemaining - 1);
  }
}

function testBudgetStrategy(budgetFunc, totalDays, totalBudget) {
  let daysSoFar = 0;
  let costSoFar = 0;
  while (daysSoFar <= totalDays + 2) {
    const newBudget = budgetFunc(costSoFar, totalBudget, daysSoFar, totalDays);
    console.log(`Day ${daysSoFar + 1} of ${totalDays}, new budget ` +
                `${newBudget}, cost so far ${costSoFar}`);
    costSoFar += newBudget;
    daysSoFar += 1;
  }
}

/**
 * Returns number of days between two dates, rounded up to nearest whole day.
 */
function datediff(from, to) {
  const millisPerDay = 1000 * 60 * 60 * 24;
  return Math.ceil((to - from) / millisPerDay);
}

function getDateStringInTimeZone(format, date, timeZone) {
  date = date || new Date();
  timeZone = timeZone || AdsApp.currentAccount().getTimeZone();
  return Utilities.formatDate(date, timeZone, format);
}

/**
 * Finds a campaign by name, whether it is a regular, video, or shopping
 * campaign, by trying all in sequence until it finds one.
 *
 * @param {string} campaignName The campaign name to find.
 * @return {Object} The campaign found, or null if none was found.
 */
function getCampaign(campaignName) {
  const selectors = [AdsApp.campaigns(), AdsApp.videoCampaigns(),
      AdsApp.shoppingCampaigns()];
  for (const selector of selectors) {
    const campaignIter = selector
        .withCondition(`CampaignName = "${campaignName}"`)
        .get();
    if (campaignIter.hasNext()) {
      return campaignIter.next();
    }
  }
  throw new Error(`Could not find specified campaign: ${campaignName}`);
}