Перейти к содержимому

Город посетителя по адресу - определение, проверка, запасной вариант

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

Решение

Геолокация в платформе собрана за одним общим фасадом ядра. Он опрашивает настроенные обработчики по очереди, а прикладной код не знает, какой именно источник ответил.

Берём одно поле:

use Bitrix\Main\Service\GeoIp\Manager;
$city = Manager::getCityName(); // адрес текущего посетителя определяется сам
// на неудачу метод возвращает пустую строку, а не ошибку
// вторым аргументом задают язык названий, если он важен

Для одного значения вполне хватает короткого метода самого фасада. Пустая строка в ответе - штатная ситуация: адрес мог оказаться неизвестным источнику или посетитель пришёл через посредника.

Берём несколько полей сразу:

$result = Manager::getDataResult('92.50.195.50', 'ru',
['countryName', 'cityName', 'latitude', 'longitude']);
if ($result && $result->isSuccess()) {
$data = $result->getGeoData();
printf("%s, %s\n", $data->countryName, $data->cityName);
}
// результат бывает пустым: ни один обработчик не смог ответить

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

Передаём чужой адрес явно:

$result = Manager::getDataResult($order->getField('USER_IP'), 'ru', ['cityName']);
// в фоновом задании и при разборе вебхука текущего посетителя нет
// адрес заказа сохраняют при оформлении, чтобы разобрать его позже

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

Даём человеку выбрать город:

$suggested = Manager::getCityName();
$city = $request->getCookie('CITY_CODE') ?: mapCity($suggested) ?: 'msk';
// выбор посетителя всегда сильнее автоматического определения
// при неудачном определении подставляют город по умолчанию

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

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

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

Типичные проблемы

Все посетители определяются как один город.

Сайт стоит за прокси, и обработчик видит только адрес посредника. Реальный адрес посетителя возвращают отдельной настройкой веб-сервера.

Страница падает при обращении к данным геолокации.

Результат геолокации не проверен перед чтением его полей. Метод возвращает пустое значение, когда ни один источник так и не ответил.

В фоновом задании город определяется неверно.

Адрес не передан явно, и фасад берёт адрес из текущего запроса. У фонового задания текущего посетителя попросту нет.

Выбор города сбрасывается при каждом заходе.

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

Определение работает медленно.

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

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

Какой источник геолокации выбрать?

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

Насколько точно определяется город?

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

Можно ли по адресу подставлять цены и склады?

Только как предложение с явной возможностью сменить город. Молчаливая подмена цен по определению адреса приводит к спорам с покупателями.

Что делать, если источник не ответил?

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

Нужно ли кэшировать результат?

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

Смежное

Первоисточник