Back to Blog
SEO#Indexing#Next.js#AI Crawlers#Technical SEO#Case Study

We Audited Our Own Site. Google Indexes 39% of It.

By Liwaa BeainiOctober 16, 20268 min read
39% of our 132 sitemap URLs are indexed by Google (Our Google Search Console, 12 Oct 2026)
Source: Our Google Search Console, 12 Oct 2026

Google indexes 52 of the 132 URLs in our sitemap. That is 39%, on a site that sells AI visibility audits, so we ran the audit on ourselves.

Nothing was blocked. The problem was what we had published, plus one framework default we had never looked at.

132
URLs in our sitemap
52
indexed by Google on 12 October
0
technical blocks on any of them

Step one: rule out the technical failures

We fetched every URL in the sitemap. All 132 returned 200, none carried noindex, and every canonical pointed at the page itself.

When every URL is technically clean and Google still skips most of them, the problem is not access. It is Google's judgement of the pages.

Page count is not the problem either. Google's crawl budget guide is written for sites with "1 million+ unique pages", or 10,000+ pages that change daily (Google, updated 2026-07-22). At 132 pages, Google can crawl everything we have.

More indexed pages did not bring more impressions

On 17 September we fixed how our pages link to each other. Ten blog posts had no inbound link from any other post, and seven docs pages were reachable only through a chain of next and previous links.

Google picked the pages up fast. Indexed pages went from 34 to 48 in two days and 53 in five, then held at 52 to 53 for three weeks.

02040600100200300Pages indexedSearch impressions per daySep 17: link fix5234avg 139avg 132Aug 1Sep 1Oct 1Jul 17: 91 impressionsJul 18: 87 impressionsJul 19: 90 impressionsJul 20: 86 impressionsJul 21: 69 impressionsJul 22: 86 impressionsJul 23: 64 impressionsJul 24: 34 indexed, 68 impressionsJul 25: 35 indexed, 61 impressionsJul 26: 35 indexed, 51 impressionsJul 27: 35 indexed, 75 impressionsJul 28: 35 indexed, 72 impressionsJul 29: 35 indexed, 82 impressionsJul 30: 35 indexed, 75 impressionsJul 31: 35 indexed, 85 impressionsAug 1: 35 indexed, 47 impressionsAug 2: 35 indexed, 56 impressionsAug 3: 35 indexed, 62 impressionsAug 4: 35 indexed, 64 impressionsAug 5: 35 indexed, 110 impressionsAug 6: 33 indexed, 122 impressionsAug 7: 33 indexed, 92 impressionsAug 8: 32 indexed, 87 impressionsAug 9: 32 indexed, 108 impressionsAug 10: 32 indexed, 121 impressionsAug 11: 33 indexed, 46 impressionsAug 12: 33 indexed, 46 impressionsAug 13: 33 indexed, 48 impressionsAug 14: 33 indexed, 75 impressionsAug 15: 34 indexed, 94 impressionsAug 16: 34 indexed, 117 impressionsAug 17: 34 indexed, 129 impressionsAug 18: 34 indexed, 136 impressionsAug 19: 34 indexed, 177 impressionsAug 20: 34 indexed, 170 impressionsAug 21: 34 indexed, 171 impressionsAug 22: 30 indexed, 176 impressionsAug 23: 30 indexed, 162 impressionsAug 24: 30 indexed, 90 impressionsAug 25: 30 indexed, 28 impressionsAug 26: 30 indexed, 36 impressionsAug 27: 30 indexed, 30 impressionsAug 28: 30 indexed, 153 impressionsAug 29: 32 indexed, 193 impressionsAug 30: 32 indexed, 196 impressionsAug 31: 32 indexed, 230 impressionsSep 1: 32 indexed, 191 impressionsSep 2: 32 indexed, 179 impressionsSep 3: 32 indexed, 166 impressionsSep 4: 32 indexed, 180 impressionsSep 5: 33 indexed, 182 impressionsSep 6: 33 indexed, 163 impressionsSep 7: 33 indexed, 181 impressionsSep 8: 33 indexed, 230 impressionsSep 9: 33 indexed, 148 impressionsSep 10: 33 indexed, 128 impressionsSep 11: 33 indexed, 100 impressionsSep 12: 33 indexed, 100 impressionsSep 13: 33 indexed, 105 impressionsSep 14: 33 indexed, 102 impressionsSep 15: 34 indexed, 124 impressionsSep 16: 34 indexed, 83 impressionsSep 17: 34 indexed, 51 impressionsSep 18: 34 indexed, 59 impressionsSep 19: 48 indexed, 36 impressionsSep 20: 48 indexed, 40 impressionsSep 21: 48 indexed, 35 impressionsSep 22: 53 indexed, 69 impressionsSep 23: 53 indexed, 67 impressionsSep 24: 53 indexed, 121 impressionsSep 25: 53 indexed, 96 impressionsSep 26: 53 indexed, 85 impressionsSep 27: 53 indexed, 85 impressionsSep 28: 53 indexed, 121 impressionsSep 29: 53 indexed, 303 impressionsSep 30: 53 indexed, 107 impressionsOct 1: 53 indexed, 170 impressionsOct 2: 53 indexed, 170 impressionsOct 3: 53 indexed, 138 impressionsOct 4: 53 indexed, 137 impressionsOct 5: 52 indexed, 198 impressionsOct 6: 52 indexed, 197 impressionsOct 7: 52 indexed, 191 impressionsOct 8: 52 indexed, 145 impressionsOct 9: 52 indexed, 122 impressionsOct 10: 52 indexed, 84 impressionsOct 11: 52 indexed, 82 impressionsOct 12: 52 indexed, 89 impressions
Our Search Console data, 17 July to 12 October 2026. The averages compare the 28 days before the fix with the 21 days after the new pages were in. Hover a day for its numbers.

Impressions did not follow. We averaged 139 a day in the 28 days before the fix and 132 a day after it.

PeriodPages indexedImpressions per day
21 Aug to 17 Sep (before the fix)30 to 34138.5
22 Sep to 12 Oct (after)52 to 53132.2

Getting a page indexed and getting it shown are different problems. Fixing discovery solved the first. It did nothing for the second: the 19 new pages either answer questions few people search for, or rank too low to be seen.

What the skipped pages have in common

We measured each page's own text: the words in its main content, minus navigation, and minus any paragraph that appears on four or more pages.

Words of its ownPages
Under 15012
150 to 29927
300 to 59933
600 to 99935
1,000 or more25

39 pages have fewer than 300 words of their own. The thinnest sections were the ones closest to the product: feature pages (median 149 words), free tools (190) and help articles (214).

The same topic, written six times

Short pages were the smaller problem. Grouping pages by title and slug, we had written the same 9 topics three to six times each, spread across the blog, academy, docs, help and resources.

TopicPages covering it
What GEO is, and GEO vs SEO6
Best GEO tools5
AI hallucinations about your brand5
Tracking competitors5
Understanding your score4
Schema markup4
How ChatGPT talks about brands4
Measuring ROI3
Checklists3

When two of your pages answer the same question for the same reader, you are asking Google to choose between them. A feature page and a docs page on one topic can both earn their place, because one sells and one explains. Two explainers of the same thing cannot.

The finding we didn't expect: our titles were in the body

The first script we wrote for this audit reported the title of every page as "99Visibility". The first <title> tag in our HTML was the one inside our SVG logo. The real page title came more than 28,000 characters after <head> had closed.

Since Next.js 15.2, the framework streams page metadata (title, description, canonical, Open Graph tags) into the <body> so pages start rendering sooner. User agents on its htmlLimitedBots list get the metadata in <head> instead (Next.js docs). We requested one of our pages as each crawler and recorded where the tags landed.

It only happens on pages rendered on demand, which was 84 of our 132 URLs. Pages built ahead of time already had their metadata in the head.

CrawlerBefore the fixAfter
GooglebotBodyHead
BingbotHeadHead
GPTBotBodyHead
OAI-SearchBotBodyHead
ClaudeBotBodyHead
PerplexityBotBodyHead

Googlebot runs JavaScript, so after rendering it sees the tags moved back into <head>. The AI crawlers do not. Vercel's study of AI crawler traffic found that ChatGPT's and Claude's crawlers fetch JavaScript files but "don't execute them" (Vercel).

What GPTBot or ClaudeBot does with a title it finds in the body is undocumented. A spec-compliant HTML parser still finds the right one; our first script didn't. No AI company publishes which kind of parser its crawler runs, so nobody outside those companies can tell you the effect.

Google is explicit about one tag. The canonical link "is only accepted if it appears in the <head> section of the HTML", and Google asks you to set it in the HTML source rather than have JavaScript change it (Google). Our raw HTML had it in the body and relied on JavaScript to move it.

The one-line fix, and the trap next to it

// next.config.ts
htmlLimitedBots: /.*/,

This serves metadata in <head> to every request. Next.js documents it as the way to turn streaming metadata off.

Don't list only the AI bots. Setting htmlLimitedBots replaces Next's default list instead of adding to it. A regex of GPTBot|ClaudeBot|PerplexityBot would move Bingbot, Twitterbot, LinkedInBot and Slackbot back to streamed metadata. The docs say so, and we confirmed it in the framework's source.

The trade-off: a page now waits for its metadata before it starts streaming. If your metadata comes from a slow API call, measure your page speed before and after.

Check your own site in ten minutes

  1. Compare two numbers. Count the URLs in your sitemap, then open the Pages report in Google Search Console and read the Indexed count. Ours were 132 and 52.
  2. Rule out access first. Run five of the non-indexed URLs through Search Console's URL Inspection. It shows the status, any noindex and the canonical Google chose.
  3. See where your title lands. In Chrome, open view-source: followed by your page URL. Search for </head>, then search for your page title. If the title comes after </head>, your metadata is being streamed.
  4. Count what is yours on each page. Ignore the navigation and the footer. A page you want to rank with fewer than 300 words of its own is where to start.
  5. Write down the question each page answers. If two pages answer the same one for the same reader, give each a different job.

What we're changing

  • Every page gets one job. Help articles answer "I'm stuck, what now?" Docs are the feature-by-feature reference. The blog and academy teach.
  • Feature pages and free tools get real product output, not filler. They are the pages that make money, and they were the thinnest on the site.
  • Metadata sits in <head> for every crawler, using the line above.

Frequently Asked Questions

Does having too many pages hurt SEO?

Not by count. Google's crawl budget guidance starts at a million pages. What matters is how many of your pages are worth indexing, and whether they compete with each other for the same question.

Does Next.js streaming metadata hurt Google rankings?

We have no evidence it does. Googlebot renders JavaScript, and Next.js designed streaming around that. We turned it off because of Google's rule on canonicals and because the AI crawlers don't render.

Will moving metadata into the head get us cited by ChatGPT?

No one has measured that. Metadata in <head> removes one way to be misread. It does not make a page more likely to be chosen.

Check the access side automatically

The checks above are manual. A 99Visibility audit runs the access side for you: it requests your site as each AI crawler, reads your robots.txt rules bot by bot, and flags noindex and nosnippet. These checks decide whether a crawler gets your page at all. The free plan includes one audit a month. Run your free audit.

Share

Want more of our research in Google Search and AI Mode? Add us as a preferred source.

Add 99Visibility as a preferred source on Google

Can AI crawlers reach your site?

Your free audit requests your site as each AI crawler, reads robots.txt bot by bot, and shows every place your firewall disagrees with it.

Start Free Audit

Related Articles