{"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-10-23T03:37:38","modified_gmt":"2026-10-23T03:37:38","slug":"web-seo-autolinker","status":"publish","type":"plugin","link":"https:\/\/ewe.wordpress.org\/plugins\/web-seo-autolinker\/","author":23535352,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"0.4.2","stable_tag":"0.4.2","tested":"7.1.3","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-10-23 03:37:38","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"","header_author_uri":"","rating":0,"author_block_rating":0,"active_installs":20,"downloads":781,"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},"0.2.1":{"tag":"0.2.1","author":"webandseofr","date":"2026-09-04 01:45:23","revision":3680556},"0.3.0":{"tag":"0.3.0","author":"webandseofr","date":"2026-09-04 09:27:28","revision":3680960},"0.3.1":{"tag":"0.3.1","author":"webandseofr","date":"2026-10-08 12:12:09","revision":3734502},"0.3.2":{"tag":"0.3.2","author":"webandseofr","date":"2026-10-08 14:53:40","revision":3734892},"0.3.3":{"tag":"0.3.3","author":"webandseofr","date":"2026-10-09 02:41:52","revision":3735801},"0.4.0":{"tag":"0.4.0","author":"webandseofr","date":"2026-10-21 14:24:42","revision":3758548},"0.4.1":{"tag":"0.4.1","author":"webandseofr","date":"2026-10-22 05:39:04","revision":3759348},"0.4.2":{"tag":"0.4.2","author":"webandseofr","date":"2026-10-23 03:37:38","revision":3760859}},"upgrade_notice":{"0.4.2":"<p>On a multisite network, Delete data on uninstall now cleans up every site where the box is ticked, not only the main site. No settings or data changes.<\/p>","0.4.1":"<p>Anchors are no longer linked in the middle of a word, and the readme now lists every case in which content is sent to OpenAI. No settings or data changes.<\/p>","0.3.3":"<p>WPML sites with a single language now use the standard embedding model, as Polylang sites already did; their posts are embedded again once. No settings or data changes.<\/p>","0.3.2":"<p>Silo mode is now applied: Strict keeps links inside shared categories, Soft places same-category links first. No settings or data changes.<\/p>","0.3.1":"<p>Anchors are now chosen by GPT-6 Sol, priced lower per token than GPT-5.6 Terra. No settings or data changes.<\/p>","0.3.0":"<p>Pages you marked noindex are no longer used as link targets. Links already written to them are left alone. No settings or data changes.<\/p>","0.2.1":"<p>Two fixes. The working language follows your site language instead of defaulting to French, and links written into Elementor or ACF pages now clear the page cache. No settings or data changes.<\/p>","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","0.2.1","0.3.0","0.3.1","0.3.2","0.3.3","0.4.0","0.4.1","0.4.2"],"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 (capitalisation aside). The link is then written into the post\ncontent and kept in a registry 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 in the source exactly, capitalisation aside; the\nlinked text keeps the capitalisation of your post. If the phrase is not there,\nthe link is rejected 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 text of\nyour link targets (up to 8,000 characters each, to compute the embeddings\nthat match them), the titles and excerpts of candidate link targets, and the\nprompts the plugin builds around them. Your API key is stored encrypted in your\nWordPress database and is sent to OpenAI to authenticate each request.<\/p>\n\n<p><strong>When it is sent:<\/strong> in these four cases, and no others:<\/p>\n\n<ul>\n<li>When you publish a post or update a published one. This processing on publish\nis on by default; you can switch it off in Settings (\"Full auto on publish\").<\/li>\n<li>When you trigger a scan yourself.<\/li>\n<li>When you add a post type to the link targets in Settings: its published content\nis queued for embedding.<\/li>\n<li>After a plugin update that changes the plugin's database, or when the embedding\nmodel changes (the plugin uses a larger model on multilingual sites): your link\ntargets are queued for embedding again.<\/li>\n<\/ul>\n\n<p>The last two cases run in the background through WP-Cron, even with \"Full auto on\npublish\" switched off. They only send content that has no embedding yet, or whose\ntext or embedding model has changed since its embedding was computed.<\/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>Anchor validation against the source text (word for word, capitalisation\naside), 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 Autolinker placed to\nit are rewritten. Links you added by hand are never rewritten automatically;\nthose that point to an old post slug are listed on the Link health screen, with\nan \"Update href\" button for each one<\/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 active languages, with WPML as with Polylang: a\nsite with a single language is treated as monolingual. 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. When the site changes mode (a second language added, or\nremoved), every post is queued once to be embedded again with the new model, which\nmeans a one-off token cost for the whole catalogue.<\/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=\"what%20happens%20if%20i%20uninstall%20the%20plugin%3F\"><h3>What happens if I uninstall the plugin?<\/h3><\/dt>\n<dd><p>By default, everything is kept. Tick \"Delete data on uninstall\" in Settings and\nuninstalling removes everything the plugin created, except the links already written\ninto your posts and their revisions. To take links out, revoke them before you\nuninstall: once its data is deleted, the plugin can no longer find them. On a\nmultisite network, each site where the box is ticked is cleaned up, and sites where\nit is not ticked keep their data. With a persistent object cache (Redis, Memcached),\nthe robots.txt rules cached by the link checker are not deleted: they expire on their\nown within 24 hours.<\/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>SeedProd is supported on landing pages and on pages edited with SeedProd. Text\nblocks are linked in both places SeedProd keeps them, so the link shows at once and\nsurvives the next save in the SeedProd builder. Other blocks, such as headlines and\nbuttons, are left alone. Tested with SeedProd Lite. Pages built with the SeedProd Pro\ntheme builder use the same storage but were not tested.<\/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>The plugin does read the noindex setting of those four: a page you have marked\nnoindex is never chosen as a link target. Nothing to configure.<\/p>\n\n<p>Two limits are worth knowing. It reads the setting you put on the page itself, not\na site-wide rule that makes a whole post type noindex. And it reads the four\nplugins above; another SEO plugin is not recognised. In both cases the page can\nstill be chosen as a target, and the per-post controls in the sidebar exclude it.\nDevelopers can also filter aial_target_is_noindex.<\/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>On an Elementor page, and in ACF fields, the plugin writes to post meta instead of the\npost content, which does not fire the post update hooks. Since 0.2.1 it signals the\nchange itself on those paths: it calls clean_post_cache(), which WP Super Cache and\nW3 Total Cache listen to, and it clears Cache Enabler and LiteSpeed Cache through\ntheir own per-post API. Measured against those four.<\/p>\n\n<p>Two are not covered. WP Fastest Cache exposes no per-post purge that another plugin\ncan reach. WP Rocket could not be tested here, so nothing is claimed about it. If a\nnew link on an Elementor or ACF page does not appear on either of those, purge that\npage in your caching plugin, or hook the aial_post_content_changed action to call your\ncache's own purge.<\/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.4.2<\/h4>\n\n<ul>\n<li>On a multisite network, \"Delete data on uninstall\" now cleans up every site where the box is ticked. Until now only the main site was cleaned up, and only if its own box was ticked; the other sites kept their tables, settings and OpenAI key.<\/li>\n<li>No settings or database changes.<\/li>\n<\/ul>\n\n<h4>0.4.1<\/h4>\n\n<ul>\n<li>An anchor is no longer linked in the middle of a word. Until now the plugin linked the first place where the anchor appeared, so \"art guide\" could be linked inside \"smart guide\". It now skips any match glued to a letter or a digit and uses the next one that stands as whole words; when there is none, no link is placed and the journal records anchor_inside_word. Chinese, Japanese, Korean, Thai, Lao, Khmer and Burmese text, which does not separate words with spaces, is not affected.<\/li>\n<li>The readme now lists every case in which content is sent to OpenAI: publishing or updating a post, a scan, adding a post type to the link targets, and the background re-embedding after some updates or a change of embedding model. It also says that the text of link targets is sent.<\/li>\n<li>The readme now says that anchors are matched with capitalisation aside, and that slug refresh rewrites only the links Autolinker placed; links you added by hand to an old post slug are listed on the Link health screen.<\/li>\n<li>No settings or database changes.<\/li>\n<\/ul>\n\n<h4>0.4.0<\/h4>\n\n<ul>\n<li>SeedProd support. Text blocks on SeedProd landing pages, and on pages edited with SeedProd, are now linked. Until now the plugin wrote into the copy of the page that SeedProd rebuilds on every save, so a link vanished the next time the page was saved in the builder, and headlines and buttons could be linked too. Links now go into both copies SeedProd keeps, and only into text blocks.<\/li>\n<li>Adding, removing or rewriting a link no longer strips the backslashes from your post. Until now every backslash in the content or excerpt was dropped when the plugin saved the post, silently, so a Windows path like C:Usersdemo came back as C:Usersdemo, and code samples, regular expressions and LaTeX were damaged. The same applied to ACF fields the plugin links. Backslashes are now kept.<\/li>\n<li>\"Delete data on uninstall\" now removes everything the plugin created, except the links already written into your posts. Until now it left behind one setting (the embedding model in use), the per-post boxes you ticked (exclusions and Force silo), its three scheduled tasks and the robots.txt rules cached by the link checker. With the box unticked, uninstalling still keeps everything.<\/li>\n<\/ul>\n\n<h4>0.3.3<\/h4>\n\n<ul>\n<li>WPML now follows the same rule as Polylang: the multilingual mode starts at two active languages. A WPML site with a single language was treated as multilingual and used the larger embedding model for no benefit. It now uses the standard model, and each post is embedded again once with it, a one-off cost.<\/li>\n<li>When the site changes mode (a second language added or removed), every post is now queued once to be embedded again with the new model. Before, posts switched one by one at their next scan, and in the meantime a newly processed post could find no candidates at all.<\/li>\n<li>The readme now says plainly that processing on publish is on by default, and how to switch it off.<\/li>\n<li>For developers: AIAL_Link_Registry::targets_without_inbound() and AIAL_Link_Registry::first_inbound_between() now count the links you wrote yourself in your content, as recorded by the link inventory. A page that only receives manual links is no longer reported as receiving none.<\/li>\n<li>No settings or database changes.<\/li>\n<\/ul>\n\n<h4>0.3.2<\/h4>\n\n<ul>\n<li>Silo mode now does what the setting says. Until this version the choice was saved but never applied, so a site set to Strict could still receive links between categories.<\/li>\n<li>Strict: a post only links to posts that share at least one category with it. Each post where the silo set candidates aside gets one line in the journal, with how many were set aside.<\/li>\n<li>Soft: posts from the same category are offered first and placed first, so they use the link budget before the others. Posts from other categories can still get a link.<\/li>\n<li>The \"Force silo\" box on a post applies Strict to that post, whatever the site setting.<\/li>\n<li>A post with no category is not affected by either mode. Only standard post categories are read; tags and custom taxonomies are not.<\/li>\n<li>No settings or database changes.<\/li>\n<\/ul>\n\n<h4>0.3.1<\/h4>\n\n<ul>\n<li>The anchor-choice step now calls GPT-6 Sol instead of GPT-5.6 Terra. Sol is priced lower per token than Terra ($2 and $10 per million input and output tokens, against $2.50 and $15). The filtering step (GPT-5.6 Luna), the nano fallback and the embeddings are unchanged.<\/li>\n<li>For developers: AIAL_Linker::build_terra_input(), AIAL_Linker::terra_schema() and the TERRA constants still work and now point to Sol. They are deprecated; use the sol names.<\/li>\n<li>No settings or database changes.<\/li>\n<\/ul>\n\n<h4>0.3.0<\/h4>\n\n<ul>\n<li>A page you have marked noindex is no longer chosen as a link target. Sending internal links to a page you have deliberately kept out of the index is the opposite of what you asked for, and nothing on screen told you it was happening. Works with Yoast SEO, Rank Math, All in One SEO and SEOPress, and there is nothing to configure.<\/li>\n<li>Links already written to such a page are left where they are. Removing them by itself would rewrite your content without being asked; the Links screen lets you revoke any of them.<\/li>\n<li>This reads the setting you put on the page itself, not a site-wide rule that makes a whole post type noindex. That limit is written in the FAQ.<\/li>\n<li>New filter for developers, aial_target_is_noindex: force a target out, keep one in, or restore the previous behaviour entirely.<\/li>\n<li>No settings or database changes.<\/li>\n<\/ul>\n\n<h4>0.2.1<\/h4>\n\n<ul>\n<li>The working language now follows your site language instead of always starting at French. A fresh install on an English site was sending French instructions to the model, at the same cost and with no guarantee on anchor quality. Sites that had already saved their settings keep the language they chose.<\/li>\n<li>Links written into Elementor pages and ACF fields now clear the page cache. They were only showing up once the cache expired: the link was in the stored content, but it read like a broken plugin. Measured against WP Super Cache, W3 Total Cache, Cache Enabler and LiteSpeed Cache.<\/li>\n<li>New action for anyone whose cache is not one of those four: aial_post_content_changed, fired with the post id whenever the plugin writes to post meta.<\/li>\n<li>No settings or database changes.<\/li>\n<\/ul>\n\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:\/\/ewe.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/358763","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ewe.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/ewe.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/ewe.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=358763"}],"author":[{"embeddable":true,"href":"https:\/\/ewe.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/webandseofr"}],"wp:attachment":[{"href":"https:\/\/ewe.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=358763"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/ewe.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=358763"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/ewe.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=358763"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/ewe.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=358763"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/ewe.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=358763"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/ewe.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=358763"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}