Hope you are all aware of the limitations of Managed Navigation in SharePoint. If not go through this article

As explained in the above article, each term set can be associated with only one site collection at given time. If you have 5 site collections, you must have 5 copies of same term set to use for 5 site collections navigation data.

To overcome this issue I have created a SharePoint Hosted app which can read the term store and dynamically build the navigation. This app can be embedded in to webpart zone or master page based on your requirement.

O365 Patterns and Practice code helped me a lot to build this app

Step 1 – Create Term Set with your desired menu items and a custom property to configure the redirect url as shown below :

termstore

Step 2 – Create a SharePoint Hosted App using Napa / Visual Studio

Step 3 – Configure Permission as per your requirement

permission

Step 4 – Add the necessary script files and a DIV tag to load the dynamic html from App.js file as shown below

default-aspx

Step 5 – Build the dynamic menu list and push the html inside the DIV from App.js as shown below:

Note: Replace the term store and termset Guid with your environment values.

"use strict";

var terms;
var sb = "";

var tree = {
term: terms,
children: []
};

\$(document).ready(function() {
fn_Build_Navigation();
});

function fn_Build_Navigation() {
var context = SP.ClientContext.get_current();
var taxSession = SP.Taxonomy.TaxonomySession.getTaxonomySession(context);
var termStores = taxSession.get_termStores();
//Name of the Term Store from which to get the Terms.
var termStore = termStores.getByName("Taxonomy_kFyvauM0tqfeNGG7M0bRmw ==");
//GUID of Term Set from which to get the Terms.
var termSet = termStore.getTermSet("fa6a6655-4db6-4568-aa41-588b9420aec9");
terms = termSet.getAllTerms();
context.load(terms);

context.executeQueryAsync(
function() {
var termEnumerator = terms.getEnumerator();

      while (termEnumerator.moveNext()) {
        var currentTerm = termEnumerator.get_current();

        var currentTermPath = currentTerm.get_pathOfTerm().split(";");
        var children = tree.children;

        // Loop through each part of the path
        for (var i = 0; i < currentTermPath.length; i++) {
          var foundNode = false;
          for (var j = 0; j < children.length; j++) {
            if (children[j].name === currentTermPath[i]) {
              foundNode = true;
              break;
            }
          }

          // Select the node, otherwise create a new one
          var term = foundNode
            ? children[j]
            : {
                name: currentTermPath[i],
                children: []
              };

          // If we're a child element, add the term properties
          if (i === currentTermPath.length - 1) {
            var navurl = currentTerm.get_customProperties().redirectTo;
            if (!navurl) {
              navurl = "#";
            }

            term.term = currentTerm;
            term.title = currentTerm.get_name();
            term.guid = currentTerm.get_id().toString();
            term.url = navurl;
          }

          // If the node did exist, let's look there next iteration
          if (foundNode) {
            children = term.children;
          }
          // If the segment of path does not exist, create it
          else {
            children.push(term);

            // Reset the children pointer to add there next iteration
            if (i !== currentTermPath.length - 1) {
              children = term.children;
            }
          }
        }
      }

      if (tree.children.length > 0) {
        sb = " < ul id = 'globalMenu' class = 'menu' > ";

        for (
          var prarentindex = 0;
          prarentindex < tree.children.length;
          prarentindex++
        ) {
          if (tree.children[prarentindex].children.length > 0) {
            buildTermSetTreeLevel(
              tree.children[prarentindex].children,
              tree.children[prarentindex].name,
              tree.children[prarentindex].url
            );
          } else {
            sb +=
              " < li > < a href = '" +
              tree.children[prarentindex].url +
              "'>" +
              tree.children[prarentindex].name +
              "</a></li>";
          }
        }

        sb += " < /ul>";

        $("#message").html(sb);
      }
    },
    function(sender, args) {
      console.log(args.get_message());
    }

);
}

function buildTermSetTreeLevel(termList, name, url) {
sb += " < li > ";
sb += " < a href = '" + url + "'>" + name + "</a>";
sb += " < ul > ";

for (var i = 0; i < termList.length; i++) {
var term = termList[i];

    if (term.children.length > 0) {
      buildTermSetTreeLevel(term.children, term.name, term.url);
    } else {
      sb += " < li > < a href = '" + term.url + "'>" + term.name + "</a></li>";
    }

}

sb += " < /ul>";
sb += " < /li>";
}

Hope you liked this post. If you have any questions on this topic, let me know…