Register for one of our upcoming Google Ads Scripts workshops.

Relatório da consulta da pesquisa: conta de administrador

This is a Manager Account script. For operating on a single account, use the Single Account version of the script.

O Relatório da consulta da pesquisa da MCC estende a geração do Relatório da consulta da pesquisa em várias contas em uma única MCC. O script usa o Relatório de desempenho da consulta da pesquisa para encontrar termos de pesquisa indesejados e adicioná-los como palavras-chave exatas negativas (ou positivas).

O script lê uma planilha para a configuração de limites. Existe uma linha para a configuração padrão e linhas para configurações de contas específicas (uma linha para cada conta especificada). Ao processar cada conta na MCC, se a conta for encontrada nas configurações de contas específicas, a configuração correspondente será usada. Caso contrário, a configuração padrão será aplicada.

Como funciona

O script funciona da mesma forma que o script de consulta de pesquisa de conta única. A única funcionalidade adicional é que ele suporta várias contas por meio da planilha especificada.

A primeira coluna na planilha é o ID da conta. Ele deve ser de uma conta de um anunciante e não de uma conta da MCC. Pode existir uma linha para a configuração padrão (com o ID da conta como "Padrão") na planilha. Nesse caso, ela precisa ser a primeira linha. Em seguida, cada linha especifica a configuração de uma conta específica. Deve existir somente uma linha para uma conta específica. Caso contrário, somente a primeira linha da conta terá efeito.

Ao processar uma conta na MCC, se houver uma configuração de conta específica para ela, o script a aplicará. Caso contrário o script ignorará essa conta.

Iterações em todas as contas gerenciadas

Inicialmente, o script é executado no contexto da conta da MCC. Primeiro ele chama

var mccAccount = AdWordsApp.currentAccount();
para armazenar a conta da MCC. Em seguida, ele chama
var accountIterator = MccApp.accounts().get();
para gerar um iterador de todas as contas gerenciadas na MCC.

Em cada iteração, o script chama

MccApp.select(account);
para mudar para o contexto da conta gerenciada. Assim, ele pode fazer operações nessa conta. Depois de processar todas as contas gerenciadas, o script chama
MccApp.select(mccAcount);
para restaurar o contexto da conta da MCC.

Solicitar um relatório com AWQL

Você pode solicitar um relatório usando AWQL desta maneira:

var report = AdWordsApp.report(
   "SELECT Query,Clicks,Cost,Ctr,ClickConversionRate,CostPerConvertedClick,ConvertedClicks,CampaignId,AdGroupId " +
   " FROM SEARCH_QUERY_PERFORMANCE_REPORT " +
   " WHERE " +
       " ConvertedClicks > 0" +
       " AND Impressions > " + IMPRESSIONS_THRESHOLD +
       " AND AverageCpc > " + AVERAGE_CPC_THRESHOLD +
   " DURING LAST_7_DAYS");
var rows = report.rows();

Quando você começar a fazer iterações nas linhas do relatório, os servidores de scripts do Google AdWords farão o download dos dados correspondentes no relatório solicitado e os armazenarão temporariamente. À medida que você faz iterações nas linhas, mais informações são enviadas para seu script.

Na AWQL acima, estamos solicitando o Relatório de desempenho da consulta da pesquisa (SEARCH_QUERY_PERFORMANCE_REPORT) e alguns campos de desempenho com dados relacionados aos últimos sete dias.

Como tomar decisões com dados do relatório

Em seguida, o script precisa fazer iterações nas linhas do relatório e decidir o que fazer com os dados do relatório:

while(rows.hasNext()) {
  var row = rows.next();
  if (parseFloat(row['Ctr']) < CTR_THRESHOLD) {
    addToMultiMap(negativeKeywords, row['AdGroupId'], row['Query']);
    allAdGroupIds[row['AdGroupId']] = true;
  } else if (parseFloat(row['CostPerConvertedClick']) < costPerConvThrsh) {
    addToMultiMap(positiveKeywords, row['AdGroupId'], row['Query']);
    allAdGroupIds[row['AdGroupId']] = true;
  }
}

Cada linha no relatório é um objeto JavaScript: uma matriz associativa em que a chave é o nome do campo solicitado e o valor é uma representação em string do valor do campo. Em seguida, o script analisa o valor do campo (que sempre será uma string) em um número e o compara com o CTR_THRESHOLD. Se a CTR (taxa de cliques) da palavra-chave estiver abaixo do limite, a palavra-chave será considerada insuficiente e adicionada à lista de palavras-chave negativas (a ser criada posteriormente). Também registramos o AdGroupId em um objeto diferente para permitir o envio de grupos de anúncios em massa.

Também acompanhamos palavras-chave acima do nosso limite de CTR e que têm um CostPerConversion razoável, e elas são adicionadas como palavras-chave positivas.

Como carregar grupos de anúncios em massa

Usando os AdGroupIds que registramos anteriormente, podemos carregar todos os grupos de anúncios em uma única solicitação:

var adGroupIdList = [];
for (var adGroupId in allAdGroupIds) {
  adGroupIdList.push(adGroupId);
}

var adGroups = AdWordsApp.adGroups().withIds(adGroupIdList).get();

Isso é muito mais eficiente do que carregá-los individualmente quando vemos uma palavra-chave a ser adicionada. É altamente recomendável usar códigos para carregar objetos em um lote durante o trabalho com relatórios.

Como adicionar palavras-chave a grupos de anúncios

Em seguida, fazemos iterações em todos os grupos de anúncios (que carregamos em massa) e adicionamos as palavras-chave apropriadas:

if (negativeKeywords[adGroup.getId()]) {
  for (var i = 0; i < negativeKeywords[adGroup.getId()].length; i++) {
    adGroup.createNegativeKeyword('[' + negativeKeywords[adGroup.getId()][i] + ']');
  }
}

Esse código verifica se temos palavras-chave negativas a serem adicionadas a esse grupo, executa loop em cada palavra e a adiciona como uma palavra-chave negativa de correspondência exata. Desse modo, não exibimos anúncios em pesquisas com esse texto exato.

Configuração

  • Configure um script com base em planilha usando o código-fonte abaixo. Use a planilha modelo de consulta de pesquisa da MCC.
  • Atualize SPREADSHEET_URL no código para refletir o URL da sua planilha.
  • Agende o script para ser executado Semanalmente.

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 MCC Search Query Report
 *
 * @overview The MCC Search Query Report script uses the Search Query Performance
 *     Report to find undesired search terms in accounts under an MCC account
 *     and add them as negative (or positive) exact keywords. See
 *     https://developers.google.com/adwords/scripts/docs/solutions/mccapp-search-query
 *     for more details.
 *
 * @author AdWords Scripts Team [adwords-scripts@googlegroups.com]
 *
 * @version 1.0.3
 *
 * @changelog
 * - version 1.0.3
 *   - Upgrade to API version v201609.
 * - version 1.0.2
 *   - Added validation for external spreadsheet setup.
 * - version 1.0.1
 *   - Improvements to time zone handling.
 * - version 1.0
 *   - Released initial version.
 */

var SPREADSHEET_URL = 'YOUR_SPREADSHEET_URL';

// Please fix the following variables if you need to reformat the spreadsheet
// column numbers of each config column. Column A in your spreadsheet has
// column number of 1, B has number of 2, etc.
var COLUMN = {
  accountId: 2,
  impressionsThreshold: 3,
  averageCpcThreshold: 4,
  ctrThreshold: 5,
  costPerConvThreshold: 6
};

// Start row/column numbers and total columns of actual config
// (without header and margin)
var CONFIG = {
  startRow: 6,
  startColumn: 2,
  totalColumns: 5
};

// One currency unit is one million micro amount.
var MICRO_AMOUNT_MULTIPLIER = 1000000;

/**
 * Configuration to be used for running reports.
 */
var REPORTING_OPTIONS = {
  // Comment out the following line to default to the latest reporting version.
  apiVersion: 'v201705'
};

function main() {
  // Read config data from the spreadsheet
  Logger.log('Using spreadsheet - %s.', SPREADSHEET_URL);
  var spreadsheet = validateAndGetSpreadsheet(SPREADSHEET_URL);

  // Make sure the spreadsheet is using the account's timezone.
  spreadsheet.setSpreadsheetTimeZone(AdWordsApp.currentAccount().getTimeZone());
  var sheet = spreadsheet.getSheets()[0];

  var endRow = sheet.getLastRow();
  var rows = endRow - CONFIG.startRow + 1;
  var config = [];
  if (rows > 0) {
    config = sheet.getRange(CONFIG.startRow, CONFIG.startColumn,
               rows, CONFIG.totalColumns).getValues();
  }
  else {
    Logger.log('Empty config, abort!');
    return;
  }

  var mccAccount = AdWordsApp.currentAccount();
  sheet.getRange(2, 6).setValue(mccAccount.getCustomerId());

  var accountIterator = MccApp.accounts().get();
  while (accountIterator.hasNext()) {
    var account = accountIterator.next();
    processAccount(account, config);
  }

  // Update "Last execution" timestamp
  var today = new Date();
  sheet.getRange(1, 3).setValue(today);
  MccApp.select(mccAccount);
}

// Core logic for processing each account
function processAccount(account, config) {
  // Swith to current adwords account
  MccApp.select(account);
  var accountId = account.getCustomerId();

  var accountIdCol = COLUMN.accountId - CONFIG.startColumn;
  var impsThrshCol = COLUMN.impressionsThreshold - CONFIG.startColumn;
  var avgCpcThrshCol = COLUMN.averageCpcThreshold - CONFIG.startColumn;
  var ctrThrshCol = COLUMN.ctrThreshold - CONFIG.startColumn;
  var costPerConvThrshCol = COLUMN.costPerConvThreshold - CONFIG.startColumn;

  // Get config for this account, if not found use default entry,
  // if no default entry just skip
  var configIndex = -1;
  var hasDefault = (config[0][accountIdCol].toLowerCase() == 'default');
  var configStartRow = hasDefault ? 1 : 0;
  for (var i = configStartRow; i < config.length; i++) {
    if (config[i][accountIdCol] === accountId) {
      configIndex = i;
      break;
    }
  }

  if (configIndex == -1) {
    if (hasDefault) {
      Logger.log('Processing account %s with default config.', accountId);
      configIndex = 0;
    }
    else {
      Logger.log('Skipping account %s: no config found.', accountId);
      return;
    }
  }
  else {
    Logger.log('Processing account %s with account-specific config.',
               accountId);
  }

  var impsThrsh = config[configIndex][impsThrshCol];
  var avgCpcThrsh = config[configIndex][avgCpcThrshCol];
  var ctrThrsh = config[configIndex][ctrThrshCol];
  var costPerConvThrsh = config[configIndex][costPerConvThrshCol];

  var report = AdWordsApp.report(
      'SELECT Query, Clicks, Cost, Ctr, ConversionRate,' +
      ' CostPerConversion, Conversions, CampaignId, AdGroupId' +
      ' FROM SEARCH_QUERY_PERFORMANCE_REPORT' +
      ' WHERE ' +
          ' Conversions > 0' +
          ' AND Impressions > ' + impsThrsh +
          ' AND AverageCpc > ' + (avgCpcThrsh * MICRO_AMOUNT_MULTIPLIER) +
      ' DURING LAST_7_DAYS', REPORTING_OPTIONS);
  var rows = report.rows();

  var negativeKeywords = {};
  var positiveKeywords = {};
  var allAdGroupIds = {};
  // Iterate through search query and decide whether to add them as positive
  // or negative keywords (or ignore).
  while (rows.hasNext()) {
    var row = rows.next();
    if (parseFloat(row['Ctr']) < ctrThrsh) {
      addToMultiMap(negativeKeywords, row['AdGroupId'], row['Query']);
      allAdGroupIds[row['AdGroupId']] = true;
    } else if (parseFloat(row['CostPerConversion']) < costPerConvThrsh) {
      addToMultiMap(positiveKeywords, row['AdGroupId'], row['Query']);
      allAdGroupIds[row['AdGroupId']] = true;
    }
  }

  // Copy all the adGroupIds from the object into an array.
  var adGroupIdList = [];
  for (var adGroupId in allAdGroupIds) {
    adGroupIdList.push(adGroupId);
  }

  // Add the keywords as negative or positive to the applicable ad groups.
  var adGroups = AdWordsApp.adGroups().withIds(adGroupIdList).get();
  while (adGroups.hasNext()) {
    var adGroup = adGroups.next();
    var adGruopId = adGroup.getId();
    if (negativeKeywords[adGroupId]) {
      for (var i = 0; i < negativeKeywords[adGroupId].length; i++) {
        var curNegativeKeyword = '[' + negativeKeywords[adGroupId][i] + ']';
        adGroup.createNegativeKeyword(curNegativeKeyword);
        Logger.log('Update adGroup "%s": add negative keyword "%s".',
                   adGroupId, curNegativeKeyword);
      }
    }
    if (positiveKeywords[adGroupId]) {
      for (var i = 0; i < positiveKeywords[adGroupId].length; i++) {
        var curPositiveKeyword = '[' + positiveKeywords[adGroupId][i] + ']';
        var keywordOperation = adGroup.newKeywordBuilder()
            .withText(curPositiveKeyword)
            .build();
        Logger.log('Update adGroup "%s": add positive keyword "%s".',
                   adGroupId, curPositiveKeyword);
      }
    }
  }
}

// Helper function that stores queries with AdGroupId
function addToMultiMap(map, key, value) {
  if (!map[key]) {
    map[key] = [];
  }
  map[key].push(value);
}

/**
 * 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.