Variants

Do you have products that come in multiple:

  • sizes
  • colors
  • region specific prices
  • region specific stock levels
  • … or all of the above?

These are all referred to as Variants.

A Variant can be visual - when we want to render this information on screen (such as the correct color). It can also be structural - for example, if we want to only show specific store pricing to a given customer.

This document is intended for clients who have products with visual variants and/or non-visual variant. The term variant refers to all items that roll up to a master SKU.

This document lays out the best practices for creating a compelling user experience when your catalog has a combination of variant and visually variant products.

The Variant Problem

Color variant

When a user comes to your store and searches for “red dress” they expect to see a result page full of red dresses.

Not yellow dresses, not red shoes. They do not want to see three identical products, one for each size.

Low Conversion:
Low Conversion:
High Conversion:
High Conversion:

In the above image, we can see a typical results page from a typical search tool that does not consider variants. All of the dresses in the low conversion section, actually have a red variant, or the word red in the product description. However, the master record is being displayed along with the master record image.

When the user sees a list of non-red dresses after a simple search for red dress, the trust in the website is greatly reduced. How can we expect a user to trust a site with their credit card if that site doesn’t understand this seemingly simple question?

While it is intuitively obvious to the end user that a search for red dress should bring back red dresses, the problem compounds when you consider the following flawed solutions:

  • Model for variants explicitly as stand-alone records and handle switching between different kinds of searches using regular expressions: complicated ETL and front-end code that is fragile and requires continuous maintenance.
  • Write front-end logic to handle variant reordering within one record - again, requires custom code and doesn’t take into account other factors of your search
  • Don’t reflect the visual variants - will reduce conversion

Stock or price variant

Frequently we need to maintain the same product with different metrics such as price or stock that differ for different regions. We don’t want to expose all of the stock or price options to our customers, while still retaining accurate navigation.

For example, if we have multiple price points, we need the engine to automatically and quickly suggest the possible price ranges for any given search and the given customer’s price rate.

This is critical, as showing the wrong rate to the wrong customer is highly detrimental to the business - both as the risk of reducing margin, or undermining the customer confidence if what is shown does not match the expectations.

The typical solutions to this include either complicated ETL, multiple records (which has higher overhead costs), and typically additional logic that’s maintained within the front-end.

Our solution

This problem is solved by using our engine’s understanding of relevancy together with the most common way to store variants: as children of a parent.

We will look at how to have the engine do the heavy lifting for both visual and non-visual variants.

Visual model

  {
    "title": "shirt",
    "visualVariants": [
      {
        "color": "red",
        "size": ["M","XL"]
      },
      {
        "color": "blue",
        "size": ["S","M"]
      }
    ]
  }

Non visual model

  {
    "title": "shirt",
    "pricingRate": [
      {
        "group": "corporate",
        "price": "5.99"
      },
      {
        "group": "individual",
        "price": "8.99"
      }
    ]
  }

Configuration

The fieldDefinition of ChildRecord is what gives us the power to support any of the above requirements.

Approach: Visual variants

We can use the ChildRecord model to automatically re-order subvariants within the record by relevancy. The kinds of business requirements this could meet is when we have multiple visual variants within one record.

This means that the front-end just needs to render the very first variant, and no business logic has to be stored in the rendering layer. The engine automatically ensures that the correct visual variant is first.

Once a field is denoted as a ChildRecord with an action of order, we can tell the engine to place the most relevant child records at the top:

Sample configuration

fieldDefinition: {name: "visualVariants", type: "ChildRecord", childAction: "Order"}

Benefits

This is exceptionally business friendly, as all the typical benefits of relevancy apply:

  • Synonyms and spell corrections that the merchandiser created will apply. This means a merchandiser can create a synonym for “maroon, red” and the correct visual variant will be automatically ordered to the top.
  • Biasing profiles will apply at child level: if we have multiple “red” variants of different fabrics, and a specific kind of fabric is biased for, this will affect the order.

The relevancy will be calculated using the entire sub-record, using the fields for refinement, or, if this was a search, using searchable fields defined within the sub-record. This relevancy will take into account the biasing profile that is being applied.

Example

For example, given the following record:

  {
    "title": "shirt",
    "visualVariants": [
      {
        "color": "red",
        "size": ["M","XL"]
      },
      {
        "color": "blue",
        "size": ["S","M"]
      }
    ]
  }

By default, searching for “blue” will bring back the full record, with the variants in the original upload order, as above.

By setting the childAction on visualVariants to Order the engine will place the most relevant child records at the top:

  {
    "title": "shirt",
    "visualVariants": [
      {
        "color": "blue",
        "size": ["S","M"]
      },
      {
        "color": "red",
        "size": ["M","XL"]
      }
    ]
  }

Approach: Non visual variants

We can use the ChildRecord model to filter to only the correct subvariant , so that only the correct pricing or stock count is returned.

The business use case is a situation where you could have multiple stores with different inventory counts, or pricing models in a B2B relationship, and you’d like to segregate some parts of the record from polluting the recall or relevancy.

The childAction of Filter will restrict the returned child records to just the matching ones, so that we only get the correct pricing back.

Sample configuration

fieldDefinition: {name: "pricingRate", type: "ChildRecord", childAction: "Filter"}

Benefits

We want to ensure that Corporate users only see their pricing, and Individuals only see theirs - and that there is no chance of an individual seeing the corporate rate.

By default, refining on pricingRate.group:“individual” will bring back the full record, which we don’t want as it would return the corporate pricing within the record.

The childAction of Filter will restrict the returned child records to just the matching ones, so that we only get the correct pricing back.

This is exceptionally fast and allows us to have thousands of different models within 1 record, without any additional overhead on the creation of the navigation or any impact to the search response time.

Example

For example, given the following record:

    {
      "title": "shirt",
      "pricingRate": [
        {
          "group": "corporate",
          "price": "5.99"
        },
        {
          "group": "individual",
          "price": "8.99"
        }
      ]
    }

By setting the childAction on pricingRate to Filter the engine will only return the filtered to price.

Using the data above, when refining on pricingRate.group:“individual”, the record returned would be:

   {
     "title": "shirt",
     "pricingRate": [
       {
         "group": "individual",
         "price": "8.99"
       }
     ]
   }

instead of the full record.

This means dynamic navigation and front-end rendering will not show the other pricing rates.

Approach: Both

You can blend both if you have custom pricing and visual variants.

The configuration is typically:

  • visual variant are the “parent”
  • non-visual variants are nested under

Example

Let’s combine the above snippets into one record:

  {
    "title": "shirt",
    "visualVariants": [
      {
        "color": "blue",
        "size": ["S","M"],
        "pricingRate": [
          {
            "group": "corporate",
            "price": "5.99"
          },
          {
            "group": "individual",
            "price": "8.99"
          }
        ]
      },
      {
        "color": "red",
        "size": ["M","XL"],
        "pricingRate": [
          {
            "group": "corporate",
            "price": "5.99"
          },
          {
            "group": "individual",
            "price": "8.99"
          }
        ]
      }
    ]
  }

The ChildRecord configuration for this record would look as such:

fieldDefinition: {name: "visualVariants", type: "ChildRecord", childAction: "Order"}
fieldDefinition: {name: "visualVariants.pricingRate", type: "ChildRecord", childAction: "Filter"}

Note how pricingRate is now a nested field under visualVariants.