Creating SEO friendly search results URLs

When you run a property search on a WordPress website using Property Hive the URL’s currently look something like so:

http://yoursite.com/property-search/?department=residential-sales&minimum_price=&maximum_price=&minimum_bedrooms=

Although functional, it does look a little messy and isn’t the most optimised URL for SEO purposes. As such, we’ve come up with a way to convert the above into nice URL’s like so:

http://yoursite.com/property-search/department/residential-sales/maximum_price/500000/

I think you’ll agree this looks much nicer. To benefit from this you use a snippet like so:

add_filter( 'query_vars', 'propertyhive_register_query_vars' );
function propertyhive_register_query_vars( $vars ) 
{
    $vars[] = 'property_search_criteria';
    return $vars;
}
 
add_action( 'init', 'propertyhive_add_rewrite_rules' );
function propertyhive_add_rewrite_rules() 
{
    global $wp_rewrite;
     
    $post = get_post( ph_get_page_id('search_results') );
 
    if ( $post instanceof WP_Post ) 
    {
        add_rewrite_rule( $post->post_name . "/(.*)/{$wp_rewrite->pagination_base}/([0-9]{1,})/?$", 'index.php?post_type=property&property_search_criteria=$matches[1]&paged=$matches[2]', 'top' );
        add_rewrite_rule( $post->post_name . "/(.*)/?$", 'index.php?post_type=property&property_search_criteria=$matches[1]', 'top' );
    }
}
 
add_action( 'parse_request', 'propertyhive_parse_request' );
function propertyhive_parse_request($wp_query)
{
    // First we do redirect if on the search page and have received the standard query string parameters
    if ( !is_admin() && !isset($wp_query->query_vars['property']) && isset($wp_query->query_vars['post_type']) && $wp_query->query_vars['post_type'] == 'property' && !isset($wp_query->query_vars['p']) && !isset($wp_query->query_vars['name']) )
    {
        $new_url_segments = array();
        if ( !empty($_GET) )
        {
            foreach ( $_GET as $key => $value )
            {
                if ( is_array($value) )
                {
                    $value = 'multi-' . implode("|", $value);
		}
                if ( trim($value) != '' )
                {
                    $new_url_segments[] = $key . '/' . urlencode($value);
                }
            }
            if ( !empty($new_url_segments) )
            {
                wp_redirect( get_permalink( ph_get_page_id('search_results') ) . implode("/", $new_url_segments) . '/', 301 );
                exit();
            }
        }
    }
 
    // Now parse nice SEO URL back into $_GET
    foreach ($wp_query->query_vars as $name => $value)
    {
        if ($name == 'property_search_criteria' && $value != '')
        {
            // Split property search criteria into blocks:
            // department/X
            // minimum_price/X
            // etc
            $segments = array_map(
                function($value) {
                    return implode('/', $value);
                },
                 array_chunk(explode('/', $value), 2)
            );
 
            // Now turn these into $_GET and $_REQUEST
            foreach ($segments as $segment)
            {
                $explode_segment = explode('/', $segment);
                $_GET[$explode_segment[0]] = strpos(urldecode($explode_segment[1]), 'multi-') !== FALSE ? explode("|", str_replace("multi-", "", urldecode($explode_segment[1]))) : urldecode($explode_segment[1]);
                $_REQUEST[$explode_segment[0]] = strpos(urldecode($explode_segment[1]), 'multi-') !== FALSE ? explode("|", str_replace("multi-", "", urldecode($explode_segment[1]))) : urldecode($explode_segment[1]);
            }
        }
    }
}

After adding the above we recommend that you to navigate to ‘Settings > Permalinks’ and just hit ‘Save changes’ to flush the internal rewrite rules of WordPress.

Note that with this snippet in place, the Radial Search add on will not function due to the order in which WordPress hooks fire. We are currently investigating a resolution to this.