## Objective

![image](https://developers.google.com/static/maps/architecture/places-aggregate-location-score/images/phone-flat-03-neue.png)

Finding the ideal location, whether a hotel for your upcoming vacation or a
family-friendly apartment, often involves a frustrating and time-consuming
process of comparing numerous options. What if you could help make this easier
for your users by providing a customized metric that reveals a hotel's
suitability for tourists or rank apartment listings based on their family
friendliness, transforming a tedious chore into an effortless decision.

This document outlines how to use [Places Aggregate
API](https://developers.google.com/maps/documentation/places-insights) to generate dynamic, custom location
scores, based on the density of places within a defined geographic area. The
score, a numerical ranking against your specified criteria, will instantly
communicate how suitable the location is for their needs.

Consider a scenario where you're promoting hotels in a city and want to
highlight those in the most attractive tourist areas by creating a *good for
tourists score* . Use Places Aggregate API to count how many relevant [place
types](https://developers.google.com/maps/documentation/places/web-service/place-types) are near each hotel.
For example, you know that your customers value hotels in locations that are
nearby a number of the following:

- Restaurants \& Coffee shops
- Parks \& Museums
- Clothing stores

By applying importance weightings to the counts of these selected place types,
you can calculate an overall score for each hotel location. The score reflects
the overall suitability of the location, based on the nearby places. The
weightings assigned to each place type should align with your specific use case
and what's important to your target audience. This document will use a *good for
tourists* score as the main example, but your score can be built to reflect your
user demographics and needs.

### Prerequisites

Before reading this document, familiarity with the following documentation is
recommended:

- [**Places Aggregate API**](https://developers.google.com/maps/documentation/places-aggregate) developer documentation to understand the technical details and the available parameters.
- \[Optional\] [**Gemini Developer
  API**](https://ai.google.dev/gemini-api/docs) developer documentation to understand how to call Gemini using an API and is used in this document as an option to generate the custom location score.

## Select relevant place types

The first step to building your custom location score is to decide on the place
types that are relevant to your customers from [Table
A](https://developers.google.com/maps/documentation/places/web-service/place-types#table-a). As we are
creating a *good for tourists* score, we have selected the following place types
that tourists will want to be located near during their stay:

- restaurant
- park
- clothing_store
- museum
- coffee_shop

Next, assign a weighting to each of these place types, reflecting its relative
importance in the final score. The weightings should be determined based on
what's most important for your use case and your user's preferences. For this
example, the weighting scale will be between 0 and 1, as follows:

|---|---|
| Place Type | Weighting |
| restaurant | 0.8 |
| park | 0.6 |
| clothing_store | 0.3 |
| museum | 0.2 |
| coffee_shop | 0.5 |

## Call Places Aggregate API

Now that you have a list of place types you're interested in, the next step is
to call Places Aggregate API.

Places Aggregate API requires a location filter. For this example use `circle`,
with the center `latLng` being the location of your hotel, and a `radius` of
500m. Also set the `ratingFilter` to return places with a rating between 3.8 and
5, excluding lower rated places from the counts.

Experiment with varying the settings of the location filter for your specific
use case. For example, you might want to capture places within a wider radius
from your center latitude and longitude by increasing the value of radius.
Alternatively, you might want to use a different method to set the search area,
such as [Region](https://developers.google.com/maps/documentation/places-insights/request-parameters#region)
or [Custom
area](https://developers.google.com/maps/documentation/places-insights/request-parameters#custom_area).

Familiarize yourself with the [location filter
section](https://developers.google.com/maps/documentation/places-insights/request-parameters) of the Places
Aggregate API documentation to learn about the options available to you.

Call Places Aggregate API for each place type and location you'd like to
generate a custom score for. For example, call for the restaurant Place Type for
one of your hotels:

```console
curl --location 'https://areainsights.googleapis.com/v1:computeInsights' \
--header 'X-Goog-Api-Key: API_KEY \
--header 'Content-Type: application/json' \
--data '{
    "insights": [
        "INSIGHT_COUNT"
    ],
    "filter": {
        "locationFilter": {
            "circle": {
                "latLng": {
                    "latitude": 51.51611,
                    "longitude": -0.12726
                },
                "radius": 500
            }
        },
        "typeFilter": {
            "includedTypes": [
                "restaurant"
            ]
        },
        "ratingFilter": {
            "minRating": 3.8,
            "maxRating": 5
        }
    }
}'
```

After all calls to the API have been completed, you have data that looks like
this for each location:

|---|---|---|
| Place Type | Weighting | Count |
| restaurant | 0.8 | 56 |
| park | 0.6 | 3 |
| clothing_store | 0.3 | 32 |
| museum | 0.2 | 8 |
| coffee_shop | 0.5 | 41 |

## Generate the custom location score

Now you have the count of places and weighting for each place type for each
location you can now generate the custom location score. We will discuss two
options in this section, using a local algorithm, or using the [Gemini Developer
API](https://ai.google.dev/gemini-api/docs).

### Option 1: Use an algorithm

The first option we'll cover is using a local algorithm to generate a score
using the weightings and counts for each Place Type. Normalize this score to a 0
to 5 scale, where higher values indicate a more attractive area based on your
criteria. For this example, generate two JavaScript objects from the data above:

|---|---|
| itemCounts | typeWeights |
| ```json { "restaurant": 56, "park": 3, "clothing_store": 32, "museum": 8, "coffee_shop": 41 } ``` | ```json { "restaurant": 0.8, "park": 0.6, "clothing_store": 0.3, "museum": 0.2, "coffee_shop": 0.5 } ``` |

Generate a score from the counts and weightings by multiplying the `itemCounts`
by the `typeWeights`, and adding the results to an overall `weightedCount`:

```javascript
let weightedCount = 0;
for (const itemType in itemCounts) {
  weightedCount += itemCounts[itemType] * typeWeights[itemType];
}
weightedCount = weightedCount.toFixed(2);
```

For this example, the output of this step is: 78.3.

Now you can use logarithmic normalization to generate the final score for this
location on a scale between 0 and 5:

```javascript
if (weightedCount === 0) {
   normalizedScore = 0;
} else {
   normalizedScore = Math.log(weightedCount + 1);
}

// Clamp between 0 and 5
normalizedScore = Math.max(0, Math.min(5, normalizedScore));
```

> [!NOTE]
> **Note:** Logarithmic normalization is just one way of achieving this. It's recommended to try other methods to find the most suitable for your use case.

For this example, the final score output is: 4.36 (rounded to two decimal
places).

### Option 2: Use Gemini Developer API

As an alternative to using a local algorithm, [Gemini Developer
API](https://ai.google.dev/gemini-api/docs) offers a powerful way to
compute the custom location score for all locations. Simply provide the count
and weighting data with system instructions for all your hotel locations.

This method is especially useful if you have nuanced information you'd like to
include in the calculation, such as:

- Text descriptions for each hotel location, for example: "This location is suitable for families and the area is quiet at night".
- Information about your user, such as: "This user is booking for a family and prefers a quiet area in a central location".

The Gemini Developer API can understand and factor in this qualitative data
leading to a more sophisticated and relevant score beyond a purely mathematical
approach.

By using the Gemini Developer API, in addition to the place type and weighting
table above, you can have description data for each location that looks like
this:

|---|---|
| Location | Description |
| [51.49884, -0.17978](https://maps.app.goo.gl/2vA2vBxwMtXXVyZf9) | Central location close to museums, quiet at night and suitable for families. |
| [51.51750, -0.13065](https://maps.app.goo.gl/7qWx1VXPkurbi3pR6) | Central location close to bars and restaurants. Loud and busy at night, good for groups. |
| [51.45712, 0.01146](https://maps.app.goo.gl/jmHoGf3cuVfbrukY8) | Residential location far from the city centre. |
| [51.51271, -0.09933](https://maps.app.goo.gl/LMNs49Tb3f3Vpw7b8) | Central location close to the river. quiet at night and suitable for families. |
| [51.58502, -0.06445](https://maps.app.goo.gl/JB2M9sTKn9wrFLUr9) | Residential location far from the city centre. |

These qualitative descriptions along with any user information or preferences
can be included in your prompt to Gemini.

#### System instructions

> [!TIP]
> **Tip:** Try building your Gemini prompt using [Google AI
> Studio](https://aistudio.google.com/) to test, and generate template API Code in a selection of languages.

Gemini requires instructions, along with the raw data, to know that it's
expected to generate a score for each location, based on the data points
provided. An example system instruction to achieve this could be as follows:

```
You will be given a json file containing details about a number of locations grouped by their latitude and longitudes.

Within the location details is information about the count of places nearby the location that match a specific category, and the weighting of importance of that category, between 0 - 1.

You will also be given information about the user's preference, and a description of each location. Take this into consideration when generating scores.

Generate a location suitability score taking these into account for each location. The score should be between 1 - 5 inclusive, to two decimal places. The minimum score a location can receive is 1.

Output in JSON
```

The above system instructions lets Gemini know what data to expect, and what the
expected output from the AI model is. It also requests the output in JSON.

#### Structured output

While we have asked Gemini to output the result in JSON, we need to be more
specific about the structure of the output, so we know what to expect when we
query it with code. For this, we can add an additional [structured
output](https://ai.google.dev/gemini-api/docs/structured-output?lang=rest)
instruction to the request, using the
[responseSchema](https://ai.google.dev/api/rest/v1beta/GenerationConfig?_gl=1*1on6xkn*_up*MQ..*_ga*MzYzODY3ODgyLjE3NDA0OTU1Nzc.*_ga_P1DBVKWT6V*MTc0MDQ5NTU3Ni4xLjAuMTc0MDQ5NTU3Ni4wLjAuMTM3NzYxOTczOA..#FIELDS.response_schema)
field in the Gemini API. This uses an [OpenAPI schema
object](https://spec.openapis.org/oas/v3.0.3#schema) to constrain
the model output.

For example:

```json
{
  "type": "array",
  "description": "Array of location data with score",
  "items": {
    "type": "object",
    "properties": {
      "location": {
        "type": "object",
        "description": "Geographical coordinates of the location",
        "properties": {
          "latitude": {
            "type": "number",
            "format": "float",
            "description": "Latitude of the location"
          },
          "longitude": {
            "type": "number",
            "format": "float",
            "description": "Longitude of the location"
          }
        },
        "required": [
          "latitude",
          "longitude"
        ]
      },
      "score": {
        "type": "string",
        "description": "A score associated with the location"
      }
    },
    "required": [
      "location",
      "score"
    ]
  }
}
```

This example requests that Gemini outputs a JavaScript array with the following:

- Location latitude \& longitude
- The custom location score

Using the above system instructions and structured output, the response from
Gemini for one location would look like this, with `score` being the custom
location score:

```json
[
  {
    "location": {
      "latitude": 51.51611,
      "longitude": -0.12726
    },
    "score": "4.13"
  }
]
```

### Display the score

Once you have generated the custom location score for each location using one of
the described methods, it can be displayed alongside the details of your hotel,
or used as a search filtering option. For example, "show me places with a high
*good for tourists* score". This will enable your customers to make data based
decisions when booking.

## Conclusion

Using custom locations scores can be a powerful tool to give your users an at a
glance overview of the suitability of an area. This document demonstrated
generating custom location scores for various locations using five separate
place types. This implementation can be modified to suit your needs, and similar
place types can be combined into one request, to return the aggregated count of
those types, to provide to your custom location scoring solution.

Try [Places Aggregate API](https://developers.google.com/maps/documentation/places-insights) today to
generate insightful location scores to help your customers make well-informed
location-based decisions!

## Contributors

[Henrik Valve](https://www.linkedin.com/in/henrikvalve/) \| DevX
Engineer