Map arbitrary URL to in WordPress without 404 or “Page Not Found”

Let’s say my blog lives here…

/blog/

Let’s say I have an infinite number of arbitrary URLs…

Read More
/blog/browse/furniture/
/blog/browse/decor/
/blog/browse/bed/

I would like the theme wrapper to load the browse.php template for any pages that match the /browse/ URL pattern.

I was able to make this happen, however, while the template content loads in just fine, WordPress is treating the page as a 404 page in the background. So the page title is “Page Not Found”, and built-in functions such as “is_404()” are returning true. Is there any way to map these dynamic pages and have WordPress think they are valid?

Here’s the code I came up with…

add_filter('template_include', function($template) {
  global $wp_query;
  if ($wp_query->query['category_name'] === 'browse') {
    $template = locate_template(array('browse.php'));
  }
  return $template;
}, 99);

By the way, this method works because my permalink structure is set to /%category%/%postname%/ — so currently, WordPress sees these /browse/ pages as a category and therefore, I am able to check against the “category_name” object.

Any help you can provide would be much appreciated.

Related posts

1 comment

  1. The problem here is that you just filter the template that should be displayed – so WordPress send a 404, and you just tell him to show a different template for your 404 page for this special case.

    What you need to do is to create a page in admin and associate it to your template – doesn’t matter if you don’t use content or title of it. You just need to attach a post/page to your template in order to make a valid rewrite rule.

    You can create that page from your plugin on activation with the following (it will store the page ID as an option):

    function register_activation_hook() {
        if(get_option('browse_page_id') !== false) {
            $page_id = wp_insert_post(array(
                'post_title' => __('Your page title', 'plugin-domain'),
                'post_content' => '',
                'post_status' => 'publish',
                'post_type' => 'page',
                'post_author' => 1,
            ));
            if($page_id && ! is_wp_error($page_id)) {
                update_post_meta($page_id, '_wp_page_template', 'browse.php');
                update_option('browse_page_id', $page_id, true);
            }
        }
    }
    register_activation_hook(__FILE__, 'register_activation_hook');
    

    You must use this in your plugin file, and deactivate/reactivate your plugin to make it trigger.

    To make your template recognized by WordPress, add the following at the top of your template:

    <?php
    /**
     * Template Name: Browse
     */
    ?>
    

    Then, in your functions.php, add the following in order to define a new rewrite tag to handle your category:

    function custom_rewrite_tag() {
      add_rewrite_tag('%browse_category%', '([^&]+)');
    }
    add_action('init', 'custom_rewrite_tag', 10, 0);
    

    And finally, add a rewrite rule that will use the page ID previously created and the rewrite tag:

    function custom_rewrite_rule() {
        if(get_option('browse_page_id') !== false) {
            add_rewrite_rule('^browse/([^/]*)/?','index.php?page_id='.get_option('browse_page_id').'&browse_category=$matches[1]','top');
        }
    }
    add_action('init', 'custom_rewrite_rule', 10, 0);
    

    To access the category parameter in your template, use the following:

    $wp_query->query_vars['browse_category']
    

Comments are closed.