loading

The SearchBar component is the main entry point for search querying. It provides the input box where the user types their query, as well as the autocomplete behavior. Search Bars can be used in both Vertical and Universal Search.

light bulb

If you’re only adding a searchbar to the page (instead of the full experience), we recommend using our searchbar-only assets. They contain only the necessary JS/CSS/hbs for the searchbar component, and are therefore optimized for page speed. The JS component has the exact same API properties as the SearchBar described here, with one exception: it requires a redirectUrl.

Read more about this bundle here, and see our Hitchhiker guide for further integration instructions.

Default Styling

Here is the default styling for a search bar: Search Bar

And here is the default styling for a search bar with autocomplete showing: Search Bar Expanded

Here is an example of adding a search bar to Universal Search:

<div class="search-bar-container"></div>
ANSWERS.addComponent("SearchBar", {
  container: ".search-bar-container",
});

Here is an example of adding a search bar to Vertical Search. It’s the same as Universal Search but requires an additional verticalKey.

<div class="search-bar-container"></div>
ANSWERS.addComponent("SearchBar", {
  container: ".search-bar-container",
  verticalKey: "VERTICAL_KEY", // required if not specified in search config in initialization.
});

Often you want to add a Search Bar to a page but then redirect to a search results page. This is accomplished via the redirectUrl property. If this property is filled out, the search will redirect when a user hits submit. This URL should be a search results page that includes a UniversalResults or VerticalResults component.

Using HTML5 Geolocation

By default, when a user types a query with “near me” intent (IE “locations near me”), we’ll prompt them to grant access to HTML5 geolocation. If you do not want this behavior, you can set the promptForLocation to false. If you notice consistently lethargic geolocation requests, you can reduce the timeout (geolocationOptions.timeout) or increase the maximum age for a geolocation request (geolocationOptions.maximumAge), and add an optional alert if the request fails (geolocationTimeoutAlert).

Finally, if the accuracy of geolocation information is particularly important, you can enable “high accuracy”, which will provide more accurate geolocation results at the expense of response time and/or device power consumption.

More information on enableHighAccuracy, timeout and maximumAge can be found in the MDN documentation.

ANSWERS.addComponent("SearchBar", {
  container: ".search-bar-container",
  redirectUrl: "https://www.domain.com",
  geolocationOptions: {
    timeout: 500,
    maximumAge: 300000,
    enableHighAccuracy: false
  },
  geolocationTimeoutAlert: {
    enabled: true,
    message: "We are unable to determine your location"
  }

});

Multiple Search Bars

Often you will want to have multiple search bars on a single page. For example one in the header and one in the center of the home page. To accomplish this make sure each search bar has a unique container and name.

ANSWERS.addComponent("SearchBar", {
  container: ".search-bar-container",
  name: "search-bar",
  redirectUrl: "https://www.domain.com/search-results",
});

ANSWERS.addComponent("SearchBar", {
  container: ".search-bar-container-2",
  name: "search-bar-2",
  redirectUrl: "https://www.domain.com/search-results",
});

Typing Placeholder

One nice UI trick to encourage more users to search is to show a user typing in the input. While the Answers JS library doesn’t support this by default, this can easily be added using Typed.js.

First, we will get the options via the /autocomplete endpoint and then we feed those options into the Typed. This should happen after the SearchBar component is added to the page. We are using axios to handle the API request.

var url = `https://liveapi-cached.yext.com/v2/accounts/me/answers/autocomplete`;
url += `?v=20190101`;
url += `&api_key=${apiKey}`;
url += `&sessionTrackingEnabled=false`;
url += `&experienceKey=${experienceKey}`;
url += `&input=`;
url += `&version=${version}`;
url += `&locale=${locale}`;

axios.get(url).then(function(response) {
  // Get strings from response
  const strings = response.data.response.results.map(function(r) {
    return r.value;
  });

  // Set up Typed
  var options = {
    strings,
    showCursor: true,
    cursorChar: "|",
    typeSpeed: 45,
    backSpeed: 20,
    smartBackspace: true,
    loop: true,
    startDelay: 500,
    backDelay: 2000,
    attr: "placeholder",
  };

  var typed = new Typed(".js-yext-query", options);
});

Here is a working example:

Property Type Default Description
verticalKey
string
The vertical for the search bar. Required if used in vertical search, and not included in the top level search configuration.
query
string
The initial search term in the search bar. Does not apply a query
labelText
string
Label for the search bar. Hidden by default.
submitText
string
The label of the submit button. Hidden by default.
submitIcon
string
Specify pre-built icon for the search bar. If none is specified, the animated search icon will be used. See icons.
customIconUrl
string
A custom icon URL to replace the default search icon.
promptHeader
string
Text label displayed above the autocomplete options.
placeholderText
string
Placeholder text of the search bar
allowEmptySearch
boolean
Allow a user to conduct an empty search. Should be set to true if the defaultInitialSearch in the top level search configuration is “”.
autoFocus
boolean
Auto-focus the search bar on page load.
autocompleteOnLoad
boolean
If autoFocus is true, show or display the autocomplete prompts.
searchCooldown
number
300
The number of miliseconds to wait before conducting new searches. Guards against someone rage-clicking the search bar.
promptForLocation
boolean
true
Ask the user for their geolocation when “near me” intent is detected.
clearButton
boolean
true
Display an “x” button to clear the current query.
redirectUrl
string
true
Redirect the search query to url
formSelector
string
form
Form Selector that is provided to the search bar template
inputEl
string
js-yext-query
Input Element that is required if a custom template is used where the input varies.
useForm
boolean
true
When true, a form is used as the query submission context. Note it’s WCAG best practice to set this to true.
geolocationOptions
object
Geolocation-related configuration. See Geolocation Documentation for more information.
enableHighAccuracy
boolean
Whether to improve accuracy at the cost of response time and/or power consumption, defaults to false.
timeout
number
1000
The maximum amount of time (in ms) a geolocation call is allowed to take before defaulting, defaults to 1 second.
maximumAge
number
300000
The maximum amount of time (in ms) to cache a geolocation call, defaults to 5 minutes.
geolocationTimeoutAlert
object
Configuration for a native alert, displayed when a call to the geolocation API fails.
enabled
boolean
Whether to display a window.alert() on the page
message
string
We are unable to determine your location
If enabled is true, the message in the alert.
voiceSearch
object
Configuration related to displaying a microphone icon for conducting a search with voice using the Web Speech API
enabled
boolean
Whether to display the voice search icon.
customMicIconUrl
string
A URL for an image that replaces the default microphone icon
customListeningIconUrl
string
A URL for an image that replaces the default listening icon

Navigation

Background

The navigation component is made of up of tabs that link to universal and vertical search pages. You’ll typically see it appear just below the search bar.

When conducting a search from universal, the tabs will reorder based on the order of the search results. By default, tabs that do not fit in the container will be placed inside a dropdown menu. This can be configured for mobile (see mobileOverflowBehavior in API Properties below).

The pages that appear in the navigation are configured in the ANSWERS.init’s verticalPages configuration. Full Width (Mobile + Desktop) Collapsed (Mobile + Desktop) Overflow (Optionally on Mobile)

We don’t recommend dynamically changing the width of the overflow button, as this can impact it’s behavior unintentionally (there is logic that checks for changes to Navigation width to update the More dropdown content). If you need to include a border on the button, we recommend using an outline instead.

Configuration

<div class="navigation-container"></div>
ANSWERS.addComponent('Navigation', {
  container: '.navigation-container',
  // mobileOverflowBehavior: 'COLLAPSE',
  // ariaLabel: 'Search Page Navigation',
  // overflowLabel: 'More',
  // overflowIcon: null
})

Example

Property Type Default Description
ariaLabel
string
Search Page Navigation
Optional, the aria-label to set on the navigation.
mobileOverflowBehavior
string
COLLAPSE
Optional, controls if navigation collapses to a more tab, or uses inner scroll on mobile. Options are COLLAPSE or INNERSCROLL.
overflowLabel
string
More
Optional, the label to display on the dropdown menu button when it overflows.
overflowIcon
string
three stacked dots
Optional, name of the icon to show on the dropdown button instead when it overflows.

SpellCheck

Background

The SpellCheck component helps correct a user’s spelling. Spell Check It is usually displayed above the results. It works on both Universal Search and Vertical Search and is generally added directly above the VerticalResults or DirectAnswer.

Configuration

The component is named SpellCheck. There are no additional required properties.

<div class="spell-check-container></div>
ANSWERS.addComponent("SpellCheck", {
  container: ".spell-check-container",
  // suggestionHelpText: "Are you sure you didn't mean: ",
});

Example

SpellCheck API

Property Type Default Description
suggestionHelpText
string
Did you mean
Did you mean text to displays before the query

DirectAnswer

Background

The DirectAnswer component shows a Direct Answer to a query. It is usually shown above the UniversalResults component. DirectAnswers are only returned on Universal Search.

Default Styling

Here is the default styling for a Direct Answer: Direct Answer

Base Configuration

Here’s a basic example of adding a direct answer.

<div class="direct-answer-container"></div>
ANSWERS.addComponent("DirectAnswer", {
  container: ".direct-answer-container",
});

Creating a Custom DirectAnswer Card

You can customize the look and behavior of your Direct Answer by creating a custom Direct Answer card.

A custom Direct Answer card is given the same data as the built-in card. That data will look something like the below:

{
  type: "FIELD_VALUE",
  answer: {
    entityName: "Entity Name",
    fieldName: "Phone Number",
    fieldApiName: "mainPhone",
    value: "+11234567890",
    fieldType: "phone" 
  },
  relatedItem: { 
    verticalConfigId: 'people',
    data: { 
      id: "Employee-2116",
      type: "ce_person",
      fieldValues: {
        description: "This is the description field.",
        name: "First Last",
        firstName: "First",
        lastName: "Last",
        mainPhone: "+1234567890",
      }
    }
  }
}

A custom Direct Answer card needs a corresponding template. This can be added either inline by changing the component’s constructor to:

  constructor(config, systemConfig) {
    super(config, systemConfig);
    this.setTemplate(`<div> your template here </div>`)
  }

Or by including a custom template bundle, and adding:

  static defaultTemplateName () {
    return 'CustomDirectAnswerTemplate';
  }

Where ‘CustomDirectAnswerTemplate’ is the name the template is registered under.

We will use the following template for our example card.

  <div class="customDirectAnswer">
    <div class="customDirectAnswer-type">
      {{type}}
    </div>
    <div class="customDirectAnswer-value">
      {{#each customValue}}
      {{#if url}}
        {{> valueLink }}
      {{else}}
        {{{this}}}
      {{/if}}
      {{/each}}
    </div>
    {{> feedback}}
  </div>

  {{#*inline 'feedback'}}
  <span class="customDirectAnswer-thumbsUpIcon js-customDirectAnswer-thumbsUpIcon"
    data-component="IconComponent"
    data-opts='{"iconName": "thumb"}'
  ></span>
  <span class="customDirectAnswer-thumbsDownIcon js-customDirectAnswer-thumbsDownIcon"
    data-component="IconComponent"
    data-opts='{"iconName": "thumb"}'
  ></span>
  {{/inline}}

  {{#*inline 'valueLink'}}
  <a class="customDirectAnswer-fieldValueLink" href="{{{url}}}"
    {{#if @root/eventType}}data-eventtype="{{@root/eventType}}"{{/if}}
    {{#if @root/eventOptions}}data-eventoptions='{{{ json @root/eventOptions }}}'{{/if}}>
    {{{displayText}}}
  </a>
  {{/inline}}

This specific example needs some css to flip the thumbs up icon the right way.

  .customDirectAnswer-thumbsUpIcon svg {
    transform: rotate(180deg);
  }

This is the javascript class for our custom Direct Answer card. It applies custom formatting to the Direct Answer, registers analytics events to the thumbs up/down icons, and passes custom event options into the template.

  class CustomDirectAnswerClass extends ANSWERS.Component {
    constructor(config, systemConfig) {
      // If you need to override the constructor, make sure to call super(config, systemConfig) first.
      super(config, systemConfig);

      // For simplicity's sake, we set this card's template using setTemplate(), as opposed to
      // a custom template bundle.
      this.setTemplate(`<div> your template here </div>`)
    }

    /**
     * setState() lets you pass variables directly into your template.
     * Here, data is the directAnswer data from the query.
     * Below, we pass through a custom direct answers value, customValue.
     * @param {Object} data
     * @returns {Object}
     */ 
    setState(data) {
      const { type, answer, relatedItem } = data;
      const associatedEntityId = data.relatedItem && data.relatedItem.data && data.relatedItem.data.id;
      const verticalConfigId = data.relatedItem && data.relatedItem.verticalConfigId;
      return super.setState({
        ...data,
        customValue: this.getCustomValue(answer),
        eventType: 'CUSTOM_EVENT',
        eventOptions: {
          searcher: 'UNIVERSAL',
          verticalConfigId: verticalConfigId,
          entityId: associatedEntityId,
        }
      });
    }

    /**
     * onMount() lets you register event listeners. Here, we register the thumbs up and thumbs
     * down buttons to fire an analytics event on click.
     */ 
    onMount() {
      const thumbsUpIcon = this._container.querySelector('.js-customDirectAnswer-thumbsUpIcon');
      const thumbsDownIcon = this._container.querySelector('.js-customDirectAnswer-thumbsDownIcon');
      thumbsUpIcon.addEventListener('click', () => this.reportQuality(true));
      thumbsDownIcon.addEventListener('click', () => this.reportQuality(false));
    }

    /**
     * reportQuality() sends an analytics event (either THUMBS_UP or THUMBS_DOWN).
     * @param {boolean} isGood true if the answer is what you were looking for
     */
    reportQuality(isGood) {
      const eventType = isGood === true ? 'THUMBS_UP' : 'THUMBS_DOWN';
      const event = new ANSWERS.AnalyticsEvent(eventType).addOptions({
        directAnswer: true
      });
      this.analyticsReporter.report(event);
    }

    /**
     * Formats a Direct Answer value based on its fieldType.
     * @param {Object} answer the answer property in the directAnswer model
     * @returns {string}
     */ 
    formatValue(answer) {
      const { fieldType, value } = answer;
      switch (fieldType) {
        case 'phone':
          return {
              url: 'http://myCustomWebsite.com/?mainPhone=' + value,
              displayText: value,
            };
        case 'rich_text':
          return ANSWERS.formatRichText(value);
        case 'single_line_text':
        case 'multi_line_text':
        default:
          return value;
      }
    }

    /**
     * Computes a custom Direct Answer. If answer.value is an array, this method
     * formats every value in the array and returns it, otherwise it just formats the single
     * given value.
     * @param {Object} answer
     * @returns {Array<string>}
     */ 
    getCustomValue(answer) {
      if (Array.isArray(answer.value)) {
        return answer.value.map(value => this.formatValue(answer))
      } else {
        return [ this.formatValue(answer) ];
      }
    }

    /**
     * The name of your custom direct answer card. THIS is the value you will use in any config,
     * such as defaultCard, when you want to specify this custom Direct Answer card.
     * @returns {string}
     */
    static get type() {
      return 'MyCustomDirectAnswerCard';
    }
  }

  // Don't forget to register your Direct Answer card within the SDK. Otherwise the SDK won't recognize your card name!
  ANSWERS.registerComponentType(CustomDirectAnswerClass);

Using Cardoverrides

Now that we’ve created a custom direct answer card, you can specify which card should be used based on the type of direct answer that returns. There are two possible types: FIELD_VALUE, which returns for NLP filters, and FEATURED_SNIPPET, which returns for document search.

Here, we’ve specified that any FEATURED_SNIPPET direct answers should use a custom card we’ve named MyCustomDirectAnswerCardDocSearch. FIELD_VALUE card types are a little more advanced, we’ll go into these below:

ANSWERS.addComponent("DirectAnswer", {
  container: ".direct-answer-container",
  types: {
    'FEATURED_SNIPPET': {
      cardType: "MyCustomDirectAnswerCardDocSearch",
    },
    'FIELD_VALUE': {
      cardType: "MyCustomDirectAnswerCard",
      cardOverrides: [
        {
          cardType: 'MyMenuCustomDirectAnswerCard',
          fieldName: 'description',
          entityType: 'ce_menuItem',
          fieldType: 'rich_text'
        }
      ]
    }
  }
});

FIELD_VALUE is using cardOverrides; with these, we can specify that a different card should be used based on the fieldName, entityType, and/or fieldType combination. This DirectAnswer component will pick the first condition matched, so the ordering of the cardOverrides is important. For example, if the following overrides were specified:

cardOverrides: [
  {
    cardType: 'MyCustomDirectAnswerCard',
    entityType: 'ce_menuItem',
  },
  {
    cardType: 'MyOtherCustomDirectAnswerCard',
    fieldName: 'description',
    entityType: 'ce_menuItem',
  },
]

All menu item entities would receive the MyCustomDirectAnswerCard, since it’s the first rule in the list that applies, even if a direct answer returned for the description field.

Formatting Data in a Direct Answer

You can format data in a direct answer using the transformData hook outlined here.

Example

In this example, we’ve overridden the viewDetailsText and the footerTextOnSubmission. We’re also using a Custom Data Transform to override the formatting for a phone number.

DirectAnswer API

Property Type Default Description
formEl
string
.js-directAnswer-feedback-form
The selector for the form used for submitting the feedback
thumbsUpSelector
string
.js-directAnswer-thumbUp
The selector to bind ui interaction to for the thumbs up button
thumbsDownSelector
string
.js-directAnswer-thumbDown
The selector to bind ui interaction to for the thumbs down button
positiveFeedbackSrText
string
This answered my question
The screen reader text for the thumbs up button.
negativeFeedbackSrText
string
This did not answer my question
The screen reader text for the thumbs down button.
viewDetailsText
string
View Details
The display text for the View Details click to action link, which is the website URL of the entity.
footerTextOnSubmission
string
Thank you for your feedback!
The footer text to display on submission of feedback
defaultCard
string
DEPRECATED Optionally specify a custom direct answer card to use, which is the default when there are no matching card overrides.
cardOverrides
DEPRECATED Formerly used to specify a specific direct answer card based on the fieldName, entityType or fieldType
types
object
Specify card types and overrides based on the direct answer type (FEATURED_SNIPPET or FIELD_VALUE). Each property is nested under the direct answer type.
type.cardType
string
The name of the card to use for this direct answer type.
type.cardOverrides
array
Card overrides for this direct answer type.
fieldName
string
The field name for which this override should apply
entityType
string
The entity type name for which this override should apply
fieldType
string
The field type for which this override should apply
cardType
string
The card to use when this override is fulfilled

UniversalResults

Background

The UniversalResults component renders a set of verticals. Each vertical is rendered as a section. Each section includes a list of results, where each result is rendered as a card. Visually, there are lots of similarities between each vertical section and the Vertical Results component. That’s because, under the hood, Universal Results uses Vertical Results component to render the sections and their results.

To learn more about how to design a full Universal Results pages, check out the Universal Search Results.

The Configuration Object

The bulk of the Universal Results work is specifying the configuration for each vertical, under the larger config object. All verticals that are specified in the backend Answers configuration will be displayed using the default standard card (even if the config is not specified, or if a vertical is not included in said config).

Configuration

Here is an example configuration for UniversalResults.

ANSWERS.addComponent('UniversalResults', {
  container: '.universal-results-container',
  appliedFilters: {
    show: true,
    showFieldNames: false,
    hiddenFields: ['builtin.entityType'],
    resultsCountSeparator: '|',
    showChangeFilters: false,
    changeFiltersText: 'change filters',
    delimiter: '|',
    labelText: 'Filters applied to this search:',
  },
  config: {
    people: { // The verticalKey
      title: 'People',
      icon: 'star',
      url: 'people.html',
      viewMore: true,
      viewMoreLabel: 'View More!',
      showResultCount: true,
      includeMap: true,
      mapConfig: {
        mapProvider: 'google',
        apiKey: '<<< enter your api key here >>>',
      },
      
    }
  },
})

Example

Here is a fully working example:

UniversalResults API

Property Type Default Description
appliedFilters
object
Settings for the applied filters bar in the results header. These settings can be overriden in the “config” option below on a per-vertical basis.
show
boolean
true
If true, show any applied filters that were applied to the universal search.
showFieldNames
boolean
If appliedFilters.show is true, whether to display the field name of an applied filter, e.g. “Location - Virginia” vs just “Virginia”.
hiddenFields
array
['builtin.entityType']
If appliedFilters.show is true, this is list of filters that should not be displayed.
resultsCountSeparator
string
|
The character that separates the count of results (e.g. “1-6”) from the applied filter bar.
showChangeFilters
boolean
Whether to display the change filters link that links out to the vertical search.
changeFiltersText
string
change filters
If showChangeFilters is true, the text for the change filters link.
delimiter
string
|
The character that separates each field (and its associated filters) within the applied filter bar.
labelText
string
Filters applied to this search:
The aria-label given to the applied filters bar.
config
object
configuration for each vertical’s results. Each property is nested under the verticalKey.
card
object
Standard
The card used to display each individual result, see Result Cards.
template
string
A custom Handlebars template for this section
title
string
The vertical key
The title of the vertical, displayed in the section heading.
icon
string
star
Icon to display to the left of the title. Must be one of the SDK’s built-in icons
url
string
VERTICAL_KEY.html
The url for both the viewMore link and the change-filters link. The VERTICAL_KEY used in the default is the key in the config object.
viewMore
boolean
true
Whether to display a view more link at the bottom of the universal results section for this vertical. Url, or the verticalPages.url initialization option must be populated. See more on verticalPages here.
viewMoreLabel
string
View More
The text for the view more link, if viewMore is true.
appliedFilters
object
Same as appliedFilters settings above. Settings specified here will override any top level settings.
show
boolean
true
If true, show any applied filters that were applied to the universal search.
showFieldNames
boolean
If appliedFilters.show is true, whether to display the field name of an applied filter, e.g. “Location - Virginia” vs just “Virginia”.
hiddenFields
array
['builtin.entityType']
If appliedFilters.show is true, this is list of filters that should not be displayed.
resultsCountSeparator
string
|
The character that separates the count of results (e.g. “1-6”) from the applied filter bar.
showChangeFilters
boolean
Whether to display the change filters link that links out to the vertical search.
changeFiltersText
string
change filters
If showChangeFilters is true, the text for the change filters link.
delimiter
string
|
The character that separates each field (and its associated filters) within the applied filter bar.
labelText
string
Filters applied to this search:
The aria-label given to the applied filters bar.
useAccordion
boolean
DEPRECATED Use the accordion card instead. Whether to use the AccordionResults component instead of VerticalResults for this vertical.
includeMap
boolean
Whether to include a map in this vertical results section.
mapConfig
object
Configuration for the map. If includeMap is true, this is required. Additional configuration for this object described in the Map Component documentation.
mapProvider
string
REQUIRED Either ‘mapbox’ or ‘google’, not case sensitive
apiKey
string
REQUIRED API key for the map provider
viewAllText
string
DEPRECATED Use viewMoreLabel instead. viewAllText is a synonym for viewMoreLabel, where viewMoreLabel takes precedence over viewAllText.

VerticalResults

Background

The VerticalResults component is similar to UniversalResults but just renders a single vertical. It displays a list of results where each result is rendered as a card.

To learn more about how to design a full Vertical Results pages, check out the Vertical Search Results.

Specifying the Vertical

First, you should make sure to specify the vertical of the page. To specify the vertical that is used on the page, the verticalKey should be added to the Facets, SearchBar, and initial search config.

The VerticalResults component does not accept a verticalKey. It is infererred based on the other components on the page.

Configuration

Here is an example configuration for VerticalResults. In this example you can see the card is customized and we are choosing to display all results if no results are found.

ANSWERS.addComponent("VerticalResults", {
  container: ".vertical-results",
  card: {
    cardType: "Standard",
    dataMappings: {
      title: (item) => item.name,
      subtitle: (item) => item.address.line1,
      details: "",
      image: (item) =>
        !item.c_advisorPhoto ? null : item.c_advisorPhoto.image.url,
      url: "#",
    },

    callsToAction: [
      {
        label: "Book Appointment",
        icon: "calendar",
        url: "#",
        analyticsEventType: "CTA_CLICK",
        target: "_self",
      },
      {
        label: "Call",
        icon: "phone",
        url: (item) => `tel:${item.mainPhone}`,
        analyticsEventType: "TAP_TO_CALL",
      },
    ],
  },
  noResults: {
    displayAllResults: true,
  },
});

Customizing Result Cards

To customize the result card you should adjust the card property. Specifically, use the dataMappings and callsToAction to customize the look and the feel of the card. You can learn more in the Result Cards Guide.

No Results

With version 0.13.1, you can show all results when no results return, and link to other verticals that return results. See more in our Vertical No Results Guide

VerticalResults API

Property Type Default Description
container
string
REQUIRED Selector for the component container
renderItem
function
string to give custom template to result item
itemTemplate
string
Handlebars template for a custom card
maxNumberOfColumns
number
1
Set a maximum number of columns that will display at the widest breakpoint. Possible values are 1,2,3 or 4.
showResultCount
boolean
true
Whether to display the total number of results
card
object
The card used to display each individual result, see the Cards section for more details
noResults
object
Configuration for what to display when no results are found
template
string
Handlebars template for the no results component
displayAllResults
boolean
Shows all results in the vertical when no results are found

Background

The FilterSearch component provides a text input box for users to type characters and select a preset matching filter.

The potential filters displayed are based on fields in the Knowledge Graph. A single FilterSearch can combine multiple filters into one interface. FilterSearch has typo tolerance built in but does not do any natural language processing and only supports selecting an explicit filter.

When a filter is selected, a vertical search is performed. If multiple FilterSearch components are on the page, the search will include all selected filters across all of the components.

Styling

FilterSearch doesn’t come with much styling, so it’s recommended to write custom CSS to style the component.

FilterSearch

The below demo includes some example custom CSS.

Configuration

The only required configuration option beyond container and verticalKey (if not specified in the top level search configuration initialization) is searchParameters.

  • searchParameters specifies which fields should be searchable. It takes in two properties: sectioned and fields.
  • fields takes in an array of field options (fieldId, entityTypeId). sectioned determines if the multiple fields should be seperated by sections.

Using Single vs. Multiple Fields

Filtersearch can filter on a single field, or more than one.

Single Field

Here is an example of FilterSearch using a single field - name

ANSWERS.addComponent("FilterSearch", {
  container: ".filter-search",
  verticalKey: "locations",
  searchText: "Find an Employee",
  searchParameters: {
    fields: [
      {
        fieldId: "name",
        entityTypeId: "ce_person",
      },
    ],
  },
});

Multiple Fields

Here is an example of FilterSearch combining two fields together - name and builtin.location. builtin.location will provide a location autocomplete experience.

ANSWERS.addComponent("FilterSearch", {
  container: ".filter-search",
  verticalKey: "people",
  searchText: "Find an Employee or Location",
  // highlight-start
  searchParameters: {
    sectioned: true,
    fields: [
      {
        fieldId: "builtin.location",
        entityTypeId: "ce_person",
      },
      {
        fieldId: "name",
        entityTypeId: "ce_person",
      },
    ],
  },
  // highlight-end
});

Setting a Default Query

You might want to set a default query on load. To do this, set the query and filter attributes; the former controls the text that displays in the input, while the latter controls the actual filter applied on load.

this.addComponent("FilterSearch", {
  container: ".filter-search-container",
  verticalKey: "locations",
  query: "Peaceful Coffee",
  filter: {
    name: {
      $eq: "Peaceful Coffee"
    }
  },
  searchParameters: {
    sectioned: true,
    fields: [
      {
        fieldId: "builtin.location",
        entityTypeId: "location"
      },
      {
        fieldId: "name",
        entityTypeId: "location"
      }
    ]
  }
});

Example

Here’s a demo of FilterSearch. In this example, we filter on two fields (name and builtin.location). We also pre-applied a query and a filter for the location name “Peaceful Cafe”. Finally, we’ve added custom CSS to style the component.

FilterSearch API

Property Type Default Description
verticalKey
string
REQUIRED verticalKey
placeholderText
string
Placeholder text for the input
searchParameters
object
Params for the FilterSearch
fields
array
List of fileds to query
fields[].fieldId
string
Field ID of the field in KG
fields[].entityTypeIds
string
Entity type api name e.g. healthcareProfessional, ce_person
searchParameters.sectioned
boolean
if true sections search results by search filter
storeOnChange
boolean
If true the selected filter is saved and used for the next search but it does not trigger a new search.
title
string
A title above the FilterSearch box
searchText
string
What are you interested in?
The search text used for labeling the input box
promptHeader
string
Text to show as the first item in autocomplete
autoFocus
boolean
Auto focuses the input box
redirectUrl
string
Redirect to search query to a new URL
query
string
Optional, the query displayed on load. Defaults to the query stored in the url (if any). Does not conduct a search.
filter
object
the filter for component to apply on load, defaults to the filter stored in the url (if any). For more information see the filter section of this API documentation

FilterOptions

Background

The FilterOptions component allows users to filter their search results using a list of static, pre-defined filters. Static filters differ from Facets in that they are defined client-side, which means that they will be rendered pre-search and are not sensitive to the results of the query. Static filters are applied once a search is conducted.

Filter Options

If you are using static filters differently and need to trigger a new search as soon as a static filter changes, use FilterOptions within the FilterBox component and toggle the searchOnChange attribute.

Here’s a basic example:

<div class="filter-container"></div>
ANSWERS.addComponent('FilterOptions', {
  container: '.filter-container',
  control: 'singleoption',
  options: [
    {
      label: 'Pick Up',
      field: 'pickupAndDeliveryServices',
      value: "In-Store Pickup"
    },
    {
      label: 'Delivery',
      field: 'pickupAndDeliveryServices',
      value: "Delivery"
    }
  ]
});

Options

There are two different types of FilterOptions: STATIC_FILTER and RADIUS_FILTER. STATIC_FILTER is used for standard filtering on booleans and string fields, whereas RADIUS_FILTER allows you to filter results based on their distance from the user.

STATIC_FILTER

STATIC_FILTER options take few attributes * field: Corresponds to the field API name in the knowledge graph * value: If the field is a boolean, true or false, otherwise the display name of the field option. * label: The label to display for this option * selected : Whether this option should be selected on load.

If an option is marked as selected: true and you’ve configured a defaultInitial search, it will be applied to the results on load. See the Vertical Search Results guide for more information.

{
  options: [
    {
      // Optional, the label to show next to the filter option.
      label: 'Pick Up',
      // Required, the api field to filter on, configured on the Yext platform.
      field: 'pickupAndDeliveryServices', 
      // Required, the value for the above field to filter by.
      value: "In-Store Pickup",
      // Optional, whether this option will be selected on page load. Selected options stored in the url
      // take priority over this. Defaults to false.
      selected: false
    },
    {
      label: 'Delivery',
      field: 'pickupAndDeliveryServices',
      value: "Delivery"
    }
  
  ]
});

Here’s an example:

RADIUS_FILTER

RADIUS_FILTER takes a value in meters, in addition to a label and the selected boolean.

{
  options: [
    {
      // Required, the value of the radius to apply (in meters). If this value is 0, the SDK will not add explicit radius filtering to the request. The backend may still perform its own filtering depending on the query given.
      value: 8046.72,
      // Optional, the label to show next to the filter option.
      label: '5 miles',
      // Optional, whether this option will be selected on page load. Selected options stored in the url
      // take priority over this. Defaults to false.
      selected: false
    },
    {
      value: 16093.4,
      label: "10 miles",
      selected: true
    },
    {
      value: 40233.6,
      label: "25 miles"
    },
    {
      value: 80467.2,
      label: "50 miles"
    }
  ],
}

Here’s an example:

Advanced Configuration

After you’ve specified your options, you can also take advantage of several of the advanced configuration options. Here, we’ve added a reset button, removed the expand/collapse, and hidden all options beyond two behind a “show more!” button.

ANSWERS.addComponent('FilterOptions', {
  container: ".filter-options-container",
  control: "singleoption",
  optionType: "STATIC_FILTER",
  showReset: true,
  resetLabel: "reset!", //defaults to "reset"
  showMore: true,
  showMoreLimit: 2,
  showMoreLabel: "show more!",
  options: [ ... ]
});

FilterOptions API

Property Type Default Description
control
string
singleoption
singleoption or multioption. singleoption will show a radio control and multioption will show as checkboxes
options
array
The list of options a user can choose from
options[].label
string
Label to show on the filter option
options[].field
string
API Field name (e.g. c_openNow)
options[].value
any
The value to the filter the field by
showReset
boolean
Show a reset button
storeOnChange
boolean
Where the filter value is saved on change and sent with the next search.
optionSelector
string
.js-yext-filter-option
The selector used for options in the template, defaults to ‘.js-yext-filter-option’
showReset
boolean
Whether to show a reset button
resetLabel
string
Reset
The label to use for the reset button
showMore
boolean
true
WWhether to allow collapsing of excess filter options after a limit
showMoreLimit
number
5
The max number of filter options to show before collapsing extras

FilterBox

Background

The FilterBox component allows users to add multiple static filter components together, including FilterOptions. Configuration on the top-level FilterBox component carries through to the individual filter components. Use FilterBox instead of individual filter components if: - A single apply button should impact all filters - The filters are grouped together visually - A set of static filter components should share settings

Bug Alert: There’s currently an issue with filterbox’s searchOnChange functionality. For now, setting this to false will simply hide the apply button, but a new search is needed to the filters to be applied.

Here’s a basic example:

this.addComponent("FilterBox", {
    container: ".filter-box-container",
    searchOnChange: true,
    filters: [
      {
        type: "FilterOptions",
        control: "singleoption",
        optionType: "STATIC_FILTER",
        label: "Services",
        options: [
            {
            label: "Pick Up",
            field: "pickupAndDeliveryServices",
            value: "In-Store Pickup"
            },
            {
            label: "Delivery",
            field: "pickupAndDeliveryServices",
            value: "Delivery"
            }
        ]
        },
        {
        control: "singleoption",
        type: "FilterOptions",
        optionType: "RADIUS_FILTER",
        showExpand: false,
        label: "Within",
        options: [
            {
            value: 8046.72,
            label: "5 miles"
            },
            {
            value: 16093.4,
            label: "10 miles"
            },
            {
            value: 40233.6,
            label: "25 miles"
            },
            {
            value: 80467.2,
            label: "50 miles"
            }
        ]
        } 
    ]
    });

Advanced Configuration & Example

After you’ve specified the individual filter components, you can also take advantage of several of the configuration options that will apply to all included filter components. Here, we’ve added a reset button per filter, and a reset button for the group of filters. We’ve also updated the showMoreLimit, which applies to both FilterOptions components. Finally, we’ve set expand to false for both FilterOptions components, but have overridden it for the static FilterOptions.

FilterBox API

Property Type Default Description
filters
object
REQUIRED List of filter component configurations
verticalKey
string
The verticalKey, required if not specified in top level search configuration.
title
string
Filters
Title to display above the filter components.
showCount
boolean
true
Show the number of results for each filter
searchOnChange
boolean
Execute a new search whenever a filter selection changes. If true, the Apply and Reset buttons will not display.
resetFilter
boolean
Whether to show a reset button per filter
resetFilterLabel
string
Reset
The label to use for the reset button per filter
resetFilters
boolean
Whether to show a reset button for the group of filters. Defaults to true if searchOnChange is true.
resetFiltersLabel
string
Reset
The label to use for the reset button for group of filters.
showMore
boolean
true
Whether to allow collapsing of excess filter options after a limit
showMoreLimit
number
5
The max number of filter options to show before collapsing extras
showMoreLabel
string
show more
If showMoreLimit is true, the label to show for displaying more filter options.
showLessLabel
string
show less
If showMoreLimit is true, the label to show for displaying fewer filter options.
showNumberApplied
boolean
Show the number of applied filter when a group is collapsed.
expand
boolean
true
Allow expanding and collapsing entire groups of filters
applyLabel
string
Apply
The label to show on the apply button. Will only display if searchOnChange is false.

Facets

Background

The Facets component allows users to filter their search results using the facets returned by the Answers API. Facets differ from static filter components in that they are returned by the server, instead of being defined by the client. This means that the server will decide which facets are relevant to a particular query and what their options should be, as well as how many of the results belong to each facet option.

For this reason, the facet component involves less configuration than other filter components. Like other filter components, facets can only be used on a VerticalSearch page. They can be added to an experience like this:

<div class="facets"></div>
ANSWERS.addComponent('Facets', {
  container: '.facets',
  verticalKey: 'VERTICAL_KEY',
});

Basic Configuration

There are a few common configuration options you may want to tweak for the facets component. Here is a standard example:

ANSWERS.addComponent('Facets', {
  container: '.facets',
  verticalKey: 'VERTICAL_KEY',
  searchOnChange: true,
  showCount: false,
  showMoreLimit: 2,
  showMoreLabel: 'More',
  showLessLabel: 'Less'
});

In this example… - showCount: false hides the number of results for each facet option - searchOnChange: true causes the search to automatically refresh as soon as the user selects a facet - showMoreLimit: 10 adds a “Show More” button to reveal more options when there are more than 10 facet options - showMoreLabel and showLessLabel control the labels of the resulting buttons

The resulting component looks something like this:

Facets

Searchable Facets

Some facet fields will have dozens or hundreds of options, so it doesn’t make sense to display them all to the user at once. A better way is to make the facet searchable, which allows the user to search for the particular option they’re looking for. Facets can be made searchable like so:

ANSWERS.addComponent('Facets', {
  container: '.facets',
  verticalKey: 'VERTICAL_KEY',
  searchable: true
});

The result looks like this: Searchable Facets

Field-Specific Configuration

Often it doesn’t make sense to apply the same configuration to all facets in an experience. For example, some facet fields may have hundreds of options and should be made searchable, but others might not.

To apply configuration for particular facet fields, use the transformFacets option. The transformFacets option of the Facets component allows facets data to be fully customized. The function takes in and returns an array of the answers-core DisplayableFacet which is described here. The function also has access to the Facets config as the second parameter.

Here’s an example of using this option to customize a boolean facet and make it searchable.

transformFacets: (facets, config) => {
  console.log(config);
  return facets.map((facet) => {
    console.log(facet);
    const options = facet.options.map((option) => {
      let displayName = option.displayName;
      if (facet.fieldId === "c_acceptingNewPatients") {
        if (option.value === false) {
          displayName = "Not Accepting Patients";
        }
        if (option.value === true) {
          displayName = "Accepting Patients";
        }
      }
      return Object.assign({}, option, { displayName });
    });
    let searchable = false;
    if (facet.fieldId === "paymentOptions") {
      searchable = true;
    }
    return Object.assign({}, facet, { options, searchable });
  });
}

Facets API

Property Type Default Description
verticalKey
string
the vertical for which these facets apply. Required if not included in the top level search configuration.
title
string
Filters
Title to display above the facets
showCount
boolean
Whether to show the number of results for each facet option
searchOnChange
boolean
Whether to execute a new search whenever a facet selection changes
resetFacet
boolean
Show a reset button per facet group
resetFacetLabel
boolean
reset
If resetFacet is true, the label to use for the reset button per facet group
resetFacets
boolean
Show a reset-all button for the facets control. Defaults to true if searchOnChange is false.
resetFacetsLabel
string
reset-all
If resetFacets is true, the label to use to reset all.
showMore
boolean
true
Whether to allow collapsing of excess facet options after a limit
showMoreLimit
boolean
true
The max number of filter options to show before collapsing extras
showMoreLabel
string
show more
If showMore is true, the label for the button to display more facets
showLessLabel
string
show more
If showMore is true, the label for the button to display less facets
expand
boolean
true
Adds an expand/collapse per facet.
showNumberApplied
boolean
true
When facet is collapsed, show the number of facet options applied.
searchable
boolean
If true, make this facet searchable by displaying the filter option search input
placeholderText
string
Search here...
If searchable is true, the placeholder text used for the filter option search input
searchLabelText
string
Search for a filter option
The form label text for the search input
fields
object
DEPRECATED Field-specific overrides
searchable
boolean
If true, make this facet searchable by displaying the filter option search input
placeholderText
string
If searchable is true, the placeholder text used for the filter option search input
control
string
singleopiton
Control type, either singleoption or multiopton
transformFacets
function
Allows for custom transforms of facets as they return
applyLabel
string
apply
If searchOnChange is false, the label to show on the apply button

SortOptions

Background

The SortOptions component shows optional sorting that a user can apply to a set of results. This component is only used on vertical search. SortOptions can be configured to include sorting by a field, distance (automatically calculated from the entity’s address), and relevance. The default sort is the order specified by the serverside configuration. Notably, any sorting applied client-side via this component does not replace what’s in the serverside configuration, it’s simply layered on top. Learn more about how to fully configure sorting in this Hitchhiker module.

SortOptions

Basic Configuration

There are only a few required configuration options for SortOptions; the verticalKey and an options array. Within the options array, you must specify the type of sorting option (either FIELD, ENTITY_DISTANCE or RELEVANCE) and the label for that sorting option.

<div class="sort-options-container"></div>
ANSWERS.addComponent('SortOptions', {
  container: '.sort-options-container',
  verticalKey: 'locations',
  options: [
    {
      type: 'FIELD',
      field: 'c_popularity',
      direction: 'ASC',
      label: 'Popularity',
    },
    {
      type: "ENTITY_DISTANCE",
      label: 'Distance'
    },
    {
      type: 'RELEVANCE',
      label: 'Relevance'
    }
  ],
});

Advanced Configuration

Beyond the basic configuration options, you can also control various settings similar to the FilterOptions and Facets. These include showMore, showMoreLimit, showMoreLabel, showLessLabel, searchOnChange and applyLabel.

Finally, you can control the defaultSortLabel, which is the label for the option that is selected on load and corresponds to the default sort. You can show a reset button via showReset, and the label of that button via resetLabel.

In the below example, we’ve updated the defaultSortLabel and the label for sorting. We’ve also added a reset button with the label “reset the sort”.

What Does Ascending and Descending Mean Per Field Type?

Field ASC DESC
Date Oldest to most recent, IE 1/1/1990, 1/1/2020 Most recent to oldest, IE 1/1/2020, 1/1/1990
Number Smallest to largest Largest to smallest
Boolean False, True True, False
String Special characters, then A-Z Z-A, then special characters

SortOptions API

Property Type Default Description
verticalKey
string
REQUIRED The vertical key for this vertical.
options
array
REQUIRED Array of sorting objects. Each object contains type, label, field and direction.
type
string
REQUIRED The type of sorting option. Can be either FIELD (on a field),ENTITY_DISTANCE (distance), or RELEVANCE (relevance determined by answers algorithm and any sorting logic in the serverside configuration, same as the default sort order).
label
string
REQUIRED The label for this sort option
field
string
Required if type is FIELD. The API name of the field on which to sort.
direction
string
Required if type is FIELD. Can be either ASC (ascending) or DESC (descending). The direction in which to sort.
defaultSortLabel
string
Best Match
The label used for the “default” sort (determined by answers algorithm and any sorting logic in the serverside configuration), defaults to ‘Best Match’
optionSelector
array
.yxt-SortOptions-optionSelector
The selector used for options in the sort options template.
searchOnChange
boolean
Whether or not changing an option triggers a search immediatley. If false the component also renders an apply button that applies the sort. If true, no apply button is shown.
showReset
boolean
Whether or not to show a “reset” in the component. If true, clicking reset will set the component back to the default label.
resetLabel
string
reset
The label to use for the reset button.
showMore
boolean
true
Allow collapsing excess filter options after a limit, defaults to true. Note, screen readers will not read options hidden by this flag, without clicking show more first.
showMoreLimit
string
5
The max number of filter options to show before collapsing extras.
showMoreLabel
string
Show more
The label to show for displaying more options
showLessLabel
string
Show less
The label to show for displaying fewer options.
onChange
function
function() => {}
The callback function to call when changed. Runs before a search is triggered if searchOnChange is true.
label
string
Sorting
The label to be used in the legend above the sort options
applyLabel
string
Apply
The label to be used on the apply button. Only appears if searchOnChange is false.

QASubmission

Background

To fully set up this module, we recommend going through our Hitchhiker Training, which covers how to add create an organization entity, enable the Q&A feature and answer questions.

QASubmission is a form that appears at the bottom of the Universal Search Page or vertical search page. It allows a user to submit a question, along with their name and email. If a user is unable to find what s/he is looking for, they can submit a question.

When a user submits a question, it creates an instance of first party Q&A within Yext. This is available in the listings tab, under Q&A. You can then answer questions within Yext. The answer is sent to the end user’s email (inputted when s/he submitted a question).

QASubmission

Basic Configuration

There are only two required attributes to add QASubmission – a privacyPolicyUrl and an entityId for the corresponding organization entityId.

<div class="question-submission-container"></div>
ANSWERS.addComponent('QASubmission', {
  container: ".question-submission-container",
  entityId: 'org-1',
  privacyPolicyUrl: 'https://mybiz.com/policy',
})

Example

In this more advanced example, we’ve updated the teaser, the description and the buttonLabel.

QASubmission API

Property Type Default Description
entityId
string
REQUIRED the Entity ID of the organization entity in the Knowledge Graph.
privacyPolicyUrl
string
REQUIRED URL for the privacy policy link.
formSelector
string
Native form node within container
Optional, the form selector to use in the component.
sectionTitle
string
Ask a Question
Optional, title displayed in the heading for the form.
teaser
string
Can't find what you’re looking for? Ask a question below.
Teaser displayed for the form, next to the title.
expanded
boolean
true
whether or not the form is expanded by default when a user arrives on the page.
description
string
Enter your question and contact information, and we'll get back to you with a response shortly.
Description that displays above the name and email, once the form is expanded
nameLabel
string
Name
Optional, label for name input
emailLabel
string
Email
Optional, label for email input.
questionLabel
string
Question
Optional, label for question input.
privacyPolicyText
string
By submitting my email address, I consent to being contacted via email at the address provided.
Text before the privacy policy link.
privacyPolicyUrlLabel
string
Learn more here.
Display text for the privacy policy url.
privacyPolicyErrorText
string
You must agree to the privacy policy to submit feedback.
Error message displayed when the privacy policy is not selected.
emailFormatErrorText
string
Please enter a valid email address.
Error message displayed when an invalid email is not submitted
requiredInputPlaceholder
string
(required)
Placeholder displayed in all required fields
buttonLabel
string
Submit
Label displayed on the button to submit a question.
questionSubmissionConfirmationText
string
Thank you for your question!
Confirmation displayed once a question is submitted.
networkErrorText
string
We're sorry, an error occurred.
Error message displayed when there is an issue with the QA Submission request.

Map

Background

The map component is displayed on both universal and vertical search pages. It’s added on a Vertical Search Page, but included as a subcomponent on a Universal Page, within Universal Results on a Universal Search Page.

Map on Universal Page Stand-Alone Map on Vertical Page

Basic Configuration

The basic config for a map requires the apiKey and the mapProvider. All other configuration is optional. We also recommend adding the no results configuration, assuming you are displaying all results as outlined here

<div class="map-container"></div>
ANSWERS.addComponent('Map', {
  container: '.map-container',
  mapProvider: 'mapBox',
  apiKey: '12345',
  noResults: {
    displayAllResults: false,
    visible: false
  },
  
});

Hooks

The Map component provides a few different hooks, where you can provide functions to trigger custom behavior.

Pin Hooks

The relevant item is passed to the call back - onPinClick fires when a pin is clicked - onPinMouseOver fires when a pin is hovered over. - onPinMouseOut fires when a pin is no longer hovered.

JS Hooks

  • onLoaded fires when the JS for the map is loaded.

Example

In the below example, we fire various alerts when pins are clicked or hovered.

ANSWERS.addComponent('Map', {
  container: '.map-container',
  mapProvider: 'mapBox',
  apiKey: '12345',
  onPinClick: function (entity) { console.log("clicked " + JSON.stringify(entity));}
  onPinMouseOver: function (entity) { console.log("hovering on " + JSON.stringify(entity));}
  onPinMouseOut: function (entity) { console.log("leaving " + JSON.stringify(entity));}
  onLoaded: function () { console.log("Loaded JS")},
});

Customizing the Pin

The Map component also accepts a pin function, that allows you to create an entirely custom pin if you’re using Google Maps. Said function should return an object with the following properities:

{
  svg: null, //if you're using an svg
  url: null, //if you're using an image hosted elsewhere
  anchor: null, // e.g. { x: 1, y: 1 }, offsets the pin
  scaledSize: null // e.g. { w: 20, h: 20 }, alters the size
};

Here’s an example using a custom svg (the pin label will automatically be added to the svg):

ANSWERS.addComponent('Map', {
  container: '.map-container',
  mapProvider: 'mapBox',
  apiKey: '12345',
  pin: function () {
    
    return {
      svg: `<svg
            xmlns="http://www.w3.org/2000/svg"
            width="20px"
            height="20px"
            viewBox="0 -1 22 28"
          >
            <g fill="none" fill-rule="evenodd">
              <path
                fill="#848484"
                fill-rule="nonzero"
                stroke="#848484"
                d="M0 10.767c0 5.563 7.196 12.418 9.947 14.836.6.527 1.509.53 2.112.005C14.815 23.212 22 16.423 22 10.767 22 4.82 17.075 0 11 0S0 4.82 0 10.767"
              />
              <text
                fill="#848484"
                font-family="Arial-BoldMT,Arial"
                font-size="12"
                font-weight="bold"
              >
                <tspan x="50%" y="15" text-anchor="middle">
                </tspan>
              </text>
            </g>
          </svg>`
    };
  }
});

Example

Map API

Property Type Default Description
mapProvider
string
REQUIRED Supported map providers include google or mapBox, not case-sensitive
apiKey
string
REQUIRED The API Key used for interacting with the map provider, except for Google Maps if provided clientId
clientId
string
Can be used for Google Maps in place of the API key
collapsePins
boolean
Determines whether or not to collapse pins at the same lat/lng
zoom
number
14
the zoom level of the map
defaultPosition
object
{lat: 37.0902, long: -95.7129}
The default coordinates to display if showEmptyMap is set to true. Takes an object with two properties, lat and lng.
showEmptyMap
boolean
Determines if an empty map should be shown on the initial page load. Also used in no results if specific no results config for the map is not provided.
onPinClick
function
Callback to invoke when a pin is clicked. The clicked item(s) are passed to the callback.
onPinMouseOver
function
Callback to invoke when a pin is hovered. The hovered item(s) are passed to the callback.
onPinMouseOut
function
Callback to invoke when a pin is no longer hovered after being hovered. The clicked item(s) are passed to the callback
onLoaded
function
Callback to invoke once the JavaScript is loaded
noResults
object
displayAllResults
boolean
Whether to display map pins for all possible results when no results are found.
visible
boolean
Whether to display the map when no results are found, taking priority over showEmptyMap. If unset, a map will be visible if showEmptyMap is true OR if displayAllResults is true and alternative results are returned.
pin
function
Custom configuration override to use for the map markers. Should return an object. See here

Pagination

Background

The Pagination component is used on Vertical Search to allow users to navigate to other pages. The default page size is 20 results, and pagination is used to help users navigate to results that are not on the first page.

Default Styling

Here is the default styling for the pagination component:

Pagination

Basic Configuration

Here is a basic example of adding pagination to a vertical results page:

<div class="pagination"></div>
ANSWERS.addComponent("Pagination", {
  container: ".pagination",
});

Configuring Page Size

By default, the page size is set to 20. To override the page size, edit the limit property on the search config in the init. Here is an example of chaning the page size to 50:

ANSWERS.init({
  // API Key, Experience Key, Business ID etc. go here
  search: {
    verticalKey: "advisors",
    limit: 50,
    defaultInitialSearch: "",
  },
});

Hiding First and Last Page

By default, the pagination component will always show a button to easily navigate to the first or last page. This is represented by a double arrow in the search results.

To disable this use the showFirstAndLastButton property. Here is an example or hiding first and last page controls: First and Last Page Controls

ANSWERS.addComponent("Pagination", {
  container: ".pagination",
  showFirstAndLastButton: false
});

Show Multiple Pages

By default, one page is shown at a time. To show multiple page numbers (and allow a user to jump to a specific page), configure maxVisiblePagesMobile and maxVisiblePagesDesktop. The pageLabel can also be removed.

Multiple Pages

ANSWERS.addComponent("Pagination", {
  container: ".pagination",
  maxVisiblePagesMobile: 5,
  maxVisiblePagesDesktop: 1,
  pageLabel: ""
});

Pin First and Last Page Number

A user might want to see how many pages are available when conducting a query, especially for those verticals that lend themselves to high-result queries. It’s not recommended to use this configuration option with showFirstAndLastButton, since the frontend behavior is redundant.

Pin First and Last Page Number

To pin the first and last page, set the pinFirstAndLastPage boolean to true.

ANSWERS.addComponent("Pagination", {
  container: ".pagination",
  maxVisiblePagesMobile: 3,
  maxVisiblePagesDesktop: 10,
  pageLabel: ""
  pinFirstAndLastPage: true,
});

Trigger Behavior On Page Change

The is a function invoked when a user clicks to change pages. It accepts the “destination” page number (newPageNumber), the previous page number (oldPageNumber), and the total number of pages (totalPages).

ANSWERS.addComponent("Pagination", {
  container: ".pagination",
  maxVisiblePagesMobile: 3,
  maxVisiblePagesDesktop: 10,
  pageLabel: ""
  pinFirstAndLastPage: true,
  onPaginate: function(newPageNumber, oldPageNumber, totalPages) {
    console.log(
      "I'm going from " + oldPageNumber + " to " + newPageNumber +
       " and there are " + totalPages + " pages.") 
       // Logs the following when paginating from page 1 to 6: 
       // "I'm going from 1 to 6 and there are 35 pages." 
  }
});

Example

Here’s a fully working example:

Pagination API

Property Type Default Description
verticalKey
string
The verticalKey for this vertical. Required if not included in the top level search configuration.
maxVisiblePagesDesktop
number
1
The maximum number of pages visible to users above the mobile breakpoint.
maxVisiblePagesMobile
number
1
The maximum number of pages visible to users below the mobile breakpoint.
pinFirstAndLastPage
boolean
ensure that the page numbers for first and last page are always shown. Not recommended to use with showFirstAndLastButton. Defaults to false
showFirstAndLastButton
boolean
true
Optional, display double-arrows allowing users to jump to the first and last page of results.
pageLabel
string
Page
Label for a page of results
noResults
object
Configuration of no results
visible
boolean
Whether pagination should be visible when displaying no results.
onPaginate
function
document.documentElement.scrollTop = 0; document.body.scrollTop = 0;
Function invoked when a user clicks to change pages. Default scrolls user to the top of the page. (newPageNumber, oldPageNumber, totalPages) => {}
showFirst - DEPRECATED
boolean
true
Display a double arrow allowing users to jump to the first page of results. DEPRECATED, please use showFirstAndLastButton instead.
showLast - DEPRECATED
boolean
true
Display a double arrow allowing users to jump to the last page of results. DEPRECATED, please use showFirstAndLastButton instead.

LocationBias

Background

The location bias shows the user where we think they are located. The purpose of this component is to inform the user as well as to allow them to opt in for HTML5 geolocation. It is recommended to display this at the bottom of any search results page.

Note: If you want to allow a user to select a location check out the GeoLocationFilter component here.

Default Styling

If we are using IP address to locate the user, the component looks something like this: Location Bias (IP Address)

If the user has opted in to HTML5 Gelocation, then the component looks something like this: Location Bias (Device)

Basic Configuration

The only required option is verticalKey when this is used on Vertical Search Results Page (if not included in top level search configuration).

<div class="location-bias-container"></div>
ANSWERS.addComponent("LocationBias", {
  container: ".location-bias-container",
  // verticalKey: "VERTICAL_KEY"
});

Advanced Configuration

HTML5 Geolocation

Similar to the SearchBar component, you can adjust the options passed to the Geolocation API.

You can reduce the timeout (geolocationOptions.timeout) or increase the maximum age for a geolocation request (geolocationOptions.maximumAge) and add an optional alert if the request fails (geolocationTimeoutAlert).

Additionally, if the accuracy of geolocation accuracy is particularly important, you can enable “high accuracy”, which will provide more accurate geolocation results at the expense of response time and/or device power consumption.

ANSWERS.addComponent("LocationBias", {
  container: ".location-bias-container",
  geolocationOptions: {
    timeout: 500,
    maximumAge: 300000,
    enableHighAccuracy: false
  },
  geolocationTimeoutAlert: {
    enabled: true,
    message: "We are unable to determine your location"
  }
});

Overriding Strings

You can also override the default strings used in the component using the following attributes: - ipAccuracyHelpText: Text displayed when geolocation fails and IP address is used to determine location - deviceAccuracyHelpText: Text displayed when geolocation succeeds and HTML5 is used to determine location. - updateLocationButtonText: Button text used to re-request location information.

ANSWERS.addComponent("LocationBias", {
  container: ".location-bias-container",
  ipAccuracyHelpText: 'based on your internet address',
  deviceAccuracyHelpText: 'based on your device',
  updateLocationButtonText: 'Update your location',
});

Example

LocationBias API

Property Type Default Description
verticalKey
string
If used on Vertical Search Page, the verticalKey for the vertical. Required if not included in top level search configuration.
updateLocationEl
string
.js-locationBias-update-location
Selector for button a user clicks to update their location
ipAccuracyHelpText
string
based on your internet address
Text displayed when geolocation fails, and IP address is used to determine location.
deviceAccuracyHelpText
string
based on your device
Text displayed when geolocation succeeds, and HTML5 is used to determine location.
updateLocationButtonText
string
Update your location
Label of the button to update your location
geolocationOptions
object
Geolocation-related configuration. See Geolocation Documentation for more information.
enableHighAccuracy
boolean
Whether to improve accuracy at the cost of response time and/or power consumption, defaults to false.
timeout
number
6000
The maximum amount of time (in ms) a geolocation call is allowed to take before defaulting, defaults to 1 second.
maximumAge
number
300000
The maximum amount of time (in ms) to cache a geolocation call, defaults to 5 minutes.
geolocationTimeoutAlert
object
Configuration for a native alert, displayed when a call to the geolocation API fails.
enabled
boolean
Whether to display a window.alert() on the page
message
string
We are unable to determine your location
If enabled is true, the message in the alert.

Icon

Background

The icon component is typically created by other components, but it can also be used as a standalone component.

Basic Configuration

<div class='icon-container'></div>
ANSWERS.addComponent('IconComponent', {
  container: '.icon-container',
  iconName: 'pantheon',
});

Built-In Icons

The following is a list of names for the icons that are supported by default. You can reference these names when a component has an attribute to set the icon (this includes the search bar, universal results and no results).

Name Icon
briefcase
calendar
callout
chevron
close
directions
document
elements
email
gear
info
kabob
light_bulb
link
magnifying_glass
mic
office
pantheon
person
phone
pin
receipt
star
support
tag
thumb
window

Icon API

Property Type Default Description
iconName
string
Use one of the predefined icons in the Answers Search UI Library
iconUrl
string
Sets the icon to reference an image URL. Overrides icon name.
classNames
string
Adds class names to the icon. Multiple classnames should be space-delimited.