Technical SEO
I Mapped the Internal Links of 15 SaaS Blogs. 38% of Posts Were Orphans.
How many blog posts have no internal links pointing at them?
On the 15 SaaS blogs I crawled, 38% of posts had no in-content internal link pointing at them — 3,979 orphans out of 10,426 posts. The median blog stranded 44% of its own library. Every single blog in the set had orphans, and the rate ranged from 1.4% to 67.5%. These posts are in the sitemap and reachable from paginated archives; what they lack is a link from inside the body of any other post.
I wrote a guide to running an internal linking audit that made a complaint: the numeric rules everyone repeats in this topic — five links per page, nothing deeper than three clicks — have no source behind them. Writing that felt slightly dishonest, because I was pointing at an empty space without filling it.
This is the evidence half. That article is the process; this one is the measurement. I crawled 10,426 posts, mapped 44,513 in-content links between them, and counted what was left stranded.
Key takeaways
- Across 15 SaaS blogs and 10,426 posts, 3,979 posts (38.2%) had zero in-content inbound links. The median blog orphaned 44.0% of its posts.
- Orphan rates were not close together. Userpilot stranded 1.4% of its posts; Ghost stranded 67.5%. Nine of the 15 blogs were above 40%.
- All 15 blogs had orphans. Not one company in the set had a fully linked library, including the analytics vendors.
- The strongest predictor was simply how often posts link out in-content. Correlation between a blog’s median in-content outbound links per post and its orphan rate was −0.84.
- Userpilot’s median post carries 15 in-content links to other posts. Ghost’s, Metabase’s and Typeform’s median post carries zero. That single editorial habit separates the top of this table from the bottom.
- Being in the sitemap did not help. Every orphan below was in its blog’s XML sitemap, because the sitemap is how I found it.
What I measured, and how you can repeat it
Every number here comes from one crawl run on 4 September 2026. The method matters more than usual in this topic, because “internal link” is a phrase that quietly means four different things, and the choice determines the answer.
The universe. For each blog, every post URL listed in its XML sitemap. No sampling — I crawled the whole library on every blog reported, at 92% coverage or better (the shortfall is redirects and posts that 404 out of a stale sitemap). Sampling was not an option: to know whether a post is an orphan you have to check every other post that could link to it, so a partial crawl systematically overstates orphan counts. I found this the hard way, on an earlier run capped at 500 posts per blog, which reported Amplitude at 64.6%. Crawled in full, Amplitude is 53.4%.
Raw HTML, no JavaScript. Every page was fetched with a plain HTTP GET and parsed as delivered. Nothing was rendered. This is deliberate: Google is explicit that “Google can only crawl your link if it’s an <a> HTML element (also known as anchor element) with an href attribute”, so an <a href> in the delivered HTML is the unit that actually carries a link signal.
In-content links only. This is the part that makes the numbers mean something. Before extracting links I stripped the navigation, header, footer, sidebar, breadcrumb, related-posts, author-bio, share and CTA containers from every page, then took the anchors from what remained — the article body.
Why bother? Because a link that appears on all 400 pages of a blog carries no editorial signal about any one of them. If the footer links to your pricing page, that tells Google nothing about which of your posts deserves attention, because it says exactly the same thing on every post you have ever published. A template link is a fact about your theme. An in-content link is a decision a writer made about this specific piece. Only the second one is evidence of anything.
To catch template links that survived the container strip, I added a frequency filter: any target linked from more than 30% of a blog’s posts was discarded as boilerplate.
The orphan definition. A post is an orphan if zero other posts on the same blog link to it from within their body copy. Links from category pages, tag archives, the blog index and pagination do not count, and neither do links from a post to itself.
That is deliberately stricter than the industry-standard definition. Screaming Frog flags a URL as orphaned when it is “found exclusively in an XML Sitemap but … not discovered during a website crawl via internal hyperlinks” — a definition under which any internal hyperlink rescues a page, including one from page 14 of a paginated archive or a related-posts widget.
That is the right definition for crawl coverage, and I am not criticising it. It is the wrong one for editorial signal, which is the thing I wanted to measure. A page that only a pagination link can reach has been found by a crawler and abandoned by its own authors, and those are different problems with different fixes.
Finding 1: the spread is enormous, and it is a choice
The headline number, 38%, is the least interesting thing in the dataset. The interesting thing is that the blogs are not clustered around it.
Userpilot orphaned 7 posts out of 500. Ghost orphaned 282 out of 418. These are both competent companies with real content teams and real budgets. The difference between them is not resources, and it is not CMS. It is whether writers link to earlier posts while drafting.
That reading is not a guess. The correlation between a blog’s median in-content outbound links per post and its orphan rate is −0.84, which for 15 data points is about as clean as this kind of measurement gets. Userpilot’s median post contains 15 in-content links to other Userpilot posts. Ghost, Metabase and Typeform all have a median of zero — more than half of their posts link to no other post at all.
Orphan rot is not something that happens to a blog. It is the accumulated result of publishing posts that do not point anywhere.
Finding 2: publishing volume does not cause it
The obvious hypothesis is that big blogs strand more posts, because nobody can hold 2,000 URLs in their head. The data does not support it.
Buffer has the largest library in the set at 2,465 posts and orphans 28.6% — better than eleven smaller blogs. Close has 956 posts and orphans 18.0%. Meanwhile Metabase orphans 64.2% of a 109-post library, and Fathom orphans 54.2% of 107 posts.
A 107-post blog is small enough for one person to know every article by name. Fathom still strands more than half of it. Size is not the variable; habit is.
There is a plausible reason the small blogs in this set do badly. Fathom’s and Metabase’s posts read as essays and engineering write-ups — standalone pieces, often first-person, with plenty of outbound links to Wikipedia and vendor documentation and almost none to their own back catalogue. That is a perfectly respectable way to write. It just leaves the library unconnected.
Finding 3: the sitemap is not doing what people think
Every orphan in this study was listed in its blog’s XML sitemap. That is not a coincidence — the sitemap is how I built the crawl list.
This matters because “it’s in the sitemap” is the most common reason teams give for not worrying about orphans, and it confuses two different things. A sitemap is a discovery hint. An internal link is both a discovery path and a relevance signal, and Google describes it as doing both jobs: it “uses links as a signal when determining the relevancy of pages and to find new pages to crawl”.
Google’s own published guidance on internal linking is one sentence long and sets a floor far below any of the invented rules: “Every page you care about should have a link from at least one other page on your site.” Not five links. One. On the median blog in this study, 44% of posts fail that.
I want to be careful about what this does and does not prove. I did not measure rankings, traffic or crawl frequency for these posts, so I am not claiming a specific ranking penalty. What I measured is that a large share of published SaaS content receives no editorial signal from the rest of its own site — and that the site’s own authors have, in effect, voted that those posts are not worth referring to.
What I could not measure, and why
Nineteen blogs went into this study. Fifteen came out. The four exclusions are worth stating plainly, because a study that only reports what worked is hiding its error bars.
- Hotjar — the post URLs in the sitemap return 404. Hotjar is now part of Contentsquare and the blog appears to have moved; the sitemap has not caught up. Nothing to measure.
- Chargebee — my crawler failed on it, not the other way round. Chargebee’s
/resources/pages are server-rendered and contain their text in raw HTML, but the markup uses neither<article>nor a recognisable content class, so my body-extraction step returned nothing. Rather than report a 98.8% orphan rate that was really a bug, I dropped it. - Groove and Databox — no reachable sitemap isolating blog posts from the rest of the site. Without a clean universe there is no denominator.
One thing I expected to find and did not: I found no blog in this set that hides its article links behind client-side rendering. I went looking for it, because it is the failure mode that would make in-content links invisible to a raw-HTML crawler, and it is a real pattern on the wider web. Across these 19 candidates, article bodies were in the delivered HTML. The median post body on the worst-performing blog in the study, Ghost, still contained 4,963 characters of text in raw HTML. Their posts are crawlable. They just do not link to each other.
That is a more uncomfortable finding than a rendering bug would have been. A rendering problem is a ticket for an engineer. This is an editorial habit, and it belongs to whoever commissions the writing.
The full results
Every blog crawled in full on 4 September 2026, ordered by orphan rate. The complete dataset, including median body length and total in-content links, is available as a CSV under CC BY 4.0.
| Blog | Posts crawled | Orphans | Orphan rate | Median in-content links per post |
|---|---|---|---|---|
| Userpilot | 500 | 7 | 1.4% | 15 |
| Close | 956 | 172 | 18.0% | 9 |
| Plausible | 105 | 25 | 23.8% | 2 |
| Buffer | 2,465 | 704 | 28.6% | 3 |
| Baremetrics | 494 | 144 | 29.1% | 2 |
| Front | 249 | 98 | 39.4% | 2 |
| Help Scout | 300 | 121 | 40.3% | 2 |
| Intercom | 1,751 | 770 | 44.0% | 1 |
| PostHog | 363 | 162 | 44.6% | 2 |
| Mixpanel | 610 | 296 | 48.5% | 1 |
| Amplitude | 1,494 | 798 | 53.4% | 1 |
| Typeform | 505 | 272 | 53.9% | 0 |
| Fathom Analytics | 107 | 58 | 54.2% | 1 |
| Metabase | 109 | 70 | 64.2% | 0 |
| Ghost | 418 | 282 | 67.5% | 0 |
| All 15 | 10,426 | 3,979 | 38.2% | — |
Read the last column first. It predicts the fourth one better than anything else in the table.
How to check your own site
You do not need a crawl of 10,000 pages to find out whether you have this problem. You need one number about one page.
Open your best post and count the in-content links pointing at it. Not links from the nav. Not the related-posts block. Links from inside the body copy of other articles you have published. If the answer is zero, and it is your best post, you have found the shape of the problem and you can stop reading.
To do it properly across a whole library, you need the link graph rather than a spot check. I built a free internal link graph tool that crawls a site and draws it — orphans show up as unconnected dots, and hubs show up as the dense clusters. It uses the same in-content definition as this study, which is why the picture it gives you is comparable to the table above.
Once you can see the graph, the audit process is the other half: which four checks matter, how to prioritise findings by what the page is worth rather than by issue count, and how to verify a fix actually landed. If internal linking is one workstream inside a larger review, it sits as its own phase in the twelve-phase framework.
The fix itself is unglamorous. It is not a plugin. It is a step in your publishing checklist that says: before this post goes live, link to it from two existing posts where the reference is genuinely useful. Blogs that do this have orphan rates near 1%. Blogs that do not have orphan rates near 60%. There is no third group.
Frequently asked questions
What is an orphan page?
An orphan page is a page with no internal links pointing to it from elsewhere on the same site. In this study I used a stricter version: a post with no in-content inbound links — meaning links from inside the body copy of other posts, ignoring navigation, footers, sidebars, related-post modules and paginated archives.
Does being in the XML sitemap stop a page being an orphan?
No. A sitemap helps a page get discovered, but it is not an internal link and carries no relevance signal. Every one of the 3,979 orphans in this study was in its site’s sitemap. Google’s guidance is that every page you care about should have a link from at least one other page on your site, which is a separate requirement from sitemap inclusion.
How many internal links should a page have?
Google does not publish a number, and neither will I. The published guidance is a floor, not a target: at least one link from another page. The useful finding from this data is directional rather than prescriptive — blogs whose posts carry more in-content links to other posts have far fewer orphans (correlation −0.84), and the blogs with a median of zero are the ones stranding two-thirds of their libraries.
Why exclude navigation and footer links?
Because a link that appears on every page of a site says nothing about any individual page. If your footer links to a post, that is a property of your template, not an editorial judgement about that post. In-content links are the ones a writer chose to place, which makes them the only ones that carry information about relative importance.
Does this study prove orphan pages rank worse?
No, and I want to be explicit about that. I measured link structure, not performance. I did not pull rankings, traffic or crawl logs for these posts. What the study establishes is how widespread the structural problem is, not what it costs. Anyone telling you the precise traffic impact of an orphan page is quoting a number nobody measured — which is the habit that prompted this study in the first place.
Can I use this data?
Yes. The full dataset is published as a CSV under CC BY 4.0. Attribution to Nadia Mohamed. If you re-run the method and get different numbers, that is useful — the crawl is a snapshot of 4 September 2026 and these libraries change.