WordPress coming soon page and SEO: what Google is given, and what to answer while a site is closed
A coming soon page that answers 200 is an ordinary page, and Google may index it as the site. For a live site closed for a day or two, Google says to answer 503. WordPress's own maintenance mode does, with Retry-After set to 600. One curl command shows what yours answers.
- By
- WP Ministry
- Published
- Tested on
- WordPress 7.1.3, PHP 8.3.35
In short
- There are two situations. A new site that has not launched has nothing in Google to lose. A live site that closes for a short while does.
- A coming soon page that answers 200 is an ordinary page. Google may index it, and whether that is wanted is your choice.
- The "Discourage search engines" box puts noindex on a coming soon page the theme draws, and stays ticked after launch until someone unticks it.
- WordPress's own maintenance mode answers 503 with Retry-After set to 600 on every address, and stops by itself after ten minutes.
- A maintenance page that answers 200 hands a search engine the same few words for every address on the site.
- Test whichever plugin you use from outside, signed out. The status line is the thing to read.
What a search engine is given while a WordPress site says "coming soon" or "under maintenance" depends on something the visitor never sees: the status code. A holding page that answers 200 is an ordinary page, and Google may index it, few words and all, as the site. A holding page that answers 503 says the address is unavailable for now, and Google ignores what is on it.
Two situations get blurred here, and they want different answers. A new site that has not launched has nothing in Google to lose, so the only question is whether you want the holding page listed. A live site that closes for a short while has pages in Google already, and Google's documentation says what to answer with: a 503. This page shows both on a real WordPress, and gives one command that reads what your own site answers.
Read what your site answers
Run this from any terminal, with your own address in place of https://example.com/. It asks for the page as a visitor who is not signed in. It prints the status line, and the Retry-After and X-Robots-Tag headers where they are sent.
curl -s -o /dev/null -D - https://example.com/ | grep -i -E "^HTTP|^retry-after|^x-robots-tag"HTTP/1.1 200 OKThe number is the status code. This second command prints the robots tag in the page, if it has one.
curl -s https://example.com/ | grep -i -o "<meta[^>]*robots[^>]*>" || echo "no robots tag"This is also how to test a coming soon or maintenance plugin, whichever one you use. Three things make the test worth trusting.
- Test signed out. A plugin that lets signed-in users through, as the one below does, shows you the real site in your own browser. A terminal is signed out. So is a private browser window.
- Test more than the home page. Ask for a post, and for
/robots.txt. - Run the commands as written, not
curl -I. That option sends a HEAD request, and WordPress ends a HEAD request before it chooses a template. On the test site, a holding page that was swapped in as a template answeredcurl -Iwith 200 and the full request with 503.
A new site that has not launched
There are two usual ways to put a coming soon page on a site that is still being built. One is an ordinary WordPress page set as the home page. The other is a plugin that shows a holding page in place of every address. Either way, an answer of 200 hands a search engine a page. Google's page on status codes says that for a 200 it "passes on whatever it received to the next processing step", and that its indexing systems "may index the content, but that's not guaranteed."
So there is a choice to make, and both sides of it are legitimate.
| You want | Setting | What a crawler is given |
|---|---|---|
| The holding page may be listed until launch | "Discourage search engines from indexing this site" unticked | Status 200 and no noindex. Google may index the holding page as the site. |
| Nothing listed until launch | The same box ticked | Status 200 and a robots tag of noindex, nofollow, on a page the theme draws. |
On the test site, a page titled "Coming soon" was set as the home page. With the box unticked it answered 200 with the tag max-image-preview:large, which blocks nothing. With the box ticked it answered 200 with this:
<meta name='robots' content='noindex, nofollow' />The second choice has a cost that arrives later. The box stays ticked when the holding page comes down, and a noindex left on a launched site is the thing that keeps it out of Google. What the "Discourage search engines" box does covers the setting, and the launch steps below include unticking it.
The box also reaches only pages that WordPress's theme draws. The holding page in the plugin further down is printed without the theme, and it carried no robots tag at all, box ticked or not. If your coming soon plugin draws its own page, the plugin's settings decide what the page says to search engines. Run the second command to see.
Neither choice hides anything. A site that must not be seen needs a password, as a staging site does, and a staging site that is already in Google is a problem of its own. A store has a separate switch: WooCommerce coming soon mode.
A live site closed for a short while
Google's page on pausing a site advises against closing one at all. It recommends keeping the site online and limiting what it does. Closing the whole site it calls "an extreme measure that should only be taken for a very short period of time (a few days at most)". Where it has to be done, the page says what to answer with:
If you need to urgently disable the site for 1-2 days, then return an informational error page with a 503 HTTP response status code instead of all content.
The HTTP specification defines 503 for this case. The server cannot handle the request "due to a temporary overload or scheduled maintenance", and it may send a Retry-After header to say how long to wait.
The same Google page lists what not to do during a closure:
- Do not answer 503 for
/robots.txt. The page says that "blocks all crawling". - Do not put a rule in robots.txt that disallows all crawling.
- Do not answer 403, 404 or 410, and do not add a
noindextag or header. The page says this "will remove the website's URLs from Google Search." - Do not use Search Console's temporary removal tool for a closure.
What WordPress's own maintenance mode answers
WordPress closes itself this way while it installs an update. It writes a file named .maintenance into the site's main folder, and while that file is fresh it answers before any plugin or theme is loaded. WP-CLI writes the same file on request:
wp maintenance-mode activateThe file holds one line, the time it was written:
<?php $upgrading = 1791417600; ?>With the file in place, the first command printed this for the home page of the test site:
HTTP/1.1 503 Service Unavailable
Retry-After: 600- Status 503 on every address tried: the home page, a post, the login page and
/robots.txt, which WordPress answers itself when the site's folder holds no such file. With a realrobots.txtfile in the folder, that address went on answering 200. Retry-After: 600. The value is in seconds, so ten minutes.- A body of one line: "Briefly unavailable for scheduled maintenance. Check back in a minute." It carried no robots tag.
- Ten minutes at most. WordPress honors the file for ten minutes from the time written in it. A file dated 601 seconds back was ignored, and the site answered 200 with the file still there.
So for a closure of minutes, WordPress already gives the answer Google asks for. This turns it off:
wp maintenance-mode deactivateOne trap is in WordPress's code. A file at wp-content/maintenance.php replaces the message, and WordPress then sends neither the 503 nor the header itself. On the test site, a maintenance.php that only printed a sentence turned the same closure into a 200. A custom maintenance file has to send the status itself.
If the message stays after an update, Briefly unavailable for scheduled maintenance covers the fix.
A holding page that answers 200
This is a coming soon or maintenance plugin at its simplest: a holding page for every visitor who is not signed in. It goes in wp-content/mu-plugins, a folder a fresh WordPress does not have until you create it.
<?php
/**
* Plugin Name: Holding page
* Description: Shows a holding page to visitors who are not signed in.
*/
add_action(
'template_redirect',
function () {
if ( is_user_logged_in() ) {
return;
}
header( 'Content-Type: text/html; charset=utf-8' );
echo '<!doctype html><html lang="en"><head><meta charset="utf-8"><title>Coming soon</title></head>';
echo '<body><h1>Coming soon</h1><p>We are getting things ready.</p></body></html>';
exit;
}
);These are the answers the test site gave a visitor who was not signed in.
| Address | Status | Body |
|---|---|---|
| The home page | 200 | The holding page |
| A post, an ordinary page | 200 | The same holding page, byte for byte |
/robots.txt | 200 | The holding page, in place of WordPress's rules |
/wp-sitemap.xml | 200 | The holding page |
| An address that does not exist | 404 | The holding page |
/wp-login.php | 200 | The login form |
A signed-in administrator was served the real site throughout.
On a new site this is the first situation again: an ordinary page that Google may index. On a live site it is the wrong answer. Every address Google already has now answers 200 with the same few words where the page used to be, and Google's page on status codes says of a 200 whose content suggests an error or an empty page that "Search Console will show a soft 404 error." The rules in robots.txt and the sitemap are gone as well.
The same page answering 503
Three changes make it the answer Google's page asks for: a 503 status, a Retry-After header, and leaving /robots.txt alone. Replace the file's contents with this.
<?php
/**
* Plugin Name: Holding page
* Description: Answers 503 to visitors who are not signed in while the site is closed for a short while.
*/
add_action(
'template_redirect',
function () {
if ( is_user_logged_in() || is_robots() ) {
return;
}
status_header( 503 );
header( 'Retry-After: 3600' );
header( 'Content-Type: text/html; charset=utf-8' );
echo '<!doctype html><html lang="en"><head><meta charset="utf-8"><title>Back shortly</title></head>';
echo '<body><h1>Back shortly</h1><p>We are working on the site and expect to be back within the hour.</p></body></html>';
exit;
}
);The first command then printed:
HTTP/1.1 503 Service Unavailable
Retry-After: 3600The home page, a post and the sitemap answered 503. /robots.txt answered 200 with WordPress's own rules, the login page still worked, and a signed-in administrator was served the real site. Google's page says to use Retry-After "with a best effort date or duration", and to keep the error page to static HTML that says when the site is expected back.
Delete the file to reopen the site. A must-use plugin has no Deactivate link, and a mistake in its code takes the whole site down. With one semicolon left out of this file, every address on the test site answered 500, the login page included, until the file was removed. Test it on a copy first.
Which to use when
| Situation | What to answer | Why | Source |
|---|---|---|---|
| A new site, and the holding page may be listed | 200, no noindex | It is an ordinary page, and Google may index it | Google, on status codes |
| A new site, and nothing is to be listed yet | 200 with noindex, taken off at launch | A noindex keeps a page's address out of Google Search | Google, on pausing a site |
| A live site, closed for minutes by an update | 503 with Retry-After | WordPress sends both by itself | WordPress's code, and the run above |
| A live site, closed for a day or two | 503 with Retry-After on every address but /robots.txt | Google's stated answer for "1-2 days" | Google, on pausing a site |
| A live site, closed for longer | Not a 503. Keep the site up and limit what it does, or "provide an indexable home page as a placeholder" with a 200 | A long closure affects how the site is indexed | Google, on pausing a site |
Launching
Step 1: Take the holding page down
Deactivate the coming soon plugin, delete the must-use file, or set the home page back under Settings, then Reading.
Step 2: Untick the box
Under Settings, then Reading, "Discourage search engines from indexing this site" must be unticked. This reads the setting from the command line:
It prints
1when the box is unticked and0when it is ticked. What the box does has the ways to change it.bashwp option get blog_publicStep 3: Clear any page cache
A caching plugin, the host's cache or a CDN can go on serving a stored copy of the holding page.
Step 4: Read what the site answers
Run the two commands at the top of this page, on the home page and on one inner page. The status should be 200, with no
Retry-Afterheader and nonoindex.Step 5: Check from outside
The page indexing check reads one address and reports its status, a
noindexin the page or its headers, a block in robots.txt and the canonical address.Step 6: Tell Google
Google's page says to use Search Console to ask for a few pages to be crawled again, and a sitemap for many. A new WordPress site that is not on Google yet covers the wait that follows.
What Google says about a 503 that stays
Google's two pages say this much, and no more.
- A 503 is for one or two days. Closing a whole site is for "a few days at most", and "even for just a few weeks" it "can have negative consequences on Google's indexing of your site."
- Crawling slows. Server errors prompt Google's crawlers "to temporarily slow down with crawling".
- Pages are kept, then dropped. The page on status codes says "already indexed URLs are preserved in the index, but eventually dropped", and that the indexing pipeline removes "URLs that persistently return a server error."
- Nothing is refreshed meanwhile. Content received with a 5xx is ignored, and the page on pausing a site warns that titles, descriptions, metadata and structured data cannot be refreshed while a page answers 503.
- Coming back is gradual. "Once the server starts responding with a 2xx status code, Google gradually increases the crawl rate for the site."
Neither page gives a number of days after which pages are dropped. A figure quoted for it does not come from these pages.
When to get help
- Ask the plugin's author or your host if a holding page answers 200 and no setting changes it.
- Hand over the launch if you would rather it was checked by someone else. SEO for a new website from WP Ministry is a one-time setup for a new or rebuilt WordPress site: indexing is switched on at launch and checked from outside, with the sitemap, Search Console and Bing Webmaster Tools set up.
Common questions
Should a coming soon page be noindex?
It is your choice. Without noindex, Google may list the holding page under your name before launch. With it, nothing is listed, and the tag has to come off at launch. If you tick WordPress's box for this, put unticking it on the launch list.
Does WordPress's maintenance mode affect Google?
During an update WordPress answers 503 with Retry-After: 600, which is the status Google's documentation asks for in a short closure. It lasts as long as the update, and WordPress ignores the file after ten minutes.
My maintenance plugin answers 200. Does that matter?
On a new site it makes the holding page an ordinary page. On a live site it replaces every page Google has with the same message, at a status that says all is well. Look in the plugin's settings for a maintenance or 503 mode, switch it on, and run the command again.
How long can a site answer 503 before Google drops its pages?
Google gives no number. Its page on pausing a site puts a 503 at one or two days, and its page on status codes says indexed addresses are kept "but eventually dropped".
Does a coming soon page keep the site private?
No. It changes what is shown at an address. Uploaded files, and anything the holding page does not cover, still answer. Use a password for a site that must not be seen.
- ResourceWordPress SEO audit checklist: what to check, in order, and how to check each item
- Error fix"Alternate page with proper canonical tag" in Search Console: what it means on a WordPress site
- Error fix"Blocked by robots.txt" in Search Console: when it is fine, and how to find the rule on WordPress
- Error fix"Blocked due to other 4xx issue" in Search Console: what it means on WordPress and what to do
- Error fix"Crawled - currently not indexed" on a WordPress site: what to leave and what to check
- Cost guideHow much does SEO cost? What sellers' surveys report, and what moves the price on a WordPress site

