2

I have a custom post type containing job listings, that is highly volatile. Jobs are frequently added and removed. Our analytics show that a lot of crawling errors are for detail pages of jobs that have been unlisted.

The solution I came up with is to redirect all visits for non-existant URLs within the CPT's slug to the job listing overview, and I would like to automate this.

How would I go about this? I'm looking for a solution that does this very early and skips as much unnecessary calls as possible. (i.e. something earlier than doing this in header.php, ideally as an action)

Example:

  • mydomain.com/jobs/existingjob/ delivers the detail page for the job
  • mydomain.com/jobs/nojobhere/ does not exist and would throw a 404 but instead gets redirected to mydomain.com/jobs/

3 Answers 3

4

It looks like template_redirect is as far up the WordPress action chain you can go while still being able to detect that a 404 error is being thrown. This action will trigger before any template files would be loaded so it will happen before loading unnecessary resources.

You can try adding this into your /wp-content/themes/yourtheme/functions.php file to achieve a dynamic redirect for all 404's that happen when viewing single jobs:

add_action( 'template_redirect', 'unlisted_jobs_redirect' );
function unlisted_jobs_redirect()
{
    // check if is a 404 error, and it's on your jobs custom post type
    if( is_404() && is_singular('your-job-custom-post-type') )
    {
        // then redirect to yourdomain.com/jobs/
        wp_redirect( home_url( '/jobs/' ) );
        exit();
    }
}
6
  • This helps me. template_redirect seems like the right place. is_singular('your-job-custom-post-type') doesn't seem to work here, get_post_type() is false, presumably since the query doesn't point to any actual content. I think I'm going to use parse_url() and check the beginning of the path.
    – Alina_0xFF
    May 31, 2017 at 11:52
  • is_singular('your-job-custom-post-type') should work if the post type is named properly(do change the text 'your-job-custom-post-type' to match your post types name). At the template_redirect point WordPress has run the main query, and objects have been instantiated, it just hasn't loaded any template files yet. Perhaps it needs global $post; declared at the beginning of the unlisted_jobs_redirect function? I didn't set up a test for this. May 31, 2017 at 11:58
  • codex.wordpress.org/Plugin_API/Action_Reference/… The Codex example uses the is_page() conditional without global $post; being declared, so I think get_post_type() is false because your custom post type name is mistyped in is_singular. May 31, 2017 at 12:06
  • if I var_dump(get_post_type()) inside unlisted_jobs_redirect() I only get string(4) "jobs" for valid URLs, but bool(false) if I as much as change the last character, so I'm pretty sure is_singular('jobs') can't be true, or am I mistaken? My solution now uses this condition instead: if(is_404() && substr($_SERVER['REQUEST_URI'], 0, strlen($slug)) === $slug)
    – Alina_0xFF
    May 31, 2017 at 12:11
  • I misunderstood your get_post_type reference, but from what you say get_post_type is saying you're at the "jobs" post type, and I would presume is_singular('jobs') would return true in this case. That being said, if your new conditional is working go for it! May 31, 2017 at 12:16
1

I don't have the rep to comment on Ben HartLenn's answer, and I know this is an old post, but to save future users from wasting time: is_singular('post_type') will not work on a 404 page. $wp_query->queried_object will also not work.

This does work:

add_action( 'template_redirect', 'unlisted_jobs_redirect' );
function unlisted_jobs_redirect(){
    //check for 404
    if( is_404()){
        global $wp_query;
        //check that wp has figured out post_type from the request
        //and it's the type you're looking for
        if( isset($wp_query->query['post_type']) && $wp_query->query['post_type'] == 'your-job-custom-post-type' ){
        // then redirect to yourdomain.com/jobs/
        wp_redirect( home_url( '/jobs/' ) );
        exit();
    }
}
1
  • Thanks. This did the trick for me. Aug 8, 2021 at 19:18
0

If there is no page on your site with that post type, you need to ask yourself the question: should I really be deleting that page? Or should I just make it better? If you decide to make sure you send the proper HTTP header: a 410 content deleted header.

404 and 410 HTTP headers The difference between a 404 and a 410 header is simple: 404 means “content not found”, 410 means “content deleted” and is thus more specific. If a URL returns a 410, Google is far more certain you removed the URL on purpose and it should thus remove that URL from its index. This means it will do so much quicker.

You can use Yoast SEO Premium plugin, the redirects module in this plugin is capable of serving 410 headers.

1
  • The content that gets deleted are job listings that are no longer needed. Returning a 410 header is a good idea but i'm looking for a solution which is easy for my client as well, who is the one posting and removing job listings. Is there an easy way to find out if a URL belongs to a now-deleted post instead of a post that never existed?
    – Alina_0xFF
    May 31, 2017 at 12:26

Your Answer

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

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