New Website Not Showing on Google? How to Get It Indexed
Your new site launched but Google shows nothing. Check you are not blocking it, verify Search Console, submit a sitemap, inspect the home page and give Google time.
A single Disallow: / or a forgotten noindex can hide an entire site from Google. Learn how robots.txt is really parsed, how to test it, and how to protect staging properly.
Search Console shows a wall of Blocked by robots.txt or Excluded by ‘noindex’ tag, and your site is fading from Google. Somewhere, one line is telling search engines to stay away. It might be Disallow: / in a robots.txt file uploaded from staging, a “discourage search engines” box left checked, or an X-Robots-Tag header added by a server rule nobody remembers.
These two controls do different jobs, and mixing them up causes most of the damage. robots.txt controls crawling: whether Googlebot may fetch a URL. noindex controls indexing: whether a page it fetched may appear in results. This guide explains how each one is read, how to find which one is hurting you, how to protect a staging site the right way, and how to recover. If your whole site vanished and you have not yet narrowed down the cause, start with FG-77.
| Control | Where it lives | What it stops | What it does not stop |
|---|---|---|---|
robots.txt Disallow |
A plain text file at /robots.txt on each host |
Crawling (fetching the URL) | Indexing of the bare URL if other sites link to it |
Robots meta tag noindex |
<meta name="robots" content="noindex"> in the page HTML |
Indexing of that page | Crawling; Google must fetch the page to see the tag |
X-Robots-Tag: noindex |
An HTTP response header, set by the server, a plugin or a CDN | Indexing, and works for PDFs and images too | Crawling; also invisible in the page source |
| Password (HTTP basic auth) | Web server config | Everyone without the password, crawlers included | Nothing relevant; this is the reliable option for staging |
The key consequence: a noindex behind a robots.txt Disallow is never seen. Google cannot fetch the page, so it cannot read the tag. If other pages link to the blocked URL, Google can still index the address with no description, which shows up as Indexed, though blocked by robots.txt. To remove a page from Google, let it be crawled and give it noindex. To save crawling on pages that do not matter, use robots.txt. Do not use both on the same URL.
robots.txt exists in the site folder, the WordPress dashboard, Search Console, and SSH if you can get it. Server-level changes (Nginx config, some headers) need root or a ticket to your host.robots.txt, .htaccess and any Nginx config file before editing.curl runs on your own computer. macOS and Linux include it; on Windows use curl.exe in PowerShell or install WSL. wp and htpasswd run in an SSH terminal on the server; run wp from the folder containing wp-config.php (some hosts name it wp-cli). Blocks that start with User-agent, Auth, Header, location or <RequireAny> are file contents you edit, not commands.Look at the Page indexing report under Indexing, Pages. A jump in Blocked by robots.txt points at robots.txt. A jump in Excluded by ‘noindex’ tag points at a meta tag or header. Then confirm on a key URL with the URL Inspection tool and Test live URL: Crawl allowed? answers the robots.txt question and Indexing allowed? answers the noindex question. Note that when crawling is blocked, the indexing answer cannot reflect a noindex Google never saw.
Check both from your computer in one go:
curl -s https://example.com/robots.txt
curl -sI https://example.com/ | grep -i -E '^HTTP|x-robots-tag'
curl -s https://example.com/ | grep -io '<meta[^>]*robots[^>]*>'
Replace example.com with your domain. -s hides progress output and -I requests headers only; grep -E lets one pattern match both the status line and the header. Good output: a robots.txt without a bare Disallow: /, an HTTP/2 200 status with no x-robots-tag line (or one without noindex), and a robots meta tag that is absent or free of noindex. Bad output is any of those blocks present on a page you want indexed.
Google follows the Robots Exclusion Protocol, published as RFC 9309, with a few documented details of its own. Misreading the rules is how sites block themselves.
A file is made of groups. Each group starts with one or more User-agent lines followed by Allow and Disallow rules. A crawler picks the group whose user agent matches it most specifically and obeys only that group. If no group names it, it uses the User-agent: * group. If two groups name the same crawler, their rules are combined.
User-agent: *
Disallow: /wp-admin/
Allow: /wp-admin/admin-ajax.php
User-agent: Googlebot
Disallow: /
This is robots.txt content, not a command. Here Googlebot ignores the * group entirely and follows its own group, which blocks everything. Every other crawler can crawl the site. This trap appears when someone adds a Googlebot-specific group to “tune” Google and accidentally writes /. The reverse trap also exists: a Googlebot group with a harmless rule means Googlebot no longer obeys any of the restrictions you put under *.
| Line | Meaning |
|---|---|
Disallow: / |
Block every URL on this host for this group |
Disallow: (empty) |
Block nothing; same as no rule |
Disallow: /shop |
Block every path starting with /shop, including /shopping-guide/ |
Disallow: /shop/ |
Block only paths inside the /shop/ folder |
Order in the file does not matter. When several rules match a URL, the one with the longest matching path wins. If an Allow and a Disallow match with equal length, Google uses the less restrictive one, the Allow. That is why Allow: /wp-admin/admin-ajax.php beats Disallow: /wp-admin/ for that one file. Paths are case-sensitive: Disallow: /Private/ does not block /private/.
Google supports two special characters in paths. * matches any sequence of characters, and $ anchors the end of the URL.
Disallow: /*? blocks every URL containing a query string. On WordPress that includes /?s= search and ?add-to-cart= links, and also any URL that carries a ? for any reason, so use it with care.Disallow: /*.pdf$ blocks URLs ending in .pdf, but not /file.pdf?download=1, because that does not end in .pdf.Disallow: /*/feed/ blocks feed URLs anywhere in the path.A single stray *, for example Disallow: /*, is the same as Disallow: /.
https://www.example.com/robots.txt and https://example.com/robots.txt are different files. Redirects are followed for a limited number of hops.WordPress does not ship a robots.txt file. When a request for /robots.txt finds no real file, the server passes it to WordPress, which generates one. In current versions the default output is:
User-agent: *
Disallow: /wp-admin/
Allow: /wp-admin/admin-ajax.php
Sitemap: https://example.com/wp-sitemap.xml
This is the generated file content, not a command. The Sitemap line appears when core sitemaps are active and the site is public; SEO plugins usually replace it with their own sitemap URL. If a physical robots.txt exists in the site folder, the web server serves it directly and WordPress, along with every plugin’s robots.txt editor, is bypassed. Staging copies often bring a physical file with Disallow: / along.
ls -la robots.txt
wp eval 'do_robots();'
Run these over SSH in the site folder. ls -la lists the file with its size and date if it exists; “No such file or directory” means WordPress generates it. wp eval runs PHP inside WordPress, and do_robots() prints what WordPress would generate, including changes from plugin filters. If a physical file exists and differs from the generated version, the physical file is what Google sees. Good: either no physical file and a sensible generated one, or a physical file you wrote on purpose. Bad: a physical file with Disallow: /. Rename it to robots.txt.bak to fall back to WordPress’s version, or edit it.
Settings, Reading, Discourage search engines from indexing this site stores blog_public = 0. Since WordPress 5.3 this outputs a noindex, nofollow robots meta tag on every page rather than a robots.txt block (older versions changed robots.txt instead). Confirm with wp option get blog_public: 1 is public, 0 is discouraged.
Yoast SEO, Rank Math, All in One SEO and SEOPress can each set noindex per post type, taxonomy or individual post, and can edit robots.txt. A staging push that copies their settings tables brings any staging noindex with it. Also search for headers set outside WordPress:
grep -rni 'x-robots-tag' .htaccess wp-content/mu-plugins/ 2>/dev/null
grep -rni 'x-robots-tag' /etc/nginx/ 2>/dev/null
Run these over SSH, the first in the site folder and the second if you have root on your own server. -r searches recursively, -n shows line numbers and -i ignores case; 2>/dev/null hides “permission denied” noise. Good output is nothing, or rules you placed on purpose for specific files. A line like Header set X-Robots-Tag "noindex" applying to the whole site is your culprit. If you find nothing but curl still shows the header, it is coming from the host’s server config or a CDN rule, so check your CDN dashboard (for example Cloudflare Transform Rules) or open a ticket.
robots.txt is a request, not a lock. A blocked staging site can still be indexed from links, and the file is easy to carry over to live by mistake. A password stops everyone, Google included, and cannot leak a block onto production because it lives in server config that you do not migrate. Many hosts offer password protection for staging in the control panel; use that if available. Otherwise, create a password file outside the public folder:
htpasswd -c /home/ACCOUNT_USER/.htpasswd STAGING_USER
Run this over SSH. Replace ACCOUNT_USER with your hosting account’s home folder name and STAGING_USER with a login name you choose; it prompts for the password. -c creates the file and overwrites any existing one, so leave it off when adding a second user. Good output is “Adding password for user STAGING_USER”. “command not found” means the Apache utilities are not installed; your host’s panel may offer the same feature.
For Apache or LiteSpeed, add this to the staging site’s .htaccess:
AuthType Basic
AuthName "Staging"
AuthUserFile /home/ACCOUNT_USER/.htpasswd
<RequireAny>
Require expr %{REQUEST_URI} =~ m#^/\.well-known/acme-challenge/#
Require valid-user
</RequireAny>
Header set X-Robots-Tag "noindex, nofollow"
This is file content. AuthUserFile must be the full path you used with htpasswd. The RequireAny block lets Let’s Encrypt reach its validation path without a password so the staging certificate can renew, and requires a login for everything else. The Header line (needs mod_headers) adds a noindex for anything that slips through. Good result: the browser shows a login prompt and curl -sI returns 401. A 500 error means a module or directive is not allowed; remove the RequireAny block and test again, or ask your host. For Nginx, inside the staging server block:
auth_basic "Staging";
auth_basic_user_file /home/ACCOUNT_USER/.htpasswd;
add_header X-Robots-Tag "noindex, nofollow" always;
location ^~ /.well-known/acme-challenge/ { auth_basic off; }
This is Nginx config. always makes the header appear on error responses too, and the location block exempts certificate validation. Test with nginx -t before reloading; “syntax is ok” and “test is successful” are good output. Expect WordPress Site Health to report failed loopback requests on a password-protected site; that is normal on staging.
Recovery time depends on how often Google crawls your site. A short block on a well-crawled site often recovers quickly once the fix is seen; a long block can take weeks to fully undo, and positions are not guaranteed to come back exactly as they were.
The Search Console robots.txt report shows what Google fetched, but it does not test individual URLs against a draft file. For that, use Google’s open source robots.txt parser, published on GitHub as google/robotstxt, which Google describes as a lightly modified copy of the production code Googlebot uses. Clone it and build it with CMake as its README describes (cmake .. then make in a c-build folder), then test a draft file:
./robots ROBOTS_FILE Googlebot https://example.com/PAGE_PATH/
Run this on your computer (macOS, Linux or WSL with a C++ compiler and CMake installed) in the c-build folder. Replace ROBOTS_FILE with the path to your draft robots.txt and PAGE_PATH with a URL you care about. The second argument is the user agent token to evaluate. Good output ends with ALLOWED, for example user-agent 'Googlebot' with URI 'https://example.com/PAGE_PATH/': ALLOWED. DISALLOWED for a page you want in Google means the draft has a problem. The exit code is 0 for allowed and 1 for disallowed, which makes it easy to script a list of URLs. Run it for your homepage, a post, a product, a category, and a URL with a query string, so you see exactly how wildcards and precedence play out. For a quick check without building anything, the URL Inspection live test tells you whether the current live file allows a URL.
A minimal, safe WordPress robots.txt for most sites is the default shown in Step 3. Every extra line should have a reason you can explain. Blocking CSS, JavaScript or /wp-content/ stops Google rendering your pages properly and should not be done.
Open a ticket when curl shows an X-Robots-Tag header or a robots.txt you cannot find in your files, when robots.txt returns 5xx or times out, or when the Search Console robots.txt report shows fetch errors. Include:
curl -sI output, including any CDN ray or request ID..htaccess contains.Our diagnostic tools can fetch robots.txt and response headers from outside your network. If the site itself is unreachable, use the Emergency Room checklist first.
Did this fix it?
Still stuck? Start again from what you can see in the Emergency Room.
Still stuck?
Print a free one-page checklist to keep, or open the Emergency Room if the symptom does not match.
Get the free checklistsKeep reading
Search the field manual
Or jump straight to a symptom
Press / to search from any page, Esc to close