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

Beschreibung

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, fact-checks its most important claims against what it finds, rewrites the text, updates the SEO metas from the Balanced level up, 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 the claims that matter. Before the rewrite, the refresh checks the most important figures, prices and dates of the post against the web, and the rewrite corrects the outdated ones. The summary in the review queue and under the editor lists each correction, with a link to the source when it found one. A second pass checks the new figures the rewrite added to the text and flags the ones no source confirms.
  • 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.
  • Year references that follow the calendar. A year written to say the content is current, „best laptops 2025“, „updated for 2025“, is moved to the current year in the text and, from the Balanced level up, in the title and the metas. A year that dates an event, a release, a study, a law, stays as it is. In the meta title and description the year is written as the current-year variable of your SEO plugin, Yoast SEO, Rank Math, All in One SEO or SEOPress, so it follows the calendar on its own. If you run a current-year shortcode plugin, the text and the title get its shortcode instead, and only where it actually renders.
  • Internal linking. Up to 15 relevant internal links per refresh, with natural, varied anchors, one link per target page.
  • Alt text and captions that match the image. In posts written with the block editor or the classic editor, the model looks at each image from your media library, up to ten per post, and rewrites the alt text only when it is empty, a file name, generic or wrong. From the Balanced level up it can add a caption where the image has none and one would help the reader. An image whose media library alt text is empty gets the new one there too, and Restore the previous version empties it again. The review queue lists every image it changed. Models that do not read images skip this step at no cost.
  • 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. Other builders are not recognised out of the box: a page built with one gets no warning and is refreshed like a standard post, so check it before you refresh it.
  • 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 an estimated cost 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 a refresh you confirm from the editor, the posts list or Content health, 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. Automatic publishing, which skips this step, is off by default and switched on in the settings. Before it publishes, Unstale saves the current post as a WordPress revision when revisions are enabled on your site. WordPress does not version Elementor or SeedProd layouts, so for those the job keeps its own copy instead. The Restore the previous version link under the editor puts the post back from either one, after a screen that names what it restores. An AI agent connected to your site prepares refreshes the same way, and cannot approve one unless you allow it in the settings.

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 the new date would change the post’s address, whichever date tags your permalinks use, and when a refresh changed nothing in the text. 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 image files and your builder settings come back exactly as they were. The alt text of an image that already has one counts as text, and the rewrite can change it. 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), WP-CLI (wp unstale refresh) and WordPress abilities that AI agents reach through the MCP adapter.

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

External services

This plugin relies on two external services.

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 a refresh you confirm.

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

YouTube oEmbed (youtube.com)

What it is: YouTube’s public oEmbed endpoint at https://www.youtube.com/oembed. During a refresh, Unstale asks it whether each YouTube video embedded in the post is still available, and checks a replacement video the same way before using it.

What is sent, and when: the public address of each YouTube video embedded in the post being refreshed, and of each replacement video before it is used, and nothing else. No content, no credentials, no site identifier. It is an unauthenticated GET, sent only while a refresh runs on a post that embeds YouTube videos. Each answer that says whether a video is available is cached for 24 hours.

This service is provided by Google: Terms of Service, Privacy Policy

A note on AI providers

Unstale does not contact any AI provider itself (Anthropic, OpenAI, Google AI) 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. To check alt text, a refresh also hands the WordPress AI Client the image files of the post, read from your own media library, so they reach that same provider.

Screenshots

Installation

  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. Open Unstale > Get started and follow the checklist: connect a provider, pick a model it serves, refresh one post, then read the diff.
  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.

Video walkthrough: https://www.youtube.com/watch?v=7YLuWUl5jZQ First refresh, from the estimate to the approval: https://www.youtube.com/watch?v=dzC125M6iek

FAQ

How much does a refresh cost?

You pay your AI provider directly, per token. Unstale shows an estimate before a refresh you confirm from the editor, the posts list or Content health, 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.70 on the dearest, depending on the model you pick. That estimate is conservative, not a ceiling: its token counts are calibrated on real pipeline runs and it counts every web search the level allows, so the cost logged after the run usually comes in 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, and it is skipped when the refresh changed nothing in the text.

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. Automatic publishing skips that step, and only runs if you switch it on in the settings.

Can an AI agent such as Claude Code, Codex or Hermes Agent drive Unstale?

Yes. Unstale registers WordPress abilities that list your stale content, estimate a refresh, start it, follow it and read its fact-check. With the MCP adapter plugin active (it is published on GitHub), your agent connects to a dedicated Unstale server with an application password, and the Unstale > AI Agent screen gives the configuration for each client, plus an SSH variant. The agent talks to your site directly: nothing goes through unstale.ai. It prepares refreshes but cannot approve or reject them unless you switch on „Let AI agents approve or reject refreshes“ on that same screen. With Unstale Pro, a refresh can also carry a custom instruction, such as a keyword to target.

Does it rewrite my titles?

Only the year in them. From 1.15.0, a refresh at the Balanced level or above can update the post title, and the one change allowed there is a year that dates the content: „Best laptops 2025“ becomes „Best laptops 2026“, or the shortcode of your current-year plugin where it renders. A title that would differ from the original in any other way is refused and the original stays. The slug never changes, the proposed title is shown in the review queue before anything is published, and the revision taken before publication keeps the previous one.

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

No: the bump is skipped automatically for any post whose address would change with the new date, whichever date tags your permalinks use (year, month, day, hour, minute or second, or a structure of its own for a post type). 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. Out of the box, Unstale recognises no other builder: such a page gets no warning, and the refresh rewrites its standard WordPress content, which may not be what your visitors see. A developer can register a builder with the unstale_builder_detectors filter; if Unstale has no adapter for it, it then asks you to confirm before refreshing its pages.

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?

The models in Unstale’s catalog, for the provider you connected. Unstale ships model cards for Gemini 3.8 Flash (default on new installs), Claude Sonnet 5.5 and GPT-6 Sol, with pricing and ratings to help you choose. A site that already ran Unstale keeps the model it had. 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.

Rezensionen

Zu diesem Plugin liegen noch keine Rezensionen vor.

Mitwirkende und Entwickler

„Unstale – Refresh Old Posts with AI, Fact-Check & Republish“ ist Open-Source-Software. Folgende Menschen haben an diesem Plugin mitgewirkt:

Mitwirkende

Änderungsprotokoll

1.35.2

  • Fixed: the old URL of a post whose slug uses non-Latin letters (Cyrillic, Greek, Chinese and others) now redirects to the post that replaced it, instead of returning a 404.
  • Fixed: the Add a redirect form keeps such URLs whole instead of cutting them short.

1.35.1

  • Fixed: the research step now sends the opening of the post with its keyword, so Google’s content filter no longer blocks it by mistake on a short product name.
  • Improved: a request blocked by Google’s content filter now says so and is not retried, since the same request gets the same refusal.

1.35.0

  • New: Unstale > Redirects is always in the menu, with an Add a redirect form to send an old URL of your site to a published post.
  • New: when a post that other redirects point to is retired in turn, those redirects now go straight to the new post, in one hop.
  • New: a redirect can no longer point to a post that is not published, and a notice on the Unstale screens counts the redirects that stopped working.
  • New: Restore the previous version of a consolidated post names the retired posts that still redirect to it.
  • Improved: the journal line of a consolidation names the posts it absorbs.
  • Fixed: on Elementor, Divi and SeedProd posts, a link of the original post in a heading or a button text is kept at publication, and no internal link is added there.

1.34.0

  • New: a refresh that points a link of the original post somewhere else now waits for your review, even with automatic publishing on.
  • New: a refresh that removes a link of the original post waits too, at the Minimal, Balanced and Strong levels. At Maximal the removed link is listed without holding the refresh.
  • New: the review queue lists removed links, changed link targets and other added links.
  • New: the Unstale block under the post editor counts the links of the original post that the refresh lost.

1.33.1

  • Fixed: a rewrite that loses a shortcode, embed or script now fails that part at once and retries it alone, instead of failing the whole refresh at publication after every step was paid.

1.33.0

  • New: in block editor and classic editor posts, the refresh shows each media library image to the model and rewrites alt text that is empty, a file name, generic or wrong.
  • New: from the Balanced level up, a caption is added where an image has none and one helps the reader.
  • New: an empty alt text in the media library is filled at publication, and Restore the previous version empties it again.
  • New: the review queue lists every image the refresh changed.
  • New: the cost estimate counts the images of the post.
  • Models that do not read images skip this step at no cost.
  • Fixed: the wrong choices of a Pro quiz are no longer fact-checked as new claims, which held some refreshes in review.

1.32.6

  • Fixed: a brief outage of the provider’s model list no longer fails a refresh; the step is retried, and a provider that is really disconnected still fails after the last attempt.
  • Fixed: Retry refuses a refresh whose post changed since it started, before paying for any step, and asks for a new refresh.
  • Fixed: the enrich and internal linking steps get the same output budget as the rewrite, so a thinking model is no longer cut off.
  • Improved: when a model answer cannot be read as JSON, the whole answer is kept in the job log.

1.32.5

  • Fixed: the editor block no longer says you can keep writing during a refresh; editing the text makes publishing refuse it, and the block now says so.
  • Fixed: the refresh summary counts outdated facts as found, not corrected.
  • Fixed: with an SEO plugin active, structured data shows as proposed, not written, instead of ready to publish.
  • Fixed: the review queue shows web searches the provider did not report as n/a instead of 0.
  • Fixed: a published refresh in the review queue links to Restore the previous version instead of pointing to native revisions.
  • Fixed: a Divi or Elementor page whose text cannot be extracted stops before any AI call.
  • Fixed: Divi and Elementor refuse to publish a shortcode placeholder the model wrote.
  • Fixed: a self-closing SVG icon no longer hides the text after it from the rewrite.

1.32.4

  • Changed: the model catalog carries Google’s new Gemini Flash rate ($1.50 / $7.50 per million tokens from January 1, 2027); estimates keep the current rate until then.

1.32.3

  • Fixed: activating Unstale from the Plugins screen opens Get started again; a background request no longer used up the redirect.

1.32.2

  • Fixed: Confirm with AI on the cannibalization screen stops at the first refusal when the default model is not served, and shows the reason once instead of failing group after group.

1.32.1

  • Fixed: Unstale admin screens load their scripts and styles again while refreshes wait for review; the menu badge no longer breaks them.

1.32.0

  • Fixed: a refresh no longer runs on another provider’s model when the default model’s provider is not connected; it is refused and names the setting.
  • Fixed: when a provider runs a different model than the one requested, the log names it and the cost follows it.

1.31.0

  • New: a refresh checks that the YouTube videos in the post are still available.
  • New: a deleted, private or non-embeddable video is replaced with a relevant YouTube video found by web search and checked before use.
  • New: the review screen lists the videos that were replaced or kept.
  • Improved: the plugin’s outbound requests no longer send your site’s address.

1.30.2

  • Fixed: the fact check now knows today’s date, and no longer names the „latest“ or „flagship“ version of a product from the model’s memory.
  • Improved: a fact-check correction only says what its source says, prefers sources from the last 12 months, and links to the page itself rather than a home page.

1.30.1

  • Fixed: the publish date no longer moves when the new date would change the post’s address. Hour, minute and second tags, and post types with a dated structure of their own, are now covered.
  • Improved: a year in your permalinks no longer stops the date from moving on a post whose year stays the same.

1.30.0

  • New: with automatic publishing on, a refresh waits for your review when the fact check finds an outdated figure it added, instead of going live with it.
  • New: the Unstale menu shows how many refreshes are waiting for your review.
  • Improved: the review notice and the editor box say why a refresh waits while automatic publishing is on.

1.29.4

  • Fixed: video and other embed blocks are kept out of the rewrite and come back exactly as they were, so the AI can no longer break their markup and get the refresh refused.

1.29.3

  • Fixed: a rewrite whose block comments came back with a closing comment missing its dashes, or a paragraph or list item missing its opening comment, is repaired instead of refused, so the refresh no longer fails after two paid attempts.
  • Improved: when a rewrite is still refused for its block markup, the error shows the passage where the markup breaks.

1.29.2

  • Fixed: a post with a code sample in a shortcode that opens an HTML tag it never closes is refused before any AI call, instead of at publication after every paid step.
  • Fixed: on SeedProd pages, a year inside a shortcode no longer publishes as a raw %%UNSTALE_YEAR%% marker.
  • Fixed: on SeedProd pages, the publish date stays when the live page still shows the previous text.

1.29.1

  • Fixed: in Settings, a model card that carries a badge keeps its name next to the radio button instead of pushing it to a second line.
  • Fixed: the „provider not connected“ badge stays on one line on narrow screens.

1.29.0

  • Changed: the publish date moves only when the refresh changed the text of the post. A refresh that only adds links, edits markup, metas or the title year leaves the date where it was.
  • Improved: the review screen says when a refresh changes nothing in the text and the date will stay, and the job summary names that reason.
  • Improved: model cards in the settings carry a „Best for quality“ or „Best for volume“ badge from the catalog, and the ratings follow a revised method.
  • Fixed: on Content health, the Bulk actions menu and its Apply button stay visible on screens narrower than 782 px.

1.28.2

  • Fixed: a long post built with blocks no longer stops at the rewrite step with „block comments unpaired“. A long section is now cut between blocks, never inside one.
  • Fixed: an H2 carried by a third-party heading block, GenerateBlocks Headline for example, stays with its block when the post is split.
  • Changed: Claude Sonnet 5.5 is the default model on a new install. It replaces Claude Sonnet 5 at the same price.

1.28.1

  • Fixed: a rewrite that breaks the block markup of a post, a list item left open or a stray closing comment, is retried instead of reaching the review queue.
  • Fixed: publishing refuses to write block markup in worse shape than the original post, which stays untouched.
  • Fixed: without an SEO plugin, the JSON-LD Unstale prints no longer carries publication or update dates written by the model.
  • Improved: Get started loads much less data on sites with many refreshes.

1.28.0

  • New: Get started is a checklist that reads your site: provider connected, model served, first post refreshed, diff reviewed. One action at a time, nothing to tick by hand.
  • New: the first refresh is one post, chosen among the five that waited longest, with its estimate before anything is spent.
  • New: when the default model needs a provider you have not connected, one click switches to a model your connected provider serves, the recommended one first.
  • New: a notice tells you when your provider is connected, and a notice on the Plugins screen replaces the redirect after a group activation.
  • Improved: an empty review queue sends you to Get started instead of the Posts list.

1.27.0

  • New: a Writing section in Settings, where an add-on can put its writing fields.
  • New: add-ons can store their settings in a refresh when it starts.

1.26.0

  • New: Unstale > AI Agent, a screen of its own to connect Claude Code, Codex, Hermes Agent or any MCP client. Settings no longer carries it.
  • Improved: „Let AI agents approve or reject refreshes“ moved to that screen, with its own Save button. Your current choice is kept.

1.25.0

  • New: Gemini 3.8 Flash is the recommended model, marked with a Recommended badge in Settings, and the default on new installs.
  • Unchanged: a site that already runs Unstale keeps the model it had, even if it never saved its settings.
  • Changed: GPT-6 Sol replaces GPT-5.6 Terra in the model cards. A site set to Terra moves to GPT-6 Sol, same provider.

1.24.3

  • Fixed: when you schedule a refresh, page builder posts that are already scheduled are no longer counted as moving to the new date unless you include them.

1.24.2

  • Fixed: with „Let AI agents approve or reject refreshes“ off, an AI agent can no longer cancel a refresh that reaches the review queue during its request.
  • Fixed: for an older job, unstale/get-job returns the stored post content as the original, not a copy altered by display filters.
  • Improved: unstale/list-stale-content declares min_age_days as always present, and unstale/estimate-refresh no longer says only published posts can be estimated.

1.24.1

  • Fixed: a bulk refresh or schedule from Content health no longer fails with „The link you followed has expired“ when the selection includes a page builder post.
  • Improved: the estimate screen shows what including page builder posts adds to the cost, before you tick the box.

1.24.0

  • New: AI agents such as Claude Code, Codex and Hermes Agent can drive Unstale: list stale content, estimate, start, cancel and retry refreshes, and read their fact-check.
  • New: eight WordPress abilities in an Unstale category, and a dedicated „unstale“ MCP server when the MCP adapter plugin is active.
  • New: Settings > Connect an AI agent shows the adapter status and a ready-to-paste configuration for each client, plus an SSH variant.
  • New: approving or rejecting a refresh stays with a person by default. The „Let AI agents approve or reject refreshes“ setting opens it to agents.
  • New: the review queue shows the custom instruction a refresh was started with, above the fact-check.
  • A custom instruction attached to a refresh requires Unstale Pro.

1.23.0

  • Improved: the review queue now shows the fact-check above the diff: the outdated facts it found, with their source, and the new figures no source confirms.

1.22.2

  • Fixed: publishing a refresh no longer removes scripts, embeds, inline SVG icons, forms or styles from the original post. They come back byte for byte, widgets included.
  • Fixed: when a refresh would lose one of those elements or an original shortcode, Unstale refuses to publish it and leaves the post untouched.
  • Fixed: Restore puts back the content the refresh replaced, even when a cleanup plugin has purged the post revisions, and says so when it cannot.
  • Fixed: a Divi or Elementor page with a script, embed, icon or form inside a text module now stops before any AI call, instead of failing after paid steps.
  • Fixed: stricter filtering of the model’s output before publishing, including markup hidden inside HTML comments.
  • A refresh already waiting for review is refused at publication if it lost one of those elements: run a new refresh.

1.22.1

  • Fixed: a post whose blocks store large hidden settings, such as widgets from older Travelpayouts versions, no longer fails its refresh with „The answer from the model was cut off at the output limit“.
  • Improved: those hidden block settings no longer reach the model at any step, so such posts cost a fraction of what they did, and the settings come back byte for byte.

1.22.0

  • New: Schedule refresh, in the Bulk actions of Content health, plans a one-off refresh of the articles you picked, on the date and time you choose.
  • New: a scheduled article shows „Scheduled for“ its date on Content health, with a Cancel link.
  • New: a scheduled refresh that WordPress runs more than a day late starts nothing, and the article says why.
  • Improved: excluding a scheduled article, or refreshing it from anywhere else, cancels its schedule.
  • New: Exclude joins Refresh selected in the Bulk actions of Content health, so a whole selection leaves the list in one go.
  • New: Show all puts the whole list on a single page, with your tranche and your search kept.
  • Improved: the title of an article opens its public page in a new tab, on Content health and on Excluded.

1.21.0

  • Improved: a consolidation from Unstale Pro waits in the review queue even when automatic publishing is on.
  • Improved: the automatic publishing setting and the block under the editor say that consolidations still wait for your review.

1.20.2

  • Fixed: with automatic publishing on, the block under the editor and the queued notices no longer promise that the refresh waits for your review.
  • Fixed: the plugin description no longer claims that every figure is checked. The fact-check covers the most important claims, and a second pass checks the figures the rewrite adds.

1.20.1

  • Fixed: a consolidation saved while a scan or a restore updates the same list at that moment is no longer lost.
  • Fixed: restoring or publishing a SeedProd page built with Pro blocks updates the cannibalization scan right away, instead of up to 12 hours later.
  • Fixed: a scan that finishes after an article changed no longer serves results computed before the change.

1.20.0

  • Fixed: a group you consolidated no longer vanishes from the scan once the keeper absorbs the other articles, as long as one of them is still published.
  • Improved: the card of a consolidated group names the article it was consolidated into, with the date, and keeps that article as the keeper.
  • Improved: restoring the previous version of a consolidated keeper forgets that consolidation, so the group is checked afresh.
  • Remembering new consolidations needs Unstale Pro 1.9.0. Update the free plugin first and Pro second.

1.19.0

  • Fixed: when Confirm with AI keeps only part of a group, the card greys out the articles it left out, marks the keeper the AI chose and says how many it confirmed.
  • Improved: each AI verdict is kept with its date and survives a page reload, until the group itself changes.
  • Improved: a group the AI found free of cannibalization shows no keeper, and a failed re-check keeps the previous verdict.
  • Consolidating only the confirmed articles needs Unstale Pro 1.8.0. Update the free plugin first and Pro second.

1.18.0

  • New: when an article is retired into another one, its URL sends visitors to the article that absorbed it, with a permanent redirect served by the plugin itself. It works the same on Apache, nginx, IIS and LiteSpeed, and nothing is ever written to your .htaccess file.
  • New: a Redirects screen lists those redirects and undoes them, either by removing the redirect alone or by publishing the article again. It appears once the site has at least one.
  • A redirect stops firing on its own the moment its article is published again, without you touching anything.
  • Retiring an article is done by Unstale Pro 1.7.0. Update the free plugin first and Pro second.

1.17.1

  • Fixed: on a site whose year comes from a date shortcode plugin (Dynamic Month & Year, Runthings, Current Year Shortcode, Shortcode for Current Date, WP Date and Time Shortcode), a refresh could end on „A shortcode placeholder was lost during the rewrite“ and publish nothing, after every step had run. The year now travels as the refresh marker instead of a shielded shortcode, and comes back as your plugin’s shortcode.

1.17.0

  • New: a search box on Content health filters the list by title and slug, case and accents ignored, without reloading the page. The age threshold, the tranches, your exclusions and the noindex rule keep their meaning.
  • Improved: the meta title and description carry your SEO plugin’s current-year variable (Yoast SEO, Rank Math, All in One SEO, SEOPress) instead of a fixed year, at Balanced and above.
  • Fixed: on an Elementor page, a style edit made in the builder while a refresh waited for review was undone on approval. Publication now refuses, without writing anything, if the layout changed since the refresh started.
  • Fixed: a refresh that leaves an Elementor, Divi or SeedProd layout unchanged keeps its point of return, which 1.16.0 dropped.

1.16.0

  • New: Restore the previous version now works on pages built with Elementor, Divi and SeedProd. Each builder records what the refresh is about to overwrite, layout included, and puts it back on click.
  • Fixed: on an Elementor page, visitors could see the old text for up to a day after publication. Elementor’s element cache is now cleared on every write.
  • Fixed: the restore link and its notices say what will actually be put back on a builder page, and a restore completed halfway is logged and can be tried again.

1.15.0

  • New: year references now follow the calendar. „In 2025“ or „updated for 2025“ reads the current year after a refresh, in the text at every level, in the title and metas at Balanced and above. A year that dates an event stays as it is.
  • New: with a current-year shortcode plugin active, the refresh writes its shortcode instead of a fixed year, only where it has been measured to render. Five plugins are recognised, and the unstale_year_token filter sets your own token per surface.
  • New: the post title is refreshed at Balanced and above, by its year only. The slug never moves, and a title you edited during the refresh is never overwritten.
  • Unstale Pro 1.6.0 needs this version. Update the free plugin first and Pro second.

1.14.4

  • Fixed: a step that failed twice in the same paid way no longer buys a third identical attempt. Failures that cost nothing keep their three tries, and a manual retry always starts with the full budget.

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“. Batches are now sized on what is actually sent, not on a word count that ignored block markup.
  • Fixed: the room allowed for a rewritten batch was shared with the model’s thinking. It is now twice as large, at no extra cost.
  • Fixed: updating Unstale halfway through a long rewrite could publish a post with one passage duplicated and another missing. The rewrite now starts over when the split changed.

1.14.2

  • Fixed: when the AI found no cannibalization in a group, Content cannibalization said „AI could not confirm this group“, which reads as a breakdown. A verdict now reads as a verdict.
  • Fixed: roughly one verdict in seven was paid for and never delivered, cut short at 1024 output tokens. The room allowed is now four times larger, and the price shown before you click does not change.

1.14.1

  • Fixed: Confirm with AI answered „This cannibalization group no longer exists“ for every group as soon as any post on the site had been saved since the scan. The groups are now recomputed and matched by their posts.
  • Fixed: the Excluded tab listed every item of a content type Unstale never refreshes, one line each. Such types now appear once, with a count, and the count above the list covers only what you can reintegrate.

Older versions: unstale.ai/changelog