Implementing the Rich Inline Template

The Rich Inline Template is a prebuilt search results template that offers more flexibility and features than our legacy inline template, while still allowing you to implement and customize it yourself.

It’s designed for those who want more control over the look and functionality of their search page, including support for AI Summary, multiple facets, and additional result fields, without waiting for a custom SERP.

When to use the Rich Inline Template

The Rich Inline Template is a good fit if:

  • You want a faster way to launch a more advanced search results page
  • You have a developer (or agency partner) who can handle implementation and styling
  • You want access to features not available in the legacy inline template, such as:
    • AI Summary
    • Categorized search
    • Result fields like badge (also often referred to as “tags”), breadcrumb, and date
    • Multiple facets

How it works

With this documentation, you will receive:

  • A script
  • HTML snippets
  • A basic stylesheet with structural styling

You are responsible for:

  • Implementing the solution on your website
  • Customizing the styling to match your brand
  • Optionally configuring additional search settings using Cludo’s script parameters

The Rich Inline Template is built using React. The following documentation will guide you through setup and customization.

Search Results and Display Fields

By default, the Rich Inline Template displays the following result fields:

  • Title
  • Description
  • URL

If these additional fields are configured in your crawler setup and content is indexed for them, the template will also display:

  • MetaDescription (Instead of the default Description)
  • Breadcrumb
  • Image
  • Date
  • Badge (also often referred to as “tags”)

These fields are automatically included in the template layout if data is available, and you can choose to style them as needed.

Note: The crawler field names are case-sensitive and must exactly match the fields listed above.

Example search result

Getting started

How to implement the Rich Inline Template

1: Add default stylesheet reference

Add the default stylesheet to the head (<head>) section on your pages to receive basic structural styling. This step is optional.

<link rel="stylesheet" type="text/css" href="https://customer.cludo.com/templates/rich-inline/v1.0/dist/styles/cludo-search-results.css">

2: Add script

Add the script just before the closing body tag (</body>) on all pages.

Here, there are a few required properties that need to be updated:

  • Customer ID and engine ID
    Find these values in MyCludo → Configuration → API)
  • Language
    The default value is ‘en’ for English. You can find the complete list of languages and their ISO code here.
  • Search URL
    This must reflect the destination of your search results page. It is recommended using a relative URL, such as /search.
  • Search input selectors
    If you are using other selectors than the one provided with the standard search input in step #3, these must be added here.
<script>
    window.cludoConfig = {
        /** Required properties **/
        customerId: CUSTOMER_ID,
        engineId: ENGINE_ID,
        language: "en", //Change this to reflect the language of the search
        searchUrl: "/", //Search URL - change this to reflect the actual search URL
        searchInputSelectors: ["#cludo-search-input"], //Array of CSS selectors for input fields that should trigger search
    };
</script>
<script src="https://customer.cludo.com/scripts/bundles/search-script.min.js" type="text/javascript"></script>
<script src="https://customer.cludo.com/templates/rich-inline/v1.0/dist/js/cludo-search-results.js" type="text/javascript" onload=""></script>

3: Add/update search form

Add the search form where it should appear. If you already have a form you would like to use for the search, simply add the selector in the searchInputSelectors array in the search script from step 2.

<form class="cludo-input-form" role="search" id="cludo-search-input">
    <input class="cludo-input-form__input" title="Search the page" name="searchrequest" type="search" autocomplete="off" placeholder="Type your search" aria-autocomplete="list" aria-haspopup="true">
    <button type="submit" title="Search" aria-label="Search" class="cludo-input-form__search-button">Search</button>
</form>

4: Add search results container (search page only)

Add this snippet on the search results page where the results should populate.

<div id="cludo-search-results" class="cludo-search-results">
        <div class="cludo-search-results__layout">
            <div class="cludo-search-results__facets search-filters cludo-search-controls" aria-controls="search-results"></div>
            <div class="cludo-search-results__results-wrapper">
                <div class="cludo-search-results__results search-results" role="region" id="search-results" aria-live="polite" aria-label="Search results"></div>
            </div>
        </div>
</div>

You have now successfully implemented the Rich Inline Template!

How to style the Rich Inline Template

When the steps above are complete, you should have a working search results page, but you’ll most likely want to customize the look and feel.

You can of course inspect the elements in a browser to learn what to style, but we’ve also gathered a list of these below:

Styling the search results

/* Individual search result container */
.cludo-search-results-item{}

/* Search result image (if indexed) */
.cludo-search-results-item__image-container{}

/* Container wrapping all text content in the result */
.cludo-search-results-item__content{}

/* Search result badge (if indexed) */
.cludo-search-results-item__badge{}

/* Search result date (if indexed) */
.cludo-search-results-item__date{}

/* Search result title */
.cludo-search-results-item__title{}

/* Search result description */
.cludo-search-results-item__description{}

/* Search result URL */
.cludo-search-results-item__path-anchor{}

/* Search result breadcrumb (if indexed) */
.cludo-search-results-item__breadcrumbs{}

Styling the search filters (facets)

These are also often referred to as categories.

/* Container wrapping all facets */
.cludo-facet-wrapper{}

/* Individual facet */
.cludo-facet{}

/* Individual facet title */
.cludo-facet__header{}

/* Individual facet list */
.cludo-facet__value-list{}

/* Individual facet value */
.cludo-facet__value-list-item{}

/* Individual facet value when selected */
.cludo-facet__value-list-item.active{}

/* Individual facet - list variation. This could be used for showing the facet on desktop */
.cludo-facet.list-facet{}

/* Individual facet - dropdown variation. This could be used for showing the facet on mobile */
.cludo-facet.dropdown-facet{}

/* Trigger button for dropdown variation facet*/
.cludo-facet__dropdown-header{}

Additional ways to customize the Rich Inline Template

To customize the SERP further, it is possible to add the following additional parameters to the cludoConfig object.

Please note

Some features, such as Banners and AI Summary, are only available with some packages. If these are implemented without being a part of your package, they will not show.

If you’re interested in adding new features to your subscribtion, reach out to your Customer Success Manager.

Below this list, you’ll find a few code examples.

searchResultsWrapperSelector: string,       // A CSS selector to target an HTML container on the 
                                            // search page. The search results template will be 
                                            // rendered inside this container. 
                                            // Default value is "#search-results"

controlsWrapperSelector: string,            // A CSS selector to target an HTML container on the 
                                            // search page. The search controls template will 
                                            // be rendered inside this container. This must be  
                                            // different than the search results container. 
                                            // Default value is ".search-filters"

behavior: {
    allowSearchWithoutSearchword: boolean,  // Allow searches with no search term? Setting this to true 
                                            // will make a wildcard search by default when the search 
                                            // results page is loaded. 
                                            // Default value: false.

    endlessScroll: {                        // Adding this parameter with nested options will
                                            // enable endless scroll. Numbered pagination will only 
                                            // render if this is disabled.
                                            
        stopAfterPage: number,              // The number of results that should load when users
                                            // scroll down and trigger the next 'page' of results.
                                            // Default value: 10.

        resultsPerPage: number,             // The number of pages that should be loaded before 
                                            // endless scroll stops and the 'load more' button appears. 
                                            // Default value: 3.

        bottomOffset: number,               // The offset (in pixels) between the bottom of the
                                            // search results container and the scroll position
                                            // that triggers an endless scroll load. Default value: 50.
    },

    focusOnResultsAfterSearch: boolean,     // Focus on the first search result after a search is made
                                            // Default value: false.

    jumpToTopOnFacetClick: boolean,         // Jump to the top of the page after a facet is clicked
                                            // Default value: false.

    pierceShadowDom: boolean,               // Pierce the shadow DOM when searching for inputs 
                                            // and results containers to use for search
                                            // Default value: false.
},

autocomplete: {
    disable: boolean,                       // Disable autocomplete from appearing 
                                            // Default value: false.

    minimumQueryLength: number,             // The minimum number of letters that need to be 
                                            // typed before autocomplete appears. Default value: 3.

    renderTemplateWhenNoResults: boolean,   // Should the autocomplete template be rendered when no
                                            // autocomplete suggestions are found? Default value: false.

    showInstantSuggestions: boolean,        // Enable Instant Suggestions 
                                            // Default value: false.

    useSearchAsYouType: boolean,            // Should autocomplete provide suggested search pages in 
                                            // addition to suggested terms as the user types a query? 
                                            // Default value: false.
},

facets: {
    keys: string[],                         // An array of keys that will be available as
                                            // facet types. NB if you need more facet keys than the 
                                            // default "Category", please reach out to support@cludo.com

    applyMultiLevel: boolean,               // Should users be able to apply more than one
                                            // facet type to a search? Default value: true

    defaultValues: {                        // Preset facets so they are applied for all searches 
                                            // Example: {'Category': 'Blog'}
        [key: string]: string[]
    },
},
facetOptions: {
    multiSelect: {
                                            // Should users be able to select multiple values for 
                                            // a facet type? Example: {'Category': true}
        [key: string]: boolean,
    },
    customOrder: {
                                            // The order in which facets values should be displayed for
                                            // a facet type. 
                                            // Example: {'Category': ['Blog', 'News', 'Events']}
        [key: string]: string[],
    },
},

categorizeResultsByField: {
    field: string;                          // The field that should be used to categorize 
                                            // results. This field must be a facet type. 
                                            // Example: 'Category'

    maxResultsPerCategory: 2 | 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | undefined; 
                                            // The maximum number of results that should 
                                            // be shown per category. Default value: 5.

    maxCategories: 2 | 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | undefined; 
                                            // The maximum number of categories that should be shown. 
                                            // Default value: 5.
};

overrideStrings: {
                                            // Provide overrides for strings the components. Keep 
                                            // {{value}} as it acts as a template placeholder for 
                                            // a number. 

    your_search_on: string,                 // Default: "Your search for <b>{{value}}</b> "
    total_results: string,                  // Default: "returned <b>{{value}}</b> results"
    total_result: string,                   // Default: "returned <b>{{value}}</b> result"
    in_category: string,                    // Default: " in the category <b>{{value}}</b> result"
    and: string,                            // Default: "and"
    suggested_searches_title: string,       // Default: "Suggested searches"
    template_all_results: string,           // Default: "All results"
    load_more: string,                      // Default: "Load more"
    
    // The following translations are for the message that will show up if no results are found
    template_nrm_use_another_search_word: string,   // Default: "Try another search word",
    template_nrm_try_to_search: string,             // Default: "Try to search",
    template_nrm_without_filters: string,           // Default: "without filters",
    template_nrm_display: string,                   // Default: "Display",
    template_nrm_all_results: string,               // Default: "all results",
},

sort: {
    defaultOrder: {
        [key: string]: string; 
                                            // By default, results will be sorted by relevance to 
                                            // the search query. To set a different sort, set a 
                                            // key-value pair where the key is the name of the field to
                                            // order results by and the value is either 'desc' 
                                            // for descending order or 'asc' for ascending order
                                            // Example: { 'Published_date': 'desc' }
    },
},

theme: {
    resultsPerPage: number,                 // The number of results that should appear on each page of 
                                            // search results. If endlessScroll is enabled it will 
                                            // override this. Default value: 10.
},

tracking: {
    disableExtendedTracking: boolean,       // Should tracking of users' searches and clicks be 
                                            // disabled? Analytics data will no longer appear in the
                                            // MyCludo dashboard. Default value: false.

    googleAnalyticsId: string,              // The specific ID of the Google Analytics property that 
                                            // should receive search events (if Google Analytics 
                                            // tracking is enabled in MyCludo). If no ID is
                                            // specified, the first available property found  
                                            // on the site will be used.
},

voiceSearch: {
    enable: boolean,                        // Should voice search be enabled? A voice search activation
                                            // icon will appear within your search input. 
                                            // Default value: false.

    disableActiveAnimation: boolean,        // While a voice search query is being processed, should the 
                                            // loading animation be disabled?
                                            // Default value: false
},

aiSummary: {
    enable: boolean;                        // Should the AI Summary be enabled? Default value: false.

    loadingElement: string | React.ReactNode;   // The element that will be shown while the AI summary 
                                                // is loading.

    chatIcon: React.ReactNode;              // The icon that will be shown in the chat bubble.

    language: SupportedLanguage;            // The language that the AI summary will be generated in. 
                                            // Default value match the language set for search.

    length: "concise" | "comprehensive";    // The length of the AI summary. Default value: "concise".

    header: string | React.ReactNode;       // If a header is provided, it will be shown in 
                                            // the AI summary.

    disclaimer: string;                     // The disclaimer that will be shown in the AI summary.

    allowFeedback: boolean;                 // Should feedback be allowed on the AI summary? 
    
    feedbackCTA: string;                    // The text that will be shown in the feedback CTA.

    feedbackPositiveIcon: React.ReactNode;  // The positive icon that will be shown in the feedback CTA.

    feedbackNegativeIcon: React.ReactNode;  // The negative icon that will be shown in the feedback CTA.

    feedbackFollowUpPrompt: string;         // The text that will be shown above the follow up 
                                            // questions. 

    feedbackFollowUpQuestions: string[];    // The follow up questions. 

    feedbackCommentPrompt: string;          // The text that will be shown above the comment box. 

    feedbackCommentPromptPlaceholder: string; // The text that will be shown in the comment box. 

    feedbackSubmitButtonText: string;       // The text that will be shown in the submit button. 

    feedbackThankYouMessage: string;        // The text that will be shown in the thank you message. 

    feedbackThankYouMessageIcon: React.ReactNode; // The icon that will be shown in the 
                                                  // thank you message.

    showReferences: boolean;                // Should the references be shown? Default value: true.

    referencesCTA: string;                  // The text that will be shown before the references.
},


callbacks: {
                                            
    afterSearch: (searchData) => {          // A callback function that will run after a search request 
        console.log(searchData);            // completes and search results are returned.
    }, 

    beforeSearch: (searchParams) => {       // A callback function that will run after a user submits 
        console.log(searchParams);          // a search query and before the search request is sent.
    }, 

    beforeRedirect: (searchParams, redirectUrl) => { // When a user makes a search from a page other
        console.log(searchParams);                   // than the search results page, this callback 
                                                     // will run before they are redirected to the
                                                     // search results page.
    }, 

    afterAutocomplete: () => {},            // A callback function that will run after an autocomplete 
                                            // request completes and autocomplete suggestions 
                                            // are returned.
},

Examples

Below are a few examples of using the customization options.

Multiple facets

Custom script example

<script>
      window.cludoConfig = {
        /** Required properties **/
        customerId: CUSTOMER_ID,
        engineId: ENGINE_ID,
        language: "en", //Change this to reflect the language of the search
        searchUrl: "/", //Search URL - change this to reflect the actual search URL
        searchInputSelectors: ["#cludo-search-input"], //Array of CSS selectors for input fields that should trigger search

        /** Optional properties **/
        facets: {
          keys: ["Category", "Feature", "Industry"],
        },
        facetOptions: {
          customOrder: { Category: ["Product info", "Customer work", "Company info", "Blog posts", "Webinars", "Other"],},
        },
      };
</script>

Demo

AI Summary

Custom script example

<script>
      window.cludoConfig = {
        /** Required properties **/
        customerId: CUSTOMER_ID,
        engineId: ENGINE_ID,
        language: "en", //Change this to reflect the language of the search
        searchUrl: "/", //Search URL - change this to reflect the actual search URL
        searchInputSelectors: ["#cludo-search-input"], //Array of CSS selectors for input fields that should trigger search

        /** Optional properties **/
        aiSummary: {
          enable: true,
          showReferences: true,
        },
      };
</script>

Demo

Hint: try to search for ‘banners’

Categorized results

Custom script example

<script>
      window.cludoConfig = {
        /** Required properties **/
        customerId: CUSTOMER_ID,
        engineId: ENGINE_ID,
        language: "en", //Change this to reflect the language of the search
        searchUrl: "/", //Search URL - change this to reflect the actual search URL
        searchInputSelectors: ["#cludo-search-input"], //Array of CSS selectors for input fields that should trigger search

        /** Optional properties **/
        categorizeResultsByField: {
          field: "Category",
          maxResultsPerCategory: 3,
        },
      };
</script>

Demo

Search As You Type

Custom script example

<script>
      window.cludoConfig = {
        /** Required properties **/
        customerId: CUSTOMER_ID,
        engineId: ENGINE_ID,
        language: "en", //Change this to reflect the language of the search
        searchUrl: "/", //Search URL - change this to reflect the actual search URL
        searchInputSelectors: ["#cludo-search-input"], //Array of CSS selectors for input fields that should trigger search

        /** Optional properties **/
        autocomplete: {
          useSearchAsYouType: true,
        },
      };
</script>

Demo

Hint: try to search for ‘content’

Example containing all features above

Custom script example

<script>
      window.cludoConfig = {
        /** Required properties **/
        customerId: CUSTOMER_ID,
        engineId: ENGINE_ID,
        language: "en", //Change this to reflect the language of the search
        searchUrl: "/", //Search URL - change this to reflect the actual search URL
        searchInputSelectors: ["#cludo-search-input"], //Array of CSS selectors for input fields that should trigger search

        /** Optional properties **/
        behavior: {
          allowSearchWithoutSearchword: true,
        },
        facets: {
          keys: ["Category", "Feature", "Industry"],
        },
        facetOptions: {
          customOrder: { Category: ["Product info", "Customer work", "Company info", "Blog posts", "Webinars", "Other"],},
        },
        categorizeResultsByField: {
          field: "Category",
          maxResultsPerCategory: 3,
        },
        autocomplete: {
          useSearchAsYouType: true,
          showInstantSuggestions: true,
        },
        aiSummary: {
          enable: true,
          showReferences: true,
        },
        voiceSearch: {
          enable: true,
        },
      };
</script>

Demo

Hint: try to search for ‘content’

Implementation Comparison

This table provides an overview of the major features available across the different implementation options. It does not include all configuration settings — for more detail, see the “How to customize the Rich Inline Template” section.

Feature Legacy Inline Template (deprecated)Rich Inline TemplateCustom SERP / API / Self-hosted React Implementations
SAYTXX
Instant SuggestionsXXX
Voice SearchXXX
Additional facets – list and/or dropdown viewXX
Additional facet – range (e.g. price or date range)X
Sub facetsX
Display selected filtersX
Sort by – buttons or dropdownX
Categorized resultsXX
Display fieldsDefault (Title, Description, Image, URL)Default + If they exist in crawler: MetaDescription, Breadcrumb, Date, BadgeCustom
BannerXXX
AI SummaryXX
Related SearchesX
Pre-search filters (setting a default filter to be applied on the search)XX