Why does my internal linking look fine and still not work?
Because you have been checking it one page at a time. Internal linking problems on a large archive are patterns, not page faults. The same anchor text pointing at four different targets, or forty posts all linking to one hub with the identical phrase, only becomes visible when you look at every link at once.
The tool for that is an anchor text inventory. It is a single table of every internal link on the site, what it says, and where it goes. Building one takes an afternoon and it is the most useful thing I know for a blog that has grown past the point where anyone remembers what is on it.
This walkthrough assumes you have a CMS-driven blog with somewhere between two hundred and a few thousand posts, and that nobody has audited the linking since it was maybe forty posts.
What exactly is an anchor text inventory?
It is one row per internal link, recording the page the link sits on, the exact visible text of the link, and the URL it points to. Nothing more. Everything useful comes from sorting and grouping that table, not from anything clever you add to it.
The value is that it converts a vague question into a countable one. Instead of asking whether the internal linking is good, you ask how many distinct anchors point at a given page, how many targets share one anchor, and which published posts receive no internal links at all. Those all have numeric answers.
It is also a snapshot with a date on it. Run it again in three months and the difference tells you whether the linking habits actually changed or whether everyone nodded and carried on.
Why can you not just use the Search Console Links report?
Because Google is explicit that it is a sample, not a census. Search Console's own documentation says the Links report is not a comprehensive list of every link on your site, that it shows a sample of internal and external links, and that tables are limited to 1,000 rows, so tables may be truncated on larger or more linked-to sites.
There are three more limitations that matter for this specific job. Google's docs say pages are grouped by canonical URL, with anchor tags and possibly some parameters omitted before grouping. Duplicate links are combined, and in the link text report duplicates are based on link text rather than URL. Some URLs may be omitted entirely, for reasons such as non-indexed pages or deduped URLs.
The documentation also notes that the report includes links Google has found over time, which may since have been removed, and that it does not specify whether a link is marked nofollow. All of that is fine for the purpose Google built it for. It is not fine as the basis for an edit list you are going to act on.
How do you pull every internal link without buying anything?
Start from your own sitemap. Fetch the sitemap XML, extract every URL on your domain, then fetch each page and pull out every anchor tag whose destination is on your domain, recording the link text and the destination. A short script does the whole thing and you own the output.
Be polite about it. Fetch sequentially rather than in parallel, put a small pause between requests, and run it once rather than repeatedly while you tinker. Save the raw HTML for each page to disk on the first pass, so that when you inevitably want to extract something else you are working from local files instead of hitting your own site again.
Two details will bite you if you skip them. Normalise the URLs before comparing, so that a trailing slash or a www prefix does not split one page into two rows. And capture the link text exactly as rendered, including capitalisation, because inconsistent capitalisation of the same phrase is itself a finding.
What should the table contain, and what should it leave out?
Source URL, anchor text, target URL. Add a column for whether the link sits inside the article body or inside navigation, because navigation links are identical on every page and will otherwise drown everything else. Leave out everything you might want later; you can always re-derive it from the saved HTML.
Separating body links from template links is the one piece of judgement in the build. The practical way to do it is to identify the links that appear on every single page and treat those as template links. Anything that appears on some pages and not others is editorial, and editorial links are what this exercise is about.
Once the table exists, the analysis is just grouping. Group by target to see how many links each page receives. Group by anchor text to see how many targets each phrase points to. Group by source to see which posts link out generously and which link nowhere.
Which problems show up first?
Three, in my experience, and always in the same order. Orphan posts that receive zero editorial links. One phrase pointing at several different targets. And a long tail of anchors used exactly once, where every link to an important page says something different.
Orphans are the easiest to fix and the most valuable. A post nobody links to is a post you published and then forgot, and it usually has no path into it except the blog index. I wrote about finding these specifically in auditing orphan pages on a large blog, and the inventory gives you the same list as a by-product.
The ambiguous anchor problem is subtler. If the phrase "AI visibility" points at five different posts across the archive, you have taught every reader and every crawler that the phrase means nothing in particular on your site. Pick one canonical target for each important phrase and move the rest.
How do you decide what to fix first?
Fix by value of the target, not by count of the problem. Take the ten pages you most want people to reach, look at how many editorial links each one receives and what those links say, and fix those first. A tidy archive with your best pages still unlinked is not progress.
My ordering is: orphaned posts that matter, then important pages with fewer than three inbound editorial links, then ambiguous anchors on important phrases, then everything else. Most of the everything else never needs fixing, which is worth saying out loud because these audits have a strong pull toward completionism.
Resist adding links purely to raise a number. The inventory makes counts visible, and visible counts invite gaming. A link that a reader would not follow is worse than no link, because it trains people to ignore your links generally.
How do you push the fixes back into the CMS without breaking anything?
Read each post's current content, insert the link into an existing sentence that already mentions the topic, and write the whole field back. Never generate a fresh body and overwrite. The second approach loses anything a human edited since your inventory ran.
Work in small batches and verify each one. Ten posts, check them on the live site, then the next ten. Bulk operations on a content field are exactly the place where a small mistake becomes two hundred small mistakes, and the time saved by batching is not worth the recovery.
The insertion itself should be editorial. Find the sentence that already refers to the concept and link a natural phrase inside it. If no such sentence exists, write one or skip the post. I described the ongoing version of this discipline in building an internal linking system in the Webflow CMS.
How often is it worth rerunning?
Quarterly if you publish regularly, and always after any migration, restructure, or bulk slug change. The inventory is cheap to rerun once the script exists, and the diff between two runs is far more informative than either single run on its own, because it shows you direction rather than position.
What the diff tells you is whether the habit stuck. If the new posts published since the last run already link sensibly into the archive, the audit worked and you can leave it alone longer. If they do not, the problem is the writing process rather than the archive, and no amount of retrospective fixing will keep up.
After a migration the rerun is not optional. Slug changes turn working links into redirects at best and broken links at worst, and the inventory is the fastest way to find every internal link that now points somewhere it should not. The search-side case for keeping all of this tidy is one I made separately in internal linking for SEO and AI citations.
What should you do next?
Pull your sitemap today and count how many URLs are in it. If that number surprises you, build the inventory this week. If it does not surprise you, you probably already know which ten pages matter, so start by checking what links point at those.
The one thing I would not do is buy a tool before you have looked at the raw data once. Doing it manually the first time teaches you what your own archive looks like, and that understanding is what makes any tool useful afterwards rather than just expensive.
If you have a large archive and you are not sure whether your internal linking is helping or just present, tell me roughly how many posts you have and I will tell you what I would check first. Let's chat.
Get found, cited and the back office automated
Let's make your site the source AI engines quote and wire up the systems behind it.
Read more blogs
Let's get your website found and cited by AI
Tell me what you're working on, whether AI search is skipping your product, your back office is buried in manual work, or you need a build that does both.