How to add nav items to the navigation on the account page in Memberpress

Edit and override the account dashboard navigation the Memberpress way-safe template overrides that survive plugin updates, plus a hook to render your custom content.

WordPress Development Memberpress

Table of Contents

Overview

The Memberpress account page is what members see after logging in-subscriptions, payments, profile details, and more. Although WordPress manages the page slug, the markup is produced by Memberpress PHP views. That's good news: you can override those views in a child theme or in a small plugin so updates don't wipe your changes.

In this guide you'll copy the account navigation template, add a new tab (e.g. "My Calendar" for an example which we actually used on a Memberpress and Gravity Forms integration), and render custom content when visitors click that tab. We'll do it the Memberpress way so it's clean and update-safe.

Where the nav template lives

If you're using ReadyLaunch, the account navigation file is located at:

Path
plugins/memberpress/app/views/readylaunch/account/nav.php

Two override options

Copy that file to one of the following locations:

  1. {your-plugin}/templates/memberpress/readylaunch/account/nav.php
  2. {your-child-theme}/memberpress/readylaunch/account/nav.php

If you choose a plugin folder (Option 1)

Register your template path so Memberpress looks there first. You don't need this filter if you place overrides in a theme.

Filter: register plugin template path
add_filter('mepr_view_paths', function($paths){
  $custom_path = trailingslashit(OUTSELLERS_GF_PLUGIN_PATH) . 'templates/memberpress';
  array_unshift($paths, $custom_path);
  return $paths;
});

If you choose a child theme (Option 2)

No filter is needed. Memberpress already checks your theme for overrides. A child theme is recommended so your changes survive main-theme updates.

Add a new nav item

Let's add a tab called "My Calendar." In your overridden nav.php, insert another nav item following the Memberpress pattern. We'll use a unique action value, my-calendar, and expose filters for the label and link (just like core items do).

Excerpt from your overridden nav.php
<div class='mepr-account-container'>
  <nav id="mepr-account-nav" x-data="{ open: false }" class="mepr-nav" :class="open ? 'open' : ''" @toggle-menu.window="open=!open">

    <!-- Existing core item (example) -->
    <span class="mepr-nav-item <?php MeprAccountHelper::active_nav('home'); ?>">
      <a href="<?php echo MeprHooks::apply_filters('mepr-account-nav-home-link', $account_url . $delim . 'action=home'); ?>">
        <?php echo MeprHooks::apply_filters('mepr-account-nav-home-label', _x('My Profile', 'ui', 'memberpress')); ?>
      </a>
    </span>

    <!-- New custom item -->
    <span class="mepr-nav-item <?php MeprAccountHelper::active_nav('my-calendar'); ?>">
      <a href="<?php echo MeprHooks::apply_filters('mepr-account-nav-my-calendar-link', $account_url . $delim . 'action=my-calendar'); ?>">
        <?php echo MeprHooks::apply_filters('mepr-account-nav-my-calendar-label', _x('My Calendar', 'ui', 'memberpress')); ?>
      </a>
    </span>

  </nav>
</div>

Key changes: the filters (mepr-account-nav-my-calendar-link and mepr-account-nav-my-calendar-label), the action in the URL (my-calendar), and your visible link text ("My Calendar").

Render content for your new action

Now hook into mepr_account_nav_content to output content when the user visits account?action=my-calendar. You can keep things simple with inline markup, or include a PHP view from your plugin.

Hook: render content for my-calendar
add_action('mepr_account_nav_content', function($action, $user){
  if ($action === 'my-calendar') {
    // Option A: include a view from your plugin
    // include OUTSELLERS_GF_PLUGIN_PATH . 'snippets/wedo-junkremoval/otslr-templates/calendar-admin-main.php';

    // Option B: inline a small template if it's simple
    echo '<section class="mepr-my-calendar-view">
      <h3>My Calendar</h3>
      <p>Welcome, ' . esc_html($user->user_login) . '. Here is your calendar.</p>
      <div id="calendar-mount"></div>
    </section>';

    // Optional: enqueue or inline scripts/styles for this tab only
    // (see the next section for patterns)
  }
}, 11, 2);

That's it-clicking "My Calendar" in the account sidebar will render your content area. If you prefer separate files for clarity, go with Option A. For a small UI, Option B keeps it self-contained.

Enqueue JS/CSS or inline them

For larger UIs (calendar widgets, charts, etc.), enqueue assets only when your tab is active:

Conditionally enqueue on my-calendar
add_action('wp_enqueue_scripts', function(){
  if (isset($_GET['action']) && $_GET['action'] === 'my-calendar' && is_user_logged_in()) {
    wp_enqueue_style('my-calendar-css', plugins_url('assets/css/my-calendar.css', __FILE__), [], '1.0');
    wp_enqueue_script('my-calendar-js', plugins_url('assets/js/my-calendar.js', __FILE__), ['jquery'], '1.0', true);
  }
});

For smaller enhancements, it's fine to inline a bit of JS right in your rendered template. Keep performance in mind and avoid loading heavy libraries on every account page view if users won't need them.

Quick troubleshooting

  • Template not loading? Confirm your override path, and if you used a plugin folder, make sure the mepr_view_paths filter is in place.
  • Wrong tab "active" state? The second parameter in MeprAccountHelper::active_nav() must match your action: my-calendar.
  • URL looks right but no content? Verify your mepr_account_nav_content callback checks for $action === 'my-calendar' and that the hook priority allows it to run (priority 11 is usually safe).
  • ReadyLaunch disabled? Paths may differ. Inspect the plugin's app/views/ folder to confirm the active template path.