Skip to main content
POST
/
api
/
storefront
/
v3
/
headless
/
recommendations
/
top
cURL
curl --request POST \
  --url https://storefront.glood.ai/api/storefront/v3/headless/recommendations/top \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --header 'x-shop: <x-shop>' \
  --data '
{
  "strategy": "BESTSELLERS",
  "view": "product_details",
  "strategy_options": {
    "sales_time_period": 7
  },
  "query": "<string>",
  "filter": {
    "variants": {
      "options": [
        {
          "name": "<string>",
          "value": "<string>"
        }
      ],
      "is_in_stock": true,
      "sku": [
        "<string>"
      ],
      "available_for_sale": true
    },
    "tags": [
      "<string>"
    ],
    "excluded_tags": [
      "<string>"
    ],
    "vendors": [
      "<string>"
    ],
    "product_types": [
      "<string>"
    ],
    "collections": [
      "<string>"
    ],
    "price": {
      "min": 123,
      "max": 123
    },
    "metafields": [
      {
        "namespace": "<string>",
        "key": "<string>",
        "value": "<string>"
      }
    ]
  },
  "facets": [
    "vendor"
  ],
  "pagination": {
    "cursor": "<string>",
    "limit": 50
  }
}
'
{
  "ok": true,
  "serve_id": "7c3f5e8a-2b14-49c1-a7d3-93f4e2bb1c8e",
  "strategy": "TRENDING",
  "products": [
    {
      "handle": "uno-usb-c-cable-100w",
      "product_id": 8123456789012,
      "title": "Uno USB-C to USB-C Cable 100W",
      "vendor": "UGREEN",
      "product_type": "Cable",
      "tags": ["cable", "usb-c", "fast-charge"],
      "is_available": true,
      "price": 9.34,
      "compare_at_price": 14.99,
      "image": "https://cdn.shopify.com/s/files/.../cable.jpg",
      "variants": [],
      "options": []
    }
  ],
  "pagination": {
    "cursor": "eyJzIjpbMC44Mzc3LCI4MTIzNDU2Nzg5MDEyIl0sInNlc3Npb24iOiI1NWRhNDYzOS01MjE2LTRhODItYjJjZS01MWE1NzJmYzM1YzQifQ==",
    "hasMore": true,
    "total": 327,
    "totalRelation": "eq",
    "limit": 24
  },
  "facets": {
    "vendor": [
      { "value": "UGREEN", "count": 142 },
      { "value": "Anker",  "count": 98 }
    ],
    "price": [
      { "min": 0,   "max": 50,  "count": 210 },
      { "min": 50,  "max": 100, "count": 78 },
      { "min": 100, "max": 250, "count": 39 }
    ]
  }
}

Documentation Index

Fetch the complete documentation index at: https://docs.glood.ai/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The top recommendations endpoint lets headless storefronts fetch products without a seed anchor — unlike /recommendations and /recommendations/automatic, no product_ids are required. It is the right endpoint for:
  • Catalog / collection landing pages (“Bestsellers”, “New arrivals”, “Trending now”)
  • Search results constrained by a strategy (e.g. trending products matching “wireless charger”)
  • Merchandising widgets that need filtered top-N lists with facet sidebars
The filter contract is identical to /recommendations/automatic — same filter shape, same Joi schema — extended with four additional dimensions (excluded_tags, collections, product_types, price). Those extensions are also accepted by the automatic endpoint going forward.
Authentication. Pass Authorization: Bearer <shop storefront token> and x-shop: <myshopify domain> on every call. See Get Started → Headless Authentication for token provisioning.

Ranking strategies

StrategyWhat it returns
BESTSELLERSProducts ranked by revenue over the last 7, 15, or 30 days (selectable via strategy_options.sales_time_period, default 7).
NEW_ARRIVALSMost recently published products.
TRENDINGProducts currently gaining popularity based on recent sales velocity and acceleration.

Filter dimensions

filter is fully optional. Each sub-field is independently optional and combined as an AND:
  • tags / excluded_tags — include / exclude by product tag.
  • vendors — vendor names (exact match).
  • product_types — product type values.
  • collections — collection IDs the product must belong to.
  • price.min / price.max — price range in shop currency.
  • variants.is_in_stock, variants.available_for_sale — variant-level availability (matches any variant).
  • variants.options[] — variant option matches (e.g. Color: Black).
  • variants.sku[] — variant SKU match.
  • metafields[] — match by {namespace, key, value}; requires a filterKey to exist on the indexed product.
Array or comma-separated string. The list-style fields tags, excluded_tags, vendors, product_types, and collections accept either a JSON array of strings or a single comma-separated string. Useful for clients whose query serializers can’t construct arrays from variables. Both forms below are equivalent:
{ "filter": { "tags": ["new", "sale", "featured"] } }
{ "filter": { "tags": "new,sale,featured" } }
Whitespace around commas is trimmed.

Text query

When query is provided, a multi_match clause is added across title^3, description, tags, vendor, productType with operator: AND, lenient: true. The strategy sort still wins — products matching the text query are ranked by sales (or recency / trending score), not by BM25 relevance. For relevance-first text search, use the AI Search endpoint instead.

Facets

Pass facets: ["vendor", "product_type", "tag", "price"] (any subset) to receive aggregations alongside the products. Each facet returns top values with counts. The price facet returns fixed buckets (0-50, 50-100, 100-250, 250+). Facet counts are computed using a post-filter model — each facet’s counts ignore that dimension’s filter so a sidebar UI can show “all available vendors” even when the user has selected one. Other filters still apply.

Pagination

Cursor-based, matching the rest of the v3 headless surface. The first request can pass pagination.limit (1–100, default 24). Subsequent pages pass the cursor returned in the previous response.
When paginating with a cursor, the filter, query, and strategy must stay identical to the request that produced the cursor — changing them invalidates the sort context and returns incoherent ordering.
The response includes pagination.total and pagination.totalRelation ("eq" or "gte"). Elasticsearch caps totals at 10,000 by default — when the relation is "gte", the real total is ≥ that value.

Examples

curl -sS -X POST 'https://storefront.glood.ai/api/storefront/v3/headless/recommendations/top' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <shop-storefront-token>' \
  -H 'x-shop: shop.myshopify.com' \
  -d '{
    "strategy": "BESTSELLERS",
    "view": "product_details"
  }'
{
  "ok": true,
  "serve_id": "7c3f5e8a-2b14-49c1-a7d3-93f4e2bb1c8e",
  "strategy": "TRENDING",
  "products": [
    {
      "handle": "uno-usb-c-cable-100w",
      "product_id": 8123456789012,
      "title": "Uno USB-C to USB-C Cable 100W",
      "vendor": "UGREEN",
      "product_type": "Cable",
      "tags": ["cable", "usb-c", "fast-charge"],
      "is_available": true,
      "price": 9.34,
      "compare_at_price": 14.99,
      "image": "https://cdn.shopify.com/s/files/.../cable.jpg",
      "variants": [],
      "options": []
    }
  ],
  "pagination": {
    "cursor": "eyJzIjpbMC44Mzc3LCI4MTIzNDU2Nzg5MDEyIl0sInNlc3Npb24iOiI1NWRhNDYzOS01MjE2LTRhODItYjJjZS01MWE1NzJmYzM1YzQifQ==",
    "hasMore": true,
    "total": 327,
    "totalRelation": "eq",
    "limit": 24
  },
  "facets": {
    "vendor": [
      { "value": "UGREEN", "count": 142 },
      { "value": "Anker",  "count": 98 }
    ],
    "price": [
      { "min": 0,   "max": 50,  "count": 210 },
      { "min": 50,  "max": 100, "count": 78 },
      { "min": 100, "max": 250, "count": 39 }
    ]
  }
}

Authorizations

Authorization
string
header
required

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Headers

x-shop
string
required

Shopify store URL

Example:

"shop.myshopify.com"

Body

application/json

Request body

strategy
enum<string>
required

Ranking strategy to apply

Available options:
BESTSELLERS,
NEW_ARRIVALS,
TRENDING
view
enum<string>
required

Response shape for each product entry.

Available options:
product_details,
product_ids
strategy_options
object

Strategy-specific tuning. Currently only BESTSELLERS uses this.

query
string

Optional free-text query. Applied as a multi_match across title, description, tags, vendor, and product_type. The strategy sort still wins; products matching the text query rank by sales/recency/trending score, not BM25.

filter
object

Same filter shape as /recommendations/automatic, extended with excluded_tags, collections, product_types, and price.

facets
enum<string>[]

Facet dimensions to return alongside the products. Facets are computed only when this array is non-empty.

Available options:
vendor,
product_type,
tag,
price
pagination
object

Response

Top recommendations

ok
enum<boolean>
Available options:
true
serve_id
string

Unique identifier for this serve.

strategy
string

Echo of the ranking strategy that produced the results.

products
object[]
pagination
object
facets
object

Present only when the request specified facets. Each requested dimension is a top-level key.