Properly Handling Sitecore Item URLs in Coveo for Sitecore 7

November 14, 2014 | Ed Kapuscinski

Sitecore logo inside a search magnifying glass iconCoveo for Sitecore opens up a lot of new possibilities for using search on a website. Here at TBG, we've discovered, however, that it needs help in generating URI for display and use on site search pages.

This is because of how Coveo works fundamentally: indexing content and storing the URI for that content in the search index entry for the item.

However, in Sitecore, that indexing happens in the context of Sitecore's "shell" site, so in the case of Coveo in Sitecore, the stored URIs will always point to the content in the context of that site on the server that it's indexed from. Using the out-of-the-box indexing, an item that lives at "/sitecore/content/CNHS Site/Locations" and that is being indexed on my local development environment, will have "http://local.cnat.dolphin.berndtgroup.net/cnhs-site/locations" indexed as the "Click URI" and "/CNHS Site/Locations" stored as the "Print URI.”

At TBG, we frequently have Sitecore running across multiple servers that serve different purposes (usually content preview and delivery). Coveo’s indexing can sometimes create problems for us: having the URI in the indexing server (usually the content management server) in the URI will send users to the wrong place. Additionally, the stored URIs contain references to parts of the content tree that site visitors shouldn't see. The URIs will work with them (because Sitecore is very forgiving), but it's not the user experience we want, and it can have negative search engine optimization (SEO) and other effects.

There is straight forward fix for this, however.

Coveo for Sitecore uses pipeline processors for its indexing, so we can create code that gets executed and cleans up the URIs that get stored in the index for us, then we can code our search results display pages to account for the standardized URIs and show the right ones to our site visitors.

The process starts by creating a method that will get the Sitecore item's proper, relative URI using the link manager. Though, there is one important nuance to this step.

The indexing of content items in Coveo for Sitecore is done in the context of the Sitecore "shell" site. In essence, this means that for the above referenced item, the URI link manager would return:"/sitecore/shell/cnhs-site/locations.” We need to account for this indexing and transform the URI so it’s more in context of the sites it'll be displayed on.

The most obvious solution for this is to switch the context site while the item is indexed. However, this won't work in our most common scenarios because the item may actually be displayed on one of a handful of sites (Dev, QA and Stage in our development environment alone). Therefore, it's sometimes helpful to use the rather brute force approach of doing string replacement. This is one place where your experience and individual project scenario will probably dictate what you need to do.

Here's the code we used to do our URI replacement:

using System;
using System.Text;
using System.Text.RegularExpressions;
using Coveo.Framework.Processor;
using Coveo.SearchProvider.Pipelines;
using Sitecore;
using Sitecore.ContentSearch;
using Sitecore.Data.Fields;
using Sitecore.Data.Items;
namespace CNAT.CoveoExtensions
{
  public class CustomItemsProcessor : IProcessor<coveopostitemprocessingpipelineargs>
  {
      public void Process(CoveoPostItemProcessingPipelineArgs p_Args)
      {
         if (p_Args.Item is SitecoreIndexableItem) {

             // Get the Item
             Item item = ((SitecoreIndexableItem) p_Args.Item).Item;
             
             //Get the item's URL from Sitecore (note: this will be in the context of the "shell" site)
             String url = Sitecore.Links.LinkManager.GetItemUrl(item);
             
             // Remove the common part of the url.
             url = url.Replace("/sitecore/shell", "");

             // Remove the part where it lives in CNHS Site in the content tree
             if (url.StartsWith("/cnhs-site"))
             {
                 url = url.Replace("/cnhs-site", "");
             }
           
             // Set the Coveo Clickable and Printable URIs
             p_Args.CoveoItem.ClickableUri = url;
             p_Args.CoveoItem.PrintablePath = url;

         }
      }
  }
}

Once you've created your processor, you need to add it to the Coveo.searchProvider.config so it gets executed when an item is indexed.

Add it to the "coveoPostItemProcessingPipeline" pipeline, after the AddCoveoVersionTag processor.

<processor type="CNAT.CoveoExtensions.CustomItemsProcessor, CNAT" />

You should now re-index all of the content in your Sitecore content tree to update the URIs.

You can confirm that your URI changes have been made by looking at the properties for content items inside the Coveo index browser.

Properties for content items inside the Coveo index browser

The final step is making sure that your search results pages display the right URIs. We like to include the server name, so we're using the following code.

<a href="{{-raw.sysclickableuri}}" class="title open-link">
      <% Response.Write(Request.Url.Host.ToLower()); %>{{-raw.sysclickableuri}}
</a>

That'll display a link that looks good to a visitor and gives them the proper clickable path.

Hopefully these instructions will help when developing a Coveo implementation. Since this seems like a piece of functionality that will always be custom and solution dependent, it's a great relief that implementing this process is a quick and easy step to include in your build out.


About the Author

Ed
Ed Kapuscinski

I am the Manager of Development Standards at TBG.

Leave A Reply

comments powered by Disqus