1C-Bitrix Integration with Yandex Maps
The contacts page shows a static map image instead of an interactive one. The delivery section provides no way to select a zone. Managers cannot see orders on a map by district. Yandex Maps API v3 covers all of these use cases, but integration requires careful handling of API keys and server-side geofencing logic.
Yandex Maps API: versions and keys
The current version is JavaScript API 3.0 (jsapi v3). Version 2.1 is deprecated and Yandex will discontinue support. An API key is required from the Yandex Developer Console (developer.tech.yandex.ru). The key is bound to a domain. Store it in COption::GetOptionString('site', 'ymaps_api_key').
Basic map initialization
<!-- In the component template -->
<div id="ymap-container" style="width:100%;height:400px"></div>
<script src="https://api-maps.yandex.ru/v3/?apikey=<?= COption::GetOptionString('site', 'ymaps_api_key') ?>&lang=ru_RU"></script>
<script>
ymaps3.ready.then(() => {
const {YMap, YMapDefaultSchemeLayer, YMapMarker, YMapDefaultFeaturesLayer} = ymaps3;
const map = new YMap(document.getElementById('ymap-container'), {
location: { center: [37.617644, 55.755819], zoom: 10 }
});
map.addChild(new YMapDefaultSchemeLayer());
map.addChild(new YMapDefaultFeaturesLayer());
// Marker from infoblock settings
const marker = new YMapMarker({coordinates: [<?= $lon ?>, <?= $lat ?>]});
map.addChild(marker);
});
</script>
Office/store coordinates are stored in infoblock element properties (type N for latitude and longitude) or in a custom property of type MAP.
Address geocoding
When importing addresses or adding a new object (office, pickup point), retrieve coordinates via the Geocoder API:
function geocodeAddress(string $address): ?array {
$apiKey = COption::GetOptionString('site', 'ymaps_api_key');
$url = 'https://geocode-maps.yandex.ru/1.x/?apikey=' . $apiKey
. '&geocode=' . urlencode($address) . '&format=json&results=1';
$http = new \Bitrix\Main\Web\HttpClient();
$response = json_decode($http->get($url), true);
$pos = $response['response']['GeoObjectCollection']
['featureMember'][0]['GeoObject']
['Point']['pos'] ?? null;
if (!$pos) return null;
[$lon, $lat] = explode(' ', $pos);
return ['lat' => (float)$lat, 'lon' => (float)$lon];
}
Cache the result — re-geocoding the same address is unnecessary. Cache in b_cached_files via CPHPCache or in a dedicated table.
Delivery zones
The task: when placing an order, the user clicks on the map or enters an address — the system determines the delivery zone and cost.
Step 1. Draw delivery zones as polygons and store them in an infoblock as a JSON string of vertex coordinates.
Step 2. Server-side check: determine whether a point lies inside a polygon (Ray Casting algorithm). PHP implementation:
function pointInPolygon(array $point, array $polygon): bool {
$x = $point['lon']; $y = $point['lat'];
$inside = false;
$n = count($polygon);
for ($i = 0, $j = $n - 1; $i < $n; $j = $i++) {
$xi = $polygon[$i]['lon']; $yi = $polygon[$i]['lat'];
$xj = $polygon[$j]['lon']; $yj = $polygon[$j]['lat'];
$intersect = (($yi > $y) !== ($yj > $y))
&& ($x < ($xj - $xi) * ($y - $yi) / ($yj - $yi) + $xi);
if ($intersect) $inside = !$inside;
}
return $inside;
}
Step 3. The Ajax handler in the checkout component receives the address, geocodes it, determines the zone, and returns the delivery cost. The cost is populated in the form before the order is placed.
Dealer/store map
A common task: a map with point clustering. Fetch all active elements with coordinates from the "Stores" infoblock and pass them to the frontend as JSON:
$stores = CIBlockElement::GetList(
['SORT' => 'ASC'],
['IBLOCK_ID' => STORES_IBLOCK_ID, 'ACTIVE' => 'Y'],
false, false,
['ID', 'NAME', 'PROPERTY_LAT', 'PROPERTY_LON', 'PROPERTY_ADDRESS', 'PROPERTY_PHONE']
);
// Build a GeoJSON Feature Collection
On the frontend — YMapClusterer from the @yandex/ymaps3-clusterer package for automatic marker grouping when zooming out.
| Task | Effort |
|---|---|
| Basic map with markers | 4–6 h |
| Geocoding + cache | 3–4 h |
| Delivery zones (polygons + server-side check) | 8–12 h |
| Store map with clustering | 6–8 h |







