Redirect Missing Pages to the Nearest Parent Page
When an address like /services/old-offer/ no longer exists, sends visitors to the closest existing level above it, such as /services/, instead of a dead end.
Opens WPIDE on
Code
// Status code: 301 (permanent) or 302 (temporary).
$wpide_parent_redirect_status = 301;
add_action( 'template_redirect', function () use ( $wpide_parent_redirect_status ) {
if ( ! is_404() || ! get_option( 'permalink_structure' ) ) {
return;
}
$path = isset( $_SERVER['REQUEST_URI'] ) ? (string) wp_parse_url( wp_unslash( $_SERVER['REQUEST_URI'] ), PHP_URL_PATH ) : '';
$base = untrailingslashit( (string) wp_parse_url( home_url(), PHP_URL_PATH ) );
$path = trim( substr( $path, strlen( $base ) ), '/' );
// Skip missing files such as images and scripts, and very deep or empty paths.
if ( '' === $path || preg_match( '/\.[a-z0-9]{2,5}$/i', $path ) || substr_count( $path, '/' ) > 6 ) {
return;
}
$parts = explode( '/', $path );
while ( count( $parts ) > 1 ) {
array_pop( $parts );
$url = home_url( user_trailingslashit( implode( '/', $parts ) ) );
if ( url_to_postid( $url ) || get_page_by_path( implode( '/', $parts ) ) ) {
wp_safe_redirect( $url, (int) $wpide_parent_redirect_status );
exit;
}
$term = get_term_by( 'slug', end( $parts ), 'category' );
if ( $term && untrailingslashit( get_term_link( $term ) ) === untrailingslashit( $url ) ) {
wp_safe_redirect( $url, (int) $wpide_parent_redirect_status );
exit;
}
}
} );
Notes
Needs pretty permalinks; missing files such as images are skipped. Set the status to 302 while you test.
How to add this snippet
- Install WPIDE on your WordPress site (it is free) and open Code Snippets.
- Use snippet above adds it from the library in one click. Or copy the code into a new snippet with the same code type.
- It is added inactive: review the code and settings, then switch it on.