Our site has 79 public pages. The sitemap lists them, the footer links a fifth of them, and until this week I had never asked the only question that matters about internal links: starting at the homepage, how many clicks to each page?

So I fetched all 79 URLs, parsed every <a href> out of the delivered HTML with Python's html.parser, and tagged each anchor with the landmark it sits in: header, footer, the breadcrumb nav, or the body of main. Then breadth-first search from /.

With the whole page, the site is two levels deep

depth pages
0 1
1 17
2 61

Nothing is unreachable and nothing is three clicks away. The 17 pages at depth 1 are not a curated set either, they are just the footer's contents: the five cluster hubs, the five venue pages it promotes, pricing, FAQ, about, and the three legal documents.

The reason is that one component does nearly all the linking:

region distinct targets anchors summed over 79 pages
footer 21 1,608
body of main 76 402
header 6 459
breadcrumb 7 141

The footer carries 21 destinations on 76 of the 79 pages (the three legal pages get a compact footer with four), which is 1,608 of the site's internal anchors. The header carries six in the markup, because the five links behind the "Resources" dropdown only exist in the DOM after you open it, so a crawler never sees them.

So from a crawler's point of view this site is perfectly flat, and the flatness is entirely borrowed. It is the same 21 links, 76 times.

With only the words, the site is ten levels deep

Now drop the header, the footer and the breadcrumb, and keep only anchors inside the body of main, which is the text a reader actually reads:

depth pages
0 1
1 4
2 21
3 3
4 7
5 7
6 5
7 4
8 2
9 1

Ten levels, and 24 of the 79 pages are not reachable at all. The homepage's body links to exactly four of our own pages (features, solutions, pricing, the FAQ) plus the sign-up form, and everything else has to be earned sentence by sentence. The longest route the copy actually offers is nine hops:

/ -> /solutions -> /solutions/pubs -> /guides/pub-event-ideas -> /guides/pub-quiz-music-licence -> /quiz-questions/music -> /quiz-questions/general-knowledge -> /quiz-questions/geography -> /quiz-questions/history -> /quiz-questions/literature 

That chain is not a navigation path anybody designed. It is what happens when every page carries a "related" block of three or four siblings and nothing else.

Four pages have a body in-degree of zero

Counting only body links, these pages are linked by no page's prose at all:

Three of them are cluster hubs. Every spoke links up to its hub through the breadcrumb, and the hubs are in the footer, so in practice nobody notices, but nothing we wrote ever says "see our guides" with a link on it.

For comparison, the top of the body in-degree table reads: /solutions/pubs 15, /quiz-questions/general-knowledge 13, /pricing 12, /guides/pub-quiz-round-ideas 12. The median page is linked from the body copy of 4 others.

The comparison cluster is an island with one-way bridges

All eight pages under /compare are in the unreachable 24, and the way they are unreachable is specific. Their own body copy links out perfectly happily: the Kahoot comparison links to /pricing, to a sibling comparison, to /compare/best-pub-quiz-apps and to /solutions/corporate-events. Across the cluster that is 30 body links.

Not one of them points inward from outside. No feature page, no guide, no pricing copy mentions the comparisons in a sentence. The cluster exists for a reader only if they scan the footer, and the footer entry is the single word "Compare".

You can check this in ten seconds: open any page on the site that is not a comparison page, select the article text, and search it for the word "compare". The links are in the chrome, not in the writing.

What the breadcrumb is quietly doing

Add the breadcrumb trail back and the unreachable set drops from 24 pages to 9: the eight comparisons and the terms of service. Seven targets, 141 anchors, and it rescues 15 pages, because once the copy drops you onto any spoke, the trail hands you the hub and the hub hands you everything else.

That is a strong argument for breadcrumbs that nobody usually makes. Ours exist because they emit BreadcrumbList structured data from the same function that renders the visible trail, and the crawling benefit was supposed to be the markup. The visible trail turns out to be the part doing the work.

The thing I would actually change

Nothing here is a bug. A sitemap lists all 79, the footer flattens the site to two clicks, every page returns 200, and the structured data is consistent. The measurement is still worth having, because the healthy-looking version of this graph, the one where everything sits two clicks deep, is produced by one shared component, and the version a reader experiences is ten levels deep with a quarter of the site missing.

Two cheap fixes, in order of value:

  1. One sentence in the feature or pricing copy that links the comparison hub. That converts eight orphans into depth-3 pages and gives the cluster an editorial reason to exist.
  2. A link to the terms from somewhere other than the footer, most obviously from the pricing copy, which is the page that describes what the terms govern.

And one measurement habit: when you audit internal links, attribute every anchor to the landmark it lives in, then run the crawl twice. The site that your footer describes and the site that your writing describes are not the same site, and only one of them is the one people read. Everything above is reproducible against our sitemap with 79 fetches and about 40 lines of Python.