Why You Shouldn’t Code URLs in WordPress Themes or Plugins

When you're developing a theme or a plugin, you'll often find that you have to include a URL in your code. For example, in a plugin you might need a link to a stylesheet bundled with the plugin, while in a theme you'll probably want to code the site's URL in your header.

It might be tempting to simply code the URL in the same way as you might in a static site, but it's a bad idea. In this tutorial I'll explain why you shouldn't do this—and show you the functions you can use to create URLs dynamically.

Why You Shouldn't Code URLs in Your Themes and Plugins

Let's start with themes. If you're developing a theme for use on a specific site, it may not seem too harmful to add that site's domain in the theme files somewhere, but there are some definite risks and downsides:

  • If you ever decide to change the site's domain name, you'll have to edit all the URLs you've hard-coded.
  • If you're working on a development site which you'll be moving to a live server on launch, you'll have to change all the URLs you've hard-coded.
  • If you decide to use the theme on another site, you'll have to edit all those URLs.
  • If you decide to release the theme to the public or let other developers use it, it will break.
  • If you use the theme as the basis for another theme you develop for another site, you'll have to edit all the URLs.
  • If your site is in a subdirectory of your domain's root directory but you've told WordPress to use the root directory for the URL, your hard-coded URLs may point to the wrong place.
  • If you ever forget to do any of the above, your site will get 404 errors, and links to resources such as images and stylesheets won't work.

So don't do it!

But what about plugins? Well, this is even more risky. It's not uncommon to develop a theme just for one site, but most plugins will be used on multiple sites. It's unlikely that you'd ever hard-code a full URL into a plugin, but you might be tempted to use a function to fetch the site's URL and then code the path to the plugin directory. Again, this is risky:

  • If your plugin is moved to a different directory (such as the must use directory) then any links will break.
  • If your plugin is installed in a Multisite network running an older version of WordPress, your links could break.
  • If your plugin is installed in a site using a different directory structure to the one you've used for your URLs, again your links will break.

This could result in your plugin simply not working at all.

So, what do you do to avoid hard-coding URLs in WordPress?

Functions to Use Instead of Hard-Coded URLs

There are a variety of functions that you use to avoid hard-coding URLs in WordPress. I'm going to split them into five categories:

  • functions to retrieve the site's home page
  • functions to retrieve other front-end links (including posts, pages, attachments and archives)
  • functions to retrieve URLs for the admin screens
  • functions to retrieve URLs for files in your plugin and theme's directories
  • functions to retrieve stylesheets and scripts

Let's start with the functions to retrieve and output a link to the home page.

Fetching the Home Page URL

The following template tags will fetch or output the home page URL for your site:

  • bloginfo( 'url' ): displays the home URL as specified in your Reading settings in the admin.
  • get_bloginfo( 'url' ): fetches the site URL without displaying it.
  • home_url(): fetches the home page URL without displaying it: use echo esc_url( home_url( '/' ) ); to display the home URL with a trailing slash. This takes two optional parameters: $path if you want to add a path to a specific page or add a trailing slash, and $scheme to specify the scheme for the URL, such as http, https and relative.
  • get_home_url() retrieves the URL for the home page, and supports Multisite: you can include the blog ID as a parameter.
  • site_url(): the URL where WordPress is stored, so if your WordPress installation is in the wordpress subdirectory, this will retrieve the URL http://mysite.com/wordpress
  • get_site_url(): retrieves the site URL without outputting it. Can also be used with parameters to output the URL for a site in a Multisite network, add a path, and use a specific scheme.
  • network_home_url(): the home URL for the main site in a Multisite network, useful if you want to include a link to the main site in the footer of each site on the network, for example.
  • network_site_url(): the site URL for the main site in a Multisite Network.

As you can see, there a few different tags you can use to display the URL. Which you use will depend on a number of actors:

  • Do you want to just fetch the URL or display it?
  • Do you want to add a path after the home URL? (You can avoid this in some cases using the functions in the next section.)
  • Do you want to specify the scheme?
  • Do you want to fetch the home page URL or the site URL, if these are different?
  • Do you want to fetch the URL for a site in a Multisite network?

You should use one of these in your theme template files where you want to insert a link to the home page, for example if a logo in your site's head links to the home page. There might also be cases where a plugin will need to fetch or display the home page URL.

Fetching Other Front-End URLs

As well as the home page URL, there may be times when you want to code links to other pages in your site. This will include pages, posts, attachments, and custom post types. Here are the functions you should use:

  • post_permalink() outputs a link to a post, with the post ID as its parameter.
  • get_page_link() fetches (but does not output) the link to a page, with the page ID as a parameter.
  • get_permalink() fetches (but does not output) the permalink for a post or page, with the post or page ID as its parameter.
  • get_category_link() fetches the link to a category archive, with the category ID as its parameter.
  • get_tag_link() fetches the link to a tag's archive page, with the tag ID as its parameter.
  • get_post_type_archive_link() fetches the link to a post type's archive, with the post type as its parameter.
  • get_term_link() fetches the link to a taxonomy term, with the term and the taxonomy as its parameters.
  • the_attachment_link() outputs the link to an attachment, with the attachment ID as its first parameter. Use other parameters to define the image size and whether the link will lead to the file itself or its attachment page.
  • get_attachment_link() fetches the link for an attachment, with the attachment ID as the parameter.
  • wp_get_attachment_link() also fetches the link to an attachment, but additionally lets you display the image if the attachment is an image, at a size you specify.
  • get_search_link() retrieves the link to the search page. You can define a query as its parameter, or leave it blank, in which case it will use the current query.

Fetching Admin URLs

If you're creating a plugin or theme with settings screens in the WordPress admin, or you're customising the admin screens, you may want to add links to admin screens. Again, you shouldn't hard-code your URLs, but use one of these tags:

  • admin_url() fetches (but doesn't output) a URL in the admin. You need to include the path to the URL as a parameter and can also include the scheme if needed. So, for example, to output the URL for the screen to create a new post, you would use echo admin_url( 'post-new.php' );.
  • get_admin_url() is similar to admin_url() but supports Multisite networks: you can include the blog ID as a parameter.
  • edit_post_link() displays a link to the editing page for a post. It can be used in the loop or outside the loop with the post ID as a parameter.
  • get_edit_post_link() fetches the link to a post's editing screen, with the post ID as its parameter.

Retrieving Files in Your Plugin and Theme Folders

Just as when you're coding URLs in the front-end or admin screens, you should also code URLs and paths correctly when referring to files in your plugin or theme folders. 

First, here are the functions you should use in theme files:

  • get_stylesheet_directory() retrieves the full server path (not the URL) for the currently activated theme's directory. Use this to call include files rather than to output links.
  • get_stylesheet_directory_uri() retrieves the URL for the currently activated theme, without a trailing slash. Use it in template files to fetch resources stored in your theme folder: for example, to display an image stored in your theme's images folder, use <img src="<?php echo get_stylesheet_directory_uri(); ?>/images/logo.jpg">.
  • get_bloginfo( 'stylesheet_directory' ) retrieves the URL for the currently activated theme: using get_stylesheet_directory_uri() is neater.
  • get_template_directory_uri() is similar to get_stylesheet_directory_uri() but if you're using a child theme, it fetches the URL for the parent theme. Similarly, get_template_directory() works in the same way as get_stylesheet_directory() but for the parent theme.

There are also functions for use in plugin files:

  • plugins_url() fetches the absolute URL to the plugins directory (without a trailing slash). It takes two optional parameters: the path to add after the URL, and the plugin which you want the URL to be relative to.
  • plugin_dir_url() retrieves the URL for the directory a file is in (with a trailing slash), with that file as its parameter. Normally you would use __FILE__ as its parameter to denote the current file.

Here's an example of each of the above. Firstly, to retrieve the URL for a file in the current plugin's includes directory:

And to retrieve the same URL using plugin_dir_url():

Note that with the second example you have to echo out the path after the function: I prefer the first as it's neater. Don't forget that the second returns a trailing slash and the first doesn't.

Retrieving Stylesheets and Scripts

You should never hard-code links to stylesheets and scripts in your template files or plugins: instead use a function and attach it to the correct hook. This avoids problems with files being moved, ensures you're using the correct scripts without duplication, and is also more efficient.

To call a stylesheet, use wp_register_style() and wp_enqueue_style() in a function and hook it to the wp_enqueue_scripts hook. The function below would do this in a plugin:

Note that I've used __FILE__ above, which tells WordPress that the path to the stylesheet is relative to the current file.

Calling a script is similar, but uses wp_register_script() and wp_enqueue_script() in your function, and attaches those to the wp_enqueue_scripts hook. The example below registers a new script and calls it:

If your script uses a script bundled with WordPress, such as jQuery, you don't need to register it; just enqueue it as follows:

Read more about the wp_enqueue_scripts hook in this tutorial on including JavaScript and CSS in your themes and plugins.


Hopefully I've convinced you that hard-coding URLs in WordPress is a bad idea: it can lead to all sorts of problems in the future, and is less efficient. Depending on where you need to link to, WordPress provides a function to replace any hard-coded URL, in either your themes or plugins. You can use functions and template tags to link to pages in your site's front end, including the home page, to screens on the WordPress admin, and to files in your templates or plugins.



Related Articles