Providing customers with easy to navigate select option is crucial in driving conversions. In catalogs with varied product assortment it bring a challenge as there could be alternative representations apart from "textual options" that can be more effective. For example consider "colour". It is much easier to depict colour as colour boxes which actually depict that colour rather than having a textual representation. Talking on the subject of colour it is also worth to note that number of options could extend into millions. Usually customers when shop only interested in "main colours" palette and therefore not the challenge is not only depicting colour boxes to ease selection but also no narrow selection options.
The configuration of such complex scenarios is already solved in the platform's PIM, so this article will only focus on configuration of the UI through CMS in order to achieve customisation that is required at the presentation layer.
This cookbook aims to provide working examples in the following key areas:
For configuring a filter navigation template please consult product type and filter navigation documentation.
<% // [SHOP_CODE]_variant_ProductsNavBlock_color_map use 'color_map' as template in product type attributes template def _filteredNavBlock = binding.hasVariable('filteredNavBlock') ? filteredNavBlock : null; // int _filteredNavBlockLimit = binding.hasVariable('filteredNavBlockLimit') ? filteredNavBlockLimit : 25; if (_filteredNavBlock != null) { // Color mapping from _filteredNavBlockValue.value to RBG def _colors = [ 'black':'#000000', 'night':'#0c090a', 'gunmetal':'#2c3539', 'midnight':'#2b1b17', 'charcoal':'#34282c', 'darkslategrey':'#25383c', 'oil':'#3b3131', 'blackcat':'#413839', 'iridium':'#3d3c3a', 'blackeel':'#463e3f', 'blackcow':'#4c4646', 'graywolf':'#504a4b', 'vampiregray':'#565051', 'graydolphin':'#5c5858', 'carbongray':'#625d5d', 'ashgray':'#666362', 'cloudygray':'#6d6968', 'smokeygray':'#726e6d', 'gray':'#736f6e', 'granite':'#837e7c', 'battleshipgray':'#848482', 'graycloud':'#b6b6b4', 'graygoose':'#d1d0ce', 'platinum':'#e5e4e2', 'metallicsilver':'#bcc6cc', 'blue':'#0000ff', 'bluegray':'#98afc7', 'lightslategray':'#6d7b8d', 'slategray':'#657383', 'jetgray':'#616d7e', 'mistblue':'#646d7e', 'marbleblue':'#566d7e', 'slateblue':'#737ca1', 'steelblue':'#4863a0', 'bluejay':'#2b547e', 'darkslateblue':'#2b3856', 'midnightblue':'#151b54', 'navyblue':'#000080', 'bluewhale':'#342d7e', 'lapisblue':'#15317e', 'denimdarkblue':'#151b8d', 'earthblue':'#0000a0', 'cobaltblue':'#0020c2', 'blueberryblue':'#0041c2', 'sapphireblue':'#2554c7', 'blueeyes':'#1569c7', 'royalblue':'#2b60de', 'blueorchid':'#1f45fc', 'bluelotus':'#6960ec', 'lightslateblue':'#736aff', 'windowsblue':'#357ec7', 'glacialblueice':'#368bc1', 'silkblue':'#488ac7', 'blueivy':'#3090c7', 'bluekoi':'#659ec7', 'columbiablue':'#87afc7', 'babyblue':'#95b9c7', 'lightsteelblue':'#728fce', 'oceanblue':'#2b65ec', 'blueribbon':'#306eff', 'bluedress':'#157dec', 'dodgerblue':'#1589ff', 'cornflowerblue':'#6495ed', 'skyblue':'#6698ff', 'butterflyblue':'#38acec', 'iceberg':'#56a5ec', 'crystalblue':'#5cb3ff', 'deepskyblue':'#3bb9ff', 'denimblue':'#79baec', 'lightskyblue':'#82cafa', 'dayskyblue':'#82caff', 'jeansblue':'#a0cfec', 'blueangel':'#b7ceec', 'pastelblue':'#b4cfec', 'seablue':'#c2dfff', 'powderblue':'#c6deff', 'coralblue':'#afdcec', 'lightblue':'#addfff', 'robineggblue':'#bdedff', 'palebluelily':'#cfecec', 'lightcyan':'#e0ffff', 'water':'#ebf4fa', 'aliceblue':'#f0f8ff', 'azure':'#f0ffff', 'lightslate':'#ccffff', 'lightaquamarine':'#93ffe8', 'electricblue':'#9afeff', 'aquamarine':'#7fffd4', 'cyanoraqua':'#00ffff;', 'tronblue':'#7dfdfe;', 'bluezircon':'#57feff', 'bluelagoon':'#8eebec', 'celeste':'#50ebec', 'bluediamond':'#4ee2ec', 'tiffanyblue':'#81d8d0', 'cyanopaque':'#92c7c7', 'bluehosta':'#77bfc7', 'northernlightsblue':'#78c7c7', 'mediumturquoise':'#48cccd', 'turquoise':'#43c6db', 'jellyfish':'#46c7c7', 'bluegreen':'#7bccb5', 'macawbluegreen':'#43bfc7', 'lightseagreen':'#3ea99f', 'darkturquoise':'#3b9c9c;', 'seaturtlegreen':'#438d80', 'mediumaquamarine':'#348781', 'greenishblue':'#307d7e', 'grayishturquoise':'#5e7d7e', 'beetlegreen':'#4c787e', 'teal':'#008080', 'seagreen':'#4e8975', 'camouflagegreen':'#78866b', 'sagegreen':'#848b79', 'hazelgreen':'#617c58', 'venomgreen':'#728c00', 'ferngreen':'#667c26', 'darkforestgreen':'#254117', 'mediumseagreen':'#306754', 'mediumforestgreen':'#347235', 'seaweedgreen':'#437c17', 'pinegreen':'#387c44', 'junglegreen':'#347c2c', 'shamrockgreen':'#347c17', 'mediumspringgreen':'#348017', 'forestgreen':'#4e9258', 'greenonion':'#6aa121', 'springgreen':'#4aa02c', 'limegreen':'#41a317', 'clovergreen':'#3ea055', 'greensnake':'#6cbb3c', 'aliengreen':'#6cc417', 'greenapple':'#4cc417', 'yellowgreen':'#52d017', 'kellygreen':'#4cc552', 'zombiegreen':'#54c571', 'froggreen':'#99c68e', 'greenpeas':'#89c35c', 'dollarbillgreen':'#85bb65', 'darkseagreen':'#8bb381', 'iguanagreen':'#9cb071', 'avocadogreen':'#b2c248', 'pistachiogreen':'#9dc209', 'saladgreen':'#a1c935', 'hummingbirdgreen':'#7fe817', 'nebulagreen':'#59e817', 'stoplightgogreen':'#57e964', 'algaegreen':'#64e986', 'jadegreen':'#5efb6e', 'green':'#00ff00', 'emeraldgreen':'#5ffb17', 'lawngreen':'#87f717', 'chartreuse':'#8afb17', 'dragongreen':'#6afb92', 'mintgreen':'#98ff98', 'greenthumb':'#b5eaaa', 'lightjade':'#c3fdb8', 'teagreen':'#ccfb5d', 'greenyellow':'#b1fb17', 'slimegreen':'#bce954', 'goldenrod':'#edda74', 'harvestgold':'#ede275', 'sunyellow':'#ffe87c', 'yellow':'#ffff00', 'cornyellow':'#fff380', 'parchment':'#ffffc2', 'cream':'#ffffcc', 'lemonchiffon':'#fff8c6', 'cornsilk':'#fff8dc', 'beige':'#f5f5dc', 'blonde':'#fbf6d9', 'antiquewhite':'#faebd7', 'champagne':'#f7e7ce', 'blanchedalmond':'#ffebcd', 'vanilla':'#f3e5ab', 'tanbrown':'#ece5b6', 'peach':'#ffe5b4', 'mustard':'#ffdb58', 'rubberduckyyellow':'#ffd801', 'brightgold':'#fdd017', 'goldenbrown':'#eac117', 'macaroniandcheese':'#f2bb66', 'saffron':'#fbb917', 'beer':'#fbb117', 'cantaloupe':'#ffa62f', 'beeyellow':'#e9ab17', 'brownsugar':'#e2a76f', 'burlywood':'#deb887', 'deeppeach':'#ffcba4', 'gingerbrown':'#c9be62', 'schoolbusyellow':'#e8a317', 'sandybrown':'#ee9a4d', 'fallleafbrown':'#c8b560', 'orangegold':'#d4a017', 'sand':'#c2b280', 'cookiebrown':'#c7a317', 'caramel':'#c68e17', 'brass':'#b5a642', 'khaki':'#ada96e', 'camelbrown':'#c19a6b', 'bronze':'#cd7f32', 'tigerorange':'#c88141', 'cinnamon':'#c58917', 'bulletshell':'#af9b60', 'darkgoldenrod':'#af7817', 'copper':'#b87333', 'wood':'#966f33', 'oakbrown':'#806517', 'moccasin':'#827839', 'armybrown':'#827b60', 'sandstone':'#786d5f', 'mocha':'#493d26', 'taupe':'#483c32', 'coffee':'#6f4e37', 'brownbear':'#835c3b', 'reddirt':'#7f5217', 'sepia':'#7f462c', 'orangesalmon':'#c47451', 'rust':'#c36241', 'redfox':'#c35817', 'chocolate':'#c85a17', 'sedona':'#cc6600', 'papayaorange':'#e56717', 'halloweenorange':'#e66c2c', 'pumpkinorange':'#f87217', 'constructionconeorange':'#f87431;', 'sunriseorange':'#e67451', 'mangoorange':'#ff8040;', 'darkorange':'#f88017', 'coral':'#ff7f50', 'basketballorange':'#f88158', 'lightsalmon':'#f9966b', 'tangerine':'#e78a61', 'darksalmon':'#e18b6b', 'lightcoral':'#e77471', 'beanred':'#f75d59', 'valentinered':'#e55451', 'shockingorange':'#e55b3c', 'red':'#ff0000', 'scarlet':'#ff2400', 'rubyred':'#f62217', 'ferrarired':'#f70d1a', 'fireenginered':'#f62817', 'lavared':'#e42217', 'lovered':'#e41b17', 'grapefruit':'#dc381f', 'chestnutred':'#c34a2c', 'cherryred':'#c24641', 'mahogany':'#c04000', 'chillipepper':'#c11b17', 'cranberry':'#9f000f', 'redwine':'#990012', 'burgundy':'#8c001a', 'chestnut':'#954535', 'bloodred':'#7e3517', 'sienna':'#8a4117', 'sangria':'#7e3817', 'firebrick':'#800517', 'maroon':'#810541', 'plumpie':'#7d0541', 'velvetmaroon':'#7e354d', 'plumvelvet':'#7d0552', 'rosyfinch':'#7f4e52', 'puce':'#7f5a58', 'dullpurple':'#7f525d', 'rosybrown':'#b38481', 'khakirose':'#c5908e', 'pinkbow':'#c48189', 'lipstickpink':'#c48793', 'rose':'#e8adaa', 'rosegold':'#ecc5c0', 'desertsand':'#edc9af', 'pigpink':'#fdd7e4', 'cottoncandy':'#fcdfff', 'pinkbubblegum':'#ffdfdd', 'mistyrose':'#fbbbb9', 'pink':'#faafbe', 'lightpink':'#faafba', 'flamingopink':'#f9a7b0', 'pinkrose':'#e7a1b0', 'pinkdaisy':'#e799a3', 'cadillacpink':'#e38aae', 'carnationpink':'#f778a1;', 'blushred':'#e56e94', 'hotpink':'#f660ab', 'watermelonpink':'#fc6c85', 'violetred':'#f6358a', 'deeppink':'#f52887', 'pinkcupcake':'#e45e9d', 'pinklemonade':'#e4287c', 'neonpink':'#f535aa', 'magenta':'#ff00ff', 'dimorphothecamagenta':'#e3319d', 'brightneonpink':'#f433ff', 'palevioletred':'#d16587', 'tulippink':'#c25a7c', 'mediumvioletred':'#ca226b', 'roguepink':'#c12869', 'burntpink':'#c12267', 'bashfulpink':'#c25283', 'darkcarnationpink':'#c12283', 'plum':'#b93b8f', 'violapurple':'#7e587e', 'purpleiris':'#571b7e', 'plumpurple':'#583759', 'indigo':'#4b0082', 'purplemonster':'#461b7e', 'purplehaze':'#4e387e', 'eggplant':'#614051', 'grape':'#5e5a80', 'purplejam':'#6a287e', 'darkorchid':'#7d1b7e', 'purpleflower':'#a74ac7', 'mediumorchid':'#b048b5', 'purpleamethyst':'#6c2dc7', 'darkviolet':'#842dce', 'violet':'#8d38c9', 'purplesagebush':'#7a5dc7', 'lovelypurple':'#7f38ec', 'purple':'#8e35ef', 'aztechpurple':'#893bff', 'mediumpurple':'#8467d7', 'jasminepurple':'#a23bec', 'purpledaffodil':'#b041ff', 'tyrianpurple':'#c45aec', 'crocuspurple':'#9172ec', 'purplemimosa':'#9e7bff', 'heliotropepurple':'#d462ff', 'crimson':'#e238ec', 'purpledragon':'#c38ec7', 'lilac':'#c8a2c8', 'blushpink':'#e6a9ec', 'mauve':'#e0b0ff', 'wisteriapurple':'#c6aec7', 'blossompink':'#f9b7ff', 'thistle':'#d2b9d3', 'periwinkle':'#d9cfec', 'lavenderpinocchio':'#ebdde2', 'lavenderblue':'#e3e4fa', 'pearl':'#fdeef4', 'seashell':'#fff5ee', 'milkwhite':'#fefcff', 'white':'#ffffff', 'gold':'#eea236', 'silver': '#bcc6cc', /* Demo data specific */ 'aluminium,gold': '#bcc6cc', 'black,blue': '#265a88', 'black,brown': '#835c3b', 'black,graphite': '#c7a317', 'black,graphite,metallic': '#c7a317', 'black,white': '#bcc6cc', 'black,silver': '#bcc6cc', 'black,grey': '#bcc6cc', 'grey,silver': '#bcc6cc', ]; %><div class="filter-nav-holder"> <h2>${(_filteredNavBlock.displayName != null ? _filteredNavBlock.displayName : _filteredNavBlock.name)}</h2> <div class="single-nav-block single-nav-block-color"><% def _fnValuesToDisplay = _filteredNavBlock.fnValues; // No macroFilterNavUtils.cutTheTail(_filteredNavBlock.fnValues, _filteredNavBlockLimit); def _multi = 'M'.equals(_filteredNavBlock.navigationType); _fnValuesToDisplay.each { _filteredNavBlockValue -> def _base = filteredURL(''); def _path = '/' + _filteredNavBlock.code + '/' + encodeURI(_filteredNavBlockValue.value); def _selected = _multi && _base.contains(_path); def _href; if (_selected) { _href = _base.replace(_path, '').replace('//', '/'); } else { _href = (_base + _path).replace('//', '/'); } %><span> <a rel="search" data-filtercode="${_filteredNavBlock.code}" data-filtervalue="${_filteredNavBlockValue.value}" href="${_href}" title="${(_filteredNavBlockValue.displayValue ? _filteredNavBlockValue.displayValue : _filteredNavBlockValue.value) + ' (' + _filteredNavBlockValue.count + ')'}"> <% def _color = _colors[_filteredNavBlockValue.value.replace(" ", "").toLowerCase()]; if (_color) { if ('#ffffff'.equals(_color)) { if (_selected) { %><i class="fa fa-check-square-o fa-2x" style="color:#000000" aria-hidden="true"></i><% } else { %><i class="fa fa-square-o fa-2x" style="color:#000000" aria-hidden="true"></i><% } } else { if (_selected) { %><i class="fa fa-check-square fa-2x" style="color:${_color}" aria-hidden="true"></i><% } else { %><i class="fa fa-square fa-2x" style="color:${_color}" aria-hidden="true"></i><% } } } else { %><i class="fa fa-question-circle fa-2x" aria-hidden="true"></i><% } %> </a> </span> <% } %></div> </div><% } %> |
Snippet above achieves two goals:
For configuring product data please consult PIM documentation.
<% // [SHOP_CODE]_variant_SkuListViewDim_13320 used for '13320', which is simple value and shows as a text box + value name hint def _sku = binding.hasVariable('sku') ? sku : null; def _fc = binding.hasVariable('fc') ? fc : null; def _variations = binding.hasVariable('variations') ? variations : []; def _variations_opts = binding.hasVariable('variationsOptions') ? variationsOptions : [:]; def _dim = binding.hasVariable('variationDimension') ? variationDimension : null; def _selection = binding.hasVariable('variationSelection') ? variationSelection : [:]; def _variation_attrs = binding.hasVariable('variationAttributes') ? variationAttributes : [:]; if (_dim != null) { def _lang = sf.locale; def _multi_dimension = _variations.size() > 1; if (_multi_dimension) { def _attr = _variation_attrs[_dim]; def _attrName = _dim; if (_attr != null) { _attrName = _attr.getLocalName(_lang); } %><div class="product-detail-sku-list-dim-name" data-dim="${_dim}">${_attrName}</div><% } %><div class="product-detail-sku-list-dim" data-dim="${_dim}"><% def _dim_opts = _variations_opts[_dim]; if (_multi_dimension) { // group SKU by attribute value _dim_opts.each { _opt, _skuItems -> def _skuItem = _skuItems[0]; def _active = false; for (def _skuItemCandidate : _skuItems) { if (_sku.skuId == _skuItemCandidate.skuId) { _active = true; _skuItem = _skuItemCandidate; break; } } def _code = sf.useManufacturerSku ? _skuItem.manufacturerCode : _skuItem.code; def _name = _skuItem.getLocalName(_lang); // use SKU name as dimension name by default def _val = _code; def _currentVal = _skuItem.getAttribute(_dim); if (_currentVal != null) { _val = _currentVal.val; _name = _currentVal.getLocalVal(_lang); // set attribute as dimension name } %> <span class="${(_active ? 'active sku-variant-box' : 'sku-variant-box')}"> <a rel="bookmark" href="${skuURL([_fc, _skuItem.uri])}" title="${_name}" data-dim="${_dim}" data-dim-value="${_val}"> <span>${_name}</span> </a> </span> <% } } else { // render all _dim_opts.each { _opt, _skuItems -> for (def _skuItem : _skuItems) { def _code = sf.useManufacturerSku ? _skuItem.manufacturerCode : _skuItem.code; def _name = _skuItem.getLocalName(_lang); // use SKU name as dimension name by default def _val = _code; def _active = _sku.skuId == _skuItem.skuId; def _currentVal = _skuItem.getAttribute(_dim); if (_currentVal != null) { _val = _currentVal.val; _name = _currentVal.getLocalVal(_lang); // set attribute as dimension name } %> <span class="${(_active ? 'active sku-variant-box' : 'sku-variant-box')}"> <a rel="bookmark" href="${skuURL([_fc, _skuItem.uri])}" title="${_name}" data-dim="${_dim}" data-dim-value="${_val}"> <span>${_name}</span> </a> </span> <% } } } %></div><% } %> |
Snippet above achieves the following:
For configuring product data please consult PIM documentation.
<% // [SHOP_CODE]_variant_SkuOptionsDim_OPTMOUSE used for 'OPTMOUSE', which show a SKU thumbnail + value name hint def _skus = binding.hasVariable('product') ? product.skus : null; def _sku = binding.hasVariable('sku') ? sku : null; def _fc = binding.hasVariable('fc') ? fc : null; def _optionsModel = binding.hasVariable('optionsModel') ? optionsModel : null; def _optionsModelItem = binding.hasVariable('optionsModelItem') ? optionsModelItem : null; if (_optionsModelItem != null) { def _lang = sf.locale; def _optionName = _optionsModelItem.getLocalName(_lang); %><div class="product-detail-sku-options-option-name" data-option="${_optionsModelItem.attributeCode}">${_optionName}</div><% %><div class="product-detail-sku-options-option" data-option="${_optionsModelItem.attributeCode}"><% _optionsModelItem.optionSku.each { _skuItem -> def _code = sf.useManufacturerSku ? _skuItem.manufacturerCode : _skuItem.code; def _name = _skuItem.getLocalName(_lang); def _val = _skuItem.code; def _skuImage = _skuItem.images != null && _skuItem.images.size() > 0 ? _skuItem.images[0].thumbnailUrl : null; %> <span class="sku-option-img"> <a class="js-buy-option" href="#" title="${_name}" data-product="${_sku?.code}" data-option="${_optionsModelItem.attributeCode}" data-optionqty="${_optionsModelItem.quantity}" data-optionrequired="${_optionsModelItem.mandatory}" data-optionvalue="${_val}"> <script type='yc-include'>/internal/skubuypanel?skuId=${_skuItem.skuId}&fc=${_fc}&itemQuantity=${_optionsModelItem.quantity}&view=SkuBuyPanelOption</script> <% if (_skuImage) { %><img src="${_skuImage.substring(0, _skuImage.indexOf('?')) + '?w=40&h=40'}"/><% } else { %><span>${(_code + ' ' + _name)}</span><% } %> </a> </span> <% } %></div><% } %> |
Snippet above achieves the following: