How the site for the clickable URI is resolved

Each Coveo for Sitecore search result typically contains a link to open the item in your browser. This link is called the clickable URI.

When you’re using the Coveo for Sitecore package in a multi-site or scaled Sitecore setup, it can be difficult to understand how the site portion of an item’s clickable URI is determined. Coveo for Sitecore determines the clickable URI of a Sitecore item at indexing time. Then, when a user runs a search query in a Coveo Hive search interface, the reverse proxy intercepts the search results and recomputes the site portion of the clickable URI on the fly before returning the results to the user.

Note

Site recomputation at query time doesn’t apply when you use the Coveo Hosted Search Page rendering or when the reverse proxy is disabled.

This article explains how the site portion of a clickable URI is resolved at indexing and query time. It also provides troubleshooting guidelines for unexpected clickable URIs.

How the site is resolved at indexing time

Coveo for Sitecore generates clickable URIs for items at indexing time without an HTTP request context. Therefore, the content tree structure and the <site> element definitions in the Sitecore configuration determine the appropriate site for each indexed item. After the site is determined, Coveo for Sitecore uses the site’s targetHostName attribute value if specified, otherwise it uses the hostName attribute value to build the clickable URI.

Important

If a site definition includes many hostName attribute values for a site, using pipes or wildcards, you must provide a value for the targetHostName attribute as well. Coveo for Sitecore needs this to be able to determine a specific host name for the clickable URI of the site items.

The order of site definitions in the Sitecore configuration affects the site selection process. The following <site> element attributes are also considered:

  • rootPath

  • startItem

  • language

For a given item, the site selection algorithm is as follows:

  1. Find all candidate sites. A candidate site is one where the item is under the site’s home path (rootPath+startItem), excluding system sites (for example, the shell, login, admin, service sites).

  2. If candidate sites exist:

    1. Select the first candidate site whose language matches the item language or that doesn’t define a language attribute.

    2. If no site was selected in the previous step, select the first candidate site based on the order of site definitions.

  3. If no candidate sites exist, use a fallback site.

Tip

Set the Coveo log level to DEBUG to see which <site> an item matches at indexing time.

Image of custom Coveo rebuild logs on the Diagnostic Page log viewer
Note

The Coveo for Sitecore ResolveItemSiteProcessor processor used to give precedence to the site definition ContentStartItem attribute over the StartItem attribute when resolving clickable URIs at indexing time. Coveo for Sitecore now disregards the ContentStartItem. If you have ContentStartItem attribute values in your site definitions, the changes in this release might affect the clickable URIs of your items in the index.

Site resolution example

You have the following structure in the Sitecore content tree and the page1, page2, and page3 items each include versions in English and French (Canada).

Screenshot of the Sitecore content tree with Site 1 Site 2 and Site 3 items with page 1 page 2 and page 3 items respectively under each | Coveo

Your compiled configuration is the following:

<sites>
  <site name="coveo_website" virtualFolder="/sitecore modules/Web/Coveo" physicalFolder="/sitecore modules/Web/Coveo" rootPath="/sitecore/content" startItem="/home" language="en" database="web" domain="extranet" allowDebug="true" cacheHtml="true" loginPage="/sitecore/login" patch:source="Coveo.SearchProvider.config"/>
  <site name="coveoanalytics" virtualFolder="/coveo/rest/v6/analytics" enableTracking="true" database="web" domain="extranet" patch:source="Coveo.SearchProvider.config"/>
  <site name="coveorest" virtualFolder="/coveo/rest" physicalFolder="/coveo/rest" enableTracking="false" database="web" domain="extranet" patch:source="Coveo.SearchProvider.config"/>
  <site name="shell" virtualFolder="/sitecore/shell" physicalFolder="/sitecore/shell" rootPath="/sitecore/content" startItem="/home" language="en" database="core" domain="sitecore" loginPage="/sitecore/login" content="master" contentStartItem="/Home" enableWorkflow="true" enableTracking="false" analyticsDefinitions="content" xmlControlPage="/sitecore/shell/default.aspx" browserTitle="Sitecore" htmlCacheSize="10MB" registryCacheSize="15MB" viewStateCacheSize="1MB" xslCacheSize="25MB" disableBrowserCaching="true" contentLanguage="en" patch:source="Sitecore.Speak.ItemWebApi.config" enableItemLanguageFallback="false" enableFieldLanguageFallback="false" itemwebapi.mode="StandardSecurity" itemwebapi.access="ReadWrite" itemwebapi.allowanonymousaccess="false"/>
  ...
  ...
  <site name="modules_website" virtualFolder="/sitecore modules/web" physicalFolder="/sitecore modules/web" rootPath="/sitecore/content" startItem="/home" language="en" database="web" domain="extranet" allowDebug="true" cacheHtml="true"/>
  <site name="site1" hostName="www.mysite1.ca" virtualFolder="/" physicalFolder="/" rootPath="/sitecore/content" startItem="/site1" language="en" database="web" domain="extranet" enableWebEdit="true" patch:source="SiteDefinition.config"/>
  <site name="site2" hostName="www.mysite2.ca" virtualFolder="/" physicalFolder="/" rootPath="/sitecore/content" startItem="/site2" language="en" database="web" domain="extranet" enableWebEdit="true" patch:source="SiteDefinition.config"/>
  <site name="site3" hostName="www.mysite3.ca" virtualFolder="/" physicalFolder="/" rootPath="/sitecore/content" startItem="/site3" language="en" database="web" domain="extranet" enableWebEdit="true" patch:source="SiteDefinition.config"/>
  <site name="site4" hostName="www.mysite4.ca" virtualFolder="/" physicalFolder="/" rootPath="/sitecore/content" startItem="/site1" language="fr-CA" database="web" domain="extranet" enableWebEdit="true" patch:source="SiteDefinition.config"/>
  <site name="site5" hostName="www.mysite5.ca" virtualFolder="/" physicalFolder="/" rootPath="/sitecore/content" startItem="/site2" language="fr-CA" database="web" domain="extranet" enableWebEdit="true" patch:source="SiteDefinition.config"/>
  <site name="site6" hostName="www.mysite6.ca" virtualFolder="/" physicalFolder="/" rootPath="/sitecore/content" startItem="/" language="en" database="web" domain="extranet" enableWebEdit="true" patch:source="SiteDefinition.config"/>
  <site name="website" enableTracking="true" virtualFolder="/" physicalFolder="/" rootPath="/sitecore/content" startItem="/home" database="web" domain="extranet" allowDebug="true" ... />
  <site name="scheduler" enableTracking="false" domain="sitecore"/>
  ...
  ...
</sites>

Given this information, the item versions would be resolved to a hostName as follows.

Item name Item version hostName

page1

English

www.mysite1.ca

page1

French (Canada)

www.mysite4.ca

page2

English

www.mysite2.ca

page2

French (Canada)

www.mysite5.ca

page3

English

www.mysite3.ca

page3

French (Canada)

www.mysite3.ca 1

1 The <site3> site is selected over <site6> because it’s declared before <site6> in the configuration.

Automatic recomputation of the clickable URI at query time

When you use Coveo Hive search interfaces (excluding the Coveo Hosted Search Page) with the reverse proxy enabled, the site portion of clickable URIs can be recomputed at query time. The ResolveResultClickableUriProcessor processor in the coveoProcessParsedRestResponse pipeline performs this recomputation. It ensures that each clickable URI points to the appropriate content delivery (CD) site based on the current site context. The processor uses the current site context provided to the pipeline (typically Sitecore’s context site for the HTTP request that served the search page).

For regular items, the ResolveResultClickableUriProcessor processor calls Sitecore LinkManager GetItemUrl method to recompute the clickable URIs. The processor provides the selected Sitecore site context to LinkManager (by default the current site context unless the coveoResolveItemSite pipeline resolves a different site). LinkManager then generates the final URL according to Sitecore link generation rules. For example, when generating cross-site links, Sitecore typically uses the site’s targetHostName value and falls back to hostName if targetHostName is not set.

Note

Sitecore uses the site’s targetHostName value when generating URLs to items in this site from the context of another site. If the targetHostName attribute is not available, Sitecore uses the value of the hostName attribute instead.

For media items, the ResolveResultClickableUriProcessor processor calls the Sitecore MediaManager.GetMediaUrl method.

Troubleshooting

Based on common support cases, this section describes frequent causes of malformed or unexpected clickable URIs. This information applies to Coveo Hive search interfaces other than the Coveo Hosted Search Page when the reverse proxy is enabled.

Tip

For complex host name resolution issues, use an indexing pipeline extension (IPE) instead of a custom link provider or custom Sitecore processor. See Example: Replacing the hostname in the clickable URI for instructions and a code sample.

Custom link providers are the most common cause of clickable URI issues reported to Coveo Support.

They often conflict with the built-in logic that Coveo for Sitecore uses to resolve clickable URIs at indexing and query time. The default Coveo for Sitecore behavior successfully handles most Sitecore environments without the need for custom link providers.

Before troubleshooting further, isolate the impact of any custom link provider logic and related configuration to determine whether it causes the issue.

Incorrect or incomplete site definitions

At query time, Coveo for Sitecore uses Sitecore LinkManager and the configured site definitions to recompute clickable URIs. Therefore, ensure that all CD servers have accurate and consistent site definitions.

Tip

Set the Coveo log level to DEBUG to review the site resolution process for a specific item using its Sitecore Item ID.

Site resolution process logs | Coveo for Sitecore

The following sections present some common site definition issues that can lead to unexpected clickable URI host names at query time.

Database/index targeting issues

If clickable URIs generated at query time target the wrong database, verify that the corresponding site definition specifies the correct database attribute value. The Coveo Search Resources rendering injects a <div class="CoveoForSitecoreContext"> element into the HTML of the search page. This element includes a data-sc-item-uri attribute that indicates the database serving the content.

Example:

... data-sc-item-uri="sitecore://web/{444B1C8C-0348-4440-8089-AD7C1C902D4F}?lang=en&amp;ver=2" ...

If this value is incorrect, verify that:

Tip

Use separate indexes and site definitions for each deployment environment (for example, development, staging, and production) to avoid issues and confusion.

Multiple hostName values without a single targetHostName

If a <site> element defines multiple hostName values (using wildcards (*) or pipes (|)):

  • The <site> element must define a single targetHostName value.

  • The targetHostName value must not contain wildcards or pipes.

Otherwise, Sitecore cannot determine which host name to apply to generated item URLs.

Note

Coveo for Sitecore logs a warning when a site definition contains multiple targetHostName values.

Warning shown by Coveo for Sitecore for multi TargetHostName sites | Coveo for Sitecore 5

Also ensure that the Rendering.SiteResolving setting is set to true.

Single-level inheritance in site definitions

Sitecore supports site definition inheritance through the inherits attribute. However, inheritance applies only one level deep.

For example, consider the following site definitions.

<site name ="site2" inherits="site1" hostName ="test.com" targetHostName="test.com" ... />
<site name ="site1" inherits="website" rootPath="/sitecore/content" ... />
<site name ="website" hostName="example.com" targetHostName="example.com" rootPath="/sitecore/content" startItem="/home" ... />

In this configuration:

  • site2 inherits rootPath from site1.

  • site2 does not inherit startItem from website.

As a result, an item under /sitecore/content/home resolves to <site1>, not <site2>, and its clickable URI uses example.com.

Other site definition issues

Other site definition problems can cause unexpected clickable URIs, both in Coveo search results and in Sitecore generally. For more information, see the Sitecore documentation on multi-site management.

Recomputation of media item clickable URIs at query time

Sometimes (for example, when the Sitecore instance is hosted in Azure), the MediaManager.GetMediaUrl method may not return the correct host name.

To address this:

  1. Add a <serverUrl> element under <defaultIndexConfiguration> in the Coveo.SearchProvider.Custom.config file to specify the host name to be used in your clickable URIs:

    <defaultIndexConfiguration>
      <serverUrl>https://oursite.com</serverUrl>
  2. Add the following <setting> element under <settings> in the same file:

    <settings>
      <setting name="Coveo.Url.UseServerUrlFromConfiguration" value="true" />
    </settings>

SXA site item clickable URIs

In SXA, site definitions are configured under <SXA_SITE_NAME>/Settings/Site Grouping rather than in configuration files. However, Coveo for Sitecore resolves SXA site item clickable URIs at indexing and query time the same way it resolves non-SXA sites. Therefore, the previously described pitfalls also apply to SXA sites.

You can use the switchableLinkProvider default link provider or set the Link Provider name site definition field to the sitecore provider. The computed clickable URIs at indexing and at query time will be the same using both providers.

Ensure that you select a Start Item in the SXA site definition (similar to specifying rootPath and startItem in non-SXA site definitions). Also review the Manage multiple sites with the SXA Site Manager article to avoid site conflicts.