Your page clearly has 50 internal links pointing to various articles, but Search Console → Links → Internal links → Top linked pages shows certain URLs with “0 internal links.” Or URL Inspection shows “Discovered – currently not indexed” even though you’ve linked to a page from five others.
Fastest answer: before you change any code, rule out two things. (1) Between May 21 and June 12, 2026 the Search Console Links report itself was broken — many sites saw zero links or 87-90% drops overnight, and even the interim “fix” only rolled the numbers back to stale data. If your drop is recent and site-wide, it may have been the report, not your links. (2) The report is a sample, not a complete index, and it lags by days. So a single URL showing “0” can be normal. If the zero persists for weeks and is specific to certain pages, then it’s almost always the real problem below: Googlebot can’t see those links. It doesn’t execute every script on the first pass, doesn’t click, and doesn’t expand accordions. Links visible in your browser may simply not exist in Google’s fetched HTML.
First, rule out the report itself
The Links report is not a live, exhaustive count:
- It’s a sample. Google’s own docs say it “isn’t a comprehensive list of every link on your site… It shows a sample of internal and external links.” A high-volume page may genuinely have links Google followed that never surface here.
- It’s delayed. Link data is days behind crawling and is decoupled from ranking systems. A page you linked yesterday won’t show up today.
- It broke in 2026. The Links report stopped reporting fresh data on May 21, 2026. Around May 23 Google rolled it back to roughly week-old numbers (so it looked fixed but showed stale counts), and fresh counts only fully returned on June 12, 2026. If your “0 links” or sudden collapse lines up with that window, wait for fresh data before touching code.
Even when the report under-counts, Google may still be using the links algorithmically — the report is a diagnostic, not the ranking signal. Confirm a specific link with URL Inspection (below) rather than trusting the aggregate count.
Which bucket are you in?
| Symptom | Likely cause | Confirm with |
|---|---|---|
| Site-wide collapse around late May 2026 | The GSC report bug (now fixed) | Compare dates; re-check after June 12 |
| Specific pages show 0; links only appear after page interaction | JS-rendered links | curl static HTML vs browser count |
| Links sit in collapsed accordions / Tab panels | Hidden-link discount | Search templates for display: none, <details>, hidden tabpanels |
| Link count low despite many links in source | Accidental rel="nofollow" | grep the rendered HTML for nofollow |
| Cards/buttons navigate but don’t count | Not real <a href> (onclick / data-link) | View source; look for <button>/<div> with JS nav |
| Target never crawled at all | Target blocked by robots.txt | Check robots.txt + URL Inspection coverage |
Common causes
1. Links render after JS hydration
React / Vue / Svelte client-side-rendered links don’t exist in the initial HTML; JS mounts the component and they appear later.
Google does render JS, but it happens in a second wave. Googlebot first indexes the raw HTML, then queues the page for the Web Rendering Service (WRS), which runs headless Chromium and executes the JS later. As of June 2026:
- The median render delay is about 5 seconds, but that median hides a long tail. Onely’s testing has found 5-50% of new JS-dependent pages still unindexed two weeks after submission.
- WRS doesn’t wait indefinitely for async work (e.g. a list rendered only after a
useEffectfetch resolves). - Under crawl-budget pressure or rendering-queue load, the second wave can lag days to weeks, so JS-only links are discovered slowly or not at all.
How to confirm:
# What Google sees on the first pass = the static HTML response
curl -sL https://yourdomain.com/page | grep -c "href=\"/article-"
# Compare to the count you see in the browser (DevTools → Elements → Cmd+F "href=")
Or use Search Console → URL Inspection → “Test live URL” → “View tested page” → “HTML” and search for your link. If it’s missing from the crawled HTML, JS is hiding it.
2. Links live inside collapsed accordions / drawers / tabs
Even with statically generated HTML, links inside display: none, a default-collapsed <details>, or a hidden Tab panel are discounted. The crawler can read the HTML, but Google has long said it weights hidden content less than visible content, and links you rely on for discovery shouldn’t depend on a click.
How to confirm: search your templates for display: none, hidden, <details>, tabpanel hidden.
3. Accidental nofollow
<a href="/article" rel="nofollow">Link</a>
Since 2020 Google treats rel="nofollow" as a hint rather than a strict directive, so it may still crawl the target — but it’s not guaranteed to, and a nofollowed internal link wastes the internal PageRank you’d otherwise pass to your own page. Internal links should never be nofollowed. Common sources of accidental nofollow:
- WYSIWYG editor default adds nofollow (many CMSes)
- UGC module auto-nofollows everything in the block
- An outbound-link template copy-pasted into internal links
How to confirm:
curl -sL https://yourdomain.com/page | grep -E 'nofollow|sponsored|ugc'
# Any output = an attribute is present; inspect which links it's on
4. Link is a button / card with JS navigation
<button onclick="location.href='/article'">View article</button>
<div data-link="/article" class="card"></div>
These aren’t <a href> elements. Google has confirmed it only follows real href links in <a> tags — onclick, data-link, and router-only navigation don’t count as links for discovery.
5. Link inside noscript or iframe
Content inside <noscript> is generally ignored, and links inside an <iframe> belong to the framed document — they don’t pass discovery or authority to the parent page.
6. Target URL blocked by robots.txt
The link is visible, but the target URL is Disallowed in robots.txt, so Google won’t crawl it. URL Inspection will report “Blocked by robots.txt” for the target.
Shortest path to fix
Step 1: Check whether your internal links survive without JS
# Pull the static HTML response (what the first crawl pass sees)
curl -sL https://yourdomain.com/your-page > raw.html
# Count <a href> links
grep -oE '<a [^>]*href="[^"]+"' raw.html | wc -l
# Compare to the browser count (DevTools → Elements → Cmd+F "href=")
A big delta means most links are JS-rendered and discovery is unreliable.
Step 2: Move critical internal links to SSR / SSG
In Next.js, render the links on the server, not in a client useEffect:
// Wrong: useEffect fetch, then render — links exist only after hydration
function Related() {
const [items, setItems] = useState([]);
useEffect(() => { fetch('/api/related').then(r => r.json()).then(setItems); }, []);
return items.map(i => <a href={i.url}>{i.title}</a>);
}
// Right: getStaticProps / getServerSideProps — links are in the HTML response
export async function getStaticProps() {
const items = await getRelated();
return { props: { items } };
}
function Related({ items }) {
return items.map(i => <a href={i.url}>{i.title}</a>);
}
In the App Router, keep the component a Server Component (no "use client") so the markup ships in the HTML. Astro is SSG by default — no issue. Vue: use Nuxt useAsyncData. Svelte: use a SvelteKit load function.
Step 3: Expand critical links out of collapsed / Tab containers
Switch the “related articles” module from <details> to a default-open <section>. Do the same for core navigation hidden inside Tab panels. If the design demands collapse, at least emit all links in the HTML and control visibility with CSS — don’t drop them from the DOM while collapsed.
Step 4: Audit rel="nofollow"
# Scan your source for nofollow on links
rg 'rel="[^"]*nofollow' src/
Internal links should not carry nofollow; reserve it (or sponsored / ugc) for the links it’s actually meant for. Fix the source: stop the CMS WYSIWYG from adding nofollow by default, and scope UGC nofollow to user-submitted content only, not template-defined related links.
Step 5: Switch every clickable element to <a href>
<!-- Wrong -->
<button onclick="location.href='/article'">View</button>
<div data-link="/article" class="card">...</div>
<!-- Right -->
<a href="/article" class="button">View</a>
<a href="/article" class="card">...</a>
If you need a button’s look, style an <a> to look like one — keep the real href.
Step 6: Verify with Search Console URL Inspection
After fixes: Search Console → URL Inspection → enter the page URL → “Test live URL” → “View tested page” → “HTML” and Cmd+F your target internal link. If it’s in the crawled HTML, Google can see it. Then click “Request indexing” on the target page to nudge re-crawl.
How to confirm it’s fixed
- Crawled HTML contains the link (URL Inspection, live test) — the definitive check, available immediately.
- The target’s coverage moves from “Discovered – currently not indexed” toward “Crawled” then “Indexed.”
- The Internal links → Top linked pages count rises. This is the slowest signal: it’s a delayed sample, so allow 1-2 weeks (longer if you’re checking during a report outage like the May-June 2026 one). Don’t treat a still-zero count here as proof the fix failed if checks 1 and 2 already passed.
Prevention
- Critical internal links always SSR / SSG — never client-side fetch only.
- Use real
<a href>— noonclick/data-linkpseudo-links. - CI runs a no-JS spot check:
curlthe static HTML and assert the critical internal-link count is>= N. - nofollow only on sponsored external links / UGC; templates never default-add it.
- Collapse / Tab designs go through SEO review: can core navigation default-expand?
FAQ
Search Console suddenly shows 0 internal links across my whole site. Did I break something? Probably not, if it happened in late May 2026. The Links report broke on May 21, 2026 and only returned fresh data on June 12, 2026. Check whether your drop matches that window before changing code. Outside that window, a site-wide zero is unusual and worth investigating.
Does Google really not render JavaScript? It does, but in a deferred second wave via the WRS. The median delay is around 5 seconds, but a meaningful tail of pages waits days to weeks, and 5-50% of JS-dependent pages can stay unindexed two weeks after submission. For links you depend on for discovery, ship them in the server HTML.
Are nofollow internal links ignored completely? Since 2020 nofollow is a hint, so Google may still crawl the target — but it’s not guaranteed, and you waste the internal authority you’d otherwise pass. Never nofollow your own internal links.
Why is the count in Search Console lower than the number of links I actually have? The Links report is an explicit sample, not an exhaustive list, and it lags by days. A lower number doesn’t mean Google missed links; confirm individual links with URL Inspection instead.
My links are real <a href> and server-rendered, but the target still says “Discovered – currently not indexed.” Why?
Discovery worked; indexing is a separate decision. That status usually means crawl-budget or quality reasons, not a link problem. Strengthen internal linking from already-indexed pages and request indexing on the target.
How long until the Internal links report reflects my fix? Typically 1-2 weeks, because it’s a delayed sample. Don’t wait on it to validate the fix — use URL Inspection’s crawled HTML, which updates immediately.
Related
External references: Google: Links report, Google: Fix Search-related JavaScript problems, Google: Qualify outbound links (nofollow / sponsored / ugc).
Tags: #SEO #Google #Search Console #Indexing