Types and attributes
Say what each entry of the catalog is and what its values mean, so "164 cm" filters as a width and "Samt" shows as velvet in English.
Every entity in the catalog has one type, such as product or category, and its properties are attributes, such as color and width. types.json says how each type is searched and shown, attributes.json what each value means. Here is the sofa SOFA-ASKA-2 on an English page:
curl -s 'http://127.0.0.1:7800/v1/product?id=SOFA-ASKA-2&locale=en' \
| jq -c '.product | (.details[] | select(.attribute | IN("material", "width", "seats"))),
(.variants[] | {id, color: .details[0].values})'{"attribute":"material","label":"Material","values":["Engineered wood","Velvet"]}
{"attribute":"width","label":"Width","values":[164],"unit":"cm"}
{"attribute":"seats","label":"Seats","values":[2]}
{"id":"SOFA-ASKA-2-GRAU","color":["Grey"]}
{"id":"SOFA-ASKA-2-SALBEI","color":["Sage"]}The catalog writes "Holzwerkstoff", "Samt", "164 cm", "Grau" and "Salbei". attributes.json makes them options with English labels, a width in centimeters and a color per variant.
Types
Each entity names its type, such as "type": "product". types.json lists the types a release searches, and for each what it searches, returns and lists:
{
"types": [
{
"type": "product",
"search": ["title", "brand", "keywords", "attributes.color", "description"],
"result": ["title", "url", "image", "price", "sale_price", "badges", "signals.rating"],
"details": ["color", "material", "upholstery", "width", "seats"]
},
{ "type": "category", "search": ["title", "keywords", "description"], "result": ["title", "url", "path"] }
]
}searchnames the searched fields in priority order (Fields and typos).resultnames the fields a hit returns, badges and signals such as the rating included.detailsnames the attributes a product page lists, in this order.
product, service, category, content and brand are built in. Any other code is a type of the merchant's own, with the capabilities it needs: variants, offers or tree. Only listed types are searched; an entity of another type is left out and reported.
Reference: types.json · capabilities · result · details
Attributes
An attribute says what one property's values mean: their type, their unit and, for an option, the values it knows. Here are the home store's color and width:
{
"attributes": [
{
"code": "color",
"type": "option",
"label": { "de": "Farbe", "en": "Color" },
"level": "variant",
"values": [
{
"code": "sage",
"label": { "de": "Salbei", "en": "Sage" },
"aliases": ["salbei", "salbeigrün", "sage green"],
"group": "green",
"swatch": "#9CAF92"
}
],
"groups": [{ "code": "green", "label": { "de": "Grün", "en": "Green" }, "aliases": ["grün", "grünes"] }],
"color_groups": true,
"filterable": true,
"detect_in_query": true
},
{
"code": "width",
"type": "quantity",
"label": { "de": "Breite", "en": "Width" },
"unit": "cm",
"filterable": true
}
]
}Each value has a label per locale, aliases for other spellings, a swatch and a group: sage shows under green. color_groups places a value without a group by the color words in its name, and level: variant lets the color differ between variants.
Both attributes are filterable, so pages offer them as facets. detect_in_query reads "graues Sofa" (grey sofa) as a filter by grey (How search understands a query).
Reference: type · values · groups · color_groups · filterable
How values are read
Each type reads what the catalog writes its own way:
type | The catalog writes | It becomes | Filters as |
|---|---|---|---|
option | "Grau", "GRAU", "salbeigrün" | The value it names: grey, sage | list, swatch |
quantity | "164 cm", "6 ft", 164 | 164, 182.88 and 164 in the attribute's unit | range, buckets, list |
number | 2, "1,5" | 2, 1.5 | range, list |
boolean | true, "ja", "nein" (yes, no) | true, false | toggle |
text | Free text | Searchable text | Never |
identifier | A GTIN or a model number | Text matched exactly | Never |
date and range are read too. A value that does not fit, such as a width in kilograms, is left out, its entity stays searchable without it, and the import report lists it.
In the panel, an import that leaves attributes.json out lists what it derived under Set up for you → Product details, each with Why. The panel does not change an attribute: its Filters and search step only chooses whether a detail is a filter, searched or not used.
Reference: unit
Spellings
A spelling is the value whose code, label or alias it matches, whatever its case, accents or ß: "Weiß", "weiss" and "WEISS" are all white. A spelling nobody listed becomes a value of its own, labeled as written, and the live index run's report lists it:
curl -s -H "Authorization: Bearer $key" $api/live \
| jq -c '.report.values.derived[] | select(.attribute == "color") | {value, label, groups, placed: .placed.by}'{"value":"klarglas","label":"Klarglas","groups":["clear"],"placed":"name"}
{"value":"rauchglas","label":"Rauchglas","groups":null,"placed":"nothing"}The pendant lamp comes in Klarglas (clear glass) and Rauchglas (smoked glass), which attributes.json does not list. color_groups placed Klarglas in the group clear by its name; Rauchglas names no color, so it stands alone in the color facet until the merchant gives it a group.
Reference: aliases · GET /api/v1/live
Slugs
A slug is a value's word in URLs, per locale. It is made once from the label and stored:
{ "code": "green", "label": { "de": "Grün", "en": "Green" }, "slug": { "de": "gruen", "en": "green" } }- CLDR's rules per locale: Grün is
gruenin German, Größe (size)groesse. - Kept when the label changes. A draft that renames a label keeps its slug. One that changes the slug keeps the old one in
slug_aliases, so old URLs still lead to the value. - One value per slug. A value nobody listed gets a numbered one, such as
gruen-2.
A release stored whole with POST $api/releases is taken as written: a value without a slug gets one made at every run, counted in values.unstored, since a new label would move its URLs.
Reference: slug · slug_aliases
Next
- Variants: products that come in colors and sizes.
- Channels: the locales labels and slugs are written in.
- The import report: every value left out or derived.