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.