Overview
Layers supports geographic filtering and sorting against any product attribute typed as geo. Once an attribute is geo-typed, products carrying that attribute can be:- Filtered to only those within a radius, polygon, or bounding box of an origin.
- Sorted by distance from an origin (ascending or descending).
Configuring a geo attribute
A geo attribute is a catalog attribute that gets geographic data from a geo-typed product metafield or a field on a referenced metaobject.Supported attribute code patterns
For metaobject-reference sources, each referenced metaobject’s named field contributes a geo point, so a product can have many points, such as all retail locations that carry it. Filters and sorts consider all of a product’s points: a product matches if any point matches, and distance sorting uses the closest point.
Automatic detection for JSON metafields
Shopify does not have a native “geo” metafield type, so coordinates are typically stored inside ajson (or untyped) metafield. Layers samples these metafield values during catalog sync. If every non-empty sample parses as the same geometry type, Layers sets the attribute’s value type to geo automatically.
- Detection runs on the base
metafields.{namespace}.{key}code only. Metaobject-reference sources are typed from the metaobject field definition and don’t need sampling. - Every sampled value must parse as a recognized geo payload (see Accepted input shapes) and must share a single geometry type (
point,polygon, ormultipolygon). A mix of shapes leaves the attribute alone so you can decide how to model it. - Detection is one-way. Once an attribute has a specific value type (geo or anything else), Layers never reclassifies it. To change a value type, edit the attribute on the Attributes page.
- The check runs when Layers first discovers a metafield attribute from your catalog. It also runs one time per store against existing
jsonmetafield attributes on the release that ships this behavior, so existing stores start populating geo values on their next product sync with no manual attribute edit.
Geometry types
Accepted input shapes
The ingestion pipeline normalizes several common shapes into canonical GeoJSON before storing:GeoJSON coordinates are
[longitude, latitude] — the reverse of conversational lat, lng order. The shorthand { lat, lng } form is provided as a convenience.Polygon matching
When the source geometry on a product is itself a polygon, such as a delivery zone, the default behavior matches it when the filter polygon and product geometry overlap. This is useful for finding any zone that overlaps the search area. A stricter matching behavior requires the filter polygon to fully contain the product geometry. This is useful for finding zones entirely within the selected region. The matching behavior is determined by the attribute definition, so the semantics stay consistent across surfaces.Geo filter operators
Three new operators extend the filter expression language. Each takes a single payload object inside thevalues array.
All operators accept either
lat/lng or latitude/longitude (and lon) on coordinate fields. Bounding boxes also accept northEast/southWest camelCase corners.
Radius units
geoRadius accepts radius with a unit of m (meters, default), km (kilometers), or mi (miles):
radius_meters (or radiusMeters) form is still accepted and always means meters. If a request provides both forms, they must resolve to the same distance or the request is rejected.
The unit you send is echoed back on any pickup-location distances in the response. See Local pickup filtering.
Examples
Products within 5 km of a shopper’s location:Validation
Geo operator payloads are validated before the query runs:latmust be between -90 and 90;lngbetween -180 and 180.radius(orradius_meters) must be greater than 0.unitmust bem,km, ormi.- Polygon rings must be closed (first and last position equal) and contain at least 4 positions.
- Unsupported geometry types (e.g.
LineString) are rejected.
Sort by distance
Thegeo_distance sort order ranks products by distance from a given origin against a geo-typed attribute.
Multi-point products
When a product has multiple geo points, such as one per retail location, distance sorting uses the closest point. A product carried at three stores sorts by the closest of the three.Products without geo data
Products with no geo values for the geo attribute are placed in a separate tier that always sorts after all products with a distance, regardless ofdirection. This prevents missing-data products from polluting the top of the result set.
Pairing filters and sort
Filter and sort can target the same or different geo attributes. A common pattern is to filter by radius and sort by distance against the same attribute, so the result set contains every product within range, ordered from nearest to farthest:Local pickup filtering
Filter products by the Shopify locations where a variant is in stock and local pickup is enabled. Layers resolves eligible pickup locations at request time from the store’s synced locations, so the filter always reflects current inventory and pickup availability without any per-product ingestion. Use this to power “available for pickup near me” experiences. A shopper sets a search origin, and Layers returns only products with at least one variant available for pickup within the radius. The response includes each matching location’s name, address, and distance so you can render pickup badges without a second request.Filter operators
Thevariants.pickup_locations property accepts the following operators:
Geo operators are capped at a 100 km radius. Requests over the cap return HTTP 422 during validation.
If no pickup-enabled locations match the geo payload or supplied ids, the filter matches zero products. An empty
notIn list matches every product.
Example
Facet display
Whenvariants.pickup_locations is requested as a facet with retrieveFacetCount enabled, Layers returns a facetDisplay block describing each matching pickup location:
distanceis measured to the location’s coordinates from thegeoRadiusorigin, converted to the response unit, and rounded to 2 decimal places. When the filter does not include ageoRadius(for example, aninfilter),distanceisnullanddistanceUnitis still present.distanceUnitfollows theunitsupplied on the filter. When no explicit unit is set, Layers picksmiforUS,GB,LR, andMM(inferred fromcontext.geo.country) andkmeverywhere else.addressis always present. Empty strings are normalized tonull. Phone numbers are not exposed.facetDisplayis omitted when empty. When non-empty, it is returned even ifenrichFacetMetaobjectsisfalse.
Requirements
- Locations must be synced from Shopify with Local pickup enabled. Layers reads pickup settings, address, and coordinates from the standard location sync.
- The
variants.pickup_locationsattribute is created automatically. It is filterable everywhere but is not exposed as a storefront facet until you enable it on the Attributes page.
Ingestion behavior
Geo values are extracted from products during the catalog sync that powers searchable data:- For a
metafields.{ns}.{key}attribute, the metafield value itself is normalized as a geo value. - For a
metafields.{ns}.{key}.{field}attribute, every metaobject reference (single or list) contributes a geo point when its named field holds a geometry. - Malformed payloads are silently skipped — a single bad metaobject does not block ingestion for the rest.
- Layers records whether each geo value came from a metafield or metaobject and identifies the source metaobject when applicable. This makes per-product geo data inspectable.
Troubleshooting
A geo filter returns no products. Confirm the attribute is configured for geographic data and that the source metafield or metaobject field contains a recognized GeoJSON or{ lat, lng } payload. Check the most recent catalog sync ran after the geo data was added.
Distance sort puts unexpected products at the top. Products with no geo data sort last by design. If a clearly-far product appears first, verify the product’s geo points actually reflect the intended coordinates. For products with multiple points, distance is measured to the closest point, so a single incorrect coordinate can pull the product higher in results.
Polygon filter matches too aggressively. The attribute’s matching behavior controls this. The default behavior allows overlapping geometries, while stricter matching requires the filter polygon to fully contain the product geometry.
Coordinate ordering looks reversed. GeoJSON uses [lng, lat], not [lat, lng]. If you’re constructing GeoJSON by hand, double-check the order — using the shorthand { lat, lng } form avoids the mismatch entirely.
See also
- Filtering language — full filter expression grammar
- Catalog attributes — defining attributes from metafields and metaobjects
- Metaobjects and reference metafields — modeling locations and zones in Shopify
- Sort Orders — configuring sort orders in the Layers dashboard