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 liquidação de outono". A estratégia de lances oferece 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 US $5.000 para anunciar nossa liquidação de outono e quisermos anunciar por 10 dias, poderemos definir um orçamento diário de US $500 para usar todo o orçamento. No entanto, isso pressupõe que gastaremos o valor total todos os dias E que queremos gastá-lo uniformemente. Não é possível informar ao Google Ads que você quer gastar a maior parte do seu orçamento nos últimos dias.

Este script ajustará dinamicamente o orçamento da sua campanha diariamente 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. Isso oferece 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 US $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 é comentada, indicando que ela só vai 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 os gastos sejam distribuídos uniformemente. Quando o limite de orçamento alocado é atingido, o orçamento é definido como zero, interrompendo os gastos.

Você pode mudar a estratégia de orçamento usada alterando a função usada ou modificando a própria função. O script vem com duas estratégias pré-criadas: calculateBudgetEvenly e calculateBudgetWeighted. Para definir uma estratégia de orçamento de teste ponderada, mude testBudgetStrategy da seguinte maneira:

testBudgetStrategy(calculateBudgetWeighted, 10, 500);

Clique em Visualizar e verifique a saída do registro. Observe que 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.

Alocar 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 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 dinheiro gastou até agora com o valor total a ser gasto e determinar onde você está na linha do tempo para todo o orçamento.

Em particular, essa estratégia de orçamento calcula quanto orçamento resta (totalBudget - costSoFar) e divide esse valor pelo dobro do 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 "dias lentos" em que o orçamento definido não é totalmente gasto.

Orçamento real

Quando estiver satisfeito com sua estratégia de orçamento, você precisará fazer algumas mudanças antes de programar a execução diária desse 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. Essa deve ser a data atual ou um dia no passado.
  • END_DATE: defina isso 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);
}

Programação

Programe esse script para ser executado diariamente, à meia-noite ou pouco depois no fuso horário local. Assim, o máximo possível do orçamento será direcionado para o dia seguinte. No entanto, os dados do relatório recuperados, como o custo, podem ter um atraso de cerca de 3 horas. Portanto, o parâmetro costSoFar pode estar referenciando o total de ontem para um script programado para ser executado após a meia-noite.

Configuração

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

    Instalar o modelo de script

  • Salve o script e clique no botão Visualizar. Esse script (por padrão) simula uma estratégia de orçamento com US $500 em 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}`);
}