Внедрение геолокации в интернет-магазин на Битриксе — задача, с которой сталкивается каждый ритейлер с собственной сетью офлайн-точек. Мы настраивали такой функционал для сетей с числом магазинов от 5 до 150. В этой статье - готовое решение: как заставить ваш Битрикс показывать покупателю ближайший магазин с актуальными остатками.
Проблема типична: пользователь заходит на сайт, видит товар, но не знает, есть ли он в магазине рядом. Он начинает искать адреса, звонить, теряет время. Наша интеграция решает это за секунды: доступ к геолокации, запрос к серверу, отображение ближайшей точки и остатков. Экономия времени пользователя — до 40%, конверсия в офлайн-визиты растёт на 15–25%.
Хранение адресов магазинов
В Битриксе магазины (склады/торговые точки) хранятся в таблице b_catalog_store (модуль catalog). У каждого склада есть поля: TITLE, ADDRESS, PHONE, SCHEDULE, GPS_N (широта), GPS_S (долгота), ACTIVE. Если поля GPS_N/GPS_S не заполнены — нужно геокодировать адреса (через API Яндекса или Google) и сохранить координаты. Для сети из 50 магазинов это занимает около 2 часов — один раз и навсегда.
Добавить координаты магазину программно:
\Bitrix\Catalog\StoreTable::update($storeId, [ 'GPS_N' => 53.9045, // широта 'GPS_S' => 27.5615, // долгота ]); Как работает определение ближайшего магазина?
Формула Haversine — стандарт для вычисления расстояния между двумя точками на сфере. Мы используем либо прямой SQL-запрос с сортировкой, либо PHP-реализацию через ORM. Первый подход быстрее для баз с 50+ магазинами (работает за 0.001 с), второй — гибче для интеграции с компонентами Битрикса. Ниже оба варианта.
SQL-запрос с сортировкой по расстоянию (MySQL/PostgreSQL):
SELECT id, title, address, gps_n, gps_s, (6371 * acos( cos(radians(:lat)) * cos(radians(gps_n)) * cos(radians(gps_s) - radians(:lng)) + sin(radians(:lat)) * sin(radians(gps_n)) )) AS distance FROM b_catalog_store WHERE active = 'Y' AND gps_n IS NOT NULL ORDER BY distance ASC LIMIT 5; PHP-реализация через ORM Битрикса (без прямого SQL):
function haversineDistance( float $lat1, float $lon1, float $lat2, float $lon2 ): float { $R = 6371; // км $dLat = deg2rad($lat2 - $lat1); $dLon = deg2rad($lon2 - $lon1); $a = sin($dLat/2)**2 + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * sin($dLon/2)**2; return $R * 2 * atan2(sqrt($a), sqrt(1-$a)); } $stores = \Bitrix\Catalog\StoreTable::getList([ 'filter' => ['=ACTIVE' => 'Y', '!=GPS_N' => false], 'select' => ['ID', 'TITLE', 'ADDRESS', 'GPS_N', 'GPS_S', 'SCHEDULE', 'PHONE'], ])->fetchAll(); usort($stores, function($a, $b) use ($userLat, $userLng) { $dA = haversineDistance($userLat, $userLng, $a['GPS_N'], $a['GPS_S']); $dB = haversineDistance($userLat, $userLng, $b['GPS_N'], $b['GPS_S']); return $dA <=> $dB; }); $nearest = array_slice($stores, 0, 3); Что выбрать: SQL или PHP?
| Критерий | SQL-запрос | PHP-сортировка |
|---|---|---|
| Скорость (50 магазинов) | 0.001 с | 0.01 с |
| Зависимость от БД | Только MySQL/PostgreSQL | Любая (ORM) |
| Гибкость настройки | Низкая (фиксированный запрос) | Высокая (можно фильтровать любые поля) |
| Поддержка кэширования | Через тегированный кэш Битрикса | Через тегированный кэш Битрикса |
Для проектов с большим каталогом (50+ магазинов) SQL-решение даёт выигрыш в скорости в 10 раз — разница заметна на мобильных устройствах. Если нужна дополнительная фильтрация (например, по типу магазина или режиму работы), используйте PHP.
AJAX-эндпоинт для фронтенда
// /local/ajax/nearest-store.php $lat = (float)$_POST['lat']; $lng = (float)$_POST['lng']; // ... выборка и сортировка ... header('Content-Type: application/json'); echo json_encode([ 'nearest' => [ 'id' => $nearest[0]['ID'], 'title' => $nearest[0]['TITLE'], 'address' => $nearest[0]['ADDRESS'], 'distance' => round($dist, 1), 'schedule' => $nearest[0]['SCHEDULE'], 'phone' => $nearest[0]['PHONE'], ], ]); Показ остатков в ближайшем магазине
После определения магазина можно показывать остатки товара в этой точке прямо в карточке товара. Данные из b_catalog_store_product:
$stock = \Bitrix\Catalog\StoreProductTable::getList([ 'filter' => [ '=PRODUCT_ID' => $productId, '=STORE_ID' => $nearestStoreId, ], 'select' => ['AMOUNT'], ])->fetch(); $inStock = $stock && $stock['AMOUNT'] > 0; UI и UX
Типичный интерфейс: всплывающий блок в шапке «Ближайший магазин: [Название], [расстояние] км» или виджет на странице товара «Наличие в магазинах». Кнопка «Определить» запускает запрос геолокации. Если пользователь отказал в доступе — показываете список магазинов с поиском по адресу. Для полноценной карты — подключаете Яндекс.Карты JS API или Google Maps API и расставляете метки всех точек.
Дополнительно: можно реализовать автоматическое определение магазина по IP (через сервис Sypex Geo) — это работает, если пользователь не дал доступ к геолокации. Погрешность — до 50 км, но для крупных городов этого достаточно.
Этапы внедрения
- Аудит текущих складов — проверить заполнение GPS-координат.
- Геокодирование — автоматическое определение координат для магазинов без GPS_N/GPS_S.
- Создание AJAX-эндпоинта — выборка ближайших магазинов с остатками.
- Разработка виджета — блок на странице товара или в шапке.
- Интеграция с картой (опционально) — Яндекс.Карты или Google Maps.
- Тестирование и кэширование — настройка тегированного кэша для быстрой работы.
- Документация и передача — подробное описание API и настроек.
Как получить координаты, если GPS_N/GPS_S не заполнены?
Используйте API геокодирования Яндекса (бесплатно 25 000 запросов/сутки) или Google Maps Geocoding API. Для Битрикса можно написать агент, который раз в день заполняет координаты пустых складов. Пример запроса: https://geocode-maps.yandex.ru/1.x/?geocode=Москва,ул.Тверская,1&format=json. Полученные координаты сохраните через \Bitrix\Catalog\StoreTable::update().
Что входит в работу
| Этап | Результат |
|---|---|
| Геокодирование и заполнение координат | Все магазины с координатами в БД |
| AJAX-эндпоинт для определения ближайшего | API-метод с сортировкой и кэшированием |
| Виджет "ближайший магазин" | Готовый блок для шапки/карточки товара |
| Вывод остатков по ближайшему складу | Отображение наличия в выбранном магазине |
| Интеграция с картой (опционально) | Интерактивная карта с метками |
| Документация и обучение | PDF-инструкция + консультация |
Стоимость рассчитывается индивидуально после анализа проекта. Экономия бюджета на разработке с нуля — до 60%. Сроки — от 3 дней до 2 недель в зависимости от сложности интеграции (наличие 1С, количество точек). Свяжитесь с нами для консультации — оценим ваш проект за один рабочий день. Получите готовое решение с гарантией совместимости с 1С и Маркетплейсом.







