self-hosted deep linking · атрибуция установок
ведём человека от клика до нужного экрана. на вашем сервере.
замена Branch, AppsFlyer OneLink и Firebase Dynamic Links: короткие ссылки, отложенный deep link, атрибуция установок и выручки. один Go-бинарник и PostgreSQL — данные не покидают вашу инфраструктуру.
01 {source}
откуда пришёл человек
кампания, блогер, реферал, QR на кассе. у каждого источника своя ссылка с UTM, кампанией и тегами. через месяц вы видите, кто привёл установки и покупки, а не только клики.
02 {path}
короткая ссылка, которая думает
свой домен или поддомен. правила по платформе, языку, стране, параметрам и времени, A/B без cookies. мессенджеры и боты получают OG-превью, десктоп — QR-код.
03 {bridge}
через стор — сразу в нужный экран
приложение стоит — Universal Link или App Link откроет его сразу. не стоит — человек идёт в App Store, Google Play или RuStore, а первый запуск ведёт в deep_link_path, а не на главную.
04 {signal}
узнать установку без IDFA
Install Referrer в Google Play и RuStore, токен в буфере обмена на iOS. вероятностный матчинг — только запасной путь, с весами и порогами на приложение. каждая попытка сопоставления пишется в журнал.
05 {event}
выручка, привязанная к ссылке
покупки и события из приложения с идемпотентностью и атрибуцией к последней ссылке. удержание D1/D7/D30, вебхуки с подписью в ваш бэкенд, фрод-флаги для дата-центров, ботов и всплесков.
→ {как это работает}
один клик, пять шагов, ноль потерянных контекстов
- linkклик записан, выдан подписанный токен
- лендингios: токен в буфер · android: referrer в ссылку стора
- сторapp store · google play · rustore
- первый запускsdk: referrer → буфер → фингерпринт → органика
- нужный экранonLink отдаёт path, payload и utm
→ {для разработчиков}
один init во Flutter, три строки в терминале
await DeepLinks.init(
baseUrl: 'https://sdk.spbse.online',
appKey: 'dl_pk_…',
linkDomains: ['go.example.com'],
);
DeepLinks.onLink.listen((link) => router.go(link.path!));
curl https://api.spbse.online/v1/links \
-H "Authorization: Bearer $DM_KEY" \
-d '{"app_id":"…","code":"spring","deep_link_path":"/item/7"}'
SDK — только Flutter. отдельных нативных SDK пока нет, и мы честно об этом пишем.
→ {AI-агенты · mcp}
спросите у Claude, откуда установки
встроенный MCP-сервер: Claude, ChatGPT и Cursor создают ссылки, читают аналитику и разбирают, почему установка сопоставилась именно так. ключ API или OAuth 2.1, права read и write, удаляющих инструментов нет, каждый вызов — в журнал аудита.
claude mcp add --transport http spbse \
https://api.spbse.online/mcp \
--header "Authorization: Bearer dl_sk_…"
> почему установка ушла в органику?
↳ explain_install · match_whatif
→ {приватность}
мы храним меньше, чем могли бы
- ∅ idfa / gaidрекламные идентификаторы не собираются, App Tracking Transparency не нужен
- ip → hmacсырой IP не пишется ни в базу, ни в логи — только HMAC-SHA256 с секретным перцем
- 72hфингерпринт клика обнуляется через 72 часа, остаются только агрегаты
- your postgresвсё лежит в вашей базе. никаких вендоров между вами и пользователями
06 {миграция с branch / appsflyer}
старые ссылки продолжают работать
переносите свой домен: ссылки Branch подтягиваются лениво при первом клике, выгрузка AppsFlyer OneLink импортируется целиком. QR-коды, рассылки и посты с прошлых лет не ломаются.
07 {манифест}
манифест
- 01данные остаются у вас
клики, установки и выручка — в вашей PostgreSQL. никто не учится на вашем трафике.
- 02точность важнее охвата
сначала детерминированные сигналы. вероятностный матч — последний, с порогом и объяснением.
- 03честно о границах
spbse — не MMP: нет SKAdNetwork, постбэков рекламным сетям и мультитач-атрибуции. ваш трафик — да, закупка — нет.
- 04один бинарник лучше десяти сервисов
Go и PostgreSQL. ни очередей, ни кешей, которые надо отдельно поднимать и мониторить.
- 05ссылка не должна умирать
Firebase Dynamic Links закрылись в 2025-м. ссылки на вашем домене переживут любого вендора, включая нас.
→ {контакт}
поставьте spbse рядом со своим бэкендом
покажем дашборд, поможем с доменом и переездом со старого вендора.