I know this is a fairly common topic around here, but I can't seem to figure out a solution to my particular case from reading similar threads.

Basically, my permalink structure needs to be /%postname%/ for compatibility with a finicky plugin. The plugin authors may fix this in the future, but for now I need to come up with my own solution. The problem is, I want my blog post urls to be /blog/%postname%/. I need some way to hook into the URL rewriting for just the post post type and change the permalink structure from /%postname%/ to /blog/%postname%/.

Any ideas?

  • Have you tried changing permalink structure to /blog/%postname%/?
    – Anh Tran
    Nov 2, 2011 at 4:11
  • @rilwis, yes, and that structure works perfectly. The problem is that I'm also using Shopp (1.2 Beta) plugin, and for some reason Shopp breaks completely with any permalink structure other than /%postname%/. I know, they should fix this on their end, but I have no idea how long that will take (or if they even will fix it), so I'm trying to find my own work around.
    – Dominic P
    Nov 2, 2011 at 23:07
  • Well, I never found a solution to this, but I wound up switching from Shopp to WooCommerce. So, my permalinks are working perfectly now. Thanks to everyone who helped on this.
    – Dominic P
    Dec 2, 2011 at 21:51
  • Please add your solution as an answer, so your question does not haunt site as unanswered.
    – Rarst
    Jan 27, 2012 at 18:49
  • @Rarst, as I said in my comment, I never found a solution for this unless you consider giving up on the problem a solution. If you like, I can post that I gave up and switched plugins so I wouldn't have to solve this as a solution.
    – Dominic P
    Jan 28, 2012 at 2:54

2 Answers 2


Even though this is no longer a problem for you, I decided to pursue it for purely academic reasons. I got it working by prepending rewrite rules and filtering permalinks. Note that I wouldn't actually recommend doing this, but it's fun to know it's possible :)

function filter_post_link($permalink, $post) {
    if ($post->post_type != 'post')
        return $permalink;
    return 'blog'.$permalink;
add_filter('pre_post_link', 'filter_post_link', 10, 2);

add_action( 'generate_rewrite_rules', 'add_blog_rewrites' );
function add_blog_rewrites( $wp_rewrite ) {
    $wp_rewrite->rules = array(
        'blog/([^/]+)/?$' => 'index.php?name=$matches[1]',
        'blog/[^/]+/attachment/([^/]+)/?$' => 'index.php?attachment=$matches[1]',
        'blog/[^/]+/attachment/([^/]+)/trackback/?$' => 'index.php?attachment=$matches[1]&tb=1',
        'blog/[^/]+/attachment/([^/]+)/feed/(feed|rdf|rss|rss2|atom)/?$' => 'index.php?attachment=$matches[1]&feed=$matches[2]',
        'blog/[^/]+/attachment/([^/]+)/(feed|rdf|rss|rss2|atom)/?$' => 'index.php?attachment=$matches[1]&feed=$matches[2]',
        'blog/[^/]+/attachment/([^/]+)/comment-page-([0-9]{1,})/?$' => 'index.php?attachment=$matches[1]&cpage=$matches[2]',
        'blog/([^/]+)/trackback/?$' => 'index.php?name=$matches[1]&tb=1',
        'blog/([^/]+)/feed/(feed|rdf|rss|rss2|atom)/?$' => 'index.php?name=$matches[1]&feed=$matches[2]',
        'blog/([^/]+)/(feed|rdf|rss|rss2|atom)/?$' => 'index.php?name=$matches[1]&feed=$matches[2]',
        'blog/([^/]+)/page/?([0-9]{1,})/?$' => 'index.php?name=$matches[1]&paged=$matches[2]',
        'blog/([^/]+)/comment-page-([0-9]{1,})/?$' => 'index.php?name=$matches[1]&cpage=$matches[2]',
        'blog/([^/]+)(/[0-9]+)?/?$' => 'index.php?name=$matches[1]&page=$matches[2]',
        'blog/[^/]+/([^/]+)/?$' => 'index.php?attachment=$matches[1]',
        'blog/[^/]+/([^/]+)/trackback/?$' => 'index.php?attachment=$matches[1]&tb=1',
        'blog/[^/]+/([^/]+)/feed/(feed|rdf|rss|rss2|atom)/?$' => 'index.php?attachment=$matches[1]&feed=$matches[2]',
        'blog/[^/]+/([^/]+)/(feed|rdf|rss|rss2|atom)/?$' => 'index.php?attachment=$matches[1]&feed=$matches[2]',
        'blog/[^/]+/([^/]+)/comment-page-([0-9]{1,})/?$' => 'index.php?attachment=$matches[1]&cpage=$matches[2]',
    ) + $wp_rewrite->rules;
  • Wow, that's an impressive list of rewrite rules. Thanks for taking the time to sort through this. I'm sure it will come in handy for someone down the line. I haven't tested this solution myself, but it looks great.
    – Dominic P
    Jan 30, 2012 at 19:08

If other people are looking for it, here is a variation of Matthew answer (which work perfectly) to achieve this:

Blog archive : /blog/

Blog category : /blog/category-name/

Blog post : /blog/category-name/post-name/

add_action( 'generate_rewrite_rules', 'add_blog_rewrites' );
function add_blog_rewrites( $wp_rewrite ) {
    $wp_rewrite->rules = array(
        'blog/([^/]+)/?$' => 'index.php?taxonomy=category&term=$matches[1]',
        'blog/([^/]+)/page/([0-9]+)/?$' => 'index.php?taxonomy=category&term=$matches[1]&paged=$matches[2]',
        'blog/[^/]+/([^/0-9]+)/?$' => 'index.php?name=$matches[1]',
        'blog/[^/]+/[^/]+/attachment/([^/]+)/?$' => 'index.php?attachment=$matches[1]',
        'blog/[^/]+/[^/]+/attachment/([^/]+)/trackback/?$' => 'index.php?attachment=$matches[1]&tb=1',
        'blog/[^/]+/[^/]+/attachment/([^/]+)/feed/(feed|rdf|rss|rss2|atom)/?$' => 'index.php?attachment=$matches[1]&feed=$matches[2]',
        'blog/[^/]+/[^/]+/attachment/([^/]+)/(feed|rdf|rss|rss2|atom)/?$' => 'index.php?attachment=$matches[1]&feed=$matches[2]',
        'blog/[^/]+/[^/]+/attachment/([^/]+)/comment-page-([0-9]{1,})/?$' => 'index.php?attachment=$matches[1]&cpage=$matches[2]',
        'blog/[^/]+/([^/]+)/trackback/?$' => 'index.php?name=$matches[1]&tb=1',
        'blog/[^/]+/([^/]+)/feed/(feed|rdf|rss|rss2|atom)/?$' => 'index.php?name=$matches[1]&feed=$matches[2]',
        'blog/[^/]+/([^/]+)/(feed|rdf|rss|rss2|atom)/?$' => 'index.php?name=$matches[1]&feed=$matches[2]',
        'blog/[^/]+/([^/]+)/[^/]+/page/?([0-9]{1,})/?$' => 'index.php?name=$matches[1]&paged=$matches[2]',
        'blog/[^/]+/([^/]+)/comment-page-([0-9]{1,})/?$' => 'index.php?name=$matches[1]&cpage=$matches[2]',
        'blog/[^/]+/([^/]+)/[^/]+(/[0-9]+)?/?$' => 'index.php?name=$matches[1]&page=$matches[2]',
        'blog/[^/]+/[^/]+/([^/0-9]+)/?$' => 'index.php?attachment=$matches[1]',
        'blog/[^/]+/[^/]+/trackback/?$' => 'index.php?attachment=$matches[1]&tb=1',
        'blog/[^/]+/[^/]+/([^/]+)/feed/(feed|rdf|rss|rss2|atom)/?$' => 'index.php?attachment=$matches[1]&feed=$matches[2]',
        'blog/[^/]+/[^/]+/([^/])+/(feed|rdf|rss|rss2|atom)/?$' => 'index.php?attachment=$matches[1]&feed=$matches[2]',
        'blog/[^/]+/[^/]+/([^/]+)/comment-page-([0-9]{1,})/?$' => 'index.php?attachment=$matches[1]&cpage=$matches[2]'
    ) + $wp_rewrite->rules;

With /%category%/%postname%/ for the permalink structure and this for the categories links:

function filter_category_link($permalink, $term) {
    if($term->taxonomy !== 'category') {
        return $permalink;
    return 'blog' . str_replace('category/', '', $permalink);
add_filter('pre_term_link', 'filter_category_link', 10, 2);
  • What's the advantage to this one over Matthew's answer?
    – Tobe_Sta
    Jan 22, 2021 at 4:11
  • @Tobe_Sta This is explained on the top of my answer...
    – vard
    Sep 23, 2021 at 16:47

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