Dušan Lovre

Putting the R in Love since 1982

Young lady typing on keyboard of laptop in living room

Optimizely Search & Navigation Autocomplete – get suggestions based on culture

In the company I used to work, we wanted to implement a search autocomplete feature, that would give the visitor suggestions based on their input in the search box. Optimizely CMS, in particular Search & Navigation (formerly known as Episerver Find) has this out of the box, but there is a catch.

Out of the box, searches can be tracked, which will provide us with, among other things, terms that our visitors are searching for. The problem is that these terms will be tracked per site definition. If you have stand-alone sites, this works fine, but if you have a scenario where you localize a master site, then all those localized sites will share the same suggestions. For instance, if you have sites in Mexico, Peru, Chile and Colombia, and they are all based off the same master site (i.e. localized into their specific cultures), all these sites will share the same autocomplete suggestions.

The way to get around this is to use custom tracking. While figuring this one out, I had a lot of help from Optimizely support that always delivers (kudos!), and from reading this article.

NB: The downside of this solution that Find UI will not be aware of these custom tags, which can mess things up if you’re planning editorial suggestions as well. However, these can be dealt with in many other ways.

The first thing is to remove the built-in .Track() from your search, if you are using it. We will be tracking searches manually, adding custom tags.

Create a method like this:

private void TrackQuery(string query, int nrOfHits, string id, string culture)
{
    _searchClient.Statistics().TrackQuery(query, x =>
    {
        x.Id = id;
        x.Tags = GetTrackingTags(culture);
        x.Query.Hits = nrOfHits;                
    });
}

GetTrackingTags looks like this:

private IEnumerable<string> GetTrackingTags(string culture)
{
    var tags = new List<string>();

    if (!string.IsNullOrWhiteSpace(culture))
    {
        tags.Add("culture:" + culture);
    }

    return tags;
}

In your search service, after the search is performed, call TrackQuery. The exact arguments will vary, but it will be along these lines:

TrackQuery(searchParams.SearchString!, totalHits, new TrackContext().Id, culture);

This will now track the query, adding the custom culture tag with the appropriate culture (this can be passed to the service in many ways).

To retrieve the suggestions, implement a method:

public IEnumerable<string> GetAutocompleteSuggestions(string query, string culture, int size)
{
    if (string.IsNullOrWhiteSpace(query))
    {
        return Enumerable.Empty<string>();
    }

    var suggestions = _searchClient.Statistics().GetAutocomplete(query, x =>
    {
        x.Tags = GetTrackingTags(culture);
        x.Size = size;
    });

    return suggestions.Hits.Where(h => h.Type == "statistical").Select(h => h.Query);
}

That’s it! The searches your visitors make will now be tracked with the appropriate culture, and those that yield results will be stored as statistical, which you can then retrieve using GetAutocompleteSuggestions.

For editorial suggestions, as I mentioned there are many ways to implement this to be culture-sensitive. One example would be adding a List<string> property to your search page type. I am sure there are others as well. 🙂