
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, 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, 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, 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.
- 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 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. Automatic publishing, which skips this step, is off by default and switched on in the settings. Approved changes are saved as a normal WordPress revision when revisions are enabled on your site, and the Restore the previous version link under the editor puts the post back, after a screen that names what it restores.
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.
Screenshots

Content health: which published content has gone stale, and by how much

Side-by-side diff before approval

Review queue with per-job actions

Settings: connected AI provider, model cards, and what each refresh level costs per 1,000 words

Journal: every refresh with its token counts and real cost, exportable to CSV

The Unstale block under the post editor: start a refresh, then read what it changed

Get started: the five posts that have waited longest, and one button to queue them all