Installation Guide

How to install Site Search 360 on your site

Go to the Design & Publish section of your SS360 Control Panel. It comes with a built-in Search Designer tool allowing you to easily tweak colors, placeholders, result and filter layouts as well as choose an implementation style: results can be shown in an overlay, embedded on your site, or in a fullscreen mode.

Check out this guide exploring the Search Designer settings in detail.

Step 2: Connect Site Search 360 to an existing search bar or add a new one.

The search needs to be connected to a trigger (e.g., a search icon) or a search input field on your site. If you already have a search bar, try loading your website in the top bar and we'll detect it automatically:

  • If your site has several search boxes that should be connected to Site Search 360, you can provide the CSS selectors for your search boxes and buttons manually under General > Search box and Search button selectors:

  • If you don't have a search box on your site yet, you can insert the following code snippet wherever you want the box and search button to be displayed on your site - for example, in your site header:

    <section role="search" data-ss360="true">
       <input type="search" id="searchBox" placeholder="Search…">
       <button id="searchButton"></button>
    </section>
  • You can also go for the "Add a search bar to my website" option and specify before or after which element on your site you'd like the search box to appear:

Step 3: Add the code snippet to your site.

Once you're happy with the design, press "Publish" in the top-right corner to get your personalized code snippet.

We recommend implementing our lightweight script bundle (a single line of JavaScript) so that the next time you return to the Search Designer to tweak some settings, all you'd need to do to apply your changes is click "Publish" and wait for a few minutes. No need to touch the code ever again.

<script async src="https://js.sitesearch360.com/plugin/bundle/0000.js"></script>

Alternatively, you can copy and paste the full configuration script and update it manually with all subsequent changes.

Remember that the SS360 script is supposed to go before the closing </body> tag and that the last four digits vary from project to project, so you'll need to get your own line of code rather than paste the one from this guide to your website.

If you're using a site platform where you can't access your site's or your site template's source code, try adding a code block element instead.

Please note: this documentation page refers to our latest search script (v14). If you are using the v13 script or older, check out our upgrade instructions.

Multiple Configurations

Our Search Designer will offer you a great deal of flexibility when it comes to both the search’s aesthetic and its functionality, and here’s the kicker - you’re not limited to a single setup.

What if you decide to revamp your configuration once it’s live on your site or create a separate one for your dev environment? What if your search needs to be customized for each of the domains you index or even specific sections of a single site? What if you want to add a new search box to your site and make both its design and the results it will return distinctly different from that of your original search box? These are just a few scenarios where an extra config object could come in handy.

In short, this feature will allow you to handle multiple (entirely unique) search moulds independently of one another. Each of them will come with a unique code snippet, so you’ll never have to worry about mixing up your meticulously customized configurations.

To get the ball rolling, click on “Main search” in the upper left corner of the “Design & Publish” section of the Control Panel to open a dropdown list of your config object(s) and press the “Add new configuration” button:

If need be, you can copy the parameters of your original configuration to the new one rather than start from scratch:

Advanced Configuration

There are many options that help you configure and customize the search experience. Here is a complete list of configuration parameters.

You can add them to your ss360Config object by editing the Plugin Configuration section in the "Advanced Configuration" tab (last tab within the Search Designer menu).

Read the inline comments to learn how to use the parameters.

<script>
// create a settings object
var ss360Config = {
   showErrors: false, // shows implementation errors if set to true
   allowCookies: true, // whether to allow the SS360 search script to set cookies
   language: 'en', // search interface language, available options: 'en', 'de', 'fr', 'nl', 'pl', 'it', 'es', 'mx', 'tr', 'pt', 
   ecom: false, // whether the ecom search api should be used (only for ecommerce projects)
   catalogId: undefined, // the catalog that should be included in the search (only for ecommerce projects)
   // suggestions are top matching results or suggested search queries shown in a dropdown below the search box
   suggestions: {
      show: true, // whether to show search suggestions, set to false to disable search suggestions
      trigger: undefined, // a suggestion overlay trigger
      showImages: true, // show images in search suggestions
      linksOpenNewTab: false, // set to true to force suggested results to open in a new tab
      num: 6, // max. number of search suggestions to be shown
      minChars: 3, // min. number of characters typed in the search box to trigger suggestions, default: 3
      highlight: true, // whether matched words should be highlighted, default: true
      throttleTime: 300, // milliseconds until suggestions are triggered after user stops typing, default: 300ms
      maxWidth: 'auto', // max. width of the suggest box, default: as wide as the input box, at least 275px
      showOnMobile: true, // whether to show search suggestions on mobile devices (less than 768px), disables specialMobileSuggestions if set to false, default: true
      mobileScrollOnFocus: true, // whether to scroll the page in order for the search box to be to the top of the window (on screens below 768 px)

      // query suggestion settings (clicking on a suggested query term triggers full search results for the query)
      maxQuerySuggestions: 3, // the maximum number of query suggestions
      querySuggestionHeadline: undefined, // the headline of the query suggestions, e.g. 'Try searching for...', by default no headline is shown
      emptyQuerySuggestions: undefined // suggestions to be shown when the search box gets focus but user hasn't started typing a query, a JSON object mapping content group names to array of suggestions, e.g. suggests:{_:[{name:"The Title",link:"https://mylink.com/",image:"https://placekitten.com/150/150"}]}

      // additional information to be shown in search suggestions
      searchHistoryLabel: 'You recently searched for', // the headline for search queries recently entered by user, displayed on empty search box focus
      maxSearchHistoryEntries: 5, // max. number of recent queries to display when the user focuses a search box, set to 0 to disable search history. If emptyQuerySuggestions is defined, search history gets disabled
      viewAllLabel: 'Show all results', // the label of a 'View All' button shown at the end of the suggestion list, default: undefined - no 'View All' button will be added
      groupCta: {
         show: false, // whether to show call-to-action buttons for each result group in search suggestions, e.g. 'View all blog articles'
         label: 'View all #GROUP# results', // the default label of the CTA, #GROUP# is replaced with the result group name
         groupLabels: {}, // custom CTA labels for your result groups, e.g. {Blog: 'Let\'s check out the blog', _: 'Show everything else'}. If groupLabels aren't specified, the default label is used. Set to null to disable the group CTA, e.g. {_: null} to show no CTA under uncategorized/Other suggestions
         callback: undefined, // the CTA click callback, by default the search results are shown and the selected result group is opened
         lowerCaseNames: false // whether to lowercase the result group names in the default CTA labels
      },
      maxSuggestions: {}, // a mapping of a max. number of suggestions to be shown per result group e.g. {Products: 5, Blog: 1}, this setting has higher priority than contentGroups.include and data-ss360-include attribute; NB: specify the limits for ALL result groups that should be displayed in suggestions, unset groups won't be shown (this overrides contentGroups.include and data-ss360-include)
      dataPoints: undefined, // (deprecated in v14) to use data points in suggestions, this overrides the deprecated extraHtml setting, e.g. {price: {html: '#Price# $', position: 1}, category: {html: '#Category#', position: 2}}
      suggestTemplate: {
         template: undefined,
         preRenderCallback: undefined,
         templateBuiltCallback: undefined,
         postRenderCallback: undefined,
         includeContentGroups: undefined // an array of content group names for which the suggest template should be applied, template will be applied for all content groups if this is not set
      },

      // other search suggestion settings
      triggersSearch: false, // set to true to skip suggestions and trigger full search results as user types, throttleTime lets you adjust how quickly results should be displayed
      equalSearch: false, // set to true if suggestions should be equal to full search results (NB: suggestions aren't counted against the search volume quota while results are)
      forceBelow: false, // set to true if you want to always display suggestions below the search box
      viewKeyMappings: undefined, // used to map things like the 'Other' result group _ to a human readable name, e.g. set by the otherName parameter
      selectionOrder: [], // if you heavily style your suggestions, e.g. display them in columns rather than a list, and the arrow key order is different from the order in the UI, you can set selectionOrder = ['Products', 'Blog'] so that the arrow keys always start with 'Products'
      noSuggestsText: undefined, // text or html to be displayed if no suggestions have been retrieved
      showEmptyStateSuggestions: true, // whether to show the empty state suggestions
      filters: undefined, // sets an initial value to the filter (ecommerce only), it's not query-specific, e.g. [{"name":"Tags","key":"fid#8","values":[{"name":"vegetarian"}]}]
   },
   style: {
      themeColor: '#4a4f62', // affects border color of headlines, links, result group tabs and filter buttons
      accentColor: '#3d8fff', // affects all clickable elements: search result titles, search buttons, 'See more' button, active filters, tab color on hover
      suggestions: undefined, // check Search Designer for customization examples
      defaultCss: true, // whether to include the default CSS,
      searchBox: undefined, // check Search Designer for customization examples
      loaderType: 'skeleton', // can be 'circle', 'square', or 'skeleton'
      animationSpeed: 250, // loading animation speed in milliseconds
      additionalCss: undefined, // custom CSS to add to the plugin's stylesheets, has to be minified e.g. '#ss360-layer{background: red;}'
      redrawTrigger: undefined // a CSS selector to an element which triggers redrawing of the applied styles
   },
   searchBox: {
      placeholder: undefined,
      autofocus: false, // if true, the search box gets focus after initialization
      selector: '#searchBox', // the selector to the search box
      searchButton: '#searchButton', // CSS selector of search buttons
      focusLayer: false, // if true, a layer is shown when the user focuses on the search input
      preventFormParentSubmit: true, // whether to disable submitting of parenting form
      searchButtonLabel: undefined // the label of the search button in Site Search 360 custom search inputs, if not set, a magnifying glass icon is rendered
   },
   results: {
      // embedding search results into your site page rather than showing them in an overlay modal (default)
      embedConfig: undefined, // {
      //   'url': undefined,
      //   'contentBlock':'.page-content-body'
      // }, // if url is given, user is redirected to that page and results are inserted into the specified content block
      showSearchBoxEmbed: false, // whether to show search box in search result block for embed search results
      semanticMode: false, // whether to generate semantic URLs like /s-t-shirts, only to be used with embed mode
      semanticModeParamName: 's-', // the search query prefix in semantic mode
      semanticModeSpaceCharacter: '-' // the character/string to use instead of space in a semantic mode

      // to open a full screen search page when user clicks on a search icon/button
      fullScreenConfig: undefined, 
      // {
      //   trigger: '#ss360-search-trigger',
      //   caption: 'Search this site',
      //   transition: 'fade'
      // }, // trigger is the CSS selector to the element that starts the search full screen overlay and searchCaption the caption on the full screen search page like the search icon/button, caption is displayed on top of the overlay page

      // overlay implementation settings
      showSearchBoxLayover: true, // whether to show search box in search result layover
      layoverTrigger: undefined // a CSS selector that points to an element which should trigger the showing of the layover search layer

      // general result snippet settings
      group: true, // if result groups are set up, results are grouped and split into tabs, no groups are configured when set to false
      showContentGroupHeadings: true, // whether to show the result group names/headings, if navigation.type is set to tabs, headings are visible for screen readers only
      limitPerGroup: true, // if set to true, the maximum number of search results is applied to every single result group, otherwise the limit is spread across all groups, default: true
      highlightQueryTerms: true, // whether to highlight the query terms in search results
      num: 999999, // the maximum number of search results to be returned
      moreResultsPagingSize: 12, // how many results to show per result page, 'See More' button loading the next page, max: 24
      stripHttp: false, // if set to true the protocol part (http:// or https://) will be removed from the visible url shown in the search results
      infiniteScroll: false, // set it to true to show more results as soon as user scrolls to the end of the result block (it only works if navigation.type is 'tabs' or if only one result group has been retrieved)
      searchQueryParamName: 'ss360Query', // the name of the search query parameter
      linksOpenNewTab: false, // whether clicking on the result link should open a new tab/window
      redirectOnSingle: false, // whether to redirect to the only result page instead of showing the result
      focusResultBlock: true, // whether to focus the result block once the results were loaded (to be able to tab directly to the first search result)
      contentDataPoint: 'searchSnippet',
      showVariants: true,
      variantsCountLabel: '+#COUNT# more options available',
      variantsCountLabelSingular: '+#COUNT# more option available',
      categorySearch: { // available for ecom projects only
         active: false,
         urlPattern: undefined, // an url pattern, if the current url matches the pattern, the category search will be executed with the first matching group set as category, e.g. '/categories/(.*)'
         contentBlock: undefined, // a content block, category search results will be rendered into the first matching element
         allIdentifier: undefined, // if the matched category equals to allIdentifier, all categories will be shown
         spaceCharacter: undefined, // all characters in the category name matching the given character will be replaced with a space
         replacementPatterns: undefined // a map of patterns to replacement strings to be performed on the extracted category name
      },
      
      // sorting and filters
      sorting: undefined, // the default sorting option to apply when data points are set up
      filters: undefined, // sets an initial value to the filter, it's not query-specific, e.g. [{"name":"Tags","key":"fid#8","values":[{"name":"vegetarian"}]}]
      nameParsing: true, // whether to use filter names and full values in query params instead of filter ids, sorting options are added to the result page URL as query parameters, e.g. ?ss360Query=recipe&tags=vegetarian
      sortingParamName: 'ss360Sorting' // the default sorting query parameter name in the URL

      // to customize search interface labels and captions; for EN/DE/FR/NL the UI can be auto-translated with the ss360Config.language setting
      caption: 'Found #COUNT# search results for "#QUERY#"', // the caption above the search results
      moreResultsButton: 'See more', // HTML for the more results button, all results are shown if set to null
      noResultsText: 'Sorry, we have not found any matches for your query.', // the text to show when no results are found
      noResultsRedirect: undefined, // the full URL to redirect to when no results are found, e.g. 'https://mysite.com/no-results'
      queryCorrectionText: 'Did you mean "#CORRECTION#"?', // #CORRECTION# is automatically replaced by the corrected query if the Spelling Correction setting is on
      queryCorrectionRewrite: 'Showing results for "#CORRECTION#"', // #CORRECTION## is replaced automatically with the rewritten/corrected query
      orderByRelevanceText: 'Relevance', // the text for the 'order by relevance' sorting option
      sortingLabel: 'Sorting:' // a text label next to the sorting dropdown menu
      
      // result image settings
      lazyLoadImages: true, // to lazy-load images as user scrolls through results, meaning when they become nearly visible rather than all at once
      placeholderImage: undefined, //  by default a striped background will be used instead of missing images, set to null to collapse all missing images or add a URL for a placeholder graphic, e.g. 'https://placekitten.com/200/300'
      hideResultsWithoutImage: false, // whether to hide all results that don't have any image or have a broken image
      checkImageQuality: true, // set to false to allow large aspect ratio images
      showAlternativeImages: true

      // adding call-to-action buttons to result snippets
      cta: [ // array of CTAs to render in the search results, every CTA is an object with the following structure: //
         {
            text: 'The text of the CTA Button', 
            link: 'The link to redirect to after the CTA is clicked', // (default: no redirect), use #RESULT_URL# to redirect to the result page
            renderAsButton: true, // whether to render the CTA as a button, default: true
            icon: 'ss360:arrow', // icon to show inside of the CTA button ('ss360:arrow' - triangle arrow, 'ss360:shopping-cart' - shopping cart icon, svg string, image URL, or 'none'), default: 'ss360:arrow', only rendered if renderAsButton is true
            clickCallback: undefined, // a callback to call after the CTA button is clicked, receives the event object and result JSON as parameter
            includeContentGroups: undefined, // JSON array of result group names for which the CTA should be shown //,
            excludeContentGroups: undefined, // JSON array of result group names for which the CTA should be hidden //,
            position: 'left' // the alignment of the CTA button, 'left', 'center' or 'right' - works only for ctaDirection: 'column'; for ctaDirection: 'row' all CTAs are aligned based on the first item in the list  //
         }
      ],
      ctaDirection: 'column', // how to place multiple CTAs within search result - 'row' vs 'column' (default)
      
      resultTemplate: {
         template: undefined,
         preRenderCallback: undefined,
         templateBuiltCallback: undefined,
         postRenderCallback: undefined,
         highlightContext: undefined, // css selector where query parts should be highlighted
         includeContentGroups: undefined // an array of content group names for which the result template should be applied, template will be applied for all content groups if this is not set
      },
      hideLayerOnBodyClick: true, // // whether to hide the search result layover layer when user clicks outside of the layer (otherwise only the ESC key and close button click will hide the layover layer)
      showRelatedQueries: false, // whether to show related queries in the search result
      relatedQueriesTitle: 'Related Searches:', // related queries title
      relatedQueriesPosition: 'aboveResultLayer', // where to show the related queries ('aboveResultLayer', 'withinResultLayer', 'belowResultLayer')
      pageDescriptionLabel: 'Showing #COUNT# of #TOTAL# results', // a pagination label shown above the 'See more' button, set to null or an empty string to hide the label
      showCopyLinkToPositionButton: true, // whether to show a button to copy a link to the current position in the result set
      copyLinkToPositionButtonLabel: 'Copy a link to this position in the list', // the label of the copy link to the current position button
      copiedLinkToPositionButtonLabel: 'Link copied' // the label of the copy link to the current position button after it's been clicked
   },
   queryTerm: {
      scrollIntoViewBlock: 'start', // how to scroll the text into view on redirect and a single query term match, one of 'start', 'center', 'end' or 'none' (don't scroll into view at all)
      highlightContext: undefined, // a CSS selector to limit a part of the page where redirect query terms are highlighted
      highlight: true, // whether to highlight search terms within result page content (once user selects a result)
      highlightMatchedContent: false, // whether to highlight content that fully matches user query within result page content (once user selects a result)
      scrollOnMultiMatch: false, // whether to scroll to the matched content even if it occurs multiple times on the page
      tokenize: false, // whether to split longer queries into tokens and highlight partial query matches within result page content (e.g. the query 'Site Search 360' would also highlight single 'site', 'search' and '360' words)
      scrollIntoViewBehavior: 'smooth', // the behavior of the scroll text into view, 'smooth' (the page smoothly scrolls to the text - over a few seconds) or 'auto' (the page instantly jumps to the text)
      highlightColor: '#b5f948', // the background color of highlighted text
      highlightOnRedirect: true, // whether to highlight search terms on redirect
      scrollOnRedirect: true // whether to scroll to the highlighted search term on redirect
   },
   contentGroups: {
      include: undefined, // JSON array of result group names to be included in the search result
      exclude: undefined, // JSON array of result group names to be excluded from the search result
      otherName: '', // the name of the uncategorized results that don't belong to any result group
      ignoreOther: false, // whether or not to ignore the "other" result group
      viewNames: {} // mapping of content group names set up in the control panel to view names
   },
   tracking: {
      providers: [], // how to track, supported values: 'GA' (Google Analytics), 'GTM' (Google Tag Manager)
      searchCallback: undefined, // callback before SERP is reported, SERP events aren't reported if this returns false, you'll get the query as the parameter for the callback
      gaAlias: undefined,
      ignoreQueryParam: false, // whether to strip all query params from the url reported to google analytics / gtm
      external: undefined // connects the site’s custom interface to ss360’s insights tracking
   },
   callbacks: { // see the Callbacks section on this documentation page for some additional details
      suggestChange: undefined, // callback triggered after suggestion set is changed, takes boolean indicating whether suggestions are visible as argument and an array of retrieved data sets
      redirect: undefined, // callback to handle search redirects, takes redirect URL as parameter, window.location.href is changed by default
      preSearch: undefined, // a callback that is triggered before the search is executed, e.g. to catch empty queries
      postSearch: undefined, // a callback that is triggered after the search results have been populated
      preSuggest: undefined, // a callback that is triggered before the search suggest is executed, takes the query and search box reference as arguments
      searchResult: undefined, // a callback that is triggered after the search is executed, e.g. to build your own result page from the response
      closeLayer: undefined,
      init: undefined, // function to call after initialization is complete
      moreResults: undefined, // a callback to call when the 'Show More Results' button is clicked
      resultImageError: undefined, // a callback to call for 404 images, should return false value (if the image should be hidden) or a new placeholder image URL, the result of this function has higher priority than the `results.hideResultsWithoutImage` handler, receives the result's DOM Node as first argument
      suggestLine: undefined, // a callback called after a suggestion entry is created
      resultLine: undefined, // a callback called after a search result entry is created
      navigationClick: undefined, // a callback called after a navigation item is clicked, receives the toggled result group name as argument
      preRender: undefined, // a callback called before the search results are rendered (does not get called on 'Show More Results' button click), receives the (grouped) search results as argument, should return a modified search results object if the search results should be modified (e.g. to reorder the result groups), if the received search result object is directly modified, all of the changes are reflected in the search results
      filterRendered: undefined, // a callback called after the filter options have been rendered
      searchError: undefined, // a callback called if the search request fails (e.g. the user is offline, or the search API is not available)
      imageLoaded: undefined, // a callback called every time an image has been loaded in the search results
      queryModification: undefined, // a callback called before the query is execute, should return a modified query
      resultsPreloaded: undefined, // a callback called after a results page has been loaded
      suggestPostRender: undefined, // a callback called after the search suggestions have been rendered
      suggestsLoaded: undefined, // a callback called after the search suggestions have been loaded, receives an array of suggestion data sets as argument
     singleResultPreRenderCallback: undefined // a callback called before a single search result is rendered, receives the result and its variants as arguments
   },
   accessibility: {
      isMainContent: false, // whether to mark ss360 layer as main content of the page
      resultTopHeadingLevel: 2, // heading level to start with in search result (default h2)
      suggestHeadingLevel: 2, // heading level to use in search suggestions, for result group heading
      searchFieldLabel: 'Search query', // invisible label to be used with screen readers when search field is focused, only be used if value is not empty and there is no label element associated to the search field, default: 'Search input'
      srSuggestionsHiddenText: 'Search suggestions are hidden', // text to announce @screen reader after search suggestions have been hidden
      srNoSuggestionsText: 'No search suggestions', // text to announce @screen reader if no suggestions are available
      srSuggestionsCountText: '#COUNT# search suggestions shown', // text to announce @screen reader after search suggestions have been shown, #COUNT# is replaced with the suggestion count
      srOneSuggestionText: 'One search suggestion shown', // text to announce @screen reader after search suggestions have been shown
      srSuggestBoxControlDescription: 'Use up and down arrows to select available result. Press enter to go to selected search result. Touch device users can use touch and swipe gestures.' // text to announce @screen reader after search input is focused - describes keyboard controls
   },
   specialMobileSuggest: {
      enabled: false, // whether to show special mobile suggests, default: false
      breakpoint: 768, // CSS breakpoint to show mobile suggests (max-width: breakpoint)
      placeholder: '', // placeholder for empty suggestions
      searchBoxPlaceholder: '', // the special search box placeholder
      customTopHtml: '', // additional HTML/text content to be shown above special mobile search field
      animateTransitions: true, // whether to animate special mobile transitions
      resizeSearchBoxOnScroll: true, // whether to resize search field when user scrolls special mobile suggests
      trigger: '.ss360-special-mobile-trigger'
   },
   smart404: {
      identifier: 'Page not found', // the string in the title that identifies the page as a 404 page
      cssIdentifier: undefined, // a CSS selector to an element identifying a 404 page, if the element is present on the page, the page is considered a 404, this setting overrides the 'identifier' setting if set
      resultSelector: '#ss360-404', // a CSS selector that points to a content block where alternative search results should be shown
      caption: 'Try going here instead:', // caption for 404 results
      num: 12, // the maximum number of results, cannot be greater than 12
      searchResultsLayerLabel: 'Recommended Links'
   },
   layout: {
      mobile: { // below 992px
         type: 'list', // can be "grid", "masonry", "list" or "mixed", default: "list"
         showImages: true, // whether to show images in search result, default: true
         showSnippet: true, // whether to show text snippet in search result, default: true
         showTitle: true, // whether to show title in search result, default: true
         showDataPoints: true, // whether to show data points in search result, default: true
         showUrl: false, // whether to show link in search result, default: false
         gridColsMd: 2, // grid layout column count for devices between 768px and 991px, default: 2
         gridColsSm: 1, // grid layout column count for devices below 768px, default: 1
         gridContentGroups: [] // array of content groups that should be displayed using grid layout (only for "mixed" layout type)
      },
      desktop: { // 992 px and larger
         type: 'list', // can be "grid", "masonry", "list" or "mixed", default: "list"
         showImages: true, // whether to show images in search result, default: true
         showSnippet: true, // whether to show text snippet in search result, default: true
         showTitle: true, // whether to show title in search result, default: true
         showDataPoints: true, // whether to show data points in search result, default: true
         showUrl: false, // whether to show link in search result, default: false
         gridColsXl: 4, // grid layout column count for devices larger than 1200px, default: 4
         gridColsLg: 3 // grid layout column count for devices between 992px and 1199px, default: 3
         gridContentGroups: [] // array of content groups that should be displayed using grid layout (only for "mixed" layout type)
      },
      masonryCols: { // how many masonry grid columns to show, minimum width to column count mapping (default: 2 columns below 768px, 3 columns between 768px and 991px, 5 columns between 992px and 1199px and 6 columns above 1200px)
         0: 2,
         768: 3,
         992: 5,
         1200: 6
      },
      singleLineGridTitle: false, // whether to force a single line of the search result title with the 'grid' layout
      navigation: {
         position: 'top', // result groups to be shown on 'top', 'left', or 'none'
         type: 'tabs', // navigation layout, can be 'scroll' or 'tabs'; for more than 6 (position: 'top') or 10 (position: 'left') result groups 'scroll' navigation is used
         tabSpacingPx: 8, // spacing between tabs
         borderRadiusPx: 3, // tab border radius
         tabTitle: '#NAME# (#COUNT#)', // e.g. 'Found 43 Recipes for "curry"'
         showGroupResultCount: true, // set to false to hide the result count for the result groups
         forceTabs: true, // whether to always show tabs (even if too many result groups or a single group are retrieved), applied to desktop only
         fallbackToScroll: false, // whether to use scroll navigation instead of tabs on desktop devices (992px and more) when more than 5 (position: 'top') or 10 (position: 'left') result groups are shown
         showAllResultsTab: true, // set to false to hide the 'All Results' tab
         allResultsTabName: 'All Results', // the name of the 'All Results' tab
         allResultsTabTitle: 'All Results (#COUNT#)', // the title of the all results group, e.g. 'All results (367)'
         keepOpenTab: true, // whether to reopen the last focused tab on new query
         allResultsFirst: true, // whether the all results tab should be displayed as first or last tab
         preventDropdown: false, // whether to keep tabs on mobile devices or create a dropdown menu with all available result groups
         forceCaption: false // whether to force the main search result title to be displayed with tabbed navigation
      }
   },
   voiceSearch: {
      enabled: false, // whether to enable voice search for browsers that support Speech Recognition API (a microphone icon is added to your search field if Speech Recognition API is supported)
      lang: 'en-US', // input language (BCP 47 language tag)
      repositionTrigger: undefined, // a CSS selector to an element which triggers a repositioning of the voice search icon once clicked
      color: '#333333', // mic icon color
      autoPosition: true // whether to inline the position attributes to the voice search icon
   },
   filters: {
      enabled: false, // whether to generate and show filter options, default: false
      position: 'left', // where to place the filter view, can be 'top' (above the search results) or 'left' (to the left of the results) + 'Show filter' button is added for mobile devices; default: 'left' for embedded or fullscreen layouts, otherwise - 'top'
      label: 'Filter', // label of the filter column, also used as screen reader text
      showCounts: true, // whether to show result counts for multiple choice filters
      showQuickDelete: true, // whether to show a 'Quick Delete' bar summarizing active filter options and providing a 'Reset All' button
      deleteAllLabel: 'Reset All', // the label of the button that clears all selected filters
      settings: {}, // range filter settings, e.g. {Price: {unit: '$', step: 1, drawHistogram: false}} or another example {Preis: {decimalPlaces: 0} }
      forceSlideIn: false, // whether to hide filters by default and only show them once toggled
      toggleButtonLabel: 'Filter results', // the label of the filter toggle button shown on mobile
      expandedGroupsCount: 6, // number of filter groups to expand by default, other groups are collapsed (default: 6), set to -1 to expand all filter groups
      multiSelectSearchLabel: 'Search #FILTER_NAME#', // the label of multi-select search input
      multiSelectEmptyState: 'No matching filter options.', // the message to show if the filter option search yields empty results
      multiSelectShowMoreLabel: 'See #COUNT# more',
      multiSelectShowLessLabel: 'See fewer options',
      multiSelectSearchThreshold: 12, // min. number of multi-select options required for the search input to be shown
      multiSelectShowMoreThreshold: 12, // min. number of multi-select options required for the 'See more options' section to be shown
      clearGroupLabel: 'clear', // label of the clear all options button within a filter group
      sliderMinUnitLabel: 'Min #UNIT#', // label of the min. val range slider input
      sliderMaxUnitLabel: 'Max #UNIT#', // label of the min. val range slider input
      submitButtonLabel: 'Set', // label of the submit button for range filters
      dateFormatLocale: undefined, // the locale to use when formatting date string
      showOnSingleResult: false, // whether to display filter options ever if those have no influcence on the result set
      preSelect: [] // an array of filter options that will be always included in the filters request (unless a filter option from the same group has been selected by the user)
   },
   dataPoints: {
      include: [], // data points that should be shown in the UI despite being set as hidden
      exclude: [], // data points to be hidden from the UI, array of data point names; you can also uncheck 'Show' in the data point section of the control panel
      single: [], // data points where only the first value should be shown (if multiple values are available), array of data point names; you can also check 'Single' in the data point section of the control panel
      direction: 'row', // the direction of the data point key-value pairs - whether the data points should be shown as a row or as a column (table)
      showNames: true, // whether to show data point names
      collapseBy: ', ', // the (HTML) string to be used when merging rows of the structured data table having the same key, default: ', ', e.g. ‘<br/>, set to null to show data points with the same key in multiple rows
      unique: false, // whether to display only unique values
      sort: [] //array of data point (strings) in the order you want them to show up on the result cards
   },
   subConfigs: { // a map of sub config ids to sub configs, the sub config overrides ss360Config settings by providing the full setting path following the dot notation, can be used for localization, e.g. 'de: {"searchBox.placeholder": "Suchen…"}', set the activeSubConfigId to turn on the desired subconfig (this can also be done after the plugin initializes by calling SS360.changeConfig('activeSubConfigId', 'ID');), set the subconfig id to undefined to use the default ss360Config configuration
   },   
   activeSubConfigId: undefined,
   errorScreen: {
     offline: {
        title: 'You are offline',
	message: 'It seems there\'s a problem with your network. Please check your internet connection.',
	tryAgain: 'Try again'
     },
     blocked: {
	title: 'Search request blocked',
	message: 'Please check your privacy extensions.',
	tryAgain: 'Try again'
     },
    generic: {
	title: 'Oops!',
	message: 'Something went wrong. Sorry about that!',
	tryAgain: 'Try again'
     },
    siteId: {
	title: 'Site ID missing',
	message: 'Please check your configuration code and make sure to provide a valid site ID.',
	tryAgain: 'Learn more'
     },
    ipBlocked: {
	title: 'Blocked',
	message: 'You are not allowed to use this service.'
     }
   },
   forceBranding: false, // whether to force the site search 360 logo to be shown in the search results/suggestions - use true to always show, 'columbo' to show the same branding as on a COLUMBO plan, or 'free' to show the same branding as on a FREE plan
   userGroup: undefined, // the current user group (ecom only)
   queryTag: undefined // the query tag, can be used to tag your searches and then cluster them within the analytics dashboard (e.g. by integration - Store vs. Blog)
};
</script>
<script src="https://cdn.sitesearch360.com/v14/sitesearch360-v14.min.js" async></script>

Callbacks

Some callbacks receive the (slightly modified) search API response or other complex data as arguments. Those are described in this section.

The search API response has the same structure for all callbacks:

{
   query: 'q', // the query (content search only)
   interpretedQuery: { // the query information (ecom search only)
      original: 'q', // the original query
      queryWasCorrected: false, // a boolean flag indicating whether a query correction was performed
      corrected: undefined // the corrected query
   },
   suggests: { // the search results, mapping of result group names to array of results (note: for ecom search a single result entry can be an array containing all resolved product variants)
      Blog: [
         {
            link: 'https://myresult.com',
            name: 'My Result',
            image: 'https://myresult.com/image.jpg',
            content: 'I am the search snippet',
            type: 'HTML', // either HTML, CUSTOM, or YOUTUBE_VIDEO
            html: undefined, // only for CUSTOM results
            dataPoints: [
               { key: 'Price', value: '$15', show: true }
            ],
            identifier: undefined // the article number (ecom search only)
         }
      ]
   },
   totalResultsPerContentGroup: { // a mapping of result group names to number of available results
      Blog: 4
   },
   activeFilterOptions: [
      {
         key: 'fid#2',
         name: 'Author',
         values: [ // only for multiselect filters
            {
               name: 'Exotic',
               value: 'exotic'
            }
         ],
         min: undefined, // the set min value, only for range filters
         max: undefined // the set max value, only for range filters
      }
   ],
   filterOptions: [
      {
         filterType: 'COLLECTION', // the filter type, COLLECTION, DATE, TREE, COLOR, BOOLEAN, RANGE (content search only)
         type: 'COLLECTION', // the filter type, COLLECTION, DATE, TREE, COLOR, BOOLEAN, RANGE (ecom search only)
         key: 'fid#2',
         name: 'Author',
         min: undefined, // for range filters
         max: undefined, // for range filters
         categories: [ // for tree filters (ecom search only)
            {
               conceptId: 'CONCEPT_ID',
               count: 4, // ecom search only
               key: '54979',
               name: 'Concept Name',
               value: 'ROOT/CONCEPT',
               viewName: 'Concept Name',
               children: []
            }
         ],
         values: [
            {
               key: 'Key',
               name: 'Name',
               value: 'Value', // ecom search only
               count: 1 // ecom search only
            }
         ], // for multiselect filters
         counts: { // a mapping of filter value to number of available results (available only for range filters with ecom search, and for all filters with content search)
            exotic: 4
         }
      }
   ],
   sortingOptions: [ // available sorting options (string array for content search, object array for ecom search)
      'Date (descending)',
      'Date (ascending)',
      {
         name: 'Preis',
         key: '4978',
         sort: 'DESC' // ASC or DESC
      } 
   ],
   sorting: 'Date (descending)', // the active sorting option (content search only)
   sortingOrder: 'DESC', // the sorting order, ASC or DESC (content search only)
   activeSortingOption: { // the active sorting option (ecom search only)
      name: 'Preis',
      key: '4978',
      sort: 'DESC' // ASC or DESC
   },
   filterMapping: { // a mapping of result group names to array of filters that should be displayed for the given group (ecom search only)
      Products: ['54979']
   },
   redirect: undefined, // set for redirect mappings, the redirect url
   totalResults: 4 // number of all available results
}

Suggest Change Callback

This callback is called whenever the search suggestions are updated.

ss360Config.callbacks.suggestChange = (suggestionsVisible : boolean, dataSets : Array<SuggestionDataSet>) => {};

The dataSets argument is an array of retrieved data sets with the following structure:

{
   type: 'resultGroup', // the data set type (resultGroup, searchHistory, or dataSet)
   data: [
      {
         title: 'My Result',
         link: 'https://myresult.com'
         image: 'https://placekitten.com/300/200',
         contentGroup: 'Blog',
         dataPoints: [
            { key: 'Price', value: '$15', show: true }
         ]
      }
   ]
}

Pre-Render Callback

This callback is called before a search result is rendered, the first argument is the suggests property of the Search API Response, and the second argument is the entire Search API Response. You can perform modifications on any of those objects and the changes will be reflected in the rendered content.

ss360Config.callbacks.preRender = (suggests : Suggests, data : SearchApiResponse) => {};

Result Line Callback

This callback is called after a DOM element for a single search result has been created, it receives the single result object, and the rendered DOM node as arguments.

ss360Config.callbacks.suggestLine = (suggest : Suggest, node : HTMLElement) => {};
/*
   Sample Suggest Data:
{
   link: 'https://myresult.com',
   name: 'My Result',
   image: 'https://myresult.com/image.jpg',
   content: 'I am the search snippet',
   type: 'HTML', // either HTML, CUSTOM, or YOUTUBE_VIDEO
   html: undefined, // only for CUSTOM results
   dataPoints: [
      { key: 'Price', value: '$15', show: true }
   ],
   identifier: undefined // the article number (ecom search only)
}
*/

Results Preloaded

This callback is called after a page of search results is preloaded and appended to the DOM, e.g. after the More Results button is clicked. It receives the Search API Response.

ss360Config.callbacks.resultsPreloaded = (data : SearchApiResponse) => {};

Post Search Callback

This callback is called after a search query is executed (including a filter or sorting option being selected). It is not called on pagination. This callback receives the Search API Response.

ss360Config.callbacks.postSearch = (data : SearchApiResponse) => {};

Search Result Callback

This callback is called before the search results are rendered, if it is set, the plugin won't render the search result cards. You can use this callback to render the search results yourself. It receives the Search API Response as an argument.

ss360Config.callbacks.searchResult = (data : SearchApiResponse) => {};