Как быстро проверить рекламные кампании Google Adwords на ошибки

Недавно я наткнулся на очень полезную статью https://blog.kinetica.su/scripts-in-adwords/.

В статье описан скрипт, который позволяет проверить все рекламные кампании в аккаунте Google Adwords на ошибки. Пользователь получит уведомление на почту о том, что в рекламных кампаниях обнаружены "битые" ссылки.

Для того, чтобы добавить скрипт достаточно перейти на страницу adwords.google.com/aw/bulk/scripts/management, нажать на знак "плюс", вставить код и нажать "Сохранить".

Единственная проблема в том, что в блоке Кинетики какая-то беда с экранированием, и все знаки ">" там обозначены в коде как ">". В результате при попытке сохранения скрипта интерфейс Adwords будет ругаться на несоответствие скобок.

Ниже я привожу корректный код, который будет без ошибок добавляться в скрипты Adwords, не забудьте только:

  • указать адрес электронной почты специалиста, на который должен приходить отчёт (поле для адреса я отметил жирным подчеркнутым курсивом в коде),
  • авторизовать скрипт,
  • настроить расписание проверки.

Код скрипта

function main() {

var mail_to = 'email-for@spam.here';

var mccAccount = AdWordsApp.currentAccount();

//получаем проекты текущего аккаунта

var childAccounts = MccApp.accounts().get();

var email = '';

//пробегаем по всем проектам аккаунта

while (childAccounts.hasNext()) {

//берем проект

var childAccount = childAccounts.next();

//делаем его текущим

MccApp.select(childAccount);

var disabled_label = 'disabled-ad';

//----выполняем логику в рамках данного проекта------

if (childAccount.getStatsFor("LAST_14_DAYS").getClicks() == 0) continue;

AdWordsApp.createLabel(disabled_label, "Отключенные объявления в связи с тем, что не нашли цену на сайте", "red");

var checked_urls = {};

var campaignIterator = AdWordsApp.campaigns()

.withCondition('Status = ENABLED')

.get();

//пробегаем по всем активным кампаниям,

while (campaignIterator.hasNext()) {

var campaign = campaignIterator.next();

var groupIterator = campaign.adGroups()

.withCondition('Status = ENABLED')

.get();

while (groupIterator.hasNext()) {

var group = groupIterator.next();

var adIterator = group.ads()

.withCondition('Status = ENABLED')

.get();

//пробегаем по всем группам

while (adIterator.hasNext()) {

var entity = adIterator.next();

var url = entity.urls().getFinalUrl();

//пропускаем, если урл пустой

if (url === null) continue;

//если объявление неактивно и нет специального лейбла, то пропускаем

if (!entity.isEnabled()) continue;

var ad_text = 'Группа: ' + group.getName() + ' Объявление: ' + entity.getId() + ' '

+ (entity.getType() == 'TEXT_AD' ? '"' + entity.getHeadline()

+ '"' : (entity.getType() == 'EXPANDED_TEXT_AD' ? '"' + entity.getHeadlinePart1()

+ ' ' + entity.getHeadlinePart2() + '"' : ''));

//очищаем урл от параметров, меток и т.д.

url = clean_url(url);

//если урл этого товара мы уже парсили,

// то берем данные о цене и наличии из массива данных

// чтобы снова не парсить

if (checked_urls[url]) {

//включили или отключили объявление в зависимости от наличия

//или просто оповещаем на имейл (нужное раскомментировать)

if (checked_urls[url]) {

if (checked_urls[url] === 'error') {

//ставим на паузу объявление

//entity.pause();

//entity.applyLabel(disabled_label);

email = email + '\n' + ' Ошибка! ' + childAccount.getName() + ' Кампания: "'

+ campaign.getName() + '" ' + ad_text + ' ' + ' Url: ' + url;

}

else {

//иначе включаем и убираем метку

//entity.removeLabel(disabled_label);

//entity.enable();

}

}

}

//если нет, то

else {

var html, headers, code;

//парсим страницу товара

try {

var parsed = UrlFetchApp.fetch(url);

//html = parsed.getContentText();

//headers = parsed.getHeaders();

code = parsed.getResponseCode();

} catch (e) {

//отключаем объявление, если не смогли распарсить страницу

//или просто оповещаем на имейл (нужное раскомментировать)

//entity.pause();

//entity.applyLabel(disabled_label);

email = email + '\n' + ' Ошибка! ' + childAccount.getName()

+ ' Кампания: "' + campaign.getName() + '" '

+ ad_text + ' ' + ' Url: ' + url;

checked_urls[url] = 'error';

}

if (code >= 400) {

//ставим на паузу объявление или просто пишем в лог

checked_urls[url] = 'error';

//entity.pause();

//entity.applyLabel(disabled_label);

} else {

//активизируем объявление или пишем в лог

checked_urls[url] = 'ok';

//entity.enable();

//entity.removeLabel(disabled_label);

}

if (code >= 300) {

//тело письма

email = email + '\n' + childAccount.getName() + ' Кампания: "'

+ campaign.getName() + '" ' + ad_text + ' '

+ (code >= 400 ? ' ОШИБКА ' : '') + ' Url: ' + url

}

}

}

}

}

//---------------------------------------------------

}

if (email != '') {

//отправляем письмо

MailApp.sendEmail(mail_to, "Оповещение об ошибках в урлах объявлениях AdWords", email);

}

//вернулись к MCC аккаунту

MccApp.select(mccAccount);

}

function clean_url(url) {

//урл может быть обернут враппером

url = url.substr(url.lastIndexOf('http'));

if (decodeURIComponent(url) !== url) {

url = decodeURIComponent(url);

}

//убираем GET параметры

if (url.indexOf('?') >= 0) {

url = url.split('?')[0];

}

//убираем скобки

if (url.indexOf('{') >= 0) {

url = url.replace(/\{[0-9a-zA-Z]+\}/g, '');

}

return url;

}