Пометка ключевых слов – управляющий аккаунт

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

Внесение крупномасштабных изменений в ключевые слова (например, отключение неэффективных вариантов) может отнимать много времени. Скрипт "Пометка ключевых слов" упрощает эту задачу, автоматически применяя ярлыки к ключевым словам в соответствии с заданными вами правилами. После этого вы сможете с легкостью фильтровать ключевые слова в интерфейсе AdWords и вносить нужные изменения, в том числе с помощью других скриптов.

Вот несколько примеров применения этого скрипта:

  • Пометка ключевых слов, эффективность которых в последнее время была неудовлетворительной. Затем их можно отфильтровать в аккаунте AdWords и изменить для них ставки, приостановить или вовсе удалить их.
  • Пометка ключевых слов, содержащих название вашего бренда или одного из ваших продуктов. Позже вы сможете использовать этот ярлык для сегментирования отчета по эффективности ключевых слов для более глубокого анализа статистики.
  • Пометка ключевых слов, для которых вы хотите изменить ставки. Вы сможете просмотреть эти ярлыки в интерфейсе AdWords, прежде чем вносить какие-либо массовые изменения.
  • Пометка всех ключевых слов показателем качества. После этого пометьте ключевые слова, текущий показатель качества которых не совпадает с предыдущим (показанным в ярлыке).
  • Любые сочетания этих действий и ещё многое другое.

При пометке новых ключевых слов скрипт отправляет электронное сообщение со ссылкой на таблицу.

Принцип работы

Вы можете задавать правила в простом формате, используя следующие поля:

  • conditions (необязательно). Список условий KeywordSelector. Они могут, например, выбирать ключевые слова в зависимости от показателей эффективности.
  • dateRange (необязательно). Диапазон дат KeywordSelector для выбора на основе полей статистики. Если этот параметр не указан, используется диапазон дат по умолчанию.
  • filter (необязательно). Функция, которая применяется к каждому полученному ключевому слову, чтобы определить, соответствует ли оно правилу. Это позволяет задать более сложную логику в полях ключевых слов, для которых нельзя использовать conditions.
  • labelName (обязательно). Название ярлыка, применяемое к любым ключевым словам, которые соответствуют правилу и у которых ещё нет этого ярлыка.

Вот пример правила, определяющего и помечающего неэффективные ключевые слова, связанные с брендом:

{
  conditions: [
    'Ctr < 0.02',
    'AverageCpc > 1',
  ],
  dateRange: 'LAST_7_DAYS',
  filter: function(keyword) {
    var brands = ['Product A', 'Product B', 'Product C'];
    var text = keyword.getText();
    for (var i = 0; i < brands.length; i++) {
      if (text.indexOf(brand[i]) >= 0) {
        return true;
      }
    }
    return false;
  },
  labelName: 'Underperforming Branded'
}

Это правило помечает все ключевые слова, CTR которых был ниже 2%, а цена за клик выше 1 доллара США за последние 7 дней, если в тексте имеется хотя бы одно из трех брендовых названий.

Как правило, вас будет интересовать пометка только активных ключевых слов, входящих в активную группу объявлений и кампанию. Вместо того чтобы указывать эти условия в каждом правиле, с помощью скрипта можно задать глобальные условия, которые будут использоваться во всех правилах:

GLOBAL_CONDITIONS: [
  'CampaignStatus = ENABLED',
  'AdGroupStatus = ENABLED',
  'Status = ENABLED'
]

В основе скрипта лежит функция, которая получает правило, создает объект KeywordSelector, используя глобальные и специфичные условия, и применяет этот фильтр к каждому полученному ключевому слову:

function getKeywordsForRule(rule) {
  var selector = AdWordsApp.keywords();

  // Add global conditions.
  for (var i = 0; i < CONFIG.GLOBAL_CONDITIONS.length; i++) {
    selector = selector.withCondition(CONFIG.GLOBAL_CONDITIONS[i]);
  }

  // Add selector conditions for this rule.
  if (rule.conditions) {
    for (var i = 0; i < rule.conditions.length; i++) {
      selector = selector.withCondition(rule.conditions[i]);
    }
  }

  // Exclude keywords that already have the label.
  selector.withCondition('LabelNames CONTAINS_NONE ["' + rule.labelName + '"]');

  // Add a date range.
  selector = selector.forDateRange(rule.dateRange || CONFIG.DEFAULT_DATE_RANGE);

  // Get the keywords.
  var iterator = selector.get();
  var keywords = [];

  // Check filter conditions for this rule.
  while (iterator.hasNext()) {
    var keyword = iterator.next();

    if (!rule.filter || rule.filter(keyword)) {
      keywords.push(keyword);
    }
  }

  return keywords;
}

Этот скрипт отправляет электронное сообщение со ссылкой на таблицу, где перечислены все помеченные им ключевые слова. Позже вы сможете войти в интерфейс AdWords и посмотреть, не нужно ли изменить эти ключевые слова, например приостановить их, удалить или установить для них другие ставки.

Чтобы обеспечить параллельное выполнение, скрипт использует метод executeInParallel. Одновременно обрабатывается не более 50 аккаунтов. Чтобы обеспечить успешное выполнение скрипта, можно настроить в ACCOUNT_LABEL обработку лишь части аккаунтов. Чтобы обработать больше аккаунтов, можно создать несколько экземпляров скрипта и для каждого использовать свои настройки ACCOUNT_LABEL

Планирование

Насколько часто запускать скрипт, зависит от ваших целей. Например, если вы помечаете неэффективные ключевые слова, можно запланировать еженедельное или даже ежедневное выполнение, чтобы быстро выявить их и устранить проблему. С другой стороны, если вы используете скрипт лишь от случая к случаю, нет никакой необходимости планировать его регулярное выполнение.

Настройка

  • Создайте новый скрипт с приведенным ниже кодом. Используйте копию таблицы.
  • Задайте правила пометки, обновив массив RULES. Ниже приведен пример исходного кода для пометки неэффективных ключевых слов, связанных с вашим брендом, а также неэффективных общих ключевых слов.
  • Не забудьте обновить SPREADSHEET_URL и RECIPIENT_EMAILS в скрипте.
  • Если требуется обработать только часть аккаунтов, используйте ACCOUNT_LABEL.

Исходный код

// 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 Keyword Labeler - Manager Accounts
 *
 * @overview The Keyword Labeler script labels keywords based on rules that
 *     you define. For example, you can create a rule to label keywords that
 *     are underperforming. Later, you can filter for this label in AdWords
 *     to decide whether to pause or remove those keywords. Rules don't have
 *     to be based solely on a keyword's performance. They can also be based
 *     on properties of a keyword such as its text or match type. For example,
 *     you could define "branded" keywords as those containing proper nouns
 *     associated with your brand, then label those keywords based on
 *     different performance thresholds versus "non-branded" keywords.
 *     Finally, the script sends an email linking to a spreadsheet when new
 *     keywords have been labeled. See
 *     https://developers.google.com/adwords/scripts/docs/solutions/mccapp-labels
 *     for more details.
 *
 * @author AdWords Scripts Team [adwords-scripts@googlegroups.com]
 *
 * @version 1.1.2
 *
 * @changelog
 * - version 1.1.2
 *   - Added validation for external spreadsheet setup.
 * - version 1.1.1
 *   - Improvements to time zone handling.
 * - version 1.1
 *   - Modified to allow generic rules and labeling.
 * - version 1.0
 *   - Released initial version.
 */

var CONFIG = {
  // URL of the spreadsheet template.
  // This should be a copy of https://goo.gl/uhK6nS.
  SPREADSHEET_URL: 'YOUR_SPREADSHEET_URL',

  // Array of addresses to be alerted via email if labels are applied.
  RECIPIENT_EMAILS: [
    'YOUR_EMAIL_HERE'
  ],

  // Label on the accounts to be processed.
  // Leave blank to include all accounts.
  ACCOUNT_LABEL: '',

  // Selector conditions to apply for all rules.
  GLOBAL_CONDITIONS: [
    'CampaignStatus = ENABLED',
    'AdGroupStatus = ENABLED',
    'Status = ENABLED'
  ],

  // Default date range over which statistics fields are retrieved.
  // Used when fetching keywords if a rule doesn't specify a date range.
  DEFAULT_DATE_RANGE: 'LAST_7_DAYS'
};

/**
 * Defines the rules by which keywords will be labeled.
 * The labelName field is required. Other fields may be null.
 * @type {Array.<{
 *     conditions: Array.<string>,
 *     dateRange: string,
 *     filter: function(Object): boolean,
 *     labelName: string,
 *   }>
 * }
 */
var RULES = [
  {
    conditions: [
      'Ctr < 0.02',
      'AverageCpc > 1',
    ],
    filter: function(keyword) {
      var brands = ['Product A', 'Product B', 'Product C'];
      var text = keyword.getText();
      for (var i = 0; i < brands.length; i++) {
        if (text.indexOf(brand[i]) >= 0) {
          return true;
        }
      }
      return false;
    },
    labelName: 'Underperforming Branded'
  },

  {
    conditions: [
      'Ctr < 0.01',
      'AverageCpc > 2',
    ],
    labelName: 'Underperforming'
  }
];

function main() {
  validateEmailAddresses();
  var accountSelector = MccApp.accounts();

  if (CONFIG.ACCOUNT_LABEL) {
    accountSelector = accountSelector
      .withCondition('LabelNames CONTAINS "' + CONFIG.ACCOUNT_LABEL + '"');
  }

  accountSelector.executeInParallel('processAccount', 'processResults');
}

/**
 * Processes the rules on the current account.
 *
 * @return {Array.<Object>} An array of changes made, each having
 *     a customerId, campaign name, ad group name, label name,
 *     and keyword text that the label was applied to.
 */
function processAccount() {
  ensureAccountLabels();
  var changes = applyLabels();

  return JSON.stringify(changes);
}

/**
 * Processes the results of the script.
 *
 * @param {Array.<Object>} accountResults An array of changes made in
 *     each account, each an array having a customerId, campaign name,
 *     ad group name, label name, and keyword text that the label was applied
 *     to.
 */
function processResults(accountResults) {
  var allResults = [];

  for (var i = 0; i < accountResults.length; i++) {
    allResults = allResults.concat(JSON.parse
                                   (accountResults[i].getReturnValue()));
  }

  if (allResults.length > 0) {
    var spreadsheetUrl = saveToSpreadsheet(allResults, CONFIG.RECIPIENT_EMAILS);
    sendEmail(spreadsheetUrl, CONFIG.RECIPIENT_EMAILS);
  } else {
    Logger.log('No labels were applied.');
  }
}

/**
 * Retrieves the names of all labels in the account.
 *
 * @return {Array.<string>} An array of label names.
 */
function getAccountLabelNames() {
  var labelNames = [];
  var iterator = AdWordsApp.labels().get();

  while (iterator.hasNext()) {
    labelNames.push(iterator.next().getName());
  }

  return labelNames;
}

/**
 * Checks that the account has a label for each rule and
 * creates the rule's label if it does not already exist.
 * Throws an exception if a rule does not have a labelName.
 */
function ensureAccountLabels() {
  var labelNames = getAccountLabelNames();

  for (var i = 0; i < RULES.length; i++) {
    var labelName = RULES[i].labelName;

    if (!labelName) {
      throw 'Missing labelName for rule #' + i;
    }

    if (labelNames.indexOf(labelName) == -1) {
      AdWordsApp.createLabel(labelName);
      labelNames.push(labelName);
    }
  }
}

/**
 * Retrieves the keywords in an account satisfying a rule
 * and that do not already have the rule's label.
 *
 * @param {Object} rule An element of the RULES array.
 * @return {Array.<Object>} An array of keywords.
 */
function getKeywordsForRule(rule) {
  var selector = AdWordsApp.keywords();

  // Add global conditions.
  for (var i = 0; i < CONFIG.GLOBAL_CONDITIONS.length; i++) {
    selector = selector.withCondition(CONFIG.GLOBAL_CONDITIONS[i]);
  }

  // Add selector conditions for this rule.
  if (rule.conditions) {
    for (var i = 0; i < rule.conditions.length; i++) {
      selector = selector.withCondition(rule.conditions[i]);
    }
  }

  // Exclude keywords that already have the label.
  selector.withCondition('LabelNames CONTAINS_NONE ["' + rule.labelName + '"]');

  // Add a date range.
  selector = selector.forDateRange(rule.dateRange || CONFIG.DEFAULT_DATE_RANGE);

  // Get the keywords.
  var iterator = selector.get();
  var keywords = [];

  // Check filter conditions for this rule.
  while (iterator.hasNext()) {
    var keyword = iterator.next();

    if (!rule.filter || rule.filter(keyword)) {
      keywords.push(keyword);
    }
  }

  return keywords;
}

/**
 * For each rule, determines the keywords matching the rule and which
 * need to have a label newly applied, and applies it.
 *
 * @return {Array.<Object>} An array of changes made, each having
 *     a customerId, campaign name, ad group name, label name,
 *     and keyword text that the label was applied to.
 */
function applyLabels() {
  var changes = [];
  var customerId = AdWordsApp.currentAccount().getCustomerId();

  for (var i = 0; i < RULES.length; i++) {
    var rule = RULES[i];
    var keywords = getKeywordsForRule(rule);

    for (var j = 0; j < keywords.length; j++) {
      var keyword = keywords[j];

      keyword.applyLabel(rule.labelName);

      changes.push({
        customerId: customerId,
        campaignName: keyword.getCampaign().getName(),
        adGroupName: keyword.getAdGroup().getName(),
        labelName: rule.labelName,
        keywordText: keyword.getText(),
      });
    }
  }

  return changes;
}

/**
 * Outputs a list of applied labels to a new spreadsheet and gives editor access
 * to a list of provided emails.
 *
 * @param {Array.<Object>} changes An array of changes made, each having
 *     a customerId, campaign name, ad group name, label name,
 *     and keyword text that the label was applied to.
 * @param {Array.<Object>} emails An array of email addresses.
 * @return {string} The URL of the spreadsheet.
 */
function saveToSpreadsheet(changes, emails) {
  var template = verifyAndGetSpreadsheet(CONFIG.SPREADSHEET_URL);
  var spreadsheet = template.copy('Keyword Labels Applied');

  // Make sure the spreadsheet is using the account's timezone.
  spreadsheet.setSpreadsheetTimeZone(AdWordsApp.currentAccount().getTimeZone());

  Logger.log('Saving changes to spreadsheet at ' + spreadsheet.getUrl());

  var headers = spreadsheet.getRangeByName('Headers');
  var outputRange = headers.offset(1, 0, changes.length);

  var outputValues = [];
  for (var i = 0; i < changes.length; i++) {
    var change = changes[i];
    outputValues.push([
      change.customerId,
      change.campaignName,
      change.adGroupName,
      change.keywordText,
      change.labelName
    ]);
  }
  outputRange.setValues(outputValues);

  spreadsheet.getRangeByName('RunDate').setValue(new Date());

  for (var i = 0; i < emails.length; i++) {
    spreadsheet.addEditor(emails[i]);
  }

  return spreadsheet.getUrl();
}

/**
 * Sends an email to a list of email addresses with a link to a spreadsheet.
 *
 * @param {string} spreadsheetUrl The URL of the spreadsheet.
 * @param {Array.<Object>} emails An array of email addresses.
 */
function sendEmail(spreadsheetUrl, emails) {
  MailApp.sendEmail(emails.join(','), 'Keywords Newly Labeled',
      'Keywords have been newly labeled in your' +
      'AdWords account(s). See ' +
      spreadsheetUrl + ' for details.');
}

/**
 * DO NOT EDIT ANYTHING BELOW THIS LINE.
 * Please modify your spreadsheet URL and email addresses at the top of the file
 * only.
 */

/**
 * Validates the provided spreadsheet URL and email address
 * to make sure that they're 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 or email 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.');
  }
  var spreadsheet = SpreadsheetApp.openByUrl(spreadsheeturl);
  return spreadsheet;
}

/**
 * Validates the provided email address to make sure it's not the default.
 * Throws a descriptive error message if validation fails.
 *
 * @throws {Error} If the list of email addresses is still the default
 */
function validateEmailAddresses() {
  if (CONFIG.RECIPIENT_EMAILS &&
      CONFIG.RECIPIENT_EMAILS[0] == 'YOUR_EMAIL_HERE') {
    throw new Error('Please specify a valid email address.');
  }
}

Оставить отзыв о...

Текущей странице
Скрипты AdWords
Скрипты AdWords