Skip to content

Leaflet Maps Integration

George Dawoud edited this page Apr 27, 2026 · 1 revision

Leaflet Maps Integration

ChurchCRM 7.0.0 replaced Google Maps / Bing Maps with Leaflet.js + OpenStreetMap. No API key is required. This guide covers how to embed interactive maps in ChurchCRM pages and plugins.


Background

Before 7.0.0, maps required a Google Maps API key (sGoogleMapsRenderKey) and a Bing Maps key (sBingMapKey). Both are now removed. Maps work out of the box using:

  • Tiles: OpenStreetMap via tile.openstreetmap.org
  • Geocoding: Nominatim (nominatim.openstreetmap.org)
  • Map renderer: Leaflet.js (already bundled in the frontend build)

Including Leaflet in a Page

Leaflet.js is bundled in ChurchCRM's frontend build. It is available globally as L on any page that includes the standard footer.

<?php require SystemURLs::getDocumentRoot() . '/Include/Footer.php'; ?>
<!-- Leaflet is already loaded by Footer.php -->

If your page does not use the standard footer, add:

<link rel="stylesheet" href="<?= SystemURLs::getRootPath() ?>/skin/css/leaflet.min.css">
<script src="<?= SystemURLs::getRootPath() ?>/skin/js/leaflet.min.js"></script>

Basic Map

<!-- Map container -->
<div id="map" style="height: 400px; width: 100%;"></div>

<script>
document.addEventListener('DOMContentLoaded', function () {
    const map = L.map('map').setView([<?= $lat ?>, <?= $lng ?>], 13);

    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
    }).addTo(map);

    // Add a marker
    L.marker([<?= $lat ?>, <?= $lng ?>])
        .addTo(map)
        .bindPopup('<?= addslashes($label) ?>')
        .openPopup();
});
</script>

Displaying Multiple Markers

<div id="map" style="height: 500px;"></div>

<script>
document.addEventListener('DOMContentLoaded', function () {
    const map = L.map('map').setView([<?= $churchLat ?>, <?= $churchLng ?>], 11);

    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
    }).addTo(map);

    const families = <?= json_encode($familiesData) ?>;

    families.forEach(function (family) {
        if (family.lat && family.lng) {
            L.marker([family.lat, family.lng])
                .addTo(map)
                .bindPopup(family.name);
        }
    });
});
</script>

Where $familiesData is a PHP array of objects with lat, lng, and name fields.


Geocoding an Address (Server-Side)

Use the Geocoder service class, which calls Nominatim:

use ChurchCRM\Service\GeocoderService;

$geocoder = new GeocoderService();
$result = $geocoder->geocodeAddress('123 Main St', 'Springfield', 'IL', '62701', 'US');

if ($result !== null) {
    $lat = $result->getLatitude();
    $lng = $result->getLongitude();
}

Do not call Nominatim directly from JavaScript — rate-limiting and CORS restrictions apply. Always geocode server-side.


Rate Limiting

Nominatim's usage policy limits requests to approximately 1 per second. ChurchCRM's geocoder automatically respects this limit with a small delay between requests during bulk operations (e.g., "Update All Family Coordinates"). Do not parallelize geocoding requests.

For large installations (tens of thousands of records), consider running a self-hosted Nominatim instance.


Map in a Plugin

Plugins can embed maps on their custom pages using the same approach as core pages. Ensure:

  1. Your plugin page includes the standard ChurchCRM footer (which loads Leaflet)
  2. Your map container has a defined height (Leaflet requires a fixed height to render)
  3. You read coordinates from the Propel ORM models (e.g., Family::getLatitude(), Family::getLongitude())

Troubleshooting

Symptom Likely cause Fix
Map container is blank Leaflet initialized before container is in DOM Move L.map() call inside DOMContentLoaded
Tiles load but map is gray Container has no height Set height: 400px (or any value) on the container
Tiles don't load Server can't reach tile.openstreetmap.org Check outbound HTTPS; verify DNS from server
Marker at 0,0 (ocean) null lat/lng passed to Leaflet Guard with if (lat && lng) before placing marker
Geocoding returns null Nominatim can't parse the address Clean the address — spell out abbreviations, add country

Related Pages

🚀 Getting Started

docs.churchcrm.io for installation & setup


👥 For End Users

docs.churchcrm.io for user manuals


🔧 For Administrators

docs.churchcrm.io for admin manuals


👨‍💻 For Developers

Contributing to ChurchCRM


📚 Help & Reference

Clone this wiki locally