12

I am trying to set up ONE global navigation for all sites and site collections in my portal.example.com SharePoint site.

Whether I am in portal.example.com, portal.example.com/sites/site1, or portal.example.com/sites/site2, I want the global navigation to be identical.

Not only that, but I need all site collections to be pulling from one source.

If I make changes in one place, I want those changes to be reflected across all portal.example.com sites, site collections, pages, etc.

Here are a few solutions that I have found, but do not want:

  1. Modify the topmost link bar, instead of the global navigation bar.
  2. Make copies the term sets (one copy per site collection.)

I do NOT want to have multiple copies of a term set. I have 20-30 site collections, and I don't want to have to maintain 20-30 term sets.

This global navigation feature seems pretty basic, but I can't find a solution anywhere.

I know that navigation can be inherited from the top-level site, but for some reason, site collections can not inherit from the root site (in my case, portal.example.com).

I have created a global term set, which can be accessed by all site collections.

The issue is that only one site can use the term set at a time. Defeating the purpose of a global term set. Here is a screenshot of the warning:

Term set error

Proceeding breaks my navigation on the other site.

How can I make the whole site pull from ONE source of links?

  • 1
    If you have 20-30 site collections and people actually move between them regularly enough that this would be useful to always use up screen real estate for, you have likely set up too many site collections. – Aboba Jul 8 '14 at 20:05
  • 1
    Im an intern. Im not going to tell my boss that he should restructure his the layout of his entire sharepoint site so i can add links. Please, comment with advice for how to solve the current problem. Restructuring the layout of the SharePoint site is not an efficient solution to the navigation problem. – RyanNHG Jul 8 '14 at 20:10
  • In SharePoint, a site collection is essentially a "security bubble" and permissions can very easily be managed from the top site of the site collection. I was taught the practice of "single purpose site collections", and that breaking inheritance should be rare. If a new site is needed for a different set of users, a new site collection should be considered. Given that school of thought Aboba's statement "you have likely set up too many site collections" seems off the mark. – Keith Hudson Apr 21 '16 at 13:42
7

When you create you're the second site collection in your fresh Web Application, it typically comes with additional sites in the URL. It doesn't affect the user unless she wants to type the URL directly. The reason for this as that we use a managed path of wildcard inclusion. With wildcard inclusion, you are able to have as many site collections you want (depending on the content database setting).

With Explicit inclusion managed path, there can be only one site collection per explicit path. You can have a total of 20 managed paths in a web application, and if you need more (highly unlikely), you have to use more web applications. But if we expect to build a consistent global navigation, usually containing four to nine nodes, that shouldn't be a problem.

Our structure will look like the following:

enter image description here

We will create this structure even if we are using site collections and the structure doesn't exist. First, we create the root site collection that we usually do when we have created a new Web Application. Just make sure to use a Publishing Portal template here, and you'll get all you need out of the box. You don't need to switch on publishing features on the site collection and the site after creation, and you don't have to fiddle with the Managed Metadata Service either (Yes, you need it. If you don't have it – create one first).

Now we should deal with the paths to subsequent site collections. In Central Administration go to Manage Web Applications (in Application Management) http://CentralAdminURL:port/_admin/WebApplicationList.aspx. Highlight your Web Application and select Managed Paths in the ribbon.

In the Path text box, type the name of your node without spaces. In the type selector, be sure to select Explicit inclusion. Next click the Add Path-button. Redo these steps, until you have what you need.

enter image description here

You can chose to leave the sites Wildcard inclusion managed path where it is, or delete it. That's up to you to decide. It's now time to create the site collection from Central Administration.

Create Explicit Inclusion Site Collection

In Central Administration, follow the link Create Site Collection (in Application Management) http://CentralAdminURL:port/_admin/createsite.aspx. Make sure you're on the right Web Application, type the title and select URL. If you removed the wildcard inclusion you can only select the not already created explicit inclusion site collections. Select the publishing portal template and the primary site collection administrator and click OK.

CreateSite.PNG

Now you have a second site collection without the /sites/ in the URL.

NewSiteCollection.PNG

Create navigation terms in Term Store (Managed Metadata Service) To get the global navigation working, you need to configure the term store term set that holds the root terms. These root terms should be reused in the Site Collection term stores Site Navigation to make a consistent global navigation. There will be a lot of configuring, with the same attributes on all site collection, so it's advisable to create a file with all the attributes to copy from.

Reuse terms

Term       Order      URL (Simple link or Header)

====       =====      ===========================

Home         1        http://Portal

Products     2        http://Portal/Products

Services     3        http://Portal/Services

Customers    4        http://Portal/Customers

Suppliers    5        http://Portal/Suppliers

About Us     6        http://Portal/About-Us

This is my simple txt-file that I use. Create your own one and it will save you from a lot of typing later on.

Navigate to your Managed Metadata Service via Central Administration > Manage Service Applications (in Application Management) http://CentralAdminURL:port/_admin/ServiceApplications.aspx. Find you Managed Metadata Service and click the link.

In the Term Store Management Tool create a new Group in the Manage Metadata Service Proxy.

NewTermGroup.PNG

Name it – and create a New Term set that you name Navigation. Under the Navigation Node – create all the other nodes, (Home, Products, Services, Customers, Suppliers and About Us. When you’re done you should have the following structure (maybe in different order):

RootTermSet.PNG

The icons may look a little different than mine, but yours' will change to if you follow the guide. This is what I call the root terms. We will reuse these terms on all site collections where we want our global navigation to function cross site collections.

Reuse terms from the Site Collection navigation

In this specific case, you shouldn't access Term Store from Central Administration. If you do, you won't see the local site collection Term Group. So head over to your Site Collection (http://portal/about-us/) and go to Site Settings. In your left column, in the section Site Administration you find the link Term store management (http://portal/about-us/_layouts/15/termstoremanager.aspx).

In term store, you'll find the term group named Site Collection – portal-about-us, which contains two term sets: Site Navigation and Wiki Categories. Add terms to the site navigation following your text file, and you'll get suggestion if you typed correct.

ReuseTerms.PNG

Click the suggestion and you have reused the navigation terms you created earlier. When you're done you should see all terms in alphabetic order. We want our own sort order, so when you have selected the Site Navigation Term Set, in the right pane select the custom sort tab at the top.

CustomSortTerms.PNG

Select the radio button Use custom sort order, and reorder your navigation nodes according to your preference in the text document. Save, and select the Home term under Site Navigation. Select the Navigation tab in the right pane and select the Simple link or header. From the text document, copy the home URL and paste it in the text field. Remember you can't browse between Site Collections, so you have to type/paste the exact URL in the text field. Save and redo these operations on all terms in this site navigation.

SimpleLinkOrHeader.PNG

When you're done, click the Logo of the site and see the magic happen. In the global navigation you now have your term driven global navigation cross site collections with a friendly URL out of the box. This is the true power of SharePoint out of the box, no-code solution.

By default, you also have the same global top navigation links in your local navigation to the left. This can be changed in Site Setting > Navigation, if you want some other type of navigation locally on each site collection. As the web application grows, that is likely the case.

GlobalNavResult.PNG

Remember to redo the above steps (reuse terms) for all you site collections, and make sure to test it when you're done.


Reference (my own blog, with the same content): Out of the box Global Navigation cross Site Collections

  • 1
    But with this approach you will have to MANUALLY create each navigation item in each site collection. This is PAINFUL if you have many site collections. Also, if a new menu item has to be added or an existing menu item has to be changed, you have to touch ALL navigations in ALL site collections? There must be a better way. – teylyn Mar 21 '18 at 21:55
3

Have you tried to use managed metadata. 1. create a new Global Term Group called Global Navigation. 2. Createjavascript and placed inside Style library folder

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');
};

Finally In your masterpage, you need to add link to script.

http://www.mavention.com/blog/building-global-navigation-sharepoint-2013

1

Building global navigation in SharePoint 2013

The solution of Waldek Mastykarz published on mavention's web site as previously pointed out by Supermode can be used, but as you can see at the bottom of the article (as of 10/23/2014) there is an update that addresses two issues I recommend.

Notice this solution add links to the known "suite links" area on the top of page, no action required to resize or relocate and not overwriting the site global navigation's links.

As usual you can check the comments on the article but there's really useful comments on the original posts at author's blog:

The comments addresses some aspects regarding security trimming, code snippets used and contributed and more, all with active response from Mastykarz.

SharePoint 2013 Global Metadata Navigation

You can use the codeplex project SharePoint 2013 Global Metadata Navigation. Just be sure to follow the instructions at documentation page.

Notice this solution introduce a new control, not overwriting the site global navigation's links. Although it could be a desired feature on some scenarios. The control could be resized and positioned with CSS. The manated metadata TermSet is marked as navigation.

Both in depth

In both cases...

  • Security trimming requirements of your solutions must be addressed.
  • Special attention regarding the IDs of the Term Store and Term Set used, even when is mentioned on the sources, could be necessary on some production scenarios a parametrized solution instead the hard-coded Ids.
0

I created a custom Global navigation solution using a SharePoint list and the JSOM.

In my list, I use a list name Global Navigation Menu with 5 columns: Title, URL, DisplayOrder, IsActive, and ParentLink.

Then, in code, inject it into the Suite Links bar across the top. I edit the master page and create a div with the id "GlobalNav" to simplify targeting and styling the area where I want the navigation

Here is a code snippet:

    var collListItem;
// Misc page javascript
var hoverOnColor  = "#1ab7ea";
var hoverOffColor = "#0072c6";

function hoverOn(obj) { obj.style.backgroundColor = hoverOnColor; }
function hoverOff(obj) { obj.style.backgroundColor = hoverOffColor; }

var clientContext;
var website;
var sMenuHTML = '<div id="HomeNav">\n<ul class="parent">\n</ul>\n</div>'; sMenuHTML = '';

// Make sure the SharePoint script file 'sp.js' is loaded before your
// code runs.
SP.SOD.executeFunc('sp.js', 'SP.ClientContext', sharePointReady);

// Create an instance of the current context.
function sharePointReady() {
    clientContext = SP.ClientContext.get_current();
    website = clientContext.get_web();

    clientContext.load(website);


    clientContext.executeQueryAsync(onRequestSucceeded, onRequestFailed);
}

function onRequestSucceeded() {

    retrieveListItems();
}

function onRequestFailed(sender, args) {
    alert('Error: ' + args.get_message());
}

function retrieveListItems() {

    var siteUrl = 'https://yoursitehere/';

    var clientContext = new SP.ClientContext(siteUrl); 
    var menuList = clientContext.get_web().get_lists().getByTitle('Global Navigation Menu');

    var camlQuery = new SP.CamlQuery();
    camlQuery.set_viewXml('<View><Query><Where><Eq><FieldRef Name="IsActive"></FieldRef><Value Type="Boolean">1</Value></Eq></Where><OrderBy><FieldRef Name="DisplayOrder" Ascending="TRUE"></FieldRef></OrderBy></Query></View>');

    collListItem = menuList.getItems(camlQuery);

    clientContext.load(collListItem);

    clientContext.executeQueryAsync(Function.createDelegate(this, this.listItemsSucceeded), Function.createDelegate(this, this.listItemsFailed));        
}

function listItemsSucceeded(sender, args) {
    var listItemData            = '';
    var listItemEnumerator      = collListItem.getEnumerator();

    // Build Dynamic Homepage Menu
    while (listItemEnumerator.moveNext()) {
        var oListItem   = listItemEnumerator.get_current();  
        var pTitle      = oListItem.get_item('Title');
        var oParent     = oListItem.get_item('ParentLink');

        // Append menu string if item has no ParentLink
        if (!oParent) {
            listItemData += '\n<li class="plink ms-core-suiteLink-a"><a href="' + oListItem.get_item('URL') + '">' + pTitle + '</a>';

            // Build menu item's submenu
            var listItemEnumeratorSub = collListItem.getEnumerator();
            var sSubHTML = '';

            while (listItemEnumeratorSub.moveNext()) {
                var oListItemSub    = listItemEnumeratorSub.get_current();
                var sParent         = oListItemSub.get_item('ParentLink');

                if (sParent) { 
                    sParent = sParent.get_lookupValue().toString(); 
                    if (pTitle == sParent) {
                        sSubHTML += '\n<li class="slink"><a href="' + oListItemSub.get_item('URL') + '">' + oListItemSub.get_item('Title') + '</a></li>';
                    }
                }
            }

            if (sSubHTML != '') {listItemData += '\n<ul class="sub">' + sSubHTML + '\n</ul>\n</li>';} else {listItemData += '</li>';}
        }
    }

    sMenuHTML = '<div id="HomeNav">\n<ul class="parent">' + listItemData + '\n</ul>\n</div>';


    // Populate menu as soon as we have the data
    // This will not complete before element has rendered

    setMenuHTML();
}

function setMenuHTML() {
    var obj = document.getElementById('GlobalNav');
    if (obj) {obj.innerHTML = obj.innerHTML + sMenuHTML;} 
    document.getElementById("GlobalNav").style.visibility="visible";

}

function listItemsFailed(sender, args) {
    alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
}

Hopefully this is helpful. I'm not clear on metrics of performance so feedback is appreciated!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.