fbpx

Insights for Building High-Precision Map Applications

At Agilno, we pride ourselves on delivering cutting-edge software solutions that meet the evolving needs of our clients. In our latest project, the Media Planning tool, we tackled the challenge of providing accurate geospatial data for media inventory locations across Canada. Initially, we relied solely on Mapbox for geolocation, but we encountered limitations when it came to retrieving data beyond simple location boundaries. Mapbox suggested using their Boundaries library, which would have cost thousands of dollars. Instead, we discovered and implemented an open-source solution that not only solved the problem but also saved our client significant costs. Our approach proved to be effective and inexpensive, leveraging the combined strengths of Mapbox Geocoder and the Nominatim API.

Why We Chose Mapbox and Nominatim

Mapbox Geocoder is a powerful tool for geocoding and autocomplete functionality. Its user-friendly interface and reliable search results make it an ideal choice for users looking to quickly find locations. However, while Mapbox provides a bounding box for selected locations, it often returns a rectangular area, which may not be precise enough for our requirements. This is where the Nominatim API comes into play. Nominatim offers the ability to retrieve the area in a polygon shape, providing a more accurate representation of the selected location. By combining Mapbox’s strengths in user interaction with Nominatim’s precision in defining geographical boundaries, we created a solution that ensures both ease of use and accuracy.

Our Approach to Integration

In our Media Planning tool built with Next.js, we implemented the following approach to combine these two APIs.

Autocomplete with Mapbox Geocoder

When a user begins typing an address, city, or province in Canada, we utilize Mapbox’s Autocomplete feature. This provides real-time suggestions and allows users to select their desired location easily. Mapbox’s intuitive interface and generally good results ensure that users can find locations quickly without needing to enter the full address.

geocoder.on('result', async (data) => {
    // Fetch results from the Nominatim API based on the place name
    const nominatimResults = await NominatimGeocoder(data.result.place_name);

    // Find the result with the highest 'importance' score
    const highestImportanceResult = nominatimResults?.reduce(
        (prev, current) => (prev.importance > current.importance ? prev : current),
        nominatimResults[0]
    );

    // Construct a new location object with relevant details
    const newLocation = {
        // Use the bounding box if available, otherwise undefined
        bbox: data.result.bbox || undefined,

        // Extract and convert the center coordinates to numbers
        center: [Number(data.result.center[0]), Number(data.result.center[1])],

        // Store the location name (place name)
        locationName: data.result.place_name,

        // Use the GeoJSON from the highest importance result
        geojson: highestImportanceResult?.geojson,
    };

    // Update the application state with the new location
    setLocationInput(newLocation);
});

Polygon Retrieval with Nominatim API

Once the user selects a location from Mapbox suggestions, we send that location data to the Nominatim API. Nominatim then returns a more precise area in the form of a polygon, which consists of coordinates defining the exact boundaries of the location—unlike the rectangular bounding box from Mapbox. This precise polygon is essential for our Media Planning tool, as it allows us to accurately display inventory data within the correct geographical boundaries.

const NominatimGeocoder = async (query) => {
    // Construct the API URL with query parameters
    const url = `${NOMINATIM_API}?q=${encodeURIComponent(query)}&format=json&polygon_geojson=1&addressdetails=1`;

    try {
        // Make a request to the Nominatim API
        const response = await fetch(url);

        // Check if the response is ok (status code 200–299)
        if (!response.ok) {
            throw new Error(`Error: ${response.status}`);
        }

        // Parse the response data as JSON
        const data = await response.json();

        // Return the parsed data
        return data;
    } catch (error) {
        // Handle any errors that occur during the fetch operation
        console.error('Error fetching from Nominatim API:', error);
        return [];
    }
};

Displaying the Results on the Map

The polygon data retrieved from Nominatim is then used to overlay the selected area on the map within our Media Planning tool, allowing users to visualize the exact coverage area, ensuring that the media inventory is accurately represented.

Technical Breakdown: Integrating Nominatim API and Mapbox in Next.js

From a technical perspective, integrating both the Mapbox Geocoder and Nominatim API into our Media Planning tool built with Next.js involved several critical steps to ensure seamless functionality and accuracy. Below is a breakdown of the key components and processes:

Frontend Implementation (Next.js)

We utilized `MapboxGeocoder` from `@mapbox/mapbox-gl-geocoder` to implement the autocomplete functionality. When the user begins typing an address, city, or province, the input is sent to the Mapbox Geocoder API, which returns a list of suggested locations. This real-time feature significantly enhances the user experience by offering immediate feedback and suggestions.

After the user selects a location, a `select` event is triggered, capturing the necessary details (e.g., latitude, longitude) from the Mapbox response. This event is handled by the frontend and passed to the Nominatim API for further processing.

Nominatim API Calls (Frontend)

Once the location is selected, the frontend processes a request to the Nominatim API. Using the location details provided by Mapbox (such as city name or coordinates), we query the Nominatim API to retrieve a more precise polygon-based boundary of the selected location.

The frontend then parses the response from Nominatim, which typically includes detailed polygon data in GeoJSON format. This data is rendered on the map for the user.

Displaying Geospatial Data (`mapbox-gl`)

Using the `mapbox-gl` library, we overlay the polygon data on the map. The polygon coordinates retrieved from Nominatim provide a detailed and accurate representation of the area, which is crucial for our media inventory display.

The bounding boxes provided by Mapbox can be inaccurate for larger or irregularly shaped areas. Nominatim’s polygon coordinates solve this by offering more flexible and precise boundaries, essential for the accuracy of our geospatial solution.

Here’s how it looks on our app: Once the selection is made, the app seamlessly retrieves the precise area using Nominatim’s polygon-based data. However, the location boundaries are not visually overlaid on the map, so the user cannot see the exact area that the data is being retrieved for. Despite this, the user-friendly interface allows for effortless exploration of the inventory data within the selected, but unseen, boundaries.

Tip: Caching and Potential Backend Integration

To improve performance, consider caching frequently requested locations and their corresponding polygon data. This reduces the need for repeated API calls to Nominatim, improving the responsiveness of the application.

If more complex logic or heavy API usage is required, moving the API request handling to a backend server can be a good solution. This would allow for more sophisticated data handling, better control over API limits, and caching at the server level.

Conclusion

Initially, we faced a limitation with Mapbox in retrieving data beyond simple location boundaries. The proposed solution from Mapbox was their Boundaries library, which came with a hefty price tag. Instead, we explored alternative solutions and found the Nominatim API, which gave us a more accurate polygon-based representation of locations, all without the associated cost. By combining Mapbox’s strong user interaction features with the precision of Nominatim, we delivered a high-performing, cost-effective geospatial solution for our client’s Media Planning tool. At Agilno, we remain committed to leveraging innovative technologies that provide the best value for our clients, ensuring they have the tools they need to succeed.