Changelog
Changelog
What changed, and why. Current version: 1.38.2.
1.38.2
- Fixed: Home and the Managed Pro reminder no longer suggest that AI answer tracking asks ChatGPT. It asks Claude with live web search, and now says so.
1.38.1
- New (technical view): Home opens with a technical snapshot: pages measured and their average AI quotability, pages with no description, pages nothing links to, thin pages, open findings by priority, the last check's duration and AI use, and whether background jobs run. Each figure opens the list behind it.
1.38.0
- New: messages from DiverzitySEO. New releases and announcements appear at the top of the plugin's screens, and the important ones on the WordPress Dashboard and Plugins screens. Each can be dismissed.
- New: "Prepare fixes". On AI answers, the FAQ and structured-data checks offer to prepare one-click fixes for the pages that gain most; Reports → Pages does the same for missing descriptions and long titles. Fixes wait in To-do until you apply them.
- New: on the Managed plan, Home shows one Managed Pro feature a week, in your site's own numbers, and can be hidden for two weeks.
- Changed: the technical view is part of Managed Pro and Lifetime.
- Fixed: a long article idea no longer runs out of the "Articles this month" panel on Home.
1.37.0
- New (technical view): Reports → Pages. Every published page in one table: search title and description length, structured data, words, how quotable it is for AI, internal links in and out, Google clicks, impressions and best position, and open to-dos. Sort by any column, filter by problem (no description, title too long, thin, no links in, position 5–20, out of date), search, and export to CSV.
- New (technical view): Reports → Checks & health. Whether background jobs run (and which are overdue), the connection to DiverzitySEO with a Test button, PHP limits, HTTPS and versions, when each job runs next, and a log of recent runs with duration, score, findings, AI calls and tokens.
- New (technical view): every finding in To-do has Details: priority out of 10, the check that raised it, the fix and what it is aimed at, and for an applied fix what was there before next to what is there now.
- Fixed: the History link on Home opened open findings instead of applied ones.
1.36.4
- Improved: security and reliability.
- Fixed: a database error on every upgrade, caused by a SQL comment in the runs table definition.
1.36.3
- New: quiet hover and entrance motion. Home panels lift slightly under the pointer, fix rows and table rows light up, buttons lift and press, the current tab has a coral underline that grows in, and arrows lean toward where they lead. Pages fade in panel by panel. All of it turns off when the system asks for reduced motion.
1.36.2
- Changed: Getting started is now one row at the top of Home until setup is finished. It shows only the step to do now, with its button, and dots for where you are; it moves on by itself as steps are done.
- New: the optional Search Console step can be skipped ("Skip for now"); the row then moves to the next step.
- New: Settings → Search Console has an eight-step setup guide, with links to each Google page and a Copy button for the redirect address. It is open until Search Console is connected.
- Changed: a larger logo in the top bar.
1.36.1
- Fixed: on DiverzitySEO credit, a check could fail with "fallbacks: Extra inputs are not permitted" when the control panel was on an older version. The site no longer sends that field; the control panel (0.7.1) adds it, with the header it needs, for the models that support it.
- New: Home has a "Scores over time" chart (Google and AI-answer scores at every check, drawn in on load, values on hover or with the arrow keys) and three rings: Google score, AI readiness and the share of to-dos done. The same numbers are in a table for screen readers.
- Changed: the Home panels are more compact: smaller headline numbers, tighter spacing, and the fix list shows four items.
1.36.0
- New: a new look for every screen. One dark top bar with six sections (Home, To-do, Articles, AI answers, Reports, Settings), Archivo type, and a matching light and dark theme. Redirects now sit under To-do and AI usage under Reports; the WordPress side menu shows the same six sections.
- New: Simple and Technical views, switched from the top bar and remembered per user. Simple (the default) uses plain words and hides tokens, models, categories and other detail; Technical shows everything.
- New: Home answers "is my site getting better, and what do I do now?" in five panels: fixes ready to apply (with Apply all), how findable the site is on Google, how ready it is for AI answers, articles this month against the plan limit, and what was changed for you this month.
- Changed: the Usage screen lists AI tasks in plain words ("Wrote a search snippet") and counts this month's tasks; token and cache figures are in the Technical view.
- Changed: clearer button and page wording ("Check now", "Write an article now") and plain-language labels on AI answers.
- Fonts: Archivo and JetBrains Mono ship with the plugin under the SIL Open Font License (admin/fonts/OFL.txt); nothing is loaded from outside the site.
1.35.0
- Fixed: every plugin screen was 20px wider than the window and scrolled sideways, on desktop and phones. Wide tables now scroll inside their own card.
- Changed: findings show their priority as High, Medium or Low (the 1–10 number is in the tooltip) and their category in words ("Internal links", not internal_linking). The coloured stripe down every row is gone; the priority pill already says it.
- New: on phones each finding is a card — priority and category, the finding, the post, then Apply and Dismiss side by side.
- New: Settings has a bar of section links that stays in view and marks the section you are reading.
- Changed: on DiverzitySEO credit, API Usage shows the credit remaining, model names read "Claude Opus 5.5" and dates use the site's format. Client reports on credit show credit, not per-call costs.
- Fixed: the dashboard no longer shows a 60-day chart that is a flat line at zero, and no longer repeats the biggest win next to a summary that already says it.
- Changed: notices, the audit progress bar and callouts use a tinted ground and a thin outline instead of a thick coloured left edge.
1.34.0
- New: Claude Opus 5.5, Sonnet 5.5, Haiku 5.5 and Fable 5.2. Opus 5.5 is the new default — better than Opus 4.8 and 20% cheaper.
- Fixed: the newest models refuse the forced tool call every audit, fix and article used for its structured answer, and refuse it on any model while it thinks. Models with JSON output now get the schema as output_config.format; length and count limits the validator rejects are written into the field descriptions instead.
- Fixed: models that always think spent short answers' whole max_tokens on thinking and returned nothing. They now get room to think and an explicit effort — low for short tasks, medium otherwise.
- New: when Claude declines a request it is reported as such, and on the newest models a declined request is answered by the next suitable model instead (server-side fallbacks). Usage is billed at the model that answered.
- Fixed: prices for every current model, including Haiku 5.5's higher rate past 100K prompt tokens and per-model cache-read prices.
- New: on the Managed plan, two AI articles a month written on demand (the button shows how many are left); scheduled articles stay Managed Pro. Each Pro feature — Autopilot, AI answer tracking (up to five questions), merge plans and client reports — can be tried once, counted by the control panel. A short note says so where each feature lives.
- Requires DiverzitySEO Control 0.7.0.
1.33.0
- New: three plans — Managed, Managed Pro and Lifetime. On Managed, Autopilot, AI answer tracking, the content engine, merge plans and client reports are shown as part of Managed Pro, with the way to upgrade. The control panel refuses those features' AI calls too, so the limit does not depend on this copy of the plugin (requires DiverzitySEO Control 0.6.0).
- New: connecting takes one field. Paste the site key from the welcome e-mail under Settings → Connect; the control panel address defaults to diverzityseo.com, and a key with no API key of its own switches AI to DiverzitySEO credit by itself.
- New: the Billing card shows the current plan. Without a running subscription it offers Managed, Managed Pro and Lifetime; with one, plan changes and cancelling happen in Manage billing, so a second subscription cannot be started by mistake.
- The last plan the control panel confirmed is remembered, so a short outage there never switches a paying site's features off.
- Changed: the Anthropic API key field appears only for a connected Lifetime licence. A site that is not connected sees where to get a site key instead; a site on a monthly plan runs on credit even if a key was saved earlier.
1.32.1
- Changed: the billing wording now describes the lifetime licence correctly — one payment, no monthly fee, and AI runs on your credit or on your own Anthropic key, whichever you choose. It previously read as own-key only.
- Fixed: sites billed by invoice were told to "top up" when their balance went below zero. They now see an account balance billed by invoice, and the top-up form is hidden (requires DiverzitySEO Control 0.5.2).
1.32.0
- New: a Redirects page. Send an old address to a new page permanently (301) or temporarily (302), or mark it gone (410) so search engines stop retrying it.
- A rule only ever applies to an address that no longer exists. A live page cannot be redirected from here at all — the homepage included — so one typo can never send working traffic somewhere else. Retiring a page that still exists stays the job of consolidation, which keeps its content and can be undone.
- Loops are refused, a rule cannot point at an address that is itself redirected, and redirecting an address other rules point at moves those rules along, so a chain is never built from either end. Only http and https targets are accepted; a same-site URL is stored as a path so it survives a domain move.
- New: a log of missing addresses still being requested, with where the broken link was last seen and the page each one most likely meant — an exact slug match for a page that moved under a new parent, or two shared words for a renamed one. One click redirects it there.
- Probes for files like /wp-login.php and missing images are not logged, and an address WordPress already redirects on its own (an old post slug) is not counted as missing.
- A missing address requested five times or more becomes a finding after the next analysis, with the redirect as its one-click fix when there is a likely match. The fix is not part of Autopilot — the match is a guess, so a person confirms each one — and undo removes the rule.
- Settings → "Record missing addresses" turns the log off. Redirects keep working either way.
1.31.0
- New: a DiverzitySEO panel in the block editor's sidebar, so the plugin is there while a post is being written instead of only on its dashboard afterwards.
- Search snippet preview with the SEO title and meta description as they are stored, their length against what results display, and "Write with AI" buttons for both.
- AI-answer readiness: the post's citability score, its three weakest signals in plain words, and one-click buttons to add an answer passage or an FAQ when they are missing.
- The open findings for this post, applied or dismissed in place, and the last few applied fixes with undo.
- Every fix started from the panel is filed and applied like any finding, so it appears in SEO Findings with its undo. Undoing one closes it rather than reopening it as a finding nobody's audit raised.
- Fixes write to the saved post, so the panel refuses them while the editor has unsaved changes and reloads the editor after one is applied. Without that, the next save would overwrite the fix, or the fix would overwrite your edits.
- Shown to administrators only, on the content types the audit covers — the buttons spend the site's API budget.
1.30.0
- New: AI answer tracking. List the questions your customers ask, and DiverzitySEO puts them to Claude with live web search on a schedule — the same search, read, answer, cite loop an answer engine runs — and records whether the answer names your business, cites your site, or sends people elsewhere.
- Measured, not asked: whether you were named, cited, or found by the search but not used is read from the answer and its citations by the plugin. The model is never asked to grade its own answer.
- The GEO / AI Search page shows a visibility score, each question with what changed since the last check, the answer itself, and the sites answers rely on most — usually the directories, reviews and articles a business needs to appear on.
- Every question where you are not named becomes a finding. When one of your pages should be the answer and has no quotable answer passage, the finding carries the one-click fix that writes it. When the page already has one, the finding says so and points at the cited sites instead of offering a fix that would change nothing. A question you become visible for retires its finding.
- "Suggest questions" drafts a starting list from your site focus and Search Console queries, for one Claude call.
- Off by default. Each question is one call with up to three web searches; the page shows what the last check actually cost, and the monthly budget covers it.
- Fixed: web searches are billed per search on top of tokens, and neither the site's usage tracker nor the control panel counted them. Both do now (requires DiverzitySEO Control 0.5.1 for managed sites).
- Labelled as what it is: the answers come from Claude with web search, not from ChatGPT or Perplexity.
- Fixed: deleting the plugin ended in a fatal error, and had since 1.11.0. Uninstall loaded only the main class, whose list of scheduled tasks names the llms.txt rebuild on another class — so tables and options were removed, then the page died before the scheduled tasks were cleared. Uninstall now loads every class those lists refer to, and a test runs it the way WordPress does.
1.29.0
- A generation run now publishes the blog page itself when the site has nowhere to list an article. Until now the page was a checklist item on the dashboard, so a site that skipped it collected posts reachable only by permalink.
- It runs after the articles are written, never before: a run that produced nothing leaves no page behind.
- The same guard rails as the manual button — your homepage is never reassigned, a page with content of its own is never overwritten, and a site that already lists posts through a theme template or a Query Loop block is left alone.
- A failure to insert the page is reported in the run summary, not raised as a failed run. Articles that were written stay written.
- Settings → Content generation has a "Blog page" toggle to turn the automatic deployment off.
- Fixed: every analysis failed outright on Claude Opus 4.8 and Haiku 4.5 — the default model included. The audit's
action_typefield was declared nullable as a union type while also carrying a list of allowed values, and strict structured outputs check each allowed value against the declared type, where no single value can match a union. The API rejected the request before the audit began. The field now usesanyOf, which says the same thing in a shape the validator accepts. Sites pinned to Opus 4.7, Opus 4.6 or Sonnet 4.6 were unaffected, because strict enforcement is only sent to models that support it — which is why this looked like a problem with one site rather than with one setting. - Fixed: an analysis that failed said nothing at all. The run happens in WP-Cron, which has no screen to report to — the reason was written to the database and never read back, while every dashboard query filtered for successful runs only. The progress panel would poll three seconds in, see no run in flight, and quietly reload an idle-looking dashboard. The last run's failure and its reason now appear at the top of the dashboard, and clear themselves when a later run succeeds.
- Fixed: a run killed mid-flight — a PHP fatal, or a host cutting the request short — never reaches the code that records a failure, so it left a row marked "running" forever. The dashboard now names that case separately and points at the PHP error log.
- Fixed: "Save settings" did nothing on any site linked to a control panel. The Billing card's three Stripe forms were rendered inside the settings form, and a browser reads the first nested </form> as the end of the outer one — so every field below the card, the save button included, sat outside the form. The card now renders above the form, where it was always documented to be.
1.28.0
- Managed sites can now pay for themselves: a Billing card in Settings tops up credit, subscribes to the monthly plan or buys a lifetime licence, all on Stripe's hosted checkout. Card details never reach the site.
- "Manage billing" opens Stripe's portal, where a customer changes their card, downloads invoices or cancels.
- Requires DiverzitySEO Control 0.5.0 or later on the control panel, with Stripe enabled there.
1.27.2
- Fixed: the analysis progress panel rendered broken — the bar and the explanatory text fell outside the box and overlapped the card below. Its container class collided with the 8px bar used inside the apply-all modal, which forced the panel to that height.
- Fixed: "Biggest win" reported the largest score rise in the period but captioned it "since the previous audit", so an older jump appeared beside a score card saying no change had happened. It now names the date of the audit that earned it.
1.27.1
- Fixed: after an analysis finished, the dashboard still showed "Analysis started — results will appear here when it finishes", because the reload kept the notice that started the run in the URL.
1.27.0
- The dashboard now shows what an analysis is actually doing — which page is being measured, out of how many — instead of two notices both guessing "up to 10 minutes".
- While Claude is working there is nothing to count, so the bar says it is waiting and shows elapsed time rather than inventing a percentage.
- The page no longer hard-reloads every fifteen seconds while a run is in flight. It polls quietly and reloads once, when the run finishes.
1.26.3
- Fixed: when the same title lives under several meta keys and they disagree — one corrected by an earlier partial fix, the one the site renders still stale — the year refresh was shown the already-correct value and had nothing to repair, so every attempt failed while the warning stood. It now works from the value that is actually wrong, and writing the correction puts every key back in agreement.
1.26.2
- Fixed: refreshing out-of-date years only ever wrote the Yoast title field. On a site not running Yoast the fix reported success while the title in search results kept last year's number. Every SEO title and meta description is now read from, and written to, whichever plugin owns it — including this one.
- Fixed: the merge panel warned about any out-of-date year anywhere in an article, including cited figures such as "the market reached $617bn in 2024". Rewriting those would falsify a statistic, so the fix correctly refused and the warning never cleared. Only titles, SEO titles and meta descriptions — the surfaces that claim a page is current — now raise the warning.
- Undo for a year refresh now restores every title and description field, including ones the fix created.
1.26.1
- Improve: a merge plan now warns when the article it recommends keeping still carries an out-of-date year, and offers to fix it on the spot. Consolidating three articles into a title that reads a year old is a worse outcome than the duplication was, and the warning arrives at the moment the decision is being made.
- Improve: the
refresh_stale_datesfix can be applied to a chosen post instead of only to a post an audit happened to raise a finding about. It is recorded as a finding when applied, so it appears in SEO Findings and undoes there like any other one-click fix.
1.26.0
- Feature: "Compare the writing" on a group of competing pages that search data cannot separate. The plugin reads the articles and says which one should survive, why, and what is worth moving across from the others before consolidating — sections, figures, angles the keeper is missing.
This is offered only where the data has already declined to choose, and is labelled an editorial opinion everywhere it appears. A verdict from search performance says which page engines already prefer and can be acted on; this says which article is better written. The two are deliberately never blended, because a judgement about prose dressed as evidence about traffic is how the wrong page gets redirected.
A recommendation that names an article outside the group, or arrives without a reason, is discarded rather than shown — it unlocks a consolidate button, so it has to point at a real page in that group. Notes about material to rescue are dropped unless they come from a page actually being retired.
The comparison is cached for a week against the pages themselves, so re-opening the findings page does not pay for it again. - Note: this makes the merge feature useful on a site whose content has not earned traffic yet, which was every group on the site it was built against. Before this, the honest answer on a new site was "no recommendation" on every cluster, which is correct and not much help.
1.25.4
- Fix: the site no longer pingbacks itself at all. Clearing the ping flag on the plugin's own writes (1.25.2) was necessary and not sufficient: WordPress sets that flag on any save and sends the pings later on cron, so flags queued before the fix still fired, and a post edited by hand still announced every internal link the plugin had put in it. On the site this was found on that meant 38 pingback comments from the site to itself — 20 of them auto-approved and showing on the posts. Links pointing at the site itself are now removed from the ping list at the moment WordPress is about to send them, whoever saved the post and whenever the flag was set.
Only same-host links are dropped, with www treated as the same site. A pingback to somebody else's site is the feature working and is untouched, and adiverzity_seo_ping_linksfilter is there for a site that genuinely wants to ping itself.
Pingbacks already received are left alone — they are comments on your site. They can be selected and trashed under Comments.
1.25.3
- Fix: an interrupted linking run could not be undone. The record needed to restore the edited posts was only written when a run reached the end, so a run that was interrupted — a killed request, or a closed page on a site with no traffic to drive cron — left its edits in place with nothing to revert. That is precisely the failure batching was introduced to contain. The record is now written after every batch.
- Fix: the "Undo all" button could be unreachable. It only appeared when a finished job record existed, so an interrupted run, or a record left by an earlier version, hid the button while the undo data sat there unused. The offer now follows the record itself, and says how many posts it would restore.
- Fix: a background pass that arrived while another was mid-batch consumed its scheduled slot and stopped, which could strand a job whose page had been closed. It now hands the work back to the scheduler.
- Fix: starting a new run clears the previous run's undo record, so "Undo all" can never restore bodies from two different runs at once.
1.25.2
- Fix: the plugin no longer makes your site send you moderation emails about itself. Saving a published post makes WordPress scan its body for links to ping, so every internal link the plugin inserted came back as a pingback comment awaiting approval — one email per link, and a mailbox full of the site talking to itself after a bulk run. Every post edit the plugin makes now clears that flag before the scan is queued.
Only the plugin's own edits are affected. A link you add by hand still pings exactly as WordPress intends.
Pingbacks already created are not touched — they are comments on your site, so removing them is your call. They sit under Comments → Pending and can be selected and trashed in one go.
1.25.1
- Fix: a queued linking job advanced one batch per visit. WP-Cron only runs when a request reaches the site, so on a quiet install the job crawled — and the progress page was meant to keep it moving by refreshing itself, which browsers throttle to a standstill in a background tab. The open page now drives the job directly, running each batch as soon as the last finishes, while cron continues to carry the work whenever the page is closed. A lock keeps the two from overlapping.
1.25.0
- Fix: bulk internal linking runs in the background. It used to do every post inside the click that started it — forty API calls in one request, about four minutes, with the browser tab blocked throughout. That survived on a permissive host and would be killed part-way through on a normal one, leaving posts half-linked and an undo record covering only what had finished. It now runs four posts per pass on WP-Cron, saving after each, with progress on the page and the same one-click undo at the end.
- Feature: consolidate competing pages, the acting half of the merge plans. Where the plan recommends a canonical page, the others can be consolidated into it: the retired page is redirected (301), marked noindex, and keeps every word of its content. Nothing is deleted, nothing is unpublished, and no article is rewritten — this changes routing only, which is why it undoes in one click.
Refusals do the heavy lifting: a page cannot be consolidated into itself, into a page that is already redirected (a chain loses ranking at every hop), or twice; drafts are refused; and a request naming two pages that are not in the same competing group is rejected, so a stale form cannot redirect an unrelated page.
The button only appears where the plan actually names a canonical page. Where the evidence does not support a choice, there is nothing to click. - Feature: a watch window. Each consolidation records what the two pages earned together beforehand, and for 28 days the surviving page is compared against that — because the promise of consolidating is that one page inherits what two were sharing. A quiet loss is reported as "traffic down" with an undo button, rather than passing as success.
1.24.0
- Change: anchor text is now chosen by the model and verified by the plugin, replacing the mechanical approach 1.23.2 introduced. Run across a real archive, deriving anchors from keywords produced "na Slovensku" linking to three unrelated posts from a single article, and "je IT outsourcing" — fragments that are not noun phrases in any language. Which phrase in a sentence should carry a link is a judgement about language, and word-boundary arithmetic cannot make it.
Every proposal is checked before anything is written: the phrase must appear in the article character for character, it must name a target that exists, one link per target, and the existing rules still apply — nothing is written inside a link, a heading or an attribute.
If the call fails or returns nothing usable, the linker falls back to exact title and keyword matches. Fewer links from real phrases beats many links from invented ones.
Because this makes one call per post, the bulk action now says so before it runs.
1.23.2
- Improve: internal linking also considers sub-phrases of a keyword. A recorded primary keyword is a search query, not prose — "vývoj webovej aplikácie cena Slovensko" is what somebody types into Google, and no article contains that sentence. The phrase inside it, "vývoj webovej aplikácie", is what the text actually says. Running the first version across a real archive linked 6 posts out of 40 for exactly this reason.
A sub-phrase must be at least twelve characters and hold at least one word that is distinctive on this site, so "cena Slovensko" — where both words appear in most of the site's own keywords — is never used as an anchor, and neither is a broken fragment like "čo je IT".
Which words count as generic is measured from the site's own keywords and titles, needing both a share and an absolute count: across a handful of phrases a 25% share is two, which would mark nearly every word generic and leave nothing to link on.
1.23.1
- Feature: "Add internal links" on SEO Findings links every published post in one pass. 1.23.0 fixed the linker for posts written from then on, which leaves an archive written before the fix with no links at all — this repairs it.
The previous body of every post it touches is recorded, and an "Undo all" button beside the result puts the whole run back exactly as it was. WordPress' own revisions are the second net.
A post that gains no links is not edited and not recorded, so the undo only ever restores what actually changed.
1.23.0
- Fix: internal linking never actually linked anything. The only anchor the linker tried was the target post's entire title, so a link was created only if one article happened to quote another's headline word for word — which on a real site never happens. The setting was on, the linker ran on every generated post, and it inserted nothing: forty published posts with no internal links between them.
An anchor is now the target's recorded primary keyword, the part of its title before a separator, or the whole title — tried longest first, so a precise phrase is used before a broad one claims the same sentence.
Linking is HTML-aware. The body is walked tag by tag and only text outside any existing link and outside any heading is eligible, so the linker can no longer nest an anchor inside another, link a headline, or write into an attribute value. Matching is case-insensitive but leaves the author's own casing intact, and it will not split an inflected word. - Note: this only affects posts written from now on. To add links to existing posts, apply the "add internal links" fix from SEO Findings — reversible, as before.
1.22.1
- Fix: a page could appear in two merge plans at once. Overlapping groups were folded into the first group they touched, which leaves two groups connected by a page that joined the second one later — so one post showed up in two plans, inviting you to redirect it in one and keep it in the other. Overlap is now transitive: if two groups share a page, they are one group.
1.22.0
- Fix: merge plans were only looking at a fraction of the site. Competing pages were grouped by the primary keyword the plugin had recorded, so any post without one — anything written by hand, or generated before the plugin stored it — was invisible, and two posts had to have landed on character-identical keywords to be grouped at all. On the site this was built against that meant 12 of 40 published posts were considered.
- Feature: pages are now grouped by three signals, and each group says which ones found it: the recorded keyword, both pages ranking for the same Search Console query (the strongest evidence there is — not "these look similar" but "Google is showing both for one search"), and near-identical titles.
Title comparison weights each word by how distinctive it is across the site's own titles, so a house style like "Koľko stojí … na Slovensku" counts for almost nothing while "outsourcing" counts for a lot. No stopword list is involved, which is what makes it work on a site that is not in English.
Years are excluded from the comparison. A year is the rarest word in a title and would otherwise be treated as the most distinctive one — pushing "…v roku 2025" and "…v roku 2026" apart when they are the same article refreshed, which is the most common duplicate a site has. - Improve: the card reports its own coverage — how many posts were examined, how many have a recorded keyword, how many groups were found — so a short list is legible as a fact about the site rather than as a suspicion about the feature.
1.21.0
- Feature: merge plans for pages that compete with each other — read-only, and read-only by construction: nothing in this feature edits, redirects, unpublishes or deletes anything. Each group of pages aimed at one keyword is shown with its evidence side by side (clicks, impressions, best position, internal links in, length, how long since it was updated) and a recommendation for which page should stay canonical.
The choice is made from measured search performance, because redirecting the page that was quietly winning is the one mistake in this area that costs real traffic. Length and freshness are shown but never decide: a longer page is not a better-performing one.
It refuses to recommend when the evidence does not support one. No Search Console connection, an even split, or too little data, and it says so and leaves the decision to you. A 60% share of five clicks is not a winner, so a decision also needs the leader to be ahead by a real margin, not just a proportional one.
Where it does recommend, the suggested next step is consolidate-and-redirect, never delete — a redirect keeps the authority the old URL earned.
1.20.0
- Feature: the audit now reviews what is already published, not just whether it is optimised. Every audited post is measured for length, how long since it was touched, and year references the calendar has overtaken, and posts aimed at the same keyword are grouped as competing. The measurements go into the audit as facts, so a finding about stale or thin content cites a number instead of a hunch.
- Feature:
refresh_stale_datesone-click fix. A post whose title, SEO title, meta description or body still says "2025" gets those references brought up to date. The model does not rewrite the article: it proposes exact find/replace pairs, and each is verified before anything is written — the text must genuinely exist in the post, the replacement must not reintroduce the old year, and it must stay close to the original length. Anything that fails verification is dropped. Reversible, and deliberately not part of "Apply all safe fixes", since it edits published copy.
A year that refers to a real past event ("founded in 2019", "the 2023 update") is left alone; only years labelling current information are corrected. The slug is never touched, so a date fix cannot move the page. - Feature: cannibalisation is reported. Two posts targeting one keyword split the authority that belongs on one page, so the audit names which should stay canonical and what to do with the other — merge, narrow, or redirect. This finding deliberately carries no one-click action: choosing which of your articles survives is your decision, not an automatic one.
- Note on deletion: nothing in this release deletes or unpublishes a post, and nothing is planned to. See the FAQ.
1.19.0
- Feature: the generator checks whether you already cover a topic before writing about it. Until now the only duplicate guard was a hash of the idea's title against ideas already used — it never once looked at what was published, which is how two posts ended up competing for the same query on a live site. Every proposed topic is now compared against the posts that exist first.
Two stages. A free one folds case, accents, punctuation and word order to catch a literal repeat. Then a single small call for the whole batch — not one per idea — asks which remaining topics would compete with an existing post, because that is a judgement about meaning: "Čo je IT outsourcing? Definícia, výhody, riziká" and "Čo je IT outsourcing? Sprievodca pre firmy" are the same subject and share almost no title text, and no amount of string comparison sees it.
It fails open. If the call errors or returns nothing usable, every idea is kept — writing one post too many costs a draft you can bin, while skipping everything on a bad response costs the whole run.
A topic found to be covered is retired rather than retried, so the same judgement is not paid for on every scheduled run, and the run summary names the overlap: "1 topic skipped — already covered. \"X\" overlaps \"Y\"."
When every proposed topic is already covered, the run says so and asks for a fresh audit instead of reporting a vague failure. - Improve: the audit is now told not to propose blog ideas the site already covers, so fewer duplicates are generated in the first place — the pre-check is the guard, not the only defence.
1.18.1
- Fix: links inside the plugin inherited WordPress' admin blue, which is fine on a white card and measures 3.1:1 on the dark one — under the 4.5:1 minimum, and visually foreign next to coral. They now use a brand link colour that is a token rather than a literal, because no single value clears 4.5:1 on both grounds: a deepened coral at 5.3:1 in light, the existing light coral at 7.7:1 in dark.
1.18.0
- Feature: dark mode, with an Auto / Light / Dark switch in the footer's right corner. Auto follows the operating system. The choice is stored per browser rather than in plugin settings, because it is a personal preference and not site configuration, and it is applied before the panel paints so a dark-theme user never gets a white flash on page load.
Not an inversion: the neutrals are re-picked for a dark ground, every text weight is checked against the dark surface rather than against white, and the semantic green, amber and red are lightened so they stay legible. Coral and charcoal are unchanged in both themes.
The charts rebuild themselves when the theme changes — Chart.js reads its colours once at construction, so without that they would keep painting the previous palette until the next page load. - Improve: "See everything we've done" rolls open instead of snapping.
<details>cannot transition its own height, so the panel animates as a grid row and the closing animation finishes before the panel actually closes. The chevron turns with it, and both respectprefers-reduced-motion.
1.17.0
- Improve: hover states lift toward the accent. Buttons, KPI tiles, tabs and finding rows carry a coral-tinted shadow rather than a plain grey one, so a surface that reacts to the cursor says so. Cards that are not interactive deliberately get nothing — a static card that lifts is claiming to be clickable.
- Improve: severity is a shape, not only a number. Each finding row carries a coloured stripe banded by priority, derived from the same rule as the priority chip so the two can never disagree. A pale "1" and a pale "9" used to look identical, which meant the list was sorted by urgency but could not be read that way.
- Improve: the score is a verdict. Each ring now carries its band in words — Excellent, Needs work, Poor — beside a thicker arc, so the number does not have to be interpreted and the meaning survives for anyone who cannot separate the colours.
- Improve: navigation reads as a segmented control instead of underlined tabs. WordPress' own admin is underline-heavy, so an underlined strip inside it reads as chrome rather than as this plugin.
- Improve: the neutral greys are warmed a few degrees toward the accent, so surfaces beside coral look chosen rather than inherited. Coral and charcoal themselves are unchanged.
- Improve: keyboard focus is visible everywhere — a coral ring on every link, button and field — and all of the above respects
prefers-reduced-motion.
1.16.0
- Improve: findings are readable at a glance. Every row rendered its full description *and* its full recommendation, so one finding filled the screen and a list of sixty could not be scanned at all. The recommendation now sits inside the finding, labelled, and both are clamped to two lines with a "Show full text" toggle per row. Long URLs no longer stretch a column into a ribbon.
- Improve: one primary action per screen. "Apply safe fixes" and "Run analysis" were both coral, so nothing stood out. Only the higher-value action is coral now; the other steps back.
- Improve: the score rings say what they mean. A middling score rendered in brand coral and a failing score rendered amber — so a bad score looked like a warning and a mediocre one looked like decoration. The bands are now green, amber and red, and coral is reserved for things you can act on.
- Fix: text contrast. Several labels used a grey that measures 2.6:1 on white, below the 4.5:1 minimum — the age of a finding, "Site-wide", completed setup steps, and the fix-progress state. All moved to a grey that passes; the failing token is now documented as borders-and-ticks only.
- Improve: numbers that are read as data (scores, priorities, counters) use tabular figures, so a ring's value no longer shifts as the score changes, and the recap paragraph is capped at a readable measure instead of running the full width of the card.
1.15.0
- Feature: sort findings by newest, and a "new" badge on everything the most recent audit raised. The list has always sorted by priority alone, which makes the top row look like the latest finding when it is usually not — a genuinely easy way to misread the table when you are scanning for what just changed.
- Improve: the audit summary now reports its two dedupe mechanisms separately — "3 already on the list. 6 restatements dropped." — instead of merging them into one figure. They are different checks (an exact database match versus the model recognising the same issue reworded), and one number made each of them impossible to judge.
1.14.2
- Harden: rows are timestamped by WordPress rather than by the database server.
created_atwas left to the column'sDEFAULT CURRENT_TIMESTAMPon the runs, findings and API-usage tables, so it came from the database's clock, whilestarted_at,finished_atandapplied_atare written by PHP in site-local time and every window the plugin queries is site-local. Where a host runs MySQL in a different timezone from WordPress — common on shared hosting with MySQL on UTC — that difference would shift displayed ages, both 90-day windows, the order of the work log, and which month API spend is billed to. Every insert now writes the site-local time explicitly.
To be clear about what prompted this: it was not an observed failure. It was written up as one after a misreading of the live findings table, which sorts by priority rather than recency — the row that looked wrong was simply an older finding. On that host the two clocks agree and nothing was ever displayed incorrectly. The change stands on its own as removing a latent portability hazard, not as a fix for a bug anyone saw.
1.14.1
- Fix: relative times are written in the plugin's own language. WordPress'
human_time_diff()answers in the *site* locale, so a Slovak site running the English admin read "raised 19 hodín ago" on every finding, and "2 dni ago" on the GEO page. All five places that show an age now use one helper whose strings carry the plugin's text domain, so the phrase is whole in whichever language the interface is in.
1.14.0
- Feature: custom post types are audited and marked up. Service, project, portfolio and product pages were skipped by both the audit and the schema output, while the prompt was still told those types existed — so the model reasoned about pages it had never been shown. They are now crawled like any other content, and a new Settings option chooses which types the audit covers (all public types by default; useful when a very large type would crowd out the rest).
Structured data follows: a custom type gets the WebPage and BreadcrumbList nodes, its FAQ markup, and whatever specific typegenerate_schemaattaches — but deliberately no Article node, because calling a service page an Article is a claim about it that is not true. Article stays with posts and pages.
Breadcrumbs understand custom types: hierarchical ones follow their parents, the rest follow their own taxonomy rather than looking for post categories that do not exist.
The list of types a page emits now comes from the same code that emits them, so the audit snapshot cannot describe markup the front end never renders. - Feature: bulk dismiss. Findings carry checkboxes and a "Dismiss selected" action, with select-all. Clearing an accumulated backlog no longer means one click per row.
- Feature: restatement pass. After each audit, one small extra call compares the new findings against the ones already open and drops the ones that restate an issue in different words — the case exact-title matching and prompt instructions both miss, and the case token heuristics cannot solve in an inflected language. If the call fails or returns nothing usable, every finding is kept: a duplicate costs one dismissal, a dropped finding costs the finding.
- Fix: dismissing a finding no longer silences it forever. Dedupe matched rows in any state with no time limit, so an issue that had once been dismissed — or fixed and later undone by an edit — could never be raised again. Resolved findings now suppress their own recurrence for 90 days; open and queued ones still suppress unconditionally, since they are on screen.
- Fix: a stale backlog no longer silences new findings. Open findings are passed to the audit so it does not restate them, which meant a year-old unresolved finding kept suppressing fresh ones. Anything open longer than 90 days is now excluded from that list and flagged "stale" in the findings table, with the age of every finding shown.
1.13.1
- Improve: the blog-page step recognises the listings a site may already have. Besides the native "Posts page" setting it now detects a theme page template (page-blog.php and similar) and a Query Loop block on an ordinary page, and it reads the theme: a site whose Reading setting says "latest posts" but whose theme paints its own front-page.php does *not* have a post listing, and is no longer told it does.
- Improve: on such a site the plugin builds a blog page that lists posts through a core Query Loop block, because the "Posts page" setting is ignored unless a static homepage is set. The homepage is never reassigned either way.
- Fix: the dashboard could not see a single audit. Every audit count asked the database for runs with status
completed, but a finished run has always been stored assuccess, so the query matched nothing — no matter how many audits had run. "Run your first SEO audit" stayed unticked forever, the recap sentence never mentioned audits, and the work log listed applied fixes only, never an audit or a generated article. All five queries now ask for the status the plugin actually writes. - Fix: the work log also excludes the per-fix
actionruns it would otherwise list a second time as "Maintenance", next to the fixes it already shows. - Fix: the dashboard cache is stamped with the plugin version, so an upgrade that adds a checklist step or a counter takes effect immediately instead of serving the pre-upgrade data for up to six hours.
1.13.0
- Feature: one-click blog page. Generated articles need somewhere to be listed. The plugin now detects whether your site has a page wired to WordPress' "Posts page" setting and, if not, publishes one, sets it, and adds it to your theme menu — the first step in Getting started. It never reassigns your homepage: on a site whose front page already lists posts the step is simply reported as done. An existing empty page at /blog is adopted rather than duplicated, and a page that has content of its own is left untouched.
- Improve: Getting started moved to the top of the dashboard, where a new site can act on it, and every open step now carries the button that completes it — create the blog page, connect Search Console, run the audit, review findings, write the first article. Each step explains why it matters.
- Improve: once all steps are done the card can be dismissed and stays hidden.
1.12.0
- Feature: citability scoring. Every post is now measured, not estimated, against the rubric the audit has always described in prose — whether it opens with a self-contained 40–70 word answer passage, how many headings are phrased as questions, whether the heading outline skips levels, how many paragraphs are too long to quote, whether it opens with a definition, freshness, lists and FAQ. The result is a 0–100 score with a per-signal breakdown, computed from the post itself with no API call and no added cost.
The measurements go into the audit snapshot, so findings can cite a number instead of inferring citability from a 600-character excerpt — the same class of fix as the schema field in 1.11.1.
Paragraph length is scored as the share of paragraphs at or under 80 words rather than an average, because an average lets one unquotable 200-word block hide behind a few short ones. - Feature:
add_answer_passageone-click fix. Claude writes the self-contained 40–70 word passage an AI engine can lift and cite, and it is inserted after the opening paragraph — placed there rather than above it so the article still reads as an article. The length is verified before saving, so the fix cannot report success while leaving the score unchanged. Reversible, and deliberately not part of "Apply all safe fixes" since it edits the post body, matching the existing rule for internal links and category changes. - Feature: AI crawler visibility. Visits from GPTBot, ChatGPT, ClaudeBot, PerplexityBot, Common Crawl and others are recorded and shown on the GEO / AI Search page, with a purpose label separating the crawlers that fetch pages in order to cite them from those that only collect training text. Ordinary visitors cost nothing — a request is only written to the database when it comes from a known AI agent.
- Feature: AI crawler policy in robots.txt, off by default. Choose to allow everything (best for AI visibility), allow answer engines while blocking training crawlers, or block everything. Google-Extended and Applebot-Extended are handled correctly as robots.txt opt-out tokens rather than crawlers, since they never appear as a user agent.
- Improve: the analyzer is told to treat the citability measurements as authoritative and to quote them in findings, so a recommendation names the observable condition behind it.
1.11.1
- Fix: the audit reported "no Schema.org markup on any blog post" on sites that emit Article and FAQPage on every post. The on-page snapshot sent to the analyzer never included the page's structured data, so the model was asked to judge markup it could not see and guessed. Each post now reports a
schema_typeslist of exactly what it emits, and the prompt treats that list as authoritative — it can only judge whether the type is specific enough, never whether markup exists. As of 1.11.0 every post carries an Article node, so this finding would otherwise have been wrong every single time. - Fix: the same issue could be reported many times over in different words — one site accumulated six separate findings for a single missing-author-byline problem. Findings that are still open are now shown to the analyzer, which is asked not to restate them in any wording or language, and the prompt requires one finding per underlying issue. Exact-title deduplication remains as a backstop; it could not catch a rewording on its own.
- Fix: the analyzer is now told never to assert something is missing unless a field in the supplied data shows it is missing.
- Fix: the GEO readiness checklist showed a green tick for llms.txt whenever the URL returned 200 — including when a static llms.txt in the web root was being served instead. A file on disk is served by the web server before WordPress sees the request, so the generated document was ignored while the checklist reported success. Responses now carry an
X-DiverzitySEO-LLMSheader, the check verifies the response actually came from this plugin, and when something else is answering it says so and names the file on disk to remove. - Fix: a front page with no static page and an empty site tagline produced no meta description at all — on the most important page of the site, and one that
write_meta_descriptioncannot target because it has no post ID. The publisher description from the AI search settings is now used there before falling back to the tagline.
1.11.0
- Feature: llms.txt. The plugin now generates and serves
/llms.txt— a markdown map of your site written for language models, so an AI answering a question about your subject can find the right page instead of guessing from whatever it happened to scrape. An optional/llms-full.txtcarries the complete text of those pages. The GEO page has always checked for this file; nothing produced one until now.
Built from the meta descriptions your one-click fixes already wrote, so it works with no API key and costs nothing to rebuild. Claude is used for one thing only — the opening site summary — and that is an explicit button, never the automatic rebuild.
Served virtually rather than written to disk, so it works on read-only and containerised hosts and can never go stale on disk. Requests are intercepted directly, so it resolves even without pretty permalinks and no rewrite flush is needed.
Rebuilt automatically when you publish or unpublish, and on demand from the GEO / AI Search page. - Feature: entity graph. Structured data is now emitted as one linked JSON-LD graph instead of two flat blocks.
Organization(orPerson, orLocalBusiness),WebSite,WebPageandBreadcrumbListnodes are connected by@id, the Article's publisher points at the single Organization node rather than repeating an inline copy, and the author is a realPersonnode — a direct E-E-A-T signal. This is how an AI engine decides that two mentions of your brand refer to the same entity.
New settings for publisher type, name, description, logo (falls back to your Site Icon) andsameAsprofile URLs. The profile URLs matter most: they are the links an engine follows to confirm identity.
Breadcrumbs are derived from the page's category or parent hierarchy, and the trail is omitted when there is nothing but Home to show. - Compatibility: when Yoast, All in One SEO, Rank Math, SEOPress, The SEO Framework or Slim SEO is active, the entity graph stays off — it would compete with the Organization node that plugin already publishes, and two conflicting ones are worse than one. The GEO and Settings pages say so explicitly and offer an override. Per-page Article and FAQ markup is unaffected and keeps working alongside any of them.
1.10.2
- Fix: on a site with no other SEO plugin installed, the
write_meta_descriptionandwrite_seo_titlefixes reported success but changed nothing a search engine could see. Their result was stored in Yoast's and All in One SEO's fields plus the plugin's own, but nothing rendered the plugin's own — so with neither of those plugins present, the tags never reached the page. DiverzitySEO now renders the title, meta description and matching Open Graph / Twitter tags itself in exactly that case, and stays silent whenever Yoast, All in One SEO, Rank Math, SEOPress, The SEO Framework or Slim SEO is active. - New setting: "Title & meta description output" (Settings → on by default), which reports which SEO plugin was detected and lets you switch the output off.
- Fix: deactivating the plugin left scheduled events behind. It used
wp_clear_scheduled_hook(), which only matches events registered with no arguments, so a duplicate or orphaned event survived and resumed on its old cadence when the plugin was re-enabled — the same defect fixed in the scheduler in 1.10.1. - Fix: uninstall left data behind. The
diverzity_seo_gsc_dailytable was never dropped, and the Search Console snapshot, dashboard cache and GEO result options were never deleted. Uninstall now removes every table, option, transient, post meta row and scheduled event by namespace, so nothing can be missed, and it cleans up correctly across a multisite network. - Fix:
readme.txthad been left atStable tag: 1.0.9for nine releases. Publishing it in that state would have served version 1.0.9 to every user. The changelog below is backfilled and continuous integration now fails when the plugin version and the stable tag disagree.
1.10.1
- Fix: switching post frequency to weekly could keep publishing daily.
wp_clear_scheduled_hook()left an orphaned or duplicate recurring event firing on its old cadence, so rescheduling was replaced withwp_unschedule_hook(). - Fix: nothing enforced the interval at run time. Scheduled post generation now skips a run until roughly 90% of the configured interval has elapsed. The manual "Generate now" button is deliberately exempt.
- Existing installs self-heal once per version: stray events are wiped and a single correct event is rebuilt from your settings. The first run is scheduled a full interval out rather than five minutes.
1.10.0
- Feature: exportable client report with the site's score, findings and search performance.
- Improve: dashboard charts redrawn at a 4:3 ratio with richer series; the cumulative chart spans the full card width and the search multiples carry a shared legend explaining the line types.
- Fix: the "add FAQ" fix failed forever on posts that already had one. It now resolves the finding instead of erroring, so it no longer resurfaces and re-fails in every "Apply all safe fixes" run.
1.9.0
- Feature: dashboard charts rebuilt on Chart.js (bundled, no external requests).
- Change: the admin interface is now in English throughout.
- Fix: content width capped on wide monitors, charts given real height, stray captions removed and the search multiples forced to a 2×2 grid.
1.8.0
- Feature: dashboard redesigned around visible progress and results.
1.7.3
- Fix:
generate_schemafailed under strict schema mode. The generated JSON-LD is now returned as a decoded JSON string, which strict mode accepts.
1.7.2
- Improve: raised the output token cap for
generate_schema(1500 → 4000) andadd_faq_block(2048 → 3000) so larger results are no longer truncated.
1.7.1
- Feature:
set_featured_imageone-click action fetches a fitting Unsplash photo for posts that have none.
1.7.0
- Feature: GEO / AI Search page — a separate AI-search readiness score, summary and checklist covering llms.txt, FAQ blocks and tailored structured data.
- Feature: one-click post categorizer.
1.6.8
- Fix: findings are now deduplicated against suggestions of any status, with case-insensitive title matching, so resolved items stop reappearing.
1.6.7
- Fix: Search Console requests used the wrong API base path (
/v1/instead of/webmasters/v3/). - Fix: property-wide totals are shown when the query breakdown comes back empty.
1.6.6
- Improve: a 404 from Search Console now reports the configured property URL alongside the properties the connected account can actually see.
1.6.5
- Improve: the settings screen lists the account's real Search Console properties to pick from, instead of requiring the exact string to be typed.
1.6.4
- Fix: the settings sanitizer stripped the Search Console OAuth tokens on every save, so the connection could never persist. It runs on every
update_option()for the settings, including programmatic writes, and now carries the token fields through.
1.6.3
- Fix: dropped
include_granted_scopesfrom the OAuth request and surfaced Google's actual token-response fields on failure.
1.6.2
- Fix: connecting now requires a refresh token, with a connection diagnostic explaining what Google returned.
1.6.1
- Fix: the dashboard was empty after a successful Search Console connect.
1.6.0
- Feature: search-performance dashboard, SEO score trend and apply-fixes progress.
- Improve: expired Search Console tokens are handled gracefully, including the seven-day expiry that applies to apps in Google's Testing mode.
1.5.2
- Improve: strict schema enforced on analysis output; default model is now Claude Opus 4.8.
1.5.1
- Brand: added the logo and "Powered by" assets; managed credit is shown inside the API Spend card rather than a separate banner.
1.5.0
- Feature: E-E-A-T, GEO and structured-data rubrics added to the audit prompt, plus a
generate_schemaone-click action that picks the correct Schema.org type for a page and builds valid JSON-LD.
1.4.0
- Feature: managed and lifetime (bring-your-own-key) plans with phone-home reporting.
1.3.0
- Feature: managed mode — API calls can be proxied through a central key instead of your own.
1.2.0
- Improve: SEO analysis runs in the background with a progress UI, so the admin request never blocks or times out on a long audit.
1.1.0
- Feature: Search Console queries in striking distance (positions ~4–15) and with low click-through are turned into targeted title and meta description rewrites aimed at that exact query.
- Improve: hardened parsing of the analysis response.
1.0.9
- Feature: three more one-click actions, widening what "Apply all safe fixes" and Autopilot can clear automatically:
write_seo_title— Claude writes an optimized 50–60 character SEO title tag (the <title> shown in search results; the post's H1 is left untouched).generate_excerpt— Claude writes a 1–2 sentence excerpt for posts that have none.add_internal_links— inserts internal links into an existing post by matching other published post titles (manual one-click only, like category re-assignment, since it edits the post body). - Every new action is reversible from the SEO Findings page.
- On-page snapshot now reports each post's existing SEO title and whether it has a manual excerpt, so the analyzer targets these accurately.
1.0.8
- Feature: "Apply all safe fixes" button on the Dashboard and SEO Findings pages applies every open one-click fix in one click. Fixes are applied in the background so the page never times out.
- Feature: Autopilot. When enabled, safe one-click fixes are applied automatically after each scheduled analysis — meta descriptions, image alt text, FAQ sections and missing categories (category re-assignment stays manual).
- Feature: Undo. Every applied one-click action now saves its previous state and can be reverted from the SEO Findings page, which returns the finding to "open".
- Schema: added a
previous_statecolumn to the suggestions table (upgrades automatically viamaybe_upgrade()on version change).
1.0.7
- Fix: the analysis findings array sometimes came back empty (stop_reason: tool_use) because the optional action fields used nullable-union types in the output schema. Those are now plain optional fields the model omits when unused, which restores reliable findings generation.
- Improve: the missing-findings error now lists the actual top-level keys the model returned, for faster diagnosis.
1.0.6
- Fix: raised the SEO analysis output token limit (8192 to 16000) so larger audits are no longer truncated mid-response, which previously surfaced as "Analysis response is missing the findings array".
- Improve: that error now reports the API stop_reason and explains whether the response was cut off by the token limit.
1.0.5
- Fix: the analyzer now measures the rendered front-end content of each page (via a loopback request) instead of only the raw post_content. Pages whose content is output by the theme template or a page builder are no longer wrongly reported as empty / 0 words.
- Improve: multibyte-safe word counting so non-English content (e.g. Slovak diacritics) is counted correctly.
1.0.4
- Feature: four more one-click actions on SEO findings — create_category (adds a content category with description), reassign_post_categories (moves a post out of Uncategorized into the right categories, creating them if needed), set_image_alt (writes alt text to a post's featured image), and add_faq_block (has Claude generate a 4–6 item FAQ, appends it to the post, and registers FAQPage schema).
- Improve: on-page snapshot now includes each post's featured image id and current alt text so the analyzer can target images.
1.0.3
- Feature: one-click "Apply" action on SEO findings. The analyzer now emits a machine-actionable action_type per finding where applicable; the first supported action is
write_meta_description, which has Claude generate a SERP-ready 120–158-character meta description for the affected page and writes it to Yoast, AIOSEO, and the plugin's own post meta keys. - New: "Applied" filter tab on the SEO Findings page and a green "applied" status pill on resolved suggestions.
- Schema: added
action_type,action_payload, andapplied_atcolumns to the suggestions table. Schema upgrade runs automatically on plugin load viamaybe_upgrade()when DIVERZITY_SEO_VERSION changes.
1.0.2
- Brand: added "Powered by DiverzityStudios.sk" footer label to all admin pages.
- Fix: WordPress admin sidebar icon now uses a 20×20 PNG, eliminating the oversized image overflow in the admin content area.
1.0.1
- Fix: SEO analysis runs no longer report a false "success, 0 findings" — Claude API structured output now uses the documented tool-use pattern with forced tool_choice.
- Fix: Analysis runs that return an empty/unparseable payload now record as errors with the API stop_reason, instead of silently logging success.
- Improve:
max_tokensfor SEO analysis raised from 4096 to 8192 to fit the full findings + blog ideas payload. - Brand: replaced the placeholder header icon with the DiverzitySEO wordmark and used the brand mark for the WordPress sidebar menu icon.
1.0.0
- Initial release.