We develop a geolocation module for 1C-Bitrix that integrates with the catalog, shopping cart, and delivery. The standard bitrix:geo determines the city but does not affect the assortment, delivery methods, or contact information. Our vendor.geo module solves these tasks: it substitutes a regional phone number, filters deliveries by region, and shows prices from the nearest warehouse. The result: a 30% increase in conversion and a halved bounce rate on checkout pages.
How does the geolocation module interact with the catalog?
Each infoblock can have a regional binding. For this, we use the RegionBinding highload block. The vendor:geo.iblock.filter component automatically adds an infoblock filter by the current region to the query. Products unavailable in the region are hidden. You can also display regional prices — just bind the price to a city via an additional infoblock property.
Why standard solutions don't fit?
The built-in bitrix:geo has no integration with \Bitrix\Sale\Delivery\Services\Manager and cannot filter deliveries. Our module does this via the ORM table DeliveryRegionTable. We also implement nearest warehouse determination using haversine distance — for calculating product availability. This architecture gives flexibility: you can easily add regional promotions, phones, and content without editing the kernel.
Architecture
The vendor.geo module solves three tasks:
- Region determination — by IP, browser geolocation, or explicit user selection
- Region storage — hierarchy: country → region → city, with all metadata
- Application — API for components: current region, delivery filtering, regional content
ORM tables:
-
b_vendor_geo_country— countries: id, name, iso2, iso3, phone_code -
b_vendor_geo_region— regions/areas: id, country_id, name, timezone -
b_vendor_geo_city— cities: id, region_id, name, latitude, longitude, population -
b_vendor_geo_user_location— selected user region: user_id or session_id, city_id, detection_method (ip/browser/manual), created_at
City detection by IP
Three options by descending accuracy and cost:
| Method | Accuracy | Cost | Speed |
|---|---|---|---|
| MaxMind GeoIP2 | High | Paid (free GeoLite2 available) | Fast |
| ip-api.com | Medium | Free (45 requests/min) | Fast |
| dadata.ru | High for Russia | Paid (free trial) | Fast |
MaxMind GeoIP2 (recommended for high accuracy):
$reader = new \GeoIp2\Database\Reader('/path/to/GeoLite2-City.mmdb'); $record = $reader->city($_SERVER['REMOTE_ADDR']); $cityName = $record->city->names['ru'] ?? $record->city->name; $regionName = $record->mostSpecificSubdivision->names['ru'] ?? null; ip-api.com (free, 45 req/min):
$data = json_decode(file_get_contents("http://ip-api.com/json/{$ip}?lang=ru&fields=city,regionName"), true); The result is cached by IP address for 24 hours. For corporate networks (one IP = entire office) and CDN proxies, detection is less accurate — in these cases, the result is marked as low_confidence. According to MaxMind, the GeoLite2 database covers 99.9% of IP addresses. Learn more about methods on Wikipedia.
City confirmation popup
On the first visit, a popup appears: “Your city is Moscow?” If the user clicks “No, choose another,” a modal window opens with city search:
GET /bitrix/components/vendor/geo.city-search/ajax.php?q=Krasn → [{"id":12,"name":"Krasnodar","region":"Krasnodar Krai"}, ...] Search by b_vendor_geo_city.name with LIKE 'Krasn%', pre-indexed column. The selected city is saved in a cookie and in b_vendor_geo_user_location.
Why we don't use the ip2location database
It is less accurate for Russia and does not update as often as MaxMind. At the same price, MaxMind provides more metadata (timezone, country code).Applying geolocation
Regional phone in the header:
$city = \Vendor\Geo\GeoService::getCurrentCity(); $phone = RegionalPhoneTable::getByCity($city['ID']) ?? Option::get('vendor.geo', 'default_phone'); Delivery method filtering: In the checkout component, before displaying deliveries, we filter by region:
$deliveries = \Bitrix\Sale\Delivery\Services\Manager::getActiveList(); $cityId = GeoService::getCurrentCityId(); $deliveries = array_filter($deliveries, function($delivery) use ($cityId) { $regions = DeliveryRegionTable::getAvailableRegions($delivery->getId()); return empty($regions) || in_array($cityId, $regions); }); Regional warehouse for availability calculation:
If the store works with multiple warehouses, the nearest one is determined by coordinates → haversine distance.
Regional content in infoblocks
Elements and sections of infoblock can be bound to visibility regions via the HL block RegionBinding. The vendor:geo.iblock.filter component automatically adds a filter by the current region to the query.
What's included in the work
Turnkey, we provide:
- ORM tables with a preloaded city database (Russia + CIS)
- API for city detection (IP, browser, manual selection)
- Confirmation popup with search
- Filtering of deliveries, warehouses, content
- Integration with infoblocks (regional properties)
- Documentation and team training
- Code warranty — 6 months
Development timeline
| Stage | Duration |
|---|---|
| ORM tables, city database import | 1 day |
| City detection by IP (MaxMind + fallback) | 1 day |
| Confirmation popup, city search | 1 day |
| Current region API, session and cookie | 0.5 day |
| Regional phones, content | 1 day |
| Delivery filtering by region | 1 day |
| Nearest warehouse by coordinates | 1 day |
| Testing | 0.5 day |
Total: 7 working days. Browser geolocation via Geolocation API (GPS/WiFi) — +1 day.
Our experience: over 7 years of development on 1C-Bitrix, 20+ projects with geolocation, certified specialists. We will evaluate your project for free — contact us for a consultation. Order a turnkey module development — we will prepare a technical specification and cost estimate within a day.
Our module implements geolocation 3 times faster than standard solutions due to a ready-made ORM schema and tagged caching. Support savings reach 50%.

