1C-Bitrix Integration with Google Maps
Google Maps Platform is the choice for international projects and sites that require correct rendering outside Russia. Unlike Yandex Maps, Google Maps requires a payment method to be attached even for free usage within the monthly limit ($200/month free credit ≈ 28,000 map loads).
Setup and API key
In Google Cloud Console, create a project and enable three APIs:
- Maps JavaScript API — renders the map in the frontend.
- Geocoding API — server-side address geocoding.
- Places API — address autocomplete during input.
Restrict the key: HTTP referrer for the JavaScript API (site domain only), server IP address for Geocoding/Places API. This prevents quota leakage if the key is stolen.
Store the key in .env or COption::GetOptionString('site', 'gmaps_api_key') — never embed it directly in templates.
Map initialization
<div id="gmap" style="width:100%;height:400px"></div>
<script>
function initMap() {
const coords = { lat: <?= $lat ?>, lng: <?= $lon ?> };
const map = new google.maps.Map(document.getElementById('gmap'), {
center: coords, zoom: 14,
styles: googleMapStyles, // custom brand styles
});
new google.maps.Marker({ position: coords, map: map, title: '<?= htmlspecialchars($title) ?>' });
}
</script>
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=<?= $apiKey ?>&callback=initMap&language=ru®ion=RU">
</script>
The language=ru®ion=RU parameters ensure Russian street names and the correct address format.
Server-side geocoding
function geocodeAddressGoogle(string $address): ?array {
$apiKey = COption::GetOptionString('site', 'gmaps_server_key');
$url = 'https://maps.googleapis.com/maps/api/geocode/json?'
. 'address=' . urlencode($address)
. '&key=' . $apiKey . '&language=ru®ion=RU';
$http = new \Bitrix\Main\Web\HttpClient();
$data = json_decode($http->get($url), true);
if ($data['status'] !== 'OK') return null;
$loc = $data['results'][0]['geometry']['location'];
return ['lat' => $loc['lat'], 'lon' => $loc['lng']];
}
Limits: Geocoding API — 40,000 requests/month free. When importing a large address directory, add a 50 ms delay between requests and cache results in b_cached_files for 30 days.
Address autocomplete via Places API
On the checkout page, the user starts typing an address — a dropdown of suggestions from Google Places appears. After selection, coordinates are populated into hidden fields and passed to the delivery handler.
const input = document.getElementById('delivery-address');
const autocomplete = new google.maps.places.Autocomplete(input, {
types: ['address'],
componentRestrictions: { country: ['ru', 'by', 'kz'] },
fields: ['geometry', 'formatted_address', 'address_components'],
});
autocomplete.addListener('place_changed', () => {
const place = autocomplete.getPlace();
document.getElementById('lat').value = place.geometry.location.lat();
document.getElementById('lon').value = place.geometry.location.lng();
// Parse address_components for individual fields (city, street, building)
parseAddressComponents(place.address_components);
});
Marker clustering
For maps with dozens of points (stores, dealers), use the @googlemaps/markerclusterer library:
import { MarkerClusterer } from '@googlemaps/markerclusterer';
const markers = storesData.map(store => new google.maps.Marker({
position: { lat: store.lat, lng: store.lon },
title: store.name,
}));
new MarkerClusterer({ map, markers });
Store data is passed from PHP to JS via json_encode() on the page or via an Ajax request to the component on the first map load.
Cost and monitoring
In Google Cloud Console, configure budget alerts. Exceeding the $200 limit causes the API to return OVER_QUERY_LIMIT errors. For control, add logging of all server-side requests to the Geocoding API with a daily quota counter.
| Task | Effort |
|---|---|
| Key setup and restrictions | 1–2 h |
| Basic map with markers | 3–5 h |
| Geocoding + caching | 3–4 h |
| Places Autocomplete in the delivery form | 4–6 h |
| Map with clustering | 5–7 h |







