The information displayed on the product detail page is driven by product and SKU properties and their values.
While the SearchAndNavigation
plugin provides all of the required code and configuration to display product name, description, price, and image for any type of product, the SKU pickers displayed for a product depend on the type of product itself. For example, a clothing product might show options for picking color and size while a furniture product might show options for picking wood finish. Because the SKU pickers on product detail pages are so tightly tied to the underlying data, generic instructions for how to create them cannot be provided. Instead, this section provides an example for you to follow by describing the code and configuration included in the B2CStore
module for rendering SKU pickers that are appropriate for its underlying sample data of clothing and furniture products.
Defining SKU Types and Their Properties
To configure SKU pickers for a given site, the product detail page must know:
The types of SKUs that belong to the products being displayed, for example, clothing SKUs and furniture SKUs.
The properties belonging to these SKU types that will be used to create a SKU picker, for example, color and size for a clothing SKU and wood finish for a furniture SKU. Note that these properties must match properties defined for the SKU types in the catalog repository.
The B2CStore
application module defines two SKU types: clothing-sku
and furniture-sku
. Two components in the B2CStore
module define the SKU properties that are used to create SKU pickers for these two types, /atg/commerce/catalog/sku/properties/ClothingSkuProperties
and /atg/commerce/catalog/sku/properties/FurnitureSkuProperties
. The properties files for these components are shown below.
ClothingSkuProperties
$class=atg.projects.store.sku.SkuTypeProperties $scope=global $description=Properties component used to define clothing SKU-related properties allowing the property names to be configured in component property files. # This is a list of properties that are used for building a SKU picker for this # SKU type. skuPropertyList=\ color,\ size
FurnitureSkuProperties
$class=atg.projects.store.sku.SkuTypeProperties $scope=global $description=Properties component used to define furniture SKU-related properties allowing the property names to be configured in component property files. # This is a list of properties that are used for building a SKU picker for this # SKU type. skuPropertyList=\ woodFinish
Both components are of class atg.projects.store.sku.SkuTypeProperties
, which is included in the SearchAndNavigation
plugin. This class contains a single property, skuPropertyList
, that defines the SKU properties that should be used to create pickers for the associated SKU type. In the case of B2CStore
, color
and size
properties are used to create SKU pickers for clothing SKUs while the woodFinish
property is used to create a SKU picker for furniture SKUs.
Informing the ProductDetails Cartridge Handler of the SKU Types
The content item that Experience Manager returns for the product detail page contains all of the information required for the initial page load including all of the product’s properties, the skuTypes
that the page must handle, and the SKU properties that are used to build the SKU pickers for the individual skuTypes
. The cartridge handler for the product detail page, namely the /atg/endeca/assembler/cartridge/handler/ProductDetails
component, uses its skuTypes
property to map each SKU type to the list of SKU properties that should be used to create a picker for that type. For example, in the B2CStore
, the skuTypes
property maps the clothing-sku
to the properties list defined by /atg/commerce/catalog/sku/properties/ClothingSkuProperties.skuPropertyList
and the furniture-sku
to the properties list defined in /atg/commerce/catalog/sku/properties/FurnitureSkuProperties.skuPropertyList
.
# Resolving Map that holds a map of the SKU types that will be served and any # unique properties that will be used for their corresponding SKU pickers. # The key for this map should be the identifier for the SKU type. skuTypes=\ clothing-sku^=/atg/commerce/catalog/sku/properties/\ ClothingSkuProperties.skuPropertyList,\ furniture-sku^=/atg/commerce/catalog/sku/properties/\ FurnitureSkuProperties.skuPropertyList
By including this configuration, additional SKU information is added to the content item to facilitate the rendering of the SKU pickers, namely childSkuType
and childSkuPickerProperties
.
"mainProductContent": [ { "metadata": { "keywords": "silk,dry,suede,buttons,newest,clean,blazer,fall,town,leather,", "description": "Greet fall with our newest suede blazer. Dry clean only.", "title": "CSA Store - Suede Blazer" }, "product": { "longDescription": "Greet fall with our newest suede blazer. Dry clean only.", "isAvailable": true, "salePrice": "84.0 - 99.0", "displayName": "Suede Blazer", "largeImageUrl": "/csadocroot/content/images/products/large/APP_SuedeBlazer_large.jpg", "repositoryId": "xprod2504", "childSkuType": "clothing-sku", "showSalePrice": false, "childSkuPickerProperties": [ "color", "size" ], "listPrice": "84.0 - 99.0" },
Note: The clothing-sku
and furniture-sku
types map to item-descriptors that are defined in the B2CStore
repository extensions.
Sku Picker Dependencies on B2CStore.Base Plugin Extensions
The SKU pickers described in the previous section also rely on some extensions made in the B2CStore.Base
module.
atg.projects.store.catalog.B2CStoreCatalogProperties
This class is an extension of the atg.projects.store.catalog.StoreCatalogProperties
class included in the Commerce Store Accelerator Base
module and it adds a new catalog property called sizePropertyName
and sets its value to size
. Instead of directly referencing the size property by name, other components use the getSizePropertyName()
method. This allows you to change the name of the size property in one location, if necessary, without having to modify other code that uses the size property. The /atg/commerce/catalog/custom/CatalogProperties
component in the B2CStore.Base
module is configured to use the B2CstoreCatalogProperties
class, thereby making the size property available to other components.
atg.projects.store.catalog.B2CstoreCatalogTools
This class is an extension of the atg.projects.store.catalog.StoreCatalogTools
class included in the Commerce Store Accelerator Base
module and it provides the CatalogTools
component with a number of additional methods for sorting lists of colors and sizes. The /atg/commerce/catalog/CatalogTools
component in the B2CStore.Base
module is configured to use this class. The component also defines the sizeSortOrder
property, which specifes the order in which lists of sizes should be presented. For B2CStore
, this order is:
sizeSortOrder=One Size, Small,Large,XS,S,M,L,XL,XXL,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20, 21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42
Sorting for colors is done alphabetically.
Creating the SKU Pickers
The process used to determine a SKU based on selections made in a SKU picker is application-specific and is not included in the SearchAndNavigation
plugin out of the box. The role of a SKU picker is twofold. First, the SKU picker is used to return a list of all available options for any child SKUs that exist for the product being rendered on the product detail page. This information is included in the content item returned for the request along with the rest of the product and SKU information. Secondly, the SKU picker responds to changes to the selected options on the client and, using the available information, attemps to find the matching SKU and return it back to the client. Several additional classes have been created in the B2CStore.Plugins.SearchAndNavigation
module to provide this functionality.
Based on the B2CStore
catalog, the minimum number of SKU pickers that could be present on the product detail page is 0, for a single SKU product, while the maximum is two, for a clothing SKU that has both color and size pickers. To accommodate this situation, the following classes were created:
atg.projects.store.sku.picker.DefaultSkuPicker
: This abstract class contains common functionality useful to all pickers and forms the basis of all SKU pickers in theB2CStore
.atg.projects.store.sku.picker.ColorSkuPicker
: This class extendsDefaultSkuPicker
and contains the logic for both locating a product’sclothing-sku
using the color selected in the SKU picker and for returning a list of all available colors for a product. This class is also used for selecting a product’sfurniture-sku
based on the selectedwoodFinish
(described in further detail below).atg.projects.store.sku.picker.SizeColorSkuPicker
: This class extends theColorSkuPicker
class and contains the logic for both locating a product’sclothing-sku
using the color and size selected in the SKU picker and for returning a list of all available sizes for a product. (Note that this class only returns the list of available sizes because theColorSkuPicker
class returns the list of available colors.)
The B2CStore.Plugins.SearchAndNavigation
module configures a set of SKU picker components using these classes.
ColorSkuPicker Component
The /atg/commerce/product/detail/ColorSkuPicker
component defined in the B2CStore.Plugins.SearchAndNavigation
module is of class atg.projects.store.sku.picker.ColorSkuPicker
. The configuration for this component is shown below:
$class=atg.projects.store.sku.picker.ColorSkuPicker $scope=prototype $description=A component used to to control the behaviour of a SKU picker that contains color options. # Instance of Catalog Tools. catalogTools=/atg/commerce/catalog/CatalogTools # Instance of ProductDetailTools. productDetailsTools=/atg/commerce/product/detail/ProductDetailsTools # Instance of skuPickerPropertyManager. skuPickerPropertyManager=/atg/commerce/product/detail/SkuPickerPropertyManager
The ColorSkuPicker
component also contains three additional properties, which are not configured here because appropriate defaults are specified for them in the class itself. These properties represent the keys that are used to identify the color property, the selected color, and the available colors in the Map
that is returned from the server when a picker change is made on the client:
colorPropertyName
: Defaults tocolor
.selectedColorPropertyName
: Defaults toselectedColor
.availableColorsPropertyName
: Defaults toavailableColors
.
These properties do not need to be adjusted if you are configuring a SKU picker for use with colors but they can be overriden to work with a different SKU property (for example, a wood finish property), as described in the next section.
WoodFinishSkuPicker Component
Furniture SKUs in the B2CStore
catalog can have a maximum of one SKU picker for selecting the furniture’s wood finish. The /atg/commerce/product/detail/WoodFinishSkuPicker
component defined in the B2CStore.Plugins.SearchAndNavigation
module is of class atg.projects.store.sku.picker.ColorSkuPicker
and its configuration is shown below:
$class=atg.projects.store.sku.picker.ColorSkuPicker $description=A component used to control the behaviour of a SKU picker that contains wood finish options. # Base this component on the ColorProductDetailsPicker component as they share # similar properties. $basedOn=ColorSkuPicker # Override the color-related properties in order to make this picker target # the wood finish-related properties. colorPropertyName=woodFinish selectedColorPropertyName=selectedWoodFinish availableColorsPropertyName=availableWoodFinishes
The WoodFinishSkuPicker
extends the ColorSkuPicker
component and inherits all of that component’s properties. However, the WoodFinishSkuPicker
overrides the default values of colorPropertyName
, selectedColorPropertyName
, and availableColorsPropertyName
to reflect the fact that this SKU picker works with wood finish-related SKU properties instead. Specifically, it sets colorPropertyName
to woodFinish
, selectedColorPropertyNames
to selectedWoodFinish
, and availableColorsPropertyName
to availableWoodFinishes
.
SizeColorSkuPicker Component
Like the WoodFinishSkuPicker
, the SizeColorSkuPicker
component extends the ColorSkuPicker
. Its configuration is shown below:
$class=atg.projects.store.sku.picker.SizeColorSkuPicker $description=A component used to to control the behaviour of a SKU picker with size and color options. # Base this component on the ColorSkuPicker component as they share similar # properties. $basedOn=ColorSkuPicker # Add 'One Size' (and its translations) to the helper property black list. helperPropertyBlackList=\ One Size
While the SizeColorSkuPicker
component is based on the ColorSkuPicker
component, it does override the $class
property to use atg.projects.store.sku.picker.SizeColorSkuPicker
instead. This class adds a number of additional properties that have defaults specified in the class definition. These properties represent the keys that are used to identify the size property, the selected size, and the available sizes in the Map
that is returned from the server when a picker change is made on the client:
sizePropertyName
: Defaults tosize
.selectedSizePropertyName
: Defaults toselectedSize
.availableSizePropertyName
: Defaults toavailableSizes
.
As with the ColorSkuPicker
, these properties do not have to be set if the SKU picker being selected has color and size properties. They can, however, be modified if required as demonstrated with the WoodFinishPicker
in the previous section. Some attention must be paid, however, if using this picker for other SKU types as some unexpected sorting can happen unless it is managed properly in the class methods.
The helperPropertyBlackList
property controls the display of the size chart hyperlink, which should be suppressed if a product only has only one size. This property ensures that a size chart link is not displayed for a product if the property values listed in the black list are the only values available to the picker. In other words, if One Size
is the only value available to the picker, do not display the size chart link.
Encapsulating the SKU Pickers and Controlling Access to Them
After the different types of SKU pickers required by the site are defined, they need a container to encapsulate them and control access to them. The /atg/commerce/product/detail/SkuPickers
component included in the B2CStore.Plugins.SearchAndNavigation
module fulfills these requirements. The SkuPickers
component encapsulates the SKU pickers in two different maps, shown below:
# Service map containing each of the available SKU pickers. These are keyed by # the unique SKU property name that a SKU picker would be generated for, for # example "color" for a clothing-sku. skuPickerMap=\ color=/atg/commerce/product/detail/ColorSkuPicker,\ size=/atg/commerce/product/detail/SizeColorSkuPicker,\ woodFinish=/atg/commerce/product/detail/WoodFinishSkuPicker # Service map that maps a SKU type to a particular product picker. Used to # retrieve the correct SKU picker when a REST call is made from the client. skuTypeToSkuPickerMap=\ clothing-sku=/atg/commerce/product/detail/SizeColorSkuPicker,\ furniture-sku=/atg/commerce/product/detail/WoodFinishSkuPicker
The skuTypeToSkuPickerMap
is keyed on the SKU item-descriptor which, in the case of B2CStore
, is clothing-sku
or furniture-sku
. The map is used to identify which SKU picker should be used to find a matching SKU for the passed SKU property value(s). The SKU property values are passed through a REST request whenever a change is made to a SKU picker on the product detail page in the browser.
The skuPickerMap
is keyed on a SKU property which should match one of the properties defined in the skuPropertyList
of either the /atg/commerce/catalog/sku/properties/ClothingSkuProperties
or /atg/commerce/catalog/sku/properties/FurnitureSkuProperties
components. This map is used by the SkuSelector
component, described below, to retrieve the correct SKU picker to use for generating a list of all available options for the passed SKU property, for example, a list of all colors associated with the color
SKU property.
SkuSelector Cartridge Handler
While the /atg/endeca/assembler/cartridge/handler/ProductDetails
cartridge handler handles the addition of product (and some SKU) properties to the content item returned by the server, it does not include the construction of data objects required for building and rendering SKU pickers on the product detail page. This task is handled by the /atg/endeca/assembler/cartridge/handler/SkuSelector
component. This component is of class atg.projects.store.assembler.cartridge.handler.SkuSelectorHandler
, which is a class included in the SearchAndNavigation
plugin out of the box. The component itself, however, must be configured in the application module. The configuration included in the B2CStore
module is shown below:
$class=atg.projects.store.assembler.cartridge.handler.SkuSelectorHandler $description=Store-specific version of the product details handler. $scope=prototype # Import properties. $basedOn=/atg/endeca/assembler/cartridge/handler/ProductDetails # Instance of SKU Picker Property Manager. skuPickerPropertyManager=/atg/commerce/product/detail/SkuPickerPropertyManager # Instance of SkuPickers which contains the service map that holds the # different sku pickers that are available. skuPickers=/atg/commerce/product/detail/SkuPickers # Remove any configured Content Item Modifiers. contentItemModifiers^=/Constants.NULL
The SkuSelectorHandler
class is an extension of the atg.projects.store.assembler.cartridge.handler.ProductDetailsHandler
class. Also, the SkuSelector
component as configured in B2CStore
is based on the ProductDetails
component and inherits all of that component’s configuration. The portion of the configuration that the SkuSelector
component overrides is:
skuPickerPropertyManager
:This property maps to a component that provides the property identifiers that are used when transferring the currently selected options (color
,size
andwoodFinish
) between the server and the client.skuPickers
:TheSkuPickers
component to use for choosing the appropriate SKU picker for a request.contentItemModifiers
:contentItemModifiers
are used to apply Bean filters to any repository items included in the response (for example, products). TheSkuSelectorHandler
does not return repository items, therefore keeping thecontentItemModifiers
property as it is configured in theProductDetails
component would have no effect. For this reason, this property is set toNULL
.
The SkuSelectorHandler
component builds the SKU picker data objects and adds them to the ProductInformation
content item list in the content item returned by the server for the product details page. An example of this data is shown below:
"ProductInformation": [ { "endeca:auditInfo": { "ecr:resourcePath": "/content/Web/Product Detail Pages/Default Product Detail Page", "ecr:innerPath": "mainProductContent[0]/ProductInformation[0]" }, "name": "SKU Selector", "metadata": { "keywords": "silk,dry,suede,buttons,newest,clean,blazer,fall,town,leather,", "description": "Greet fall with our newest suede blazer. Dry clean only.", "title": "CSA Store - Suede Blazer" }, "@type": "SkuSelector", "skuPickers": [ { "options": [ "Black", "Blue", "Olive" ], "type": "color", "value": null }, { "options": [ "S", "M", "L", "XL", "XXL" ], "helperInformation": { "type": "sizeChart", "contentUrl": "SizeChart.html" }, "type": "size", "value": null } ] },
In the example above, you can see a skuPickers
array that has been created for a clothing-sku
that has both color and size options. The skuPickers
array contains two objects, each representing a SKU picker, one for color and one for size. Each SKU picker object contains a list of available options as well as the SKU picker type and the currently selected value
. In this case, the value
is set to null because no option has been selected. In cases where only a single option exists for the picker, the value
property is set to that single option.
Also seen in this example is the addition of the size chart information included in the helperInformation
object of the size SKU picker. This portion of the data structure defines that the size chart will only appear for the size picker.
Configuring Helper Information
Helper information can come in many forms. The example included in the B2CStore
is a link to a size chart for the shopper to reference while choosing clothing products. While the size chart itself is found in an HTML file, ensuring that it is included for rendering within the correct SKU picker is configured using the /atg/commerce/product/detail/ProductDetailsPropertyManager
component in the B2CStore.Plugins.SearchAndNavigation
module.
$description=Properties component used to define product detail related properties allowing the property names to be configured in component property files. # ResolvingMap keyed by the SKU properties that, if present in a product's child # SKUs, will trigger the inclusion of additional information in the response to # the Product Detail Page. In this case, when there is a size property present # the URL for the size chart will be made available to the modal window. additionalInformationProperties+=\ size^=/atg/commerce/catalog/custom/SizeChart.additionalInformationMap
In this example, the additionalInformationProperties
map is populated with an entry for the size
property. This entry maps to the additionalInformationMap
property of the /atg/commerce/catalog/custom/SizeChart
component, shown below:
$class=atg.projects.store.product.detail.AdditionalInformationProperty $scope=global $description=Properties component used to define size chart related properties, allowing the property names to be configured in component property files. # Map containing the information required for including the Size Chart on the # Product Detail Page. additionalInformationMap+=\ type=sizeChart,\ contentUrl=SizeChart.html
The SizeChart
component is based on the atg.projects.store.product.detail.AdditionalInformationProperty
class and contains a single property called additionalInformationMap
that has been populated with two entries:
type
: Text string used to identify the size chart. This string can be used as a lookup key to retrieve a locale-specific label for the size chart hyperlink rendered on the product detail page.contentUrl
: The path to the HTML file that contains the markup for rendering the additional information.
REST Object Examples
The following examples show what the REST objects look like as requests are being sent to the server and responses are sent back to the client.
// Object sent to server when Black/S are selected for a Suede Jacket { "selectedColor": "Black", "selectedSize": "S", "productIdPropertyName": "xprod2504", "type": "clothing-sku" } // Object containing matching SKU received from server { "selectedSku": { "showSalePrice": false, "type": "clothing-sku", "repositoryId": "xsku2504_4", "isAvailable": true, "size": "S", "id": "xsku2504_4", "color": "Black", "listPrice": 84, "displayName": "Suede Blazer", "inStock": true } }