Unstale – Refresh Old Posts with AI, Fact-Check & Republish

설명

Your best posts stopped bringing traffic. Not from a penalty: the prices, the statistics and the year references inside them grew outdated while fresher pages took the rankings. A content refresh fixes that, and Unstale runs one with real AI, through the AI provider you already connected to WordPress.

Point it at a published post. It reads the post, searches the live web, checks every figure and price against what it finds, rewrites the text, updates the SEO metas, adds internal links, and hands you the result as a diff to approve. Then it republishes with a fresh date, without breaking your URLs.

What one content refresh actually does

  • Live web research. The refresh searches the web while it runs, so the rewrite is based on what is true today and not on what the model remembers.
  • Fact-check of every number. Outdated figures, prices and dates are fact-checked against the sources the refresh just read. A step that cannot verify a claim says so in the journal instead of inventing one.
  • Rewrite at the level you choose. Minimal fixes typos, facts, internal links and the date. Balanced adds the SEO work: optimized metas, JSON-LD when no SEO plugin already emits it, key-takeaway callouts, readability.
  • Internal linking. Up to 15 relevant internal links per refresh, with natural, varied anchors, one link per target page.
  • Pages built with Elementor, Divi or SeedProd. The refresh reads the text out of the builder’s own data, sends only that text through, and writes it back where it came from, so your layout and your styling are untouched. A page built with a builder Unstale does not support is flagged before anything runs instead of being rewritten behind your back.
  • A journal per article. Every step, every token count and the real cost, each on its own line.

Find out what has gone stale, for free

Knowing a refresh works is one thing. Knowing which of your 400 posts needs one is another. The Content health screen lists your published content that has not been updated in a while, oldest first, split into three age ranges so you can see how much of your archive has drifted.

It reads nothing but your own database, so looking costs you nothing and needs no AI provider connected. When you are ready, select what you want from that screen and send it off in one batch. Unstale shows the total your provider will bill before anything starts, and names anything it left out of the batch along with the reason.

Find out what competes with itself, for free

Two posts that cover the same ground do not rank together, they rank against each other, and the newer or thinner one usually loses. The same Content health screen scans your published content and groups the posts that overlap too closely, so you see the competition before Google decides it for you.

The scan compares your own text with itself, on your own server: no AI provider needed, nothing sent anywhere, and it costs nothing to run. Each group names the post Unstale would keep, and why. With an AI provider connected, an optional AI pass reads every group in context and tells two posts that merely share vocabulary from two posts that genuinely chase the same query.

You keep the keys, and you keep the bill

Since WordPress 7.0, providers and credentials live in Settings > Connectors and are managed by WordPress itself. Unstale uses whatever you set up there, so this plugin stores no API key of its own and never sees your credentials.

Your WordPress talks to that provider directly. Your content, published or draft, never passes through our servers. We do not see it.

You pay your provider directly, at its own rates, and nothing to us per refresh. No credits, no monthly quota, no cap on how many old posts you refresh. Unstale shows an estimated cost before each launch and logs the real one after.

Nothing goes live without you

Every refresh waits in a review queue with a side-by-side diff of the current post and the proposed one. You approve it or you discard it. An optional full-auto mode exists for people who want it, off by default. Approved changes are applied as a normal WordPress revision, so one click rolls them back when revisions are enabled on your site.

Republishing that does not break your URLs

Republishing plugins usually warn you not to use them when your permalinks contain the post date, because bumping the date moves the URL. Unstale skips the bump automatically when your permalink structure uses the core date tags. To keep dated URLs and still refresh the date, switch to the %unstale_year%, %unstale_monthnum% and %unstale_day% tags: they freeze the original date in the URL for good. Republication also carries position control, randomized timing, allowed days and time windows.

Works with what you already run

Unstale fits the stack you have instead of asking you to change it, and none of this needs a setting: it detects what is active and adapts.

  • Page builders: Elementor, Divi and SeedProd. The refresh rewrites the text inside the page the builder already built and puts it back in the builder’s own data, so your layout, your styling, your images and your builder settings come back exactly as they were. On a SeedProd page that uses blocks from SeedProd Pro, the new text lands in the builder and the live page waits for you to reopen it and save, which the journal tells you plainly.
  • SEO plugins: Yoast SEO, Rank Math, All in One SEO and SEOPress. The rewritten meta title and description go straight into that plugin’s own fields, not into a second set of fields your theme would ignore. Unstale also stops emitting its own JSON-LD while one of them is active, so a refreshed post never ends up carrying two Article schemas. With no SEO plugin installed, Unstale writes the metas and the structured data itself.
  • Cache plugins: WP Rocket, W3 Total Cache, LiteSpeed Cache, WP Super Cache, WP Fastest Cache and SG Optimizer. Once a refresh is published, Unstale purges the post through that plugin’s own public purge API so the new version is live at once. The purge is always aimed at the refreshed post, never a full-site flush, so the rest of your cache stays warm. Anything not on that list, a CDN for instance, hooks onto the unstale_purged action.
  • Editors and content types. Gutenberg and the Classic editor both, on posts, pages and public custom post types.

What Unstale does not do

It does not write new articles. It works only on posts you already published, which is the point: the traffic is easier to win back on an evergreen post that once ranked than on a new one nobody has read. It does not read Search Console and does not rank your archive by traffic lost, so you choose which old posts to refresh, one by one or in batches from the Content health screen. And there is no account to create anywhere.

Two refresh levels are free: Minimal and Balanced, and so is sending a batch off from the Content health screen. The Strong and Maximal levels, scheduled automation and per-category rules are part of Unstale Pro. Automation of the free levels is available through the REST API (unstale/v1) and WP-CLI (wp unstale refresh).

Unstale is developed by Web & SEO Ltd, the company that owns and operates unstale.ai.

External services

This plugin relies on one external service.

The Unstale model catalog (unstale.ai)

What it is: a public, static JSON file at https://unstale.ai/api/v1/models.json listing the supported model ids, their prices per million tokens and their notes. It exists so that a new provider model becomes available in your settings without waiting for a plugin update, and so the plugin can show you a cost estimate before each refresh.

What is sent, and when: nothing but the HTTP request itself. It is an unauthenticated GET, fired by a single scheduled task once every 24 hours. No content, no credentials, no personal data, no site identifier is transmitted, and there is no manual refresh button that could trigger it more often. If the request fails the plugin keeps using the catalog bundled in the plugin files.

This service is provided by Unstale: Terms, Privacy

A note on AI providers

Unstale does not contact Anthropic, OpenAI or Google itself and declares none of them as its own external service. Prompts are handed to the WordPress AI Client, which routes them to the provider you connected in Settings > Connectors. That provider, its terms and its billing are the relationship between you and them, set up in WordPress and not in this plugin.

스크린샷

설치

  1. Install and activate the plugin. WordPress 7.0 or newer is required.
  2. Go to Settings > Connectors and connect an AI provider if you have not already. Unstale will tell you if none is connected.
  3. Go to Unstale > Settings, pick a default model and refresh level.
  4. In the Posts list, click “Refresh with Unstale” on any published post. Review the estimated cost, confirm, then approve the proposed rewrite in Unstale > Review queue.

FAQ

How much does a refresh cost?

You pay your AI provider directly, per token. Unstale shows an estimate BEFORE each launch and logs the real cost after. For a 1000-word article at the Balanced level the estimate runs from roughly $0.08 on the cheapest model in the catalogue to roughly $0.73 on the dearest, depending on the model you pick. That estimate bounds the worst case (it assumes every web search the level allows is spent), so the cost logged after the run is lower: on the cheapest model, measured runs land around two cents.

Models whose provider grants a monthly allowance of free web searches are estimated with that allowance applied, and the confirmation screen says so. A site that refreshes enough articles in one month to exhaust the allowance will pay for the searches beyond it, which the estimate does not yet track.

Web search fees are part of the estimate shown before a refresh, but not of the cost logged after it. None of the three provider plugins passes the number of searches back to WordPress today, so the plugin cannot price them once the run is over. The journal says so instead of showing a zero, and the estimate remains the honest figure for that part of the bill.

How is this different from a plugin that just changes the publish date?

A date bump moves an old post back to the top of your feeds, but the text stays exactly as outdated as it was. Unstale rewrites the content first: it researches the subject on the live web, corrects the figures and prices that aged, updates the metas and the internal links, and only then republishes. The date bump is the last step of the job, not the whole job.

Can I try it on a single post before touching my archive?

Yes, and that is the default path. The Posts list has no bulk action: you refresh one post at a time, review the diff, and approve or discard. Nothing sweeps your archive unless you ask for it, either by ticking the posts you want on the Content health screen, from WP-CLI (wp unstale refresh –all, which asks you to confirm first, because every job spends money at your provider), or through the scheduled rules in Unstale Pro.

Does my content go through your servers?

No. WordPress calls the provider you connected, directly. The only request to unstale.ai is the public model catalog (no content, no personal data).

Which API key does it use?

None of its own. Since WordPress 7.0, credentials live in Settings > Connectors and are managed by WordPress. Unstale never sees, stores or transmits them. If you used an older version of this plugin, the API keys it had stored are deleted automatically when you update.

Can it publish without my approval?

Not by default. Every refresh waits in the review queue with a side-by-side diff. You can enable full-auto publishing in the settings if you want it.

My permalinks contain the post date. Will the date bump break my URLs?

No: the bump is skipped automatically when your permalink structure uses the core date tags. To keep dated URLs AND bump dates, switch your structure to the %unstale_year%, %unstale_monthnum% and %unstale_day% tags: they freeze the original date in the URL forever. If you deactivate Unstale later, the plugin automatically restores the core date tags so your site keeps routing (posts whose date was bumped will then use the bumped date in their URL). Deleting the plugin files manually without deactivating skips that safety net: re-save your permalink structure in that case.

Does it work with my page builder, my SEO plugin and my cache plugin?

Page builders: Elementor, Divi and SeedProd. The refresh rewrites the text inside the page the builder already built, so nothing about your layout moves. Unstale asks you to confirm before refreshing any builder-built page, whichever builder it is, so nothing is ever rewritten behind your back.

SEO plugins: Yoast SEO, Rank Math, All in One SEO and SEOPress. The meta title and description go into their own fields, and Unstale stops emitting its own structured data so you never get two Article schemas on one post. With no SEO plugin, Unstale writes both itself.

Cache plugins: WP Rocket, W3 Total Cache, LiteSpeed Cache, WP Super Cache, WP Fastest Cache and SG Optimizer. Only the refreshed post is purged, never your whole cache. A cache or CDN outside that list plugs onto the unstale_purged action.

None of it needs configuring: Unstale detects what is active on your site and adapts.

Which models are supported?

Whichever models the provider you connected exposes. Unstale ships model cards for Claude Sonnet 5 (default), GPT-5.6 Terra and Gemini 3.8 Flash, with pricing and ratings to help you choose. All three are generally available, so the model you pick is the model that runs; if the catalog ever marks one as preview, Unstale runs its fallback instead and states the substitution on the model card and in the job log. The catalog is updated remotely: when a provider ships a new model, it appears in your settings without a plugin update.

후기

이 플러그인에 대한 평가가 없습니다.

기여자 & 개발자

“Unstale – Refresh Old Posts with AI, Fact-Check & Republish”(은)는 오픈 소스 소프트웨어입니다. 다음의 사람들이 이 플러그인에 기여하였습니다.

기여자

변경이력

1.14.4

  • Fixed: a step that failed twice in the same paid way went on to buy a third attempt that could only fail the same way. Retrying is the right answer when the trouble is passing, a provider under load or a connection that never answers, and those attempts are not billed because nothing came back. It is the wrong answer once the model has answered and its answer could not be used, because the next attempt sends exactly the same thing again. Measured on a real site: one post burned nine paid rewrite calls over three manual retries and produced nothing at all. Unstale now stops after the second paid failure of the same kind, and the job log says why, instead of leaving a batch that will never go through looking like a network problem. Failures that cost nothing, a blocked connection for instance, keep all three attempts as before, and a retry you start yourself always begins again with the full budget, which is what you want right after installing a fix.

1.14.3

  • Fixed: a long post could fail its refresh over and over with “The answer from the model was cut off at the output limit”, and retrying never helped. Unstale splits a long post into batches before rewriting it, and it sized each batch in words, counted after stripping every tag and every HTML comment. On a post built with blocks, a large part of a batch was therefore invisible to that budget while still having to be rewritten in full. Measured on a real site: four batches of 700 to 785 words weighed 11149, 10003, 11132 and 21080 bytes, and the heaviest one asked for more of an answer than the model was allowed to give. Because the split is the same on every attempt, that batch came back identical every time, which is why retrying could not fix it. Batches are now sized on what actually gets sent, so one can no longer quietly grow to twice the size of its neighbours.
  • Fixed: the room allowed for a rewritten batch was shared with the model’s thinking, and a model that thinks before it writes spends it there first. Same batch and same request on a real site: one attempt was cut short after 540 tokens of answer, the next one finished in 3450. That is why a batch of refreshes often needed one or more retries even on posts that eventually went through. The room allowed is now twice as large, which costs nothing extra: only the answer is billed, never the room.
  • Fixed: updating Unstale while a long post was halfway through its rewrite could publish that post with one passage duplicated and another missing. The batches already rewritten only make sense for the split that produced them, and this release changes that split. Unstale now records the split alongside its progress and starts the rewrite over when the two no longer match.

1.14.2

  • Fixed: when the AI checked a group and found no cannibalization, Content cannibalization announced it as “AI could not confirm this group”, which reads as a tool that broke rather than a check that ran. The AI had run: it read the posts, decided they do not compete for the same query, and the sentence shown under the group is its reason. That is the whole point of this check, since the first pass groups posts on shared vocabulary alone and the AI is what tells apart the ones that really compete. A verdict now reads as a verdict, and the three sentences that do announce a breakdown stay clearly apart from it.
  • Fixed: roughly one verdict in seven was paid for and never delivered. Unstale allowed 1024 output tokens for one verdict, and a model that thinks before it writes spends that room on the thinking, so the answer stopped mid-sentence and was reported as an answer that could not be read. Measured on a real site with three long posts: two calls out of thirteen were cut short at 1024, none out of twelve at 4096. The room allowed for an answer is now four times larger. The price shown before you click does not change, because it is now worked out from the output these checks actually produce instead of from the ceiling they are allowed.

1.14.1

  • Fixed: Confirm with AI, on the Content cannibalization section, answered “This cannibalization group no longer exists” for every group on screen, from the first click. The list Unstale keeps between a scan and that click is thrown away whenever any post on the site is saved, published, unpublished or deleted, by anyone and by any plugin: a refresh published by the Pro automation, a revision, a form entry stored as a post. One such event between the scan and the click was enough for the check to find nothing to confirm, and to say so about groups still on screen and still there to be computed. The check now recomputes the groups when that list is gone, exactly as the scan already did, and finds each group by the posts it holds rather than by its position in a list that may have changed shape since. A group whose composition really did change is noted under its own card and the check moves on to the next one, instead of stopping the whole run on the first.
  • Fixed: the Excluded tab on Content health listed every item of a content type Unstale never refreshes, one line each, and counted them as excluded items. A site with two thousand affiliate links stored as their own content type read “2,000+ more items are excluded” above a tab capped at a hundred pages, with the exclusions you can actually undo buried under them. A content type with no search surface is one decision, not two thousand: such types now appear once each, with a count, in their own table under the list, and the count above the list covers only what you can reintegrate, your own exclusions and the noindex ones.

1.14.0

  • Fixed: Confirm with AI, on the Content cannibalization section, answered “AI could not confirm this group” for every group and gave no reason. The model had refused nothing: its answer was cut off before it began. Unstale allowed 200 tokens for a verdict, and a model that thinks before it writes spends that room on the thinking, so the visible answer stopped after a few characters and was read as a refusal. The cap is now 1024 tokens, and an answer that is cut short or cannot be read is shown as a failure with its cause, never as a verdict. Measured on a real site: given room, the same model rejected a group of four single-plugin reviews and a group of three yearly retrospectives, each with a sentence saying why, which is exactly what this check exists to do.
  • Fixed: the AI check asked for the catalog’s recommended model instead of the one you chose in the settings. On a site with a single provider connected it landed on the right model by chance; with two, the click would have gone to the other provider at the other price while the estimate named yours.
  • Fixed: the cannibalization scan grouped content that Content health already excludes: pages your SEO plugin marks noindex, and posts you excluded by hand. A page search engines do not index competes with nothing, and a post you excluded is not one to consolidate. Both now stay out of the scan, a post excluded after a scan drops out of its group, and the Pro weekly sweep applies the same rule.
  • Fixed: after a scan, titles in the cannibalization cards could show raw HTML entities, an ampersand written as a code for instance. They now read as text.
  • Fixed: a server reply that was not JSON, a maintenance page or a firewall answering in place of WordPress, was read as an empty verdict and shown as “could not confirm”. It is now reported as a failed request.

1.13.0

  • New: a notice tells you when your default refresh level is one your plan no longer allows. Deactivate or remove the Pro add-on while Strong or Maximal is your default and every refresh stops: row actions, the REST API and WP-CLI all refuse, and no screen said why. The notice names the level and says what actually repairs it, which is to choose a level and save, not merely to open the settings screen. It changes nothing on its own. A setting you chose is not rewritten behind your back.
  • Fixed: the settings screen shows the refresh level you actually saved. When your plan locked the level you had picked, the slider slid back to Balanced on its own while the database still held Strong, so the screen said one thing and your site did another. Saving any unrelated setting on that page then wrote Balanced over your choice. The slider now reflects what is stored, even a locked level, and saving a locked level overwrites nothing: Unstale keeps your setting and names the reason it cannot be used.
  • Fixed: a model that leaves the catalog now stops the job instead of quietly calling another provider. A site that had chosen a Google model could end up calling Anthropic without asking for it, without being told, and without necessarily having connected it. The estimate showed the other model’s price, and the log, the review queue and the API could name a model that never ran. A retired model is now refused by name, and what gets logged and billed is what actually ran.
  • Fixed: the bulk refresh screen stops on a level your plan has locked, instead of sending you to check your AI provider. It priced an estimate at that level, every item then failed, and the notice blamed the provider for what was a plan problem.
  • Fixed: an Elementor floating button, the WhatsApp or contact button that hovers over your pages, is no longer treated as refreshable content. It sat in Content health with an active Refresh link and could be picked as an internal-link target. What removes it is a property any content type declares for itself, not a list of plugin names, so every page builder that registers an interface widget as public content is covered: a type its own developer keeps out of navigation menus is not editorial content. WooCommerce products declare the opposite and stay.

1.12.0

  • New: content your SEO plugin marks noindex is now left out of Content health. A page you have told search engines not to index is not a page worth spending a refresh on, and until now it sat in the list with an active Refresh link. Unstale reads that setting from Yoast SEO, All in One SEO, SEOPress and Rank Math. Each one was read against its own source and then measured on a real site, because the four disagree in ways that matter: three of them let a single post say “index” and override a site-wide or per-type noindex, one of them does not, and one stores a value whose name says index while it means the opposite. Anything Unstale cannot read for certain stays in the list. Hiding a page you are actually trying to rank is the worse mistake of the two, so every doubt is settled in favour of showing it, and settings that apply to your archives, tag pages or attachments are never read as if they applied to your posts.
  • New: an Excluded tab on the Content health screen, listing what Unstale never refreshes and who decided it. Three reasons show up there: a content type with no search surface, a post you excluded by hand, and a noindex set in your SEO plugin. The noindex rows name the plugin that set it, so a verdict you did not expect can be traced back to the screen it came from instead of leaving you to guess. Posts you excluded by hand keep their Reintegrate link right there in the tab. The tab only covers content old enough to be checked, so it is not a list of every noindex page on your site, and it says so.
  • Fixed: refusing to refresh an excluded post sent you to the wrong screen. The message said to reintegrate it from Content health, which is exactly where an excluded post no longer appears. It now names your posts list, where the Reintegrate link actually is.

1.11.0

  • New: an Exclude link, next to Refresh, in your posts list and on the Content health screen. Some posts should never be refreshed: a landing page tuned by hand, a legal notice, an article whose wording was signed off. Excluding one takes it out of the Content health screen and out of every list Unstale draws its work from, and a refresh started on it anyway is refused rather than run, so a bulk action or a job queued earlier cannot walk over your decision. An excluded post still shows in your posts list, where the link reads Reintegrate: nothing here is one-way.
  • Fixed: content types with no search surface no longer appear as posts to refresh, nor as internal-link targets. Popup Maker popups, Elementor templates and the Elementor Default Kit showed up on Content health with an active Refresh link, and Unstale could place a link to one of them inside a published article. The criterion that removes them was measured on a real site rather than guessed: a type must be viewable and not excluded from search. WooCommerce products pass both halves and stay. Attachments are dropped on their own terms, a media file not being editorial content.
  • Fixed: a bulk refresh that refuses a post now says why. When the post was of a type Unstale does not refresh, it failed without a word.

1.10.0

  • New: a refresh now checks the figures it added itself. The fact-check has always run on your original article, before the rewrite, so a price, a percentage or a date that the rewrite introduced reached the review screen without ever having been held against a source, underneath a count of checked facts that read as a green light for the whole proposal. Unstale now takes the passages carrying a figure your original article did not have, searches the web for each one, and lists on the review screen the added figures that are outdated or that no source confirms, with a source link next to each. It runs at every level, Minimal included, because a refresh adds figures there too. It calls no model at all when the refresh added none, so a rewrite that only rephrases costs exactly what it cost before. The estimate you approve before a refresh now covers the searches this step can make, which is why it reads higher than it did on 1.9.1.
  • Fixed: the line counting checked facts now says what it looked at. It reads “5 claims checked in the original article” rather than “5 claims checked”, because that check runs before the rewrite and says nothing about the text shown underneath it. What the refresh added gets its own line, right below, so the two counts can no longer be taken for one.
  • Fixed: the Journal no longer reports 0 searches for refreshes that did search the web. Not one of the AI provider plugins passes that count on to WordPress today, so zero was never a measurement, on a plugin whose live web search is the point. The Journal now says the count was not reported by the provider plugin, and the cost recorded beside it is documented as a floor rather than the whole bill: the search fee is in the estimate you approve before a refresh, not in the cost logged after it. The day a provider plugin reports the count, it shows up on its own, with nothing to change on your side.

1.9.1

  • Fixed: when the catalog replaces a model with a newer one from the same family, your site now follows the upgrade instead of staying behind. A site set to Gemini 3.7 Flash moves to Gemini 3.8 Flash, and the day Claude Sonnet 5 replaces Sonnet 4.8 a site set to the older one moves to Sonnet 5. The move stays inside the family: a replacement that would send you to a different provider, one you may hold no credentials for, is refused rather than followed. Your setting is rewritten once, so the settings screen, the job log and the cost estimate all name the model that actually runs. A model that is simply unknown is left alone, because turning a fallback into a saved choice you never made would be worse than leaving it visible.

1.9.0

  • Fixed: a refresh could change how your article speaks to its reader. An article written in the informal address came back formal, on a level whose instructions ask the model to speak to the persona the page describes: nothing told it which address the article already used, so it chose one. Unstale now measures the voice of your article before rewriting it, the form of address and the person it speaks in, and holds every step that writes to what it found. That includes the step that writes your meta description, which is the part Google shows and the part that addresses the reader most directly. An article whose voice cannot be measured is rewritten exactly as it was before, and so is any refresh queued before this version.
  • New: the Unstale block under the editor now tells you, before you start, whether the refresh will move the post’s publish date. The setting has always been there, under Republication between two time fields, and nothing said what it would do until it had done it. Reasons that depend on the post or on the moment are still settled when the refresh republishes, because they cannot be known in advance and announcing them would promise wrongly.
  • Fixed: the model catalog now records when a model is renamed. Gemini 3.7 Flash became Gemini 3.8 Flash on 4 September, and for part of that day a site that had chosen it fell back to the recommended model instead: a different provider, and about three times the cost per refresh. The catalog was corrected the same day for every site, with no update needed. From this version a renamed model keeps your choice and its own rate on the cost screen, and the job log names the reason for any substitution rather than reporting a preview that does not exist.

1.8.3

  • Fixed: on a site made of short pages, such as product sheets or answers to a single question, Content health found few competing posts and could miss two pages that said the same thing word for word. Every pair was measured against the length of a full page, so a short post never had enough to give and could not reach the mark whatever it said. A pair is now measured against the shorter of the two posts, so short pages that cover the same ground are found the way long ones already were. Posts long enough to fill a comparison are scored exactly as before, so nothing Unstale already found on your site moves. Pages carrying too little distinctive text to say anything either way are still left out rather than guessed at.

1.8.2

  • Fixed: on a site written in a language that does not put spaces between words, Content health found very few competing posts, and often none at all. Unstale compares character sequences instead of words for those languages, but it decided when to switch by counting characters per word, and Chinese never reached the mark: Chinese punctuates, so every comma cut the text into pieces short enough to pass for ordinary words. Thai did not reach it either. Japanese did, but only past a length that was there to protect German compound words, so shorter Japanese posts stayed invisible whatever they said. Unstale now looks at the writing system itself, so Chinese, Japanese, Thai, Lao, Khmer and Burmese are compared properly at any length. Korean, which does separate its words, is unchanged, and so is every language written with spaces.

1.8.1

  • Fixed: on the Content health screen, a group of more than 25 posts that share a vocabulary is a template rather than competition. Product listings, location pages and archives are built from one layout, so Unstale never sends such a group to the optional AI pass and never charges you for a verdict on it. The screen did not say so: it showed “AI could not confirm this group.”, word for word what it shows when the model has looked at a group and disagreed. A template therefore read as a verdict that had never been asked for, which is the most reassuring way to be wrong. These groups now say that the pages share a layout rather than a topic, and that no model was called. A group the AI genuinely could not confirm, and a provider that failed to answer, still say exactly what they said before.

1.8.0

  • New: the Content health screen now also finds published posts that compete with each other over the same topic, grouped together with the post Unstale would keep and why. The comparison runs on your own site, with no AI provider needed and at no cost: it looks only at your own text, never at anyone’s rankings. With an AI provider connected, an optional AI pass on each group tells two posts that merely share vocabulary from two that genuinely target the same query, and says in one line why it disagrees when it does, before you decide what to do about it. The screen tells you what that pass would cost before you start it, and calls no model until you say so.
  • If you use the Unstale Pro add-on, groups found by its weekly sweep now show on this screen too, whatever content types you are allowed to edit. Until now the sweep could report a group by notice that the screen itself would not list. Needs Unstale Pro 1.3.0 or newer; without the add-on nothing changes.

1.7.0

  • New: a Get started screen, which opens by itself the first time you activate Unstale. It lists the five posts that have gone longest without an update, with their age, and one button that queues all five. Nothing is spent from that button: it hands you the same estimate screen every other launch goes through, so you still see the cost and confirm before any model is called. If no AI provider is connected yet, the five posts are shown anyway, with a link to connect one: you see what Unstale would work on before being asked for anything. The screen stays in the Unstale menu as Get started, so you can come back to it whenever you want a batch ready to launch.

1.6.0

  • New: a Restore button in the Unstale block, on a post whose refresh has been published. It puts the post back as it was before that refresh: the text, the publish date the refresh moved, and the SEO title and description it wrote. Field by field, and only what the refresh itself changed: anything you edited since stays yours, and the confirmation screen names exactly what will go back rather than quietly overwriting the rest.
  • New: a notice across the admin when refreshes are waiting for your review. A refresh that finishes while you are working elsewhere no longer waits unnoticed. With one waiting, the notice opens its diff directly; with several, it opens the review queue. It stays off the Unstale screens, which already list that queue.
  • New: the Unstale column in the posts list now colours the age of the last refresh, on the same thresholds as the Content health screen. One glance down the list shows what has drifted, without opening another screen. The colour only repeats what the cell already says in words, so nothing is lost if you do not see it.
  • New: an Export CSV button on the Journal, which carries whatever filter you are looking at. Costs come out as plain numbers a spreadsheet can add up, and the file holds only the posts you are allowed to edit.
  • New: the refresh level slider in Settings now shows what each level costs per 1,000 words, and the figure follows both the slider and the model you pick. The levels reserved for Unstale Pro show their cost too, so you can see what they would cost before deciding.

1.5.1

  • New: if you use the Unstale Pro add-on, the Unstale block under the editor now tells you what the automation decides for the post you have open: which category rule governs it, the refresh level that rule imposes, and when the next scheduled pass runs. Above all it says when a rule excludes the post, which until now was invisible: you could believe a post was covered by the automation while nothing would ever pick it up. Needs Unstale Pro 1.0.3 or newer; without the add-on, or on an older one, the block looks exactly as it did.

1.5.0

  • New: an Unstale block under the post editor, above the one your SEO plugin puts there. Pick a refresh level, start the refresh and follow it step by step without leaving the page you are writing on, in both the block editor and the classic editor.
  • New: once a refresh is ready, that same block lists everything it did to the post: how its length changed, which outdated facts were corrected and against which source, the new meta title and description, the structured data, every internal link placed with its anchor, and the blocks inserted into the body.
  • New: on the free plugin, picking Strong or Maximal opens a note saying what that level would add to the post you have open, naming the secondary queries, the reader profile, the content gaps and the products Unstale already found for it. With no refresh run yet it says what those levels do without putting numbers on it: nothing is invented to make the case. The note stays out of the way until you ask for it, and it does not exist at all once a Pro licence unlocks those levels.

1.4.2

  • Fixed: on the Content health screen, every post that had never been refreshed carried an empty line inside its Unstale cell. The Refresh link dropped to the bottom of the cell and the row stretched to match. A site that has just installed the plugin has refreshed nothing yet, so the whole table showed it, and Content health is the first Unstale screen a new site opens.

1.4.1

  • Fixed: the model catalogue shipped with the plugin still expected Claude Sonnet 5 to get more expensive on 1 September. Anthropic made its $2 / $10 per million tokens permanent on 10 August and cancelled that increase. Sites already pick up the correction from the online catalogue within a day; this puts it in the plugin itself, so a fresh install starts with the right figure.
  • New: if you use the Unstale Pro add-on, its licence key field now appears in Unstale > Settings, next to the refresh levels it unlocks, instead of only under its own Licence menu. Nothing changes without the add-on.

1.4.0

  • Fixed: on a site using All in One SEO, a refresh wrote its new title and description where nothing ever read them. AIOSEO has kept its data in its own table since version 4, and the fields Unstale was writing are only read once, when migrating from version 3. Your pages did not move, and the journal still reported success. Unstale now writes through AIOSEO’s own interface, and All in One SEO joins Yoast, Rank Math and SEOPress in the supported list.
  • Fixed: the cost announced before a refresh was far too high on Google models, by about fifteen times. Two separate causes. The token estimate was calibrated on a provider that bills web search results as input tokens, which Google does not. And the free monthly search allowance some providers grant was never taken into account, although the plugin already knew about it. On a 500-word article at the Balanced level, the estimate went from 24 cents to 4, against 2 cents actually measured.
  • Fixed: Elementor, Divi and SeedProd pages no longer raise a page builder warning. Those three are exactly what a refresh knows how to handle without moving your layout, so sending them to a notice that said the result may be unexpected told you the opposite of the truth. The warning is now kept for a builder Unstale has no adapter for, and it says what would really happen: the refresh would rewrite the standard WordPress content, not the page your visitors see.
  • Fixed: a page builder section holding a script or a style block could carry that code into the rewritten text. The block is now removed with its contents.
  • Improved: the cost question in this readme now gives the real range across the catalogue instead of a single guess, and says when web searches are covered by a provider’s free monthly allowance.

1.3.2

  • Fixed: on a site running PHP 8.1, Unstale did not work at all. One of its files used a piece of syntax that …