Get Attribute Options
About
The attributeOptions query returns attribute option values — the individual entries behind a select, multiselect, or checkbox attribute, such as Red, Green, Large.
The query is not scoped to an attribute. It pages through every option in the catalog, so Red from Colour and Large from Size arrive in the same list with nothing on a node to say which attribute it belongs to. To read the options of one attribute, query that attribute instead and select its options connection — see Get Attribute.
Use this query when a client wants the whole option set at once, typically to build a lookup table of option ID to label that it can reuse across screens.
Arguments
| Argument | Type | Required | Description |
|---|---|---|---|
first | Int | ❌ No | Number of options to return from the start (forward pagination). Default: 10 |
after | String | ❌ No | Cursor to start after for forward pagination. |
last | Int | ❌ No | Number of options to return from the end (backward pagination). Default: 10 |
before | String | ❌ No | Cursor to start before for backward pagination. |
There is no argument to filter by attribute, by swatch type, or by label.
Possible Returns
| Field | Type | Description |
|---|---|---|
edges | [AttributeOptionEdge] | Option edges for the current page. |
edges.node | AttributeOption | A single option — fields below. |
edges.cursor | String! | Cursor for this option, used as after on the next request. |
pageInfo | AttributeOptionPageInfo! | Pagination metadata. |
pageInfo.hasNextPage | Boolean | Whether more options follow the current page. |
pageInfo.hasPreviousPage | Boolean | Whether options precede the current page. |
pageInfo.startCursor | String | Cursor of the first option on the page. |
pageInfo.endCursor | String | Cursor of the last option on the page. |
totalCount | Int! | Total options across every attribute in the catalog. |
AttributeOption Fields
| Field | Type | Description |
|---|---|---|
id | ID! | IRI-style identifier (/api/shop/attribute-options/{id}). |
_id | Int! | Numeric option ID. This is the value to send when filtering products. |
adminName | String | Admin-facing option name. Use translation for the shopper-facing label. |
sortOrder | Int | Display order within the option's own attribute. |
swatchValue | String | Hex colour for a colour swatch, or the text value. null when the attribute uses no swatch. |
swatchValueUrl | String | URL of the swatch image, for image swatches. |
translation | AttributeOptionTranslation | The option's label in the current locale. |
translations | AttributeOptionTranslationCursorConnection | The option's label in every locale. |
Translation Fields
| Field | Type | Description |
|---|---|---|
id | ID! | IRI-style translation identifier. |
_id | Int! | Numeric translation ID. |
attributeOptionId | String! | ID of the option this translation belongs to. |
locale | String! | Locale code, e.g. en, ar. |
label | String | Translated label for the option. |
Use Cases
1. Caching an option-ID lookup table
A client that renders filters and product attribute values keeps hitting the same option IDs. Page the full set once and cache it:
query optionLookup($after: String) {
attributeOptions(first: 100, after: $after) {
edges {
node {
_id
adminName
swatchValue
translation {
label
}
}
cursor
}
pageInfo {
hasNextPage
endCursor
}
totalCount
}
}Repeat with the returned endCursor while hasNextPage is true.
2. Resolving an option ID that came back on a product
A product's attributeValues carry option IDs rather than labels. A cached lookup built from this query turns those IDs into text without a request per product.
3. Reading the options of one attribute
This query cannot do it — use Get Attribute and select its options connection, which returns only that attribute's values in their configured order.
Best Practices
- Do not use this to populate one attribute's control — the result spans every attribute and carries no attribute reference, so a colour picker built from it would list sizes too; query the attribute directly instead
- Page with
firstandafter— the default page is 10 options, which is smaller than most single attributes - Never pass a made-up cursor — an
aftervalue that did not come from a previous response fails the request outright rather than returning an empty page - Show
translation.label, notadminName—adminNameis the internal admin label and is never translated - Cache the result — options change only when a merchant edits an attribute, so the whole set caches well and saves a request per screen
Error Scenarios
| Scenario | Cause |
|---|---|
| Invalid cursor | The after or before value is not a cursor returned by a previous response. |
Related Resources
- Get Attribute - One attribute with its own options
- Attributes - List every attribute
- Category Attribute Filters - Filterable attributes for one category
- Pagination Guide - Cursor pagination documentation
- Shop API Overview - Overview of Shop API resources

