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 & restore plugin like BackupBuddy, or using 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.

Note: The topic of relative URLs in WordPress is not new, some people discussed in WP.org forum, and there’s also a solution. What I’m trying to do in this post is making a better, more completed solution.

Remove protocol and domain from absolute URLs

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. The function is in /wp-includes/formatting.php file. 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 relative URLs

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 = array(
    '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

(Updated on 12/06/2012)

After making this technique live on Deluxe Blog Tips, I found some problems:

  • The URLs in feed are relative, which is not expected. This was reported by Jared.
  • If you’re using WordPress SEO plugin by Yoast, the URLs in sitemap are relative, too, which causes some problems in Google Webmaster Tool.

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 = array(
        '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' );
    }
}

I’m using relative URLs in Deluxe Blog Tips, and will update this post if I found any bugs.

Subscribe to the Newsletter

Subscribe to get my latest content by email. I won't send you spam. Unsubscribe at any time.