I'm trying to find a way to change the href of a nav menu page link from the parent theme's default, which goes to its relative page, to another url. For example, I have a menu link "Our Philosophy" that links to the "Our Philosophy" page, but desire for it to go to timecube.com (rip).

It seems perhaps using a filter (nav_menu_link_attributes?) might be a simple way to achieve this. However, I've been unable to wrap my head around using filters to get this working.

I would think I'd need something like:

function change_nav_url( $atts, $item ) {
    // modify $item href?
add_filter ( 'nav_menu_link_attributes', 'change_nav_url');

My initial thought would be I would need to call this function somewhere--with apply_filters() maybe--and would need to get $atts and $item manually from somewhere and pass them into it. But that creates the problem--how do I get them, and from what (a menu object?). And thinking about it, if I do have to retrieve them manually, I don't really see the point of using a filter v. a plain function, so maybe I have to put it into the plugin folder and it'll automatically give me access to $atts or something? (That didn't work). Either way, I'm clearly not understanding something.

I appreciate any help bringing light to my newb ignorance.

  • If one of the answers below were helpful please mark it as the accepted answer.
    – user9447
    Mar 27, 2018 at 16:14
  • You asked this, because you were unable to do it from inside the Menu admin screen by choosing & adding a 'Custom Links' item to the Menu ? (maybe back in '16 this feature not existed) I'm just curious, cheers Jan 29, 2021 at 21:47

2 Answers 2


You are on right track, with few minor kinks.

  1. You need to modify $atts and return it. Any arguments after the first one are provided for information and should not be changed.
  2. You need to tell add_filter() that you expect more than one argument.

The example with some debug code would be along the lines of:

add_filter( 'nav_menu_link_attributes', function ( $atts, $item, $args, $depth ) {

    var_dump( $atts, $item ); // a lot of stuff we can use

    var_dump( $atts['href'] ); // string(36) "http://dev.rarst.net/our-philosophy/"

    var_dump( get_the_title( $item->object_id ) ); // string(14) "Our Philosophy", note $item itself is NOT a page

    if ( get_the_title( $item->object_id ) === 'Our Philosophy' ) { // for example

        $atts['href'] = 'https://example.com/';

    return $atts;
}, 10, 4 ); // 4 so we get all arguments
  • Thanks for getting back--that's very helpful with the code of where to access / modify the href (also about var_dump, didn't know about that). I'm curious though, is what I was thinking right about just needing to put this add_filter function in a plugin folder to access all the parameters like $atts, $item, or do I need to use apply_filters at all?
    – Aristoatle
    Aug 13, 2016 at 22:21
  • You don't need to apply filters anywhere, you just need to add to existing filter, which gets applied inside core's menu code. My example is self–sufficient.
    – Rarst
    Aug 13, 2016 at 22:45
  • So practically, just writing that function somewhere (functions.php or its own .php) is sufficient to have it getting applied / executed via core? Or do I need to activate it as a plugin in Wordpress or something? I tried just putting it in its own .php, as well as some test filters that just echo stuff, but it doesn't seem to do anything. Sorry if this seems a little obtuse... I feel like I'm missing something staring me in the face.
    – Aristoatle
    Aug 13, 2016 at 23:32
  • You need to put this somewhere that appropriate in what WP loads. This is would typically be a plugin or theme's functions.php file.
    – Rarst
    Aug 14, 2016 at 8:34
  • Gotcha. I tried it in functions.php along with test output (using echo) but it doesn't seem to do anything. Will try it as a plugin and see what happens
    – Aristoatle
    Aug 14, 2016 at 18:21

This will allow you to update the URL for specific menu items. In the case of the OP, "Link Title" would be replaced with "Our Philosophy".

This would be placed in your child theme's functions.php

 function update_menu_link($items){

    //look through the menu for items with Label "Link Title"
        foreach($items as $item){

            if($item->title === "Link Title"){ // this is the link label your searching for
                $item->url = "http://newlink.com"; //this is the new link
        return $items;

    add_filter('wp_nav_menu_objects', 'update_menu_link', 10,2);
  • The check for if($item->title should be if ( $item->title === 'Link Title' ) - your use of single equals = would assign the value of "Link Title" to $item->title, not compare it.
    – phatskat
    Mar 23, 2018 at 20:37
  • @phatskat - thanks, I have it updated. It was working correctly, but you are right
    – dbmpls
    Mar 27, 2018 at 15:48
  • simple and helpful, it works for me :)
    – user123
    Aug 12, 2020 at 6:50
  • Do you need to write that "2" as the add_filter arg number there (last line)? It seems you are not using the 2nd arg in the function. As best practice i would suppose you can leave that out (?) Jan 29, 2021 at 22:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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