Internal links marked nofollow
What is this issue?
This check reports a page that puts rel="nofollow" on a link to another page
of the same site.
nofollow tells a search engine not to pass any ranking signal along the link,
and to treat it as a hint not to follow it. It was designed for links you cannot
vouch for — comment spam, paid placements, user-submitted content. On a link to
a page you publish yourself there is nobody to withhold trust from: the page at
the other end is yours.
For a page to pass this check:
- Its links to pages on the same site carry no
nofollowtoken.
Example: a template adds rel="nofollow" to every card in a "related
articles" block, because the block was originally built for third-party links.
Those articles are now cut off from the signal the rest of the site is passing.
There are places nofollow on an internal link is the right answer — a cart, a
login form, an endlessly recombining faceted filter — which is why this is
graded a standard defect rather than an important one, and why the finding lists
exactly which links carry it rather than telling you to remove them all.
sponsored and ugc are not reported. They are different tokens with different
meanings, and neither is what this check is about.
Why it matters
- The link stops passing anything. Internal links are how authority moves around a site. A nofollowed internal link is a route on the map with a barrier across it, and the page on the far side has one fewer way to earn its position.
- It is usually an accident. The overwhelmingly common cause is a template written for external or user-submitted links being reused for internal ones, or a plugin applying a blanket rule. Almost nobody sets out to nofollow their own navigation.
- "Sculpting" does not work. Withholding
nofollowfrom some internal links to concentrate signal on others has not worked since 2009; the signal is not redistributed, it is simply lost. - It contradicts the sitemap. A site that lists a page in its XML sitemap and then nofollows every link to it is sending two different instructions about the same page.
It is graded standard, not important. The directive has a genuine effect, but it is deliberate often enough — carts, logins, filters, print views — that this check cannot claim a measurable ranking cost in every case, which is where IMPORTANT begins. What it can do is show you every one and let you confirm each was meant.
Removing the ones that were not meant restores those routes, and the Link Integrity part of the health score with them.
How to fix it
Confirm each one was intended. Open the finding and read the list. A cart, a login, a "print this page" or a faceted filter is a legitimate place for
nofollow; a related-articles block or a breadcrumb is not.Remove the attribute from the ones that were not. For links to pages you want indexed, delete the
nofollowtoken and leave any others in place —rel="nofollow noopener"becomesrel="noopener", not an empty attribute.Fix the template, not the page. These almost always come from one component applying a blanket rule. Editing the component clears every page it renders.
Check any plugin doing it for you. SEO and comment plugins often add
nofollowto whole classes of link by configuration, including internal ones.Use the right tool for the right job. To keep a page out of the index, use
noindexon that page. To keep crawlers out of a URL pattern, use robots.txt.nofollowon a link does neither reliably and costs you the signal either way.Leave it where it belongs. Links to pages that genuinely should not be crawled — infinite filter combinations, session URLs, add-to-cart actions — are exactly what it is for.
Examples
Example 1: An ordinary internal link
Scenario: A related-article link.
Passes because: nothing stands between the two pages.
<a href="/guides/technical-seo">Our technical SEO guide</a>Example 2: A component built for external links, reused internally
Scenario: A card component that was written for a link roundup and is now used for the site's own articles.
Fails because: every card cuts its target off from the site's own signal.
<a href="/guides/technical-seo" rel="nofollow">Our technical SEO guide</a>Corrected version:
<a href="/guides/technical-seo">Our technical SEO guide</a>Example 3: A security attribute that should stay
Scenario: A link that opens a new tab and was given the whole set of tokens by habit.
Fails because of nofollow only. noopener is about browser security and
must not be removed with it.
<a href="/pricing" target="_blank" rel="nofollow noopener noreferrer">Pricing</a>Corrected version:
<a href="/pricing" target="_blank" rel="noopener noreferrer">Pricing</a>How PixyScan detects this
Reads the
relattribute on every internal link. The crawl has always parsedrelto decide what to follow; it is now stored, so it can be reported.Treats
relas a token list. It is a space-separated set of words, sonofollowhas to appear as a whole token.nofollowingandno-followare different words and are not this directive.Reports only
nofollow.sponsored,ugc,noopenerandnoreferrerare left alone — they say other things, and two of them are about security rather than ranking.Distinguishes "no rel" from "not recorded". A link inspected and found to declare nothing is a measurement. A link stored before
relwas recorded is not, and no claim is made about it in either direction. If a whole scan recorded norelat all, the absence of this finding is not a statement that the site has none.Merges duplicate anchors safely. Where a page links to the same target more than once, the tokens from every one of those anchors are combined, so a link that is plain in the header and nofollowed in the footer is still reported.
Raises one finding per page, listing the targets it nofollows.
What we store
Storage Level
Page Level
Database Table / Prisma Model
PageInternalLink. The finding itself is stored on audit_issues.details.
Fields Used
| Field | Type | Description |
|---|---|---|
| page_internal_links.url_id | String | The page that carries the link, and the page this finding is raised against |
| page_internal_links.target_url_id | String | The page being linked to |
| page_internal_links.rel | String | The link's rel as a lower-cased token list. Three states: the tokens, '' for an anchor that declares none, and NULL for a row written before the column existed |
| page_internal_links.anchor_text | String | The visible text of the link |
Stored Fields on the finding
| Field | Type | Description |
|---|---|---|
| nofollowLinkCount | Int | How many of this page's internal links carry the token |
| targets | Object[] | Up to 25 of them: target URL and anchor text |
| truncated | Boolean | Whether more targets exist than the finding lists |
| url | String | The page carrying the links |
Detection Dependencies
- Internal Links
- HTML Document — the
relattribute as written on each anchor