Впровадження геолокації в інтернет-магазин на Бітріксі — задача, з якою стикається кожен рітейлер з власною мережею офлайн-точок. Ми налаштовували такий функціонал для мереж з числом магазинів від 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С та Маркетплейсом.







