Skip to content

Mukesh Chapagain Blog

  • PHP
    • PHP
    • Laravel
    • WordPress
    • Joomla
  • Magento
    • Magento 2
    • Magento Extension
  • Node.js
    • Node.js
    • Javascript
    • jQuery
  • Database
    • MySQL
    • MongoDB
  • Data Science
    • Machine Learning
    • Recommender System
    • Natural Language Processing (NLP)
    • Sentiment Analysis
    • Python
    • R
  • Categories
    • Blockchain
      • Hyperledger Composer
      • Hyperledger-Fabric
    • Other
      • Cryptography
      • Data Structures & Algorithms
      • Git
      • LaTeX
      • Linux
      • Ubuntu
      • Xubuntu
      • Google
      • Google AppScript
  • About
    • About
    • Contact
    • Privacy Policy

Home » Magento » Magento 2 » Magento 2: Add Custom Link/Tab & Page to Customer Account Sidebar

Magento 2: Add Custom Link/Tab & Page to Customer Account Sidebar

October 6, 2022February 11, 2019 by Mukesh Chapagain
Categories Magento, Magento 2 Tags account, customer, Magento, magento2, navigation, sidebar
FacebookTweetLinkedInPinPrintEmailShares

This article shows how you can add custom link or tab in the Customer account sidebar section.

I will also show how you add/show your custom page when you click on the newly added custom link in the customer account sidebar.

So, basically, we will be adding a custom link and linking it to a custom page. The custom page will also contain the customer account sidebar displayed.

Here’s how you do it:

Suppose, your module name is YourNamespace_YourModule.

Table of Contents

Toggle
  • 1) Create customer_account layout XML file
  • 2) Create your module’s routes.xml file
  • 3) Create your module’s layout XML file
  • 4) Create Controller class files
  • 5) Create Block class file
  • 6) Create Template files

1) Create customer_account layout XML file

Create the layout file at this location:

app/code/YourNamespace/YourModule/view/frontend/layout/customer_account.xml

Here, I have added two ways (one is commented out) to add the custom links in the customer account navigation sidebar.

– One will add the links at the bottom of the sidebar list
– The other has the sortOrder feature which can sort the custom links in any custom order

app/code/YourNamespace/YourModule/view/frontend/layout/customer_account.xml
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceBlock name="customer_account_navigation">
            <!-- Add menu to the end of the sidebar -->
            <block class="Magento\Framework\View\Element\Html\Link\Current" name="customer-account-navigation-your-first-link">
                <arguments>
                    <argument name="path" xsi:type="string">yourmodule/yourfirstlink/index</argument>
                    <argument name="label" xsi:type="string">Your First Link</argument>
                </arguments>
            </block>
            <block class="Magento\Framework\View\Element\Html\Link\Current" name="customer-account-navigation-your-second-link">
                <arguments>
                    <argument name="path" xsi:type="string">yourmodule/yoursecondlink/index</argument>
                    <argument name="label" xsi:type="string">Your Second Link</argument>
                </arguments>
            </block>

            <!-- Add menu in the sidebar with sort order -->
            <!--
            <block class="Magento\Customer\Block\Account\SortLinkInterface" name="customer-account-navigation-your-first-link">
                <arguments>
                    <argument name="path" xsi:type="string">yourmodule/yourfirstlink/index</argument>
                    <argument name="label" xsi:type="string">Your First Link</argument>
                    <argument name="sortOrder" xsi:type="number">250</argument>
                </arguments>
            </block>
            <block class="Magento\Customer\Block\Account\SortLinkInterface" name="customer-account-navigation-your-second-link">
                <arguments>
                    <argument name="path" xsi:type="string">yourmodule/yoursecondlink/index</argument>
                    <argument name="label" xsi:type="string">Your Second Link</argument>
                    <argument name="sortOrder" xsi:type="number">260</argument>
                </arguments>
            </block>
            -->
        </referenceBlock>
    </body>
</page>

Showing Active Menu Link when clicked

There was one issue with showing the active menu link in the customer sidebar navigation.

My custom link was clicked and my custom page was displayed but the custom link was not highlighted. Highlighting the active menu link makes it easy to figure out on which page we are in.

To fix this issue, I had to remove the “action” path in the XML code.

In the above XML code, you can see that I have defined my custom menu path as:

<argument name="path" xsi:type="string">yourmodule/yourfirstlink/index</argument>

Here,

yourmodule = my module name
yourfirstlink = my module’s controller name
index = my controller’s action

I removed the ‘index’ text from the path, like this:

<argument name="path" xsi:type="string">yourmodule/yourfirstlink</argument>

Then, the active link issue was solved. Now, when I click on my custom menu link, it becomes highlighted.

TIP:

You can also remove customer sidebar menu items by writing the remove code in the customer_account.xml file you created inside your custom module.

app/code/YourNamespace/YourModule/view/frontend/layout/customer_account.xml
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceBlock name="customer-account-navigation-wish-list-link" remove="true"/>
    </body>
</page>

2) Create your module’s routes.xml file

The routes.xml file maps which module to use for a URL with a specific frontName.

For frontend URL mapping, we create routes file inside etc/frontend folder.
Similarly, for backend URL mapping, we create routes file inside etc/adminhtml folder.

app/code/YourNamespace/YourModule/etc/frontend/routes.xml
<?xml version="1.0"?>

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="standard">
        <route id="productsinrange" frontName="productsinrange">
            <module name="YourNamespace_YourModule" />
        </route>
    </router>
</config>

3) Create your module’s layout XML file

We have defined two links. The paths of the links defined in the above XML code are:

– yourmodule/yourfirstlink/index
– yourmodule/yoursecondlink/index

These paths indicate the controller classpath of your module. These paths should also match the layout XML file name. Hence, we create two different XML files for each specified paths.

<update handle="customer_account"/>

Note:
This code is important in the below XML files. Without this code, the customer sidebar navigation menu will not appear on your custom pages.

We specify our custom Block class and link it to our firstlink phtml file.

app/code/YourNamespace/YourModule/view/frontend/layout/yourmodule_yourfirstlink_index.xml
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="2columns-left" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <update handle="customer_account"/>
    <head>
        <title>
            Your First Link
        </title>
    </head>
    <body>
        <referenceContainer name="content">
            <block class="YourNamespace\YourModule\Block\YourBlock" name="yourmodule.firstlink.index" template="YourNamespace_YourModule::yourfirstlink/index.phtml" cacheable="false" />
        </referenceContainer>
    </body>
</page>

We specify a general Template block class and link it to our second link phtml file.

app/code/YourNamespace/YourModule/view/frontend/layout/yourmodule_yoursecondlink_index.xml
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="2columns-left" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <update handle="customer_account"/>
    <head>
        <title>
            Your Second Link
        </title>
    </head>
    <body>
        <referenceContainer name="content">
            <block class="Magento\Framework\View\Element\Template" name="yourmodule.secondlink.index" template="YourNamespace_YourModule::yoursecondlink/index.phtml" cacheable="false" />
        </referenceContainer>
    </body>
</page>

4) Create Controller class files

We have specified two controller paths in the layout XML file. So, we create two controller classes.

app/code/YourNamespace/YourModule/Controller/YourFirstLink/Index.php
<?php
namespace YourNamespace\YourModule\Controller\YourFirstLink;
 
class Index extends \Magento\Framework\App\Action\Action
{
        /**
         * @var \Magento\Framework\View\Result\PageFactory
         */
        protected $resultPageFactory;
 
        /**
         * @param \Magento\Framework\App\Action\Context $context
         * @param \Magento\Framework\View\Result\PageFactory resultPageFactory
         */
        public function __construct(
            \Magento\Framework\App\Action\Context $context,
            \Magento\Framework\View\Result\PageFactory $resultPageFactory
        )
        {
            $this->resultPageFactory = $resultPageFactory;
            parent::__construct($context);
        }
    /**
     * Default customer account page
     *
     * @return void
     */
    public function execute()
    {
        return $this->resultPageFactory->create();
    }
}
?>
app/code/YourNamespace/YourModule/Controller/YourSecondLink/Index.php
<?php
namespace YourNamespace\YourModule\Controller\YourSecondLink;
 
class Index extends \Magento\Framework\App\Action\Action
{
        /**
         * @var \Magento\Framework\View\Result\PageFactory
         */
        protected $resultPageFactory;
 
        /**
         * @param \Magento\Framework\App\Action\Context $context
         * @param \Magento\Framework\View\Result\PageFactory resultPageFactory
         */
        public function __construct(
            \Magento\Framework\App\Action\Context $context,
            \Magento\Framework\View\Result\PageFactory $resultPageFactory
        )
        {
            $this->resultPageFactory = $resultPageFactory;
            parent::__construct($context);
        }
    /**
     * Default customer account page
     *
     * @return void
     */
    public function execute()
    {
        return $this->resultPageFactory->create();
    }
}
?>

5) Create Block class file

For our firstlink, we had defined our own custom Block class. So, we create the Block class now.

app/code/YourNamespace/YourModule/Block/YourBlock.php
<?php
namespace YourNamespace\YourModule\Block;
class YourBlock extends \Magento\Framework\View\Element\Template
{        
    public function __construct(
        \Magento\Backend\Block\Template\Context $context,        
        array $data = []
    )
    {        
        parent::__construct($context, $data);
    }
    
    public function getHelloWorld()
    {
        return 'Hello World';
    }
    
}
?>

6) Create Template files

app/code/YourNamespace/YourModule/view/frontend/templates/firstlink/index.phtml
<h2>
    <?php echo $block->getHelloWorld(); ?>
</h2>

echo 'My First Link Page';
app/code/YourNamespace/YourModule/view/frontend/templates/secondlink/index.phtml
echo 'My Second Link Page';

Hope this helps. Thanks.

Related posts:

  1. Magento: Add new tab to Customer Account Section
  2. Magento 2: Customer Image/File Upload in Registration & Account Page
  3. Magento2: Programmatically Create Custom Layout XML
  4. Magento: Programmatically Remove Layout Block
Categories Magento, Magento 2 Tags account, customer, Magento, magento2, navigation, sidebar
Magento 2: Show Calendar/DatePicker & Date-Range Field in Custom Form
Magento 1 & 2: Join Collection to get Customer Fullname

About

Mukesh Chapagain Hi, I’m Mukesh Chapagain — a web developer, programmer, and tech enthusiast. Whether you're a beginner or an experienced developer, you’ll find tips, tutorials, and insights to help you navigate the ever-evolving world of technology. Happy coding! 🚀 about...

         

Subscribe via Email



Categories

Most Viewed

  • Very Simple Add, Edit, Delete, View (CRUD) in PHP & MySQL [Beginner Tutorial] - 435,128 views
  • How to Calculate Inverter & Battery Backup Time? - 430,453 views
  • LaTeX: Generate dummy text (lorem ipsum) in your document - 238,158 views
  • GPG: Remove keys from your public keyring? - 203,599 views
  • Magento: How to get attribute name and value? - 189,657 views

Recent Posts

  • Magento: The store that was requested wasn’t found. Verify the store and try again.
  • Magento2: Check Services version on Adobe Cloud Server
  • Magento 2 API: Add Products to Cart & Checkout Place Order
  • Magento 2 API: Create New Customer
  • Magento 2 API: Get Categories

Recent Posts

  • Magento: The store that was requested wasn’t found. Verify the store and try again.
  • Magento2: Check Services version on Adobe Cloud Server
  • Magento 2 API: Add Products to Cart & Checkout Place Order
  • Magento 2 API: Create New Customer
  • Magento 2 API: Get Categories

Most Viewed

  • Very Simple Add, Edit, Delete, View (CRUD) in PHP & MySQL [Beginner Tutorial] - 435,128 views
  • How to Calculate Inverter & Battery Backup Time? - 430,453 views
  • LaTeX: Generate dummy text (lorem ipsum) in your document - 238,158 views
  • GPG: Remove keys from your public keyring? - 203,599 views
  • Magento: How to get attribute name and value? - 189,657 views

Tag Cloud

admin Adobe Commerce api array attribute block category checkout CLI command line crud currency customer Database error extension git Google grid HTML image Javascript Joomla jQuery latex Linux login Magento magento2 magento 2 module MySQL natural language processing NLP nltk nodejs order PHP product python shopping cart template Ubuntu url Wordpress
© 2026 Mukesh Chapagain Blog
Manage Cookie Consent
To provide the best experiences, we use technologies like cookies to store and/or access device information. Consenting to these technologies will allow us to process data such as browsing behavior or unique IDs on this site. Not consenting or withdrawing consent, may adversely affect certain features and functions.
Functional Always active
The technical storage or access is strictly necessary for the legitimate purpose of enabling the use of a specific service explicitly requested by the subscriber or user, or for the sole purpose of carrying out the transmission of a communication over an electronic communications network.
Preferences
The technical storage or access is necessary for the legitimate purpose of storing preferences that are not requested by the subscriber or user.
Statistics
The technical storage or access that is used exclusively for statistical purposes. The technical storage or access that is used exclusively for anonymous statistical purposes. Without a subpoena, voluntary compliance on the part of your Internet Service Provider, or additional records from a third party, information stored or retrieved for this purpose alone cannot usually be used to identify you.
Marketing
The technical storage or access is required to create user profiles to send advertising, or to track the user on a website or across several websites for similar marketing purposes.
  • Manage options
  • Manage services
  • Manage {vendor_count} vendors
  • Read more about these purposes
View preferences
  • {title}
  • {title}
  • {title}