ГдеЯ? geo-сниппеты для России и мира

3 мин. чтения

Давайте зайдём на сайт Министерства иностранных дел.

Скриншот сайта сделан 22.03.2025

На странице такой серьёзной организации размещены значки некоторых организаций, признанных в России экстремистскими. Чтобы не травмировать вашу психику, я применил к ним эффект стекла (а заодно и к некоторым другим, потому что не знаю, в каком году вы открыли эту статью).

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

И вот как быть серьёзной организации, которая работает не только для России? Помимо нашей страны есть и другие, в которых тоже есть интернет. И там свои варианты дозволенного.

Самый известный пример — GDPR (General Data Protection Regulation), регламент Евросоюза о защите персональных данных. Если ваш сайт посещает пользователь из ЕС, вы обязаны спросить у него разрешение на сбор cookies и объяснить, зачем они нужны. Именно поэтому при первом заходе на европейские сайты вас встречает баннер «Мы используем cookies» — это не прихоть дизайнера, а юридическое требование. Чтобы показывать этот баннер только нужным людям (и не раздражать им всех остальных), сайты и используют геотаргетинг: определяют страну посетителя по IP-адресу и уже тогда решают, что ему показать.

Та же задача встала передо мной, когда я делал промо-страницу для своего приложения ScreenLines. Приложение доступно в App Store, а там пользователи со всего мира. На странице я предлагал промокод на премиум-подписку в обмен на видео: нужно было снять, как клеишь защитное стекло на телефон, и выложить в соцсети. Но в какие именно? ВКонтакте понятен российской аудитории и бесполезен для иностранца. Instagram (принадлежит компании Meta, признанной экстремистской организацией и запрещённой в РФ) и X (Twitter) — наоборот, привычны на Западе, но в России заблокированы. Вот тут и пригодился геотаргетинг. Для посетителей из России — одно предложение, для всех остальных — другое.

Первый подход: цепочка сторонних сервисов

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

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

Но главная проблема обнаружилась позже. В России на мобильном интернете действуют белые списки: без ограничений открываются только одобренные ресурсы, особенно хорошо работает виртуальный хостинг — провайдеры этот вопрос решают. А вот обращение к зарубежному геосервису, например ipinfo.io, попадает под шейпинг — это когда доступ не заблокирован, но скорость намеренно урезана до минимума. Нам нужно получить буквально несколько байт с геоданными, но из-за шейпинга даже этот крошечный запрос может тянуться секунды.

Второй подход: свой сервис

Я решил сделать иначе. Если вы когда-то настраивали хостинг, то могли видеть галочку «доступ к сайту только из РФ». На мой взгляд, абсурднейший флажок — особенно сейчас, когда люди запросто «оказываются в другой стране», как только просыпаются. Но именно эта механика мне и нужна.

Идея: разместить на своём хостинге специальный адрес /geo/ru и закрыть к нему доступ для российских IP. Дальше всё просто: скрипт на странице делает один HEAD-запрос на этот адрес — он не скачивает никакого содержимого, только получает код ответа сервера. Если пришёл 403 (или любая другая ошибка) — значит, доступ закрыт, пользователь в России. Если 200 — пользователь за рубежом.

CDN — российский, запрос к нему не шейпится, ответ приходит мгновенно. Никаких цепочек, никаких зависимостей от сторонних сервисов.

Так появился ГдеЯ — инструмент с открытым исходным кодом, который доступен на GitHub. Можно использовать мой сервис или развернуть собственный.

Как этим пользоваться

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

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

При загрузке страницы скрипт определяет местоположение пользователя по одному HEAD-запросу. За пределами России — показывается международный вариант. В остальных случаях (ошибка, таймаут, Россия) — российский.

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

<span
  data-gdeya-ru="t9G08LCjEOKFt9C1zEzjsuKIR7Taqd8S4I/m37TfqOISUUBCAgkHFg1dRF1A"
  data-gdeya-intl="t9ZDFwNBQAkKBkQNCwRUDRBeExAVClsdH1tYFBAEHhNTXRxVCAlKGBNGVV9UCAgKDQ5EEgzm37TYqODjsuKGt9e0+bGC4I7m0lhKGF8=">
</span>

А вот пункт списка со ссылками на соцсети. Обратите внимание: data-gdeya-ru пустой — для российских пользователей этот элемент просто не появится:

<li
  data-gdeya-ru=""
  data-gdeya-intl="R0RFWUESEBIKBkQGFQBBQw8UDgcKF0MS...">
</li>

Содержимое закодировано — в исходном коде страницы его не прочитать. Это важно, если вы, например, прячете иконки заблокированных в России соцсетей: они не присутствуют в HTML явно, а раскодируются и подставляются скриптом уже в браузере.

Кстати, МИД тоже мог бы воспользоваться ГдеЯ. Показывать российским пользователям одно, иностранным — другое. Но, видимо, пока не в курсе.