Воркшоп: Анализ показателя качества ключевых слов в Google Ads с помощью языка R и пакета rgoogleads

Воркшоп по работе с Google Ads API с помощью языка R и пакета rgoogleads. В ходе которого мы с нуля разберёмся как пройти авторизацию, запрашивать отчёты из Google Ads, и проанализируем показатель качества ключевых слов рекламного аккаунта.

Видео

Тайм коды:

  • 00:00:00 Приветствие
  • 00:01:12 О спикере
  • 00:03:43 Программа воркшопа
  • 00:04:14 Что такое контекстная реклама и сервис Google Ads
  • 00:06:34 Варианты авторизации в пакете rgoogleads
  • 00:07:24 Авторизация в Google Ads с помощью дефолтных параметров пакета rgoogleads
  • 00:10:00 Создание собственных учётных данных для авторизации
  • 00:21:12 Авторизация в Google Ads с помощью собственных учётных данных
  • 00:23:00 Иерархия аккаунтов в Google Ads API
  • 00:24:53 Ограничения при использовании собственных учётных данных
  • 00:25:54 Автоматизация процесса авторизации с помощью переменных среды
  • 00:26:43 Опции пакеа rgoogleads
  • 00:27:34 Запрос отчётов из Google Ads API
  • 00:30:49 GAQL QueryBuilder
  • 00:34:52 Пример запроса отчётов из Google Ads API
  • 00:39:54 Аргументы функции gads_get_report()
  • 00:41:13 Загрузка отчётов из Google Ads API в многопоточном режиме
  • 00:44:34 Запрос объектов рекламного кабинета Google Ads
  • 00:45:49 Что такое показатель качества ключевых слов и как проходит аукцион среди рекламодателей в Google Ads
  • 00:47:47 Что влияет на показатель качества ключевых слов Google Ads
  • 00:48:29 На что влияет показатель качества Google Ads
  • 00:49:16 Пример анализа качества ключевых слов
  • 01:03:36 Ответы на вопросы

Презентация

Материалы к воркшопу

Скрипт 1-google-ads-auth.R

library(rgoogleads)

# простейший способ авторизации
gads_auth('a.seleznev@netpeak.group')

# учётные данные кешируются в файл
gads_auth_cache_path()
gads_open_auth_cache_folder()

# настройка конфигурации авторизации
gads_auth_configure(
  path = 'auth/gads.client.json'
    )

gads_auth('a.seleznow@netpeak.group')

# иерархия аккаунтов
top_accounts <- gads_get_accessible_customers()

# опции
gads_set_login_customer_id(1754107253)

# запрос все иерархии аккаунтов
account_hie <- gads_get_account_hierarchy()

Скрипт 2-google-ads-reporting.R

library(rgoogleads)

# ####################################
# авторизация
gads_auth('a.seleznev@netpeak.group')

# ####################################
# установка клиентского и упраляющего аккаунта
gads_set_login_customer_id("175-410-7253")
gads_set_customer_id("896-697-8643")

# ####################################
# запрос данных используя текст GAQL запроса
## Текст запроса
campaign_query <- "
SELECT 
  campaign.id, 
  campaign.name, 
  segments.date, 
  metrics.clicks, 
  metrics.impressions 
FROM campaign 
WHERE 
  segments.date DURING THIS_MONTH AND metrics.clicks > 0
"

## Запрос данных
campaign_data <- gads_get_report(gaql_query = campaign_query) 

# ####################################
# метаданные и информация о ресурсах
resources <- gads_get_metadata("RESOURCE")
metadata  <- gads_get_metadata("ALL")

fields    <- gads_get_fields("campaign")

# ####################################
# Задаём параметры запроса внутри gads_get_report()
## Повторяем используемый ранее запрос, но через параметры функции
campaign_data_2 <- gads_get_report(
  resource = "campaign", 
  fields   = c("campaign.id", 
               "campaign.name",
               "segments.date", 
               "metrics.clicks",
               "metrics.impressions"), 
  during = "THIS_MONTH",
  where  = "metrics.clicks > 0") 

# Статичные даты
campaign_data_3 <- gads_get_report(
  resource = "campaign", 
  fields   = c("campaign.id", 
    "campaign.name",
    "segments.date", 
    "metrics.clicks",
    "metrics.impressions"), 
  date_from = "2022-04-01", date_to = "2022-04-19",
  where  = "metrics.clicks > 0") 

# ####################################
# Использование многопоточности
## задаём список клиентских аккаунтов
client_ids <- c(
  "896-697-8643", 
  "201-949-5809", 
  "263-160-7978", 
  "793-293-9250", 
  "927-254-7535")

gads_set_login_customer_id("175-410-7253")
gads_set_customer_id(client_ids)

## создаём кластер
cl <- parallel::makeCluster(4)

## выполняем запрос в многопоточном режиме
tictoc::tic("Loading in parallel")

multi_account_data <- gads_get_report(
  resource = "campaign", 
  fields   = c("campaign.id", 
    "campaign.name",
    "segments.date", 
    "metrics.clicks",
    "metrics.impressions"), 
  during = "THIS_MONTH",
  where  = "metrics.clicks > 0", 
  cl     = cl) 

tictoc::toc()

## останавливаем кластер
parallel::stopCluster(cl)

## запускаем тот же запрос в последовательном режиме
tictoc::tic("Loading in sequences")

multi_account_data <- gads_get_report(
  resource = "campaign", 
  fields   = c("campaign.id", 
    "campaign.name",
    "segments.date", 
    "metrics.clicks",
    "metrics.impressions"), 
  during = "THIS_MONTH",
  where  = "metrics.clicks > 0") 

tictoc::toc()

# ####################################
## Забираем списки объектов
gads_set_customer_id("927-254-7535")

campaigns <- gads_get_campaigns()
ad_groups <- gads_get_ad_groups()
ads       <- gads_get_ads()
keywords  <- gads_get_keywords(limit = 100)

3-google_ads_quality_score_analisys.R

# подключение пакетов
library(rgoogleads)
library(dplyr)
library(forcats)
library(ggplot2)

# авторизация
gads_auth('a.seleznev@netpeak.group')

# аккаунты
## управляющий аккаунт
gads_set_login_customer_id('175-410-7253')
## рекламный аккаунт
gads_set_customer_id('474-944-7568')

# запрос данных из Google Ads
ads_data <- gads_get_report(
  resource = 'keyword_view', 
  fields = c('customer.descriptive_name', 
             'ad_group_criterion.criterion_id', 
             'ad_group_criterion.final_urls',
             'ad_group_criterion.status',
             'ad_group.id', 
             'ad_group.name',
             'ad_group.status',
             'campaign.id',
             'campaign.name',
             'campaign.status',
             'metrics.impressions',
             'metrics.clicks',
             'metrics.cost_micros',
             'metrics.ctr',
             'metrics.search_top_impression_share',
             'ad_group_criterion.quality_info.creative_quality_score',
             'ad_group_criterion.quality_info.post_click_quality_score',
             'ad_group_criterion.quality_info.search_predicted_ctr', 
             'ad_group_criterion.quality_info.quality_score'),
  where     = c('metrics.impressions > 0', 
                'ad_group_criterion.quality_info.creative_quality_score IN ("ABOVE_AVERAGE", "AVERAGE", "BELOW_AVERAGE")'),
  during    = 'LAST_30_DAYS'
)

# Определяем группу показателя качества для каждого ключевого слова
ads_data <- mutate(ads_data, 
                   qiality_score_group = case_when(
                     ad_group_criterion_quality_info_quality_score <= 4           ~ 'Low',
                     between(ad_group_criterion_quality_info_quality_score, 5, 7) ~ 'Middle',
                     ad_group_criterion_quality_info_quality_score >= 8           ~ 'High'
                   )
)

# Визуализация среднего показателя качества в разрезе кампаний
ads_data %>% 
  group_by(campaign_name) %>% 
  summarise(avg_qs = mean(ad_group_criterion_quality_info_quality_score, na.rm = TRUE)) %>% 
  ggplot(aes(x = fct_reorder(.f = campaign_name, .x = avg_qs, .fun = median), y = avg_qs, fill = avg_qs)) +  
  geom_bar(stat = "identity", position = "dodge") +
  theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0.5, size = 9)) + 
  scale_fill_gradient(low = hcl(15,100,75), high = hcl(195,100,75)) +
  ggtitle("Average Quality Score by Campaign") +
  xlab('Campaign') +
  ylab('Average Quality Score')

# Визуализация по группированному показателю качества
ads_data %>% 
  group_by(campaign_name, qiality_score_group) %>% 
  summarise(keywords_count = n_distinct(ad_group_criterion_criterion_id)) %>% 
  ggplot(aes(x = campaign_name, y = keywords_count,fill = qiality_score_group))+  
  geom_col(stat = "count", position = "fill") +  
  scale_fill_manual(breaks=c("High","Middle","Low"),
                    values=c(High = "forestgreen", 
                             Middle = "tan1" , 
                             Low = "firebrick1"))+  
  theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0.5, size = 9))+  
  ggtitle("Number of keywords by Quality Score Group") +
  xlab('Campaign') +
  ylab('Kweywords number')

# Визуализация по релевантности объявления
ggplot(ads_data, aes(x = campaign_name, fill = ad_group_criterion_quality_info_creative_quality_score))+  
  geom_bar(stat = "count", position = "fill")+   
  scale_fill_manual(values=c("forestgreen", "tan1" , "firebrick1","grey" ))+  
  theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0.5, size = 9), 
        legend.position = 'bottom')+  
  ggtitle("Landing page experience by Campaign") +
  xlab('Campaign') +
  ylab('Kweywords number')

# Визуализация по качеству целевой страницы
ggplot(ads_data, aes(x = campaign_name, fill = ad_group_criterion_quality_info_post_click_quality_score))+  
  geom_bar(stat = "count", position = "fill")+   
  scale_fill_manual(values=c("forestgreen", "tan1" , "firebrick1","grey" ))+  
  theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0.5, size = 9), 
        legend.position = 'bottom')+  
  ggtitle("AdRelevance by Campaign") +
  xlab('Campaign') +
  ylab('Kweywords number')

# Визуализация по ожидаемому значению CTR
ggplot(ads_data, aes(x = campaign_name, fill = ad_group_criterion_quality_info_search_predicted_ctr))+  
  geom_bar(stat = "count", position = "fill")+   
  scale_fill_manual(values=c("forestgreen", "tan1" , "firebrick1","grey" ))+  
  theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0.5, size = 9), 
        legend.position = 'bottom')+  
  ggtitle("Expected CTR by Campaign") +
  xlab('Campaign') +
  ylab('Kweywords number')

# оценка % показа над результатами поиска
ads_data %>% 
  group_by(qiality_score_group) %>% 
  mutate(med_impression_share = median(search_top_impression_share)) %>% 
  ggplot(aes(x = fct_relevel(qiality_score_group, "Low", "Middle", "High"), y = search_top_impression_share, fill = med_impression_share))+
  geom_boxplot(outlier.color = "grey", outlier.stroke = F) +
  scale_fill_gradient(high = hcl(15,100,75), low = hcl(195,100,75)) +
  scale_y_continuous(labels = scales::percent_format()) +
  theme(legend.position = 'none') +
  ggtitle("Search Top Impression Share by Quality Score Group") +
  xlab('Quality Score Group') +
  ylab('Search Top Impression Share, %')

# CTR в зависимости от группы показателя качества
ads_data %>% 
  group_by(qiality_score_group) %>% 
  mutate(med_ctr = median(ctr)) %>% 
  ggplot(aes(x = fct_relevel(qiality_score_group, "Low", "Middle", "High"), y = ctr, fill = med_ctr))+
  geom_boxplot(outlier.color = "grey", outlier.stroke = F) +
  scale_fill_gradient(high = hcl(15,100,75), low = hcl(195,100,75)) +
  scale_y_continuous(labels = scales::percent_format()) +
  theme(legend.position = 'none') +
  ggtitle("Search Top Impression Share by Quality Score Group") +
  xlab('Quality Score Group') +
  ylab('Search Top Impression Share, %')


Google BigQuery: Динамический UPSERT с помощью EXECUTE IMMEDIATE

Обычный паттерн обновления данных в BigQuery — добавление новых записей, даже если это означает дублирование данных. А затем обрабатывать дубликаты при чтении с помощью группировки или оконных функций, или удаление записей, и последующая повторная запись одних и тех же данных, но уже с новыми значениями. В любом случае все эти варианты не являются лучшей практикой.

Иногда вам нужно выполнить UPSERT операцию (обновление или вставку) данных одним запросом. Возможно вы хотите «исправить» некоторые записи, или внести какие-то обновления в них (например обновить статусы транзакций), либо хотите сохранить чистую таблицу без дубликатов для своего коллеги-аналитика или специалиста по данным.

Продолжить чтение «Google BigQuery: Динамический UPSERT с помощью EXECUTE IMMEDIATE»

Как в Google Таблицу загрузить данные из Google BigQuery (видео урок)

Недавно в интерфейс Googlе Таблиц добавили меню «Коннекторы данных». Пока там доступен только один нативный коннектор, к облачной базе данных Google BigQuery.

Опубликовал видео обзор этой функции, в котором продемонстрировал все возможности коннектора к Google BigQuery.

Продолжить чтение «Как в Google Таблицу загрузить данные из Google BigQuery (видео урок)»

Пишем telegram бота на языке R (часть 5): Управление правами пользователей бота

В предыдущих статьях мы достаточно подробно разобрали тему ботостроения, от отправки первого сообщения до программирования логического диалога с ботом.

Это последняя статья из данной серии, в которой мы разберёмся с тем, как управлять правами использования отдельных методов бота на различных уровнях.

Продолжить чтение «Пишем telegram бота на языке R (часть 5): Управление правами пользователей бота»

Доклад: Зачем интернет маркетологу понимать что такое API. Разбираем устройство API Google Ads (8P 2021)

В ходе доклада мы разберёмся с тем, как знания языков программирования облегчат работу маркетологу, разберёмся с устройством API одной из наиболее популярных в мире рекламных платформ Google Ads. И разберём функционал новой библиотеки rgoogleads, которая значительно упрощает работу с API Google Ads.

Продолжить чтение «Доклад: Зачем интернет маркетологу понимать что такое API. Разбираем устройство API Google Ads (8P 2021)»

Как загружать данные о расходах, офлайн-конверсиях и звонках в Яндекс Метрику

Весной 2020 года в Яндекс Метрике появился отчёт «Источники, расходы и ROI». Отчет автоматически посчитает ROI по всем рекламным источникам, при одном условии: вам необходимо передать в Метрику всю информацию для расчетов. 

Информацию по доходу необходимо передавать либо через ценность цели, либо через Ecommerce.

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

В этой статье мы разберемся, как бесплатно загружать в Яндекс.Метрику расходы, офлайн-конверсии и данные о звонках с помощью языка R и пакета rym.

Поскольку рекламных кабинетов, сервисов коллтрекинга и CRM систем существует достаточно много, в этой статье мы не будем останавливаться на том, как получить данные из нужных источников для загрузки в Метрику. Поэтому я приведу ссылки на некоторые статьи, которые помогут вам разобраться с тем, как запрашивать данные из популярных источников с помощью языка R:

На самом деле почти для любого источника данных можно найти готовый пакет на R, поэтому в этой статье я акцентирую внимание на загрузке данных в Яндекс.Метрику.

Кстати, ранее я уже рассказал в одной из статей и вебинаре о том, как на языке R запрашивать данные из Яндекс Метрики.

Продолжить чтение «Как загружать данные о расходах, офлайн-конверсиях и звонках в Яндекс Метрику»

Пишем telegram бота на языке R (часть 4): Построение последовательного, логического диалога с ботом

Если вы уже ознакомились с предыдущими тремя статьями из данной серии, то вы уже умеете писать полноценных telegram ботов с клавиатурой.

В этой статье мы с вами научимся писать бота, который будет поддерживать последовательный диалог. Т.е. бот будет задавать вам вопросы, и ждать от вас ввода какой-либо информации. В зависимости от введённых вами данных бот будет выполнять некоторые действия.

Также в данной статье мы научимся использовать под капотом бота базы данных, в нашем примере это будет SQLite, но вы можете использовать любую другую СУБД. Более подробно о взаимодействии с базами данных на языке R я писал в этой статье.

Продолжить чтение «Пишем telegram бота на языке R (часть 4): Построение последовательного, логического диалога с ботом»

Пишем telegram бота на языке R (часть 3): Как добавить боту поддержку клавиатуры

Это третья статья из серии «Пишем telegram бота на языке R». В предыдущих публикациях мы научились создавать телеграм бота, отправлять через него сообщения, добавили боту команды и фильтры сообщений. Поэтому перед тем как приступить к чтению данной статьи я крайне рекомендую ознакомиться с предыдущими, т.к. тут я уже не буду останавливать на описанных ранее основах ботостроения.

В этой статье мы повысим юзабилити нашего бота за счёт добавления клавиатуры, которая сделает интерфейс бота интуитивно понятным, и простым в использовании.

Продолжить чтение «Пишем telegram бота на языке R (часть 3): Как добавить боту поддержку клавиатуры»

Пишем telegram бота на языке R (часть 2): Добавляем боту поддержку команд и фильтры сообщений

В предыдущей публикации мы разобрались как создать бота, инициализировали экземпляр класса Bot и ознакомились с методами отправки сообщений с его помощью.

В этой статье я продолжаю данную тему, поэтому приступать к чтению данной статьи я рекомендую только после прочтения первой части.

В этот раз мы разберёмся как оживить нашего бота и добавим ему поддержку команд, а также познакомимся с классом Updater.

В ходе статьи мы напишем нескольких простых ботов, последний будет по заданной дате и коду страны определять является ли день в данной стране выходным или рабочим согласно производственного календаря. Но, как и прежде цель статьи ознакомить вас с интерфейсом пакета telegram.bot для решения ваших собственных задач.

Продолжить чтение «Пишем telegram бота на языке R (часть 2): Добавляем боту поддержку команд и фильтры сообщений»

Создайте бесплатный сайт или блог на WordPress.com.

Вверх ↑