MediaCG
MediaCG / Plugins / Linkloom – AI Internal Linking

Linkloom – AI Internal Linking

Weaves your articles together with internal links. Some sources pick with a small Claude model and a second independent check; others are free rules - a place name, a shared tag, an earlier episode of the same story. Nothing about your site's categories, language or content is hardcoded: every source is configured after activation.

Description

News sites publish hundreds of short-lived posts that search engines crawl every day, while the long-living guides and topic pages that should earn traffic for years receive almost no internal links. Linkloom connects the two, automatically, on every publish.

Four layers of links, eight source types

  1. AI pick (forward) - a post picks one page a reader would genuinely want next. A first pass shortlists candidates by word/tag overlap and asks a small Claude model to choose one (or none); a second, independent model call checks that choice before it goes live.
  2. AI pick (backfill / reverse) - the moment a new guide is published, it searches existing posts for good matches and inserts a link to itself into them, so a brand-new page gets inbound links from day one.
  3. Place -> its guide (rule, free) - the first mention of a town, community or other named place in the text links to the guide about it. The dictionary is built automatically from your guide titles (every case form is recognised); a manual list can add or remove entries. Posts tagged as sensitive (deaths, crimes, accidents - you choose the tags and title words) link to a category/district page instead of a leisure guide.
  4. Earlier episode of the story (rule + one check, free) - for a news post, the previous report on the same story (shared category, shared tag, within N days) is shown as a "Previously:" line after the lead, confirmed by one independent AI check so unrelated stories are never linked.
  5. Topic -> its tag page (rule, free) - the first mention of one of the post's own tags links to that tag's archive page, the way large newsrooms link their topic pages. Words are derived from the tag names and can be overridden per tag.
  6. Guide <-> guide - forward and reverse versions of source 1-2 among your evergreen pages themselves, so guides stop being an island.
  7. Hub links - every guide's bottom list can end with a link to its own subcategory, which lists the whole cluster and works as a topical hub page.
  8. Manual / editorial - approve, reject or re-pick any link per post from a metabox in the editor; two Posts-list columns show live inbound/outbound counts with one click to see which posts.

How a link reaches the page

Candidates are pre-selected by stemmed word and tag overlap (works with inflected languages - developed for Ukrainian). AI sources add an independent verification pass before anything goes live, with a stricter mode for reverse sources (candidates came from word overlap alone) and an editorial mode for forward sources (the candidate was already ranked best). The anchor phrase is chosen by code, not the model, and is rejected if it isn't found verbatim in the text, crosses a sentence boundary, ends on a dangling word, or contains your site's own name or a byline. A configurable cap limits how many links are embedded in one post's text, with a fixed priority order; the rest fall back to a "read also" box or the list below the article. Post content in the database is never modified - everything is inserted at render time, so deactivating the plugin restores the site exactly as it was.

Features

  • Any number of independent link sources, each fully self-contained: its own categories (in either direction), its own AI hint or rule settings, its own confidence threshold
  • Review queue with approve / reject / re-select, or fully automatic mode, plus a dedicated "rejected by the check" tab that never needs review
  • Sensitive-content guard (tags + title words) shared by every rule source, so tragedy/crime/accident posts never get a leisure or tourism link
  • Per-source and global confidence thresholds, daily request cap (counted atomically, safe under parallel processing), cost meter
  • Background processing through WP-Cron plus an on-publish hook (rule sources fire within seconds; AI sources within minutes), with an archive backfill mode for existing content
  • Caches results; adds no queries to cached pages
  • Fully translatable; ships with a complete Ukrainian translation

Requirements

An Anthropic API key for the AI sources only - the rule sources (place, tag, hub) need no API key and no AI at all, and the thread source needs only one cheap check per candidate. Linkloom can use the key stored by the WordPress AI connector, the ANTHROPIC_API_KEY constant, or a key saved in its own settings. Typical AI cost: about $0.01 for a news post checked by two sources, about $0.10-0.30 for a newly published guide (it re-checks existing content against itself).

Privacy

For AI sources, Linkloom sends the text of published posts and the titles/excerpts of candidate pages to the Anthropic API (api.anthropic.com) to choose links. It sends no visitor data and no personal data of your users. Rule sources (place, tag, thread, hub) make no external request at all. See Anthropic's privacy policy for how they handle API data.

REST API

For external editors (e.g. cDash): the same as the Linkloom box in the post editor. Application Passwords (Basic auth, no nonce); the user needs edit_post on the post. Errors come as HTTP 400 / 403 / 404 with code and message in the site language.

  • GET /wp-json/linkloom/v1/post/{id} — settings (off_all, off_ai, off_list, no_target), manual (prev: {id, title, url, date} or null, also: up to 5 of them) and auto — the automatic picks («Chosen automatically»): link_id, target_id, title, url, anchor, block_id, block, status (auto/approved — on the site, pending/lowconf/checkfail — not shown, rejected — removed), live, confidence, reason.
  • POST /wp-json/linkloom/v1/post/{id} with JSON { "off_all": bool, "off_ai": bool, "off_list": bool, "no_target": bool, "manual_prev": id|0, "manual_also": [ids, at most 5] } — any field may be left out; applies at once (the same code as saving the box: caches purged, pages linking to the post rebuilt when «no_target» changes). Answer as GET.
  • POST /wp-json/linkloom/v1/post/{id}/repick — «Choose links again». Answer as GET plus log.
  • DELETE /wp-json/linkloom/v1/link/{link_id} — «Remove this link». Answer as GET for its post.
  • GET /wp-json/linkloom/v1/search?q=…&exclude={id} — published posts by title, address or ID: [{id, title, date, url}].

Installation

On a new site, nothing is pre-configured - every category, tag and rule is yours to set:

  1. Upload the linkloom folder to /wp-content/plugins/ and activate it. The database table is created automatically (and upgraded automatically on later plugin updates - no need to deactivate/reactivate).
  2. Open Linkloom -> Settings. Choose your regular-content categories and your evergreen-guide categories; check that an API key is detected (or paste one). List the tags and title words that mark a post as sensitive if you plan to use the place or AI sources.
  3. Open Link sources and add at least one source. Pick a Kind first (AI pick / place / earlier episode / topic), then a Mode for AI sources (forward or reverse), then the categories it applies to and, for AI/place sources, the categories it searches in. A rule source needs no hint; an AI source's "What to choose" text has the biggest effect on quality.
  4. Open Placements and tick which sources feed the in-text block and the list below the article; set the per-post cap on embedded links; optionally turn on the hub link under guides.
  5. On Overview, send a test request, then process a few posts by hand and check the Review queue. When you're happy, switch the mode to Automatic.
  6. Disable your theme's or another plugin's related-posts block if it would duplicate the list below the article.

Backfilling an existing archive: turn on the archive checkbox on Overview to let WP-Cron work through old, unprocessed posts a few at a time, or use the manual "Run now" tool to process specific posts immediately.

FAQ

Does it change my posts?

No. Links are added when the page is displayed. Deactivate the plugin and everything is back to normal.

Is this tied to one site's categories or language?

No category IDs, tag names or site name are hardcoded anywhere - everything is read from your settings and your content (guide titles, tag names, get_bloginfo()) at run time. Word-stemming rules and a few grammar patterns (used only by the place source, to recognise Ukrainian case endings) assume an inflected Slavic language; sites in other languages should still get full value from the AI, tag and thread sources.

How much does it cost?

Only the AI sources call the API. Expect roughly $0.005-0.01 per news post checked by two AI sources, and $0.10-0.30 when a new guide is published (the reverse sources re-check existing content against it). Rule sources are free. The Overview tab shows a running cost estimate and today's request count against your daily cap.

Why do many posts get no AI link?

Because the plugin prefers no link over a weak link: every AI pick goes through an independent second check before it can go live. The share of linked posts depends on how many relevant guides or tags you have - the place, tag and thread sources usually cover a large share of posts even where the AI sources find nothing.

Which post types are supported?

Standard posts and categories. Custom post types are not supported yet.

Changelog

1.16.0 (2026-10-19)

  • REST API for external editors (cDash): read and change a post's switches and hand-picked links, choose links again, remove an automatic link, search posts — linkloom/v1/post/{id}, /post/{id}/repick, /link/{link_id}, /search. Application Passwords; the same rights and the same code as the editor box.

1.15.1 (2026-10-15)

  • The «MCG Plugins» menu is now at the top of the admin menu, right under the Dashboard.

1.15.0 (2026-10-15)

  • Linkloom::add_manual_also( $post_id, $target_id ) for other MCG plugins: SearchPulse's internal linking suggestions can be sent to Linkloom as hand-picked «Read also» links (same rules as the editor box: published posts, up to 5).
Older versions (25)

1.14.0 (2026-10-12)

  • Updates now come from the MEDIA CONTENT GROUP update server (mediacg.org): new versions show up in Plugins → Updates like any other plugin, with «View details» and auto-updates.
  • Plugin URI and Author URI point to mediacg.org.

1.13.0

  • Processing window: «Process posts not older than N days» on Overview (instead of the fixed 2 days), and the same limit per link source (More options → empty = Overview limit, 0 = whole archive). Applies to AI, thread, tag and place sources; reverse sources are limited only when set explicitly.

1.12.1

  • Fix: the «Thread» source (one AI call per post) walked the whole archive in every cron run when «Process older posts» was off, using up the daily limit before new posts were linked. It now keeps to the same 2-day window as the AI sources.

1.12.0 (2026-10-06)

  • «Combine into one box» (Display blocks → Inside the article): the «Previously» line and the «Read also» box become one styled box after paragraph N, spread over long articles (Read also at a set part of the text); lists, tables and quotes after the paragraph are never split. Background and label colours; the line uses the accent colour. Off by default.

1.11.0 (2026-10-06)

  • Dashboard widget «Linkloom — linking today»: new posts processed in 24 h, links added today (AI vs. free rules), AI requests, queue and the latest AI links.

1.10.0 (2026-10-06)

  • Editor box rebuilt into three sections: «Add links by hand», «Settings for this post», «Chosen automatically».
  • Hand-picked links: one «Previously» post (replaces the automatic story-thread line) and up to five «Read also» posts that go first in the in-text box; shown even when automatic links are off. Article search by title, link or ID.
  • New per-post switches: «Hide all Linkloom blocks in this post» and «Do not link to this post from other posts» (such posts are never candidates and existing links to them disappear at once; pages that showed them are purged from cache).
  • Anchors: an AI phrase is embedded in the text only when it shares a stem with the target title or the model is very confident (≥ 0.9); otherwise the link goes to the «Read also» box. Topic-page anchors lose function words at their edges.
  • Fixed stemming of multi-word topic synonyms (only the last word is stemmed; short words stay exact).
  • API: text is now taken from all «text» blocks of the response, so models that answer with a thinking block first (e.g. Sonnet 5.5) work.
  • The «Rejected by the check» state is labelled in the editor box.
  • Settings page moved under the shared «MCG Plugins» menu (the address admin.php?page=linkloom is unchanged); new icon.
  • Ukrainian translation completed (all strings).

1.9.4 (2026-09-26, patched on kyivshchyna.info)

  • Sensitive-content guard is now a hard rule for AI sources too, not only for the place source: a sensitive post (tone tags / title words) never gets candidates from the "Keep sensitive news away from" categories, and a new leisure guide is never backfilled into sensitive news. Previously this was left to the model prompt, which let through e.g. a funeral report linking a city tourism guide.
  • Thread source ("Previously:") finds far more real earlier episodes: it searches all news of the district within the window without requiring a shared tag, ranks by shared title/lead stems plus a recency bonus (2026-10-02: reports from the last 24-72 hours are favoured, top 5 candidates), requires at least two shared stems (a bare town name no longer qualifies), and sends the top 4 candidates to one check that picks the same story or none. The check sees both dates and treats attacks/accidents/fires on different days as different stories. Picks below the source's confidence threshold go to the review queue. On a 40-post sample: 27% linked automatically vs 15% before.

1.9.3

  • Fixed a real bug in the reverse sources (news/guide -> new guide): a candidate post that already had a decision for that source - even "nothing useful" or "rejected by the check" for a DIFFERENT earlier target - was skipped forever for every later target, because the check only asked "does this post have a decision" and not "for this target". After the very first archive-wide run this meant almost every newly published guide found zero candidates. Candidates now stay open for re-evaluation unless they already carry a live link or a human rejection.

1.9.2

  • Anchor phrases never contain the site name, bylines ("передає", "редакція зібрала"), a sentence boundary or an abbreviation dot, and never end on a dangling particle ("не", "або"). Existing anchors of that kind were re-picked or moved to the "read also" box.

1.9.1

  • New rule source Topic → its tag page: the first mention of a topic the post is tagged with (police, accidents, rescuers…) links to that tag page, the way BBC links its topic pages. Only the post's own tags are used, so the link is always on topic; words come from the tag names and can be overridden per tag. Tag links take the last in-text slot, after the "Previously:" line, the place link and the AI pick.

1.9.0

  • Two new kinds of link source, both without the AI choosing anything, so they are free and predictable. Place → its guide: the first mention of a town or community in the text links to the guide about it; the place names are read from the guide titles automatically, every case form is recognised, and a manual list can add or remove names. For sensitive news (tags and title words you choose in Settings) the link goes to the district page instead of the city guide. Earlier episode of the story: for a news post, the previous report on the same story (same district, shared tag, within N days, confirmed by one AI check) is shown as a "Previously:" line after the first paragraph.
  • Links in the text are now capped per post across all sources (default 3), with a fixed priority: the "Previously:" line, then the place link, then the most confident AI pick.
  • Under every guide the list now ends with a link to the guide's own subcategory, which lists the whole cluster - the hub page.
  • The anchor picker prefers early sentences when several phrases fit; the first AI pass is asked to do the same.
  • The daily request counter is incremented in SQL, so parallel runs no longer lose counts.

1.8.2

  • The independent check now has two modes. For a forward source the candidate was already chosen as the best fit by the first pass, so the check now judges like a web editor picking "read also" links: related reading, background, the next step or a guide to the same city all count, and only off-topic or tonally wrong pages (leisure under a tragedy) are rejected. The old strict wording ("must describe the same situation") was rejecting about two thirds of good picks. For a reverse source the candidate comes from word overlap alone, so the strict mode stays.
  • Existing rejected forward pairs were re-judged with the new mode.

1.8.1

  • Fixed a real distribution bug in the free "Related guides" list: ties were broken by recency, so within a group of guides with an equally good match (for example, several city guides in the same subcategory) the same few newest ones always won, on every other guide's page - older siblings were never shown to anyone, no matter how relevant. The tiebreak is now pair-stable but no longer favours one winner, spreading exposure across the whole tied group. On this site it took the count of guides with zero internal links (from any source) from 24 down to 4, at no extra cost.

1.8.0

  • Two new columns on the Posts screen: "Links out" and "Links in", showing how many live Linkloom links point from and to each post. Click a number to see exactly which posts, with links straight to them.

1.7.1

  • New "Rejected by the check" queue tab. Pairs that the independent second AI pass explicitly judged not useful used to land in "Low confidence" (forward sources) or "Nothing suitable" (the reverse pipeline), next to genuinely uncertain ones - and, because the stored confidence blended the wrong two numbers, a firmly rejected pair could show a high percentage, looking like a strong candidate. These are now their own tab, no review needed, with the correct number (the original pick's confidence, before the check ran).
  • "Old posts to link per new article" can now go up to 300 (was 30).
  • The "What to choose" hint now also reaches the independent check for the reverse pipeline (previously only the first pick used it).

1.7.0

  • Each link source now picks its own categories instead of a fixed "news / guides / both" choice: "Mode" sets the direction (find a link to add into an article, or find articles to add a link to this one), "Add links to" sets which categories trigger the source, and "Look for pages in" sets which categories it searches. This makes a source fully self-contained and portable to any site, with any category structure - it no longer depends on a single site-wide "news vs evergreen" split.
  • Existing sources were migrated automatically to the equivalent explicit categories; nothing changes in how they behave.

1.6.0

  • Two-way pipeline. Until now only news posts searched for a guide to link to. A link source can now run in reverse: the moment a guide is published, Linkloom searches existing news for good matches and inserts a link to the new guide into them - fully automatic, no editor or author action needed. A manual "Find old news for this guide" button is also available for updating older guides.
  • Anchors are now chosen by code, not by the AI: the model only points at a sentence, and Linkloom scans it (and, for the reverse pipeline, the whole article) for the most specific matching phrase, never crossing a comma or starting on a preposition or verb.
  • Independent second check on every proposed link: a separate pass judges whether the page is genuinely useful before it goes live, rejecting loosely-related matches the first pass alone would have kept.
  • Fixed: when two sources proposed the same target for one post, the one without an embeddable phrase could win over the one with a working phrase, leaving a plain box instead of an in-text link.
  • New per-target cap so no single guide can absorb an outsized share of all links.

1.5.0

  • Links can now be added inside evergreen guides too. Each link source has an "Add links to" setting: news posts, guides, or both. A guide source looks among the guides themselves, prefers guides of the same subcategory, and links a guide to a closely related one.

1.4.1

  • The "read also" box inside the article is now a faint neutral grey with a soft grey left border; the border colour is configurable.
  • New setting: fresh news under guides are shown only under guides about places by default (a city name gives a reliable match), or always, or never.

1.4.0

  • Simpler "After the article" block: the default mode is now "Latest from the same category" (the newest posts of the same category, for example the same district). The smarter "Related by topic" mode is one click away. Rarely needed options moved under "More options".

1.3.0

  • New Linkloom box in the post editor: see the links chosen for the post, remove or restore each one, choose links again, switch off automatic links for the post, or hide the list below it.
  • Posts with automatic links switched off are skipped by the background queue, so they cost nothing.

1.2.0

  • New model: link sources decide where to look for pages (for example Articles, Travel); display blocks decide where links appear. Two display blocks - inside the article and after the article - each collect links from any sources you tick.
  • Links from several sources are shown together in one "read also" box (a line for one link, a short list for several).
  • The list after the article can start with AI-picked links and is filled up with related posts.
  • Optional embedding of a link into the words of the text can be turned off.

1.1.1

  • Fix: category pickers now show subcategories as a tree under their parent instead of one flat alphabetical list.

1.1.0

  • New admin interface: an Overview page with status, setup checklist, progress and recent links; blocks as collapsible cards; settings split into four numbered steps; a clearer review queue with explanations for each status.
  • Category and tag pickers are checklists instead of multi-select boxes.
  • One-click Switch on / Switch off.

1.0.0

  • First public release.

Versions

Version
1.16.0 (current)
1.15.1
1.15.0
1.14.0

The plugins update themselves on every site: a new version shows up in Dashboard → Updates within ~12 hours, or right after «Check again».

For now the plugins run only on MediaCG and partner websites and are not distributed publicly. Interested in a plugin? Write to [email protected].