> ## Documentation Index
> Fetch the complete documentation index at: https://developer.plugsurfing.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Integrating geosearch with client maps

This guide will show you how to fetch locations and show them on a map, using data from the [**Geosearch**](/reference/searchLocationsByRadius) endpoints.

Recommended UI flow:

1. Use radius or rectangle search to render map pins.
2. Use connector and EVSE fields from the search response for basic filtering.
3. When the user opens a pin or charger detail page, call [Get location by id](/reference/getLocationById).
4. Display prices from the detail response. If price is absent, show "Price temporarily unavailable."

Most client-side map libraries offer an `onRegionChangeComplete` event or similar, which is triggered when the user moves the map.\
This event should contain data for the current map position like `latitude`, `longitude`, `longitudeDelta`, `latitudeDelta`.

To get the correct amount of locations and aggregations, you need to know the `aggregationPrecision`, `latitude`, `longitude` and `distance`. Fortunately all of this can be retrieved or calculated from the map's `Region` data.

Let's look at the main function that will handle that. This sample code is written in TypeScript, but the logic will be the same in all programming languages.

```ts theme={null}
// This function calculates the necessary data and fetches locations from the Geosearch endpoint
async function getLocationsForRegion(region: Region) {
  // get data from the map region
  const { latitude, latitudeDelta, longitudeDelta } = region;

  // calculate the distance for latitudeDelta
  const latDistance = (latitudeDelta / 360) * 2 * Math.PI * EARTH_RADIUS;

  // calculate the distance for longitudeDelta
  const lonDistance =
    (longitudeDelta / 360) *
    2 *
    Math.PI *
    EARTH_RADIUS *
    Math.cos((latitude * Math.PI) / 180);

  // use the larger of the two distances
  const distance = Math.max(latDistance, lonDistance);

  // calculate aggregation precision based on latitude delta
  const aggregationPrecision = getClusteringPrecision(region);

  // fetch locations from the Geosearch endpoint
  try {
    const locations = await driveClient.fetchLocations({
      latitude: region.latitude,
      longitude: region.longitude,
      distance: distance,
      aggregate: true,
      aggregationPrecision: aggregationPrecision,
    });
    return locations;
  } catch (e) {
    console.log(e);
    return {
      locations: [],
      aggregates: [],
    };
  }
}
```

The `aggregationPrecision` plays an important role in what you get from the Geosearch endpoint, it controls how tightly clustered locations should be.\
Let's dive into the details now: how to get a correct `aggregationPrecision` and how to adjust it to your needs.

```ts theme={null}
// minimal supported aggregation precision via Geosearch API is 2
const MINIMUM_PRECISION = 2;
// maximal supported aggregation precision via Geosearch API is 9
const MAX_PRECISION = 9;
//controls how tightly markers should be clustered
const K = 0.00001;

// calculate precision from a region's latitudeDelta
function precisionFrom(latitudeDelta: number) {
  const x = latitudeDelta / K;
  switch (true) {
    case x > 1800000:
      return MINIMUM_PRECISION;
    case x > 162000:
      return 3;
    case x > 54000:
      return 4;
    case x > 10800:
      return 5;
    case x > 5400:
      return 6;
    case x > 4500:
      return 7;
    case x > 3600:
      return 8;
    default:
      return MAX_PRECISION;
  }
}

export function getClusteringPrecision(region: Region) {
    return precisionFrom(region.latitudeDelta),
}
```

The easiest way to manipulate how tightly locations are aggregated is via the `K` constant, here you can see examples for different values. Different `K` values generate very different output, so adjust it to your application needs.

Example:

| K value | 0.000001 | 0.00001 | 0.0001 |
| - | - | - | - |
| <span style={{ display: "block", position: "relative", top: "-215px", textAlign: "center" }}>Preview</span> | <img src="https://files.readme.io/90cc64bab53cc1d3be06d9845de9c5144d9ed9b52d34902c475e9193e6b4930c-69eb2401219196df1b49e22d142d5d45a697efb82726a5dc6faaf9a37cc433e9-image.png" alt="Map aggregation preview for K value 0.000001" width="200" /> | <img src="https://files.readme.io/a9d132ec22c0e822ca51e1bf9ff08faa6f9594d74f797c2af4afd467025f09c8-e51fce2e414565b0cc11717e8cf061396e9d8854ae43a74de9bbe9eac81ea8a4-image.png" alt="Map aggregation preview for K value 0.00001" width="200" /> | <img src="https://files.readme.io/6560eb45438d4b5f44b9636ed0356ca9054e89c1587caebb608540aaf350a66f-4ed39ab425128082189c3b31ff658d4db7f537c9279aae9f61905807ba7cb39d-image.png" alt="Map aggregation preview for K value 0.0001" width="200" /> |

<br />

The last step is rendering the markers on map, this differs a lot between popular map libraries, but let's look at an example built with `react-native` and the `react-native-maps` library. We will render red pins for locations and blue pins for aggregations.

```tsx theme={null}
type LocationResponse = {
  locations: Locations; // type for locations from Geosearch response
  aggregates: Aggregates; // type for aggregations from Geosearch response
};

// set default state
const [response, setResponse] = useState({
  locations: [],
  aggregates: [],
});

const Map = () => {
  const onRegionChangeComplete = async (region: Region) => {
    // use getLocationsForRegion function showed before
    const { locations, aggregates } = await getLocationsForRegion(region);
    // set fetched locations to state
    setResponse({
      locations,
      aggregates,
    });
  };

  return (
    // add onRegionChangeComplete event handler to fetch locations
    // when user finishes moving map
    <MapView onRegionChangeComplete={onRegionChangeComplete}>
      {response.locations.map((location) => (
        // render location markers
        <Marker
          key={location.id}
          coordinate={{
            latitude: parseFloat(location.coordinates.latitude),
            longitude: parseFloat(location.coordinates.longitude),
          }}
          pinColor="red"
        />
      ))}

      {response.aggregates.map((aggregate) => (
        // render aggregates markers
        <Marker
          key={aggregate.coordinates.latitude + aggregate.coordinates.longitude}
          coordinate={{
            latitude: parseFloat(aggregate.coordinates.latitude),
            longitude: parseFloat(aggregate.coordinates.longitude),
          }}
          pinColor="blue"
        />
      ))}
    </MapView>
  );
};
```

> ❗
>
> This is just an example to show how to display locations as on a map, the Drive API is not meant to be called from client apps. Instead, it should be integrated on your backend, as described in [this page](/docs/introduction/getting-started#interaction-between-you-as-a-partner-plugsurfing-drive-api-and-the-charge-point-operators).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.