Introduction

The search engine and search experience in SharePoint 2013 has been totally re-written, since its predecessors. In SharePoint 2010 we had something called Best Bets or Visual Best Bets if you worked with FAST for SharePoint. A best bet was a promoted result that was triggered by one or more keywords, used by the search admins to promote certain links or banners for specific search queries. In SharePoint 2013 this is now called a Promoted Results and the procedure of creating them is different and so much better – there’s more ways to trigger on, more ways to render the results etc, but the actual shown result isn’t that smart, until now…

In this post I will show you how to create an even smarter and more intelligent Promoted Result – a best bet that actually uses the search query to do something interesting with. In this sample I will let users enter simple math questions and then we let the promoted result calculate the math question for you (just as the big search engines on the interwebz does).

SNAGHTML5e5971

Creating Promoted Results aka Best Bets

A Promoted Result is created either on Search Service Application, Site Collection or Site level using the Search Query Rules option. To create a new Site Collection scoped Promoted Result you navigate to Site Settings > Search Query Rules. Next thing to do is to choose which scope to create this Query Rule for, choose Local SharePoint Results in this case. You have the option to further narrow down the Query Rule using segments and topic categories, but that’s not relevant for this exercise. Next thing to do is to click on New Query Rule. The Add Query Rule page contains quite a few options to make sweet things happening. First we have to give it a name and then we have to specify the query conditions. Query Conditions is what is used to trigger this promoted result. In order to trigger on our “mathematical” question we need to use a regular expression. To use a regular expression as the Query Condition you have to select Advanced Query Text Match and then write a regular expression.

SNAGHTML6b29a7

I’m no regular expression savant, but this regular expression works for this blog post. Anyone with a cooler or smarter or more complex regex – feel free to post it in the comments.

\d+\s*[/\+\-\/*]\s*\d+

Using a custom page as the Promoted Results

Next up is to add the Promoted Results Action to this Query Rule. This is done by clicking on the Add Promoted Result further down on the Add Query Rule page. When adding a promoted result you will be asked for a Title, a URL and a description. In our case the URL is of interest – we want to render a page containing our logic to calculate the math query.

I let the URL point to a page (an .aspx page we’ll create in a few seconds) and then I pass two query string parameters to it; IsDlg=1 to get rid of the chrome in the page and query={SearchTerms} to pass the actual query to the page. I also check the check box Render the URL as a banner instead of as a hyperlink so that the promoted result will be rendered as an iframe instead of a link.

SNAGHTML70ca44

Seem simple, doesn’t it, but wait – this will not work until you followed all the steps in this post. There is no thing out of the box that allows you to pass the search query to the Visual Best Bet.

Now click Save on the Add Promoted Result page and then Save on the Add Query Rule page.

Creating the custom promoted results page

Now, before we test this (and it also takes a couple of seconds before this promoted result can be used – don’t ask me why!) let’s create our page that should calculate the result from the query. For this demo we create a fairly simple .aspx page with a JavaScript section and a small HTML snippet, as shown in the snippet below:

<%@ Page Inherits="Microsoft.SharePoint.WebPartPages.WebPartPage, Microsoft.SharePoint,     Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"     MasterPageFile="~masterurl/default.master" Language="C#" %>
<asp:Content ContentPlaceHolderID="PlaceHolderAdditionalPageHead" runat="server">
    <script type="text/javascript">
        function getQueryStringValue(name) {
            var qs = window.location.search.substring(1);
            var pairs = qs.split("&");
            for (var i = 0; i < pairs.length; i++) {
                var pair = pairs[i].split("=");
                if (pair[0] == name) {
                    return pair[1];
                }
            }
            return '';
        }
        _spBodyOnLoadFunctions.push(function () {
            var query = getQueryStringValue("query")
            try {
                document.getElementById("result").innerHTML = eval(query)
            } catch (e) {
                document.getElementById("result").innerHTML = "error"
            }
        });
    </script>
    <style>
        #s4-ribbonrow {
            display:none;
        }
    </style>
</asp:Content>

<asp:Content ContentPlaceHolderID="PlaceHolderPageTitleInTitleArea" runat="server">
    Intelligent Best Bet
</asp:Content>

<asp:Content ContentPlaceHolderID="PlaceHolderMain" runat="server">
    <h1>SharePoint Search Calculator</h1>
    <h2>The result is: <span id="result"></span></h2>
</asp:Content>

The first section contains a simple JavaScript that extracts the Search Query from the query string and then uses the JavaScript eval() method on it to “calculate” the value. In the PlaceHolderMain I added a span element which is where the calculator writes the result.

So let’s upload this page to the Documents library in the Search Center – which was the location I specified when creating the Promoted Results. If we now search for something that should be triggered by the Query Rule you will see the page rendered as a banner, but  it will not calculate the query as we expected.

Passing the search query to the custom promoted results page

So, why aren’t our result rendering properly? It all comes down to that the default Display Template for Best Bets/Promoted Results does not pass the search query to the iframe. In order to fix this we need to modify this Display Template. The Display Template that we need to edit is the Item_BestBet.html file.

First we add two lines, directly following the var isVBB = … line, like this

var isVBB = ctx.CurrentItem.IsVisualBestBet;

var url = ctx.CurrentItem.Url
url = url.replace('{SearchTerms}',ctx.CurrentItem.ParentTableReference.Properties.QueryModification)

The code is crafting the URL to use in the iframe by retrieving the URL from the CurrentItem and then replacing the text {SearchTerms} with the actual search terms used.

Next we need to modify the line where the iframe is rendered.

<iframe id="_#= $htmlEncode(id + Srch.U.Ids.visualBestBet) =#_" 
    class="ms-srch-item-visualBestBet" title="_#= $htmlEncode(ctx.CurrentItem.Title) =#_" 
    scrolling="no" frameborder="0px" 
    src="_#= $urlHtmlEncode(url) =#_"></iframe>

Modify the src attribute of the iframe element so that it uses our new url property instead of the default URL value from the current context. Save the file and go back to the Search Center…

See it in action

Now we can take it for a test drive. Search for simple mathematical questions and see the results being rendered as a promoted result.

SNAGHTML80e9e4

Summary

I’ve just shown you how to make the Promoted Results aka Visual Best Bets more intelligent by creating a Query Rule that promotes a web page that does operations on the search query. To get this all to work the secret ingredient was to modify the Display Template for promoted results to allow it to pass the search query to the promoted results page.

I can really see this being extended to provide the users with even more interesting “intelligent” promoted results.