Leverage variants and availabilities

This is for:

Developer

The way you define your commerce catalog data will determine which fields of the catalog object types you create can be associated to a filter when using facets.

When the structure of your queried catalog is simple (i.e., contains only products), then understanding which fields are available for facets is straightforward. You can create facets on all facet-enabled fields populated by items identified as products in the catalog.

However, if the structure of the queried catalog is more complex (i.e., contains products, variants, and/or availability channels), facets can affect multiple object types (see Facet association).

Tip
Leading practice

Ensure that a given field on which you want to create a facet is only defined for one type of object in the catalog.

This can be verified in the Content Browser (platform-ca | platform-eu | platform-au). For example, to test the color field, in the content browser search bar, enter @color and ensure that there’s only one value in the Object Type facet (e.g., Variant)

Facet association

The Facet Association tab lets you quickly view which facetable field names exist for each object type. The percentage shown represents the ratio of each field by object type. By hovering over the percentage shown, you can see the number of documents that contain the associated field name.

Note

Depending on your specific use case, if the percentages deviate from what you expect, this could be an indication that your data isn’t properly structured.

In advanced use cases, your data structure may require having the same facetable fields on multiple object types. For example, you may want to use the same language field across all your items. In this case, the value @language would need to appear on all object types (Product, Variant, and Availability) to return matching results.

To access the Facet Association tab:

  1. On the Catalogs (platform-ca | platform-eu | platform-au) page, click the catalog used by your search interface, and then click Edit in the Action bar.

  2. Select the Facet Association tab.

    You can edit the string options or advanced settings by selecting the desired field and clicking Edit Field.

The catalog automatically detects the fields that you can use to generate facets and checks for updates every 15 minutes. The last update time appears at the bottom right of the Field Association tab in your catalog.

Retrieve the available variant and availability fields

Use the GET endpoint to retrieve the variant.fields and availability.fields for a specific catalog. The variant and availability fields you’ll see in the response are fields you can create facets on, which are automatically selected by the catalog.

Example

You’ll get a response like this one:

{
  "availability": {
    "availableSkusField": "availableskus",
    "fields": [
      "availabilityid",
    ],
    "idField": "productid",
    "objectType": "Availability"
  },

// ...

  },
  "variant": {
    "fields": [
      "productsize",
      "width"
    ],
    "idField": "sku",
    "objectType": "Variant"
  }
}

Product filters for a specific channel

When filtering on products, users may want to locate a specific store that carries a certain product. Using the method of your choice, your site will need to determine which stores are the closest to the user. You must then retrieve the identifier associated to this store that matches the value from your catalog availability identifier field.

You can leverage this store identifier (i.e., store-123) in your search interface to filter on products that are only available in this store. Ensure you have properly configured your availability channels. The identifier must match the value set in the catalog’s availability identifier field.

Example

You’ve configured your catalog with the field availabilityid as the availability.idField in the following fashion:

{
   "name": "Multiple Channel Catalog",
   "product": ...,
   "variant": ...,
   "availability": {
       "idField": "availabilityid",
       "availableSkus": "availableskus"
   }
}

You then pushed availability items where the availabilityid field contains a unique identifier (i.e., store-123):

 {
    "availabilityid": "store-123",
    "lat": 45.4975,
    "long": -73.5687,
    "availableskus": ["001-red-8_wide","001-red-9_wide","001-red-10_wide","001-red-11_wide", "001-blue-8_wide"],
    "objecttype": "Availability"
 }

With both your items and catalog on the same availabilityid, you can therefore add the @availabilityid==store-123 query to filter on all products that are available in this store.

Availability constraints

If you have any availability constraints defined in your availability channel and in your data format from the source, it means you may want to filter on that specific channel. For instance, in a business-to-business scenario (B2B), we commonly see this availability constraint as being a price list, group, or entitlement. In a business-to-consumer scenario (B2C), this availability constraint could be a store.

Important

For this filter to work properly, your search interface must use a catalog configured with multiple channels.

The following code showcases how to add a filter in the query to only retrieve products that are available in your channel, in the context of the Coveo Atomic library search interface:

<head>
  <!-- ... -->
    <script type="module">
    import {loadAdvancedSearchQueryActions} from 'https://static.cloud.coveo.com/atomic/v2/headless/headless.esm.js'; 1

    function setAvailabilityFilter(engine) { 2
      const action = loadAdvancedSearchQueryActions(engine).updateAdvancedSearchQueries({ 3
        aq: '@availabilityid=<AVAILABILITY_ID>',
      });
      engine.dispatch(action);
    }

    (async () => {
      await customElements.whenDefined('atomic-search-interface');
      const searchInterface = document.querySelector('atomic-search-interface');

      await searchInterface.initialize({
        accessToken:'<ACCESS_TOKEN>',
        organizationId: '<ORGANIZATION_ID>'
        organizationEndpoints: await searchInterface.getOrganizationEndpoints('<ORGANIZATION_ID>')
      });

      const engine = searchInterface.engine; 4
      setAvailabilityFilter(engine); 5

      searchInterface.executeFirstSearch();
    })();
  </script>
  <!-- ... -->
</head>
1 Import the target loadAdvancedSearchQueryActions Headless action loader via the CDN.
2 Create a function that takes as input an engine instance and uses the imported action loader to dispatch an action to update the query expression sent to Coveo.
3 Retrieve an action using the updateAdvancedSearchQueries action loader. Utilize the aq property to specify a query filter by choosing the unique availability ID of the channel for which you wish to fetch products.
4 Access and store the engine in a variable.
5 Call the setAvailabilityFilter method to dispatch the action.

For more information on dispatching actions, see the Headless documentation.

Availability channel limitations

Having your availability channel uploaded to a separate source offers benefits when creating your commerce catalog, but once you’ve set up your catalog configuration, you can only access information from product objects in the search response, as result folding can only be done on either a product with variants or its availability, but not both. An alternative solution to surface availability information is to leverage dictionary fields on the product object from the Catalog source. Let’s explore two scenarios:

Scenario 1: Two source approach

On a standard search page, to filter products by availability, you use the two source approach by having your products and variants contained in one source and your availabilities in another. Your product and variant source metadata will look like this:

// Product metadata
{
   "documentId": "product://001-red",
   "FileExtension": ".html",
   "ec_name": "Coveo Soccer Shoes - Red",
   "model": "Authentic",
   "ec_brand": ["Coveo"],
   "ec_description": "<p>The astonishing, the original, and always relevant Coveo style.</p>",
   "color": ["Red"],
   "ec_item_group_id": "001",
   "productid": "001-red",
   "ec_images": ["https://myimagegallery?productid"],
   "gender": "Men",
   "ec_price_dict": {
        "": "28.00",
        "store1": "28.00",
        "store2": "30.00"
   },
   "ec_category": "Soccer Shoes",
   "objecttype": "Product"
 }

// Variant metadata

 {
   "documentId": "variant://001-red-8_wide",
   "FileExtension": ".html",
   "ec_name": "Coveo Soccer Shoes - Red / Size 8 - Wide",
   "sku": "001-red-8_wide",
   "productsize": "8",
   "width": "wide",
   "productid": "001-red",
   "objecttype": "Variant"
 }
//...

Your source for availability data will look like this:

{
    "documentId": "store://s000002",
    "ec_name": "Montreal Store",
    "lat": 45.4975,
    "long": -73.5687,
    "availableskus": ["001-red-8_wide","001-red-9_wide","001-red-10_wide","001-red-11_wide", "001-blue-8_wide"], 1
    "availabilityid": "s000002",
    "objecttype": "Availability"
 }
//...

Scenario 2: Single source approach

When you want to display availability information another way (e.g., you need to surface availability information on the product template to control visibility of the “add to cart” button to establish whether a product is available in a specific location), your availability information needs to appear in the same Catalog source as part of your product or variant data. You would index your data under a single source and add the availability data info using the dictionary field.

Your product, variant and availability source data contained in a single source will look like this:

{
    "title": "This is a product title",
    "documentId": "product://000001",
    "clickUri": "https://www.coveo.com/000001",
    "ec_brand": "Coveo",
    "objecttype": "Product",
    "ec_shortdesc": "This is a short descripton",
    "sku": "000001",
    "modelnumber": "000001",
    "ec_item_group_id": "2x8AC2",
    "subsite": "Coveo",
    "wordcount": 11,
    "ec_price": 15.79,
    "ec_promo_price": 15.79,
    "availablestores": "0001;0002;0003;0004;0005;0006;0007",
    "shippingoptions": {
        "": "Ship to Home;Ship to Store",
        "0001": "Ship to Home;Ship to Store",
        "0002": "Ship to Home;Ship to Store",
        "0003": "Ship to Store",
        "0004" : "Ship to Home;Ship to Store",
        "0005" : "Ship to Home",
        "0006" : "Ship to Home",
        "0007" : "Ship to Store"
    }
}
//...

The availablestores field contains the list of stores, which will be used for filtering. The shippingoptions object (dictionary field) contains info specific to a store.

Disable availability filtering

If your catalog contains availability channels and your commerce interface allows customers to disable availability filtering (i.e., the ability to view the products from all availability channels at once), you can use the AvailabilityFilterStrategy parameter to ensure that all products are returned in search results.

By default, if your catalog uses availability channels, only products referenced in at least one availability channel are displayed.

Changing the filter strategy ensures that all products matching the search criteria are displayed, even if no availabilityId is specified. This feature allows customers who disabled availability filtering to access the entire product catalog, regardless of whether the products are referenced in availability channels or not.

Whether this may apply to your website search interface depends entirely on your use case. It can be enabled after the catalog configuration.

Example

A retailer sets up their 1:1 catalog configuration and doesn’t have availability objects that contain all their products, regardless of location. By changing the AvailabilityFilterStrategy, a user would be able to query a catalog without a store location.

How to change the availability filter strategy

Currently, you can only disable availability filters on the catalog through the REST API. You’ll need to modify the AvailabilityFilterStrategy option in the catalog configuration. By default, the option is set to ALWAYS and will only return items that have availabilities. When changed to WHEN_SPECIFIED, it will only filter by availability, if an availability is specified in the search request. Otherwise, it won’t filter by availabilities.