Глубокие ссылки в Telegram: параметр start для трекинга и рефералок
Практика3 минРедакция Innovialabs
Коротко
Добавьте к ссылке на бота ?start=КОД (или ?startapp=КОД для Mini App) — бот получит этот код при запуске, и вы узнаете, какая реклама, блогер или друг привели пользователя.
Как работает параметр start
Глубокая ссылка — обычная ссылка t.me с одним дополнительным параметром. Когда пользователь открывает https://t.me/your_bot?start=c_8f3k2 и нажимает Start, бот получает сообщение /start c_8f3k2.
Для Mini App параметр называется startapp: https://t.me/your_bot/app?startapp=c_8f3k2 открывает приложение и передаёт значение как start_param в данных запуска. Бот в этом случае сообщения не получает — значение доступно только внутри Mini App.
Одной ссылки на каждое размещение достаточно, чтобы понимать, откуда пришёл пользователь: из рекламной кампании, от блогера, по QR-коду на упаковке или по приглашению друга.
Правила для параметра
- До 64 символов.
- Допустимые символы:
A-Z,a-z,0-9,_и-. - Без пробелов,
=,&и кириллицы — поэтому UTM-строка целиком не поместится.
| Подход | Пример | Когда подходит |
|---|---|---|
| Короткий читаемый код | ig_spring | Кампаний немного |
| Поля с разделителями | src-ig__cmp-spring | Несколько атрибутов, без базы |
| ID из базы данных | c_8f3k2 | Кампаний много, связи могут меняться |
| Base64url | закодированный JSON | Произвольные данные в пределах 64 символов |
Самый практичный вариант — ID из базы: храните кампанию (источник, площадку, креатив, дату) в таблице, а в ссылку кладите только короткий ID. Ссылки остаются короткими, не раскрывают внутренние названия, а ошибку в разметке можно исправить без перевыпуска ссылок.
Обработка в aiogram и grammY
В aiogram 3 обработчик deep link регистрируется раньше обычного /start:
from aiogram import Router
from aiogram.filters import CommandStart, CommandObject
from aiogram.types import Message
router = Router()
@router.message(CommandStart(deep_link=True))
async def start_with_code(message: Message, command: CommandObject):
await save_touch(message.from_user.id, command.args)
await message.answer("Добро пожаловать!")
@router.message(CommandStart())
async def start_plain(message: Message):
await message.answer("Добро пожаловать!")
В grammY значение доступно как ctx.match:
bot.command("start", async (ctx) => {
const code = ctx.match; // пустая строка, если параметра нет
if (code) await saveTouch(ctx.from!.id, code);
await ctx.reply("Добро пожаловать!");
});
В Mini App Telegram.WebApp.initDataUnsafe.start_param подходит для решений в интерфейсе, но для атрибуции доверяйте только значению из initData, проверенной на сервере.
Атрибуция рекламного трафика
- Создайте запись кампании и отдельную ссылку для каждого размещения.
- При
/startсохраняйте первое касание, только если пользователь новый. Последующие касания пишите в отдельную таблицу. - Связывайте пользователей с целевыми событиями — регистрацией, заказом, оплатой — и считайте конверсии по кампаниям, а не только запуски.
- Пользователей без параметра помечайте как органику или «неизвестно»: Telegram не передаёт реферер, и тот, кто нашёл бота через поиск, придёт без кода.
Заранее решите, по какой модели строятся отчёты — первое или последнее касание. Пользователь может открывать разные ссылки в разное время, и смешение моделей делает цифры несопоставимыми.
Реферальная программа с защитой от накруток
Реферальная ссылка выглядит как ?start=ref_x7k2p. Используйте случайный код для каждого пользователя, а не Telegram ID: ID легко перебрать, и он раскрывает данные аккаунта.
Базовая защита:
- Только новые пользователи. Если приглашённый уже был в базе — бонуса нет.
- Запрет самоприглашения. Игнорируйте код, принадлежащий самому пользователю.
- Награда за целевое действие, а не за
/start. Нажать Start ничего не стоит, и фермы фейковых аккаунтов быстро выкачают программу «бонус за запуск». - Период удержания перед выплатой бонусов, чтобы успели проявиться возвраты и фрод.
- Уникальное ограничение: одна реферальная запись на приглашённого, чтобы повторы и двойные нажатия не создавали дубли.
- Лимиты и алерты: ограничьте число наград на одного пригласившего в день и отмечайте резкие всплески или приглашённых, которые ничего не делают после запуска.
Частые ошибки
- Полная UTM-строка в ссылке: она нарушает правила символов, и параметр теряется.
- Перезапись источника при каждом
/start— исходная кампания пропадает. - Доверие к
start_paramс клиента без проверки на сервере. - Необработанный случай пустого параметра, из-за которого падает обработчик.