Add a Custom Page to the "My Account" Area in WooCommerce

Want custom account pages right now?

Try the 14-day free trial of WooCommerce Account Pages and build up your account area using the WordPress pages interface.

Get Free Trial

Since WooCommerce v2.6.0, the My Account area in WooCommerce has utilised what is called “endpoints”. This means that there is only 1 page set up in WordPress (something like “/my-account”), and the subpages of that are dynamic loaded (like “/my-account/orders”). It’s a good method for WooCommerce to have implemented, as it means you do not need to manage as many pages in your WordPress admin; the contents of that page is loaded in dynamically based on the “endpoint” (“orders”, in our example).

This does make adding a new subpage to the My Account area a little more complicated, but it’s definitely possible! Take a look at how it’s done.

Note: I’ll be writing this in standard functions which you could add to your theme’s functions.php file, but I’d recommend creating a plugin for the functionality and doing it within a class.

Add An “Information” Link To The My Account Navigation

Firstly, let’s add an information link to the My Account navigation.

  • The woocommerce_account_menu_items filter accepts 1 parameter: an array of navigation items.
  • In the iconic_account_menu_item() we’re adding our “Information” link to the end of the $items array. We’re using a key/value pair; the array key is the endpoint URI (“information”), and the value is a translatable string of the link title (“Information”).

Add A “My Account” Endpoint

For this example, we’ll add a new page called “Information”, under the URI of my-account/information. This means our endpoint is simply information, as per our custom menu link above.

  • We’re adding a function called iconic_add_my_account_endpoint on the init action.
  • We’re using add_rewrite_endpoint() to add our endpoint. This will require you permalinks to be refreshed (just visit SettingsPermalinks).
  • add_rewrite_endpoint() accepts 2 parameters. The first is our endpoint URI, and the second is where the endpoint will be available. As “My Account” is a page, we’ve assigned our endpoint to EP_PAGES. You can view all available “Places” on the codex.

After this is added, the /my-account/information URL should return the normal account dashboard, and not a 404 page.

Add Content To Our New Endpoint

Rather than using a custom template, I think it’s better to use the hooks available. This way we can keep the default account layout, including the sidebar navigation. WooCommerce provide a custom hook for your endpoint, which can be accessed like so:

We’re using the woocommerce_account_information_endpoint action. This is a custom action that you can use for any endpoint you create by formatting it like so woocommerce_account_{your-endpoint-slug}_endpoint.

Looking for an easier solution?

Simply install WooCommerce Account Pages and build up your account area using WordPress subpages.

Get Free Trial

Add An “Is Endpoint?” Helper

It could be useful for us to add a helper function to check whether the currently viewed page is an endpoint. I couldn’t see any native functions in WordPress that do this (correct me if I’m wrong?), so I wrote this simple function for that purpose.

So now we can use if( iconic_is_endpoint('information') ) { ... } to check whether the current page is our endpoint. Note: You can pass any endpoint into the function.

Conclusion

That should get you started! There’s obviously a few lines of code to add, but once you’ve done it, it’s fairly straightforward to modify and evolve. Let me know if you use this tutorial on your WooCommerce site. I’d be interested to know what tabs you’ve added.

36 Comments

  1. cuqpon says:

    Why don`t just use this hook, instead of endpoint checking on template redirect 🙂

    add_action( ‘woocommerce_account_SLUGHERE_endpoint’, function(){
    echo ‘hello’;
    } );

  2. Osber Bermúdez says:

    what is the right way to add css to the iconic_information_endpoint_content function?

    • James Kemp says:

      Hey Osber,

      If you want it to only show on that page, I’d suggest using the iconic_is_endpoint helper to detect the current page and then add scripts/styles in the normal way using wp_enqueue_style. You’d need to check this at a point where $wp_query is accessible, so probably best on the wp_enqueue_scripts hook.

  3. Bakhash 2677 says:

    Hi
    Thank you ! very useful
    How could i get customer info like name email … ?

  4. Geetha Lakshmi says:

    Hi, this is very good post, here i want to add sub menu items, can u pls give idea for it

  5. Scott J Freeman says:

    Fair warning for anyone using this… I added these code snippets to my child theme’s functions.php file and my entire site went to a 500 error. This was on a local dev environment and I’m still trying to fix it… it won’t even let me re-enable WooCommerce anymore due to some fatal error for “allowed memory size” and is referencing wp-includesfunctions.php even AFTER removing this code.

    • Scott J Freeman says:

      Update: Fixed the issue. Turns out ALL of my local sites went offline (500 error) due to PHP freaking out about memory limit. I had to change this in php.ini
      memory_limit = 256M
      Seems like a big jump for a small addition.

      • James Kemp says:

        Sounds like something else is going here. Did you try enabling debug log to see if any other errors were thrown?

  6. coachasymi says:

    Great & easy tut, even for somebody without much experience in code like me! A question though, can you call / display in the Information tab a content from another page instead of “Your new content” that have to be manually put under function iconic_information_endpoint_content() ? Cause it would be great if we could do that.

    • James Kemp says:

      Glad to hear it! Do you mean content from another WP page? If so, hold on a second and I’ll get the code for you!

      • coachasymi says:

        Yes, content from another WP page. Say the page has text, images and shotcode (why not?). I wonder if we could display them in the newly added tab. I’m experimenting around on my own based on your codes but has no luck so far.

    • James Kemp says:

      echo apply_filters( ‘the_content’, get_post_field( ‘post_content’, 42 ) );

      Where 42 is your page ID.

      • coachasymi says:

        How on earth did you do that!? It’s working perfectly on my site =) Blew me away! Thanks a lot! Just so you know, I have changed all the ‘information’ text I could find in the code and replace with my own. I understand that those are the new tab / endpoint name, right? Is this the right way to do it? Also, do we need to put some filter or array to change the order of the tabbed menus?

        • James Kemp says:

          Glad it works! yes, just change the information wording – probably should have chosen something less generic to make it more clear!

          In terms of ordering, you’d need to sort the $items array in the iconic_account_menu_items function.

          • coachasymi says:

            Yeah, I managed to re-order the tabbed menus! Thanks for the hint =) Now I noticed one tiny “flaw” in the original code, if you could prefect it – when you click on “Information” menu, however the entry-title doesn’t change to “Information” but went to the default “My Account” entry-title instead. You know, when you click on “Orders” the entry-title would be “Orders” so our users won’t be confused. Can you help tweak it a little bit more? TIA

          • Will Ambrose says:

            Hi, following this thread. It’s helping me a lot. Can you elaborate a bit on how you ordered the account menu items? Do I have to rewrite that whole $item array in my custom order or can ‘information’ be inserted into a different spot in $items?

          • James Kemp says:

            Hey @disqus_90ufxQjrVd:disqus

            You’d probably need to loop through the current items, check which if the item you’re currently on is the one you want to insert “Information” after, then add information to the array and break out of the loop.

          • mrblack says:

            Would love some direction on this as well!

          • Will Ambrose says:

            I created this snippet in order to add my extra item (videos). It basically rewrites the menu items. There might be a more elegant solution to ‘insert’ the extra menu item but this works and has been live on a busy site for a few months.

            https://codedump.io/share/U

          • mrblack says:

            Is there a snippet for this? Having trouble.

      • Hey James,

        Thanks for the post. I am a complete non-techie with no knowledge of coding. I sort of understood your thing, as you have written it in very simple language. I got my endpoint. Now, I also want to add a customer wp page. I replaced given below line of code with your and my page ID but I am still not getting redirected to that page. Can you help please ? Thanks in advance.

        echo ‘Your new content’; —-> echo apply_filters( ‘the_content’, get_post_field( ‘post_content’, 1136 ) );

  7. Aleksandr Kh says:

    Thanks)

  8. yusra says:

    when i use this echo apply_filters( ‘the_content’, get_post_field( ‘post_content’, 42 ) ); the respective page opens.(named : customer) But I have applied a self created template on page customers that does not work.
    on the other hand if I don’t add page customer as a tab it works perfect and template shows the respective data

  9. Isaías Subero says:

    Thank you so much. It works like a charm.

  10. Johann Le Niniven says:

    hello,

    when I use your code I have my content display twice :
    https://drive.google.com/fi

    i don’t get why
    could you help me ?

    best regards,
    Johann

  11. I want to add up to 3 different menus, how do I go about it. The content of each menu should be printed using a short code generated by a plugin like [affiliate_area], [twofactor_user_settings] and [insert page=’user-wallets’ display=’content’].
    How do I achieve such?

  12. Asola Akbar says:

    Hi, nice tutorial, i get the tabs part. Im looking for the same function, but not exactly like this. I want to add edit profile in the new page, not inside the tabs like usual woocommerce. Any idea how to move the “form-edit-account.php” function to new page?

  13. hardik says:

    i want to know that is there a way to display a content of some page or php file instead of ‘your new content’?

  14. Alex says:

    Can you tell me how to add a field in Registration form? I have been stuck in this code

    function wooc_validate_extra_register_fields( $username, $email, $validation_errors ) {
    if ( isset( $_POST[‘billing_first_name’] ) && empty( $_POST[‘billing_first_name’] ) ) {
    $validation_errors->add( ‘billing_first_name_error’, __( ‘Error: First name is required!’, ‘woocommerce’ ) );
    }
    if ( isset( $_POST[‘billing_last_name’] ) && empty( $_POST[‘billing_last_name’] ) ) {
    $validation_errors->add( ‘billing_last_name_error’, __( ‘Error: Last name is required!.’, ‘woocommerce’ ) );
    }
    return $validation_errors;
    }
    add_action( ‘woocommerce_register_post’, ‘wooc_validate_extra_register_fields’, 10, 3 );

    I have used this article as reference https://www.cloudways.com/blog/add-woocommerce-registration-form-fields/

  15. jadenew says:

    As someone with EXTREMELY basic knowledge of PHP – thank you for posting the tutorial, it’s awesome and very easy to follow!! 🙂

  16. Ferdin Norbert says:

    Hi, Thanks for the tutorial. By the way, I still have problem. My endpoint always redirects to the dashboard.

Leave a Reply

Your email address will not be published. Required fields are marked *