Cognito Search
Go to App

Products

Products feed

Products are the main searchable catalog of an e-shop — the items returned by the search widget and the recommendations API. Register the feed as a source of type Products.

Structure

  • Root element: <items>
  • Item element: <item> (zero or more)
<?xml version="1.0" encoding="UTF-8"?>
<items>
<item>
<title>Aspirin 500 mg, 20 tablets</title>
<shop_item_id>SKU-12345</shop_item_id>
<url>https://shop.example.com/aspirin-500</url>
<availability>42</availability>
<price>89 Kč</price>
<price_old>109 Kč</price_old>
<availability_rank_text>In stock</availability_rank_text>
<category primary="true">Pain &amp; fever | OTC medicines</category>
<category>Health supplements</category>
<brand>Bayer</brand>
<image_link_s>https://shop.example.com/img/asp-s.jpg</image_link_s>
<image_link_m>https://shop.example.com/img/asp-m.jpg</image_link_m>
<image_link_l>https://shop.example.com/img/asp-l.jpg</image_link_l>
<description><![CDATA[Fast pain relief, <strong>500 mg</strong> tablets.]]></description>
<parameters>
<param>
<name><![CDATA[Active substance]]></name>
<value><![CDATA[Acetylsalicylic acid]]></value>
</param>
<param>
<name><![CDATA[Pack size]]></name>
<value><![CDATA[20 tablets]]></value>
</param>
</parameters>
<labels>sale,new</labels>
<product_code>ASP-500-20</product_code>
</item>
</items>

DTD

<!ELEMENT items (item*)>
<!ELEMENT item (title, shop_item_id, url, availability, price, price_old?, availability_rank_text?, category*, brand?, image_link_s?, image_link_m?, image_link_l?, description?, parameters*, labels?, product_code?)>
<!ATTLIST item language CDATA #IMPLIED>
<!ELEMENT title (#PCDATA)>
<!ELEMENT shop_item_id (#PCDATA)>
<!ELEMENT url (#PCDATA)>
<!ELEMENT availability (#PCDATA)>
<!ELEMENT price (#PCDATA)>
<!ELEMENT price_old (#PCDATA)>
<!ELEMENT availability_rank_text (#PCDATA)>
<!ELEMENT category (#PCDATA)>
<!ATTLIST category primary (true|false) "false">
<!ELEMENT brand (#PCDATA)>
<!ELEMENT image_link_s (#PCDATA)>
<!ELEMENT image_link_m (#PCDATA)>
<!ELEMENT image_link_l (#PCDATA)>
<!ELEMENT description (#PCDATA)>
<!ELEMENT parameters (param*)>
<!ELEMENT param (name, value*)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT value (#PCDATA)>
<!ELEMENT product_code (#PCDATA)>
<!ELEMENT labels (#PCDATA)>

Children must appear in the order shown above.

Elements

ElementRequiredTypeSearchedMeaning
titleyestextyesProduct name. Full-text and prefix (as-you-type) searchable. An item with an empty title is skipped.
shop_item_idyestextnoYour unique product identifier. Returned as externalId and used as shopItemId by the recommendations API. An item with an empty id is skipped.
urlyestextnoLink to the product page.
availabilityyesintegernoStock indicator as a whole number (e.g. units in stock; 0 = unavailable). In-stock items rank higher. A non-numeric value is treated as 0.
priceyestextfilterPre-formatted price string, shown verbatim (e.g. "89 Kč"), and also read as a number for the price filter. See Prices below.
price_oldnotextnoOriginal price before a discount. Stored and returned verbatim alongside price, and shown struck through next to it in the widget. Never read as a number.
availability_rank_textnotextnoHuman-readable availability label (e.g. "In stock", "Skladem"). Returned with the result.
categorynotext—Category name; repeatable; optional primary attribute. See Categories and the primary flag. Matched against a Categories feed's hierarchy to resolve a URL.
brandnotext—Single brand name. Matched against a Brands feed to resolve a URL. An empty <brand> is ignored.
image_link_snotextnoSmall image URL.
image_link_mnotextnoMedium image URL.
image_link_lnotextnoLarge image URL.
descriptionnotextyesProduct description; HTML allowed (wrap in CDATA). Indexed as the result's annotation.
parametersnoelementyesAttribute name/value pairs; repeatable. Searchable but not returned. See Parameters below.
labelsnotextfilterComma-separated merchant tags (e.g. akce,novinka,bio). Shown on the result and offered as a checkbox filter. Used verbatim. See Labels below.
product_codenotextnoManufacturer/product code, SKU, or EAN. Used for exact-match lookups and shown in click analytics. Optional in the schema, but strongly recommended — omit it and those lookups cannot match.

Prices

<price> is what the shopper sees: whatever you send is stored and displayed verbatim, currency and all. On top of that we read a number out of it, which is what the price filter — the range slider with the histogram above it — runs on.

<price>9 999 Kč</price>

Rules:

  • The formatting is yours. Every kind of space is ignored, including the non-breaking space, so 9 999 Kč, 9999 Kč and 9999Kč are the same 9999.
  • Thousands and decimals are worked out from the value itself, not from a locale setting. A . or , followed by exactly one or two digits is the decimal point; everything else is a group separator. So 1 299, 1.299 and 1,299 are all 1299, while 19,99 and 19.99 are both 19.99. Two decimal places are the limit.
  • The currency comes from the feed. Whatever follows the number — Kč, CZK, € — is kept as the label the filter shows. Send one currency per feed: a feed that mixes them gets a filter with no currency label, because labelling euro amounts "Kč" would be worse than saying nothing.
  • 0 means "price not stated". A product priced at 0 is still imported and still displayed as you sent it, but it is left out of the filter entirely — out of the range, out of the histogram, and never returned by a price range. Otherwise a handful of zero-priced items would drag the low end of every slider down to nothing.
  • A price we cannot read costs nothing else. cena na dotaz, od 39 Kč, 39 Kč / ks — the product imports, ranks and displays exactly as before, it simply does not take part in the price filter. There is no error and no rejected item.
  • price_old is display only. It is never parsed, and nothing is derived from it — a discount is a label you send, not something we infer.

The filter appears only where an admin has placed the Price filter block in the Visual settings, and only for product results: articles, categories and brands carry no price.

Parameters

Products often carry attributes that never appear in the title or the description — grape variety, volume, active substance, pack size. Send them as <parameters> and customers can find the product by that content: a search for nebbiolo will return a wine whose only mention of it is Grape variety: Nebbiolo.

<parameters>
<param>
<name><![CDATA[Grape variety]]></name>
<value><![CDATA[Nebbiolo]]></value>
</param>
<param>
<name><![CDATA[Volume]]></name>
<value><![CDATA[0,75 l]]></value>
</param>
</parameters>

Rules:

  • Entirely optional. A feed with no <parameters> behaves exactly as it does today. Nothing about your existing results changes.
  • Position matters. <parameters> goes after <description> and before <labels>. The content model is ordered, so a wrapper placed anywhere else fails validation — and validation is all-or-nothing, so one misplaced wrapper rejects the whole feed, not just that item.
  • Group them however you like. One <parameters> holding many <param>, or one <parameters> per <param> repeated — both are accepted and produce the same result.
  • Names may repeat within one product. Award three times gives you three pairs; nothing is merged or deduplicated.
  • A <param> needs a non-empty <name> and <value>. One that doesn't is skipped on its own — the product still imports and the rest of its parameters are kept.
  • Units belong in the value. There is no unit element: write 0,75 l, 13 %, 20 tablets. Values are free text and are indexed as written.
  • Limits per product: 100 pairs, 500 characters per name, 500 per value. Anything beyond is truncated, never rejected.

What parameters do not do yet:

  • They are not returned in search results and are not displayed by the widget. They affect matching and ranking only.
  • They are not filters or facets. You cannot yet ask for "all wines where Volume = 1,5 l" — a parameter search is a text match, so it can also match a product that merely mentions those words elsewhere in its parameters.
  • A parameter match ranks below a title match. Parameters help a product be found; they do not push it above products that match by name.

Because names are indexed exactly as you send them, consistency pays off: Grape variety and Grape varieties are two unrelated strings to the search engine, not one attribute.

Labels

A product may carry merchant-defined tags — akce, novinka, bio. Send them as one comma-separated <labels> element and they appear as badges on the result and as a checkbox filter in the search panel.

<labels>akce,novinka,bio</labels>

Rules:

  • Entirely optional. A feed with no <labels> behaves exactly as it does today.
  • Position matters. <labels> goes after <parameters> and before <product_code>. As with <parameters>, the content model is ordered and one misplaced element rejects the whole feed.
  • The text is used verbatim. It is what the shopper sees, so send it in the item's language (the language attribute). Nothing is translated, renamed or reordered by us.
  • Nothing is derived, either. If you want a "Sale" badge, send it as a label — it is not inferred from price_old. Whether an item is on sale is your call, and a label you send is one you can also rename or switch off without waiting on a release.
  • Whitespace is trimmed, empties dropped, exact duplicates removed. akce, ,bio,akce becomes akce and bio.
  • Case is significant. Akce and akce are two different labels, because only you know which spelling the shopper should see.
  • Up to 50 labels per product, each up to 100 characters. Anything beyond that is truncated; the product still imports.

Keep the vocabulary small and stable. Every distinct value becomes a checkbox in the panel, and the filter shows the 50 most common — a label unique to one product helps nobody find anything.

Selecting several labels widens rather than narrows: a product shown matches at least one of the checked labels.

Multiple languages

The <item> element accepts an optional language attribute, so one feed can carry every language version of your content — including per-market prices, URLs and availability. Omit it and the record uses the instance's default content language.

See Multi-language feeds.