Когда наш продукт (протокол рекуррентных криптоплатежей на NodeJs, React) вырос, возникла необходимость подключить систему продуктовой аналитики, чтобы понимать, что и как делают наши пользователи. В статье хочу рассказать об опыте подключения и использования системы аналитики Posthog. Думаю, статья будет полезна разработчикам, впервые подключающим аналитику, техдиректорам и менеджерам для оценки потенциальных сроков и рисков.
UPD. Внимание пользователям из России, Posthog соблюдает санкции США и после 9 сентября 2024 пользоваться им легально из РФ не получится

Выбор инструмента
Как водится, вначале мы подключили Google Analytics, и даже залогировали определенные события. Но в процессе работы стало понятно, что нужно ее менять. Во-первых, GA4 не заточена под продукт, а больше под веб-аналитику. Во-вторых, ее юзабилити под большим вопросом. В-третьих, завязываться на монополиста, особенно в крипте – не самая лучшая идея (децентрализация все-таки, вспомним client diversity – всегда выбираем наименее распространенное решение). И в-четвертых, хотелось выбрать опенсорс решение, которое можно будет перетащить на собственный сервер в случае чего.
Выбирал между опенсорсными umami, matomo, plausible, posthog. Первый выбор всегда очень субъективен – продукт еще не попробовал, зазывающие сообщения с сайта не в счет. У всех примерно около 20к звезд на Гитхабе. Исключил matomo (может, зря) – первый коммит 2011 год, побоялся что старовата и много легаси – в итоге остановился на posthog (в разработке с 2020го). Подкупило позиционирование – сразу про developers (а я разработчик) – а также конкретика на главной странице – оцените – "код – вместо тысячи слов".


Первые шаги
Стандартно, создал проект, подключил в приложение скрипт аналитики.

Можно подключать через голый JS (см. выше), можно через библиотеку языка, который вы используете. Порадовала документация, где есть описания для более чем десятка языков и технологий. Да, все это "одно да потому", и можно дойти самому, но удобно прочитать непосредственно про свою технологию.

В настройках проекта можно включить
Autocapture (по умолчанию логгировать клики, ввод текста, смены фокуса)
Heatmaps (тепловые карты, где можно посмотреть, куда чаще всего смотрят/кликают пользователи).
Можно сразу отфильтровывать "внутренних" пользователей, чтобы не сбивали статистику

Session replay (запись сессий, чтобы посмотреть видео, как себя вели пользователи).
И множество других настроек, довольно понятных.
Первым делом я хотел разделить разные окружения, чтобы не смешивать данные локального тестирования и облачных окружений development/stage/production. Оказалось, на free плане только один проект, поэтому я подался на стартап программу, в рамках которой дали еще $50K кредитов, которые нам, конечно же, пока не пригодились. Posthog тарифицируется согласно использованным ресурсам (usage-based), до определенного предела не платите ничего – на текущий момент бесплатны (за месяц) до 1 000 000 событий (events), до 5000 записей (session replays), 1 000 000 флагов (feature flags), 250 ответов опросов (surveys).
Особенность – в рамках стартап программы нам дали $50K кредитов на год с момента одобрения, а кредиты нам по факту не нужны, т.к. мы в пределах бесплатного плана пока. Сейчас бы я подался на стартап программу только тогда, когда не влезаю в free план, чтобы год начался как можно позже.
Начало работы
Мы составили эксельку с событиями, которые нужно отправлять в аналитику, и прикрутили вызовы posthog в коде в нашем Реакт-приложении.

А вот как отправляется событие в posthog (очень стандартно, события и его свойства):
posthog.capture('payment_success', {
price: 1599,
plan_id: 'XYZ12345',
frequency: 'monthly',
features: {
'SSO': true,
'Custom branding': true,
'Custom domains': false,
}
})
Воронки
Первым делом я построил воронку по событиям. Все оказалось довольно интуитивно понятно.


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

A/B тестирование
Много слышал про A/B тестирование и впервые реализовал его руками. В posthog это делается на основе feature flags (не знаю как лучше перевести на русский, будет просто флаг). То есть вы создаете, например, эксперимент с флагом signup-button-color, который возвращает цвет кнопки для текущего пользователя. Он будет возвращать значение либо control (это нельзя изменить), обозначающее дефолтный (зеленый) цвет, либо red, blue. По умолчанию распределение будет 33,3% на каждый из флагов (конечно, проценты можно поменять в настройках). В ходе эксперимента мы задаем, конверсию в какое событие мы измеряем:


В коде фронтенда у вас будет код что-то вроде (псевдокод):
const variant = useFeatureFlagVariantKey('signup-button-color');
const color = variant === 'control' ? 'green' : variant;
signUpButton.color = color;
Далее отправляете события как обычно и posthog считает, где лучше конверсия. Подробности можно прочитать в официальной документации. Что мне нравится – любая документация покрывает сразу все языки и среды разработки (см. рисунок ниже, выбираешь язык и получаешь сниппеты для него).

Бутстрапинг флагов (feature flags bootstrapping)
На текущем шаге может показаться, что все очень просто и безоблачно :) на самом деле это не так, есть множество нюансов. Мне нужен было сделать A/B тест с редиректом – направлять пользователя на одну или другую страницу в зависимости от значения флага. Проблема в том, что posthog запрашивает флаг с некоторой задержкой на клиенте, поэтому мгновенный редирект невозможен. Для этого используется бутстрапинг флагов:
При первой загрузке страницы серверная часть приложения запрашивает значения всех флагов для пользователя. Тут есть 2 варианта:
Пользователь не новый – в браузере лежит cookie с distinct_id пользователя.
Новый пользователь – мы вручную генерируем distinct_id пользователя функцией crypto.randomUUID().
Мы получаем флаги для полученного в варианте 1 или 2 distinct_id, далее устанавливаем их значение в cookie.
На клиенте, в инициализации posthog, достаем значения флагов из куки и соответственно, имеем в наличии его значение сразу же, не дожидаясь еще одного запроса на удаленный сервер posthog.
Все бы хорошо, но у нас был фронтенд на create-react-app без серверной части...

Миграция на Next.js
Пришлось мигрировать проект на nextjs 14, к тому же у нас в планах был SSR (серверный рендеринг), пришлось совместить. За основу взял инструкцию с сайта некста, она в принципе ничего, но основное время ушло на то, чтобы использовать существующие клиентские компоненты/страницы (например, использующие useEffect или компоненты типа web3modal, которые используют useEffect). Я подгружал клиентские компоненты в серверных страницах (из папки app AppRouter) через динамический импорт, ниже сильно упрощенный код:
import dynamic from "next/dynamic";
import Loader from "src/components/Loader";
// динамически подгрузить клиентский компонент
const TariffPlanPage = dynamic(() => import("src/pages/TariffPlan"), {
ssr: false,
loading: () => <Loader />,
});
type ParamsType = {
params: {
// входные параметры для страницы
};
};
export default async function Page({ params }: ParamsType) {
const { pageParam1, pageParam2 } = params;
// загрузить данные
const response = await fetch('https://myapi/v1/data');
const data = await response.json();
// показать клиентскую страницу с загруженными данными
return (
<TariffPlanPage
prop1={data.prop1}
prop2={data.prop2}
/>
);
}
Миграция на Next.js заняла примерно 2 недели (не сильно большой проект) без опыта его предыдущего использования. Далее использовал nextjs middleware по инструкции posthog, чтобы забутстрапить флаги и сделать A/B тест на редирект.
Из нюансов, мне нужно было устанавливать флаг только для тех пользователей, которые открыли определенный URL для редиректа. Сложность в том, что нужно было делать это на сервере при первом обращении, когда у posthog еще нет данных, что это за пользователь и с какого URL он зашел. В таком случае можно самостоятельно задать свойства (overriding server properties), чтобы вернуть нужное значение флага.
Разное
Текущее
Есть удобные инструменты, такие как Activity (можно посмотреть поток происходящих событий), People (пользователи).


Удобно использовать posthog как хранилище данных на лендингах и в экспериментах – просто отправить событие с атрибутами пользователя (например, имя или email), а потом экспортировать в CSV – например, чтобы посмотреть, кто оставил контакты.
У нас в платежке пользователь авторизуется по адресу кошелька. В процессе работы поняли, что забыли писать адрес кошелька в событие, чтобы идентифицировать пользователя.
Reverse proxy
Столкнулись с тем, что плагины типа Adblock блокируют обращения к серверам posthog. Чтоб пофиксить сделали reverse proxy (в данном случае через Next.js) – это когда posthog обращается вместо us.i.posthog.com обращается к нашему серверу, а сервер обращается уже к облаку.
Выводы
Минусы
Стабильность. В процессе написания статьи я получал "A server error occurred", когда пытался получить данные (хотя такого за 2 месяца использования не видел). Иногда подглючивает UI, приходится перезагружать страницу. Не работал с большими объемами данных, как себя поведет – пока сказать не могу. В целом, есть ощущение, что продукт чуть сыроват. Возможно, более зрелые системы не имеют таких недостатков.
Плюсы
Интуитивная понятность UI и концепций. После GA4 думаешь, что аналитика – это очень сложно. После posthog – что все очень просто и понятно. Действительно ориентация на разработчиков – документации много и в ней много конкретики, кода. Хорошая бесплатная поддержка – к каждой статье можно оставить комментарий и автор статьи быстро отвечает. Понятная цена и наличие стартап программы.
Результат
Подключение аналитики заняло примерно недели три, при кажущейся простоте. Система работает и собирает данные, накапливаем данные для A/B оптимизации.
Возможно, кому-то могло показаться, что статья уж больно ванильная :) Я с posthog никак не аффилирован, просто описал свой опыт. Надеюсь, вы почерпнули что-то полезное. Будет интересно узнать про ваш опыт с аналитикой, особенно по другим системам – делитесь в комментариях.
Минутка PR. Веду тг‑канал Web3 разработчик. Пишу небольшие заметки (не часто) о задачах по блокчейну/крипте, которые решаю. Буду рад видеть среди подписчиков!