Internal Link Opportunity Mapper
Crawls the site, embeds every page, and builds the internal link graph to find semantically related pages that are not…
Updated
Use this skill
$ npx skills add seoskills.sh/internal-link-optimizerAbout this skill
Internal Link Opportunity Mapper is a Content and Writing skill for AI agents, published in the seoskills.sh catalog. Reach for it when your work involves content briefs from SERP intent, editorial planning, and SEO writing. Install it with one command and it runs inside your own agent, so the work happens in your workflow, not a separate SEO tool.
SKILL.md
Internal Link Opportunity Mapper
AGENT ROLE: Autonomous internal-linking agent. Build the site's page-similarity matrix and existing link graph, find high-similarity unlinked pairs, and emit ranked recommendations per references/output.schema.json.
OBJECTIVE
Recommend the highest-value missing internal links: pairs of pages that are semantically related but not currently linked, prioritized by relevance and the target page's link deficit — plus surface orphan pages.
INPUTS
start_url(REQUIRED): crawl seed; host defines scope.max_pages(OPTIONAL, default 1000).similarity_threshold(OPTIONAL, default 0.75): cosine floor to call two pages "related".max_recommendations(OPTIONAL, default 200).embedding_backend(OPTIONAL enumopenai|tfidf): defaultopenaiif a key is set, else localtfidf.
AUTHENTICATION
- Crawl: keyless HTTPS GET, UA
seoskills-internal-links/1.0, honor robots. openaibackend: REQUIRE envOPENAI_API_KEY; endpointPOST https://api.openai.com/v1/embeddings(modeltext-embedding-3-small). IF unset THEN fall back to localtfidfcosine and noteembedding_backend="tfidf".
EXPECTED TOOL CALLS
- Run
scripts/internal_links.py --start {url} --max 1000. - BFS crawl (same host); per page store main text + outbound internal links; then embed each page's text.
PROCEDURE (deterministic)
STEP 1 — CRAWL (bounded BFS), capturing per page: {url, title, main_text, internal_links_out}.
STEP 2 — EMBED each page's title + main_text (OpenAI batch, or local TF-IDF vectors).
STEP 3 — EXISTING GRAPH: build the set of directed internal links already present.
STEP 4 — CANDIDATES: for every unordered page pair with cosine >= similarity_threshold, IF neither direction is already linked THEN it is a candidate.
STEP 5 — DIRECTION + PRIORITY: recommend linking FROM the higher-authority/older page TO the one with the larger link deficit (fewer inbound internal links). priority = cosine * (1 / (1 + inbound_links(target))).
STEP 6 — ANCHOR: propose an anchor from the target page's title / most salient shared n-gram present in the source's text.
STEP 7 — ORPHANS: list pages with 0 inbound internal links. EMIT recommendations sorted by priority desc.
RATE LIMITS & ERROR HANDLING
- Crawl politeness: ≤ 5 concurrent, ≥ 200ms between same-host requests, obey robots
Crawl-delay. HARD stop atmax_pages(hit_cap=true). - OpenAI embeddings
429→ honorRetry-Afterelse backoff2^attempt(max 5); on persistent failure switch totfidfand setembedding_backend="tfidf"(never fail the whole run for embeddings). - Per-page fetch failure → skip; a page needs ≥ 100 words to be embedded (else excluded, listed in
skipped).
MISSING / INSUFFICIENT DATA
- IF fewer than 5 embeddable pages THEN STOP
error.code="INSUFFICIENT_PAGES"(nothing meaningful to link). - Never recommend a link that already exists in either direction; never recommend self-links.
- Anchor text must appear in the source page's vocabulary; if none fits, return the target title and mark
anchor_confidence="low".
OUTPUT
One JSON object per references/output.schema.json. No prose.
FILES
scripts/internal_links.py— crawler, embeddings/TF-IDF cosine, candidate ranking, anchor suggestion.references/output.schema.json— output contract.
Not using the CLI? Copy the SKILL.md and paste it straight into ChatGPT, Claude, or any agent.
Embed a badge
Install into your agent
More in Content and Writing
brief
Produce an editor-ready content brief for a target keyword or topic. Use when the user asks for a content brief, writing guidelines, article outline, SEO brief, what to include in a blog post, or how to structure content for a keyword. For choosing which topics to write about, see find-keywords. For a full site-wide SEO audit, see audit.
seo-content
Content quality and E-E-A-T analysis with AI citation readiness assessment, plus last-mile draft cleanup (AI-typical phrasing and invisible Unicode watermark characters). Use when user says "content quality", "E-E-A-T", "content analysis", "readability check", "thin content", "content audit", "humanize", "AI phrasing", "remove watermarks", or "invisible characters".
seo-content-brief
Generate competitive SEO content briefs with per-section word counts, competitor scoring, keyword density guidance, and page-type templates. Supports both new page briefs and improve-existing-page briefs. Use when user says "content brief", "write a brief", "content outline", "blog brief", "service page brief", "brief for", "writing brief", "content plan", or "outline for".
seo-content-optimizer
No description available.
seo-content-auditor
Analyzes provided content for quality, E-E-A-T signals, and SEO best practices. Scores content and provides improvement recommendations based on established guidelines.
Content Decay Predictor
Builds per-URL clicks and impressions time-series from Search Console, fits a trend to detect sustained decline and inf…