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