<img src="https://secure.leadforensics.com/84962.png" style="display:none;">

Search

The search results from Loop54 are returned in two lists; DirectResults and RecommendedResults. Products in DirectResults contain the actual query in the metadata while RecommendedResults is what we consider to be contextually similar to the query.

Design guidelines

The different results are to be presented in two different blocks on the site. We have chosen to place the recommended results to the right because it works great when showing our features in the demo but on a live site we suggest you put them under the direct results. On the response object you'll find DirectResults_TotalItems which states how many direct hits you have, it is good practice to present it to the user as shown below.

Scenario 1: DirectResults and RecommendedResults are present

Search_Scenario_1.png

Scenario 2: DirectResults are present, but there are no RecommendedResults

If the search query is wide (many hits in different contexts) we might not return any recommended results.

Search_Scenario_2.png

Scenario 3: When a user searches for a word not present in the product catalogue

Whenever a user searches for a query that does not match any product in your catalogue we'll do a "fuzzy" search and try to guess what the user is after. These "fuzzy" results will be delivered in the DirectResults collection. 

 
In this scenario the response will have a flag saying that the engine did not understand the query. It is called MakesSense and will be false (the query made no sense to the engine). The fact that it is a guess has to be shown properly to the user to avoid confusion. 
 
There might also be a list with spelling suggestions along with the results if we've found any relevant suggestions. Mind that there might not be any spelling suggestion and sometimes not even results. We suggest presenting the spelling suggestions as links, and when clicked the site should perform a new search request on the clicked term.

Search_Scenario_3.png

Code examples
SHOW INSTRUCTIONS FOR: PHP JSON JAVA .NET
//if the result does not make sense, show error message
//(note that there may still be results!)
if (!$response->getValue("MakesSense"))
    echo "We did not understand your query.";

//render spelling suggestions
if($response->hasData("SpellingSuggestions"))
{
    $suggestions = $response->getCollection("SpellingSuggestions");
    if(count($suggestions)>0)
        echo "Did you mean: ";

    foreach($suggestions as $suggestionItem)
    {
        echo $suggestionItem->key . " ";
    }
}

Best practice

Paging

Display 20-30 direct hits on the landing page, with the option to continue to page 2, 3 etc.

Results above the fold

Make sure the user does not have to scroll to reach the actual product results. At least 1, but preferably 2, rows of results should be visible above the fold after a search.

The search field

Keep the search query in the search field, even after the user has performed the search. This serves as a form of breadcrumb and makes it far easier for the user to refine their query.

//initialize "Search" request
$request = new Loop54_Request("Search");

//set search query
$request->setValue("QueryString",$_GET{"query"});

//specify number of response items
$request->setValue("DirectResults_FromIndex",0);
$request->setValue("DirectResults_ToIndex",9);
$request->setValue("RecommendedResults_FromIndex",0);
$request->setValue("RecommendedResults_ToIndex",9);

//fetch response from engine
$response = Loop54_RequestHandling::getResponse("http://helloworld.54proxy.com", $request);

//successful response
if ($response->success)
{
    //if the result does not make sense, show error message
    //(note that there may still be results!)
    if (!$response->getValue("MakesSense"))
        echo "We did not understand your query.";

    //render spelling suggestions
    if($response->hasData("SpellingSuggestions"))
    {
        $suggestions = $response->getCollection("SpellingSuggestions");
        if(count($suggestions)>0)
            echo "Did you mean: ";

        foreach($suggestions as $suggestionItem)
        {
            echo $suggestionItem->key . " ";
        }
    }

    //render direct results
    if($response->hasData("DirectResults"))
    {
        $results = $response->getCollection("DirectResults");
        if(count($results)==0)
            echo "There were no items matching your search.";

        foreach($results as $resultItem)
        {
            $productId = $resultItem->key->externalId;
            $productTitle = $resultItem->key->getStringAttribute("Title");
            echo $productId . " " . $productTitle; //render a product on the search results page
        }
    }

    //render recommended results
    if($response->hasData("RecommendedResults"))
    {
        $results = $response->getCollection("RecommendedResults");
        if(count($results)>0)
            echo "Maybe you also want these?";

        foreach($results as $resultItem)
        {
            $productId = $resultItem->key->externalId;
            $productTitle = $resultItem->key->getStringAttribute("Title");
            echo $productId . " " . $productTitle; //render a product on the search results page
        }
    }
}
else
{
    echo $response->requestId; //log this
}
//if the result does not make sense, show error message
POST to  http://helloworld.54proxy.com/search
{
    "UserId" : "helloworlduser",
    "IP" : "127.0.0.1",

    "QueryString" : "bananasss",
    "DirectResults_FromIndex" : 0,
    "DirectResults_ToIndex" : 9
}

Response: 200 OK
{
    "Success" : true,
    "HeroId" : "The Queen of the Brown Mills",
    "Data" : {
        "MakesSense": false,
        "DirectResults_TotalItems": 1,
        "SpellingSuggestions": [
          {
            "Key": "banana",
            "Value": 1694
          }
        ]
    }
}

Best practice

Paging

Display 20-30 direct hits on the landing page, with the option to continue to page 2, 3 etc.

Results above the fold

Make sure the user does not have to scroll to reach the actual product results. At least 1, but preferably 2, rows of results should be visible above the fold after a search.

The search field

Keep the search query in the search field, even after the user has performed the search. This serves as a form of breadcrumb and makes it far easier for the user to refine their query.

POST to  http://helloworld.54proxy.com/search
{
    "UserId" : "helloworlduser",
    "IP" : "127.0.0.1",

    "QueryString" : "banana",
    "DirectResults_FromIndex" : 0,
    "DirectResults_ToIndex" : 9,
    "RecommendedResults_FromIndex" : 0,
    "RecommendedResults_ToIndex" : 9
}

Response: 200 OK
{
    "Success" : true,
    "HeroId" : "The Queen of the Brown Mills",
    "Data" : {
        "MakesSense" : true,
        "DirectResults_TotalItems" : 2,
        "RecommendedResults_TotalItems" : 1,
        "RelatedQueries" : [],
        "DirectResults" : [{
                "Key" : {
                    "ExternalId" : "1",
                    "EntityType" : "Product",
                    "Attributes" : {
                        "Manufacturer" : [
                            "The banana company"
                        ],
                        "Category" : [
                            "Fruit"
                        ],
                        "Title" : [
                            "Banana"
                        ]
                    }
                },
                "Value" : 467.5
            }, {
                "Key" : {
                    "ExternalId" : "7",
                    "EntityType" : "Product",
                    "Attributes" : {
                        "Manufacturer" : [
                            "The banana company"
                        ],
                        "Category" : [
                            "Fruits"
                        ],
                        "Title" : [
                            "Organic Apple"
                        ]
                    }
                },
                "Value" : 100
            }
        ],
        "RecommendedResults" : [{
                "Key" : {
                    "ExternalId" : "3",
                    "EntityType" : "Product",
                    "Attributes" : {
                        "Manufacturer" : [
                            "Fruits n Veggies"
                        ],
                        "Category" : [
                            "Fruits"
                        ],
                        "Title" : [
                            "Apple"
                        ]
                    }
                },
                "Value" : 0.171984790212361
            }
        ]
    }
}
//if the result does not make sense, show error message
//(note that there may still be results!)
if (!loopResponse.getBoolean("MakesSense"))
    response.getWriter().print("We did not understand your query.");
//render spelling suggestions
if (loopResponse.hasData("SpellingSuggestions"))
{
    List items = loopResponse.getItemArray("SpellingSuggestions");

    if(items.size()>0)
        response.getWriter().print("Did you mean: ");

    for(int i=0;i<items.size();i++)
    {
        Item item = items.get(i);
        response.getWriter().print(item.key);

        if(i<items.size()-1)
            response.getWriter().print(", ");
    }
}
    

Best practice

Paging

Display 20-30 direct hits on the landing page, with the option to continue to page 2, 3 etc.

Results above the fold

Make sure the user does not have to scroll to reach the actual product results. At least 1, but preferably 2, rows of results should be visible above the fold after a search.

The search field

Keep the search query in the search field, even after the user has performed the search. This serves as a form of breadcrumb and makes it far easier for the user to refine their query.

//initialize "Search" request
Request loopRequest = new Request("Search",request,response);

//set search query
loopRequest.setValue("QueryString",request.getParameterValues("query")[0]);

//specify number of response items
loopRequest.setValue("DirectResults_FromIndex",0);
loopRequest.setValue("DirectResults_ToIndex",9);
loopRequest.setValue("RecommendedResults_FromIndex",0);
loopRequest.setValue("RecommendedResults_ToIndex",9);

//fetch response from engine
Response loopResponse = RequestHandling.getResponse("http://helloworld.54proxy.com", loopRequest);

//successful response
if (loopResponse.success)
{
    //if the result does not make sense, show error message
    //(note that there may still be results!)
    if (!loopResponse.getBoolean("MakesSense"))
        response.getWriter().print("We did not understand your query.");

    //render spelling suggestions
    if (loopResponse.hasData("SpellingSuggestions"))
    {


        List items = loopResponse.getItemArray("SpellingSuggestions");

        if(items.size()>0)
            response.getWriter().print("Did you mean: ");

       for(int i=0;i<items.size();i++)
        {
            Item item = items.get(i);
            response.getWriter().print(item.key);

            if(i<items.size()-1)
                response.getWriter().print(", ");
        }
    }

    //render direct results
    if(loopResponse.hasData("DirectResults"))
    {
        ArrayList results = loopResponse.getItemArray("DirectResults");
        if(results.isEmpty())
            response.getWriter().print("There were no items matching your search.");

        for(Item resultItem: loopResponse.getItemArray("DirectResults"))
        {
            String productId = ((Entity)resultItem.key).externalId;
            String productTitle = ((Entity)resultItem.key).getAttribute("Title").firstValue();
            response.getWriter().print(productId + " " + productTitle); //render a product on the search results page
        }
    }

    //render recommended results
    if(loopResponse.hasData("RecommendedResults"))
    {
        ArrayList results = loopResponse.getItemArray("RecommendedResults");
        if(!results.isEmpty())
            response.getWriter().print("Maybe you also want these?");

        for(Item resultItem: loopResponse.getItemArray("RecommendedResults"))
        {
            String productId = ((Entity)resultItem.key).externalId;
            String productTitle = ((Entity)resultItem.key).getAttribute("Title").firstValue();
            response.getWriter().print(productId + " " + productTitle); //render a product on the search results page
        }
    }
}
else
{
    response.getWriter().print("ERROR: " + loopResponse.requestId); //keep track of unsuccessful requests
};
//if the result does not make sense, show error message
//(note that there may still be results!)
if (!response.GetValue<bool>("MakesSense"))
    Response.Write("We did not understand your query." + Environment.NewLine);

//render spelling suggestions
if (response.HasData("SpellingSuggestions"))
{
    var keys = response.GetValue<list<item<string>>>("SpellingSuggestions").Select(o => o.Key);
    var suggestions = string.Join(", ", keys);

    Response.Write("Did you mean: " + suggestions + "?" + Environment.NewLine);
}

Best practice

Paging

Display 20-30 direct hits on the landing page, with the option to continue to page 2, 3 etc.

Results above the fold

Make sure the user does not have to scroll to reach the actual product results. At least 1, but preferably 2, rows of results should be visible above the fold after a search.

The search field

Keep the search query in the search field, even after the user has performed the search. This serves as a form of breadcrumb and makes it far easier for the user to refine their query.

//initialize "Search" request
var request = new Loop54.Request("Search");

//set search query
request.SetValue("QueryString", Request.QueryString["query"]);

//specify number of response items
request.SetValue("DirectResults_FromIndex", 0);
request.SetValue("DirectResults_ToIndex", 9);
request.SetValue("RecommendedResults_FromIndex", 0);
request.SetValue("RecommendedResults_ToIndex", 9);

//fetch response from engine
var response = Loop54.RequestHandling.GetResponse("http://helloworld.54proxy.com", request);

//successful response
if (response.Success)
{
    //if the result does not make sense, show error message
    //(note that there may still be results!)
    if (!response.GetValue("MakesSense"))
        Response.Write("We did not understand your query." + Environment.NewLine);

    //render spelling suggestions
    if (response.HasData("SpellingSuggestions"))
    {
        

Related Queries 

The search response from the engine may include a collection called RelatedQueries. Related queries are phrases that other customers have searched for and that are within the same context as the query in the current search request. 
 
We recommend that these are presented at the top right corner on a desktop, and just before the paging buttons for a mobile device. 5 to 8 related queries is a reasonable amount. 
 

Parameters

  • QueryString: the actual query typed by the client
  • Paging: The results can be separated into pages using FromIndex and ToIndex (inclusive). Asking for DirectResults_FromIndex : 0 and DirectResults_ToIndex : 9 will yield 10 results. You will have to apply paging to the DirectResults, RecommendedResults, and RelatedQueries collections.
  • Descriptives: IP and UserId (the library should take care of this)
  • Faceting: See separate paragraph.