Skip to main content

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).
Use this to power experiences like “stores near me”, “products available in this delivery zone”, or “tours within the highlighted region on the map”. Geo data is stored in a dedicated PostGIS-backed sidecar table and queried via spatial indexes, so geo filters and sorts run at the same scale as the rest of the catalog.

Configuring a geo attribute

A geo attribute is a catalog attribute whose value_type is set to geo. Geo attributes are sourced from product metafields or referenced metaobjects.

Supported attribute code patterns

For metaobject-reference sources, every referenced metaobject’s named field contributes one row — a product can have many geo points (e.g. all retail locations that carry it). Filters and sorts use EXISTS / MIN() semantics so a product matches if any of its geo rows match.

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 match mode

When the source geometry on a product is itself a polygon (e.g. a delivery zone), you can configure whether the filter polygon must contain the product polygon or merely intersect it: This setting lives on the attribute definition, not on the filter request, so the matching semantics are consistent across surfaces.

Geo filter operators

Three new operators extend the filter expression language. Each takes a single payload object inside the values array. All operators accept either lat/lng or latitude/longitude (and lon) on coordinate fields. Bounding boxes also accept northEast/southWest camelCase corners. Radius can be supplied as radius_meters or radiusMeters.

Examples

Products within 5 km of a shopper’s location:
Products inside the visible map viewport:
Products whose delivery zone covers a hand-drawn region:

Validation

Geo operator payloads are validated before the query runs:
  • lat must be between -90 and 90; lng between -180 and 180.
  • radius_meters must be greater than 0.
  • Polygon rings must be closed (first and last position equal) and contain at least 4 positions.
  • Unsupported geometry types (e.g. LineString) are rejected.
A geo filter against a non-geo attribute, a missing attribute, or a malformed payload matches zero products rather than erroring on the whole request.

Sort by distance

The geo_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 rows (e.g. one per retail location), the distance used for sorting is the minimum distance across all rows. A product carried at three stores sorts by the closest of the three.

Products without geo data

Products with no rows for the geo attribute are placed in a separate tier that always sorts after all products with a distance, regardless of direction. 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:

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 and stored as one row.
  • For a metafields.{ns}.{key}.{field} attribute, every metaobject reference (single or list) contributes one row per metaobject whose named field holds a geometry.
  • Malformed payloads are silently skipped — a single bad metaobject does not block ingestion for the rest.
  • Each row records its source (metafield or metaobject) and a source_ref (the metaobject ID), making per-product geo data inspectable.
Shopify Locations also gain a generated geography column during the standard location sync, ready for future location-backed filtering features. No action is required to opt in.

Troubleshooting

A geo filter returns no products. Confirm the attribute’s value_type is geo 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 rows actually reflect the intended coordinates — multi-point products use MIN(distance) so a single bad row pulls the product up. Polygon filter matches too aggressively. The attribute’s polygon_match mode controls this. Switch from intersects (the default) to contains if you want only fully enclosed product geometries to match. 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