Results Pages | Yext Hitchhikers Platform
Universal Search Results Page
A universal search results page combines results from multiple verticals into a set of results. You can read more about each individual component referenced here in the Components section.
Recommended Components
Component | Description |
---|---|
SearchBar
|
Where the user enters their Search |
Navigation
|
Navigate between Universal and Vertical Search |
SpellCheck
|
Show UI to correct user’s spelling |
DirectAnswer
|
Show a direct answer if one is found |
UniversalResults
|
Show the results |
LocationBias
|
Show where the search was run from |
Code
Putting these components together, the page looks like this:
<body>
<div class="answers-layout">
<div class="searchbar-container"></div>
<div class="navigation-container"></div>
<div class="spellcheck-container"></div>
<div class="universal-container"></div>
<div class="directanswer-container"></div>
<div class="locationbias-container"></div>
</div>
<script>
ANSWERS.init({
apiKey: "3517add824e992916861b76e456724d9",
experienceKey: "answers-js-docs",
businessId: "3215760",
experienceVersion: "PRODUCTION",
onReady: function () {
// init components
this.addComponent("SearchBar", {
container: ".searchbar-container",
allowEmptySearch: true
});
this.addComponent("Navigation", {
container: ".navigation-container",
});
this.addComponent("SpellCheck", {
container: ".spellcheck-container",
});
this.addComponent("DirectAnswer", {
container: ".directanswer-container",
});
this.addComponent("UniversalResults", {
container: ".universal-container",
config: {
locations: {
icon: "pin",
card: {
cardType: "Standard",
dataMappings: {
title: (item) => item.name,
subtitle: (item) => item.address.line1,
details: (item) => item.description,
image: (item) =>
item.photoGallery ? item.photoGallery[0].image.url : null,
url: "#"
},
callsToAction: [
{
label: "Get Directions",
icon: "directions",
url: "#",
analyticsEventType: "GET_DIRECTIONS",
target: "_self"
},
{
label: "Call",
icon: "phone",
url: (item) => `tel:${item.mainPhone}`,
analyticsEventType: "TAP_TO_CALL"
}
]
},
appliedFilters: {
show: true,
showFieldNames: true,
hiddenFields: ["builtin.entityType"],
delimiter: "|",
labelText: "Filters applied to this search:",
removableLabelText: "Remove this filter"
}
},
faqs: {
icon: "support",
title: "FAQs",
card: {
cardType: "Accordion",
dataMappings: {
title: (item) => item.name,
details: (item) => item.answer,
url: "#"
},
callsToAction: [
{
label: "Learn More",
icon: "",
url: "#",
analyticsEventType: "CTA_CLICK",
target: "_self"
}
]
}
},
jobs: {
icon: "briefcase",
card: {
cardType: "Standard",
dataMappings: {
title: (item) => item.name,
subtitle: (item) => `Date Posted: ${item.datePosted}`,
details: (item) => item.description,
url: "#"
},
callsToAction: [
{
label: "Learn More",
icon: "info",
url: "#",
analyticsEventType: "CTA_CLICK",
target: "_self"
}
]
}
}
}
});
this.addComponent("LocationBias", {
container: ".locationbias-container",
});
}
});
</script>
</body>
Example
Here is a fully working example:
Vertical Search Results Page
A Vertical Search Results Page displays results for a single vertical. You can read more about each individual component referenced here in the Components section.
Recommended Components
Component | Description |
---|---|
SearchBar
|
Where the user enters their Search |
Navigation
|
Navigate between Universal and Vertical Search using tabs |
SpellCheck
|
Show UI to correct user’s spelling |
Facets
|
Show a list of facets to help the user filter |
Pagination
|
Show pagination controls the help the user navigate to subsequent pages |
VerticalResults
|
Show the results for the vertical |
LocationBias
|
Show where the search was run from |
Example Code
Putting these components together, the page looks like this:
<body>
<div class="answers-layout">
<div class="searchbar-layout">
<div class="searchbar-container"></div>
<div class="navigation-container"></div>
</div>
<div class="filters-and-results-layout">
<div class="facets-container"></div>
<div class="results-layout">
<div class="spellcheck-container"></div>
<div class="vertical-container"></div>
<div class="locationbias-container"></div>
</div>
</div>
</div>
<script>
ANSWERS.init({
apiKey: "3517add824e992916861b76e456724d9",
experienceKey: "answers-js-docs",
businessId: "3215760",
experienceVersion: "PRODUCTION",
verticalKey: "locations",
search: {
verticalKey: "locations",
defaultInitialSearch:
"locations that take mastercard and offer free wifi",
limit: 20
},
verticalPages: [
{
label: "All",
url: "/index.html",
isFirst: true
},
{
verticalKey: "locations",
label: "Locations",
url: "/locations.html",
isActive: true
},
{
verticalKey: "jobs",
label: "Jobs",
url: "/jobs.html"
},
{
verticalKey: "faqs",
label: "FAQs",
url: "/faqs.html"
}
],
onReady: function () {
// init components
this.addComponent("SearchBar", {
container: ".searchbar-container",
allowEmptySearch: true,
verticalKey: "locations"
});
this.addComponent("Navigation", {
container: ".navigation-container"
});
this.addComponent("SpellCheck", {
container: ".spellcheck-container"
});
this.addComponent("Facets", {
container: ".facets-container",
verticalKey: "locations",
searchOnChange: true
});
this.addComponent("VerticalResults", {
container: ".vertical-container",
verticalKey: "locations",
card: {
cardType: "Standard",
dataMappings: {
title: (item) => item.name,
subtitle: (item) => item.address.line1,
details: (item) => item.description,
image: (item) =>
item.photoGallery ? item.photoGallery[0].image.url : null,
url: "#"
},
callsToAction: [
{
label: "Get Directions",
icon: "directions",
url: "#",
analyticsEventType: "GET_DIRECTIONS",
target: "_self"
},
{
label: "Call",
icon: "phone",
url: (item) => `tel:${item.mainPhone}`,
analyticsEventType: "TAP_TO_CALL"
}
]
},
noResults: {
displayAllResults: true
},
appliedFilters: {
show: true,
removable: true
}
});
this.addComponent("LocationBias", {
container: ".locationbias-container"
});
}
});
</script>
</body>
UX Recommendations
Vertical Result pages can come in all shapes and sizes. Here are some recommendations to consider when designing a Vertical Search Results page.
Show all results on load
Generally, you want to display ALL results for a vertical as soon as the page loads. To do this:
- Set
allowEmptySearch: true
on theSearchBar
component - Set
defaultInitialSearch: ""
on thesearch
config
Display ALL Results on No Results
You never want your user to hit a dead end. To help solve this, you can easily
display ALL results if the user would see no results. To do this set displayAllResults
in the noResults
configuration option in the VerticalSearch
component.
For example:
noResults: {
displayAllResults: true,
}
Example
Here is a fully working example:
No Results
With version 0.13.1, you can show all results when no results return, and link to other verticals that return results.
Basic Template
In version 0.13.1 and up, you can specify noResults
in your
verticalResults
component:
ANSWERS.addComponent("VerticalResults", {
container: ".vertical-results-container",
card: {
cardType: "Standard",
dataMappings: () => {},
callsToAction: () => [],
},
noResults: {
displayAllResults: true, //controls whether all results appear below. defaults to false if not specified.
}
});
Overwriting the Template
It’s very easy to override the no results template. Note: We did this because the logic is a little bit complicated (like iterating through the list of all alternative verticals, and deciding when to use plural vs. singular for “result” and “category”). We wanted you to still have access to those fancy things, even if you just wanted to customize part of the string.
You have access to the following Handlebars variables in the no results template:
universalUrl
- The url for universal searchcurrentVerticalLabel
- The current verticalquery
- The query that was createdresultsCount
- Results count for all resultsverticalSuggestions
- The set of all alternative verticals that returned results
You can see these in the following code sandbox.
ANSWERS.addComponent("VerticalResults", {
container: ".vertical-results-container",
card: {
cardType: "Standard",
dataMappings: () => {},
callsToAction: () => [],
},
noResults: {
displayAllResults: true, //controls whether all results appear below. defaults to false if not specified.
template: `
<div class="yxt-AlternativeVerticals{{#unless isShowingResults}} yxt-AlternativeVerticals--notShowingResults{{/unless}}">
<div class="yxt-AlternativeVerticals-noResultsInfo">
<em class="yxt-AlternativeVerticals-noResultsInfo--emphasized">
No results found
</em>
in {{currentVerticalLabel}}.
{{#if isShowingResults}}Showing<em class="yxt-AlternativeVerticals-noResultsInfo--emphasized">all {{currentVerticalLabel}}</em>instead.{{/if}}
</div>
{{#if verticalSuggestions}}
<div class="yxt-AlternativeVerticals-suggestionsWrapper">
<div class="yxt-AlternativeVerticals-details">
The following search
{{plural verticalSuggestions.length 'category' 'categories'}}
yielded results
{{#if query}}
for
<span class="yxt-AlternativeVerticals-details--query">
"{{query}}"</span>:
{{/if}}
</div>
<ul class="yxt-AlternativeVerticals-suggestionsList">
{{#each verticalSuggestions}}
<li class="yxt-AlternativeVerticals-suggestion">
<a class="yxt-AlternativeVerticals-suggestionLink"
href="{{url}}">
{{#if iconName}}
<div class="yxt-AlternativeVerticals-verticalIconWrapper"
data-component="IconComponent"
data-opts='{
"iconName": "{{iconName}}"
}'>
</div>
{{/if}}
<div class="yxt-AlternativeVerticals-suggestionLink--copy">
<span class="yxt-AlternativeVerticals-suggestionLink--copyLabel">
{{label}}
</span>
<span class="yxt-AlternativeVerticals-suggestionLink--copyResults">
({{resultsCount}} {{plural resultsCount 'result' 'results'}})
</span>
</div>
<div class="yxt-AlternativeVerticals-arrowIconWrapper"
data-component="IconComponent"
data-opts='{
"iconName": "chevron"
}'>
</div>
</a>
</li>
{{/each}}
</ul>
{{#if universalUrl}}
<div class="yxt-AlternativeVerticals-universalDetails">
Alternatively, you can
<a class="yxt-AlternativeVerticals-universalLink"
href={{universalUrl}}>
view results across all search categories</a>.
</div>
{{/if}}
</div>
{{/if}}
</div>
`
}
});
FAQs
1. Can this apply to universal?
Not yet but this is on the roadmap. – the construct is going to be a little different.
2. How does this work for third party backends?
Third party backends do not get the no results functionality.
3. How do I change the color of the background or the styling?
Overwrite any of the scss here.