Teste de lance

Ao determinar o melhor lance para as suas palavras-chave, convém testar níveis diferentes de lances. Dessa forma, é possível identificar quais funcionam melhor para atingir suas metas. Aqui, mostramos como ajustar sistematicamente seus lances para encontrar o "ponto certo" para seus lances de palavra-chave.

O script ajusta seus lances de palavra-chave com base em uma série de multiplicadores e registra os resultados de cada alteração.

Como funciona

Como trabalhar com planilhas

Este script usa uma Planilha do Google para armazenar o estado (por exemplo, os multiplicadores de lance e os lances iniciais) e o desempenho do catálogo (para cada intervalo de teste do lance, registramos o lance de palavra-chave, a CTR [taxa de cliques], os cliques e as impressões).

Os multiplicadores de lance são aplicados sucessivamente para cada interação do script. Cada execução aplicará o próximo multiplicador de lance não usado aos seus lances de palavra-chave. Por exemplo, um lance inicial de US$ 1 e multiplicadores de 0,8 e 1,2 resultaria em lances de US$ 0,80 e US$ 1,20.

Como atualizar lances

A função updateBids aplica o multiplicador desta interação a todas as palavras-chave na campanha escolhida por você:

var keywordIter = campaign.keywords().get();
while (keywordIter.hasNext()) {
  var keyword = keywordIter.next();
  var oldBid = startingBids[keyword.getText()];
  if (!oldBid) {
    // If we don't have a starting bid, keyword has been added since we
    // started testing.
    oldBid = keyword.bidding().getCpc() || keyword.getAdGroup().bidding().getCpc();
    startingBids[keyword.getText()] = oldBid;
  }
  var newBid = oldBid * multiplier;
  keyword.bidding().setCpc(newBid);
}

O código acima usa o CPC máximo da palavra-chave (ou o CPC máximo padrão do grupo de anúncios caso a palavra-chave não tenha um lance) e aplica o multiplicador. Ele também detecta se uma palavra-chave foi adicionada entre as execuções do script e armazena o CPC máximo atual para referência futura.

Como gerar relatórios sobre o desempenho do lance

Sempre que o script é executado com os lances aplicados a pelo menos um período (semana, dia etc.), a função outputReport é executada. Usamos a data marcada na guia "Multiplicadores" e a data de hoje como o período na consulta de métricas para cada palavra-chave. Armazenamos isso, além do lance de palavra-chave durante o período definido pelo período, em uma página à parte para análise posterior.

// Create a new sheet to output keywords to.
var reportSheet = spreadsheet.insertSheet(start + ' - ' + end);
var campaign = getCampaign();

var rows = [['Keyword', 'Max CPC', 'Clicks', 'Impressions', 'Ctr']];
var keywordIter = campaign.keywords().get();
while (keywordIter.hasNext()) {
  var keyword = keywordIter.next();
  var stats = keyword.getStatsFor(start, end);
  rows.push([keyword.getText(), keyword.bidding().getCpc(), stats.getClicks(),
      stats.getImpressions(), stats.getCtr()]);
}

reportSheet.getRange(1, 1, rows.length, 5).setValues(rows);

Estamos fazendo iterações em cada palavra-chave na campanha e adicionando a uma matriz uma linha que contém "Palavra-chave", "CPC máximo", "Cliques", "Impressões" e "CTR". Em seguida, essa matriz é gravada na nova página (nomeada de acordo com as datas de início e de término do nosso relatório).

Se você usa indicadores principais de desempenho que não estão presentes no script, pode alterar essa lógica para incluí-los. Para isso, adicione outra entrada na primeira linha (linha do cabeçalho) desta forma:

var rows = [['Keyword', 'Max CPC', 'Clicks', 'Impressions', 'Ctr']];

e modifique o script para incluir também esta métrica:

rows.push([keyword.getText(), keyword.bidding().getCpc(), stats.getClicks(),
    stats.getImpressions(), stats.getCtr()]);

Programação

Recomendamos que você escolha uma campanha para teste e agende o script para ser executado Semanalmente (ou em qualquer outro agendamento da sua preferência). No intervalo agendado, o script gerará um relatório sobre o desempenho do período anterior (se aplicável) e aplicar um novo multiplicador de lance.

A função principal contém a lógica que gerencia cada etapa do seu teste de lance. Assim que o teste de lance for concluído, o script registrará esse fato, e as execuções futuras não farão alterações adicionais:

if (finishedReporting) {
  Logger.log('Script complete, all bid modifiers tested and reporting. ' +
    'Please remove this script\'s schedule.');
}

Como analisar os resultados do teste

O script aplicou uma matriz de modificadores de lance às palavras-chave e registrou o desempenho desses valores em todas as palavras-chave. Agora é o momento de decidir o que fazer com esses dados. Lembre-se de que é possível que um modificador de lance não ofereça o mesmo desempenho para todas as palavras-chave.

Registramos o CPC máximo da palavra-chave e diversos indicadores de desempenho. Cabe a você determinar o que é mais importante. Em seguida, você deve avaliar cada palavra-chave nos vários intervalos e usar seu IPD (indicador principal de desempenho) para escolher o melhor lance para cada palavra-chave.

Configuração

  • Faça uma cópia desta planilha (Arquivo -> Fazer uma cópia).
  • Observe o URL da cópia.
  • Crie um novo script do Google AdWords usando o código-fonte abaixo.
  • Altere o valor da variável SPREADSHEET_URL para o URL da cópia da planilha. Em seguida, escolha uma campanha para realizar o teste de lance e altere o valor da variável CAMPAIGN_NAME, de acordo com a campanha escolhida.

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 Bid Testing
 *
 * @overview The Bid Testing script allows you to try different levels of
 *     bidding for keywords in your advertiser account to determine what bids
 *     work best to achieve your goals.
 *     See https://developers.google.com/adwords/scripts/docs/solutions/bid-testing
 *     for more details.
 *
 * @author AdWords Scripts Team [adwords-scripts@googlegroups.com]
 *
 * @version 1.0.3
 *
 * @changelog
 * - version 1.0.3
 *   - Replaced deprecated keyword.setMaxCpc() and keyword.getMaxCpc().
 * - version 1.0.2
 *   - Added validation for user settings.
 * - version 1.0.1
 *   - Improvements to time zone handling.
 * - version 1.0
 *   - Released initial version.
 */

var SPREADSHEET_URL = 'YOUR_SPREADSHEET_URL';
var CAMPAIGN_NAME = 'YOUR_CAMPAIGN_NAME';

function main() {
  validateCampaignName();
  Logger.log('Using spreadsheet - %s.', SPREADSHEET_URL);
  var spreadsheet = validateAndGetSpreadsheet(SPREADSHEET_URL);
  spreadsheet.setSpreadsheetTimeZone(AdWordsApp.currentAccount().getTimeZone());

  var multipliersSheet = spreadsheet.getSheetByName('Multipliers');

  var multipliers = multipliersSheet.getDataRange().getValues();
  // Find if we have a multiplier left to apply.
  var multiplierRow = 1;
  for (; multiplierRow < multipliers.length; multiplierRow++) {
    // if we haven't marked a multiplier as applied, use it.
    if (!multipliers[multiplierRow][1]) {
      break;
    }
  }

  var today = Utilities.formatDate(new Date(),
      AdWordsApp.currentAccount().getTimeZone(), 'yyyyMMdd');

  var shouldReport = multiplierRow > 1;
  var shouldIncreaseBids = multiplierRow < multipliers.length;
  var finishedReporting = multipliersSheet.getSheetProtection().isProtected();

  if (shouldReport && !finishedReporting) {
    // If we have at least one multiplier marked as applied,
    // let's record performance since the last time we ran.
    var lastRun = multipliers[multiplierRow - 1][1];
    if (lastRun == today) {
      Logger.log('Already ran today, skipping');
      return;
    }
    outputReport(spreadsheet, lastRun, today);

    if (!shouldIncreaseBids) {
      // We've reported one iteration after we finished bids, so mark the sheet
      // protected.
      var permissions = multipliersSheet.getSheetProtection();
      permissions.setProtected(true);
      multipliersSheet.setSheetProtection(permissions);
      Logger.log('View bid testing results here: ' + SPREADSHEET_URL);
    }
  }

  if (shouldIncreaseBids) {
    // If we have a multiplier left to apply, let's do so.
    updateBids(spreadsheet, multipliers[multiplierRow][0]);
    multipliers[multiplierRow][1] = today;
    // Mark multiplier as applied.
    multipliersSheet.getDataRange().setValues(multipliers);
  }

  if (finishedReporting) {
    Logger.log('Script complete, all bid modifiers tested and reporting. ' +
      'Please remove this script\'s schedule.');
  }
}

function updateBids(spreadsheet, multiplier) {
  Logger.log('Applying bid multiplier of ' + multiplier);

  var startingBids = getStartingBids(spreadsheet);
  if (!startingBids) {
    startingBids = recordStartingBids(spreadsheet);
  }
  var campaign = getCampaign();
  var keywordIter = campaign.keywords().get();
  while (keywordIter.hasNext()) {
    var keyword = keywordIter.next();
    var oldBid = startingBids[keyword.getText()];
    if (!oldBid) {
      // If we don't have a starting bid, keyword has been added since we
      // started testing.
      oldBid = keyword.bidding().getCpc() || keyword.getAdGroup().bidding().getCpc();
      startingBids[keyword.getText()] = oldBid;
    }
    var newBid = oldBid * multiplier;
    keyword.bidding().setCpc(newBid);
  }
  saveStartingBids(spreadsheet, startingBids);
}

function outputReport(spreadsheet, start, end) {
  Logger.log('Reporting on ' + start + ' -> ' + end);

  // Create a new sheet to output keywords to.
  var reportSheet = spreadsheet.insertSheet(start + ' - ' + end);
  var campaign = getCampaign();

  var rows = [['Keyword', 'Max CPC', 'Clicks', 'Impressions', 'Ctr']];
  var keywordIter = campaign.keywords().get();
  while (keywordIter.hasNext()) {
    var keyword = keywordIter.next();
    var stats = keyword.getStatsFor(start, end);
    rows.push([keyword.getText(), keyword.bidding().getCpc(), stats.getClicks(),
        stats.getImpressions(), stats.getCtr()]);
  }

  reportSheet.getRange(1, 1, rows.length, 5).setValues(rows);
}

function recordStartingBids(spreadsheet) {
  var startingBids = {};
  var keywords = getCampaign().keywords().get();
  while (keywords.hasNext()) {
    var keyword = keywords.next();
    var bid = keyword.bidding().getCpc() || keyword.getAdGroup().bidding().getCpc();
    startingBids[keyword.getText()] = bid;
  }
  saveStartingBids(spreadsheet, startingBids);
  return startingBids;
}

function getStartingBids(spreadsheet) {
  var sheet = spreadsheet.getSheetByName('Starting Bids');
  if (!sheet) {
    return;
  }
  var rawData = sheet.getDataRange().getValues();
  var startingBids = {};
  for (var i = 0; i < rawData.length; i++) {
    startingBids[rawData[i][0]] = rawData[i][1];
  }
  return startingBids;
}

function saveStartingBids(spreadsheet, startingBids) {
  var sheet = spreadsheet.getSheetByName('Starting Bids');
  if (!sheet) {
    sheet = spreadsheet.insertSheet('Starting Bids');
  }
  var rows = [];
  for (var keyword in startingBids) {
    rows.push([keyword, startingBids[keyword]]);
  }
  sheet.getRange(1, 1, rows.length, 2).setValues(rows);
}

function dateToString(date) {
  return date.getFullYear() + zeroPad(date.getMonth() + 1) +
      zeroPad(date.getDate());
}

function zeroPad(n) {
  if (n < 10) {
    return '0' + n;
  } else {
    return '' + n;
  }
}

function getCampaign() {
  return AdWordsApp.campaigns().withCondition("Name = '" +
      CAMPAIGN_NAME + "'").get().next();
}

/**
 * Validates the provided campaign name and throws a descriptive error
 * if the user has not changed the email from the default fake name.
 *
 * @throws {Error} If the name is the default fake name.
 */
function validateCampaignName(){
  if (CAMPAIGN_NAME == "YOUR_CAMPAIGN_NAME") {
    throw new Error('Please use a valid campaign name.');
  }
}

/**
 * Validates the provided spreadsheet URL
 * to make sure that it's set up properly. Throws a descriptive error message
 * if validation fails.
 *
 * @param {string} spreadsheeturl The URL of the spreadsheet to open.
 * @return {Spreadsheet} The spreadsheet object itself, fetched from the URL.
 * @throws {Error} If the spreadsheet URL hasn't been set
 */
function validateAndGetSpreadsheet(spreadsheeturl) {
  if (spreadsheeturl == 'YOUR_SPREADSHEET_URL') {
    throw new Error('Please specify a valid Spreadsheet URL. You can find' +
        ' a link to a template in the associated guide for this script.');
  }
  return SpreadsheetApp.openByUrl(spreadsheeturl);
}

Enviar comentários sobre…

Precisa de ajuda? Acesse nossa página de suporte.