3 минут чтения
2 октября 2024 г.
Проблема Roistat как готового решения для аналитики
Нередко компании, которые обращаются к нам за системой сквозной аналитики, уже используют какие-то инструменты для работы с данными. Иногда это «коробочные» решения. Сразу отказываться от них в пользу кастома не обязательно — на старте их можно интегрировать в новую систему, чтобы сэкономить время и деньги на разработку. Но в этом случае надо быть готовым к тому, что готовые решения не гарантируют точность данных на том же уровне, что специально построенная под вас система аналитики. Именно с этой проблемой мы столкнулись, когда начали строить аналитику для стартапа Refocus: до нас они использовали Roistat, но ошибки в его работе вынудили нас отказаться от него раньше, чем мы планировали.
Способов построить сквозную аналитику, не обращаясь к готовым решениям, немало: можно собрать in-house отдел аналитики или найти специалистов на аутсорсе.
При этом нужно учитывать, что работа целой команды аналитики может стоить порядка 5-7 тысяч евро или 500-700 тысяч рублей в месяц. И это не предел — все зависит от размеров компании-заказчика, состояния аналитики до начала работ и других факторов.
На начальном этапе для многих компаний, у которых объем данных небольшой, такие расходы неоправданы. Из-за этого они часто предпочитают «коробочные» продукты — например, тот же Roistat. Это самое популярное решение на рынке, которое предлагает премиум-тариф с максимумом функционала и полной поддержкой от 1500 евро / 150 тысяч рублей в месяц. Базовые тарифы у них и того дешевле. У этого инструмента больше 200 встроенных интеграций, и не только с популярными Google Analytics или Яндекс Директ, но и с целым списком нишевых кабинетов и систем, о которых вы даже не слышали.
После настройки интеграций с вашими источниками Roistat позволит создать дашборды за пару кликов, а сверху предложит автоматизацию маркетинга и лидогенерации. Конкуренты Roistat вроде OWOX BI или Alytics также предоставляют базовые возможности для аналитики и визуализации. В общем, недорогих решений под любые потребности много.
Хотя “коробка” гораздо лучше бесконечных таблиц и поначалу хорошо оптимизирует работу с данными, она далеко не идеальна. С точки зрения эксперта все минусы универсальных решений видны как на ладони:
- не заглянешь под капот, если что-то идет не так;
- их система интеграций может не включать нужных источников;
- интеграции могут устаревать, создавая ошибки в выгрузке данных.
Кроме того, у вендоров таких готовых решений почти никогда нет ресурсов и возможностей, чтобы подогнать его под специфические требования каждого клиента. Более того, чаще такие “кастомные” требования многократно превосходят стоимость самой коробки (в этом суть готового решения). Если что-то не так на бэке у юзера, если меняется воронка в CRM, если нужно настроить кастомные интеграции — велики шансы, что за это придется доплатить немаленькие деньги, если вендор вообще согласится реализовать эти “специфичные требования”.
На одном из наших проектов нам довелось поработать именно с такой ситуацией: Roistat не смог обеспечить точность данных и интеграций со всеми нужными источниками, и с этим пришлось разбираться самой компании — и нам.
Как Refocus работал с аналитикой
Один из наших заказчиков, который строил аналитику на самых ранних этапах — EdTech-стартап Refocus. Неудивительно, что когда мы пришли создавать для них кастомную систему, они уже работали с Roistat.
Почему Refocus выбрали именно его? Во-первых, он доступен на русском языке, и это было удобно для команды, в которой много русскоязычных сотрудников. Во-вторых, им нужна была именно система сквозной аналитики, а не CRM с функцией автоматического построения графиков, поэтому альтернативы вроде HubSpot не подходили. В-третьих, все базовые потребности компании он удовлетворял за относительно небольшую сумму. Ну и в-четвертых — многие сотрудники из команды Refocus уже имели опыт работы с Roistat, так что для них это был удобный и знакомый инструмент.
Roistat тянул данные из двух основных рекламных кабинетов — Google и Facebook*. В нем трекались все базовые метрики — бюджеты, показы, клики, конверсия — и отражались на автоматически созданных внутри программы дашбордах.
К сожалению, скрины дашбордов из Roistat у нас не сохранились, но мы нашли для вас пример в интернете — выглядели они примерно так.
Там даже присутствовал свой пользовательский идентификатор — когда мы вводили общий айди студентов, мы думали попробовать использовать его для мэтчинга персональных данных. На практике оказалось, что сопоставление по нему проходит очень неточно, и эту идею оставили.
Стартап рос, число требований и людей увеличилось, поэтому нас позвали строить для ребят кастомную аналитику и более подробные дашборды, и подключились мы.
Как обнаружилась проблема
Мы провели аудит существующей системы, получили доступы к нужным ресурсам и начали выстраивать инфраструктуру и готовить первый дашборд — маркетинговый, самый актуальный для компании на тот момент.
Откуда мы тянули данные для этого дашборда? Конечно, из Roistat, ведь именно там уже лежали готовые маркетинговые показатели. Настройка хранилища и выгрузка данных из источников, которые Roistat не трекал, еще не была закончена, а смотреть на классные, качественные дашборды хотелось уже сейчас.
Например, так выглядел код для выгрузки данных о затратах на рекламу через API:
def get_costs(channel, channel_level, date_from, date_to, source):
data = ‘{«dimensions»: [«marker_level_2», «marker_level_3», «marker_level_4»],\
«metrics»:[«visitsCost», «impressions», «visits»],\
«period»:{«from»:»‘ + date_from + ‘»,»to»:»‘ + date_to + ‘»},\
«filters»:[{«field»:»‘ + channel_level + ‘», «operation»:»=», «value»:»‘ + channel + ‘»}],\
«interval»: «1d»}’
columns=[‘dimensions.marker_level_2.value’,
‘dimensions.marker_level_2.title’,
‘dimensions.marker_level_3.value’,
‘dimensions.marker_level_3.title’,
‘dimensions.marker_level_4.value’,
‘dimensions.marker_level_4.title’,
‘dateFrom’
]
headers = {‘content-type’: ‘application/json’}
response = requests.request(«POST», url, data=data, headers=headers)
df = response.json()[‘data’]
l = []
for i in range(len(df)):
if df[i][‘items’] != []:
l.append(df[i])
if len(l) > 0:
res1 = pd.json_normalize(l, ‘items’, [‘dateFrom’])[columns]
res2 = pd.DataFrame()
q = pd.json_normalize(l, [‘items’, ‘metrics’])
for x in [«visitsCost», «impressions», «visits»]:
res2[x] = q.query(‘metric_name == @x’)[‘value’].values
res = pd.concat([res1, res2], axis=1)
res[‘source’] = source
return res
else:
return pd.DataFrame()
Подробнее о marker_levels можно прочитать здесь в документации API Roistat.
Когда Refocus посмотрели на первую версию дашборда, они заметили, что цифры не сходятся с их реальными бюджетами, кликами, конверсией в рекламных кабинетах.
Мы начали искать ошибку с нашей стороны, но убедились, что наш код работает исправно и данные в нашем дашборде один в один совпадают с цифрами в Roistat. Никаких сбоев между источником и дашбордом не происходило.
Дело в том, что пока компания смотрела только на визуализации Roistat, расхождения в данных не бросались в глаза. А наш дашборд содержал несколько новых графиков, более подробных, чем мог предложить Roistat. Когда Refocus стали сравнивать детали по разным срезам, на которые Roistat не позволял посмотреть, расхождения стали очевидны.
У нас дашборд был более гибкий — можно было отфильтровать данные по разным важным срезам, более тонко настроить гранулярность. И благодаря этому ошибки в метриках стали заметны.
Об этом мы и сообщили коллегам, продемонстрировав совпадение. Как раз в этот момент сыграл роль недостаток закрытой системы — посмотреть внутрь Roistat и найти, где именно происходит ошибка, не могли ни мы, ни бэкенд-специалисты Refocus.
Разумеется, кастомная система уже предполагала отключение этого источника в будущем — зачем платный посредник, если мы все равно будем грузить данные напрямую и из рекламных кабинетов, и из кучи других источников?
После обнаружения ошибки стало ясно, что затягивать с этим не стоит, если мы хотим предоставить клиенту чистые данные.
Полностью отказаться от Roistat сразу не получилось, поэтому мы добавили на дашборд фильтр “match with Roistat”.
На нем мы отмечали количество рекламных кампаний, данные по которым расходятся с показателями на нашем дашборде и на Roistat’овском.
Как мы наконец заменили Roistat на кастомную систему и уточнили данные о воронках
Мы сразу написали несколько скриптов для выгрузки тех же самых данных из GA4 и Facebook Ads* через API.
Например, так данные о рекламных показах, затратах и кликах за день в разрезе {campaign, adset, adname} выгружались из кабинета GA4:
def get_google_costs(date_start, customer_id):
request = RunReportRequest(
property = f»properties/{property_id}»,
dimensions = [Dimension(name = «date»),
Dimension(name = «sessionGoogleAdsCustomerId»),
Dimension(name = «sessionGoogleAdsCampaignId»),
Dimension(name = «sessionGoogleAdsCampaignName»),
Dimension(name = «sessionGoogleAdsAdGroupId»),
Dimension(name = «sessionGoogleAdsAdGroupName»),
Dimension(name = «sessionGoogleAdsCreativeId»)],
metrics = [Metric(name=»advertiserAdCost»),
Metric(name=»advertiserAdImpressions»),
Metric(name=’advertiserAdClicks’)],
date_ranges = [DateRange(start_date = date_start, end_date = date_start)],
dimension_filter = FilterExpression(
filter = Filter(
field_name = «sessionGoogleAdsCustomerId»,
string_filter = Filter.StringFilter(value = customer_id),
)
),
)
response = client.run_report(request)
date = map(lambda x: x.dimension_values[0].value, response.rows)
customer_id = map(lambda x: int(x.dimension_values[1].value), response.rows)
campname_id = map(lambda x: int(x.dimension_values[2].value), response.rows)
campname = map(lambda x: x.dimension_values[3].value, response.rows)
groupname_id = map(lambda x: int(x.dimension_values[4].value), response.rows)
groupname = map(lambda x: x.dimension_values[5].value, response.rows)
adnam_id = map(lambda x: int(x.dimension_values[6].value), response.rows)
visitsCost = map(lambda x: float(x.metric_values[0].value), response.rows)
impressions = map(lambda x: int(x.metric_values[1].value), response.rows)
visits = map(lambda x: int(x.metric_values[2].value), response.rows)
df = pd.DataFrame({‘region’: customer_id, ‘date’: date, ‘campname’: campname, ‘groupname’: groupname, ‘campname_id’: campname_id, ‘groupname_id’: groupname_id, ‘adnam_id’: adnam_id, ‘visitsCost’: visitsCost, ‘impressions’: impressions, ‘visits’: visits})
return df
df = pd.DataFrame()
После этого обнаружилось еще одно несовпадение: метрики в самом кабинете были чуть меньше, чем у нас на дашбордах. Отклонение не было критичным, но клиент снова не был уверен в точности наших данных.
Оказалось, что в GA4 по умолчанию включается настройка Thresholding applied. Ее цель — предотвратить возможную идентификацию отдельных пользователей по данным о возрасте, гендере и интересах. В результате ее применения терялись данные о кампаниях с небольшим (меньше 50) количеством кликов. Чтобы этого избежать, нужно было или не трекать эти показатели, или не использовать в дашбордах метрики, касающиеся пользователей напрямую. Roistat тоже не выгружал эти “пограничные” кампании через свою дефолтную интеграцию с GA4, поэтому для Refocus расхождение стало неожиданностью. Зато при прямой выгрузке через API этого ограничения не было, и ускользнувшие поначалу кампании считались, так что данные были более полными без дополнительных ухищрений.
С добавлением все новых и новых источников, конечно, пришлось еще и мэтчить данные рекламных кабинетов о затратах, кликах и показах с записями на вебинары и их посещением, со сделками в CRM — но Roistat этого вовсе не делал, и поэтому не мог дать полной картины о воронках.
После введения прямой выгрузки из рекламных кабинетов данные наконец-то стали полностью совпадать с реальностью, и Roistat отключили, заменив другими источниками. Теперь Refocus могли не платить дважды и получить куда более точный анализ.
Выводы
Кастомная сквозная аналитика — конечно, не панацея, и есть много причин и возможностей обойтись без услуг агентств, которые ее строят. Тем не менее, даже самое популярное на рынке коробочное решение, очевидно, не всегда корректно работает. Обрубать его сразу не обязательно, и ничего не мешает сочетать Roistat и похожие продукты с кастомом. В конце концов, иногда удобно просто достроить интеграции, которые не поддерживает Roistat, и держать дашборды в нем. Но в этом случае важно понимать, что данные там могут быть неполными или некорректными, а сообщение с бэком компании — ненадежным. В результате обнаружить или исправить ошибки может быть сложнее, чем организовать прямую выгрузку данных в хранилище — и здесь кастомная система отлично справится.
*Facebook принадлежит компании Meta, которая признана экстремистской организацией в России.
Комментарии
Добавить комментарий
[ Рекомендации ]
Читайте также
[ Связаться ]
Давайте раскроем потенциал вашего бизнеса вместе
Заполните форму на бесплатную консультацию
Спасибо большое, за полезную статью.
Планируете статьи или гайды по OWOX BI выпускать ?