{"id":191154,"date":"2014-12-19T10:04:30","date_gmt":"2014-12-19T17:04:30","guid":{"rendered":"http:\/\/css-tricks.com\/?p=191154"},"modified":"2015-10-07T05:47:38","modified_gmt":"2015-10-07T12:47:38","slug":"redirect-web-page","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/redirect-web-page\/","title":{"rendered":"How to Redirect a Web Page"},"content":{"rendered":"

A redirect is when a web page is visited at a certain URL, it changes to a different URL. For instance, a person visits “website.com\/page-a” in their browser and they are redirected<\/em> to “website.com\/page-b” instead. This is very useful if we want to redirect a certain page to a new location, change the URL structure of a site, remove the “www.” portion of the URL, or even redirect users to another website entirely (just to name a few).<\/p>\n

Let’s say we’ve just moved our website and we want to shut down the old one. However we don’t want all those pages from the old site to give a dreaded 404 Not Found<\/b>. What we need is for those old links to redirect to the same content on our new site.<\/p>\n

Here’s our example: we want old-website.com\/blog\/post<\/code> to redirect to new-website.com\/blog\/post<\/code>, along with all the other posts that use that same URL format. Also it would be nice if our redirects would report to search engines that this change is permanent so they should update accordingly.<\/p>\n

So how do we that? Well, before we start we need to learn a little about HTTP.<\/p>\n

HTTP response codes<\/h3>\n

Every time we enter a URL or make a request from a browser we’re using the Hypertext Transfer Protocol<\/em> (HTTP). Although this sounds like a really cool name for a sci-fi cop movie it’s actually the process by which we request assets such as CSS, HTML and images from a server. After we’ve sent a request these assets will then give a response like “hey I’m here, let’s go!” (response code HTTP 200 OK<\/code>). There are many different kinds of HTTP response code, the most familiar perhaps being 404 Not Found<\/b>; web pages can respond with a 404 status but so can any other asset that we request, whether that’s an image or any other kind of asset.<\/p>\n

Every HTTP response is categorized under a certain three digit number, so 404 Not Found<\/b> is a 4XX status code to clarify that it’s a client error and 200 is in the 2XX category to signify that it’s a success message of some kind. We’re interested in the 3XX category of HTTP response, like 301 Moved Permanently<\/b> or 302 Found<\/b>, because these are the status codes specifically set aside for redirects. Depending on the method we choose we won’t necessarily need to know about these codes but it’s essential for others.<\/p>\n

In our case we’ll use a 301 redirect because some web browsers or proxy servers will cache this type, making the old page inaccessible which, in this instance, is exactly what we want.<\/p>\n

So how do we actually go about redirecting a web page?<\/p>\n

HTML redirects<\/h3>\n

Perhaps the simplest way to redirect to another URL is with the Meta Refresh tag. We can place this meta tag inside the <head><\/code> at the top of any HTML page like this: <\/p>\n

<meta http-equiv=\"refresh\" content=\"0; URL='http:\/\/new-website.com'\" \/><\/code><\/pre>\n

The content<\/code> attribute is the delay before the browser redirects to the new page, so here we’ve set it to 0 seconds. Notice that we don’t need to set a HTTP status code, but it’s important to double check the weird opening and closing of the quotes above (there are quotes within quotes, so they need to be different types and matching).<\/p>\n

Although this method is the easiest way to redirect to a web page there are a few disadvantages. According to the W3C there are some browsers that freak out with the Meta refresh tag. Users might see a flash as page A is loaded before being redirected to page B. It also disables the back button on older browsers. It’s not an ideal solution, and it’s discouraged to use at all.<\/em> <\/p>\n

A safer option might be to redirect the website with JavaScript.<\/p>\n

JavaScript redirects<\/h3>\n

Redirecting to another URL with JavaScript is pretty easy, we simply have to change the location<\/code> property on the window<\/code> object:<\/p>\n

window.location = \"http:\/\/new-website.com\";<\/code><\/pre>\n

JavaScript is weird though, there are LOTS of ways to do this.<\/p>\n

window.location = \"http:\/\/new-website.com\";\r\nwindow.location.href = \"http:\/\/new-website.com\";\r\nwindow.location.assign(\"http:\/\/new-website.com\");\r\nwindow.location.replace(\"http:\/\/new-website.com\");<\/code><\/pre>\n

Not to mention you could just use location<\/code> since the window object is implied. Or self<\/code> or top<\/code>.<\/p>\n

With the location<\/code> object we can do a lot of other neat stuff too like reload the page or change the path and origin of the URL. <\/p>\n

There are a few problems here:<\/p>\n

    \n
  1. JavaScript needs to be enabled and downloaded\/executed for this to work at all.<\/li>\n
  2. It’s not clear how search engines react to this.<\/li>\n
  3. There are no status codes involved, so you can’t rely information about the redirect.<\/li>\n<\/ol>\n

    What we need is a server side solution to help us out by sending 301 responses to search engines and browsers.<\/p>\n

    Apache redirects<\/h3>\n

    Perhaps the most common method of redirecting a web page is through adding specific rules to a `.htaccess` on an Apache web server. We can then let the server deal with everything.<\/p>\n

    `.htaccess` is a document that gives us the ability to give orders to Apache, that bit of software that runs on the server. To redirect users to our new site we’ll make a new .htaccess file (or edit the existing one) and add it to the root directory of the old website. Here’s the rule we’ll add:<\/p>\n

    Redirect 301 \/ http:\/\/www.new-website.com<\/code><\/pre>\n

    Any page that the user visits on the old website will now be redirected to the new one. As you can see, we put the HTTP response code right at the front of the redirect rule.<\/p>\n

    It’s worth mentioning that this kind of redirect only works on Linux servers with the mod_rewrite<\/code> enabled, an Apache module which lets us redirect requested URLs on the server by checking a certain pattern and, if that pattern is found, it will modify the request in some way. Most hosting companies have this enabled by default, but contacting them is your best bet if there’s a problem. If you’re looking for more info on mod_rewrite then there’s a great tutorial<\/a> on tuts+. There are also lots of .htaccess snippets<\/a> here on CSS-Tricks.<\/p>\n

    Back to our example, if we use the code above then a user will go to “old-website.com\/blog\/post” and be sent to “new-website.com” which isn’t very user friendly because they won’t see actual page they asked for. Instead, we’ll add the following rule to our `.htaccess` file in order to redirect all those blog posts to the right place:<\/p>\n

    RedirectMatch 301 \/blog(.*) http:\/\/www.new-website.com$1<\/code><\/pre>\n

    Or perhaps we want to redirect individual pages very specifically. We can add the rules like this: <\/p>\n

    Redirect 301 \/page.html http:\/\/www.old-website\/new-page.html<\/code><\/pre>\n

    And for errors we can redirect users to our 404 page (probably chock full of puns and gifs):<\/p>\n

    <IfModule mod_rewrite.c>\r\n  RewriteEngine on\r\n  RewriteCond %{REQUEST_FILENAME} !-f\r\n  RewriteCond %{REQUEST_FILENAME} !-d\r\n  RewriteRule .* 404.html [L]\r\n<\/IfModule><\/code><\/pre>\n

    First we check if we have the mod_rewrite<\/code> module is available then we can turn it on and, if the file or directory is not found, we send the user off to our 404 page. It’s sort of neat that the contents of the page they see will be from the 404.html<\/code> file whilst the requested URL will remain the same.<\/p>\n

    If you’re not comfortable with messing around with `.htaccess` files and you have WordPress installed then there’s a nifty extension<\/a> that can deal with this stuff for us.<\/p>\n

    Nginx redirects<\/h3>\n

    If your server is running Nginx<\/a> as the web server, then in the `nginx.conf` file you can add a server block to handle these redirect requests: <\/p>\n

    server {\r\n  listen 80;\r\n  server_name old-website.com;\r\n  return 301 $scheme:\/\/new-website.com$request_uri;\r\n}<\/code><\/pre>\n

    Again we’re using the 301 HTTP response and, with the scheme<\/code> variable, we’ll request http:\/\/<\/code> or https:\/\/<\/code> depending on what the original website used. It might be a good idea to take a closer look at the HTML5 Boilerplate nginx.conf<\/a> for best practices on other Nginx related things.<\/p>\n

    Lighttpd redirects<\/h3>\n

    For those servers running a Lighttpd<\/a> web server, you make a redirect by first importing the mod_redirect<\/code> module and using url.redirect<\/code>:<\/p>\n

    server.modules  = (\r\n  \"mod_redirect\"\r\n)\r\n\r\n$HTTP[\"host\"] =~ \"^(www\\.)?old-website.com$\" {\r\n  url.redirect = (\r\n    \"^\/(.*)$\" => \"http:\/\/www.new-website.com\/$1\",\r\n  )\r\n}<\/code><\/pre>\n

    PHP redirects<\/h3>\n

    With PHP we can use the header function<\/a>, which is quite straightforward:<\/p>\n

    <?php \r\n  header('Location: http:\/\/www.new-website.com');\r\n  exit;\r\n?><\/code><\/pre>\n

    This has to be set before any markup or content of any other sort, however there is one small hitch. By default the function sends a 302 redirect response which tells everyone that the content has only been moved temporarily. Considering our specific use case we’ll need to permanently move the files over to our new website, so we’ll have to make a 301 redirect instead:<\/p>\n

    <?php\r\n  header('Location: http:\/\/www.new-website.com\/', true, 301);\r\n  exit();\r\n?><\/code><\/pre>\n

    The optional true<\/code> parameter above will replace a previously set header and the 301 at the end is what changes the response code to the right one.<\/p>\n

    Ruby on Rails redirects<\/h3>\n

    From any controller in a Rails project<\/a>, we can quickly redirect to a new website with redirect_to<\/code> and the :status<\/code> option set to :moved_permanently<\/code>. That way we override the default 302 status code and replace it with Moved Permanently: <\/p>\n

    class WelcomeController < ApplicationController\r\n  def index\r\n    redirect_to 'http:\/\/new-website.com', :status => :moved_permanently \r\n  end\r\nend<\/code><\/pre>\n

    In Rails 4 there’s any easier way to handle these requests where we can add a redirect<\/code> in the routes.rb<\/code> file which automagically sends a 301 response:<\/p>\n

    get \"\/blog\" => redirect(\"http:\/\/new-website.com\")<\/code><\/pre>\n

    Or if we want to redirect every article on the blog to posts on the new website we can do so by replacing the above with the following: <\/p>\n

    get \"\/blog\/:post\" => redirect(\"http:\/\/new-website.com\/blog\/%{post}\")<\/code><\/pre>\n

    .NET redirects<\/h3>\n

    I’ve never written anything with the .NET framework before but it looks like there’s clear documentation<\/a> over on Microsoft’s Developer Network.<\/p>\n

    Node.js redirects<\/h3>\n

    Here’s a very quick local setup that explains how redirects work with Node. First we include the http<\/code> module and create a new server, followed by the .writeHead()<\/code> method:<\/p>\n

    var http = require(\"http\");\r\n\r\nhttp.createServer(function(req, res) {\r\n  res.writeHead(301,{Location: 'http:\/\/new-website.com'});\r\n  res.end();\r\n}).listen(8888);<\/code><\/pre>\n

    If you make a new file called index.js<\/code> and paste the code above and then run node index.js<\/code> in the command line you’ll find the local version of the website redirecting to new-website.com<\/code>. But to redirect all the posts in the \/blog<\/code> section we’ll need to parse the URL from the request with Node’s handy url<\/code> module:<\/p>\n

    var http = require(\"http\");\r\nvar url = require(\"url\");\r\n\r\nhttp.createServer(function(req, res) {\r\n  var pathname = url.parse(req.url).pathname;\r\n  res.writeHead(301,{Location: 'http:\/\/new-website.com\/' + pathname});\r\n  res.end();\r\n}).listen(8888);<\/code><\/pre>\n

    Using the .writeHead()<\/code> function we can then attach the pathname from the request to the end of URL string. Now it’ll redirect to the same path on our new site. Yay for JavaScript!<\/p>\n

    Flask redirects<\/h3>\n

    With the Flask<\/a> framework on top of Python<\/a> we can simply create a route that points to subpages with the redirect<\/code> function, again 301 has to be an option that is passed in at the end because the default is set to 302: <\/p>\n

    @app.route('\/notes\/<page>')\r\ndef thing(page):\r\n  return redirect(\"http:\/\/www.new-website.com\/blog\/\" + page, code=301)<\/code><\/pre>\n
    \n

    If you know of any other tricks to redirect a web page add a comment below and I’ll update this post with the latest info.<\/p>\n","protected":false},"excerpt":{"rendered":"

    A redirect is when a web page is visited at a certain URL, it changes to a different URL. For instance, a person visits “website.com\/page-a” in their browser and they are redirected to “website.com\/page-b” instead. This is very useful if we want to redirect a certain page to a new location, change the URL structure […]<\/p>\n","protected":false},"author":223806,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_bbp_topic_count":0,"_bbp_reply_count":0,"_bbp_total_topic_count":0,"_bbp_total_reply_count":0,"_bbp_voice_count":0,"_bbp_anonymous_reply_count":0,"_bbp_topic_count_hidden":0,"_bbp_reply_count_hidden":0,"_bbp_forum_subforum_count":0,"sig_custom_text":"","sig_image_type":"featured-image","sig_custom_image":0,"sig_is_disabled":false,"inline_featured_image":false,"c2c_always_allow_admin_comments":false,"footnotes":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":[]},"categories":[4],"tags":[],"jetpack_publicize_connections":[],"acf":[],"jetpack_featured_media_url":"","jetpack-related-posts":[{"id":185724,"url":"https:\/\/css-tricks.com\/intermediary-pages-site-heirarchy\/","url_meta":{"origin":191154,"position":0},"title":"Intermediary Pages in a Site Hierarchy","date":"October 8, 2014","format":false,"excerpt":"I had a reader write in with an interesting question: When one has multi-level navigation, do you think it crucial to have an actual page for the top-level item? For instance, About > Company, Founder, History. There isn't really anything worth putting on the About page that wouldn't be on\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":364070,"url":"https:\/\/css-tricks.com\/trailing-slashes-on-urls-contentious-or-settled\/","url_meta":{"origin":191154,"position":1},"title":"Trailing Slashes on URLs: Contentious or Settled?","date":"February 25, 2022","format":false,"excerpt":"A fun deep dive from Zach. Do you have an opinion on which you should use? 1) https:\/\/website.com\/foo\/ 2) https:\/\/websites.com\/foo The first option has a \"trailing slash.\" The second does not. I've always preferred this thinking: you use a trailing slash if that page has child pages (as in, it\u2026","rel":"","context":"In "Link"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2022\/02\/trailing-slash.jpg?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":377,"url":"https:\/\/css-tricks.com\/how-to-redirect-indexhtml-to-indexphp\/","url_meta":{"origin":191154,"position":2},"title":"How to Redirect index.html to index.php","date":"December 10, 2007","format":false,"excerpt":"Just this past week I finished up with a redesign project for a client and took the project live. Later on in the afternoon the day of the launch, the client called me: Client: I just clicked on our site and it's not working!! Me: Really? That's strange. The site\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":183076,"url":"https:\/\/css-tricks.com\/thoughts-pagination\/","url_meta":{"origin":191154,"position":3},"title":"Thoughts on Pagination","date":"September 29, 2014","format":false,"excerpt":"I've had some disparate thoughts regarding pagination lately, so I thought I'd attempt to organize them in a post. That's how blogging works right? Consistent Positioning If there is any way to make sure your pagination buttons don't move, do it. It's such a nice experience to be able to\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":307593,"url":"https:\/\/css-tricks.com\/how-to-redirect-a-search-form-to-a-site-scoped-google-search\/","url_meta":{"origin":191154,"position":4},"title":"How to Redirect a Search Form to a Site-Scoped Google Search","date":"April 28, 2020","format":false,"excerpt":"This is just a tiny little trick that might be helpful on a site where you don't have the time or desire to build out a really good on-site search solution. Google.com itself can perform searches scoped to one particular site. The trick is getting people there using that special\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2020\/04\/search-form-to-google.png?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":761,"url":"https:\/\/css-tricks.com\/redirecting-to-a-splash-page-but-only-once-with-cookies\/","url_meta":{"origin":191154,"position":5},"title":"Redirecting to a Splash Page ( …but only once! ) with Cookies","date":"May 13, 2008","format":false,"excerpt":"Splash pages can be annoying. You know the ones... like being forced to watch some advertisement before you can see the page you are trying to get to. Or maybe some fancy introduction to a site that you are automatically redirected to every time you visit. Great. There are some\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"featured_media_src_url":null,"_links":{"self":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/191154"}],"collection":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/users\/223806"}],"replies":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/comments?post=191154"}],"version-history":[{"count":7,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/191154\/revisions"}],"predecessor-version":[{"id":209345,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/191154\/revisions\/209345"}],"wp:attachment":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/media?parent=191154"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/categories?post=191154"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/tags?post=191154"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}