avatar Deluxe Blog Tips About Projects

Using relative URLs in WordPress

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

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' ) ) {

    $filters = [
    foreach ( $filters as $filter ) {
        add_filter( $filter, 'wp_make_link_relative' );

🔥 HOT: Interested in boosting your WordPress SEO? My Slim SEO plugin is a super lighweight and automated plugin that handles most the hard work for you: meta tags, sitemap, redirection, schema & link building.

👉 Have a look and you will love it: wpslimseo.com