Автоматизируем работу с помощью скриптов AdWords

У маркетологов, работающих с контекстной рекламой в Google AdWords, много времени уходит на важную, но рутинную работу. Например, сбор семантики, кросс-минусовку, изменение объявлений, составление отчетов и так далее.

Но в AdWords есть множество инструментов, максимально облегчающих работу. Например, гибко управлять кампаниями помогают автоматизированные правила

К сожалению, не все маркетологи знают об этих инструментах, а еще меньше применяют их в работе.

В этой статье я расскажу, что такое скрипты AdWords и как ими пользоваться.

Что такое скрипты?

Скрипты – небольшие программы на JavaScript, выполняющие различные полезные функции. Для тех, кто не знаком с программированием, в AdWords есть готовые решения. Встроенные скрипты удобно распределены по тематическим группам.

Встроенные скрипты

Если встроенных скриптов AdWords недостаточно, но вы умеете работать с JavaScript, то можете внести в шаблон изменения.

На основе встроенных скриптов AdWords разработчики Google предлагают множество решений для самых разных случаев: от проверки эффективности объявлений до управления ставками в зависимости от программы телепередач или прогноза погоды.

image7

Я не умею программировать на JavaScript, но на просторах интернета нахожу полезные скрипты и применяю их в своем проекте. Расскажу про два крутых скрипта, которые сильно облегчают мне жизнь.

Как добавить скрипт в аккаунт?

В боковом меню аккаунта заходим в «Массовые операции» и выбираем «Скрипты».

С

Нажимаем на красную кнопку «+Скрипт» и открываем поле для редактирования. Сюда мы и добавим код скрипта.

image1

Перед запуском система попросит пройти авторизацию, чтобы скрипт получил доступ к нашим рекламным кампаниям. Чтобы увидеть предварительный результат, нажмем кнопку «Просмотр» и запустим скрипт в тестовом режиме.

Кросс-минусовка с помощью скрипта AdWords

Как делать кросс-минусовку в Яндекс.Директ, писал мой коллега Андрей Шестаков. А для пользователей AdWords это больная тема. Минусовать ключи приходится вручную или с помощью сторонних сервисов. Но этот процесс я автоматизирую с помощью скрипта, который нашла на одном форуме.

Код скрипта:

//Ярлык кампании(ий), в которой необходима кросс-минусовка
//можно использовать несколько через запятую, например '["cross", "hot", "cool"]'
var CampaignLabel= '["cross"]'; 


function main() {
  var keyArray=[];
  var campaignIterator = AdWordsApp
     .campaigns()
     .withCondition("LabelNames CONTAINS_ANY "+CampaignLabel)
     .withCondition("Status = ENABLED")
     .get();
  Logger.log('Всего найдено активных кампаний: ' + campaignIterator.totalNumEntities());
  
 while (campaignIterator.hasNext()) {
    var campaign = campaignIterator.next();
   Logger.log('Кампания: '+campaign.getName());
   
    var adGroupIterator = campaign.adGroups()
   .withCondition("AdGroupStatus = ENABLED")
   .get();
   Logger.log('Всего найдено активных групп: ' + adGroupIterator.totalNumEntities());
   
    while (adGroupIterator.hasNext()) {
      var adGroup = adGroupIterator.next();
      var adGroupID=adGroup.getId();
      var keywordIterator = adGroup.keywords().withCondition("KeywordMatchType = BROAD").get();
    
      while (keywordIterator.hasNext() ) {
        var keyword = keywordIterator.next();
        keytext= keyword.getText();
        keyArray.push({'adGroup':adGroupID,'key': keytext.replace( /\+/g, '' ).split(' ') });
    }
};
  }


  
//обработка ключей     
for (j=0; j< keyArray.length; j++){
var exkey=[];
var resSravn=null;
for (i=0; i< keyArray.length; i++){
	if (i!==j){
		resSravn=differ(keyArray[i]['key'],keyArray[j]['key']);
		if (resSravn!==null){
			addUnical(resSravn,exkey);
			(keyArray[j]['exkey'])=exkey;
			}
	}
	}
}

//добавляем исключения в группы
var i = 0;
while (i < keyArray.length) {
  if (keyArray[i]['exkey']!==undefined) {
    
  addExKeyword(keyArray[i]['adGroup'],keyArray[i]['exkey']);
  }
  i++;
}      
        
 
//вывод лога
var i = 0;
while (i < keyArray.length) {
  Logger.log("Группа:"+keyArray[i]['adGroup']+"; Ключ:"+keyArray[i]['key']+"; Исключения:"+keyArray[i]['exkey']);
  i++;
}
}




//Добавляем в массив только новые слова
//Первый параметр - массив что добавляем, Второй куда
function addUnical(a1, a2) {
a1.forEach (
	function(item, i, arr){
		if (a2.indexOf(item)===-1){
		a2.push(item);
		} 
	})
}

//возвращает массив слов, которые не совпали
function differ(a, b) {
var alen = a.length;
var arr = [];
var samekey=0;
var i = 0;
while (i < alen) {
  var key = a[i++];
  if (b.indexOf(key) === -1) {
    arr.push(key);
  }
  else {samekey++}
}
if (samekey===b.length){
return arr;
}
return null;
}

//Добавляет исключения в заданную группу
function addExKeyword(adGroupId,key) {
  var adGroupIterator = AdWordsApp.adGroups()
      .withCondition('Id ="'+adGroupId+'"')
      .get();
  if (adGroupIterator.hasNext()) {
    var adGroup = adGroupIterator.next();
    for (i=0;i<key.length;i++){
    adGroup.createNegativeKeyword(key[i].toString());
    }
  }
}

Автор кода – Андрей Москалец

В тексте указываем ярлык кампании, в которой будем минусовать ключевые слова.

Ярлык кампании в коде кросс-минусовкиРезультат работы оцениваем с помощью кнопки «Просмотр». Если скрипт настроен без ошибок, запускаем выполнение. Результат смотрим в «Журнале».

Результат работы скрипта кросс-минусовкиСкрипт сам нашел нужные минус-слова и добавил их в группы.

Автоматизированные еженедельные отчеты с помощью скриптов

Другая огромная польза от скриптов – в быстрой организации различных отчетов по самым разным параметрам.

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

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

Сначала копируем шаблон тепловой карты на Google Диск. Для этого в меню «Файл» выбираем «Создать копию».

Код скрипта:

/**
*
* Heat Map Creation Tool - with Devices
*
* This script calculates the smoothed average performance of each hour of each day
* of the week, and outputs this into a heat map and graph in a Google Sheet. This
* can be done for all data and for device data. It also suggests ad schedules and
* device bid adjustments based on conversion rates.
*
* Version: 2.0
* Google AdWords Script maintained on brainlabsdigital.com
*
**/


//////////////////////////////////////////////////////////////////////////////
// Options 

var spreadsheetUrl = "https://docs.google.com/YOUR-SPREADSHEET-URL-HERE";
// The URL of the Google Doc the results will be put into.
// Copy the template at https://docs.google.com/spreadsheets/d/19OsCHG5JE_TqHHCZK1HNXyHizrJZ0_iT6dpqUOzvRB4/edit#gid=1022438191
// so you have the correct formatting and charts set up.

var dateRanges = ["2016-09-01,2016-10-31"];
// The start and end date of the date range for your data
// You can have multiple ranges, eg ["2016-06-01,2016-07-31","2016-09-01,2016-10-31"]
// would get data from June, July, September and October 2015.
// Format for each range is "yyyy-mm-dd,yyyy-mm-dd" (where the first date is the
// start of the range and the second is the end).

var ignoreDates = [];
// List any single days that are within your date range but whose data you do not
// want to use in calculations, for instance if they had atypical performance or
// there were technical issues with your site.
// eg ["2016-02-14","2016-03-27"] would mean data from Valentine's Day and Easter
// 2016 would be ignored.
// Format for each day is "yyyy-mm-dd"
// Leave as [] if unwanted.

var fields = ["Impressions", "Clicks", "Conversions"];
// Make heat maps of these fields.
// Allowed values: "Impressions", "Clicks", "Cost", "Conversions",
// "ConversionValue"

var calculatedFields = ["Clicks/Impressions","Conversions/Clicks"];
// Make heat maps of a stat calculated by dividing one field by another. 
// For example "Clicks/Impressions" will give the average clicks divided by the
// average impressions (ie the CTR).
// Allowed fields: "Impressions", "Clicks", "Cost", "Conversions",
// "ConversionValue"

var devices = ["Mobile"];
// Make heat maps and bid modifier suggestions for these devices
// Allowed fields: "Mobile", "Tablet", "Desktop"

var suggestAdSchedules = true;
// If true, the script will suggest hourly ad schedules, based on conversion rate.

var suggestDeviceBidModifiers = true;
// If true, the script will suggest bid modifiers for the devices specified above,
// based on the devices' conversion rates.

var baseDeviceModifiersOnBiddingMultiplier = true;
// If true, then the device bid modifiers given will be adjusted to take into
// account the suggested ad schedules.
// For example suppose that at a certain hour device bids should be increased by
// 30%, and the suggested ad schedule for that hour is 10%.
// If this is false, the the device modifier will be given as 30%.
// If this is true, then the device modifier will be given as 18%, because when
// this and the 10% ad schedules are applied this increases the bid by 30%.

var campaignNameDoesNotContain = [];
// Use this if you want to exclude some campaigns.
// For example ["Display"] would ignore any campaigns with 'Display' in the name,
// while ["Display","Competitors"] would ignore any campaigns with 'display' or
// 'competitors' in the name. Case insensitive.
// Leave as [] to not exclude any campaigns.

var campaignNameContains = [];
// Use this if you only want to look at some campaigns.
// For example ["Brand"] would only look at campaigns with 'Brand' in the name,
// while ["Brand","Generic"] would only look at campaigns with 'brand' or 'generic'
// in the name. Case insensitive.
// Leave as [] to include all campaigns.

var ignorePausedCampaigns = true;
// Set this to true to only look at currently active campaigns.
// Set to false to include campaigns that had impressions but are currently paused.


//////////////////////////////////////////////////////////////////////////////
// Advanced settings.

var smoothingWindow = [-2,   -1,   0,   1,    2   ];
var smoothingWeight = [0.25, 0.75, 1,   0.75, 0.25];
// The weights used for smoothing.
// The smoothingWindow gives the relative hour (eg 0 means the current hour,
// -2 means 2 hours before the current hour) and the smoothingWeight gives the
// weighting for that hour.

var minBidMultiplierSuggestion = -0.35;
var maxBidMultiplierSuggestion = 0.35;
// The minimum and maximum for the suggested bidding multipliers.


//////////////////////////////////////////////////////////////////////////////
function main() {
  
  // Check the spreadsheet works.
  var spreadsheet = checkSpreadsheet(spreadsheetUrl, "the spreadsheet");
  
  
  // Check the field names are correct, and get a list with the correct capitalisation
  var allowedFields = ["Conversions", "ConversionValue", "Impressions", "Clicks", "Cost"];
  var fieldsToCheck = [];
  for (var i=0; i -1) {
          continue;
        }
        if (dailyData[row["Date"]] == undefined) {
          dailyData[row["Date"]] = {};
          dailyData[row["Date"]]["Day"] = row["DayOfWeek"];
          for (var h=0; h<24; h++) {
            dailyData[row["Date"]][h+""] = {};
            for (var f=0; f 23) {
            if (dailyData[tomorrow] != undefined) {
              totalWeight += smoothingWeight[w];
              smoothedTotal += smoothingWeight[w] * dailyData[tomorrow][(h + smoothingWindow[w] - 24)][fieldsIncDevice[f]];
            }
          } else {
            totalWeight += smoothingWeight[w];
            smoothedTotal += smoothingWeight[w] * dailyData[date][(h + smoothingWindow[w])][fieldsIncDevice[f]];
          }
        }
        if (totalWeight != 0) {
          smoothedData[day][h][fieldsIncDevice[f]] += smoothedTotal / totalWeight;
        }
      }
    }
  } // end for dailyData
  Logger.log("Collected daily data.");
  
  
  // Calculate the averages from the smoothed data
  var hourlyAvg = {};
  var totalConversions = 0;
  var totalClicks = 0;
  var deviceClicks = {};
  var deviceConversions = {};
  for (var i=0; i maxBidMultiplierSuggestion) {
            multiplier = maxBidMultiplierSuggestion;
          } else if (multiplier < minBidMultiplierSuggestion) {
            multiplier = minBidMultiplierSuggestion;
          } 
          hourlyAvg[dayNames[d]][h+""]["AdSchedules"] = multiplier;
        }
        
      }
    }
    
    // Device level bid modifiers
    if (suggestDeviceBidModifiers) {
      var deviceConvRate = {};
      for (var i=0; i maxBidMultiplierSuggestion) {
                modifier = maxBidMultiplierSuggestion;
              } else if (modifier < minBidMultiplierSuggestion) {
                modifier = minBidMultiplierSuggestion;
              }
              hourlyAvg[dayNames[d]][h+""][devices[i] + "BidModifiers"] = modifier;
            }
          } 
        }
      }
    }
    
  } // end if suggestAdSchedules or suggestDeviceBidModifiers
  Logger.log("Averaged and smoothed data.");
  
  
  // Make the heat maps on the spreadsheet
  var sheet0 = spreadsheet.getSheets()[0];
  var calculatedFieldNames = calculatedFields.map(function (arr){return arr.join("/")});
  var baseFields = checkFieldNames(allowedFields, fields, "", true).concat(calculatedFieldNames);
  var allFieldNames = baseFields.slice();
  for (var i=0; i -1) {
      var components = allFieldNames[f].split("/");
      var multiplierIsMoney = (components[0] == "Cost" || components[0] == "ConversionValue");
      var divisorIsMoney = (components[1] == "Cost" || components[1] == "ConversionValue");
      if ((!multiplierIsMoney && !divisorIsMoney) || (multiplierIsMoney && divisorIsMoney)) {
        // If neither component is monetary, or both components are, then the result is a percentage
        format = "#,##0.00%";
      }
    }
    if (allFieldNames[f] == "AdSchedules" || allFieldNames[f].substr(-12) == "BidModifiers") {
      format = "#,##0.00%";
    }
    sheet.getRange(4, 2, sheetData.length, sheetData[0].length).setNumberFormat(format);
    
    // Update the chart title
    var charts = sheet.getCharts();
    if (sheet.getCharts().length === 0) {
      Logger.log("Warning: chart missing from the " + fieldName + " sheet."); 
    } else {
      var chart = charts[0];
      chart = chart.modify().setOption('title', fieldName).build();
      sheet.updateChart(chart);
    }
  }
  
  Logger.log("Posted data to spreadsheet.");
  Logger.log("Finished.");
}


// Check the spreadsheet URL has been entered, and that it works
function checkSpreadsheet(spreadsheetUrl, spreadsheetName) {
  if (spreadsheetUrl.replace(/[AEIOU]/g,"X") == "https://docs.google.com/YXXR-SPRXXDSHXXT-XRL-HXRX") {
    throw("Problem with " + spreadsheetName + " URL: make sure you've replaced the default with a valid spreadsheet URL.");
  }
  try {
    var spreadsheet = SpreadsheetApp.openByUrl(spreadsheetUrl);
    
    // Checks if you can edit the spreadsheet
    var sheet = spreadsheet.getSheets()[0];
    var sheetName = sheet.getName();
    sheet.setName(sheetName);
    
    return spreadsheet;
  } catch (e) {
    throw("Problem with " + spreadsheetName + " URL: '" + e + "'");
  }
}


// Get the IDs of campaigns which match the given options
function getCampaignIds() {
  var whereStatement = "WHERE ";
  var whereStatementsArray = [];
  var campaignIds = [];
  
  if (ignorePausedCampaigns) {
    whereStatement += "CampaignStatus = ENABLED ";
  } else {
    whereStatement += "CampaignStatus IN ['ENABLED','PAUSED'] ";
  }
  
  for (var i=0; i 0) {
    throw unrecognisedFields.length + " field(s) not recognised in '" + souceName + "': '" + unrecognisedFields.join("', '") + 
      "'. Please choose from '" + allowedFields.join("', '") + "'.";
  }
  
  return wantedFields;
}
 

 

Автор – Brainlabs, описал Даниэль Гилберт

 

Теперь настраиваем скрипт:

  • spreadsheetUrl — ссылка на вашу таблицу-шаблон тепловой карты;
  • dateRanges — период, за который мы собираем данные. Указываем дату начала и окончания в формате ГГГГ-ММ-ДД через запятую. Например: [«2018-05-01,2018-07-31»]. Можно указать несколько периодов через запятую;
  • ignoreDates — заполняем, если нужно исключить из отчета какой-либо период.  Дату указываем так же, как в пункте выше.
  • fields — показатели, которые хотим включить в отчет. Например, "Impressions", "Clicks", "Cost", "Conversions" (показы, клики, стоимость, конверсии);
  • calculateFields — метрики, которые скрипт рассчитает из показателей в предыдущем поле. Это будут CTR и коэффициент конверсии. Ставим их в кавычки и разделяем запятой [«Clicks/Impressions», «Conversions/Clicks»];
  • devices — заполняем, если нужно получить отдельные тепловые карты по типам устройств (desktop, mobile, tablet). Если поле будет пустым, в отчете вы получите общий трафик;
  • campaignNameContains и campaignNameDoesNotContain: первое – названия кампаний, которые мы анализируем, а второе – которые хотим исключить из анализа. Если оставить поле пустым, мы получим данные всех кампаний;
  • ignorePausedCampaigns —  исключает из отчета приостановленные кампании. Для формирования отчета только по активным кампаниям указываем в поле  «true», а если мы хотим посмотреть и приостановленные кампании — «false».
  • Данные по удаленным кампаниям в отчет не включаются.

Запускаем скрипт в работу и получаем файл с тепловыми картами поведения пользователей.

image3В файле несколько вкладок, где можно посмотреть данные по показам, кликам и конверсии в зависимости от дня недели, времени суток и устройства.

В настройках можно задать частоту выполнения скрипта.

image6


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

Вот где можно взять скрипты:

А какие скрипты используете в работе вы? Делитесь в комментариях.

comments powered by HyperComments

Подпишись!

Оставьте адрес, и каждую среду мы будем высылать свежую статью

Спроси
автора статьи