When no permalink plugin is used, WordPress uses its built-in rewrite rules to manage URL structures. This system is not highly customizable, yet you can use the available hooks to programmatically modify and manage them.
This article focuses on slugs, which define the dynamic part of the URLs. When you publish a new post or page, WordPress generates them dynamically. Typically, the slugs are created from the initial title and converted to make it more readable for search engines and people.
Automating Permalink Updates
Even though WordPress does not have any out-of-box functionality that would allow o automatically update permalinks, you can make it happen with an extra code snippet.
When updating permalinks programmatically in WordPress, the most convenient way is to use the wp_update_post() function.
wp_update_post( array( 'ID' => $post_id, 'post_name' => $new_slug ) );
This core function is designed to update post data, including the post's slug (permalink). You can also use the $wpdb global to run a SQL update query, but this will not trigger any WordPress hooks or filters that would let plugins and themes react to the change.
Below you can find a few snippets that you may use to update the slug or execute extra code when certain post-update conditions are met. These code snippets are basic examples intended to illustrate how permalink updates can be automated.
Please feel free to modify and expand them as needed. Ask an expert WordPress developer for help if you are uncomfortable with PHP, especially while working on a live website.
Changed Post Title
function pm_update_slug_on_title_change( $post_id, $post_after, $post_before ) {
	$post = get_post( $post_id );
	if ( $post_after->post_type == 'post' && $post_after->post_title !== $post_before->post_title ) {
		$new_slug = sanitize_title( $post_after->post_title );
		wp_update_post( array(
			'ID' => $post_id,
			'post_name' => $new_slug
		) );
	}
}
add_action( 'post_updated', 'pm_update_slug_on_title_change', 9, 3 );
Changed Assigned Category
function pm_update_slug_on_term_change( $post_id, $terms, $tt_ids, $taxonomy ) {
	if ( $taxonomy == 'category' ) {
		$new_slug = sanitize_title( $post_after->post_title );
		wp_update_post( array(
			'ID' => $post_id,
			'post_name' => $new_slug
		) );
	}
}
}
add_action( 'set_object_terms', 'pm_update_slug_on_term_change', 9, 4 );
Changed Custom Field Value
function pm_update_slug_on_custom_field_change( $meta_id, $post_id, $meta_key, $meta_value ) {
	if ( $meta_key == 'sample-custom-field' ) {
		$new_slug = sanitize_title( $post_after->post_title );
		wp_update_post( array(
			'ID' => $post_id,
			'post_name' => $new_slug
		) );
	}
}
}
add_action( 'updated_postmeta', 'pm_update_slug_on_custom_field_change', 9, 4 );
Handling 404 Errors After Permalink Changes
Changing permalinks, especially for pages that rank high in search results or receive significant organic traffic, can be risky. Broken links returning "404" errors can negatively affect user experience and SEO.
There are exceptions where updating permalinks can be useful but do not change indexed permalinks unless necessary. If changes are required, make sure that the old URL redirects correctly to the new one.
WordPress includes a canonical redirect feature to handle this, but it is important to verify that it works as expected.
Built-in Fallback Redirect
The most straightforward solution is WordPress' built-in mechanism (wp_old_slug_redirect() function), which monitors slug changes and automatically redirects old URLs to new URLs.
This solution is very basic, but it usually works well enough. When a post's slug changes, WordPress saves the previous slug in the wp_postmeta database table (using the meta key "_wp_old_slug").
When a visitor attempts to access a URL that does not exist, WordPress extracts the slug and looks for a matching "_wp_old_slug" item. If a match is identified, WordPress redirects the visitor to the updated URL.
This functionality is built into WordPress and does not require any further configuration. Unfortunately, it is not perfect. One of the biggest problems is that it only detect the most recent slug's change.
In other words, if a post's slug has been changed multiple times, only the most recent old slug will redirect. Furthermore, it doesn't handle changes to other parts of the URL structure, such as changes in linked categories' slugs.
Leave a Reply