Fall Sale! Code FALL2024 takes 25% OFF our Pro Plugins & Books »
Web Dev + WordPress + Security

Temporary Site Redirect for Visitors during Site Updates

[ Image: Abstract Mathematical Diagram ] In our article Stupid htaccess Tricks, we present the htaccess code required for redirecting visitors temporarily during periods of site maintenance. Although the article provides everything needed to implement the temporary redirect, I think readers would benefit from a more thorough examination of the process — nothing too serious, just enough to get it right. After discussing temporary redirects via htaccess, I’ll also explain how to accomplish the same thing using only a small slice of PHP. It’s like two tutorials combined into one! ;)

Temporary Site Redirect via .htaccess

For those of us with access to Apache .htaccess, this is the best way to redirect visitors temporarily.

The Complete Code

Without a doubt, many visitors to this article will be looking for a quick copy-&-paste fix. So we begin by presenting the required htaccess code in its entirety:

<Limit GET POST PUT>
	Order deny,allow
	Deny from all
	Allow from 123.456.789
</LIMIT>
ErrorDocument 403 /custom-message.html
<Files custom-message.html>
	Order allow,deny
	Allow from all
</Files>

Three steps to use this code:

  1. Change the IP address (123.456.789) to that of your own.
  2. Edit both “custom-message.html” to match your path and file name.
  3. That’s it. Copy/paste into your site’s root htaccess file, upload, test, and get out!

The Break-Down

Let’s break it down. You want to update your site privately, temporarily redirecting all visitors to a nice “Be Right Back” page. Our code makes it happen via the following logic (translated to meatspeak):

  1. First deny access to everyone, then allow access only to the webmaster.
  2. Serve everyone without access a customized 403 (forbidden) error page.
  3. Allow everyone access to the customized 403 (forbidden) error page.
<Limit GET POST PUT>
In the first line of our temporary redirect code, we open a <Limit> container targeting all requests to get, post, or put files to and from the server.
order deny,allow
The second line then specifies the order in which the server should execute the proceeding directives. It basically says, “first obey the deny rule and then obey the allow rule.”
deny from all
The next line is the deny rule. It simply says, “deny everybody” (i get like this sometimes). At this point in the game, everyone is denied access.
allow from 123.456.789
Then, this line says, “allow access to only this address”. Thus, the net effect of the first five lines accomplishes the first step of our logical sequence.
</LIMIT>
The fifth line simply closes the <Limit> container block.
ErrorDocument 403 /custom.html
In the sixth line, we are specifying a custom error page. All visitors that are denied access to your site will receive some sort of 403 error page. By default, a user that is denied access will see a simple page that says something to the effect of “403 Forbidden — You do not have authorization to access the requested resource.” Yikes, remove the sixth line of our htaccess code and that is the type of message that visitors will receive. Not exactly encouraging. So, by specifying a customized 403 error page in our redirect code, we are able to serve a much warmer 403 biscuit, as if to say, “I am updating my site right now, but I still love you and want you to come back in like 30 minutes.” Much better..
<Files success.html>
After all that drama, the next line opens the <Files> container and exclusively targets our custom 403 error page. Note that if the custom page were to exist in subdirectory, we would want to cut and paste the last four lines into the htaccess file of that directory, and also edit the ErrorDocument path to reflect its location.
order allow,deny
Again, we are specifying the order in which Apache should process the allow/deny directives.
allow from all
This line then allows everyone access to the previously specified file. You know, the one with the inspiring message.
</Files>
Finally, we conclude our htaccess redirect by closing the <Files> container. Taken together, the last four lines are basically telling the server to ignore the previous “deny everybody” directive only for the customized error page. All other pages remain strictly off-limits (at least until the site is ready and the code is commented out or removed).

The Wrap-Up

There you have it. To use this code during your next site update, prepare your customized 403 document and upload to your server. Edit the two variables mentioned in the first part of this article, copy and paste to your root htaccess file, and upload to your server. Remember to check that everything has been done properly by using a proxy to test the redirect. Once everything is up and running tough, go ahead update your site in relaxed fashion, knowing full-well that you are keeping your loyal visitors in the loop instead of scaring them away into the night.

Temporary Site Redirect via PHP

If redirecting via .htaccess is not an option, you can always do the job with a little PHP. Here are three possible ways of going about it..

Option One — Quick and Dirty

This is the easiest way to inform your visitors that the site is temporarily unavailable. Especially useful for quick site updates, this code will return a “503 Service Unavailable” HTTP status code to the client device while displaying a customized message informing visitors that a site update is in progress. Simply edit the following code with your specific information and place at the very beginning of your header.php file:

<?php $my_ip = "123.456.789";
if($_SERVER["REMOTE_ADDR"] != $my_ip && $_SERVER["HTTP_X_FORWARDED_FOR"] != $my_ip) {
   $retry = 60 * 60; // = 60 minutes
   header("HTTP/1.1 503 Service Unavailable");
   header("Retry-After: $retry");
   echo "<h1>Site update in progress - Please return in 60 minutes!</h1>";
   exit();
} ?>

Here are the items you should customize for the previous code to function properly:

  • $my_ip = "123.456.789" → your IP address
  • $retry = 60 * 60; → seconds until client should revisit your site
  • <h1>Site update..</h1> → your custom message to visitors

Option Two — Full Meal Deal

This method is more flexible in that it provides a temporary redirect to an alternate location. This is useful when you would like to send your visitors to a completely customized maintenance page or to a preexisting page on a different domain. As before, this method also delivers a “503 Service Unavailable” HTTP status code to the client and instructs a revisit after the specified period of time. To throw it down, first edit the next code block and place at the top of your header.php file:

<?php $my_ip = "123.456.789";
if($_SERVER["REMOTE_ADDR"] != $my_ip && $_SERVER["HTTP_X_FORWARDED_FOR"] != $my_ip) {
	header("Location: http://domain.tld/path/custom.php");
} ?>

..then, edit and paste this code into the top of your customized maintenance page (e.g., custom.php):

<?php
   $retry = 60 * 60; // = 60 minutes
   header("HTTP/1.1 503 Service Unavailable");
   header("Retry-After: $retry");
?>

Here are the items you need to customize for the previous method to function properly:

  • $my_ip = "123.456.789" → your IP address
  • ("Location: http://..) → the URL of your custom maintenance page
  • $retry = 60 * 60; → seconds until client should revisit your site

Option Three — Combo Pack

Our third method for redirecting site visitors during updates and maintenance is somewhat of a hybrid of the first two methods. As before, we are redirecting visitors to an alternate location, only this time we are replacing the content of the target maintenance page with an informative message. This option provides yet another degree of flexibility by enabling you to redirect and replace content on the fly. To set it off, edit and drop this first code chunk into the top of your header.php file:

<?php $my_ip = "123.456.789";
if($_SERVER["REMOTE_ADDR"] != $my_ip && $_SERVER["HTTP_X_FORWARDED_FOR"] != $my_ip) {
	header("Location: http://domain.tld/path/custom.php");
} ?>

..and then edit and slap this bad boy at the beginning of your target page:

<?php
   $retry = 60 * 60; // = 60 minutes
   header("HTTP/1.1 503 Service Unavailable");
   header("Retry-After: $retry");
   echo "<h1>Site update in progress - Please return in 60 minutes!</h1>";
   exit();
?>

Here are the items you need to customize for the previous method to function properly:

  • $my_ip = "123.456.789" → your IP address
  • ("Location: http://..) → the URL of your custom maintenance page
  • $retry = 60 * 60; → seconds until client should revisit your site
  • <h1>Site update..</h1> → your custom message to visitors

Further reading

A Question to readers..

The attentive reader will have noticed the use of two different HTTP status codes in this article. For the htaccess redirect, we call upon the mighty powers of the “403 - Fabidden” code, while in the PHP methods we get tough with a few “503 - Service Unavailable” chillz. I chose to include both because I am undecided as to which method is optimal from an SEO point of view.

So, my question to you: which HTTP status code is the better choice, and for what reasons?

About the Author
Jeff Starr = Web Developer. Security Specialist. WordPress Buff.
WP Themes In Depth: Build and sell awesome WordPress themes.

27 responses to “Temporary Site Redirect for Visitors during Site Updates”

  1. I really enjoy your clear and easy-to-understand breakdown of whats going on with .htaccess, if only I could write like that!

    I published a few htaccess temporary redirect examples (404 link removed 2017/01/20) that you might want to check out!

  2. seriocomic 2007/12/28 2:38 pm

    This post absolutely rocks!

    As with your other .htaccess articles, others should take note on how to write helpful articulate posts.

  3. Perishable 2007/12/29 8:57 am

    Thanks for feedback, seriocomic — it is very encouraging! Also, I tried checking out your site in Firefox 2.0.0.11, but the page content disappeared from the browser after the page had loaded. The only items visible were the header and footer.. Just thought you should know. I would be more than happy to help troubleshoot this, just drop an email and we’ll knock it out.

  4. Here is a bit from Google webmaster blog re 503 http code: “If my site is down for maintenance, how can I tell Googlebot to come back later rather than to index the “down for maintenance” page?
    You should configure your server to return a status of 503 (network unavailable) rather than 200 (successful). That lets Googlebot know to try the pages again later.”

    From reading this I will use the 503 code. p.s. Your article is great. Many thanks

  5. Perishable 2008/02/26 6:16 pm

    Aha! Very good, Angus! Thanks for the information. I had been wondering about this for quite some time, and now see that my initial suspicions were correct. 503 it is then! — Cheers! ;)

  6. Yep, Angus is right. Returning a response code of 503 (Gateway timeout), will mean Googlebot will return soon.
    This means your Google positions shuld remain intact whilst you carry out your maintenance work.
    Great tut Perishable!

  7. Perishable 2008/05/25 6:35 am

    Thanks, Stuff! Good to get some confirmation on the 503 code. Thanks for the comment! :)

  8. And here is another method:

    #in your .htaccess file
    RewriteEngine On
    RewriteCond %{REMOTE_HOST} !123\.456\.789\.012
    RewriteCond %{REQUEST_URI} !^/offline\.html$
    RewriteRule .* /offline.html [R=301,L]

    Which will redirect all not from ip 123.456.789.012 to offline.html

  9. Perishable 2008/07/26 4:34 pm

    Thank you, Rune! :)

  10. I use your method for maintenance :

    --------------------------

    <Limit GET POST PUT>
       order deny,allow
       deny from all
       allow from 123.456.789
    </LIMIT>
    ErrorDocument 403 /custom-message.html
    <Files custom-message.html>
       order allow,deny
       allow from all
    </Files>

    --------------------------

    It’s working for redirect people, But for Admin (me), i got my web layout not work clearly , specialy for require & include function, anyone know why ?

    Thanx

  11. Jeff Starr 2008/09/01 9:19 am

    Borneo, What exactly is happening with the require and include functions? How are they being used, and are the included files located on the same server as the main page?

  12. Thanks for yet another extremely helpful and “exactly what I needed” article. After unsuccessful attempts of my own, I found your great .php redirection solution.

    Works like a charm.

Comments are closed for this post. Something to add? Let me know.
Welcome
Perishable Press is operated by Jeff Starr, a professional web developer and book author with two decades of experience. Here you will find posts about web development, WordPress, security, and more »
Banhammer: Protect your WordPress site against threats.
Thoughts
I disabled AI in Google search results. It was making me lazy.
Went out walking today and soaked up some sunshine. It felt good.
I have an original box/packaging for 2010 iMac if anyone wants it free let me know.
Always ask AI to cite its sources. Also: “The Web” is not a valid answer.
All free plugins updated and ready for WP 6.6 dropping next week. Pro plugin updates in the works also complete :)
99% of video thumbnail/previews are pure cringe. Goofy faces = Clickbait.
RIP ICQ
Newsletter
Get news, updates, deals & tips via email.
Email kept private. Easy unsubscribe anytime.