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 terão um custo fixo associado a elas; por exemplo, "Quero gastar US $5.000 com nossas vendas de outono". A estratégia de lances oferece certo controle sobre como o orçamento diário é gasto, mas nenhum controle sobre como o orçamento é consumido durante a campanha.

Por exemplo, se quiséssemos gastar apenas R $5.000 para anunciar nossa liquidação de outono e quiséssemos anunciar por 10 dias, poderíamos definir um orçamento diário de R $500 para usar todo o orçamento. No entanto, isso pressupõe que gastaremos todo o valor por dia E que queremos gastar da mesma forma. Não é possível informar ao Google Ads que você quer gastar a maior parte do seu orçamento durante os ú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 em vários dias. Isso dá uma ideia melhor do que pode acontecer quando o script está programado para ser executado diariamente durante um período.

Por padrão, este script simula uma distribuição uniforme de orçamento de US $500,00 gastos ao longo de 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 vai executar apenas 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 alocado é atingido, o orçamento é definido como zero, interrompendo o gasto.

A estratégia de orçamento usada pode ser alterada mudando a função usada ou modificando a função em si. O script vem com duas estratégias predefinidas: calculateBudgetEvenly e calculateBudgetWeighted. Para definir uma estratégia de orçamento de teste ponderado, altere testBudgetStrategy da seguinte maneira:

testBudgetStrategy(calculateBudgetWeighted, 10, 500);

Clique em Visualizar e verifique a saída do registro. Essa estratégia de orçamento aloca menos orçamento no início do período e mais durante os ú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 estes argumentos:

costSoFar
Custo acumulado da campanha de START_DATE até hoje.
totalBudget
Gasto alocado de START_DATE para 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 descobre quanto orçamento resta (totalBudget - costSoFar) e divide esse valor pelo dobro do número de dias restantes. Ela pondera a distribuição do orçamento mais para o final da campanha. Usando o custo desde START_DATE, ela também considera "dias lentos", em que o orçamento definido não é totalmente gasto.

Criação de um orçamento de verdade

Quando estiver satisfeito com sua estratégia de orçamento, você precisará fazer algumas alterações antes de programar a execução diária desse script.

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

  • START_DATE: defina essa opção como o início da sua estratégia de orçamento. Deve ser a data atual ou um dia no passado.
  • END_DATE: defina como o último dia que você quer anunciar usando 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 deve 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, dados de relatórios recuperados, como o custo, podem atrasar cerca de três horas. Por isso, o parâmetro costSoFar pode estar referenciando o total de ontem para um script programado para ser executado após a meia-noite.

Instalaçã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, este script simula uma estratégia de orçamento com US $500 ao longo de 10 dias. A saída do registro 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}`);
}