I'm new to writing rewrite rules in WordPress and I want to make sure I'm not going about this the wrong way.

My goal: to use random numbers and letters as the URL ending for my custom post type project pages

My code below is what I've attempted so far ...


// Create a random string and save it to the post for the URL ending
function add_url_id( $id, $post ){
  $url_id = uniqid();

  if ( isset( $post->url_id ) ) {
update_post_meta($id, 'url_id', $url_id );

// Let WordPress know about my custom query variable url_id
add_filter( 'query_vars', 'add_query_var' );
function add_query_var( $vars )
  $vars[] = 'url_id';
  return $vars;

// My rewrite rule to search for the custom post with the URL's same url_id
add_action('init', 'custom_rewrite_rule', 10, 0);    
function custom_rewrite_rule() {

When I var_dump my post on the individual custom post pages, I can see that they do have a value in their url_id field. When I save this code and flush the permalinks cache, I find that I'm redirected to http://example.com/projects/<string of numbers and letters>, but I only see the homepage instead of the custom post. I'm guessing the issue has to do with no results being returned by my url_id variable, but I'm not sure why my query doesn't have any result since I do have posts with this field populated.


This is what I'm currently seeing in the Rewrite Analyzer plugin rewrite results

I'm also not finding that my URLs are being re-written at all at the moment, so I am not as far along as I had expected.

  • Your url_id may be a query variable now, but there's no logic attached to it. Those variables are passed into WP_Query, which doesn't have a url_id parameter. I take it this is a post meta field? ( a custom field? ) Where's the implementation of uniqid and how does it map on to posts?
    – Tom J Nowell
    Apr 11, 2017 at 19:21
  • @TomJNowell thanks for taking a look. url_id is a custom field, but it is only created/updated in the function I've included above (does it need some setup elsewhere as well?). uniqid() is a build in PHP function to generate the random string I'm looking for.
    – ktbee
    Apr 11, 2017 at 19:28
  • I would keep in mind then that this will involve a meta query, which are super expensive and do not scale. You will need to put that meta query inside the URL in your rewrite rules
    – Tom J Nowell
    Apr 11, 2017 at 19:34

2 Answers 2


You should use 'post_type_link' hook
and register post type 'project' with ('with_front' => true) parameters

 'rewrite' => array('slug' => $slug, "with_front" => true),   


add_rewrite_rule('^project/([0-9a-z]+)/?$', 'index.php?project=$matches[1]', 'top');


  function post_type_link_hook($link, $post) {
    if ('projects' == get_post_type($post)) {
        $urlId = get_post_meta($post->ID, 'url_id', true);

        //Lets go to get the parent cartoon-series name
        return str_replace('%url_id%', $urlId, $link);
    return $link;
 add_filter('post_type_link', 'post_type_link_hook', 10, 2);
  • Thank you for your suggestion! I ended up taking a different approach on this (see my posted answer), but I appreciate your example of how to incorporate the meta post query.
    – ktbee
    Apr 13, 2017 at 19:07

I've ended up taking another route based on Tom J Nowell's feedback that I would need an expensive meta query as part of my rewrite rules. I ended up changing the post's slug itself, which allows me to use WordPress's default functionality without any complicate rewrite rules. This is my code:

add_action('wp_insert_post_data','add_url_id', 50, 2);
function add_url_id( $post_data ){
  // Only set the random slug once and only for published posts
  $original_slug = sanitize_title( $post_data['post_title'] );
  if ( $post_data['post_name'] != $original_slug || $post_data['post_status'] != 'publish' ) {

  // Generate random string
  $caps_letters = '';
  $caps_letters_len = 6;
  for ($i = 0; $i < $caps_letters_len; $i++) {
    $caps_letters .= chr( rand(65, 90) );

  $numbers_and_lowercase = uniqid();
  $slug_length = strlen($caps_letters) + strlen($numbers_and_lowercase);
  $random_slug = '';
  for ($i = 0; $i < $slug_length; $i++) {
    if ( $i % 2 == 0 ) {
      $random_slug .= $numbers_and_lowercase[0];
      $numbers_and_lowercase = substr($numbers_and_lowercase, 1);
    } else {
      $random_slug .= $caps_letters[0];
      $caps_letters = substr($caps_letters, 1);

  $post_data['post_name'] = $random_slug;
  return $post_data;

Thank you everyone for your help on this! Now my posts have random URL endings, which was my original goal.

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.