Geolocation Filters with Static Filters | Yext Hitchhikers Platform

Background

Geolocation filters are a special type of Static Filter , which filter location-type results based on their proximity to a point (a specific latitude and longitude) and whether they fall within a specific radius. All geolocation filters must have these two things – a point and a radius – which can be calculated in different ways depending on how the filter is created.

In this document, we are going to focus on geolocation filters that are defined explicitly in an API request using static filters. This is the approach used by locators, find-a-doctors, and other similar use cases.

However, geolocation filters can also be triggered implicitly with inferred Filter, which uses NER to identify locations mentioned in the user’s search query and translates them into geolocation filters (e.g., for queries like “locations in Seattle” or “doctors in New York”).

We will not discuss how inferred Filter selects these geolocation filters in this document; for that, see the inferred Filters section of the Geolocation Filters with inferred Filters reference document.


API Request

Geolocation filters today can only be defined on the Vertical Search query endpoint .

There are three (3) different parameters on the API request that can be used to define geolocation filters: filters (which can be used in two different ways), location, and locationRadius.

Parameter Description Example
filters ($eq) A Static Filter on the special builtin.location field (or the builtin.location field of any related entities), which is set equal to a Mapbox location ID. &filters={ "builtin.location": { "$eq":"P-place.297027820"} }
filters ($near) A Static Filter on the special builtin.location field (or the builtin.location field of any related entities), which uses the $near operator and accepts an object with a latitude, longitude, and radius (in meters). &filters={ "builtin.location": { "$near": { "lat": -84.253981, "lng": 49.451563, "radius": 804672}}}
location A parameter that accepts an object with a latitude and longitude, which is meant to represent the user’s location. &location={ "lat": -84.25398,"lng": 49.451563}
locationRadius A parameter that accepts a number (in meters) that represents the radius of a geolocation filter. &locationRadius=804672


filters ($eq)

The filters parameter is used to define Static Filters on a search query, and geolocation filters are a special type of Static Filter made using the special builtin.location field, or the builtin.location field of any related entities (e.g., c_relatedLocations.builtin.location). You have the option to define filters on builtin.location in two different ways – using the $eq operator or the $near operator.

We’ll start with the $eq operator, which is the most common way of defining a geolocation filter today. This is the type that is returned by Filter Search (more on Filter Search below ).

{
  "builtin.location": {
  "$eq":"P-place.297027820"
  }
}

This filter uses an ID from Mapbox, which is returned from their Geocoding API endpoint. Each ID corresponds to a specific location; for example, the ID in the example above (P-place.297027820) corresponds to Seattle, Washington.

Using this ID, we fetch information about the place from Mapbox which are required to define a geolocation filter, including a point (the lat/long for the center of the place), a radius (which approximates the “size” of the place), as well as a display name.

Example Mapbox Geocoding API Response

{
  "type": "FeatureCollection",
  "query": ["seattle"],
  "features": [
  {
    "id": "place.297027820",
    "type": "Feature",
    "place_type": ["place"],
    "relevance": 1,
    "properties": {"wikidata": "Q5083"},
    "text": "Seattle",
    "place_name": "Seattle, Washington, United States",
    "bbox": [-122.462846337, 47.477226752, -122.215854018, 47.737930928],
    "center": [-122.330062, 47.603832],
    "geometry": {"type": "Point", "coordinates": [-122.330062, 47.603832]},
    "context": [
    {
      "id": "district.12322540",
      "wikidata": "Q108861",
      "text": "King County"
    },
    {
      "id": "region.66796",
      "short_code": "US-WA",
      "wikidata": "Q1223",
      "text": "Washington"
    },
    {
      "id": "country.8940",
      "short_code": "us",
      "wikidata": "Q30",
      "text": "United States"
    }
    ]
  },
  { ... }
  ],
}

The way we calculate the radius from this Mapbox response is by using the bbox property; which is Mapbox’s approximate bounding box representing the area of the place in question. We first compute a radius from this bounding box, and then round it up as follows:

  • 25 miles (if the computed radius is between 0 and 25 miles), or
  • 50 miles (if the computed radius is between 25 and 50 miles), or
  • As is (if the computed radius is greater than 50 miles)

Finally, there are a few caveats about the Mapbox ID worth mentioning:

  • We always prepend “P-” to the Mapbox ID when constructing the static filter.

  • IDs from Mapbox are not immutable; Mapbox does occasionally change IDs for their places.


filters ($near)

The second type of geolocation filter, also on the special builtin.location field, is a $near filter that explicitly defines the latitude, longitude, and radius of a filter in an object. For example:

{
  "builtin.location": {
  "$near": {
    "lat": -84.253981,
    "lng": 49.451563,
    "radius": 804672
  }
  }
}

This filter is pretty straightforward compared to the $eq filter, as all of the necessary geolocation parameters are explicitly defined in the provided object, and doesn’t require any more elaboration.


location

With every Search query, we automatically compute an approximate latitude and longitude point that the search was placed from server-side based on the IP address the request was made from. The location query parameter allows you to override this point, and can accept an object with any arbitrary latitude and longitude.

When used alongside a locationRadius parameter (discussed below ), the point represented by location and the radius represented by locationRadius together effectively form a geolocation filter.

However, location also has several other important functions outside of this, which include:

  • Computing Distance - For every location result, Search computes the distance of that result to the lat/long provided in this location param (or the lat/long derived from the IP address, if not provided). This can be used to rank results by distance to the user.

  • Biasing Mapbox Locations - When fetching locations from Mapbox for either Filter Search or inferred Filter, we pass the location provided as a bias into Mapbox, which affects which candidate locations returned. For example, a query for “Akron” may return “Akron, OH” if the user is in Ohio, or “Akron, CA” if the user is in California.

The location parameter is also available on the Universal Search query endpoint , specifically for these two purposes. However, the Universal Search query endpoint does not have the filters or locationRadius parameters, so you cannot define geolocation filters.

Finally, if location is provided alongside a geolocation filter in the filters property of a query, then it will only be used for these two purposes, and does not affect the geolocation filter provided at all.


locationRadius

The locationRadius parameter accepts a number (in meters) which is used to set (or override) the radius of any geolocation filter applied on the query. This can include geolocation filters passed in the filters parameter, or to create a geolocation filter alongside location.

For example, if the user makes a request that contains a geolocation filter like this:

/query?...&filters={"builtin.location":{"$near":{"lat":-84.253981,"lng":49.451563,"radius":804672}}}&locationRadius=10000

The radius that will be applied will be 10,000 meters, not 804672 meters, as indicated in the filter.

One expected side effect of this is that locationRadius alone is enough to create a geolocation filter, because as mentioned earlier, the user’s location is always determined automatically server-side from the IP address of the request.


API Response

The API response for a query with a geolocation filter includes several properties determined from the filter, including:

Property Description Example
distance The distance (in meters) from the result to the user’s location. "distance": 3866961
distanceFromFilter The distance (in meters) from the result to the lat/long point of the geolocation filter applied on the query. "distanceFromFilter": 5347
locationBias The user’s location that was used, either explicitly provided in the location query parameter on the request, or inferred from the IP address of the request. "locationBias": { "latitude": 40.7306, "longitude": -73.9866, "locationDisplayName": "New York City, New York, United States", "accuracy": "IP"}
appliedQueryFilters A list of query-time filters applied on the query. Query-time filters do not include Static Filters provided in the filters parameter, but rather, only include filters that were computed after the query was made. For example, filters inferred by inferred Filter, or by the locationRadius parameter. "appliedQueryFilters": [ { "displayKey": "Location" "displayValue": "near me", "filter": { "builtin.location": { "$near": { "lat": 47.603832, "lng": -122.330062, "radius": 2.0E7}}}, "type": "PLACE"}]


distance and distanceFromFilter

distance and distanceFromFilter are computed and returned for every location-type result, and represent the distance from that result to the user’s location and to the geolocation filter’s lat/long point, respectively.

If no geolocation filter is applied, then only distance is computed (because we will always have the user’s location from either the location parameter, or from the IP address).

For example, see this query, which contains a geolocation filter in the filters parameter, and the response:

/query?...&filters={"builtin.location":{"$eq": "P-place.297027820"}}
{
  "meta": {
    "uuid": "01857f5f-b597-98d9-628d-661c25abd23e",
    "errors": []
  },
  "response": {
    "businessId": 0000000,
    "queryId": "01857f5f-b5a6-d942-c931-900d0d907f1f",
    "resultsCount": 1,
    "results": [
      {
        "data": { ... },
        "highlightedFields": {},
        "distance": 3866961,
        "distanceFromFilter": 5347
      }
    ],
    "appliedQueryFilters": [],
    "facets": [],
    "source": "YEXT",
    "searchIntents": [],
    "locationBias": {
      "latitude": 40.7306,
      "longitude": -73.9866,
      "locationDisplayName": "New York City, New York, United States",
      "accuracy": "IP"
    }
  }
}

distance and distanceFromFilter are the properties used by the Distance sorting criteria , which can be set on the Search Configuration. By default, the Search algorithm will sort by distanceFromFilter when it is available, and distance if not.


locationBias

locationBias represents the user’s location that was used for the search, either as provided directly in the location parameter of the request, or inferred from the user’s IP address.

The accuracy property indicates which method was used; “IP” indicates it was determined from the IP address, and “DEVICE” indicates it was provided in the location parameter. For example:

/query?...&location=47.603832,-122.330062
{
  "meta": {
    "uuid": "01857f5f-b597-98d9-628d-661c25abd23e",
    "errors": []
  },
  "response": {
    "businessId": 0000000,
    "queryId": "01857f5f-b5a6-d942-c931-900d0d907f1f",
    "resultsCount": 1,
    "results": [
      {
        "data": { ... },
        "highlightedFields": {},
        "distance": 3866961,
        "distanceFromFilter": 5347
      }
    ],
    "appliedQueryFilters": [],
    "facets": [],
    "source": "YEXT",
    "searchIntents": [],
    "locationBias": {
      "latitude": 47.603832,
      "longitude": -122.330062,
      "locationDisplayName": "Seattle, Washington, United States",
      "accuracy": "DEVICE"
    }
  }
}


appliedQueryFilters

appliedQueryFilters returns a list of filters that were determined at query time. This does not include geolocation filters that were provided in the filters parameter, but it does include filters inferred from inferred Filter (e.g., if the user searches “locations in Seattle” or “doctors near me”), as well as filters derived from locationRadius.

For example, for the following request, the appliedQueryFilters parameter indicates that the locationRadius parameter was automatically converted into a $near filter using the user’s locationBias and the locationRadius.

/query?...&locationRadius=20000
{
  "meta": {
    "uuid": "01857f73-bed0-fbea-5da8-9b040c60fba2",
    "errors": []
  },
  "response": {
    "businessId": 0000000,
    "queryId": "01857f73-beea-d55d-8c35-8cdff28e15f8",
    "resultsCount": 2,
    "results": [ ... ],
    "appliedQueryFilters": [
      {
        "displayKey": "Location",
        "displayValue": "near me",
        "filter": {
          "builtin.location": {
            "$near": {
              "lat": 40.7099,
              "lng": -73.9591,
              "radius": 20000.0
            }
          }
        },
        "type": "PLACE"
      }
    ],
    "facets": [],
    "source": "YEXT",
    "searchIntents": [],
    "locationBias": {
      "latitude": 40.7306,
      "longitude": -73.9866,
      "locationDisplayName": "New York City, New York, United States",
      "accuracy": "IP"
    }
  }
}


The Filter Search endpoint is used to return candidate filters that match (using prefix matching logic) with an input. It is used to create search bars like the following:

Geolocation Mapbox Places


builtin.location

You can return geolocation filters in Filter Search by using builtin.location as the field in the search_parameters parameter of the request. For example:

/filtersearch?...&search_parameters={"fields":[{"fieldId":"builtin.location","entityTypeId":"location"}]}

This will return candidate locations from Mapbox that match with the user’s query. The behavior is essentially identical to Mapbox’s own Geocoding API endpoint; however, results are returned in the format of a geolocation filter using $eq (as discussed above ).

By default, Filter Search will only return results from Mapbox of a select set of place types. This includes:

  • Country
  • Region
  • Postcode
  • District
  • Place
  • Locality

However, Mapbox does support three other place types as well: address, neighborhood, and poi (point of interest).

Geolocation Mapbox Places


address.countryCode

There are some cases where Filter Search on builtin.location will not return $eq filters on builtin.location. Specifically, when Mapbox determines that the type of location is a country.

In these cases, Filter Search will instead return a filter on the address.countryCode field. This field uses ISO-3166-2 codes for countries. For example, the country code for Canada is “CA”.

{
  "meta": {
    "uuid": "01858283-5737-a041-2a01-2c71fc8864f6",
    "errors": []
  },
  "response": {
    "businessId": 0000000,
    "sections": [
      {
        "results": [
          {
            "key": "address.countryCode",
            "value": "Canada",
            "filter": {
              "address.countryCode": {
                "$eq": "CA"
              }
            },
            "matchedSubstrings": [{...}]
          },
          {...}
        ]
      }
    ],
    "failedVerticals": [],
    "queryId": "01858283-5746-40bb-6f84-9ce226c457e5"
  }
}

Filtering on this field means that we are not performing a search using a point and radius, like typical geolocation filters do. Instead, we filter to locations that explicitly have the same country code as the filter.

The benefit of this is that this filter will respect the boundaries of the country that they represent, and avoid situations where results in neighboring countries that happen to be near the border of the country in question get returned in the search.

One side effect worth noting is that this means that the results will not contain distanceFromFilter for these filters, as there is not a “point” that we are using to calculate the distance from. The results will still contain the distance property however, which can be used to sort results by distance to the user’s location.


Search Configuration

There are several properties on the Search Configuration that can be used to influence the behavior of geolocation filters in queries and in Filter Search.


minLocationRadius

minLocationRadius can be used to set a minimum on the radius of geolocation filters applied. This specifically applies to filters that are provided in the filters parameter, both using $eq and $near.

For example; as mentioned above for $eq filters, Search will automatically compute a radius from the bbox property of the Mapbox response. After performing this calculation, if the resulting radius is less than the minLocationRadius set on the config, the radius will be increased to the minLocationRadius value.

However, locationRadius is still the final override for geolocation filter radiuses. Therefore, the priority ranking of ways we determine the radius of a geolocation filter is:

  1. locationRadius, if provided

  2. The greater of the radius calculated from the Mapbox bbox (for $eq) or provided in the filter (for $near), and minLocationRadius


boundingBox

The boundingBox property is a pair of lat/long points that represent opposite corners of a bounding box, which is used to limit the scope of places that are considered when using Filter Search (or when inferring location filters using inferred Filter). It is passed directly to the Mapbox Geocoding API endpoint .

Geolocation Mapbox Places


additionalSearchablePlaces

The additionalSearchablePlaces property can be used to override the default set of place types considered for Filter Search (or inferred Filter). Today, the only option this property accepts is “neighborhoods”, which will allow neighborhoods to be returned from Mapbox.

For example:

{
  "meta": {
    "uuid": "018582a0-a9cb-37ad-bf68-af477ec3f5db",
    "errors": []
  },
  "response": {
    "businessId": 0000000,
    "sections": [
      {
        "results": [
          {
            "key": "builtin.location",
            "value": "Williamsburg, New York City, New York, United States",
            "filter": {
              "builtin.location": {
                "$eq": "P-neighborhood.721145068"
              }
            },
            "matchedSubstrings": [{...}]
          },
          { ... }
    ],
    "failedVerticals": [],
    "queryId": "018582a0-a9db-3b76-4d0d-edf091c1fd57"
  }
}