Relative URLs has some benefits: smaller page size (and thus download time) and making the site more portable when you move to another domain. The 2nd problem often happens and it can make your post links broken. Although it can be solved using some backup plugins, or using Better Search and Replace plugin, we better avoid it before it happens. This post will show you how to make your WordPress site support relative URLs.
Making a URL relative
Basically, we think about a string replacement: replace home_url()
by /
from absolute URLs, and we can write a simple function like this:
function rw_remove_root( $url ) {
$url = str_replace( home_url(), '', $url );
return '/' . ltrim( $url, '/' );
}
But do you know that WordPress has a built-in function for this purpose? It's wp_make_link_relative
. Here it is:
function wp_make_link_relative( $link ) {
return preg_replace( '|https?://[^/]+(/.*)|i', '$1', $link );
}
Pretty simple. What it does is removing protocol and domain name from the absolute URLs (without using home_url
).
Making WordPress URLs relative
Now what we have to do is apply this function to post, category, term, archive, ... links. Fortunately, WordPress always uses filters in getting URL functions. All of them are in wp-includes/link-template.php
and wp-includes/taxonomy.php
files. So, we'll add wp_make_link_relative
filter to those functions. Here's the the code that you can put in functions.php
file of your theme or in your plugin:
add_filter( 'post_link', 'wp_make_link_relative' ); // Normal post link
add_filter( 'post_type_link', 'wp_make_link_relative' ); // Custom post type link
add_filter( 'page_link', 'wp_make_link_relative' ); // Page link
add_filter( 'attachment_link', 'wp_make_link_relative' ); // Attachment link
add_filter( 'get_shortlink', 'wp_make_link_relative' ); // Shortlink
add_filter( 'get_pagenum_link', 'wp_make_link_relative' ); // Paginated link
add_filter( 'get_comments_pagenum_link', 'wp_make_link_relative' ); // Paginated comment link
add_filter( 'term_link', 'wp_make_link_relative' ); // Term link, including category, tag
add_filter( 'search_link', 'wp_make_link_relative' ); // Search link
add_filter( 'post_type_archive_link', 'wp_make_link_relative' ); // Post type archive link
// Date archive link
add_filter( 'day_link', 'wp_make_link_relative' );
add_filter( 'month_link', 'wp_make_link_relative' );
add_filter( 'year_link', 'wp_make_link_relative' );
Or better code with simple improvements:
$filters = [
'post_link', // Normal post link
'post_type_link', // Custom post type link
'page_link', // Page link
'attachment_link', // Attachment link
'get_shortlink', // Shortlink
'post_type_archive_link', // Post type archive link
'get_pagenum_link', // Paginated link
'get_comments_pagenum_link', // Paginated comment link
'term_link', // Term link, including category, tag
'search_link', // Search link
'day_link', // Date archive link
'month_link',
'year_link',
];
foreach ( $filters as $filter ) {
add_filter( $filter, 'wp_make_link_relative' );
}
After doing that, whenever you show a link in a theme template file, for ex. using the_permalink
function, the corresponding filters will be applied (in this case: post_link
), including our wp_make_link_relative
function. That means all URLs in your WordPress site will be changed relative URLs automatically without touching to template files. Enjoy relative URLs!
Relative URLs in feed or sitemap
However, making all links relative has some problems:
- The URLs in feed are relative, which is not expected.
- If you're using Yoast SEO plugin (which I'd not recommend), the URLs in sitemap are relative, too, which causes some problems in Google Search Console.
So, I update the code to make the filters are applied only when we need. I might miss some cases when it doesn't work, and hope to hear your feedback:
add_action( 'template_redirect', 'rw_relative_urls' );
function rw_relative_urls() {
// Don't do anything if:
// - In feed
// - In sitemap by WordPress SEO plugin
if ( is_feed() || get_query_var( 'sitemap' ) ) {
return;
}
$filters = [
'post_link',
'post_type_link',
'page_link',
'attachment_link',
'get_shortlink',
'post_type_archive_link',
'get_pagenum_link',
'get_comments_pagenum_link',
'term_link',
'search_link',
'day_link',
'month_link',
'year_link',
];
foreach ( $filters as $filter ) {
add_filter( $filter, 'wp_make_link_relative' );
}
}
Leave a Reply