Internal link platform
How to use it
- Run an analysis. It reads your crawl and your content to find pages that should link to each other.
- Review the suggestions. Each row shows the source page, the target, the proposed anchor text, and the target's value.
- Apply the ones you want — individually, or in bulk as a background job.
- Set a policy if you are going to work in bulk. The defaults are sensible; the point is that a batch cannot quietly breach them.
- Come back for the impact panel once the links have had time to be crawled.
⏱ ~10 min per pass · 💳 Starter+ · 🎯 Move link equity to the pages that earn
What gets linked, and where
| Surface | Written into | Notes |
|---|---|---|
| Product | Description HTML | The most common case |
| Collection | Description HTML | |
| Blog post | Article body | |
| Page | Page body |
The source type is determined from the URL rather than from a stored label,
because older suggestion rows can carry a stale classification — a /blogs/…
URL is a blog article regardless of what the row says it is.
An internal link is written as /products/winter-throw, never
https://…/products/winter-throw.
The reason is concrete. Suggestion targets come from crawled page URLs. If a
crawl ran against the .myshopify.com mirror, every absolute URL written into a
product description would point customers and Google at the mirror —
permanently, inside your live product HTML, long after the crawl that caused
it was forgotten. Root-relative links resolve correctly on whatever domain the
page is served from, so a wrong-host crawl becomes merely unhelpful instead of
destructive.
Off-domain targets are refused. When the platform cannot confirm which host is yours — a failed lookup, a throttled API call — it declines the write as retryable and records nothing, rather than guessing.
Ranking: which link is worth making
Suggestions are ranked by the value of the target page, not by keyword similarity alone. The value model blends:
- Search Console clicks, impressions and position for the target
- Attributed revenue where available
- Click depth — how many clicks from the home page the target sits at
- Whether the target is actually indexable
Depth is read as a real number, so depth 0 is the home page, not "unknown". Target quality is read from the crawl: robots directives, canonical status, status code. A target that is missing from the crawl is marked unknown, never "not indexable" — the difference matters when you are deciding whether to link to it.
Orphans and depth distribution
An orphan is a page nothing links to. The orphan panel lists them alongside the distribution of click depth across your site, which is usually the more actionable of the two: a store where 60% of products sit at depth 5 has a structural problem that fixing twelve orphans will not solve.
Policy guardrails
Guardrails exist because bulk application is where internal linking goes wrong. Each is set per store:
| Guardrail | Default | What it prevents |
|---|---|---|
| Inbound per target per week | 10 | A single "money page" absorbing hundreds of links in one run |
| Outbound per source | 8 | A product description turning into a link farm |
| Repeated anchor cap | 30% | The same anchor phrase used over and over across the site |
| Block off-domain | On | Any target outside your domain |
| Block non-indexable | On | Linking to pages Google will not index |
| Max depth | — | Linking to pages buried too deep to be worth it |
| Minimum target value | — | Spending link equity on pages that earn nothing |
The important property is that a batch cannot breach a budget that each row respected individually. When 40 suggestions each point at the same target, all 40 individually pass a limit of 10 — so bulk evaluation carries a running tally and stops at the tenth.
The same rules are evaluated in three places — the list you are looking at, a single apply, and the background worker — so what the tab greys out is what the worker will actually refuse.
When the platform cannot load your current link tallies, empty tallies would read as "no links yet" and wave every guardrail through. Bulk runs and single applies both fail closed in that case, and the scheduler skips the cycle rather than proposing against unknown budgets.
Applying in bulk
Bulk application is a tracked background job, not something that happens inside your browser request. Kinds:
| Kind | What it does |
|---|---|
| Preview | Dry run — evaluates everything, writes nothing |
| Propose | Moves suggestions to proposed for review |
| Approve | Approves proposed suggestions |
| Apply | Writes the links into live content |
Writes are spaced out, one run at a time per store. The tab polls the job and shows progress; if a run is already going, a second request is refused rather than queued behind it.
Undo
Undo re-reads the live page and removes the exact anchor that was applied. Only if that fails does it fall back to matching on href and text, then to "already absent", and only as a last resort to the stored whole-body snapshot — and that final fallback runs only when the current body still hashes to what was recorded at apply time. If the page has changed since, undo reports that and offers an explicit "restore anyway".
This sequence exists because the naive version — restore the snapshot — destroys every edit made after the apply, and undoing the first of two links silently reverts the second while its row still says applied.
Multi-locale
Writes reach your primary locale only. If you publish translated content, the translated bodies of your published locales are checked and reported — the platform tells you which locales are missing the link. It never rewrites a translation automatically, because a machine-inserted anchor in a language you have had professionally translated is not a fix.
Measuring what the links did
The impact panel does not simply compare clicks before and after. It snapshots a control cohort of about 25 Search Console-covered pages that are not link targets, on the same clock, and measures them first each run. The median change across that cohort is subtracted from the change on your linked pages, producing an adjusted figure.
If fewer than five comparable pages exist, the panel reports "no control" — it does not fabricate one. A number with no control group during a seasonal upswing is a story, not a measurement.
Scheduled analysis
Analysis can run on a per-store cadence. It generates suggestions and, if you enable it, proposes them.
Scheduled analysis can never apply a link. Application is always a human action. Scheduling is off by default, and a cycle where guardrail data cannot be read is skipped rather than run blind.
Governance and audit
| Action | Who can do it |
|---|---|
| Run an analysis | SEO audit permission |
| Apply a link, bulk apply, bulk propose | SEO autofix permission |
| Approve in bulk, edit policy, clear suggestions | SEO governance permission |
Clearing suggestions only deletes pending, rejected and expired rows. Applied rows are kept, because they hold the undo record for every live link — deleting them would strand real links in your content with no way to remove them. The result of a clear tells you how many were deleted and how many kept.
Rejecting a suggestion takes a reason, and every action writes to the audit history, viewable from the tab.
Plan tiers
| Capability | Free | Starter | Pro | Agency | Enterprise |
|---|---|---|---|---|---|
| Suggestions + value ranking | — | ✓ | ✓ | ✓ | ✓ |
| Apply into products and collections | — | ✓ | ✓ | ✓ | ✓ |
| Apply into blog posts and pages | — | ✓ | ✓ | ✓ | ✓ |
| Orphan + click-depth report | — | ✓ | ✓ | ✓ | ✓ |
| Surgical undo | — | ✓ | ✓ | ✓ | ✓ |
| Policy guardrails | — | ✓ | ✓ | ✓ | ✓ |
| Background bulk apply | — | ✓ | ✓ | ✓ | ✓ |
| Control-group impact measurement | — | — | ✓ | ✓ | ✓ |
| Multi-locale gap report | — | — | ✓ | ✓ | ✓ |
| Scheduled analysis | — | — | ✓ | ✓ | ✓ |
Best practices
- Fix the crawl host before applying anything. Suggestion targets come from the crawl. Root-relative writes make a wrong-host crawl survivable, not correct.
- Preview before you apply in bulk. The dry run costs nothing and shows you exactly which rows the guardrails will block.
- Lower the repeated-anchor cap if your catalogue is narrow. Thirty percent of a hundred links is thirty identical anchors.
- Link to earners, not to everything. Set a minimum target value and let the ranking do the work.
- Do not enable auto-propose on day one. Run two manual passes first, so the policy is tuned before the scheduler starts using it.
See also
- Site crawler — where the link graph and target quality come from
- Technical health — indexability, which gates link targets
- Topical clusters — hub-and-spoke linking as a content programme
- Backlink intelligence — external links, the other half of the picture