У маркетологов, работающих с контекстной рекламой в Google AdWords, много времени уходит на важную, но рутинную работу. Например, сбор семантики, кросс-минусовку, изменение объявлений, составление отчетов и так далее.
Но в AdWords есть множество инструментов, максимально облегчающих работу. Например, гибко управлять кампаниями помогают автоматизированные правила.
К сожалению, не все маркетологи знают об этих инструментах, а еще меньше применяют их в работе.
В этой статье я расскажу, что такое скрипты AdWords и как ими пользоваться.
Скрипты – небольшие программы на JavaScript, выполняющие различные полезные функции. Для тех, кто не знаком с программированием, в AdWords есть готовые решения. Встроенные скрипты удобно распределены по тематическим группам.
Если встроенных скриптов AdWords недостаточно, но вы умеете работать с JavaScript, то можете внести в шаблон изменения.
На основе встроенных скриптов AdWords разработчики Google предлагают множество решений для самых разных случаев: от проверки эффективности объявлений до управления ставками в зависимости от программы телепередач или прогноза погоды.
Я не умею программировать на JavaScript, но на просторах интернета нахожу полезные скрипты и применяю их в своем проекте. Расскажу про два крутых скрипта, которые сильно облегчают мне жизнь.
В боковом меню аккаунта заходим в «Массовые операции» и выбираем «Скрипты».
Нажимаем на красную кнопку «+Скрипт» и открываем поле для редактирования. Сюда мы и добавим код скрипта.
Перед запуском система попросит пройти авторизацию, чтобы скрипт получил доступ к нашим рекламным кампаниям. Чтобы увидеть предварительный результат, нажмем кнопку «Просмотр» и запустим скрипт в тестовом режиме.
Как делать кросс-минусовку в Яндекс.Директ, писал мой коллега Андрей Шестаков. А для пользователей 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][fieldsIncDevice[f]]; } } else { totalWeight += smoothingWeight[w]; smoothedTotal += smoothingWeight[w] * dailyData[date][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, описал Даниэль Гилберт
Теперь настраиваем скрипт:
Запускаем скрипт в работу и получаем файл с тепловыми картами поведения пользователей.
В файле несколько вкладок, где можно посмотреть данные по показам, кликам и конверсии в зависимости от дня недели, времени суток и устройства.
В настройках можно задать частоту выполнения скрипта.
Я рассказала только о двух скриптах AdWords, которые помогают мне в работе. Но уверена, что при желании можно найти решение для любой задачи. Скрипты имеют открытый исходный код, поэтому пользоваться ими можно бесплатно.
Вот где можно взять скрипты:
А какие скрипты используете в работе вы? Делитесь в комментариях.
[EPSB]Настроим скрипты AdWords за вас[/EPSB]