{"id":358763,"date":"2026-09-02T04:41:17","date_gmt":"2026-09-02T04:41:17","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/ai-auto-linker\/"},"modified":"2026-09-03T13:07:07","modified_gmt":"2026-09-03T13:07:07","slug":"web-seo-autolinker","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/web-seo-autolinker\/","author":23535352,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"0.2.0","stable_tag":"0.2.0","tested":"7.1","requires":"6.2","requires_php":"7.4","requires_plugins":null,"header_name":"Web & SEO Autolinker - AI Internal Linking","header_author":"","header_description":"AI-powered permanent internal linking. Direct OpenAI embeddings + GPT anchor selection.","assets_banners_color":"7f7e7b","last_updated":"2026-09-03 13:07:07","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"","header_author_uri":"","rating":0,"author_block_rating":0,"active_installs":0,"downloads":82,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"0.1.1":{"tag":"0.1.1","author":"webandseofr","date":"2026-09-02 04:40:54","revision":3677148},"0.1.2":{"tag":"0.1.2","author":"webandseofr","date":"2026-09-02 13:38:54","revision":3678102},"0.1.3":{"tag":"0.1.3","author":"webandseofr","date":"2026-09-02 14:47:59","revision":3678210},"0.2.0":{"tag":"0.2.0","author":"webandseofr","date":"2026-09-03 13:07:07","revision":3679763}},"upgrade_notice":{"0.2.0":"<p>The admin interface moves from French to English. Sites running in French keep French: the translation ships with the plugin. No settings or data changes.<\/p>","0.1.3":"<p>Cosmetic and documentation. The admin screens now carry the plugin&#039;s name, and the journal shows why a candidate was dropped.<\/p>","0.1.2":"<p>Fixes content damage on page builders that store their layout as shortcodes, such as Divi. Recommended for those sites.<\/p>","0.1.1":"<p>Performance only. No settings or data changes.<\/p>","0.1.0":"<p>Initial release.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3677147,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3677147,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3677147,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3677147,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["0.1.1","0.1.2","0.1.3","0.2.0"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3679761,"resolution":"1","location":"assets","locale":"","width":1400,"height":820},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3679761,"resolution":"2","location":"assets","locale":"","width":1400,"height":1500},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3679761,"resolution":"3","location":"assets","locale":"","width":1400,"height":950},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3679761,"resolution":"4","location":"assets","locale":"","width":1400,"height":820},"screenshot-5.png":{"filename":"screenshot-5.png","revision":3679761,"resolution":"5","location":"assets","locale":"","width":1400,"height":560},"screenshot-6.png":{"filename":"screenshot-6.png","revision":3679761,"resolution":"6","location":"assets","locale":"","width":1400,"height":900}},"screenshots":{"1":"Every link the plugin has placed, with its source, its target, the anchor it used and the similarity that justified it. One click revokes a link and removes it from the content.","2":"The whole configuration on a single screen: similarity threshold, link budget per post, anchor length, which post types are sources and which are targets.","3":"Link health. Broken internal and external links, duplicate destinations, anchor cannibalisation, and registry entries whose target no longer exists.","4":"The journal. Every candidate that was considered and dropped, with the reason next to it.","5":"One button scans the whole catalogue. Progress is shown as it goes.","6":"The result in the published article: ordinary HTML links in the text, which survive in exports and feeds and do not depend on the plugin still running."}},"plugin_section":[],"plugin_tags":[2353,19933,175,194533,186],"plugin_category":[55],"plugin_contributors":[274230],"plugin_business_model":[],"class_list":["post-358763","plugin","type-plugin","status-publish","hentry","plugin_tags-ai","plugin_tags-internal-linking","plugin_tags-links","plugin_tags-openai","plugin_tags-seo","plugin_category-seo-and-marketing","plugin_contributors-webandseofr","plugin_committers-webandseofr"],"banners":{"banner":"https:\/\/ps.w.org\/web-seo-autolinker\/assets\/banner-772x250.png?rev=3677147","banner_2x":"https:\/\/ps.w.org\/web-seo-autolinker\/assets\/banner-1544x500.png?rev=3677147","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/web-seo-autolinker\/assets\/icon-128x128.png?rev=3677147","icon_2x":"https:\/\/ps.w.org\/web-seo-autolinker\/assets\/icon-256x256.png?rev=3677147","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/web-seo-autolinker\/assets\/screenshot-1.png?rev=3679761","caption":"Every link the plugin has placed, with its source, its target, the anchor it used and the similarity that justified it. One click revokes a link and removes it from the content."},{"src":"https:\/\/ps.w.org\/web-seo-autolinker\/assets\/screenshot-2.png?rev=3679761","caption":"The whole configuration on a single screen: similarity threshold, link budget per post, anchor length, which post types are sources and which are targets."},{"src":"https:\/\/ps.w.org\/web-seo-autolinker\/assets\/screenshot-3.png?rev=3679761","caption":"Link health. Broken internal and external links, duplicate destinations, anchor cannibalisation, and registry entries whose target no longer exists."},{"src":"https:\/\/ps.w.org\/web-seo-autolinker\/assets\/screenshot-4.png?rev=3679761","caption":"The journal. Every candidate that was considered and dropped, with the reason next to it."},{"src":"https:\/\/ps.w.org\/web-seo-autolinker\/assets\/screenshot-5.png?rev=3679761","caption":"One button scans the whole catalogue. Progress is shown as it goes."},{"src":"https:\/\/ps.w.org\/web-seo-autolinker\/assets\/screenshot-6.png?rev=3679761","caption":"The result in the published article: ordinary HTML links in the text, which survive in exports and feeds and do not depend on the plugin still running."}],"raw_content":"<!--section=description-->\n<p>Autolinker builds internal links between the posts you already have. It reads\neach post, finds the most semantically related pages on your site, and asks a\nlanguage model to choose an anchor phrase that already exists, word for word, in\nthe source text. The link is then written into the post content and kept in a\nregistry so it can be tracked, repaired, or removed later.<\/p>\n\n<p>There is no keyword list to maintain. Relevance comes from meaning, not from\nmatching strings.<\/p>\n\n<h4>How it works<\/h4>\n\n<ol>\n<li><strong>Embedding.<\/strong> Each post is converted to a vector with an OpenAI embeddings\nmodel, stored locally, and refreshed only when the content changes.<\/li>\n<li><strong>Candidate search.<\/strong> Cosine similarity ranks every possible target above a\nconfigurable threshold.<\/li>\n<li><strong>Filtering.<\/strong> A first model pass drops candidates that are topically close but\neditorially wrong.<\/li>\n<li><strong>Anchor selection.<\/strong> A second model pass proposes an anchor phrase. The plugin\nverifies the phrase appears verbatim in the source; if it does not, the link is\nrejected rather than forced.<\/li>\n<li><strong>Writing.<\/strong> The link is inserted with a marker attribute so the plugin can find\nits own links again without guessing.<\/li>\n<\/ol>\n\n<p>Every rejection is written to a journal with a reason, so an empty result is never\nindistinguishable from a broken plugin.<\/p>\n\n<h4>IMPORTANT: this plugin relies on a third-party service<\/h4>\n\n<p>Autolinker does not work without an OpenAI API key that you supply. The plugin\nsends data to the OpenAI API (api.openai.com), a third-party service that is not\naffiliated with this plugin or with WordPress.org.<\/p>\n\n<p><strong>What is sent:<\/strong> the text content of the posts you choose to process, the titles\nand excerpts of candidate link targets, and the prompts the plugin builds around\nthem. Your API key is stored encrypted in your WordPress database and is sent to\nOpenAI to authenticate each request.<\/p>\n\n<p><strong>When it is sent:<\/strong> only when a post is processed, either automatically on publish\n(if you enable that) or when you trigger a scan. Your post content is never sent to\nOpenAI at any other time.<\/p>\n\n<p><strong>What is not sent:<\/strong> no data is sent to the plugin author, and no post content\nleaves your site other than to OpenAI, as described above.<\/p>\n\n<p><strong>One clarification about link health.<\/strong> The plugin also checks whether the links in\nyour content still resolve. That check runs on a schedule and makes ordinary HTTP\nrequests to the URLs already present in your posts, and to their robots.txt, which it\nhonors. It sends none of your content and involves no third-party service: it only\nvisits the addresses you already link to. Those requests identify themselves with a\nuser agent naming the plugin and your site URL, so the hosts you link to can see that\nthe request came from your site.<\/p>\n\n<p>Using this plugin means your content is processed under OpenAI's terms. Please read\nthem before installing:<\/p>\n\n<ul>\n<li>OpenAI Terms of Use: https:\/\/openai.com\/policies\/terms-of-use<\/li>\n<li>OpenAI Privacy Policy: https:\/\/openai.com\/policies\/privacy-policy<\/li>\n<li>OpenAI API data usage policies: https:\/\/openai.com\/policies\/api-data-usage-policies<\/li>\n<\/ul>\n\n<p>You pay OpenAI directly for the tokens the plugin consumes. See the FAQ for cost\ncontrol.<\/p>\n\n<h4>Features<\/h4>\n\n<ul>\n<li>Semantic candidate search with a configurable similarity threshold<\/li>\n<li>Verbatim anchor validation, so anchors are never invented<\/li>\n<li>A per-post link budget and anchor length bounds (default 2 to 6 words)<\/li>\n<li>Silo mode, to keep links inside the same category<\/li>\n<li>Per-post exclusions: exclude entirely, as a source only, or as a target only<\/li>\n<li>Link health: periodic checking, broken link detection with a failure threshold,\nand an orphaned state when a link disappears from the content<\/li>\n<li>Slug refresh: when a target's permalink changes, the links pointing at it are\nrewritten<\/li>\n<li>Elementor support, including posts stored in Elementor's own data structure<\/li>\n<li>A decision journal covering every link placed and every candidate rejected<\/li>\n<\/ul>\n\n<h4>Multilingual<\/h4>\n\n<p>Sites running WPML or Polylang are detected automatically and links are kept inside\na single language. A French post never links to its English translation.<\/p>\n\n<p>Detection requires at least two configured languages. Translation layers that render\non the fly without duplicating posts (TranslatePress, Weglot, GTranslate) are treated\nas monolingual, because only the original content exists in the database.<\/p>\n\n<p>On a multilingual site the plugin switches to a larger embedding model for better\ncross-language separation. Posts are re-embedded lazily, at their next scan, which\nmeans a one-off token cost the first time each post is processed after you add a\nsecond language.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Install and activate the plugin.<\/li>\n<li>Go to Autolinker &gt; Settings and paste your OpenAI API key. You can create one\nat https:\/\/platform.openai.com\/. Review the OpenAI terms linked in the description\nbefore you do.<\/li>\n<li>Set your similarity threshold and per-post link budget, or keep the defaults.<\/li>\n<li>Either enable automatic processing on publish, or run a scan by hand from the\nplugin screen.<\/li>\n<\/ol>\n\n<p>Processing runs through WP-Cron. On a site with little traffic, consider a real\nsystem cron calling wp-cron.php so scans do not stall.<\/p>\n\n<!--section=faq-->\n<dl>\n<dt id=\"do%20i%20need%20an%20openai%20api%20key%3F\"><h3>Do I need an OpenAI API key?<\/h3><\/dt>\n<dd><p>Yes. The plugin has no bundled key and no free tier of its own. You create a key on\nyour own OpenAI account and pay OpenAI for what you use.<\/p><\/dd>\n<dt id=\"how%20much%20does%20it%20cost%20to%20run%3F\"><h3>How much does it cost to run?<\/h3><\/dt>\n<dd><p>It depends on how many posts you process and how long they are. Two levers reduce\nit: the per-post link budget caps how many placements are attempted, and embeddings\nare cached, so a post that has not changed is never re-embedded.<\/p><\/dd>\n<dt id=\"does%20it%20modify%20my%20post%20content%3F\"><h3>Does it modify my post content?<\/h3><\/dt>\n<dd><p>Yes. Links are written into the post content, with a marker attribute so the plugin\ncan identify its own links later. This is deliberate: the links are real HTML, they\nsurvive in exports, in feeds, and for search engines, and they do not depend on a\nfilter running at display time.<\/p><\/dd>\n<dt id=\"what%20happens%20if%20i%20deactivate%20the%20plugin%3F\"><h3>What happens if I deactivate the plugin?<\/h3><\/dt>\n<dd><p>The links stay in your content, because they are ordinary HTML. Link tracking,\nhealth checks and repair stop until you reactivate.<\/p><\/dd>\n<dt id=\"can%20i%20stop%20it%20from%20touching%20a%20specific%20post%3F\"><h3>Can I stop it from touching a specific post?<\/h3><\/dt>\n<dd><p>Yes. Each post has controls to exclude it entirely, to stop it being used as a link\nsource, or to stop it receiving links.<\/p><\/dd>\n<dt id=\"does%20it%20work%20with%20page%20builders%3F\"><h3>Does it work with page builders?<\/h3><\/dt>\n<dd><p>Elementor is supported, including content stored in Elementor's own data structure.\nWithin an Elementor page, text editor widgets are linked; other widgets are left\nalone.<\/p>\n\n<p>Builders that store their layout as shortcodes in the post content, such as Divi,\nare linked inside their text, and their shortcodes are left untouched. Text that a\nbuilder keeps in a shortcode attribute rather than in the body, such as a module\ntitle, is never linked: writing there would break the module and the link would be\ninvisible. The journal records those as an anchor found only in a shortcode.<\/p>\n\n<p>Builders that keep their content outside the post content field entirely, such as\nSeedProd, are not supported yet. Nothing is written on those pages, and nothing is\ndamaged either.<\/p><\/dd>\n<dt id=\"does%20it%20conflict%20with%20yoast%20seo%2C%20rank%20math%2C%20all%20in%20one%20seo%20or%20seopress%3F\"><h3>Does it conflict with Yoast SEO, Rank Math, All in One SEO or SEOPress?<\/h3><\/dt>\n<dd><p>No, and the reason is structural rather than a list of integrations: the plugin adds\nnothing to the front end. No meta tag, no canonical, no sitemap, no filter on the\ncontent at display time. The links are written into your content as ordinary HTML,\nso an SEO plugin counts them exactly like a link you typed yourself.<\/p>\n\n<p>One behaviour is worth knowing: the plugin does not read the noindex setting of those\nplugins. A page you have marked noindex can still be chosen as a link target. Use the\nper-post controls in the sidebar to exclude it.<\/p><\/dd>\n<dt id=\"does%20it%20work%20with%20caching%20plugins%3F\"><h3>Does it work with caching plugins?<\/h3><\/dt>\n<dd><p>Yes. Nothing is computed at display time, so a cached page can never serve a version\nwithout the links: they are already part of the stored content. Writing to the post\ncontent goes through the normal WordPress update path, which is the signal WP Rocket,\nW3 Total Cache, LiteSpeed Cache, WP Super Cache, WP Fastest Cache and SG Optimizer\nalready watch in order to clear a page by themselves.<\/p>\n\n<p>One case to know about: on an Elementor page, and in ACF fields, the plugin writes to\npost meta instead of the post content. That does not fire the post update hooks, and\nthe plugin sends no purge of its own. If a new link on such a page does not appear,\npurge that page in your caching plugin.<\/p><\/dd>\n<dt id=\"why%20did%20it%20place%20no%20links%20on%20a%20post%3F\"><h3>Why did it place no links on a post?<\/h3><\/dt>\n<dd><p>Open the journal. Every candidate that was considered and dropped is recorded with a\nreason: below the similarity threshold, rejected by the filtering pass, or an anchor\nthat did not appear verbatim in the source. The last one is the most common, and it\nis working as intended: the plugin will not invent an anchor that is not in your text.<\/p><\/dd>\n<dt id=\"does%20it%20send%20my%20content%20anywhere%20other%20than%20openai%3F\"><h3>Does it send my content anywhere other than OpenAI?<\/h3><\/dt>\n<dd><p>No. The only external service is the OpenAI API, and only for the posts you process.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>0.2.0<\/h4>\n\n<ul>\n<li>The admin interface is now in English. It was written in French, which read oddly next to an English listing and left the plugin untranslatable for everyone else.<\/li>\n<li>French is not gone. It ships with the plugin as a translation, so a site running in French keeps the interface it already had. Nothing to install, nothing to configure.<\/li>\n<li>The plugin can now be translated into any language, either on translate.wordpress.org or with your own .po file.<\/li>\n<li>The reason codes in the journal are in English too: anchor_inside_link rather than ancre_dans_un_lien. Entries written before this update keep their old code until they age out of the journal.<\/li>\n<li>No settings or database changes.<\/li>\n<\/ul>\n\n<h4>0.1.3<\/h4>\n\n<ul>\n<li>The admin screens now carry the plugin's own name. They still said \"AI Auto Linker\", the name the plugin had before it was published.<\/li>\n<li>The journal now shows the reason next to each dropped candidate. It was recorded but only readable from the database, which made the answer in the FAQ half true.<\/li>\n<li>Documentation: page builders, SEO plugins and caching plugins each have their own entry in the FAQ, limits included.<\/li>\n<li>No settings or database changes.<\/li>\n<\/ul>\n\n<h4>0.1.2<\/h4>\n\n<ul>\n<li>Fixed: on a page whose layout is stored as shortcodes in the post content, such as Divi, a link could be written inside a shortcode attribute instead of the visible text. The module broke and the link was invisible.<\/li>\n<li>Fixed: removing or repointing a link no longer rewrites a raw ampersand inside a shortcode attribute, and no longer lets a raw angle bracket there swallow the rest of the field.<\/li>\n<li>Text that a builder keeps in a shortcode attribute, such as a module title, is now never linked. The journal records those as an anchor found only in a shortcode.<\/li>\n<li>No settings or database changes.<\/li>\n<\/ul>\n\n<h4>0.1.1<\/h4>\n\n<ul>\n<li>Performance: inbound link counts for several pages are now read in a single grouped query instead of one query per page.<\/li>\n<li>Performance: those counts are cached in the object cache and cleared whenever the link registry is written to. Sites without a persistent object cache still get the grouped query, which is the larger of the two gains.<\/li>\n<li>No settings, database or behaviour changes.<\/li>\n<\/ul>\n\n<h4>0.1.0<\/h4>\n\n<ul>\n<li>Initial release.<\/li>\n<\/ul>","raw_excerpt":"AI-powered internal linking. OpenAI embeddings find the targets, GPT picks natural anchors, and the links are written into your posts.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/358763","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=358763"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/webandseofr"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=358763"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=358763"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=358763"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=358763"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=358763"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=358763"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}