Adding links to the Top menu in Magento

One of the things that may sound easy to set are the top menu items, or the main menu items if you prefer. But we’re talking about Magento here and it isn’t as easy as it sounds. A specific way of creating menu items out of categories makes this fairly easy task a nightmare. Fortunately for us, Magento has a secret up its sleeve.
Magento’s logic allows only categories to appear in the top navigation. When creating a new category a simple Include in Navigation Menu setting will add the category in the navigation. Magento already explained how to add a custom link by creating a fake category and redirecting it to a specific page, but they also gave us an event to hook on to do more versatile things with the top menu.
Config
First things first. A hook has to be defined by adding the code below to the config.xml. By this we’re simply adding an event that will be fired by a dispatch event where a hook, model and method names are required.
<config>
<frontend>
<events>
<page_block_html_topmenu_gethtml_before>
<observers>
<my_module>
<class>my_module/observer</class>
<method>addToTopmenu</method>
</my_module>
</observers>
</page_block_html_topmenu_gethtml_before>
</events>
</frontend>
</config>
Observer
Now, inside the observer file defined in the config.xml a method named addToTopmenu has to be placed. The code below is just an example that adds a top menu item named “Categories” together with its children menu items, category names. That’s right, with this we’re able to create nested menu items!
public function addToTopmenu(Varien_Event_Observer $observer)
{
$menu = $observer->getMenu();
$tree = $menu->getTree();
$node = new Varien_Data_Tree_Node(array(
'name' => 'Categories',
'id' => 'categories',
'url' => Mage::getUrl(), // point somewhere
), 'id', $tree, $menu);
$menu->addChild($node);
// Children menu items
$collection = Mage::getResourceModel('catalog/category_collection')
->setStore(Mage::app()->getStore())
->addIsActiveFilter()
->addNameToResult()
->setPageSize(3);
foreach ($collection as $category) {
$tree = $node->getTree();
$data = array(
'name' => $category->getName(),
'id' => 'category-node-'.$category->getId(),
'url' => $category->getUrl(),
);
$subNode = new Varien_Data_Tree_Node($data, 'id', $tree, $node);
$node->addChild($subNode);
}
}
The result is visible in the image below:
Conclusion
This way of adding new top menu links is easy to implement into Magento and gives us a greater flexibility as opposed to other methods. No fake categories are made and no templates are edited. This method requires some code, but with this programmatic way we’re able to create more than just static menu links. We’re able to create nested menu items, use collections to generate menu items, etc.
If all of this still seems like something you would rather have a professional do, we can help you with Magento development. Feel free to drop us a line!
12 comments
Very helpful post. As a new developer it helps me a lot. I have learned a lot. I am going to follow your tips. Hope I will able to add links to the top menu in magento.
I use mega menu but some categories is not displayed why ?
make sure you set the field “Include in Navigation Menu” to “Yes” first.
how can i display Categories menu First ?
Hello Damir,
I tried your solution by adding a new module myself, but something goes wrong somewhere.
Can you give some more details regarding in which config.xml you have to change this and in which observer.php ?
Thank you !
Thank you, you saved my day !
You could say where the files should be located, filename, etc..
Hi, I’m new in magento. I have noticed that there are several config.xml files in Magento. Which one of them should I modify in order to get this work?
Thanks for your help!
@Tona, when you rebuild index, then the changes get lost…
1. create a fake category.
2. get the category id
3. search for category/id in id_path column into core_url_rewrite table on db.
4. change requested path and target path. DONE
is there any way to sort it,for example I’d like to add home link to first..