WordPress is wonderful. I think we can all agree it's not only an awesome blogging platform, but an immensely powerful open-source CMS. There are a lot of things that WordPress does really well out of the box, but every once in a while you run into something more complicated.

This happened to me recently when working on a site redesign for my company. We wanted to show all open job listings at a specific URL, for example: bozo.com/careers. On this page we gave visitors the option to filter job results by location and by department. This would make it easy for prospects to search for Developer positions in our San Francisco office, or Design positions in our Bangalore office. Without giving it much thought, I created two custom taxonomies location and department, added them to my careers custom post-type and went on my way. After getting well into building this portion of the site I realized I had missed something. We needed to have a specific URL for each possible outcome, so that HR could send a potential prospect a list of open positions relevant to them. How could we make this work?

On the one hand, it would be possible to use a URL structure like bozo.com/careers/department/design. But then what if we only wanted to show design openings in a specific office? How about bozo.com/careers/department/design/san-francisco? Not so great. It could just as easily be bozo.com/careers/locations/san-francisco/design.

This is where query vars come in handy.

A much better option for this sort of thing would be to send potential prospects to a URL like bozo.com/careers/?location=san-francisco&department=design. It's very clear what you're going to get, and we can get away with only one page template for all of the results.

Getting down to business

1. Adding your custom query vars

The first thing we'll need to do is to add our custom query vars to the list of public query variables available to WP_Query. In your functions.php file:

  function custom_query_vars_filter($vars) {
  $vars[] .= 'location';
  $vars[] .= 'department';
  return $vars;
add_filter( 'query_vars', 'custom_query_vars_filter' );

2. Creating the URLs

Now that you've made you custom query vars available to WP_Query, you can start using them. Wordpress has a helpful function for this called add_query_arg. You can read more up on it here.

In short, you pass the function an associative array of the query variables and their value, as well as the URL that you want to append your query vars to.

For example, let's say we want to link to the careers page and filter by jobs that are in San Francisco and in the Design Department with the URL bozo.com/careers/?location=san-francisco&department=design. To generate the link we can use something like this:

    // an associative array containing the query var and its value
    $params = array('location' => 'san-francisco', 'department' => 'design');
    <!-- pass in the $params array and the URL -->
    <a href="<?php echo add_query_arg($params, '/careers'); ?>">My Link</a>

3. Use 'Dat Data

Ok, so you've got a fancy looking URL. Now what? In my example, I've created a page in the wordpress admin panel called 'careers'. Even though the URL has query args on the end, it still knows to use the page template that I specified when I created the careers page. So in my template for the careers page I can use the URL query vars like so:

    $location = get_query_var('location');
  $department = get_query_var('department');

Then, I can go about my business of displaying the appropriate job listings by checking the value of these variables and using them in a WP_Query.

For example, if I wanted to display only job listings in the location San Francisco in the department Development with a custom post type of careers:

  $args = array(
'post-type' => 'careers',
'tax_query' => array(
    'relation'  => 'AND',
    'taxonomy'  => 'location',
    'field'         => 'slug',
    'terms'         => $location,
    'taxonomy'  => 'departments',
    'field'         => 'slug',
    'terms'         => $department,

I hope this helps someone out there, let me know if you have questions or if I've left something out.