Sunday, April 28, 2013

Custom Link Provider for Items outside startItem in Sitecore

In a recent website development using Sitecore, we had to keep pages outside startItem to implement the required the information architecture of the site. Below is an image depicting the page hierarchy.


Sitecore page item outside contentStartItem

The user friendly URL generated for page "Our-Range" was /sitecore/Content/site_name/Website/our-range instead of /our-range.

On troubleshooting it was found that as "Our-Range" item is out side contentStartItem (in this case, "home" item), Sitecore's default linkProvider returned full path for the item. Displaying full item path as URL is not a good practice from SEO and security point of views.

To fix this, Sitecore's out of box LinkProvider (Sitecore.Links.LinkProvider) was extended and the GetItemUrl method was overridden.


namespace Sitecore.Custom.Providers
{
/// <summary>
/// Class to generate URL for Sitecore items.
/// </summary>
public class LinkProvider : Sitecore.Links.LinkProvider
{
/// <summary>
/// Returns user friendly URL for given Sitecore item.
/// </summary>
/// <param name="item">The Sitecore item for which URL is needed.</param>
/// <param name="options">The options to be considered when generating URL</param>
/// <returns>User friendly URL for Sitecore item.</returns>
public override string GetItemUrl(Sitecore.Data.Items.Item item, Sitecore.Links.UrlOptions options)
{
// Get URL from Sitecore out of box link provider.
string originalURL = base.GetItemUrl(item, options);


// Get contentStartItem path for context site.
string contentStartItem = Sitecore.Context.Site.RootPath.ToLower();

// Replace contentStartItem path in originalURL with empty string and return the resultant string.
return originalURL.ToLower().Replace(contentStartItem, String.Empty);
}
}
}

In above code, GetItemUrl method is overridden to adjust the friendly URL for Sitecore items. First, friendly URL for required item is retrieved using default link provider. Then the contentStartItem path is replaced with empty string. Finally the resultant URL is returned.

After the code is build and deployed, below configuration changes have to be make in web.config file of Sitecore instance:

<add patch:instead="*[@name='sitecore' and @type='Sitecore.Links.LinkProvider, Sitecore.Kernel']" name="sitecore" type="Sitecore.Custom.Providers.LinkProvider, Sitecore.Custom" addAspxExtension="false" alwaysIncludeServerUrl="false" encodeNames="true" languageEmbedding="asNeeded" languageLocation="filePath" shortenUrls="true" useDisplayName="true"></add>

After deploying these changes, URLs for items outside startItem did not have full item path.

Full source code for above custom link provider can be found at GitHub.

Friday, April 5, 2013

Improve Sitecore Media Library Performance with IIS ARR

Recently one of our Sitecore production environment was having performance issues. On troubleshooting we found that one of the causes was media library. It was performing poorly when there was heavy load on the server. Even after configuring various media library related settings in web.config, performance was not getting improved. We were still observing CPU spikes in production environment.

Due to budget constraints, CDN option was ruled out for media library. Then we came up with a solution to have a proxy before the CD server. We found that reverse proxy can be setup with help of IIS Application Request Routing and URL Rewrite.

After setting up reverse proxy, all media library requests were forwarded to CD server for the first time and its response was cached on disk. After creation of cache, media library request were not forwarded to CD server and instead were being served from cache.

When we performed load testing on our Staging environment, there was vast improvement in performance with ARR cache. CPU Utilization reduced by almost 10x times, Requests/Sec increased by 1.5x times and Response Time reduced to half.

Till now we haven't seen any functionality issues in Sitecore websites with ARR caches. All sites were working fine as expected.

One important setting to be configured in web.config file is to set HTTP Cache-Control Header to Public for media library files. This will enable media library items to get cached at proxy sites.
<setting name="MediaResponse.Cacheability" value="public" />

There are other ways as well to improve media library performance but more on that in later posts.

Wednesday, April 3, 2013

Basic Form Abandonment in SiteCatalyst

In my recent web project which involved creating a Contact Us form, Captcha was added to avoid spam. But client was skeptical about user abandoning the form because of Captcha. So client came up with a requirement of tracking the field on which user was dropping of from the page. SiteCatalyst 15 was used for web analytics and it required custom JavaScript code for achieving the goal. By implementing custom link tracking user actions were being captured.

Solution

In SiteCatalyst admin, a custom event called Dropped Off was configured. Also a custom variable (eVars) was configured in which the name of last accessed field by user before she dropped off, was set.

In Javascript, a variable was used to store the name of last access field. Its value is set whenever a user clicks or sets focus on a form field. An event listener was attached to beforeunload event of the document. In this event handler last access field name was set in SiteCatalyst custom variable (eVar) and event was set to event corresponding Dropped Off event. Finally track link method (s.tl()) was invoked to send the tracking data to SiteCatalyst.

As beforeunload event is triggered even when form is submitted, ensure that custom link tracking code is not executed. This can be achieved by making use of boolean flag which will be used to check form is submitted or not before sending data to SiteCatalyst.

You can find sample JS code at github.

In SiteCatalyst, report can be seen under Custom Conversion > Custom Conversion 1-10 > eVar Name


Sample report in Site Catalyst
Sample report in Site Catalyst


Above implementation can be further extended to include form validation errors so as to track for which validation error user is abandoning the page.

Monday, April 1, 2013

April Fool !!!

Hmm... so I fooled myself to start a blog. Hope to remain foolish till eternity.