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


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

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

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

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

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

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

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

Делимся с вами кодом, с помощью которого и вы сможете автоматизировать проверку остатков бюджета.
Скрипт для 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

<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>
Нужен знак, что пора автоматизировать воронку продаж? Вот он!
Оставьте ваши данные и мы свяжемся с вами
Нажимая кнопку «Жду», я даю согласие на
обработку моих персональных данных.