Search Informal Landmarks and Local Aliases
The business problem
Ghanaians navigate by landmark, not street address, but landmark names are
often short, generic, and shared by dozens of unrelated places — "Market,"
"Junction," "Station" describe hundreds of locations each; "Circle" and "37"
are single words that mean one very specific place in Accra and nothing
useful anywhere else. A naive text search over landmark names returns a long,
unranked list of near-identical matches for exactly the queries that matter
most. This guide explains how GET /v2/landmarks/geocode actually ranks
results, and how to use its parameters instead of the raw query string to do
the disambiguation.
What AfriHex returns
Landmark search runs in one of two modes, and they rank results differently
— read data.query/data.anchor in the response to know which mode you got:
| Mode | Triggered by | Ranked by |
|---|---|---|
| Name search | q alone | score — 0–1 trigram (substring) similarity to the query text |
| Anchored search | near (a point) or anchor (a landmark name, geocoded first) | distance_m — metres from the anchor, closest first |
| Viewport search | bbox | Every landmark whose centroid falls in the box — no ranking, it's a map query, not a search |
bbox takes precedence over q/near/anchor if more than one is
supplied. There is no separate alias list — each landmark has one canonical
name (plus an optional name_local) — so disambiguating a generic word is
entirely a matter of which parameters you add, not a database of alternate
names to search against.
Before you begin
- Know which of the three modes fits your UI: a search box typically wants
name search; a "landmarks near me" list or a route corridor wants anchored
search; a map viewport wants
bbox. - Have a fallback anchor ready (device GPS, or the user's last known location) — name search alone on a generic word is close to useless without one.
Copyable request
A bare generic term, ranked only by text similarity — every "Market" in the
country is a plausible match, so score alone won't separate them:
curl "https://api.afrihex.com/v2/landmarks/geocode?q=market&limit=5" \
-H "X-API-Key: $AFRIHEX_API_KEY"
The same term, anchored to a point — now ranked by actual distance, which is what "which Market did they mean" really depends on:
curl "https://api.afrihex.com/v2/landmarks/geocode?q=market&near=5.556,-0.196&radius=2000" \
-H "X-API-Key: $AFRIHEX_API_KEY"
Full example response
{
"success": true,
"data": {
"query": "market",
"results": [
{
"id": 88,
"slug": "makola-market",
"name": "Makola Market",
"kind": "market",
"region_code": "GH-AA",
"source": "osm",
"confidence": 90,
"centroid": { "lat": 5.5497, "lng": -0.2115 },
"distance_m": 1840,
"street": "Kojo Thompson Road"
}
]
}
}
Field-by-field explanation
score(name search only) — trigram similarity, 0–1. A short generic word scores similarly against every landmark containing it — this field alone can't tell "Makola Market" from "Kaneshie Market"; addnear,anchor,kind, orregionto actually disambiguate.distance_m(anchored search only) — metres from yournear/anchorpoint. For a term like "Circle" or "37" — effectively unique within a region but ambiguous nationally — pairing a looseqwith aregionornearfilter is far more reliable than trying to make the text match more specific.confidence(0–100, integer) — how well-documented this landmark record is, independent of how well it matched your query. A landmark can scoreconfidence: 100and still not be the one your user meant ifscore/distance_msay it's a weak match. Don't confuse this withprovenance.confidence(0.0–1.0) elsewhere in the API — see Understanding Confidence and Verification for the full set of same-named-but-different fields.source(osm/field/user_submitted) — where the landmark record itself came from, not how sure the match is. This is a different vocabulary fromprovenance.source(device_gps/geocoded_text/etc.) used elsewhere in the API — the schema explicitly normalizes one to the other, but they're not literally the same field.kind— a coarse category (market,church,hospital, …). Cheap and effective disambiguation:q=station&kind=transportnarrows "Station" dramatically before distance or text similarity even get involved.
Error and edge cases
- Zero results for a well-known name. Landmark coverage is real but
incomplete (~130 photo-matched landmarks and growing, many more without
photos) — a genuine miss is possible, not necessarily a bad query. Fall
back to
GET /v2/search?q=(place/address search) as a second attempt — see Addresses & Geocoding. - Many equally-plausible matches for a generic term with no anchor.
Expected behaviour for words like "Market" or "Junction" — this isn't a bug
to work around with a smarter query string, it's the actual ambiguity of
the term. Require a
near/anchor/region/kindfilter in your UI before running the search, rather than trying to rank an inherently ambiguous list. anchor(a landmark name) doesn't resolve. It's geocoded first, using the same name search asq— if the anchor name itself is ambiguous or missing, the whole anchored search fails. Prefernear(a coordinate) overanchor(a name) whenever you already have a device location.- A
photo_urlshows a clearly wrong or foreign image. Known, flagged limitation — the name-based photo matcher isn't geo-verified yet (~130 landmarks affected). Treat photos as illustrative, not authoritative.
Production checklist
- Every generic-word search in your UI is paired with
near,anchor,region, orkind— neverqalone for short/common terms. - Zero-result landmark searches fall back to place/address search rather than showing an empty state.
-
score/distance_m/confidenceare shown to users (or used in ranking logic) as three separate signals, not blended into one number. - Landmark photos are labelled as illustrative, or hidden, until you've independently confirmed them for landmarks that matter to your flow.
Related endpoints / next guide
- Choose the Right Location Identifier — how a landmark compares to a coordinate, digital address, or hex code.
- Build a Delivery Address Capture Flow for Ghana — using a landmark pick as the human-readable part of a saved address.
- Route a Driver to the Correct Entrance — landmarks along a route corridor and in turn-by-turn narration.