How to add a new item to the navigation menu in Magento

Adding a new item to the navigation menu is fairly simple.

We will add this ability to a custom module. There is no need to modify core Magento files or templates and layouts.

First, we need to rewrite the block that is responsible for menu drawing; however, we will not be using a <rewrite> tag. The reason for this is, if the module is disabled, Magento will break. Instead, will will use an observer for it.

At global scope, in your config.xml file, add the following code:

<events>
  <controller_action_layout_generate_blocks_after>
    <observers>
      <allproducts>
        <type>singleton</type>
        <class>Company_ModuleName_Model_Observer</class>
        <method>regeneratemenu</method>
      </allproducts>
    </observers>
  </controller_action_layout_generate_blocks_after>     
</events>

You can also use other events instead of controller_action_layout_generate_blocks_after. Next, you must create Observer.php in the Model folder using method regenerateMenu

class Company_ModuleName_Model_Observer
{

public function regenerateMenu($observer)
{
  // if module is active
  if (!Mage::getStoreConfig('advanced/modules_disable_output/Company_ModuleName'))
  {
    $layout = Mage::getSingleton('core/layout');

    // remove all the blocks you don't want
    $layout->getUpdate()->addUpdate('<remove name="catalog.topnav"/>');

    // load layout updates by specified handles
    $layout->getUpdate()->load();

    // generate xml from collected text updates
    $layout->generateXml();

    // generate blocks from xml layout
    $layout->generateBlocks();

  }
}
}

Next step: you should create the block file Navigation.php with the following code:

class Company_ModuleName_Block_Navigation extends Mage_Catalog_Block_Navigation
{

public function renderCategoriesMenuHtml($level = 0, $outermostItemClass = '', $childrenWrapClass = '') 
{

  // if route is active
  $active = ($this->getRequest()->getRouteName()=='yourroute' ? 'active' : '');

  // Get navigation menu html
  $html = parent::renderCategoriesMenuHtml($level, $outermostItemClass, $childrenWrapClass);

  // if module is active
  if (Mage::helper('core/data')->isModuleEnabled('Company_ModuleName')) {
    // Adding new menu item. You can also add few items or child elements there
    $html .=  "<li class='$outermostItemClass $active'><a class='$outermostItemClass' href='" . Mage::getUrl('yourroute') . "'><span>" . Mage::helper('yourroute')->__('New Menu Item') . "</span></a></li>";
  }
  return $html;
}
}

Note: Don’t forget to declare the block in your config.xml file.
After, you need to declare the path for your layout XML in config:

<layout>
  <updates>
    <yourroute>
      <file>newmenuitem.xml</file>
    </yourroute>
  </updates>
</layout>

Lastly, here is content for newmenuitem.xml

<?xml version="1.0"?>
<layout version="0.1.0">
  <default>
    <reference name="top.menu">
     <!--Note: use custom block file for menu drawing and default template file-->
      <block type="yourroute/navigation" name="newmenu.topnav" template="catalog/navigation/top.phtml">
      </block>
    </reference>
  </default>
</layout>

Now you will have successfully added a menu item without modifying core files.
Happy coding!

Read more: