Global navigation displayed on a site in SharePoint 2013
One of the new capabilities of SharePoint 2013 is Managed Navigation which is a perfect candidate for build cross-Site Collection navigation. Unfortunately, by default, Managed Navigation is limited to one single Site Collection. Find out how to overcome this limitation and use Managed Navigation to build consistent cross-Site Collection navigations.

Bound to a boundary

Being a web platform for enterprises SharePoint is often used to host different portals. For different reasons, such as scalability or permissions, those portals are divided into separate Site Collections. In the context of the SharePoint platform Site Collections are a boundary to many things, amongst which the navigation.

Providing a consistent navigation across all the different Site Collections was a challenge since quite some time now. In the past, the only way to overcome this boundary, was to build a custom navigation provider based on some data source, such as a List, an XML file or a database. Building navigation providers however isn’t the easiest task you could imagine, and since navigation providers are requested on every page, you had to ensure that your navigation provider wouldn’t have a negative impact on the performance of the whole portal.

When SharePoint 2013 came out, for a moment it seemed like building global navigations would never be a problem again. One of the new capabilities of SharePoint 2013 is Managed Navigation that allows us to build navigation using Managed Metadata. With this we can decouple the physical structure of the Site Collection from its navigation. Unfortunately, the reality is less promising. Although SharePoint 2013 allows us to define navigation using Managed Metadata, that navigation is bound to a specific Site Collection and cannot be reused across Site Collections.

Luckily, by leveraging the customization capabilities of SharePoint 2013, there is a way to use Managed Metadata to build a consistent cross-Site Collection navigation.

Building global navigation in SharePoint 2013

To build global navigation in SharePoint 2013 using Managed Metadata let’s start from creating a new Global Term Group called Global Navigation.

The ‘Global Navigation’ Global Term Group highlighted in the Term store management tool in SharePoint 2013

Next, in the Global Navigation Group, let’s create a new Term Set called Global Navigation.

The ‘Global Navigation’ Term Set highlighted in the Term store management tool in SharePoint 2013

Save the ID of the newly created Global Navigation Term Set as we will need it later on.

The ID of the ‘Global Navigation’ Term Set highlighted in the Term store management tool in SharePoint 2013

Next, let’s create a few Terms. For every Term, on the Navigation tab, select the Simple Link or Header option and provide the URL to the corresponding Site Collection.

URL configuration of one of the navigation terms in the Term store management tool in SharePoint 2013

Next, copy the following code snippet and upload it to the Style Library:

Function.registerNamespace('Mavention.GlobalNavigation');

Mavention.GlobalNavigation.MenuItem = function(title, url) {
    this.title = title;
    this.url = url;
};

Mavention.GlobalNavigation.viewModel = {
    globalMenuItems: new Array()
};

Mavention.GlobalNavigation.init = function(termStoreName, termSetId) {
    SP.SOD.executeOrDelayUntilScriptLoaded(function() {
        'use strict';
        var nid = SP.UI.Notify.addNotification("<img src='/_layouts/15/images/loadingcirclests16.gif?rev=23' style='vertical-align:bottom; display:inline-block; margin-" + (document.documentElement.dir == "rtl" ? "left" : "right") + ":2px;' />&nbsp;<span style='vertical-align:top;'>Loading navigation...</span>", false);

        SP.SOD.registerSod('sp.taxonomy.js', SP.Utilities.Utility.getLayoutsPageUrl('sp.taxonomy.js'));
        SP.SOD.executeFunc('sp.taxonomy.js', false, Function.createDelegate(this, function () {
            var context = SP.ClientContext.get_current();
            var taxonomySession = SP.Taxonomy.TaxonomySession.getTaxonomySession(context);
            var termStore = taxonomySession.get_termStores().getByName(termStoreName);
            var termSet = termStore.getTermSet(termSetId);
            var terms = termSet.getAllTerms();
            context.load(terms);
            context.executeQueryAsync(Function.createDelegate(this, function(sender, args) {
                var termsEnumerator = terms.getEnumerator();
                var menuItems = new Array();
                
                while (termsEnumerator.moveNext()) {
                    var currentTerm = termsEnumerator.get_current();
                    Mavention.GlobalNavigation.viewModel.globalMenuItems.push(new Mavention.GlobalNavigation.MenuItem(currentTerm.get_name(), currentTerm.get_localCustomProperties()['_Sys_Nav_SimpleLinkUrl']));
                }
                
                ko.applyBindings(Mavention.GlobalNavigation.viewModel);
                SP.UI.Notify.removeNotification(nid);
            }), Function.createDelegate(this, function(sender, args) {
                alert('The following error has occured while loading global navigation: ' + args.get_message());
            }));
        }));
    }, 'core.js');
};

Save the file as Mavention.GlobalNavigation.js and upload it to the Mavention folder in Style Library.

Next, choose where on your Master Page you want to display the global navigation. For this example I chose to have it displayed in the Suite Links area.

The ‘Suite Links’ area highlighted on the standard SharePoint 2013 Master Page

To have the global navigation displayed in the Suite Links area, copy the standard seattle.master Master Page, and paste the following code snippet on line 81 right after div with id suiteLinksBox:

<script src="http://ajax.aspnetcdn.com/ajax/knockout/knockout-2.2.1.js"></script>
<script src="/Style Library/Mavention/Mavention.GlobalNavigation.js"></script>
<div>
    <ul class="ms-core-suiteLinkList" data-bind="foreach: globalMenuItems">
        <li class="ms-core-suiteLink"><a class="ms-core-suiteLink-a" data-bind="attr: { href: url }"><span data-bind="text: title"></span></a></li>
    </ul>
</div>
<script>
Mavention.GlobalNavigation.init('Managed Metadata Service', '779a5609-7190-4b43-9071-6979841a8d71');
</script>

Before you save the Master Page, ensure that in line 9 the script refers to the right Term Store (Managed Metadata Service in the example above) and the Term Set ID where Global Navigation is defined (779a5609-7190-4b43-9071-6979841a8d71 in the example above).

Save the Master Page, set it as the default Master Page for your site, and when you refresh the page in the browser, you should see the global navigation displayed.

Global Navigation displayed on the page

To implement the global navigation across multiple Site Collection you would only need to do the last part where you upload the Mavention.GlobalNavigation.js file to the Style Library and modify the Master Page to include the HTML snippet. You could simplify this process even further by uploading the Mavention.GlobalNavigation.js file to a central location in your farm accessible by all sites and have the HTML snippet point to that location.

Summary

One of the new capabilities of SharePoint 2013 is Managed Navigation that allows you to define site’s navigation using Managed Metadata. Unfortunately Managed Navigation is bound to a specific Site Collection and cannot be reused across different Site Collections. Using the standard capabilities of SharePoint 2013 you can leverage Managed Metadata and build global navigation within your organization.