AddSearch is an instant search for websites that gives results immediately and is very easy to install. This manual demonstrates how to integrate the search widget into the default Alloy site template developed by Optimizely team.

How to Install AddSearch onto a Optimzely/Episerver CMS

First, find your Site key by following these instructions:

  1. Login to your AddSearch Account
  2. Go to Keys and installation under Setup
  3. Copy your site key under Your Site Key

Use our Search Designer tool to configure the widget according to your needs and copy the installation script. Then paste the script into your website template where you would like the AddSearch field to appear. Here is an example of what the script snippet might look like:

<script>
 window.addsearch_settings = {
  "asw_01": {
    "show_search_suggestions": false,
    "search_suggestion_position": "left",
    "default_sortby": "relevance",
    "display_date": false,
    "display_meta_description": false,
    "display_result_image": true,
    "link_target": "_self",
    "hide_logo": false,
    "direction": "ltr",
    "analytics_enabled": false,
    "automatic_filter_results_by_site_language": false
  }
} 
</script>
<script src="https://cdn.addsearch.com/v5/addsearch-ui.min.js?key=xxxxxx&id=asw_01"></script>

Create a block in Optimizely representing a search widget

The best way to integrate a widget inside CMS would be to create a Block-wrapper around with widget’s settings connected to the Block’s properties. Such approach allows following:

  1. In edit mode Admin can create single instance of the Block and share it across all pages where search widget is needed.
  2. Admin can create another instance of the Block if some pages require another search widget’s configuration.
  3. Block-wrapper is represented by following code:
[ContentType(DisplayName = "Search Widget", GUID = "7B1048A4-E521-4B38-A05E-47E88BCE9A26")]
public class SearchWidgetBlock : BlockData
{
    [Display(Order = 1)]
    [Required]
    public virtual string AddSearchSiteKey { get; set; }
    
    [Display(Order = 2)]
    [Required]
    public virtual string Placeholder { get; set; }
    
    [Display(Order = 3)]
    public virtual bool ShowSearchSuggestions { get; set; }
    
    [Display(Order = 4)]
    [Required]
    public virtual string SearchSuggestionPosition { get; set; }
    
    [Display(Order = 5)]
    [Required]
    public virtual string DefaultSortBy { get; set; }
    
    [Display(Order = 6)]
    public virtual bool DisplayDate { get; set; }
    
    [Display(Order = 7)]
    public virtual bool DisplayMetaDescription { get; set; }
    
    [Display(Order = 8)]
    public virtual bool DisplayResultImage { get; set; }
    
    [Display(Order = 9)]
    [Required]
    public virtual string LinkTarget { get; set; }
    
    [Display(Order = 10)]
    public virtual bool HideAddSearchLogo { get; set; }
    
    [Display(Order = 11)]
    [Required]
    public virtual string Direction { get; set; }
    
    [Display(Order = 12)]
    public virtual bool AnalyticsEnabled { get; set; }
    
    [Display(Order = 13)]
    public virtual bool AutomaticFilterResultsBySiteLanguage { get; set; }

    public override void SetDefaultValues(ContentType contentType)
    {
        base.SetDefaultValues(contentType);

        AddSearchSiteKey = "150618b356e2412604a6cc625eb0a591";
        Placeholder = "Search page";
        SearchSuggestionPosition = "left";
        DefaultSortBy = "relevance";
        DisplayResultImage = true;
        LinkTarget = "_self";
        Direction = "ltr";
    }
}

Since the block doesn’t contain any logic except field mapping – you don’t need a Controller or BlockComponent. As the last step, you must add a View for this Block as demonstrated below.
Path to locate: /Views/Shared/Blocks/SearchWidgetBlock.cshtml

@model SearchWidgetBlock
<script>
 window.addsearch_settings = {
  "asw_01": {
    "placeholder": "@Model.Placeholder",
    "show_search_suggestions": @Model.ShowSearchSuggestions.ToString().ToLower(),
    "search_suggestion_position": "@Model.SearchSuggestionPosition",
    "default_sortby": "@Model.DefaultSortBy",
    "display_date": @Model.DisplayDate.ToString().ToLower(),
    "display_meta_description": @Model.DisplayMetaDescription.ToString().ToLower(),
    "display_result_image": @Model.DisplayResultImage.ToString().ToLower(),
    "link_target": "@Model.LinkTarget",
    "hide_logo": @Model.HideAddSearchLogo.ToString().ToLower(),
    "direction": "@Model.Direction",
    "analytics_enabled": @Model.AnalyticsEnabled.ToString().ToLower(),
    "automatic_filter_results_by_site_language": @Model.AutomaticFilterResultsBySiteLanguage.ToString().ToLower()
  }
} 
</script>
<script src="https://cdn.addsearch.com/v5/addsearch-ui.min.js?key=@Model.AddSearchSiteKey&id=asw_01"></script>

In our example we put Site Key as a property to the block for demonstration purpose, but more secure approach would be to place it inside app configuration file or any Key Vault solution

Configure Block to be rendered as part of Website’s header

In this step you need to modify code of the default Alloy website to display the search widget at the top of the website.
You need to add a new property to the /Models/Pages/SitePageData.cs. This class represents the basic model for all pages.

[Display(GroupName = SystemTabNames.Content, Order = 300)]
[AllowedTypes(typeof(SearchWidgetBlock))]
public virtual ContentReference SearchWidgetRef { get; set; }

You must add a new property to the /Models/ViewModels/LayoutModel.cs. This class holds common data for all pages.

public SearchWidgetBlock SearchWidget { get; set; }

You need to modify logic in /Controllers/PageControllerBase.cs. This class executes a common logic to prepare basic layout model for rendering. At this point we need to resolve a reference to the search Block and initialize LayoutModel with Block’s instance.

protected readonly Injected<IContentLoader> ContentLoader;

public virtual void ModifyLayout(LayoutModel layoutModel)
{
    if (PageContext.Page is SitePageData page)
    {
        layoutModel.HideHeader = page.HideSiteHeader;
        layoutModel.HideFooter = page.HideSiteFooter;

        if (page.SearchWidgetRef != null && ContentLoader.Service.TryGet(page.SearchWidgetRef, out SearchWidgetBlock instance))
        {
            layoutModel.SearchWidget = instance;
        }
    }
}

And as the last step you need to modify /Views/Shared/Header.cshtml to render our Block with search widget in the header on each page where it’s configured.

@using EPiServer.Web

@model IPageViewModel<SitePageData>

@{
    HelperResult ItemTemplate(HtmlHelpers.MenuItem item)
    {
        <li class="nav-item">
            @Html.PageLink(item.Page, null, new { @class = "nav-link" + (item.Selected ? " active" : null) })
        </li>
        return new HelperResult(w => Task.CompletedTask);
    }
}

<header>
    <div class="container">
        <nav class="navbar navbar-expand-lg">
            <div class="container-fluid">
                <a class="navbar-brand logo" href="@Model.Layout.LogotypeLinkUrl" title="@Model.Layout.Logotype.Title">
                    @Html.PropertyFor(x => x.Layout.Logotype)
                </a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"><i class="bi bi-list"></i></span>
                </button>
                <div class="collapse navbar-collapse" id="navbarNav">
                    <ul class="navbar-nav">
                        @Html.MenuList(SiteDefinition.Current.StartPage, ItemTemplate)
                    </ul>
                </div>
                @if (Model.Layout.SearchWidget != null)
                {
                    @Html.PropertyFor(x => x.Layout.SearchWidget)
                }
            </div>
        </nav>
    </div>
</header>

Configure widget in Edit mode

At this point, your codebase is ready, and you can launch/deploy a website and enter Edit mode to configure the widget to be shown on specific pages.
As a first step, we need to create and publish an instance of our Block in the global blocks’ catalogue and configure its properties according to your needs:
optimizely-elementor-1
To link the block to the Start page, do the following:

  1. Navigate to the Start page in the pages’ tree
  2. Find SearchWidgetRef property on tab Content
  3. Click Select Block button and pick up a Block created on previous step
  4. Publish a page

optimizely-elementor-2
Repeat this instruction for all pages where you would see your search widget enabled.The expected result will be as shown below.
optimi 3

Was this helpful?

Need more help?

We’re always happy to help with code or other questions you might have. Search our documentation, contact support, or connect with our sales team.