Appy
← Назад в блог
Гайд

Deferred deep linking без SDK: как это на самом деле устроено под капотом

Контекст ссылки можно пронести через установку приложения, не встраивая SDK атрибуции. Разбираем, что реально переживает границу стора на Android и iOS, что ломается и во что каждый обходной путь обходится приватности.

14 августа 2026•11 минут

Контекст умирает на границе стора

Человек нажимает ссылку на /product/42. Приложение не установлено, и редирект отправляет его в стор. Он устанавливает, открывает приложение и попадает на общий главный экран. HTTP-запрос, нёсший его намерение, закончился на странице стора: свежеустановленное приложение стартует без URL, без cookie, без referrer. От клика не осталось ничего.

Перенос этого контекста через установку — это deferred deep linking, и стандартный ответ — «встройте MMP SDK». Многие команды такой ответ не устраивает — тред 772811 на Apple Developer Forums лишь один из многих с вопросом, как сделать это без стороннего SDK, — а после того как в августе 2026 AppsFlyer убрал deferred deep linking из бесплатного плана, спрашивающих стало больше. Так можно ли собрать это самому? На Android — да, чисто и официально. На iOS — отчасти, через обходные пути с реальной ценой.

Замечание о рамках: что такое deferred deep linking и когда он окупается, мы разбираем в отдельной статье. Этот пост — только про сантехнику: какой транспорт способен протащить токен через установку и насколько каждому можно доверять.

Что переживает установку, а что нет

С install referrerОбычная ссылка в сторконтекст потерянТапТапСторСторУстановкаУстановкаПервый запускПервый запуск
Верхняя полоса: токен едет в параметре referrer Play через стор и выходит с другой стороны при первом запуске. Нижняя полоса: обычная ссылка в стор — контекст клика исчезает, как только загрузилась страница стора.

Android: Install Referrer API — честная хорошая новость

Google Play решает задачу нативно. URL стора принимает параметр referrer, Play сохраняет эту строку вместе с установкой, а приложение после первого запуска читает её дословно через Install Referrer API. Это весь механизм: без фингерпринтинга, без буфера обмена, без угадываний.

Строго говоря, это не «ноль кода»: чтение значения требует библиотеки com.android.installreferrer — маленького артефакта, который локально общается с приложением Play Store. Она не делает сетевых вызовов, не является аналитическим SDK, звонящим домой, и ничего не добавляет к вашим декларациям приватности, кроме того, что вы сами сделаете со строкой.

Что класть в параметр — решать вам: ID ссылки, кампанию, закодированную цель диплинка. Держите его коротким и URL-encoded — referrer в play.google.com/store/apps/details?id=com.example&referrer=tok_8f2 вернётся ровно таким, каким был отправлен.

Полный цикл, от начала до конца

  1. 1При тапе редирект добавляет referrer=<token> к URL Play; токен указывает на контекст клика, сохранённый на вашем сервере.
  2. 2При первом запуске приложение подключает InstallReferrerClient и читает строку installReferrer.
  3. 3Приложение обменивает токен в вашем API на сохранённый контекст — путь диплинка, кампанию — и маршрутизирует пользователя.
  4. 4Сервер помечает токен использованным. Строка referrer остаётся на устройстве, поэтому одноразовость должна обеспечиваться на сервере.

Ограничения узкие и предсказуемые: API покрывает только установки, реально прошедшие через Google Play. Sideload, Huawei AppGallery и другие сторы referrer Play не несут, а значение стоит прочитать один раз вскоре после первого запуска.

Ссылки Appy уже закрывают Android-половину

С сентября 2026 года каждая ссылка Appy, которая ведёт на страницу в Google Play, сама добавляет параметр referrer. Настраивать ничего не нужно, SDK добавлять тоже. В referrer всегда есть appy_slug — слаг ссылки, по которой нажали, поэтому приложение знает, какая ссылка принесла установку. Эта часть работает на всех тарифах, включая Free.

Если у ссылки включена передача параметров, в referrer попадает и query string из клика. QR-код, ведущий на appy.to/summer?screen=product-42&utm_source=poster, приходит в приложение при первом запуске в виде строки ниже. Для этого мы ничего не храним у себя и ничего не сопоставляем наугад.

Отсканировали или нажали
https://appy.to/summer?screen=product-42&utm_source=poster
Ушло в Google Play
https://play.google.com/store/apps/details?id=com.example.app&referrer=appy_slug%3Dsummer%26screen%3Dproduct-42%26utm_source%3Dposter&screen=product-42&utm_source=poster
Приложение читает при первом запуске
appy_slug=summer&screen=product-42&utm_source=poster

Настройка в панели

Передача параметров включается отдельно для каждой ссылки на тарифе Business. При создании ссылки это переключатель «Включить передачу параметров», у существующей ссылки та же настройка называется «Передавать входящие параметры». Если она выключена, referrer по-прежнему содержит appy_slug, и больше ничего.

Несколько правил, которые стоит знать. То, что вы сами прописали в URL Play, важнее: если в назначении уже есть referrer=utm_source%3Dposter, Appy сохранит это значение и добавит рядом appy_slug. Сам appy_slug нельзя перезаписать из query string, так что одна ссылка не присвоит установки другой. А если переданные параметры раздуют referrer больше чем до 1 КБ, Appy их отбросит и оставит только слаг.

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

Как прочитать это в приложении

Подключите библиотеку Install Referrer, прочитайте значение один раз при первом запуске и разберите его как query string. Вот и вся клиентская часть:

implementation("com.android.installreferrer:installreferrer:2.2")
fun readAppyReferrer(context: Context, onResult: (Map<String, String>) -> Unit) {
    val client = InstallReferrerClient.newBuilder(context).build()
    client.startConnection(object : InstallReferrerStateListener {
        override fun onInstallReferrerSetupFinished(responseCode: Int) {
            val raw = if (responseCode == InstallReferrerClient.InstallReferrerResponse.OK) {
                runCatching { client.installReferrer.installReferrer }.getOrNull()
            } else null
            client.endConnection()
            val uri = Uri.parse("?" + raw.orEmpty())
            onResult(uri.queryParameterNames.associateWith { uri.getQueryParameter(it).orEmpty() })
        }

        override fun onInstallReferrerServiceDisconnected() = Unit
    })
}

readAppyReferrer(this) { params ->
    val slug = params["appy_slug"] ?: return@readAppyReferrer
    params["screen"]?.let { openScreen(it) }
    analytics.logInstallSource(slug, params["utm_source"])
}

Запускайте это только при первом запуске после установки и запоминайте, что уже сделали. Referrer остаётся на устройстве, и если читать его при каждом холодном старте, человека будет всё время уводить на один и тот же экран. Установки из AppGallery или из APK приходят без referrer, поэтому в таком случае просто откройте обычный главный экран.

iOS: официального аналога нет, три обходных пути по порядку

Apple не поставляет ничего похожего на Install Referrer. Страница App Store не проносит произвольные параметры через установку; всё ниже — обходные пути, построенные на этом отсутствии. От наименее плохого к самому нишевому:

Передача через буфер обмена

01 · средняя надёжность, за разрешением

Страница клика записывает короткий токен в буфер обмена — по нажатию кнопки, поскольку Safari требует жеста пользователя для копирования — и переадресует в App Store. При первом запуске приложение читает буфер, находит токен и обменивает его на сервере.

Подвох появился с iOS 16: чтение буфера вызывает системный запрос на вставку. Пользователь видит «Разрешить вставку из Safari?» на первом же экране приложения, установленного тридцать секунд назад, и многие отказывают. Отказ — тихая потеря: его не отличить от «токена не было». UIPasteboard.detectPatterns может проверить паттерн без запроса, но не прочитать значение. К тому же буфер могут перезаписать между тапом и запуском. Работает измеримо часто, но вторая сторона монеты хорошо видна.

Вероятностное сопоставление — если делать его честно

02 · догадка с оценкой, но никогда не гарантия

В момент клика сервер сохраняет короткую запись: какая ссылка, какая платформа, версия ОС из user agent, время и способ узнать сеть, из которой пришёл клик. При первом запуске приложение запрашивает недавний клик, похожий на клик с того же телефона в той же сети. Токен при этом не передаётся вовсе. Сопоставление — это догадка, и весь вопрос в том, признаётся ли она в этом.

Если делать его небрежно, дурная слава вполне заслужена: сырые IP-адреса хранятся днями, лучший кандидат выдаётся за стопроцентное совпадение, а незнакомец из того же офисного Wi-Fi может забрать чужой реферальный бонус. К тому же сигналы слабее, чем кажутся. iCloud Private Relay скрывает адреса, NAT мобильного оператора прячет много телефонов за одним адресом, Chrome на Android выдаёт любой телефон за Android 10, а Safari в iOS 26 замораживает версию на 18.6.

Если делать аккуратно, это всё равно догадка, но полезная. Оценивайте каждого кандидата и возвращайте оценку вместе с сигналами, из которых она сложилась. Не давайте догадке дотянуть до полной уверенности. Пусть порог выбирает приложение, а клик с оценкой ниже порога не расходуйте, чтобы телефон, с которого действительно кликнули, ещё мог его получить. Держите окно коротким и не храните IP-адреса. SDK Appy для Enterprise оставляет всё это на стороне Appy. Приложение получает либо ссылку, либо ничего, ваш бэкенд может проверить, подтверждена ли установка, а сети распознаются по хешу адреса с ключом, который меняется каждый день и живёт два часа. При включённой строгой атрибуции учитываются только подтверждённые установки, а всё остальное считается органическим.

App Clips и другие нишевые пути

03 · надёжно, но узко

App Clip, вызванный по вашей ссылке, получает полный URL и после установки может передать контекст полному приложению через общий контейнер. В своей нише это самый надёжный путь на iOS — но он требует построить и поддерживать App Clip и подходит только там, где лёгкий мгновенный сценарий имеет смысл. Shared web credentials решают смежную задачу — непрерывность авторизации, а не общий контекст ссылки. Знать полезно, ответом бывает редко.

Паттерн проектирования, который работает при любом механизме

Какой бы транспорт ни нёс токен — строка referrer, буфер обмена или даже ID вероятностного совпадения — серверная архитектура одна и та же, и сделать её правильно важнее выбора транспорта. Не запихивайте весь диплинк в канал: храните контекст клика на сервере и передавайте только короткоживущий ключ.

01

Храните контекст под случайным токеном

При клике запишите {deep_link, кампания, метка времени} под коротким случайным токеном и положите в транспорт только токен. Полезная нагрузка мала, данные кампаний не оседают в буферах и логах, а смысл «контекста» можно менять, не трогая клиент.

02

Агрессивно истекайте

TTL в 30–60 минут покрывает реальный путь от тапа до установки. Отложенный маршрут, разрешённый через неделю после клика, чаще ошибается, чем попадает.

03

Обеспечьте одноразовость

Погашайте токен при первом обмене. Строки referrer сохраняются на устройстве, буфер можно прочитать дважды; без одноразовости переустановка или второе устройство воспроизведёт чужой контекст.

04

Падайте в значение по умолчанию, а не в догадку

Нет токена, токен истёк, запрос на вставку отклонён — ведите пользователя на обычный главный экран. Обычный первый запуск слегка разочаровывает; попадание в чужую корзину — это тикет в поддержку.

Надёжность, сказанная честно

Грубые цифры от команд, эксплуатирующих эти механизмы в проде. Ваш микс источников, задержка установки и версия iOS аудитории сдвигают каждое число.

МеханизмПлатформаНадёжностьПримечания
Play Install ReferrerAndroidВысокаяОфициальный API, переживает отложенные установки, без запросов пользователю. Только установки из Play.
Токен в буфере обменаiOSСредняяУпирается в запрос вставки iOS 16+; отказы бесшумны; буфер волатилен.
Вероятностное сопоставление с оценкойiOS, Android без referrerСредняя, с оценкойТа же сеть, версия ОС и время. Хорошо работает в том же Wi-Fi через несколько минут после тапа, слабо — при смене сети, за CGNAT и Private Relay. Имеет смысл только с видимой оценкой и порогом.
Передача через App ClipiOSВысокая, узкаяДетерминированно, но только для сценариев, оправдывающих App Clip.

Что это значит для вашего стека

Если отложенная маршрутизация нужна только на Android, вам нужно совсем немного: ссылка, добавляющая параметр referrer, маленькая библиотека и один endpoint обмена токенов. Это полдня работы, и это по-настоящему без SDK в том смысле, который важен: никакой сторонний код не наблюдает за вашими пользователями.

Именно на iOS готовые решения оправдывают свою цену, потому что там обходные пути и есть продукт: инфраструктура сопоставления, модель оценки, которую кто-то должен держать честной, и каждый релиз ОС, который выбивает почву из-под ног, — как iOS 26 с замороженной версией Safari. Поэтому SDK Appy для iOS и Android с отложенными диплинками и атрибуцией установок входит в тариф Enterprise, а Android-referrer работает с каждой ссылкой.

Но будьте честны, какая у вас задача. Если на деле нужно, чтобы «пользователи с уже установленным приложением попадали на нужный экран», это стандартный deep linking — границы установки нет. Диплинк-прослойка Appy закрывает этот случай на плане Pro за $9,99 в месяц: без приложения человек попадает в стор, и SDK по-прежнему не нужен. Прежде чем покупать тяжёлую машинерию, измерьте, какая доля воронки — действительно свежая установка с контекстом.

Что почитать дальше

Частые вопросы

Работает ли Install Referrer при сканировании QR?

Да, если QR разрешается через ссылку, добавляющую параметр referrer к URL Play. Механизму всё равно, как начался клик — скан, тап или NFC — важно лишь, что URL стора нёс referrer в момент открытия Play. QR, указывающий на голый URL Play, не несёт ничего.

Почему мой подход с токеном в буфере внезапно сломался?

Почти наверняка запрос вставки iOS. С iOS 16 первое чтение буфера вызывает системный диалог разрешения, и заметная доля пользователей отказывает. Ваш код не деградировал; в вашем чтении теперь участвует человек. Проверьте, снизилась ли доля найденных токенов, а не упала ли в ноль — это и есть почерк проблемы.

Разрешено ли вероятностное сопоставление на iOS?

Соглашение Apple для разработчиков запрещает извлекать из устройства данные, чтобы однозначно его идентифицировать, и App Review может отклонить приложения, чьи SDK так делают. Отпечаток, по которому телефон узнают в разных приложениях и неделями, — явно за этой чертой. Сравнить один клик с одним первым запуском в той же сети в пределах двух часов — для вашей собственной ссылки, без хранения IP и с оценкой — задача гораздо более узкая, но эти данные всё равно нужно указать в сведениях о конфиденциальности. Каким бы инструментом вы ни пользовались, спросите, что он хранит, как долго и говорит ли он, когда угадывает.

Нужен ли мне deferred deep linking вообще?

Только если экран после установки заметно меняет вашу воронку. Если большинство установок приходит из общих кампаний без конкретной цели, хороший онбординг даст больше, чем отложенный маршрут. Сначала измерьте: посчитайте клики, где была реальная цель диплинка и приложение не было установлено. Если число мало — потратьте усилия на другое.

Продолжить изучение

Продукт
1 окт. 2026 г.
8 мин чтения

Узнайте, какая ссылка принесла каждую установку: SDK Appy для iOS и Android

Appy теперь видит, что происходит с вашими ссылками после стора. Новый SDK показывает установки, события в приложении и выручку по каждой ссылке, QR-коду и кампании и открывает новым пользователям нужный экран.

install attribution
deferred deep linking
install referrer
mobile attribution
Читать статью
Гайд
1 окт. 2026 г.
7 мин чтения

Chrome сообщает каждому серверу, что ваш телефон работает на Android 10

Chrome на Android выдаёт любой телефон за Android 10, модель K. Что это сломало в сопоставлении отложенных диплинков, почему Critical-CH посчитал бы каждый клик дважды и как Client Hints возвращают настоящие версию и модель.

android
user agent
client hints
deferred deep linking
Читать статью
Гайд
14 мая 2026 г.
9 мин чтения

Deferred deep linking: как это работает и когда применять

Переносите исходный intent ссылки через установку, чтобы новые пользователи попадали сразу на нужный экран, а не на дефолтную главную.

deferred deep linking
install referrer
deep linking
mobile attribution
Читать статью

Ищете другое? Посмотрите все темы в блоге.

Маршрутизируйте установки, которые уже заработали

Install referrer Google Play в каждой ссылке и диплинки на Pro, которые ведут в стор, если приложения нет, — и всё это без SDK в вашем приложении. А когда нужны отложенные диплинки и атрибуция установок на iOS и Android, SDK для Enterprise связывает каждую установку со ссылкой, которая её принесла.

Начать с Appy