Advanced storefront search
Advanced storefront search
Developers, system administrators and power users can customize Elastic Path Commerce's advanced search feature in the storefront.
Customizing advanced storefront search
The major steps involved in customizing advanced storefront search are:
- Identify the product attributes you want to allow shoppers to use for filtering their searches.
- Configure the search options for each attribute in COMMERCE/STORE/ADVANCEDSEARCH/advancedSearchConfiguration setting or in the store's Advanced Search tab.
- (Optional) Modify the advanced search template to render the search options to suit your needs.
Product attributes
To see the list of available product attributes, you can either:
- use the Commerce Manager client (in the Catalog Management activity, open the master catalog and click the Attributes tab)
- query the TATTRIBUTES table in your Elastic Path Commerce database. For example:
select ATTRIBUTE_KEY, LOCALE_DEPENDANT, ATTRIBUTE_TYPE, NAME, CATALOG_UID from TATTRIBUTE where SYSTEM = 0;
Take special note of the values in the ATTRIBUTE_KEY, LOCALE_DEPENDANT, and ATTRIBUTE_TYPE columns; you need these when you configure the search configuration setting. Advanced storefront search supports the following attribute types:
Attribute type name | ATTRIBUTE_TYPE column value |
---|---|
Short text | 1 |
Long text | 2 |
Integer | 3 |
Decimal | 4 |
Boolean | 5 |
The search configuration setting
The COMMERCE/STORE/ADVANCEDSEARCH/advancedSearchConfiguration setting contains the search options. The value of the setting is an XML document with the same structure as the filtered navigation configuration (in the COMMERCE/STORE/FILTEREDNAVIGATION/filteredNavigationConfiguration setting). It can be configured either in the store's Advanced Search tab or in the System Configuration tab.
Each store can have a different value for the COMMERCE/STORE/ADVANCEDSEARCH/advancedSearchConfiguration setting, thus each store can have completely different advanced search options.
In the <IntelligentBrowsing> root element, you can add elements to control what options are available to shoppers when searching.
Attributes with predefined ranges
You may want to provide shoppers with a limited number of values to choose from. For example, the Viewfinder type attribute (attribute key A00556) only has six possible values. The following configuration adds a combo box in the advanced search page that displays only those options:
<!-- Viewfinder type (attribute with a preset range of values) --> <attribute key="A00556" localized="true"> <simple id="01" value="TFT active matrix" language="en" /> <simple id="02" value="Matrice active TFT" language="fr" /> <simple id="03" value="LCD passive matrix" language="en" /> <simple id="04" value="LCD à matrice passive" language="fr" /> <simple id="05" value="None" language="en" /> <simple id="06" value="Aucun(e)" language="fr" /> <simple id="07" value="LCD" language="en" /> <simple id="08" value="LCD" language="fr" /> <simple id="09" value="CRT" language="en" /> <simple id="10" value="CRT" language="fr" /> <simple id="11" value="Conventional" language="en" /> <simple id="12" value="Conventionnel" language="fr" /> </attribute>
The key specifies the key of the attribute you're configuring. Inside the <attribute>, each <simple> represents one of the possible values. If values are locale-dependent, include the language attribute and set it to the locale.
To find localized attribute values, you can use a SQL query similar to the following:
select distinct(SHORT_TEXT_VALUE) from TPRODUCTATTRIBUTEVALUE where ATTRIBUTE_UID='100007' and LOCALIZED_ATTRIBUTE_KEY IN ('A00409_fr');
The last two characters of LOCALIZED_ATTRIBUTE_KEY indicate the language.
By default, this is rendered as a combo box.
- The id of each <simple> must be unique within that <attribute>.
- An All item is automatically added to the combo box to allow users to exclude the attribute from their search filtering. You can change this behavior by modifying the renderAttributeFields macro in the advanced search template.
You can also use radio buttons when displaying boolean (true/false) type attributes as shown in the following example.
<!-- Red Eye Reduction (attribute with a yes/no value) --> <attribute key="A02028" localized="true"> <simple id="01" value="true" displayName="true" language="en"/commerce-legacy/> <simple id="02" value="false" displayName="false" language="en"/commerce-legacy/> <simple id="03" value="true" displayName="vrai" language="fr"/commerce-legacy/> <simple id="04" value="false" displayName="faux" language="fr"/commerce-legacy/> </attribute>
A Don't Care radio button is automatically included to allow users to exclude the attribute from their search filtering. You can change this behavior by modifying the renderAttributeFields macro in the advanced search template.
Attributes with configurable ranges
For some attributes, you may want to let shoppers set the range of values they want to match. Use the <attributeRange> for attributes that have shopper-configurable minimum and maximum values. For example, the Sensor Resolution attribute (attribute key A02638) contains a decimal value. The following would allow shoppers to narrow their search by setting the lower and upper bounds for this attribute.
<!-- Optical Sensor / Sensor Resolution (attribute with shopper-configurable min/max) --> <attributeRange key="A02638" localized="false"></attributeRange>
By default, this is rendered as two input boxes for setting the minimum and maximum values.
Brands
You can configure a set of check boxes to be displayed to allow shoppers to filter search results by brand name.
<brands> <brand key="F00002"/commerce-legacy/> <brand key="F00007"/commerce-legacy/> <brand key="F00008"/commerce-legacy/> <brand key="F00009"/commerce-legacy/> <brand key="F00010"/commerce-legacy/> <brand key="F00011"/commerce-legacy/> <brand key="F00012"/commerce-legacy/> <brand key="F00005"/commerce-legacy/> <brand key="F00013"/commerce-legacy/> <brand key="F00014"/commerce-legacy/> </brands>
By default, this is rendered as a set of check boxes next to the localized brand names.
To see the brand name/key mappings, execute the following SQL query:
SELECT b.CODE, b.CATALOG_UID, lp.VALUE, lp.LOCALIZED_PROPERTY_KEY FROM TBRAND b INNER JOIN TLOCALIZEDPROPERTIES lp ON lp.OBJECT_UID = b.UIDPK AND lp.TYPE = 'Brand'
Text Attributes
You can configure a keyword search field on any text attribute value.
<attributeKeyword key="PR_SearchISBNs"/commerce-legacy/> <attributeKeyword key="PR_Author"/commerce-legacy/> <attributeKeyword key="PR_Title"/commerce-legacy/> <attributeKeyword key="PR_Series"/commerce-legacy/>
The above example will generate four text fields with the localized attribute names as labels.
To see the available list of product attribute keys that are text-only, execute the following SQL query:
SELECT attr.ATTRIBUTE_KEY, attr.CATALOG_UID, attr.NAME, attr.LOCALE_DEPENDANT FROM TATTRIBUTE attr WHERE attr.ATTRIBUTE_USAGE = 2 AND (attr.ATTRIBUTE_TYPE IN (1, 2))
The advanced search template
The electronics theme includes an advancedSearch.vm template for rendering the advanced search page. This template includes macros that will automatically generate the search form controls for the attributes configured in the COMMERCE/STORE/ADVANCEDSEARCH/advancedSearchConfiguration setting. It's located in <assets>\themes\electronics\default\templates\velocity\search.
The price slider
The price slider is a jQuery UI widget that allows the shopper to adjust the price range. It does not required any configuration in the COMMERCE/STORE/ADVANCEDSEARCH/advancedSearchConfiguration setting. You adjust the price slider's default upper and lower values by modifying these lines in the template:
#set($amountFromDefault = 1000) #set($amountToDefault = 2000)
You can also adjust its minimum, maximum, and step values by modifying the object passed to jq("#slider-range").slider(). Look for the following code inside the advancedSearchBody Velocity macro:
jq().ready(function() { jq("#slider-range").slider({ range: true, min: 0, max: 2000, values: [$!amountFrom, $!amountTo], step: 10, slide: function(event, ui) { jq("#amountFrom").val(ui.values[0]); jq("#amountTo").val(ui.values[1]); } }); jq("#amountFrom").val(jq("#slider-range").slider("values", 0)); jq("#amountTo").val(jq("#slider-range").slider("values", 1)); });
The renderBrands macro
You can change how #brands are displayed by modifying the contents of this macro. By default, brands are rendered in a <table> with four columns. To increase the number of columns, locate the following code and change the number in the #set($rowMaxReached = $i % 4) line.
#foreach($brand in $brandList) ##four brands in a row #set($rowMaxReached = $i % 4)
The renderAttributeFields macro
This macro controls how attributes with predefined ranges are displayed. For example, by default, an All is automatically included in combo boxes and a Don't Care in radio button groups. If you don't want them added, remove the line #set($ret = $map.put("", $allMsg)).
#macro(renderAttributeFields $attributeValueMap $msg $shortText) #foreach($attributeKey in $attributeValueMap.keySet()) #set($map = $attributeValueMap.get($attributeKey)) #set($allMsg = $springMacroRequestContext.getMessage($msg)) <br/> #set($ret = $map.put("", $allMsg)) <label>#springMessage("productTemplate.${attributeKey}")</label> #if ($shortText == "true") #springFormSingleSelect("advancedSearchControllerFormBean.attributeValuesMap[$attributeKey]" $map "") #else #springFormRadioButtons("advancedSearchControllerFormBean.attributeValuesMap[$attributeKey]" $map " " "") #end #end #end
The renderSimpleAttributeRangeFilterField macro
This macro controls how attributes with configurable ranges are rendered.
#macro(renderSimpleAttributeRangeFilterField) #foreach($attributeRangeKey in $advancedSearchControllerFormBean.nonPreDefinedAttributeRangeFilterMap.keySet()) <label for="$attrRangeFrom">#springMessage("productTemplate.${attributeRangeKey}")</label> #springFormInput("advancedSearchControllerFormBean.nonPreDefinedAttributeRangeFilterMap[$attributeRangeKey].fromField" "") #springMessage("advancedSearch.to") #springFormInput("advancedSearchControllerFormBean.nonPreDefinedAttributeRangeFilterMap[$attributeRangeKey].toField" "") #springShowErrors("<br>" "req") <br/> #end #end