Search suggestions (places, brands and categories)

getSearchSuggestions() answers "what might the user mean?" in one call. A query like "italian" means both a cuisine category and Ristorante Italiano down the road, and the call returns both in one ranked list. A complete query works as well as a partial one.

Type a few letters into the demo below. Places, brands and categories come back in one list. Pick a brand or category to search it in view.

Basic usage

import { getSearchSuggestions } from '@tomtom-org/maps-sdk/services';

const { suggestions } = await getSearchSuggestions({ query: 'italian' });

for (const result of suggestions) {
    if (result.kind === 'brand' || result.kind === 'category') {
        console.log(`Refine by ${result.kind}: ${result.title}`);
    } else {
        console.log(result.title, result.subtitles);
    }
}

Result kinds

Every result carries a kind. Narrowing on it tells you what else it carries.

Kind What it is Carries
place, address, street, area A location id, title, subtitles, distanceInMeters, resolve()
brand A refinement, which narrows the next query title, refineParams, refine()
category A refinement The same, plus category, its POICategory code

A location suggestion carries what a list needs, not the place. To get the full place with its geometry, call resolve() on the one the user picks:

const place = await result.resolve();
map.flyTo({ center: place.geometry.coordinates });

Acting on a refinement

refine() runs the follow-up search. A brand result searches that brand, and a category result searches that category. Both stay inside the original call's scope (its filters.countries, filters.boundingBox or geoBias). It works whichever endpoint produced the result:

const { suggestions } = await getSearchSuggestions({ query: 'shell' });
const brand = suggestions.find((result) => result.kind === 'brand');

if (brand) {
    const stations = await brand.refine();
}
const stations = await discoverPlaces({ ...brand.refineParams, limit: 50 });

Cost

Ranking

The SDK blends the list the way Places Search v3's suggest does:

Neither backend returns a score comparable with the other's, so this blend is the SDK's heuristic, not the API's.

Parameters

Parameters follow Places Search v3's suggest body. The full type is SearchSuggestionsParams. It also takes the options every service call takes.

Parameter Type Description
query string What the user typed. Required.
limit number Size of the merged list. Default 5, capped at 10.
filters.kinds SearchSuggestionKind[] Which kinds of result to return, and so which arms run. Default: every kind.
filters.boundingBox HasBBox Restricts results to a box: a [west, south, east, north] array, or a GeoJSON object or array of them, whose bounds are used. Search arm only. geoBias then measures distances but does not rank the places. A refinement keeps the box.
filters.countries string[] Restricts results by country. Both arms.
filters.poiTypes POICategory[] Restricts results by POI category. Search arm only.
filters.areaTypes GeographyType[] Restricts which administrative levels area results come from. Search arm only.
geoBias.position HasLngLat The point to search around. Ranks nearer results higher on both arms, unless a filters.boundingBox confines the search. distanceInMeters is measured from it.
geopoliticalView GeopoliticalView Defaults to the global one. See Geopolitical views.

The autocomplete arm accepts no category filter and no bounding box, so only the search arm gets them. A brand or category suggestion is therefore not category-filtered, because it is a concept, not a place.

Cancellation

Both arms share one signal, so aborting drops both. A slow arm can't resolve on its own and refill the list under a newer query. To keep only the newest keystroke's pair, use createLatestRequest:

import { createLatestRequest, getSearchSuggestions } from '@tomtom-org/maps-sdk/services';

const latestSuggestions = createLatestRequest();

searchBox.addEventListener('input', async () => {
    const response = await latestSuggestions.run((signal) =>
        getSearchSuggestions({ query: searchBox.value, signal })
    );
    if (response.current) showSuggestions(response.value.suggestions);
});

If either arm fails, the call rejects with an SDKError whose service is 'SearchSuggestions', instead of returning half a list.

Related guides and examples