How to Implement a Splash Page in Sitecore

Splash pages are stupid. Unfortunately this doesn’t stop people from asking for them.

I would say that the idea of a splash page has been brought up for every major Sitecore site I have ever built. If possible I try to steer clients away from splash pages since it has been well documented that most users can’t stand them. Having said that I have still implemented many splash pages in Sitecore for various reason such as government regulations or additional advertising mechanisms.

Here is the pipeline I use whenever I need to implement a splash page in Sitecore in order to allow the user to select a language. It contains the following settings:

  • SetLangFromBrowserPreferences (true/false) – This setting allows you to forgo the splash page all together and attempt to set the context language based on the user’s browser language.
  • AlwaysShowForBaseUrl (true/false) – This setting will allow you to always display the splash page if the requested URL is the base domain (ex: example.com) even if the context language is already set.
  • ItemGuid – This setting should contain the GUID of the splash page item in Sitecore.

So the splash page can be displayed in different scenarios based on the settings above. In addition, if you attempt to navigate to an inner page before the context language is set (ie: a user’s first visit to the site) then the splash page will be displayed so that the user can select a language and then be redirected back to the inner page that they originally requested.

public class SplashPageResolver
{
    public bool SetLangFromBrowserPreferences { get; set; }

    public bool AlwaysShowForBaseUrl { get; set; }

    public string ItemGuid { get; set; }

    public void Process(HttpRequestArgs args)
    {
        if (Context.Site == null)
            return;

        Database db = Context.Database;
        if (db == null)
            return;

        Item itemRequested = Context.Item;
        if (itemRequested == null)
            return;

        Item startItem = Context.Database.GetItem(Context.Site.StartPath);
        if (startItem == null)
            return;

        if (String.IsNullOrWhiteSpace(ItemGuid))
            return;

        Item splashPageItem = db.GetItem(ItemGuid);
        if (splashPageItem == null)
            return;

        UrlOptions urlOptions = new UrlOptions
        {
            LanguageEmbedding = LanguageEmbedding.Never,
            AlwaysIncludeServerUrl = false
        };

        string startItemUrl = LinkManager.GetItemUrl(startItem, urlOptions).ToLower();
        string rawUrl = WebUtil.GetRawUrl().ToLower();

        if (AlwaysShowForBaseUrl && startItemUrl.Equals(rawUrl))
        {
            Context.Item = splashPageItem;
            return;
        }

        if (!itemRequested.Paths.FullPath.ToLower().StartsWith(Context.Site.StartPath.ToLower()) ||
            WebUtil.GetCookieValue(Context.Site.GetCookieKey("lang")) != String.Empty)
            return;

        if (SetLangFromBrowserPreferences && SetLanguageFromBrowserPreferences())
            return;

        Context.Item = splashPageItem;
        Context.Items.Add("requestedItem", itemRequested);
    }

    private bool SetLanguageFromBrowserPreferences()
    {
        var test = HttpContext.Current.Request.UserLanguages;
        if (test == null) return false;

        foreach (string lang in test)
        {
            if (lang.IndexOf(';') <= -1) continue;
            string langName = lang.Substring(0, lang.IndexOf(';'));
            if (SetLanguage(langName))
                return true;
        }

        return false;
    }

    private bool SetLanguage(string languageName)
    {
        if (String.IsNullOrEmpty(languageName)) return false;
        foreach (Language compare in Context.Item.Database.Languages)
        {
            if (!languageName.Equals(compare.Name, StringComparison.InvariantCultureIgnoreCase)) continue;
            if (!HasVersionInLanguage(Context.Item, compare)) continue;
            SetContextLanguage(compare);
            return true;
        }
        return false;
    }

    private static bool HasVersionInLanguage(Item item, Language language)
    {
        Item langItem = Context.Database.GetItem(item.ID, language);
        return langItem.Versions.Count > 0;
    }

    private void SetContextLanguage(Language language)
    {
        Context.SetLanguage(language, true);
        Context.Item = Context.Database.GetItem(Context.Item.ID, language);
        string cookieName = Context.Site.GetCookieKey("lang");
        WebUtil.SetCookieValue(cookieName, language.Name, DateTime.MaxValue);
    }
}

And here is the associated config file.

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <pipelines>
      <httpRequestBegin>
        <processor patch:after="*[@type='Sitecore.Pipelines.HttpRequest.ItemResolver, Sitecore.Kernel']" type="SplashPageResolver, __ASSEMBLY__">
          <SetLangFromBrowserPreferences>true</SetLangFromBrowserPreferences>
          <AlwaysShowForBaseUrl>true</AlwaysShowForBaseUrl>
          <ItemGuid>{00000000-0000-0000-0000-000000000000}</ItemGuid>
        </processor>
      </httpRequestBegin>
    </pipelines>
  </sitecore>
</configuration>

This splash page pipeline has served me well but there is one thing I would like to work on next. This example is only set up for a single splash page. If I were required to implement multiple splash pages for different sites within a Sitecore solution then I would need to make some changes to allow for this functionality.

Let me know if you have any thoughts or improvements!

Advertisements
Posted in Sitecore

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s