Fifteen articles on my own site have exactly one internal link pointing at them. The blog index. Nothing else on the internet I control points at those pages.
I found out by building the link graph instead of trusting the sitemap.
The site is a proportion calculator with a content section: 56 URLs in the sitemap, 40 of them blog posts. I fetched all 56 with curl through a local proxy — every one returned 200 first pass, no retries needed — then parsed 1,617 <a> tags with a regex, resolved relative hrefs to absolute, dropped the external hosts, deduped repeats inside each page, and built the in/out table in Python. Server-rendered HTML, so what I saved is the page.
| Measure | Value |
|---|---|
| URLs in sitemap | 56, all HTTP 200 |
| Canonical equals own URL | 56 of 56 |
<a> tags parsed | 1,617 |
| Unique internal links after dedupe | 944 |
| Blog posts among those 56 pages | 40 |
| Internal links pointing at any blog post | 220 |
| Of those, held by the 3 newest posts | 129 (58.6%) |
| Posts reachable by exactly one link | 15 |
| Posts with two links or fewer | 22 |
| Median links per post | 2 |
| Links leaving a post that go to nav or legal pages | 360 of 700 |
| Correlation, word count vs inbound links | r = −0.10 |
| Clicks from home to any post | 2 |
People assume a link audit finds broken links. It did not. Every URL resolved, every canonical pointed at itself, and the site is technically clean. The problem is arithmetic, not plumbing.
The "latest three" block is doing almost all the work. Forty of the 56 pages render a block with the three newest articles, and each block links all three. That is 129 links aimed at 3 URLs — 58.6% of all internal links into blog content, and 13.7% of every internal link on the domain. Remove that block and those three pages fall back to near-zero. It is not a related-posts system. It is a clock.
Length buys nothing. Pearson r between word count and inbound links is −0.10, noise leaning slightly negative. The site's longest article, 1,969 words on ratios as decimals, holds 2 links. A 1,239-word grade-6 examples page holds 44. If you write longer hoping the site notices, the site does not notice.
Half of every article's outbound links point at furniture. The 40 posts emit 700 unique internal links; 360 go to the homepage, /learn/, /blog/, /practice/ and five legal pages. Only 340 point at other content, roughly 8.5 per post, and most of those land on the same three pages as everything else.
Something I did not go hunting for: 46 anchors begin with a literal date string, "2026-11-14 ↗ How to find x in a ratio". Anchor text that mutates daily is a timestamp, not an anchor.
What I cannot measure: whether that block builds at deploy time or renders per request. I fetched each page once, on one afternoon, and they all agreed. If it rotates on a schedule, tomorrow's crawl gives a different distribution and my table is one snapshot of one Thursday. Ranking flow I cannot measure at all — that graph belongs to Google.
Correction, because the first version of this audit was wrong in a way worth publishing. My initial crawl reported 41 orphan pages with zero inbound links. It was a parser bug. I had stripped /blog/ out of every path while extracting filenames, so the graph asked whether /blog/how-to-cross-multiply/ linked to /how-to-cross-multiply/ — which returns 404. Forty real pages, forty URLs that do not exist, forty phantom orphans. I rebuilt the parser to key off sitemap order, re-ran it, and orphan count went to zero. What survived: fifteen posts with a single link, median two.
Disclosure: this is my site, proportioncalculatoronline.com, so I have the sitemap and the templates. The fix is boring — replace the date block with three hand-picked related posts per article, and add two links from the relevant guides into the fifteen single-link posts. About thirty manual links. Not done yet.
The three pages holding 59% of the links are dated 13 and 14 November. Next week they will be three different pages. The fifteen sitting on one link will still be sitting on one link.