I need to add the author name as a subdirectory prefix for all user's posts and pages.

For example:

example.com/johndoe/ //The author page for John Doe
example.com/johndoe/category/test-post/ //Test post by user John Doe
example.com/johndoe/test-page/ //Test page by user John Doe

If I change the permalink structure to: /%author%/%category%/%postname%/ this works fine for displaying a user's post but not a user's page.

However I'm not sure if there is something I can do in .htaccess or functions.php that will allow me to get the pages to work in the same manner.

I understand this can be accomplished with Multisite, however I'm trying to avoid using this because the client doesn't want to use it.

  • You say "this works fine". So what is wrong ?
    – Random
    May 4 '16 at 16:03
  • It works fine for posts, but not for pages. I'll edit the question to make this more clear. May 4 '16 at 16:06
  • 1
    Will every user have the same set of "pages"? It would be helpful if you would outline the desired complete solution in more detail, but it seems offhand that you might do better with a programmatic solution involving categories or other taxonomies, or custom post types and custom taxonomies, than by relying on Pages.
    – CK MacLeod
    Mar 10 '17 at 6:28
  • 1
    Oops, got snookered by the revived old question syndrome. What I get for StackExchanging on my phone. I'm going to assume this question is dead until further notice...
    – CK MacLeod
    Mar 10 '17 at 6:29
  • 1
    With that said: utility is for informational purposes and rarely changed, almost static data specific to the "user" or "author" in this case; archival is the data the "user" has input over time. Mar 10 '17 at 6:38

By the looks of it, there's a plugin to achieve exactly this, so save you rolling your own for it.

The plugin is: https://wordpress.org/plugins/permalinks-customizer/

I installed it to test that it does what you're looking for. Here's a screenshot that shows what you'd do:

Permalinks Customizer


Tested with Wordpress 5.0.4

The first problem to solve it's the post_name value for pages that would share the same slug (e.g. about-me).

The simpler solution I found is to add the author nicename (beware: in my solution it should not contain a hyphen!) as the first part of the slug:

about-me page post_name for john: john-about-me
about-me page post_name for mary: mary-about-me

This could be achieved using the wp_insert_post_data filter hook (see wp_insert_post() function defined in wp-includes/post.php) when creating the page:

// about-me => <author_name>-about-me

add_filter( 'wp_insert_post_data', 'custom_wp_insert_post_data', 99, 2);

function custom_wp_insert_post_data($data, $postarr)
    if(($data["post_type"] == "page") && ($data["post_status"] != "auto-draft"))
        $author_name = get_the_author_meta( 'user_nicename', $data["post_author"] );

        // insert
        if($postarr['hidden_post_status'] == "draft") {         
            $data["post_name"] = $author_name . "-" . $data["post_name"];               
        // update
        else {
            list($author, $slug) = explode("-", basename($data["post_name"]), 2 );

            // wrong permalink -> prepend the author
            if($author != $author_name) { 
                $data["post_name"] = $author_name . "-" . $data["post_name"];

    return $data;   

Next step it will be to change the wp rewrite rules to reflect our desires (you need also to update the settings > permalinks):

add_filter('page_rewrite_rules', 'custom_page_rewrite_rules');

function custom_page_rewrite_rules($page_rewrite) 
    // remove : john/about-me  => index.php?pagename=john/about-me

    // add: john/about-me  => index.php?pagename=john-about-me
    $page_rewrite["(.?.+?)/(.+?)/?$"] = "index.php?pagename=\$matches[1]-\$matches[2]";

    return $page_rewrite; 

add_filter('post_rewrite_rules',  'custom_post_rewrite_rules'); 

// posts have the /%author%/%category%/%postname% permalink structure
function custom_post_rewrite_rules($post_rewrite) 
    // remove: john/about-me  => index.php?category_name=about-me&author_name=john

    return $post_rewrite; 

Last step it will be to change the value returned when the code asks for a page permalink (e.g. in menus).
To do that we have to use the page_link filter hook (located in get_page_link() function defined in wp-includes/link-template.php)..

// http://www.example.com/john-about-me => http://www.example.com/john/about-me
add_filter('page_link', 'custom_page_link', 99, 3);

function custom_page_link( $link, $ID, $sample ) 
    list($author, $slug) = explode("-", basename($link), 2 );

    return ( site_url() . "/" . $author . "/" . $slug  );   

..but it won't work if you don't set to false the use_verbose_page_rules property of $wp_rewrite global instance; this will stop parse_request() to check if a "wrong" matched pagepath exixts:

add_action('init', 'disable_verbose_page_rule');

function disable_verbose_page_rule()
    global $wp_rewrite;

    $wp_rewrite->use_verbose_page_rules = false;            

That's all.. Well, to be honest this is the main part, but it will be some other work to do, like change the rewrite rules also for all the attachment/comments/feed/embed stuff linked to a page and may be something else that I didn't have enough time to discover.

This is my first post; I hope it will help someone, like many others helped me.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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