×

Нет рутине: как автоматизировать проверку остатков в рекламных кабинетах Яндекс Директа и Google Ads

Россия +7 (495) 139-20-33
Шрифт:
1 5010

Привет! Я Владимир Малюгин, CEO агентства Performance-маркетинга Digital Geeks. В нашей сфере много рутинных задач, от которых зависит результат. Например, если сотрудник забудет отследить баланс в рекламном кабинете, объявления клиента какое-то время не будут видеть потенциальные покупатели. Чтобы этого не произошло, мы решили делегировать проверку роботу. Алгоритм рассчитывает, на сколько дней хватит бюджета, и отправляет уведомления в Telegram. 

Рассказываю, как мы это сделали, чтобы вы смогли повторить.

Владимир Малюгин, основатель агентства performance-маркетинга Digital Geeks

Задача

У Digital Geeks много аккаунтов в сервисах Google Ads и Яндекс Директ – их ведут разные специалисты. Если деньги в одном из кабинетов закончатся, рекламная кампания остановится, поэтому нужно контролировать остатки.  

Делать это вручную долго и неудобно. Мы решили автоматизировать процесс и создать алгоритм, который будет сообщать об остатках средств. 

Решение 

На базе Google Ads Scripts мы создали алгоритм, интегрированный с чатом в Telegram. Он запускается автоматически и собирает информацию об остатках бюджета каждой активной рекламной кампании (то есть получившей больше одного клика за последние две недели).  

Алгоритм автоматически рассчитывает, на сколько дней хватит средств в личном кабинете. Для этого он вычисляет средние затраты за прошлый день и делит на них сумму остатка. 

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

Уведомления в Telegram

Подобный алгоритм мы создали и для Яндекс Директа. Внутри этого сервиса нет скрипта, поэтому мы сами написали его на языке программирования R. Система работает точно так же, как и робот для Google Ads, отправляя сообщения в тот же чат. 

Решения позволяют извлекать из личных кабинетов не только данные об остатках, но и любую другую информацию. Условия парсинга можно легко поменять. При этом интеграция Google Ads с Telegram реализована напрямую, без привлечения стороннего софта. Для Яндекс Директа мы использовали сервис Make (бывший Integromat). Через него информация об остатках отравляется в Telegram. 

Результат 

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

Делимся с вами кодом, с помощью которого и вы сможете автоматизировать проверку остатков бюджета. 

Скрипт для Yandex Direct

Скрипт для Yandex Direct

<pre>

<code>

library(ryandexdirect)

library(dplyr)

setwd("C:/Scripts/Access")

Token = "C:/Scripts/Access"


#Замените login@yandex.ru на ваш агентский аккаунт в Я.Директ

yadirAuth(Login = "login@yandex.ru",

TokenPath = Token)


client <- yadirGetClientList(AgencyAccount= "login@yandex.ru")


print("Получаем данные по расходам Я.Директ")

# загрузка статистики из рекламных аккаунтов привязанных к агентскому аккаунту

stat <- yadirGetReport(ReportType = "CAMPAIGN_PERFORMANCE_REPORT",

DateRangeType = "CUSTOM_DATE",

DateFrom = Sys.Date()-7,

DateTo = Sys.Date()-1,

FieldNames = c(

"Cost"),

FilterList = c("Impressions GREATER_THAN 0"),

AgencyAccount = "login@yandex.ru",

Login = client$Login)


df = as.data.frame(stat)


df1 <- df

df1 %>%

group_by(Login) %>%

summarise_all(sum) %>%

data.frame() -> df1


df1$Cost <- as.numeric(df1$Cost)

df1$Cost <- df1$Cost / 7


client_balance <- yadirGetBalance(Logins = df1$Login,

AgencyAccount = "login@yandex.ru")



client_balance <- as.data.frame(client_balance)


client_balance <-select(client_balance,Login,Amount)

client_balance <- client_balance %>% rename('Balance' = Amount)


client_balance$`Balance` <- as.numeric(client_balance$`Balance`)


client_balance$`Date` <- c(Sys.time())

client_balance$`System` <- c("Яндекс Директ")


client_balance <- client_balance [order (-client_balance$`Balance`),]

client_balance <- subset(client_balance, Login != 'bank')



library(googlesheets4)

#Замените login@site.ru на ваш аккаунт в Gmail

gs4_auth(email = "login@site.ru")


sh = "https://docs.google.com/spreadsheets/ID"


write_sheet(client_balance, sh,sheet = 'Я.Директ')

write_sheet(df1,sh, sheet = "Расход за вчера в Директ")


print("Я.Директ - готово")


</code>

</pre>


Скрипт для Google Ads

Google Ads

<pre>

<code>


var bud = 0


function main ()

{

sendTelegramMessage('Проверка бюджета в Google Ads:', CHAT_ID);

var accounts = MccApp.accounts()

.withCondition("Clicks >= 1")

.forDateRange("LAST_14_DAYS")

.executeInParallel("budgetControl")


Logger.log(bud);

sendTelegramMessage('Бюджет проверен.', CHAT_ID);


}


function budgetControl()

{

var accountName = AdWordsApp.currentAccount().getName();

var budgets = AdWordsApp.budgetOrders().withCondition('Status = ACTIVE').get();

while (budgets.hasNext())

{

try {

var budget = budgets.next();

if (budget.getSpendingLimit() !== null )

{

var startDate = timeFormat(budget.getStartDateTime());

var cost = AdWordsApp.currentAccount().getStatsFor(startDate,today()).getCost().toFixed(2);

var last7DaysCostByDay = (AdWordsApp.currentAccount().getStatsFor("YESTERDAY").getCost()).toFixed(2);

var limit = budget.getSpendingLimit().toFixed(2);

var remainingDays = rDays(limit, cost, last7DaysCostByDay);

var budgetNow = (limit - cost).toFixed(2);

if (budgetNow < 0)

{

var budgetNow = 0;

}

else

{

var budgetNow = budgetNow;

}

Logger.log([accountName, limit, cost, budgetNow,last7DaysCostByDay,remainingDays]);

if (remainingDays < 6 && last7DaysCostByDay >0)

{

bud = 1


sendTelegramMessage('Аккаунт ' + accountName+ '. Осталось на = ' + remainingDays + ' дней.' + ' Текущий остаток = ' + budgetNow + ' рублей.'+ ' Расход за вчера = ' + last7DaysCostByDay + ' рублей.',CHAT_ID);


/*

MailApp.sendEmail(CONFIG.email,

CONFIG.names +' / Заканчивается бюджет на аккаунте: ' + accountName,

'Аккаунт ' + accountName + ' . Текущий остаток = ' + budgetNow +

'. Расход в день = ' + last7DaysCostByDay + ' в валюте аккаунта. ' +

'Денег хватит на ' + remainingDays + ' дня/дней. В аккаунте заканчиваются средства. Необходимо предупредить PM.');

*/

}

}

}

catch (e)


{


Logger.log(e);


sendTelegramMessage('Ошибка выполнения скрипта контроль Бюджетов ' + accountName);

//MailApp.sendEmail(CONFIG.email,

//'Ошибка выполнения скрипта Контроль бюджетов',

//'Необходимо проверить работу скрипта Контроль бюджетов ' + accountName + ' ' + e);

}

}

}



function timeFormat (date)

{

var year = date.year.toString();

var month = date.month.toString();

var day = date.day.toString();

if (month.length == 1)

{

month = "0" + month;

}

if (day.length == 1) {

day = "0" + day;

}

return [year, month, day].join("");

}


function today () {

var date = new Date();

var timeZone = AdWordsApp.currentAccount().getTimeZone();

var format = 'yyyyMMdd';

return Utilities.formatDate(date, timeZone, format);

}

function rDays(limit, cost, last7DaysCostByDay) {

var remainingDays = ((limit - cost) / last7DaysCostByDay).toFixed();

if (remainingDays < 1 || remainingDays == "Infinity" || remainingDays == "-Infinity" || remainingDays == -0 ) {

remainingDays = 0;

}

return remainingDays;

}




function sendTelegramMessage(text, chat) {

var CONFIG2 = {

TOKEN: TOKEN_ID,

//CHAT_ID: '211002715'

CHAT_ID: '-575137669'

};

var telegramUrl = 'https://api.telegram.org/bot' + CONFIG2.TOKEN + '/sendMessage?chat_id=' + chat + '&text=';

var message = encodeURIComponent(text);

var sendMessageUrl = telegramUrl + message;

var options = {

method: 'POST',

contentType: 'application/json'

};


try {

UrlFetchApp.fetch(sendMessageUrl, options);

} catch (e) {

// Logs an ERROR message.

Logger.log('Ошибка: ' +e);

Logger.log('У пользователя: ' + chat);

}

}


function rDays(limit, cost, last7DaysCostByDay) {

var remainingDays = ((limit - cost) / last7DaysCostByDay).toFixed();

if (remainingDays < 1 || remainingDays == "Infinity" || remainingDays == "-Infinity" || remainingDays == -0 ) {

remainingDays = 0;

}

return remainingDays;

}



</code>

</pre>


(Голосов: 3, Рейтинг: 5)
0
0

Есть о чем рассказать? Тогда присылайте свои материалы в редакцию.


Новые 
Новые
Лучшие
Старые
Сообщество
Подписаться 
Подписаться на дискуссию:
E-mail:
ОК
Вы подписаны на комментарии
Ошибка. Пожалуйста, попробуйте ещё раз.
Отправить отзыв
  • Гость
    1
    комментарий
    0
    читателей
    Гость
    3 месяца назад
    со временем скрипт начнет работать не правильно. так как он не учитывает возвраты за недействительный клики или скликивание.
    -
    1
    +
    Ответить
ПОПУЛЯРНЫЕ ОБСУЖДЕНИЯ НА SEONEWS
13 инструментов для SEO-специалиста, актуальных в 2022 году
Саша
6
комментариев
0
читателей
Полный профиль
Саша - кажись какой-то британец
Продуктовый подход в SEO: новая эпоха поисковой оптимизации
Борис
1
комментарий
0
читателей
Полный профиль
Борис - Почитал и спич очень близок к тому, что гугловоды говорят у себя на курсере. К комменту ниже: инклюзивность, доступность - это часть маркетинга и seo становится. Удивился даже, что в снг о таком слышали)))))
Скоринг запросов: почему он необходим при сборе семантического ядра
Илья Горбачев
3
комментария
0
читателей
Полный профиль
Илья Горбачев - Сбор сезонности в последней версии находится на вкладке "Парсинг" и вызывается кликом по иконке с графиком на черном фоне. Только он собирает общую частоту, поэтому лучше собирать данные с фраз (маркеров), которые не пересекаются в реальных запросах.
Альманах фатальных ошибок b2b-сайта: как владельцы бизнеса обрекают сайты на бесславное существование. Часть первая
Сергей Ерофеев
3
комментария
0
читателей
Полный профиль
Сергей Ерофеев - Спасибо за комментарий! Вы правы, если за CMS следит заинтересованный профессионал - риски минимальны. Но мы же с вами понимаем, что: а) Не каждый разработчик делает все, как "для себя". б) После создания сайта разработчик редко остается на проекте в) Часто разработчик не является маркетологом. В этом случае принцип "функционал работает и этого достаточно" может быть на первом месте. Мы тоже видели большое количество хороших и качественных проектов на бесплатных CMS, но проблемных проектов мы видели сильно больше. Просто статистика.
Почему не стоит отказываться от SEO на этапе разработки
Максимус
3
комментария
0
читателей
Полный профиль
Максимус - Я уже сделал и сегодня в первый класс отвёл!
Как автоматизировать мессенджеры для бизнеса в CRM-системе
Алиналина
1
комментарий
0
читателей
Полный профиль
Алиналина - Кстати да. Но мы зарегались, CRMка реально интересная
Санкции поисковых систем: как узнать, что сайт попал под фильтры. Обзор главных инструментов
Volodyka Filipov
6
комментариев
0
читателей
Полный профиль
Volodyka Filipov - Нужно не крутить, а по честному развивать)))
Белые и серые методы продвижения. Тренды 2023
Гость
1
комментарий
0
читателей
Полный профиль
Гость - Я тоже заметил. Если встать в 5 утра и шёпотом сказать 3 раза Ажгибесов. Сайт в гугле растёт.
Кейс MediaNation: увеличили еженедельный трафик автомобильной компании на 50% за год и вышли в топ поиска по 300 запросам
Игорь Скляр
1
комментарий
0
читателей
Полный профиль
Игорь Скляр - Действительно, изначально рост был именно по информационным запросам. Но рост позиций и трафика по информационным запросам положительно повлиял и на связанные позиции по коммерческим запросам и сдвинул видимость с мёртвой точки
Количество запросов по теме онлайн-образования выросло на 17%. Исследование Яндекса
Марина Ибушева
63
комментария
0
читателей
Полный профиль
Марина Ибушева - Это релиз от пресс-службы Яндекса
ТОП КОММЕНТАТОРОВ
Комментариев
910
Комментариев
834
Комментариев
554
Комментариев
540
Комментариев
483
Комментариев
385
Комментариев
373
Комментариев
262
Комментариев
249
Комментариев
171
Комментариев
156
Комментариев
141
Комментариев
121
Комментариев
115
Комментариев
100
Комментариев
97
Комментариев
97
Комментариев
96
Комментариев
80
Комментариев
77
Комментариев
74
Комментариев
67
Комментариев
63
Комментариев
60
Комментариев
59

Отправьте отзыв!
Отправьте отзыв!