16 февр. 2025 г.·8 мин чтения

Обработка deep link, которая сохраняет пользователя в нужном состоянии

Обработка deep link ломается, когда авторизация, просроченные страницы и проверки версии прерывают путь. Продумайте маршруты, которые возвращают каждого пользователя на нужный экран.

Обработка deep link, которая сохраняет пользователя в нужном состоянии

Почему пользователи оказываются не на том экране

Ссылка из email или рекламы почти никогда не открывает приложение в чистом, предсказуемом состоянии. Человек может уже держать приложение открытым, а может сначала войти в аккаунт. Он может нажать на ссылку в старой версии приложения, а предложение по ссылке уже могло исчезнуть. Один URL может попадать в несколько разных реальностей.

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

Именно так люди и оказываются не на том экране. Пользователь нажимает скидку в email и попадает на вкладку с главной. Другой нажимает рекламу конкретного товара, входит в аккаунт и видит общий дашборд вместо этого товара. Еще кто-то вынужден обновить приложение, открывает его снова и полностью теряет исходную цель. Это кажется случайностью. Хуже того, это ощущается как поломка, даже когда приложение делает именно то, что ему сказали в коде.

Плохая обработка deep link обычно начинается с одной простой ошибки: команда воспринимает ссылку как конечную точку, а не как запрос, который должен пережить все проверки состояния. Перед тем как показать нужную страницу, приложение задает несколько вопросов. Этот человек уже вошел в аккаунт? Этот контент еще существует? Может ли эта версия приложения его открыть? Если каждая проверка ведет в свое место, исходное намерение теряется.

Четкий поток исправляет не одну проблему. Он дает каждому входящему deep link один маршрут с правилами для входа, отсутствующего контента и проверки версии в одном и том же порядке каждый раз. Это менее эффектно, чем набор особых случаев, и обычно гораздо надежнее. Когда приложение помнит, куда именно человек хотел попасть, опыт перестает зависеть от удачи.

Состояния, которые нужно учитывать для каждой входящей ссылки

Обработка deep link начинается с простого правила: ссылка указывает на намерение, а не всегда на экран. Прежде чем приложение откроет хоть что-то, оно должно проверить состояние пользователя, состояние контента и состояние приложения.

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

Хороший поток обычно учитывает пять случаев:

  • Пользователь уже вошел в аккаунт и имеет доступ. Откройте нужный экран сразу.
  • Пользователь не вошел в аккаунт. Отправьте его на вход, а затем верните ровно на ту же цель с теми же параметрами.
  • У пользователя нет приложения. Предложите правильный запасной вариант: установку, открытие в браузере или страницу, которая сохраняет тот же смысл.
  • Контент изменился. Если он истек, был перемещен, удален или теперь требует особого доступа, покажите понятное сообщение и полезный запасной вариант.
  • Версия приложения слишком старая. Не открывайте экран, если он небезопасно не загрузится, попросите обновить приложение, а затем повторите попытку открытия той же цели.

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

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

Просроченный контент нуждается в настоящем запасном варианте, а не в тупике. Если акция закончилась, отправьте людей на текущую страницу предложения. Если товар удалили, отправьте их в родительскую категорию или на результат поиска, который соответствует исходному намерению.

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

Постройте один путь принятия решений для каждой ссылки

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

Начинайте с цели и ожидаемого результата. Не начинайте с канала. Email, реклама, QR-коды и push-кампании должны вести в один и тот же обработчик, потому что проблема у пользователя одна: «Покажите мне именно это место и сохраните достаточно контекста, чтобы я мог им воспользоваться».

Простой порядок делает поток предсказуемым:

  1. Прочитайте и проверьте цель.
  2. Проверьте, установлен ли app или должен ли открыться web-fallback.
  3. Проверьте, нужно ли пользователю войти в аккаунт.
  4. Проверьте, существует ли контент и может ли пользователь к нему получить доступ.
  5. Проверьте, может ли текущая версия приложения обработать эту цель.

Порядок важен. Если сначала запросить вход в аккаунт, а потом сохранить цель, многие пользователи так и не вернутся назад. Если проверить версию слишком рано, можно отправить человека обновляться, не запомнив, зачем он пришел.

Сохраняйте исходную цель до любого редиректа. Храните полный адрес назначения и минимальный контекст, который нужен для восстановления: ID контента, параметры кампании и любые флаги режима. Держите эту запись через экраны установки, входа, согласий и обновления.

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

Раздельная логика для ссылок из email и рекламы сначала кажется безобидной. Обычно она быстро расходится. Одна команда добавляет новую проверку авторизации, другая меняет запасной вариант, и одна и та же цель ведет себя по-разному в зависимости от того, откуда пользователь кликнул.

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

Обрабатывайте вход в аккаунт, не теряя целевой экран

Первое нажатие считайте намерением пользователя, а не доказательством доступа. Когда приложение открывается из email или рекламы, сразу прочитайте всю ссылку и сохраните цель до начала любой проверки авторизации. Хорошая обработка deep link зависит именно от этого первого шага.

Не сохраняйте только название экрана. Сохраните полное состояние, которое запросил пользователь:

  • маршрут или экран
  • ID или slug элемента
  • фильтры, сортировку и выбранную вкладку
  • любой токен, который нужен для безопасного завершения запроса

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

Простой пример показывает, почему это важно. Пользователь нажимает в email предложение для списка товаров, отфильтрованного по черным ботинкам 9-го размера. После входа в аккаунт он должен попасть на тот же самый отфильтрованный список, а не на главный экран, не в профиль и не на общий поиск.

Истечение сессии требует той же аккуратности. Если пользователь уже находится в приложении и сессия закончилась, держите путь коротким. Попросите войти снова, а затем верните его на тот же экран, который он использовал. Не отправляйте его через полный стартовый сценарий приложения, если только у вас нет другого выхода.

Проверки доступа все равно важны после входа. Пользователь может успешно войти в аккаунт и при этом не иметь права открыть контент. В таком случае не перебрасывайте его между экранами и не подменяйте содержимое чем-то другим молча. Покажите простое сообщение вроде «Этот контент недоступен для этого аккаунта», а затем предложите одно понятное действие, например «Назад» или «Сменить аккаунт».

Когда этот поток работает, пользователи почти его не замечают. Они нажимают, входят в аккаунт и продолжают там, куда и хотели попасть.

Разбирайтесь с просроченным или отсутствующим контентом

Сделайте мобильные сценарии лучше
Используйте советы Олега по CTO, чтобы сделать правила маршрутизации проще для проверки и поддержки.

Просроченный контент — это нормально. Товары заканчиваются, промоакции завершаются, посты удаляются, а рекламные кампании часто продолжают жить дольше, чем планировалось. Хорошая обработка deep link проверяет, существует ли цель, прежде чем приложение откроет экран назначения.

Эта проверка должна происходить рано. Если элемента уже нет, не загружайте полупустую страницу в надежде, что пользователь сам догадается. Вместо этого покажите понятный запасной вариант.

Лучше всего работает короткое сообщение. Одного предложения достаточно: «Это предложение уже закончилось» или «Эта страница больше недоступна». Пользователю не нужно длинное объяснение. Ему нужно понять, что произошло, и что он может сделать дальше.

Выбирайте ближайший полезный запасной вариант

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

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

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

Отслеживайте просроченные ссылки отдельно от битых ссылок. Это не одна и та же проблема. Просроченная ссылка означает, что URL был корректным, но контент исчез по сроку или по задумке. Битая ссылка означает, что что-то сломалось: неверный ID, неверный маршрут или неверный редирект.

Такое разделение помогает командам чинить именно то, что нужно. Маркетинг может пересмотреть завершившиеся кампании. Продукт или инженерная команда может исправить сломанные потоки.

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

Проверяйте версию приложения, не ломая путь

Проверка версии должна быть точечной. Если ссылка открывает экран, который старые сборки все еще могут показать, пропускайте пользователя. Останавливайте поток только тогда, когда цель зависит от кода, интерфейса или правил безопасности, которых в установленном приложении нет.

Это звучит очевидно, но многие команды ставят перед каждой маркетинговой ссылкой полноценную стену обновления приложения. Это просто тратит клики. Если email ведет на страницу товара, которую старые версии умеют открывать, отправляйте пользователя туда. Если та же кампания использует еще и новый сценарий оформления заказа, ограничьте только эту часть.

Блокируйте только там, где это действительно нужно

Считайте проверку версии проверкой возможностей, а не универсальным правилом. Промоссылке на новый кошелек вознаграждений может потребоваться версия 6.2. Простая страница контента из того же email может нормально работать и на 6.0, если это более легкий макет.

В обработке deep link сохраняйте цель до того, как отправите кого-то в app store. Делайте это сразу, как только приложение прочитает ссылку.

  • Сохраните маршрут и ID контента
  • Сохраните параметры кампании или реферальные параметры
  • Сохраните минимальную версию, которая нужна этому маршруту
  • Сохраните короткое время жизни для ожидающей цели

Если приложение закроется во время обновления, вы все равно будете знать, куда именно пользователь хотел попасть.

Сделайте возврат надежным

После обновления приложение должно при запуске проверить наличие ожидающей цели и сразу вернуть пользователя к ней. Не отправляйте его сначала на главный экран. Люди воспринимают это как сломанную ссылку, даже если приложение обновилось правильно.

На некоторых устройствах переход в store работает нестабильно. Иногда магазин снова открывает приложение. Иногда пользователи сами нажимают на иконку через 10 минут. Планируйте оба варианта. Сохраняйте ожидаемую цель на разумный срок, а затем показывайте понятный призыв продолжить, например «Перейти к вашему предложению», если автоматический возврат не сработал.

Вам также нужен запасной вариант на случай, если исходный контент больше не подходит. Если рекламная кампания закончилась во время обновления, отправьте пользователя на ближайшую валидную страницу и объясните это одной короткой фразой. Обычно достаточно страницы похожего товара или активного экрана с промо.

Старые версии не должны терять доступ к контенту, который они все еще могут открыть. Это правило сильно снижает трение, особенно для ссылок из email и рекламы, где каждый лишний шаг отнимает внимание.

Промоссылка из email от начала до конца

Проверьте свой поток ссылок
Получите практическую проверку путей входа, обновления и запасных сценариев до релиза.

Хороший тест для обработки deep link — промоemail, открытый на телефоне со старой версией приложения. Человек нажимает на предложение для конкретного товара и ожидает увидеть именно это предложение, а не пустой экран, не дашборд и не общий главный экран.

Приложение должно сначала прочитать ссылку и сохранить цель до того, как проверит что-либо еще. Сохраненная цель может быть простой: ID товара, ID кампании и несколько безопасных значений, например код купона или тег источника. Как только эта цель надежно сохранена в локальном хранилище, приложение может проверить версию.

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

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

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

Сломанная версия этого потока обычно выглядит так:

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

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

Ошибки, которые ломают сценарии ссылок

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

Хорошая обработка deep link начинается с одного правила: сохраняйте намерение при первом касании. Это значит — цель, ID контента и все важные параметры кампании. Если человек нажал промоссылку в email на скидочный тариф, приложение должно помнить об этом и после входа, и после обновления, и после холодного запуска.

Еще один простой способ сломать поток — потерять данные кампании во время авторизации. Команды часто сохраняют цель, но теряют значения отслеживания, прикрепленные к ссылке. Пользователь все еще попадает на страницу, но атрибуция неверна, промо может не примениться, а поддержка получает расплывчатую жалобу вроде «предложение исчезло после входа».

Отправлять все случаи сбоя на главный экран — тоже ленивое решение, и пользователи это сразу чувствуют. Просроченный контент, удаленный контент, отозванный доступ и неверно сформированная ссылка — это разные проблемы. У них не должен быть один и тот же финал. Если документ истек, скажите об этом и предложите ближайшее полезное действие. Если доступ отозван, покажите это прямо. Главный экран скрывает причину и заставляет людей думать, что приложение их просто проигнорировало.

Разные правила для iOS, Android и web создают еще больший хаос. Если на web цель сохраняется после входа, а на мобильных устройствах теряется, продукт выглядит ненадежным. Одна спецификация маршрутизации должна описывать одни и те же состояния и запасные варианты везде. Код платформ может различаться. Путь принятия решений — нет.

Короткая проверка ловит большую часть таких проблем:

  • откройте ссылку, будучи не в аккаунте
  • откройте ту же ссылку на старой версии приложения
  • откройте контент, срок которого истек
  • откройте контент после того, как доступ был удален
  • убедитесь, что данные кампании переживают весь путь

Команды пропускают эти случаи, потому что happy path работает. Обычно именно там и начинаются проблемы. Если ссылка может прийти из email или рекламы, тестируйте ее как реальный пользователь: на неправильной версии, в неправильной сессии, в неправильное время.

Короткий чек-лист перед релизом

Исправьте потерянные целевые страницы
Сохраняйте пользователя на том маршруте, по которому он перешел, даже после входа или обновления приложения.

Чек-лист перед релизом должен ловить ошибки состояния раньше, чем это сделают пользователи. Обработка deep link часто выглядит нормально на демо, а потом ломается, когда реальный пользователь открывает старый email, нажимает рекламу на медленном телефоне или попадает в приложение после запроса на обновление.

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

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

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

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

Когда этот чек-лист проходит, обработка deep link обычно становится незаметной для пользователей. В этом и есть цель.

Что делать дальше

Большинство ошибок со ссылками начинаются не в коде. Они начинаются тогда, когда никто не согласовал порядок проверок, запасные экраны и точный текст, который увидит пользователь, если что-то пойдет не так.

Опишите на одной странице путь принятия решений для каждой входящей ссылки. Оставьте порядок неизменным: состояние установки, состояние входа, состояние контента, затем версия приложения. Если две команды описывают этот порядок по-разному, пользователи почувствуют это сразу.

Достаточно короткого чек-листа:

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

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

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

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

Если вашей команде нужен второй взгляд, Oleg Sotnikov может провести разбор обработки deep link в рамках работы Fractional CTO или консультаций для стартапов. Такой разбор часто касается не столько кода, сколько устранения маленьких разрывов между командами, из-за которых в продакшене появляется не то состояние.