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

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

Какую задачу решали?

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

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

Как мы это сделали?

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

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

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

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

Такие сообщения от робота мы получаем в проектный чат
Такие сообщения от робота мы получаем в проектный чат

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

Как решение помогает сотрудникам и клиентам?

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

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

Скрипт для Yandex Direct

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("Я.Директ - готово")

Скрипт для Google Ads

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: ID }; 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; }

Если вам нужно больше лайфхаков о продвижении в Сети, подписывайтесь на наш телеграм-канал Digital Geeks. Его цель — облегчить жизнь директорам и менеджерам по Digital-маркетингу, а также предпринимателям, которые ищут клиентов в Интернете. Из постов вы узнаете, например, о том, как построить эффективную систему управления SЕО, не погружаясь в технические детали, как автоматизировать процессы по продвижению и помочь сотрудникам работать быстрее.

11
2 комментария

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

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

Какую задачу решали?

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

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

Как мы это сделали?

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

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

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

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

Такие сообщения от робота мы получаем в проектный чат
Такие сообщения от робота мы получаем в проектный чат

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

Как решение помогает сотрудникам и клиентам?

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

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

Скрипт для Yandex Direct

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("Я.Директ - готово")

Скрипт для Google Ads

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: ID }; 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; }

Если вам нужно больше лайфхаков о продвижении в Сети, подписывайтесь на наш телеграм-канал Digital Geeks. Его цель — облегчить жизнь директорам и менеджерам по Digital-маркетингу, а также предпринимателям, которые ищут клиентов в Интернете. Из постов вы узнаете, например, о том, как построить эффективную систему управления SЕО, не погружаясь в технические детали, как автоматизировать процессы по продвижению и помочь сотрудникам работать быстрее.

11
2 комментария
Balance` \u003C- as.numeric(client_balance

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

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

Какую задачу решали?

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

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

Как мы это сделали?

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

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

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

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

Такие сообщения от робота мы получаем в проектный чат
Такие сообщения от робота мы получаем в проектный чат

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

Как решение помогает сотрудникам и клиентам?

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

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

Скрипт для Yandex Direct

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("Я.Директ - готово")

Скрипт для Google Ads

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: ID }; 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; }

Если вам нужно больше лайфхаков о продвижении в Сети, подписывайтесь на наш телеграм-канал Digital Geeks. Его цель — облегчить жизнь директорам и менеджерам по Digital-маркетингу, а также предпринимателям, которые ищут клиентов в Интернете. Из постов вы узнаете, например, о том, как построить эффективную систему управления SЕО, не погружаясь в технические детали, как автоматизировать процессы по продвижению и помочь сотрудникам работать быстрее.

11
2 комментария
Balance`) \n\nclient_balance

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

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

Какую задачу решали?

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

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

Как мы это сделали?

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

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

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

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

Такие сообщения от робота мы получаем в проектный чат
Такие сообщения от робота мы получаем в проектный чат

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

Как решение помогает сотрудникам и клиентам?

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

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

Скрипт для Yandex Direct

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("Я.Директ - готово")

Скрипт для Google Ads

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: ID }; 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; }

Если вам нужно больше лайфхаков о продвижении в Сети, подписывайтесь на наш телеграм-канал Digital Geeks. Его цель — облегчить жизнь директорам и менеджерам по Digital-маркетингу, а также предпринимателям, которые ищут клиентов в Интернете. Из постов вы узнаете, например, о том, как построить эффективную систему управления SЕО, не погружаясь в технические детали, как автоматизировать процессы по продвижению и помочь сотрудникам работать быстрее.

11
2 комментария
Date` \u003C- c(Sys.time())\nclient_balance

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

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

Какую задачу решали?

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

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

Как мы это сделали?

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

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

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

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

Такие сообщения от робота мы получаем в проектный чат
Такие сообщения от робота мы получаем в проектный чат

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

Как решение помогает сотрудникам и клиентам?

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

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

Скрипт для Yandex Direct

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("Я.Директ - готово")

Скрипт для Google Ads

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: ID }; 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; }

Если вам нужно больше лайфхаков о продвижении в Сети, подписывайтесь на наш телеграм-канал Digital Geeks. Его цель — облегчить жизнь директорам и менеджерам по Digital-маркетингу, а также предпринимателям, которые ищут клиентов в Интернете. Из постов вы узнаете, например, о том, как построить эффективную систему управления SЕО, не погружаясь в технические детали, как автоматизировать процессы по продвижению и помочь сотрудникам работать быстрее.

11
2 комментария
System` \u003C- c(\"Яндекс Директ\")\n\nclient_balance \u003C- client_balance [order (-client_balance

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

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

Какую задачу решали?

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

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

Как мы это сделали?

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

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

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

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

Такие сообщения от робота мы получаем в проектный чат
Такие сообщения от робота мы получаем в проектный чат

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

Как решение помогает сотрудникам и клиентам?

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

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

Скрипт для Yandex Direct

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("Я.Директ - готово")

Скрипт для Google Ads

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: ID }; 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; }

Если вам нужно больше лайфхаков о продвижении в Сети, подписывайтесь на наш телеграм-канал Digital Geeks. Его цель — облегчить жизнь директорам и менеджерам по Digital-маркетингу, а также предпринимателям, которые ищут клиентов в Интернете. Из постов вы узнаете, например, о том, как построить эффективную систему управления SЕО, не погружаясь в технические детали, как автоматизировать процессы по продвижению и помочь сотрудникам работать быстрее.

11
2 комментария
Balance`),]\nclient_balance \u003C- subset(client_balance, Login != 'bank')\n\n\nlibrary(googlesheets4)\n#Замените login@site.ru на ваш аккаунт в Gmail\ngs4_auth(email = \"login@site.ru\")\n\nsh = \"https://docs.google.com/spreadsheets/ID\"\n\nwrite_sheet(client_balance, sh,sheet = 'Я.Директ')\nwrite_sheet(df1,sh, sheet = \"Расход за вчера в Директ\")\n\n\nprint(\"Я.Директ - готово\")","lang":""}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"\u003Cp\u003E\u003Cb\u003EСкрипт для Google Ads\u003C/b\u003E\u003C/p\u003E"}},{"type":"code","cover":false,"hidden":false,"anchor":"","data":{"text":"var bud = 0\n\nfunction main ()\n{\n sendTelegramMessage('Проверка бюджета в Google Ads:', CHAT_ID);\n \n var accounts = MccApp.accounts()\n .withCondition(\"Clicks \u003E= 1\")\n .forDateRange(\"LAST_14_DAYS\")\n .executeInParallel(\"budgetControl\")\n\n Logger.log(bud);\n sendTelegramMessage('Бюджет проверен.', CHAT_ID);\n\n}\n\nfunction budgetControl()\n{\n \n var accountName = AdWordsApp.currentAccount().getName();\n var budgets = AdWordsApp.budgetOrders().withCondition('Status = ACTIVE').get();\n while (budgets.hasNext())\n {\n try {\n var budget = budgets.next();\n if (budget.getSpendingLimit() !== null ) \n {\n var startDate = timeFormat(budget.getStartDateTime());\n var cost = AdWordsApp.currentAccount().getStatsFor(startDate,today()).getCost().toFixed(2);\n var last7DaysCostByDay = (AdWordsApp.currentAccount().getStatsFor(\"YESTERDAY\").getCost()).toFixed(2);\n var limit = budget.getSpendingLimit().toFixed(2);\n var remainingDays = rDays(limit, cost, last7DaysCostByDay);\n var budgetNow = (limit - cost).toFixed(2);\n \n if (budgetNow \u003C 0)\n \n {\n var budgetNow = 0;\n }\n \n else \n \n {\n var budgetNow = budgetNow;\n }\n \n Logger.log([accountName, limit, cost, budgetNow,last7DaysCostByDay,remainingDays]);\n \n if (remainingDays \u003C 6 && last7DaysCostByDay \u003E0) \n \n {\n bud = 1\n\n sendTelegramMessage('Аккаунт ' + accountName+ '. Осталось на = ' + remainingDays + ' дней.' + ' Текущий остаток = ' + budgetNow + ' рублей.'+ ' Расход за вчера = ' + last7DaysCostByDay + ' рублей.',CHAT_ID);\n\n /*\n MailApp.sendEmail(CONFIG.email,\n CONFIG.names +' / Заканчивается бюджет на аккаунте: ' + accountName,\n 'Аккаунт ' + accountName + ' . Текущий остаток = ' + budgetNow +\n '. Расход в день = ' + last7DaysCostByDay + ' в валюте аккаунта. ' +\n 'Денег хватит на ' + remainingDays + ' дня/дней. В аккаунте заканчиваются средства. Необходимо предупредить PM.');\n */\n \n }\n }\n }\n catch (e) \n\n {\n\n Logger.log(e);\n\n sendTelegramMessage('Ошибка выполнения скрипта контроль Бюджетов ' + accountName);\n //MailApp.sendEmail(CONFIG.email,\n //'Ошибка выполнения скрипта Контроль бюджетов',\n //'Необходимо проверить работу скрипта Контроль бюджетов ' + accountName + ' ' + e);\n \n }\n }\n \n}\n\n\nfunction timeFormat (date)\n {\nvar year = date.year.toString();\nvar month = date.month.toString();\nvar day = date.day.toString();\n \n if (month.length == 1)\n \n {\n month = \"0\" + month;\n }\n if (day.length == 1) {\n day = \"0\" + day;\n }\n \n return [year, month, day].join(\"\");\n }\n\nfunction today () {\nvar date = new Date();\nvar timeZone = AdWordsApp.currentAccount().getTimeZone();\nvar format = 'yyyyMMdd';\nreturn Utilities.formatDate(date, timeZone, format);\n}\n \n \nfunction rDays(limit, cost, last7DaysCostByDay) {\nvar remainingDays = ((limit - cost) / last7DaysCostByDay).toFixed();\nif (remainingDays \u003C 1 || remainingDays == \"Infinity\" || remainingDays == \"-Infinity\" || remainingDays == -0 ) {\nremainingDays = 0;\n}\nreturn remainingDays;\n}\n\n\n\nfunction sendTelegramMessage(text, chat) {\nvar CONFIG2 = {\nTOKEN: TOKEN_ID,\n//CHAT_ID: ID\n \n};\nvar telegramUrl = 'https://api.telegram.org/bot' + CONFIG2.TOKEN + '/sendMessage?chat_id=' + chat + '&text=';\nvar message = encodeURIComponent(text);\nvar sendMessageUrl = telegramUrl + message;\nvar options = {\nmethod: 'POST',\ncontentType: 'application/json'\n};\n \n\n try {\n UrlFetchApp.fetch(sendMessageUrl, options);\n } catch (e) {\n // Logs an ERROR message.\n Logger.log('Ошибка: ' +e);\n Logger.log('У пользователя: ' + chat);\n }\n}\n\nfunction rDays(limit, cost, last7DaysCostByDay) {\nvar remainingDays = ((limit - cost) / last7DaysCostByDay).toFixed();\nif (remainingDays \u003C 1 || remainingDays == \"Infinity\" || remainingDays == \"-Infinity\" || remainingDays == -0 ) {\nremainingDays = 0;\n}\nreturn remainingDays;\n}","lang":""}},{"type":"delimiter","cover":false,"hidden":false,"anchor":"","data":{"type":"default"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"\u003Cp\u003EЕсли вам нужно больше лайфхаков о продвижении в Сети, подписывайтесь на наш\u003Ca href=\"https://api.vc.ru/v2.8/redirect?to=https%3A%2F%2Ft.me%2Fdigitalgeeks&postId=460950\" rel=\"nofollow noreferrer noopener\" target=\"_blank\"\u003E телеграм-канал Digital Geeks\u003C/a\u003E. Его цель — облегчить жизнь директорам и менеджерам по Digital-маркетингу, а также предпринимателям, которые ищут клиентов в Интернете. Из постов вы узнаете, например, о том, как построить эффективную систему управления SЕО, не погружаясь в технические детали, как автоматизировать процессы по продвижению и помочь сотрудникам работать быстрее.\u003C/p\u003E"}}],"summaryContent":null,"isExistSummaryContent":false,"warningFromEditor":null,"warningFromEditorTitle":null,"counters":{"comments":2,"favorites":22,"reposts":0,"views":86,"hits":1689,"reads":null,"online":0},"dateFavorite":0,"hitsCount":1689,"isCommentsEnabled":true,"isLikesEnabled":true,"isRemovedByUserRequest":false,"isFavorited":false,"isPinned":false,"repostId":null,"repostData":null,"subscribedToTreads":false,"isEditorial":false,"isAudioAvailable":false,"audioUrl":null,"isAudioAvailableToGenerate":false,"commentEditor":{"enabled":true,"who":null,"text":"","until":null,"reason":null,"type":"everybody"},"isBlur":false,"isPublished":true,"isDisabledAd":false,"withheld":[],"ogTitle":null,"ogDescription":null,"url":"https://vc.ru/marketing/460950-net-rutine-kak-avtomatizirovat-proverku-ostatkov-v-reklamnyh-kabinetah-yandeksdirekta-i-google-ads-kod-vnutri","author":{"id":722317,"name":"Малюгин Geeks","nickname":"vova_geeks","description":"Руковожу Digital Geeks — агентством performance-маркетинга с уклоном в SEO и GEO-продвижение в нейросетях. Канал: https://t.me/digitalgeeks","uri":"/vova_geeks","avatar":{"type":"image","data":{"uuid":"ce4ff37e-c704-5ab3-9054-2d9cb6c6ab03","width":334,"height":340,"size":55711,"type":"png","color":"95a7a6","hash":"","external_service":[],"base64preview":"/9j/4AAQSkZJRgABAQIAHAAcAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/2wBDAQMDAwQDBAgEBAgQCwkLEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBD/wAARCAAKAAoDAREAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAABQf/xAAmEAACAQIEBQUAAAAAAAAAAAABAgMEEQAFBhIHEyEiYSMxMlHR/8QAGAEAAwEBAAAAAAAAAAAAAAAAAwUGAgT/xAAiEQACAQMEAgMAAAAAAAAAAAABAgADBBEFEyFRMZGhscH/2gAMAwEAAhEDEQA/AHMz0lGeN4parMqxttBCaGCKtdIILt38yIHa5br8hcC3jHPeX1yL2kKbYU+f2Z07TrRtLrNVXLjOD9Slto6bcbBLX6emv5hxvL38yb2n6HoQHT0MMvEOKaSJHdsuWUsygkvtbuv9+cKnUF0OO5TU2IpuAeOJTkY7F6n2GCmBwJ//2Q=="}},"cover":null,"achievements":[{"title":"Год на vc.ru","code":"registration_1_year","description":"Первый год с vc.ru. Получена 24 июля 2025.","previewUuid":"0d11c244-49de-50e7-894e-b9b27945d42b","formats":{"glb":"https://static.vc.ru/achievements/fish.glb","usdz":"https://static.vc.ru/achievements/fish.usdz"},"viewData":{"contentColor":"#C67AA3","textMaxWidth":0.634765625,"textX":0.5888671875,"textY":0.54296875,"logoX":0.5859375,"logoY":0.6669921875,"logoXNoText":0.6044921875,"logoYNoText":0.5439453125},"id":4710099,"userId":722317,"count":0,"shareImage":"https://api.vc.ru/achievements/share/4710099"},{"title":"3 года на vc.ru","code":"registration_3_years","description":"Провёл 3 года вместе с vc.ru. Получена 23 июля 2025.","previewUuid":"d9d72ac5-bcb5-55e0-8c72-b99251e5cdd9","formats":{"glb":"https://static.vc.ru/achievements/shark.glb","usdz":"https://static.vc.ru/achievements/shark.usdz"},"viewData":{"contentColor":"#8E6F09","textMaxWidth":0.66796875,"textX":0.5205078125,"textY":0.341796875,"logoX":0.5205078125,"logoY":0.4609375,"logoXNoText":0.5,"logoYNoText":0.3662109375},"id":1086012,"userId":722317,"count":0,"shareImage":"https://api.vc.ru/achievements/share/1086012"}],"lastModificationDate":1765946582,"isSubscribed":false,"isSubscribedToNewPosts":false,"isMuted":false,"isAvailableForMessenger":true,"badgeId":"1ee4281e-b189-6840-aca8-c2b27ffffb1a","isDonationsEnabled":false,"isPlusGiftEnabled":true,"isUnverifiedBlogForCompanyWithoutPro":false,"isRemovedByUserRequest":false,"isFrozen":false,"isDisabledAd":false,"isPlus":true,"isVerified":false,"isPro":false,"yandexMetricaId":null,"badge":"plus","isOnline":false,"tgChannelShortname":"digitalgeeks","isUnsubscribable":true,"type":1,"subtype":"personal_blog"},"subsite":{"id":199113,"name":"Маркетинг","description":"Рекламные кейсы из России и других стран, советы по продвижению, маркетинг и digital.","uri":"/marketing","avatar":{"type":"image","data":{"uuid":"d66009fe-9bf0-52da-bdbf-4c758eba39e7","width":2400,"height":2400,"size":841299,"type":"jpg","color":"f97373","hash":"0c1cf06cf0d010","external_service":[]}},"cover":{"type":"image","data":{"uuid":"5488a646-f32d-57a6-a31f-d290afc4388a","width":960,"height":280,"size":177,"type":"png","color":"fc7c7c","hash":"","external_service":[]}},"lastModificationDate":1661337194,"isSubscribed":false,"isSubscribedToNewPosts":false,"isMuted":false,"isAvailableForMessenger":false,"isDisabledAd":false,"nickname":"marketing","isUnsubscribable":true,"badge":null,"badgeId":null,"isDonationsEnabled":false,"isOnline":false,"isPlus":false,"isUnverifiedBlogForCompanyWithoutPro":false,"isVerified":false,"isRemovedByUserRequest":false,"isFrozen":false,"isPro":false,"type":2,"subtype":"community"},"reactions":{"counters":[{"id":1,"count":11}],"reactionId":0},"isNews":false,"source":null,"clusters":[],"donations":{"amount":0,"isDonated":false},"commentsSeenCount":null,"keywords":["замените"],"media":null,"customCover":null,"robotsTag":null,"categories":[],"isAnonymized":true}};