I have a Wordpress site that is built to be a job listing board, and I'm looking to create SEO friendly URLs based on data that is stored in the database.

The URL structure should include the state abbreviation, city, and job title, and result in the following format: www.domain.com/job/ca/sacramento/janitor

There is currently a "Job" page in the backend that uses custom page template located at 'page-templages/job-template.php' that displays the database information at the following URL: www.domain.com/job/?2020-412341235134

How can I display the www.domain.com/job/?2020-412341235134 at the friendly virtual URL www.domain.com/job/ca/sacramento/janitor.

Here's how I'm accessing the database information in my current page template.

$job_title = $job[0]['job_title'];
$sanitized_job_title = str_replace(" ", "-", $job_title);
$bloginfo_url = get_bloginfo('url');
$friendly_url = $bloginfo_url . '/job/'. $job[0]['city'].'/'. $job[0]['state'] .'/'. $sanitized_job_title;

I've read through the add_rewrite_rule() documentation, and can't seem to get my head around it.

Any help would be greatly appreciated.

2 Answers 2


How can I display the www.domain.com/job/?2020-412341235134 at the friendly virtual URL www.domain.com/job/ca/sacramento/janitor

Well, you can't do that easily because the job ID in the first URL is not contained directly in the second URL, so you would have to do something complicated where you look up the job based on the parameters 'ca/sacramento/janitor' and this introduces a ton of complexity.

A simpler approach, which you'll see on many big websites is to include the ID and the SEO friendly stuff in the same URL, so that it's good for SEO but also very easy to work with in code because it has the ID. This also means that if e.g. the city the job is in changes, any links to the old URL with the old city will still work fine. In your previous approach if the city changed, then any URL's anywhere on the web with the old city would break unless you did some very complicated matching.

So I'd suggest you make your URL look like this:


And now all you need is a simple rewrite rule in Wordpress or direct in .htaccess to do that mapping. For quickness here's an .htaccess example, but you could probably also achieve this with add_rewrite_rule, you just would need to figure out how to map the URL parameters to an index.php page.

RewriteRule ^/job/[^/]+/[^/]+/[^-]*-(\d+-\d+)$ job/?$1 [L, NC]

So this says:

  • /job/ - match this specific string
  • [^/]+/ - two URL parameters that don't contain '/' but have an / on the end, so this will match up to /job/ca/sacramento/
  • [^-]+- - anything that doesn't include - with an - on the end, so this will match up to /job/ca/sacramento/janitor-
  • (\d+-\d+) - capture two strings of digits with `- in the middle

This htaccess rule is untested, but you can see the approach I'm suggesting here, and please reply here to work through bugs in this RewriteRule if you use it


  • The htaccess rule would need to go outside and above the WP rules in the root .htaccess
  • Similar approach could be used for a WP add_rewrite_rule, you just need to figure out the right index.php parameters.

One approach could be to create a rewrite rule that will catch the 3 variables and provide them as parameters that can be passed on to your job template. Assuming your template slug is "job":

function jobquery_rewrite_rule() {
add_action( 'init', 'jobquery_rewrite_rule' );

After inserting this action into your theme, you must refresh the permalink rule cache by visiting Settings > Permalinks for this new rewrite rule to take effect.

These creates 3 new GET parameters that you can now access in your job template, but first you need to allow them to be accessed using query_vars_filter to create safe variables from each of them:

add_filter( 'query_vars', 'add_query_vars_filter' );
function add_query_vars_filter( $vars ) {
  $vars[] = 'state';
  $vars[] = 'city';
  $vars[] = 'job';
  return $vars;

Without having your full custom post structure or meta fields, it would be kind of tough for me to write what the query is, but somehow in your job template you should be able to capture these GET vars into vars you need to build a 'reverse' wp_query to get your post content for that job:

$state_var = get_query_var('state');
$city_var = get_query_var('city');
$job_var = get_query_var('job');

//Use something like this to find the job based off the passed params
$args = array(
    'post_type'  => 'job',
    'meta_query' => array(
            'key'     => 'job_state',
            'value'   => $state_var,
            'key'     => 'job_city',
            'value'   => $city_var,
            'key'     => 'job_title',
            'value'   => $job_var,
$query = new WP_Query( $args );

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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