> For the complete documentation index, see [llms.txt](https://help.seoutils.app/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://help.seoutils.app/guide/google-search-console/internal-links.md).

# Internal Links

**Internal Links** finds the pages on your site that would benefit from more links pointing at them, then proposes a specific sentence on a specific page to add each link to. You review every suggestion, and nothing reaches your site until you accept it.

The tool works in three stages:

* **Read your pages** — a crawler visits the URLs in your sitemap and records every link, where it sits on the page, and the text it could suggest links from
* **Prepare the topics** — each page becomes a vector, so the tool can tell which pages cover the same subject
* **Find the links** — for each page you choose, the closest pages are read again and one sentence per link is proposed, with the exact words to turn into the link

<figure><img src="https://1176579443-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F2DwV6sJBiKjUHMDggb4d%2Fuploads%2Fz2dFd0w7cGASJFoBZXBu%2FXnapper-2026-09-22-19.08.43.png?alt=media&amp;token=6256b62a-99b3-43f0-bc22-a0b152fb19c4" alt=""><figcaption><p>The Internal Links page showing the Opportunities and Suggestions tabs</p></figcaption></figure>

{% hint style="info" %}
Only links in the **main content** count as body links. Menus, headers, footers and sidebars are recorded but never counted as an editorial link, because they appear on every page and tell search engines nothing about a specific page.
{% endhint %}

***

## What You Need Before You Start

| Requirement                                                          | Why it is needed                                    | Cost                                                |
| -------------------------------------------------------------------- | --------------------------------------------------- | --------------------------------------------------- |
| A connected Google Search Console property with at least one sitemap | The crawler reads the URLs listed in your sitemaps  | Free                                                |
| **Embeddings** turned on for Internal Links                          | Lets the tool tell which pages cover the same topic | A few cents for a whole site, once per changed page |
| A **TypeSafe API key**                                               | Chooses the sentence and the words to link          | A few cents per run                                 |
| A **WordPress connection** (optional)                                | Writes accepted links into your pages automatically | Free                                                |

Without a TypeSafe key you can still crawl your site, embed your pages, and read every list in the Opportunities tab. Only the link suggestions need it.

***

## Getting Started

When you open Internal Links on a property that has never been crawled, the page shows three numbered steps instead of empty tables. Work down them in order.

{% stepper %}
{% step %}

#### Read your pages

Click **Run the crawler**. The crawler opens each URL in your sitemap and records its links and its text.

Progress appears at the top of the page as **"Crawling… 24/99 URLs"**. The crawler paces itself so it never overloads your server — at the default of one request per second, expect roughly **60 pages per minute**, so a 2,000-page site takes about half an hour.

You can leave the page while it runs.

<figure><img src="https://1176579443-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F2DwV6sJBiKjUHMDggb4d%2Fuploads%2F6b3OqlfmycZVC5JQw6vR%2FXnapper-2026-09-22-19.18.35.png?alt=media&amp;token=93b9123c-b0a7-43ae-ac10-25aeda3396c4" alt=""><figcaption><p>The three-step get-started panel on a property that has not been crawled</p></figcaption></figure>
{% endstep %}

{% step %}

#### Prepare the topics

If embeddings are not yet on for Internal Links, click **Choose a model** and turn them on.

Go to **Settings → Embeddings**, enable the master switch, then enable **Internal Links pages** and pick a model. Your choice here is independent of the model used for Search Console queries — the two features never share vectors.

<figure><img src="https://1176579443-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F2DwV6sJBiKjUHMDggb4d%2Fuploads%2FKjzG0IbTcSOgaxia0FIH%2FXnapper-2026-09-22-19.11.22.png?alt=media&amp;token=45f103c0-6f32-40b2-8bc8-e0c89062b9c7" alt=""><figcaption><p>Embedding settings with Internal Links pages enabled</p></figcaption></figure>
{% endstep %}

{% step %}

#### Find the links

Click **Find links** to open the run dialog, choose the pages you want links pointing at, and start the run.

Suggestions appear in the **Suggestions** tab when the run finishes.
{% endstep %}
{% endstepper %}

{% hint style="success" %}
**Pull your query data first.** Use **Pull query data** when the page offers it. With the searches each page ranks for, the tool prefers source pages that rank for the same searches, offers those searches as link text, and tells you which search a sentence matches. Without it, the run works on page similarity alone.
{% endhint %}

***

## The Opportunities Tab

Five lists, each answering a different question about your internal linking. Every list can be searched, sorted and paged.

<figure><img src="https://1176579443-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F2DwV6sJBiKjUHMDggb4d%2Fuploads%2FLXB8qhMJBp8e7tfAVanA%2FXnapper-2026-09-22-19.09.09.png?alt=media&amp;token=63cd8b79-bc59-4380-8d94-b1299331d096" alt=""><figcaption></figcaption></figure>

### Priority targets

Pages ranking between **position 4 and 20** with enough impressions and few body links pointing at them — the pages where one more internal link is most likely to move something. A page on page two of the results needs a smaller push than a page nobody can find.

| Column                | Meaning                                                   |
| --------------------- | --------------------------------------------------------- |
| **Page**              | The page that could use more links                        |
| **Position**          | Its average position over the last 28 days                |
| **Impressions (28d)** | How often it appeared in results                          |
| **Body links in**     | Links pointing at it from the main content of other pages |
| **Top query**         | The search it gets the most impressions for               |

Each row carries two controls:

* **Page type** — set what kind of page this is. Marking a page **legal**, **contact** or **utility** keeps it out of suggestions entirely, in both directions.
* **Sources** — opens a panel listing the pages whose content is closest to this one, with a similarity score for each. This costs nothing and needs no TypeSafe key.

{% hint style="info" %}
If no page on your site has enough Search Console data yet, this list changes to **Fewest links in** and ranks by how few body links each page receives instead.
{% endhint %}

### Orphans

Crawled pages that **no other page links to from its main content**. A menu or footer link does not save a page from this list — those appear on every page and carry no editorial signal.

Orphan pages are the clearest internal linking problem you can fix, and they are often pages that were published and then forgotten.

### Anchors

How varied the link text pointing at each page is. **Low diversity** means most links to that page use the same words.

| Column               | Meaning                                         |
| -------------------- | ----------------------------------------------- |
| **Body links in**    | Total editorial links pointing at the page      |
| **Distinct anchors** | How many different phrases are used             |
| **Diversity**        | Distinct anchors as a percentage of total links |
| **Most used anchor** | The phrase used most, and how often             |

Below it, a second table lists **the same anchor used more than three times for one page**. Repeating one exact phrase across many links looks deliberate rather than natural.

### Too many links

Pages with more body links than your cap allows. These pages are **never used as link sources** — the tool will not add an eleventh link to a page already carrying ten.

### Duplicate links

Pages that link to the same page more than once from their main content. The first link is the one readers use; the rest add nothing.

***

## Finding Links

Click **Find links** to open the run dialog. It answers two questions: **which pages** get links pointed at them, and **what that costs**.

<figure><img src="https://1176579443-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F2DwV6sJBiKjUHMDggb4d%2Fuploads%2FU1eOh78rnzce6ci8aOBX%2FXnapper-2026-09-22-19.12.43.png?alt=media&amp;token=915fc935-17fc-474b-9ecf-4dd5f6302a6c" alt=""><figcaption><p>The Find internal links dialog with target pages chosen and the cost estimate</p></figcaption></figure>

### Choosing the target pages

Two lists to choose from:

{% tabs %}
{% tab title="Best opportunities" %}
The priority targets — pages ranking in your chosen position range with enough impressions. This is the default, and the right choice most of the time.

Quick picks (**First 10**, **First 25**) appear when the list is long enough for them to mean something.
{% endtab %}

{% tab title="Every page" %}
Every crawled page that can receive links, with the ones receiving the fewest first.

Use this for a page with **no search data yet** — a page you published last week can never reach the priority list, however much it needs links. A filter box helps you find it by title or path.
{% endtab %}
{% endtabs %}

One run takes at most **50 target pages**. The header tells you how many you have chosen, and the checkbox beside it selects or clears everything listed.

### Reading the cost

The estimate leads with the total you might spend:

| Line                            | What it covers                                                                                 |
| ------------------------------- | ---------------------------------------------------------------------------------------------- |
| **Embedding pages**             | Turning page text into vectors. Happens once per page, then only again when that page changes. |
| **Reading pages for sentences** | Reading the shortlisted source pages and choosing the sentences. This is the larger half.      |

{% hint style="warning" %}
The figure is quoted as **"up to"** on purpose. It is the most a run of this size has cost in testing; the real price depends on how much text your pages have, and shorter pages come in well under it. Recent runs have landed at roughly **half** the quoted ceiling.
{% endhint %}

The cost grows with the number of target pages, because each target has its own shortlist of source pages to read. Choosing 25 pages costs roughly five times what choosing 5 does.

### Embed pages only

This button runs the **first stage alone** and stops: your pages are embedded, no suggestions are made, and nothing is spent at TypeSafe. It appears only when there are pages left to embed.

Use it to prepare a large site now and find links later, or to work before you have a TypeSafe key.

{% hint style="info" %}
You never have to press it to keep things current. **Every** Find links run embeds whatever is new or changed before it starts looking, so a page you edited last night is re-read automatically.
{% endhint %}

***

## Reviewing Suggestions

The **Suggestions** tab groups proposals by the page they link **to**. Each one shows the source page, the exact sentence, the words that would become the link, and why the tool chose it.

The reason is highlighted under each sentence. When the target has search data, it names the search the page ranks for, with its position and impressions — for example *Ranks #2.5 for "serving per container" (28 impressions, 31 days to Sep 20)*.

<figure><img src="https://1176579443-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F2DwV6sJBiKjUHMDggb4d%2Fuploads%2FtQ9M6D1Xcr4Xg37iTkCv%2FXnapper-2026-09-22-19.13.41.png?alt=media&amp;token=cb875b38-aeac-4a66-aa97-a8623a794e0f" alt=""><figcaption><p>Suggestions grouped by target page, each with its sentence and proposed anchor</p></figcaption></figure>

### Available actions

Every suggestion has an **Actions** menu. It lists only the actions that fit the suggestion's current state.

| Action                  | What it does                                                                                                                |
| ----------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| **Accept & apply**      | Accepts the suggestion and writes the link into the page on WordPress in one step. Needs a WordPress connection.            |
| **Accept**              | Reserves the link against your caps. Nothing is written to your site yet.                                                   |
| **Apply to WordPress**  | Writes an accepted link into the page.                                                                                      |
| **Change link text**    | Choose different words from the same sentence. The sentence itself is never rewritten.                                      |
| **Back to review**      | Returns an accepted, rejected or reverted suggestion to the **To review** tab.                                              |
| **Reject**              | Moves it to the **Rejected** tab. That sentence is not suggested again for the same pair of pages unless you bring it back. |
| **Revert on WordPress** | Removes an applied link from the page.                                                                                      |
| **Apply again**         | Writes a reverted link back into the page.                                                                                  |

The three tabs — **To review**, **Accepted** and **Rejected** — hold suggestions at each stage:

| Tab           | Actions in the menu                                                                                                                                         |
| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **To review** | **Accept & apply**, **Accept**, **Change link text**, **Reject**                                                                                            |
| **Accepted**  | **Apply to WordPress**, **Change link text**, **Back to review**, **Reject** — then **Revert on WordPress** once applied, or **Apply again** after a revert |
| **Rejected**  | **Accept**, **Back to review** — a rejection is never final                                                                                                 |

To act on several suggestions at once, tick their checkboxes. The buttons above the list change to match: **Accept**, **Accept & apply** and **Apply** for the selected rows, or **Revert** for applied ones.

{% hint style="info" %}
Accepting is not publishing. An accepted link waits in the **Accepted** tab until you write it to WordPress or export it.
{% endhint %}

{% hint style="warning" %}
Anything that changes your live site asks first. **Accept & apply**, **Apply to WordPress**, **Apply again** and **Revert** each open a confirmation that lists every link it will change, as the source page and the link text.
{% endhint %}

### Changing the link text

Choose **Actions → Change link text** to pick different words from the same sentence. You choose the link text with two clicks: its first word, then its last word.

1. Click the **first** word of the link text.
2. Click the **last** word. Every word in between is included. To link a single word, click the same word twice.
3. Click **Save**.

A line above the words always tells you which click comes next. To start over, click a new first word. The link text can have up to the **Maximum words in the link text** setting (6 by default); a last word further away than that is refused.

You can also pick one of the **Suggested** phrases instead.

### More suggestions for the same page

Each target page shows its three best source pages first. The others wait in a queue and are not shown yet. The group header says how many are queued — for example **3 suggestions · 12 more waiting**.

<figure><img src="https://1176579443-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F2DwV6sJBiKjUHMDggb4d%2Fuploads%2FfZ2JId1J5I3AfsIodmZJ%2FXnapper-2026-09-22-19.14.18.png?alt=media&amp;token=4103b0a0-85c1-4cdc-90f0-ee0da7f73aaa" alt=""><figcaption></figcaption></figure>

A queued suggestion appears **only when you accept or reject** a suggestion shown for the same target page:

1. Click **Accept** or **Reject** on a suggestion.
2. It leaves the **To review** tab.
3. The next source page from the queue appears at the bottom of the group, and the "more waiting" count goes down by one.

When you reject a sentence and the same source page has another good sentence, that sentence is offered first, before the queue moves.

{% hint style="info" %}
Queued suggestions are not revealed any other way. Review the ones shown to see the next ones.
{% endhint %}

***

## Applying Links to WordPress

If your property has a WordPress connection, accepted links can be written into your pages directly.

{% stepper %}
{% step %}

#### Connect WordPress

Open **Actions → Rules** and choose this property's WordPress connection under **WordPress connection for applying links**.
{% endstep %}

{% step %}

#### Accept the suggestions you want

Work through the **To review** tab. Accepted suggestions collect in the **Accepted** tab.

To accept and publish in one step, choose **Actions → Accept & apply** instead and skip the next step.
{% endstep %}

{% step %}

#### Apply

In the **Accepted** tab, choose **Actions → Apply to WordPress** on a suggestion, or tick several and click **Apply** above the list. Confirm, and each chosen sentence has its link text wrapped in a link. Nothing else on the page is touched.
{% endstep %}
{% endstepper %}

### Reverting

Every applied link can be reverted. The sentence returns to exactly what it was before the link was added.

To revert, choose **Actions → Revert on WordPress** on an applied link, or tick several and click **Revert** above the list.

A reverted link stays in the **Accepted** tab. Choose **Actions → Apply again** to write it back into the page, or **Back to review** to reconsider it. Applying again re-checks your caps first, so it is refused if the page has since reached its link limit or already links to the same page.

{% hint style="warning" %}
If the page changed on your site after the link was applied, the status becomes **Page changed** and the link is not reverted automatically — the tool will not edit a sentence it no longer recognises. Fix those by hand.
{% endhint %}

### When an apply or revert is not confirmed

If a write to WordPress is cut off — the connection drops, or the app closes mid-way — the tool cannot tell whether the change reached your site. The link's status then reads **Apply not confirmed** or **Revert not confirmed**, and a **Check N unconfirmed** button appears above the **Accepted** list.

Click it to read those pages on WordPress and settle each link's status. Nothing is sent to your site. The button only appears when there is something to check.

***

## Settings

All settings for this tool live on the property's settings page. Open **Actions → Rules** from the Internal Links page, or go to the property's settings and use the sidebar.

### Internal link rules

| Setting                                     | Default | What it controls                                                                          |
| ------------------------------------------- | ------- | ----------------------------------------------------------------------------------------- |
| **Maximum body links per page**             | 10      | Pages at this number are not used as link sources                                         |
| **Same anchor to the same page, site-wide** | 3       | An anchor already used this often for a page is not suggested again                       |
| **Paragraphs to skip at the top**           | 1       | No link is suggested in the opening paragraphs                                            |
| **Source pages shortlisted per target**     | 25      | How many related pages are read for each target. **Lower this to cut the cost of a run.** |
| **Priority position from / to**             | 4 to 20 | The ranking range that makes a page a priority target                                     |
| **Minimum queries per page**                | 3       | Fewer than this counts as too little search data                                          |
| **Minimum impressions per page (28 days)**  | 10      | Fewer than this counts as too little search data                                          |

Each field shows its allowed range under it. A value outside the range is marked in red, and **Save** stays disabled until it is fixed.

Three rules cannot be changed:

* One link per target page on each source page
* Anchors are words already in the sentence — the text is never rewritten
* Pages built with a page builder (Elementor and similar) are never edited

### Advanced settings

Click **Advanced** at the bottom of the rules card to open these. The defaults suit most sites; change them when the suggestions are consistently too many, too few, or use link text you do not like.

| Setting                              | Default | Range | What it controls                                                                                                                                                 |
| ------------------------------------ | ------- | ----- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Minimum sentence confidence (%)**  | 50      | 10–95 | How sure the AI must be that a sentence is a good place for the link. Lower it to see more suggestions; raise it to see only the clearest ones.                  |
| **Minimum link text confidence (%)** | 50      | 0–95  | How sure the AI must be of the words it picked as the link text. Unsure picks are usually words about a broader topic than the page. **0** turns this check off. |
| **Minimum words in the link text**   | 1       | 1–10  | Set **2** or more to never get a one-word link text.                                                                                                             |
| **Maximum words in the link text**   | 6       | 1–10  | The longest link text the AI may pick. Also the most words you can choose when you edit a link text.                                                             |

**Reset numbers to defaults** puts these four back. It does not clear your own rules below.

{% hint style="info" %}
Settings apply to the **next** Find links run. Suggestions already in the list keep the settings they were made with — run **Find links** again for the same pages to see the effect.
{% endhint %}

### Your rules for the AI

Below the numbers, two boxes let you give the AI rules of your own, written as plain sentences:

* **Your rules for choosing the sentence** — where a link may go.
* **Your rules for choosing the link text** — which words may become the link.

Write one rule per line, up to 5 rules per box and 200 characters per rule. Your rules are added to the tool's built-in rules; they never replace them.

Examples of useful rules:

* ✅ Never use a broader topic as link text, e.g. "nuts" for a page about cashews.
* ✅ Brand names are always two words.
* ✅ Do not put a link in a sentence that is a question.

Rules that do not work well:

* ❌ Always suggest a link. *(The AI still drops sentences that do not fit; a rule cannot force a link.)*
* ❌ Write a better sentence. *(The tool never rewrites your text, so the AI cannot follow it.)*

{% hint style="warning" %}
A rule can make suggestions better or worse, and the app cannot tell which. Your rules are also sent with every question the AI is asked, so each run costs a little more — one rule of about 100 characters adds roughly 3%, and the estimate in the Find links dialog includes it. Try a new rule on a few pages first and compare the results before running it on many.
{% endhint %}

<figure><img src="https://1176579443-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F2DwV6sJBiKjUHMDggb4d%2Fuploads%2FOLnTfsaRpcgsxFW4ugfu%2FXnapper-2026-09-22-19.15.05.png?alt=media&amp;token=57210c74-ee57-4040-849a-a17f2b549722" alt=""><figcaption><p>The Advanced section of the Internal Links rules, with the confidence and link text settings and your own rules for the AI</p></figcaption></figure>

### Link crawler

Under **Crawling** on the same settings page:

| Setting                 | Default | What it controls                                                                                           |
| ----------------------- | ------- | ---------------------------------------------------------------------------------------------------------- |
| **Requests per Second** | 1       | How fast the crawler visits your pages. Range 1–3. Raise it for your own site; keep it low for a client's. |
| **Max Chrome Tabs**     | 3       | How many pages load at once, within the rate above. Range 1–3.                                             |
| **Auto-Crawl Schedule** | Weekly  | How often the crawler runs by itself: Weekly, Bi-weekly, Monthly, or Manual Only                           |

{% hint style="info" %}
A scheduled crawl updates your page text but does not embed it. The new text is embedded the next time you run **Find links**, so a scheduled crawl never spends money on its own.
{% endhint %}

You can also start a crawl at any time from **Actions → Run link crawler**.

***

## Troubleshooting

<details>

<summary>The Find links dialog only offers a handful of pages</summary>

The default list is **priority targets**, not every page. A page only reaches it by ranking between positions 4 and 20 with enough impressions, so a site with little Search Console data will have very few.

Two ways forward:

1. Switch to **Every page** in the dialog to choose from every crawled page.
2. Widen the range in **Rules** — lower **Minimum impressions per page** or stretch the **Priority position** range.

</details>

<details>

<summary>"Turn on embeddings for Internal Links"</summary>

The tool cannot tell which pages share a topic without page vectors.

1. Go to **Settings → Embeddings**.
2. Turn on the master switch.
3. Enable **Internal Links pages** and choose a model.
4. Return to Internal Links and run again.

</details>

<details>

<summary>"No TypeSafe API key"</summary>

Link suggestions need a TypeSafe key. Add one under **Settings → Services → AI Era**.

Everything else — crawling, embedding, all five Opportunities lists and the Sources panel — works without it.

</details>

<details>

<summary>A page I want links for is not in any list</summary>

Check these in order:

1. **Is it in your sitemap?** The crawler only reads URLs listed there.
2. **Has it been crawled?** The **Pages crawled** tile shows the count.
3. **Is its page type excluded?** Legal, contact and utility pages are never used as sources or targets. Change the type from the **Page type** control on a Priority targets row.
4. **Is it over the link cap?** Pages with too many body links are excluded as sources, though they can still receive links.

</details>

<details>

<summary>The estimate says a run will cost more than expected</summary>

The cost is driven by **source pages read**, not target pages chosen. Each target has its own shortlist — at the default of 25, choosing 10 targets means reading up to 250 pages.

Lower **Source pages shortlisted per target** in Rules to reduce it. Dropping it from 25 to 10 cuts the reading cost by about 60%, at the price of fewer candidate sources per page.

</details>

<details>

<summary>A suggestion shows "No search data"</summary>

That suggestion was chosen on page similarity alone, without the searches each page ranks for.

Use **Pull query data** on the Internal Links page, then run again. Suggestions will then prefer source pages that rank for the same searches and explain which search each sentence matches.

</details>

<details>

<summary>Link text uses a word that is too broad</summary>

For example, "nuts" as the link text for a page about cashews. This usually means the AI was unsure of its pick.

1. Keep **Minimum link text confidence** at 50 or raise it. Most broad picks fall below 50.
2. Add a rule under **Your rules for choosing the link text**, such as *Never use a broader topic as link text.*
3. Run **Find links** again for the same pages.

</details>

<details>

<summary>Too few suggestions, or a page gets none</summary>

The AI only suggests sentences and link text it is sure enough about.

1. Lower **Minimum sentence confidence** (for example to 40) to allow more sentences.
2. Lower **Minimum link text confidence**, or set it to 0 to turn that check off.
3. Check **Minimum words in the link text** — a high minimum removes many choices.
4. Review your own rules — a strict rule can remove most choices.

</details>

<details>

<summary>A one-word link text</summary>

Set **Minimum words in the link text** to 2 in the Advanced settings. For a single suggestion, click the edit button and pick more words from the same sentence.

</details>

***

## Related Guides

{% content-ref url="/pages/GEScTVAkP5gZtYV3mNYz" %}
[Embedding Database](/guide/embedding-database.md)
{% endcontent-ref %}

{% content-ref url="/pages/Ow9upwg0tyWfwpI0MBPb" %}
[Indexing Dashboard](/guide/google-search-console/indexing-dashboard.md)
{% endcontent-ref %}
