Перейти к содержимому

Откуда пользователь пришёл на самом деле

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

Браузер отдаёт referrer сам. Худшее, что вы получите в вебе, — грязный отчёт. Мессенджер и магазин приложений не передают ничего, поэтому метку вы должны попросить прямо в ссылке и сохранить её у себя при первом же контакте.

Поэтому честный ответ звучит не как «примерно половина пришла из того каталога», а как «я не знаю», потому что из ничего никакой анализ задним числом ничего не сделает.

Почему одна площадка потом оказывается четырьмя

Заголовок раздела «Почему одна площадка потом оказывается четырьмя»

Запишите словарь до того, как уйдёт первая ссылка: фиксированный список значений источника, по одному на площадку, в файле, который можно открыть.

Размечать на ходу не выйдет. За месяц вы получите reddit, Reddit, reddit-selfhosted и r/selfhosted, а склеить их потом не удастся, потому что вы уже не помните, какой пост уходил с какой меткой.

Что считается каналом, включая ваши собственные

Заголовок раздела «Что считается каналом, включая ваши собственные»

Метку вы вешаете на каждую исходящую ссылку. Свой канал, свою рассылку и свой закреплённый пост — тоже. В вебе метка живёт в параметрах кампании, у бота — в payload deep link, у магазина приложений — в ссылке кампании.

Свои посты пропустить проще всего, и стоит это дороже всего. Без метки они падают в direct. Потом вы открываете direct и читаете там сарафанное радио, которого не было.

Влезет, а раньше на этой странице было написано обратное. Telegram документирует 64 символа из A-Za-z0-9_- в start-payload, и ссылка, которую вы раздаёте, выглядит так:

https://t.me/my_bot?start=reddit-selfhosted-2026-08-12

Этот payload занимает 28 символов: площадка, канал и дата уже внутри, место ещё осталось. Разделителей дают два, дефис и подчёркивание. Выберите один, запишите выбор в словарь и не мешайте их. Парсер, которому приходится угадывать, угадает неверно.

Куда класть источник, чтобы его потом не затёрли

Заголовок раздела «Куда класть источник, чтобы его потом не затёрли»

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

create table users (
id bigint primary key,
source text,
source_raw text,
created_at timestamptz not null default now()
);

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

Пишете вы один раз на человека и больше никогда:

insert into users (id, source, source_raw)
values ($1, $2, $3)
on conflict (id) do nothing;

Весь смысл здесь в do nothing: человек вернулся с другой меткой, попал в конфликт, исходное значение уцелело. Last touch почти всегда оказывается вашей же ссылкой — вернувшиеся приходят через ваш канал и перезаписывают ровно тот ответ, ради которого всё затевалось.

Что записывать про тех, кто пришёл без метки

Заголовок раздела «Что записывать про тех, кто пришёл без метки»

Дайте им отдельную корзину и назовите её unknown. Свалите их в direct — и дырка в данных превратится в уверенный неверный вывод на графике.

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

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

Это не вежливость. Сарафанное радио не несёт метки, ни один технический метод с этой страницы его не видит, и ответ самого человека — единственное место, где оно вообще появится.

Задним числом атрибуцию не восстановить. Поэтому эта страница стоит в маршруте рано, а не поздно: каждый день с голыми ссылками — это приходы, которые вы уже никогда не разложите по источникам.

  • Считать, что источник виден по умолчанию. Ссылки у меня были голые, обработчик не читал start parameter, и колонки, которая приняла бы его, всё равно не было. Атрибуцию я имел не приблизительную, а нулевую, и месяцы работы над дистрибуцией остались без оценки.
  • Читать географию пользователей как сигнал рынка. Состав пользователей шёл за полем метаданных, а не за рынком. Полем этим оказался алфавит, которым написано имя моего продукта, и продуктовые теории я построил на артефакте имени.
  • Считать параметр deep link слишком коротким для схемы. Здесь было написано, что структурное значение туда не влезет. В документации Telegram — 64 символа, нужная мне схема заняла 28, а мешал всё это время не параметр, а отсутствующая колонка.
  • Писать источник при каждом контакте. За несколько недель вся моя таблица стала говорить «мой собственный канал». Вернувшиеся жмут именно туда.
  • Добавить метку, но не добавить колонку. Параметр приходил, попадал в строку лога и там же уезжал в ротацию. Мои ссылки неделями выглядели размеченными. Не сохранялось при этом ничего.
  • Верить referrer в веб-аналитике. Встроенные браузеры и превью ссылок его срезают, поэтому настоящие переходы копятся в direct. Отчёт у меня был уверенно неверный, и это хуже пустого.
  • Спрашивать «откуда вы про нас узнали» на первом экране. Вопрос встаёт между человеком и ценностью, и ровно там onboarding и теряет людей. Ответ стоит меньше, чем этот лишний шаг.
  • Одна метка на весь день запуска. Пять площадок под одной меткой сказали мне, что запуск сработал. Какую из пяти повторять, они не сказали, а это было единственное, что я хотел знать.
  • Открыть свою же размеченную ссылку, зарегистрироваться по ней и прочитать строку из базы, в которой значение источника и должно лежать.

  • Вернуться по другой размеченной ссылке. Сохранённое значение обязано остаться прежним.

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

    select date_trunc('week', created_at) as week,
    count(*) as signups,
    count(source) as tagged
    from users
    group by week
    order by week desc;
  • Сверить ответы самих людей с сохранёнными метками, и там, где ответ и метка расходятся, метка обычно не неверная. Её просто нет.

  • Отправить себе ссылку с меткой, которой ваш парсер никогда не видел, и она должна попасть в unknown, а не уронить код и не превратиться тихо в direct.

  • Сгруппировать сохранённые источники по месяцам и посмотреть на площадки, которыми вы уже не пользуетесь.

    select date_trunc('month', created_at) as month,
    source,
    count(*)
    from users
    group by month, source
    order by month desc, count(*) desc;

    Вы бросили площадку месяцы назад, а она всё ещё набирает строки в этом месяце. Значит, колонку перезаписывают или подставляют в неё дефолт.

Следующий вопрос — во сколько вам обходится приходящий пользователь: сколько стоит один пользователь.

Предложить правку · Страница не помогла