Недавно я наткнулся на очень полезную статью 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;
}