3

Is there a way to create a custom menu item in the magento 2 Top menu which links to an external URL.

Static page only category doesnt suit my need because I just want to redirect the user to a different website.

Update: I tried with the plugin as suggested and it doesn't come. I cleared the cache too.

enter image description here

1

1 Answer 1

10

You can do it with a Plugin. In a custom module:

add magento\app\code\Custom\Module\etc\frontend\di.xml

<?xml version="1.0"?>

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Theme\Block\Html\Topmenu">
    <plugin name="add_menu_item_plugin" type="Custom\Module\Plugin\TopmenuPlugin" sortOrder="10" disabled="false"/>
</type>
</config>

It says it will use the plugin you defined in Custom\Module\Plugin\Topmenuplugin.php when the block Magento\Theme\Block\Html\Topmenu is used

Now add the plugin under magento\app\code\Custom\Module\Plugin\TopmenuPlugin.php

<?php

namespace Custom\Module\Plugin;

class TopmenuPlugin
{

    public function afterGetHtml(\Magento\Theme\Block\Html\Topmenu $topmenu, $html)
    {


        $html .= "<li class=\"level0 nav-4 level-top parent ui-menu-item\">";
        $html .= "<a href=\"" . "REPLACE_BY_YOUR_EXTERNAL_URL" . "\" class=\"level-top ui-corner-all\" aria-haspopup=\"true\" tabindex=\"-1\" role=\"menuitem\"><span class=\"ui-menu-icon ui-icon ui-icon-carat-1-e\"></span><span>" . __("REPLACE_BY_THE_TITLE_OF_THE_LINK") . "</span></a>";
        $html .= "<ul class=\"level0 submenu ui-menu ui-widget ui-widget-content ui-corner-all\" role=\"menu\" aria-expanded=\"false\" style=\"display: none; top: 47px; left: -0.4375px;\" aria-hidden=\"true\">";

        $html .= "<li class=\"level1 nav-5-1 first ui-menu-item\" role=\"presentation\">";
        $html .= "<a href=\"" . "REPLACE_BY_YOUR_EXTERNAL_URL" . "\" class=\"ui-corner-all\" tabindex=\"-1\" role=\"menuitem\"><span>" . __("REPLACE_BY_THE_TITLE_OF_THE_LINK") . "</span></a>";
        $html .= "</li>";

        $html .= "<li class=\"level1 nav-5-1 first ui-menu-item\" role=\"presentation\">";
        $html .= "<a href=\"" . "REPLACE_BY_YOUR_EXTERNAL_URL" . "\" class=\"ui-corner-all\" tabindex=\"-1\" role=\"menuitem\"><span>" . __("REPLACE_BY_THE_TITLE_OF_THE_LINK") . "</span></a>";
        $html .= "</li>";

        $html .= "<li class=\"level1 nav-5-1 first ui-menu-item\" role=\"presentation\">";
        $html .= "<a href=\"" . "REPLACE_BY_YOUR_EXTERNAL_URL" . "\" class=\"ui-corner-all\" tabindex=\"-1\" role=\"menuitem\"><span>" . __("REPLACE_BY_THE_TITLE_OF_THE_LINK") . "</span></a>";
        $html .= "</li>";

        $html .= "</ul>";
        $html .= "</li>";

        return $html;
    }


}

So, after the Topmenu Block generates its html, we intercept it and add our new menu items. Here you have one top menu item with 3 sub-items. Simply replace the "REPLACE_BY_YOUR_EXTERNAL_URL" by your urls and the "REPLACE_BY_THE_TITLE_OF_THE_LINK" by the title of your links.

EDIT: To make it a complete workable module, you'll need 3 more files:

  • Custom/Module/etc/module.xml
  • Custom/Module/composer.json
  • Custom/Module/registration.php

module.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Custom_Module"  setup_version="0.0.1">
        <sequence>
            <module name="Magento_Theme"/>
        </sequence>
    </module>
</config>

Composer.json

{
  "name": "custom/module",
  "description": "N/A",
  "require": {
    "magento/framework": "*"
  },
  "suggest": {
  },
  "type": "magento2-module",
  "version": "100.0.1",
  "license": [
    "OSL-3.0",
    "AFL-3.0"
  ],
  "autoload": {
    "files": [
      "registration.php"
    ],
    "psr-4": {
      "Custom\\Module\\": ""
    }
  }
}

registration.php

 <?php \Magento\Framework\Component\ComponentRegistrar::register(\Magento\Framework\Component\ComponentRegistrar::MODULE,'Custom_Module',__DIR__);

After these changes, do in a terminal (and from your magento install dir)

php bin/magento setup:upgrade
6
  • Thanks. I tried your code but it seems not working. I updated the question with the screenshot showing where I placed the suggested code. Jan 14, 2016 at 22:51
  • I edited my answer so you can build a full working module :)
    – csmarvz
    Jan 15, 2016 at 8:28
  • Thanks. It works. Edit the post and show the composer.json in code block... Had tough time to identify double slashed in this line "Custom\\Module\\": "" Jan 15, 2016 at 20:05
  • Sorry, it's corrected. Glad it worked
    – csmarvz
    Jan 18, 2016 at 11:11
  • Very awkward for only adding menu items to the top menu, but I also didn't find any other way. The last class in the resulting html is wrong, and nav-4 wouldn't be correct anymore if you add new categories. Is there still no better way for handling this?
    – bpoiss
    May 13, 2016 at 6:55

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