SEOWing
  • Features
  • Pricing
  • FAQ
  • Docs
EN/DELoginStart for free

Changelog

Plugin release history. Updates install automatically inside WordPress.

[3.10.0] - 2026-06-03

Self-hosted image optimization. SEOWing no longer depends on the Imagify cloud: it compresses and serves next-gen images on your own server.

Added

- Local compression engine (new Local_Engine): JPEG/PNG re-encode, downscale to max dimensions and metadata strip, using Imagick (preferred) or GD. No API key, no upload to any third party. Verified ~60% reduction on a test image. - Next-gen serving (new Image_Serving): rewrites <img> to <picture> with AVIF and WebP <source> elements when the converted files exist, so supporting browsers download the smaller format and everyone else gets the original. Works via an output buffer, so it also covers theme and Elementor markup, not just the_content. Responsive srcset is preserved; opt out per image with a "no-picture" class, or globally via the seowing/imagify/serve_nextgen filter.

Changed

- The optimizer now defaults to the local backend. The Imagify cloud is optional: set the backend to "cloud" with a key to use it. Image optimization therefore works out of the box with no external account. - WebP generation stays on by default; AVIF is opt-in (it is CPU-heavier and depends on the host). Existing bulk, auto-on-upload and restore-from-backup all use the local backend now.

Notes

- Quality and best-in-class compression depend on the host's image libraries; for the last few percent you can still plug in an Imagify key. The big win (next-gen images are now actually delivered) needs no configuration.

[3.9.0] - 2026-06-03

Plugin side of the industry policy, plus the licensing gate it shares.

Added

- Prohibited-industry handling. When the license server marks a site as industry-blocked (gambling, adult, weapons, tobacco, alcohol, drugs), the plugin disables its active features (audit, AI assistant, MCP, automated changes, updates) and shows a clear admin notice. This applies regardless of the license-enforcement flag, because it is a policy block, not a licensing toggle. Existing SEO output (meta, schema, sitemaps) is left in place. - Advisory industry scanner: a weekly, throttled heuristic scans the site name, tagline and a few pages (Elementor-aware) against the server's keyword lists and reports a SUSPECTED category to the license server for admin review. It never blocks the site itself (word-boundary matching avoids false positives like "rum" inside "forum"); the authoritative block stays admin-controlled and server-side.

Notes

- License enforcement remains OFF by default, so updating changes nothing for existing installs until an operator turns it on per site.

[3.8.4] - 2026-06-02

Changed

- Removed the card lift-on-hover from the audit summary panel (score + Critical / Warnings / Passed tiles). It is a static panel, so the hover effect wrongly implied it was clickable. Interactive cards keep their hover. Done with a scoped .sw-no-lift opt-out, so no other admin cards are affected.

[3.8.3] - 2026-06-02

Fixed

- Setup wizard: the "Legal company name" field was marked required, which blocked finishing or leaving the wizard until something was typed, even though the wizard is meant as a guard rail (the submit handler already accepts empty fields). The name is now optional-but-recommended, so Finish and Skip both work without it.

[3.8.2] - 2026-06-02

Fixed

- Critical: the setup screen (and potentially the whole wp-admin) could enter a redirect loop (ERR_TOO_MANY_REDIRECTS) on hosts with a persistent object cache (for example LiteSpeed). The one-shot activation redirect could read a stale "redirect pending" option after deleting it, so every admin pageload bounced to the welcome dashboard, which the setup wizard then bounced to the setup page, with no exit. The activation redirect is now loop-proof: it never fires when you are already on a SEOWing screen or when the target is the page you are already viewing, so it cannot cycle even if the one-shot flag fails to clear.

[3.8.1] - 2026-06-02

Content analysis now works in the languages the customer base actually writes in, and the image audit sees Elementor pages.

Fixed

- Readability analysis (transition words, passive voice) was English-only, so on German and Italian sites it reported zero transitions and zero passive voice and its guidance never applied. It is now locale-aware: German and Italian word lists and passive-voice patterns, with English as the fallback. The German passive pattern correctly handles participles without a ge- prefix (analysiert, bezahlt, entwickelt). - E-E-A-T detection (personal experience, real examples, author credentials, original research, review/fact-check signals) was English-only. German and Italian phrases are now matched too, merged with English so multilingual (WPML) sites are covered in every language.

Added

- seo_image_audit now also reports Elementor on-page widget images (count and missing alt text), reusing the Elementor analyzer, and points to seo_elementor_audit / seo_elementor_fix_alt. The media-library scan alone could not see images placed through Elementor widgets.

[3.8.0] - 2026-06-02

Two SEO capabilities that were advertised but did nothing are now real, both Elementor-aware.

Added

- seo_suggest_internal_links now works (it was a stub returning an empty list). It reads the real page text (Elementor-aware), finds published pages whose topic (focus keyword, else title) is already mentioned on the page but not yet linked, and proposes contextual internal links with a suggested anchor and target URL. It skips targets the page already links to (Elementor button/link widget URLs included) so it never suggests a duplicate link. - seo_elementor_audit: a deep Elementor-specific audit exposed over MCP for the first time (the analyzer existed but was reachable only from an admin screen). Pass a post_id for one page or omit it for a site-wide summary. Reports heading hierarchy problems, multiple/missing H1, empty headings, images without alt text and thin text blocks, read from the actual Elementor widget tree. - seo_elementor_fix_alt: bulk auto-fills missing alt text on Elementor widget images, deriving readable alt text from the file name. Runs as a dry-run preview by default and creates a restorable backup before writing.

[3.7.0] - 2026-06-02

Elementor-aware content analysis. SEOWing's customer base is mostly Elementor sites, where the visible text lives in Elementor's own data, not in the WordPress post content. Every analysis that read only the post content therefore saw almost no text on Elementor pages: it counted ~0 words, flagged every page as "thin content", and could not see the real heading structure.

Added

- New Content_Extractor: one Elementor-aware source for "the real text of a page". It harvests visible text from all common Elementor widgets, including repeaters (tabs, accordions, icon lists, price lists, testimonials, CTAs), and falls back to the post content on non-Elementor pages. Word counting is now Unicode-correct, so German and Italian content (umlauts, accents) is counted properly. - Heading-structure check in the per-page audit (deep mode): flags pages with no H1, more than one H1, or skipped heading levels (for example an H4 directly under an H2). These are rampant on Elementor sites because the heading widget lets editors pick any tag per element. Reported as an issue, not scored, so it surfaces the problem without a sudden site-wide score change.

Fixed

- Thin-content detection is now Elementor-aware everywhere it matters: it flows through Page_Evaluator, which is the single source used by the admin audit, the AI audit and the Claude connector. Elementor pages are no longer falsely flagged as thin. - The in-editor readability analysis (Flesch, Gunning Fog, word count shown in the post sidebar) now reads the real Elementor text instead of the near-empty post content.

[3.6.4] - 2026-06-02

Fixed

- The Claude connector now follows the same writing house style the in-admin AI Assistant already used: write in the page's natural language with correct characters (German umlauts and eszett ä ö ü Ä Ö Ü ß, never transliterated to ae/oe/ue/ss), and never use em or en dashes. Previously content written through the connector could come back transliterated. The MCP server instructions also no longer contained a transliterated "Datenschutzerklaerung" themselves.

[3.6.3] - 2026-06-02

Finishes the "one score everywhere" work from 3.6.2. In 3.6.2 the admin audit and the AI audit shared the same formula but still ran over different category sets, so they could still disagree (e.g. 55 vs 99). Now they report the exact same number.

Fixed

- The admin "Run Full Audit" headline score now comes from the one canonical scorer, the same Site_Auditor the AI Assistant and the Claude connector use. Verified on a 939-page site: admin page and connector both report 99 where the admin page previously showed ~55. The detailed per-category checks stay as the actionable fix-it list; only the headline number is single-sourced. - SSL check no longer reports a false "not using HTTPS" critical on the weekly cron audit and via WP-CLI. is_ssl() only inspects the current request, so it is false in cron/CLI even on HTTPS sites; the audit now also accepts an https site URL, matching how the AI auditor already checked it.

[3.6.2] - 2026-06-02

One SEO score everywhere. Previously the same site could show three different numbers: the chat Site-Health card said "no issues", the admin "Run Full Audit" page showed ~50/100, and the AI/connector audit showed ~96/100. They each used their own math.

Fixed

- Single canonical scoring formula (new Audit_Score class) now drives both the admin audit and the AI/MCP site audit. Each category scores (pass + 0.5*warning) / checks; the overall score is the mean of the category scores. The admin audit no longer uses the old passed/total formula that collapsed to ~50 whenever a single page-level check failed, so the admin page and the connector audit now report the same number. - The chat Site-Health card now reflects the real last full audit (meta descriptions, internal links, schema coverage, low-scoring pages, ...) instead of only a handful of settings checks plus two narrow SQL counts. It reads the stored audit data, so opening the card stays fast (no live site scan).

[3.6.1] - 2026-06-01

Fixes from real connector usage (a full 939-page audit + auto-setup run through the Claude connector).

Fixed

- Audit recommendations now point at the tool that actually performs the fix. The "modern image formats (WebP/AVIF)" warning recommended seo_auto_setup, which only writes alt text and never converts images; it now points to seo_optimize_image. llms.txt and sitemap recommendations are routed correctly too. - Glossary / term custom post types now get DefinedTerm schema (and norm / standard CPTs get TechArticle) instead of falling through to generic WebPage. - Audit pagination returns next_offset = null on the last page instead of an offset past the total.

[3.6.0] - 2026-06-01

Start unifying the two audits so they stop reporting different numbers.

Changed

- Added a single Page_Evaluator as the source of truth for per-page SEO judgment (meta title/description, focus keyword, schema, featured image, thin content). The AI/MCP full-site audit now uses it. This removes the main cause of the admin audit and the AI audit disagreeing on counts for the same site. - Corrected an over-report: a page with no SEO meta-title override but a real post title is no longer counted as "missing title" (a title still exists).

Note

- The admin "Run Full Audit" engine keeps its detailed per-check affected-item output for now; migrating it onto Page_Evaluator is a follow-up so its UI contract is preserved. The shared evaluator is in place for that step.

[3.5.7] - 2026-06-01

Fix the Claude connector rejecting the whole tool list.

Fixed

- Tools with no parameters declared properties as an empty PHP array, which serializes to []; JSON Schema requires an object {}, so Claude rejected the connector with "input_schema.properties: Input should be a valid dictionary" and loaded no tools. The MCP tools/list now normalizes every schema (root is an object, empty properties becomes {}), and the two offending tool definitions were fixed at source.

Changed (cleanup)

- API key generation now goes through a single canonical CSPRNG generator (two ad-hoc paths removed). The agent's blocked-tools list is a single constant instead of being duplicated at each use site.

[3.5.6] - 2026-06-01

Audit-driven fixes, batch 2: security hardening (mostly the new connector) and assistant capability + cleanup.

Security

- The OAuth connector no longer auto-provisions a plaintext, full-privilege shared MCP key on fresh installs; per-site hashed tokens are the only issuance path. Existing legacy keys keep working. - Connector access tokens now get a narrowed scope (read + content + settings write, never self_update) instead of full wildcard; filterable. - OAuth token lookup is now an O(1) hash->user index instead of scanning every user's meta (fixes a scale/lockout risk on sites with many users). - The MCP rate limiter only trusts the CF-Connecting-IP header when the request actually originates from a Cloudflare IP range, so the per-IP limit cannot be bypassed by spoofing the header. - Dynamic client registration is rate-limited and only accepts https (or loopback) redirect URIs, closing a consent-phishing / option-bloat surface.

Changed

- The in-admin assistant gains seo_create_post, seo_suggest_internal_links and seo_fix_audit_issues in its toolset. - save_meta_box nonce is now unslashed + sanitized before verification. - Removed two dead methods from the audit engine (count_links_in_html, an unused calculate_seo_score) that still shipped in the build.

[3.5.5] - 2026-06-01

Audit-driven fixes, batch 1 of 2: a critical guardrail regression, plus correctness and large-site performance.

Fixed

- CRITICAL: under the default (OpenAI) provider the AI assistant ran with NO system prompt, so every guardrail was silently disabled (do-not-invent business/legal data, preview-vs-execute discipline, correct umlauts, no false success). OpenAI now receives the system prompt like Anthropic and Gemini do. - Autoloader could not resolve acronym class names (it splits before every capital, e.g. MCP_OAuth -> class-mcp-o-auth.php). Added an explicit map for acronym classes (MCP_Oauth, IndexNow, WebP_Converter, SEMrush, WooCommerce). - The weekly audit cron used a 'weekly' interval that WordPress does not ship, so it never ran; the interval is now registered. - create_tables() now verifies each table exists after dbDelta instead of always reporting success, so a failed activation is visible. - MCP token revoke no longer reports a false failure when the token was already revoked. Dead always-'warning' branch in the SEO-scores audit fixed.

Changed (performance on large multilingual sites)

- The AI full-site audit no longer repeats the expensive site-wide scans on every paginated page; collect_missing_info and the PDF scan run once (offset 0) and are cached. collect_missing_info no longer pulls every post into one string (a 504/OOM risk); it scans a bounded set of key + recent pages. - The admin audit no longer computes and writes an SEO score for every post during a read-only audit (it now reads stored scores only), and the image audit uses aggregate SQL plus a bounded file-stat sample instead of loading every attachment and stat-ing every file.

[3.5.4] - 2026-06-01

Fix the Claude connector login loop.

Fixed

- After logging in with the WordPress admin account during the connector OAuth flow, authorization failed and bounced back to login. The authorize endpoint is a REST route, and WordPress only honours cookie auth on REST when an X-WP-Nonce is present; a plain browser redirect from wp-login has the login cookie but no nonce, so the user looked "logged out" and the flow looped. The endpoint now validates the WordPress auth cookie directly, so a normal admin login completes the connection.

[3.5.3] - 2026-06-01

Changed

- Removed the "lift" (upward jump) on card and module hover. Cards still get a soft shadow on hover for feedback, but no longer move, which felt jumpy on the module and settings grids.

[3.5.2] - 2026-06-01

Fix saving the MCP settings tab (the Claude-connector toggle would not stick, and a no-op save reported a false error).

Fixed

- The MCP settings tab dropped the "Enable MCP" and "Connect to Claude" (OAuth) checkboxes on save. The save whitelist only keeps keys present in the group defaults, and enabled / oauth_enabled were missing from those defaults, so the values were discarded and the checkbox reverted. Added both to the defaults. (A latent bug that could affect any tab whose field names were not in the defaults.) - Saving a settings tab without changing anything reported "Failed to save settings." update_option returns false for an unchanged value, which is not an error; the save now treats "value already matches" as success.

[3.5.1] - 2026-06-01

Critical hotfix for 3.5.0.

Fixed

- 3.5.0 caused a fatal error ("critical error", HTTP 500) on every page, including wp-admin. The new OAuth class was named MCP_OAuth but the autoloader maps that to class-mcp-o-auth.php (it splits before each capital), while the file is class-mcp-oauth.php, so the class could not be found and instantiating it fataled on every request. Renamed the class to MCP_Oauth to match the autoloader. Anyone on 3.5.0 should update immediately.

[3.5.0] - 2026-06-01

Use SEOWing directly inside Claude.ai, and let the assistant finish image and llms.txt tasks it previously declined.

Added

- Claude custom connector (OAuth 2.1). SEOWing can now be added as a remote MCP connector in the Claude app and web, not only via Claude Code CLI. The plugin acts as its own OAuth 2.1 + PKCE authorization server: discovery metadata (RFC 9728 / RFC 8414), dynamic client registration (RFC 7591), a WordPress-login authorization step, and access/refresh tokens. An unauthenticated MCP call now returns 401 with a WWW-Authenticate header so Claude can start the flow. CORS is sent for the browser-based connector. Off by default; enable under SEOWing > Settings > MCP ("Connect to Claude"), HTTPS required. Tokens run tools as the authorizing admin, so all capability checks still apply; expired tokens are pruned daily.

Fixed

- The AI assistant can now set featured images, optimize/convert images, run bulk image updates, regenerate llms.txt and ping IndexNow. These tools existed but were not in the assistant's curated toolset, so it kept replying that it "could not do" those tasks. They are now available.

[3.4.7] - 2026-06-01

Correct German spelling in generated content, and audit the whole multilingual site.

Fixed

- The AI assistant now writes real umlauts and eszett (ä, ö, ü, ß) and other accented characters in the content language, instead of transliterating to ae/oe/ue/ss or dropping them. Generated meta and content for German sites is now spelled correctly (for example "Prüflabor für Materialprüfung"). - Audits now cover every language. WPML/Polylang restrict WordPress queries to the active language by default, so on a bilingual site (e.g. German + English) only half the pages were audited. Both the AI audit and the admin "Run Full Audit" now scan all translations.

Changed

- The AI seo_full_site_audit analyzes more pages per call (default 100, up to 500) and the tool now tells the assistant to paginate through every page on large sites before summarizing, instead of judging the whole site from the first batch.

[3.4.6] - 2026-06-01

Recent chats no longer disappear.

Fixed

- AI conversations are now stored in the database (user meta) instead of transients, so they survive page reloads and object-cache eviction (common on managed hosts). Previously a transient could be evicted at any time, which emptied the "Recent chats" list and lost context on the next message. - Conversation expiry is enforced by timestamp (7 days idle) rather than a transient TTL. Legacy transient histories are still read once for a smooth transition. - A turn that times out or errors now still saves its history, so the thread appears in Recent and a retry keeps context instead of starting blank.

[3.4.5] - 2026-06-01

Second timeout root-cause: the AI tool seo_full_site_audit on large, document-heavy sites.

Fixed

- The audit's PDF scan is now bounded by both count and wall-clock time (defaults: 12 files, 8 seconds; filters seowing/audit/pdf_scan_limit and seowing/audit/pdf_scan_seconds). On sites with many accreditation PDFs the scan previously read up to 50 files from disk in one request, which could exceed a strict host gateway timeout. The reported total PDF count is unchanged; only how many are read per call is capped. - The seo_full_site_audit tool raises its time ceiling as a safety margin.

Note

- This complements 3.4.4 (which fixed the admin "Run Full Audit" button). The two audits are separate code paths; both are now timeout-safe.

[3.4.4] - 2026-06-01

Root-cause fix for the Full Audit timing out (504) on real sites.

Fixed

- The site-wide audit no longer fetches every page over HTTP. The internal-link check did one wp_remote_get (15s timeout) PER POST in a single synchronous request, so on a site with many pages the audit reliably hit the gateway timeout and returned a 504. It now counts internal links from the stored content (post_content + Elementor data) with no network calls, producing the same result instantly. - The audit request raises its time and memory ceiling on large sites as a safety margin; with the HTTP loop gone the audit is now CPU/DB-bound and finishes well within it.

[3.4.3] - 2026-06-01

Root-cause fix for AI Assistant timeouts (the 504 on long runs).

Fixed

- The agent now keeps a wall-clock budget (default 45s, filterable via seowing/ai/time_budget) and stops itself cleanly between tool rounds before the server's gateway timeout can fire. It then summarizes what it completed and offers to continue, so a long task never ends in a silent 504. Partial work is always preserved and reported.

[3.4.2] - 2026-06-01

AI Assistant reliability: it now always reports back, recent chats stay current, and timeouts no longer hang the chat silently. Audit screen redesigned.

Fixed

- The assistant always ends with a plain-language summary. When a tool run finished with no text, or the step limit was reached, it now forces a final text-only turn that says what it did and asks for anything it still needs, instead of going silent or showing "(no reply)". - "Recent chats" refreshes after every turn (new server endpoint seowing_ai_recent), so a chat shows up without reloading the page. - Chat and Apply requests now abort cleanly on a server timeout and show a clear message with any steps that finished, instead of hanging or a bare "request failed". A failed step in an Apply no longer aborts the rest.

Changed

- Audit & Autopilot screen rebuilt in the new design: severity-led issue cards (critical/warning/passed) with area tags, affected counts, the MCP tool name in mono, and an expandable preview of the affected items.

[3.4.1] - 2026-05-30

Polish pass on the new brass interface.

Changed

- Warm neutral gray scale across the whole admin so the page chrome harmonises with the brass accent instead of the old cool, blue-tinted gray. - Score ring gained depth (inner shadow + soft brass glow); cards now lift gently on hover with a refined shadow; health rows highlight on hover and their Fix arrow nudges. - Primary brass buttons use a subtle gradient and press feedback; severity dots carry a faint coloured ring so they read on any background. - All motion respects prefers-reduced-motion.

[3.4.0] - 2026-05-30

Visual rebrand of the whole admin: warm brass and gold palette with IBM Plex typography, plus a rebuilt dashboard.

Changed

- New brand palette across every SEOWing admin screen: the old orange accent is replaced by a warm brass/gold scale, driven from a single set of design tokens so audit, meta, schema, settings and the setup wizard all pick it up at once. - Typography switched to IBM Plex Sans for the interface and IBM Plex Mono for tool names and metrics, giving the cockpit a deliberate, instrument-panel character. - Focus rings, gradients and module accents recoloured to match; no more stray blue or indigo from earlier themes.

Added

- Rebuilt dashboard (Data cockpit layout): a brass SEO-score ring, four metric tiles (indexable pages, SEO coverage, published posts, active modules), a live Site Health snapshot computed straight from the database (missing meta titles, missing descriptions, images without alt text) with one-click links to the fix, the MCP server status, and the active-module list.

[3.3.7] - 2026-05-29

Proactive site-health snapshot in the AI Assistant empty state.

Added

- Site health card on the AI Assistant landing screen lists concrete issues the assistant can fix in one click: incomplete company profile, missing local-SEO fields, missing E-E-A-T experience markers, published pages with no meta title, images without alt text, and a missing llms.txt. - Each issue is a clickable row coloured by severity (red high, amber medium, blue low) that pre-fills the chat composer with the fix prompt so the operator can hit Send or edit first. - Re-scan control on the card to refresh after fixes; results are cached for five minutes so opening the page is cheap. - New ajax endpoint seowing_ai_health (capability-gated, nonce-protected) drives the snapshot.

[3.3.6] - 2026-05-29

Recent chats in the empty state, collapsible run log.

Added

- Recent chats card in the AI Assistant empty state: shows the last six conversations (title, age) and resumes one with a click so the operator can continue where they left off. - Per-user conversation index in user-meta backs the recent-chats list and is trimmed automatically when a conversation expires or is reset.

Changed

- Run log moved into a collapsed <details> panel labelled "Run log (N)" so the chat stays the focus and the debugging surface is one click away when needed.

[3.3.5] - 2026-05-29

When business identity fields are missing, the assistant now asks for them in the chat and can save them itself, instead of going silent or refusing.

Added

- seo_update_settings is now in the curated core toolset, so the assistant can persist business identity values (Company, Local SEO, E-E-A-T) directly from the conversation after the operator provides them.

Changed

- System prompt updated: when a needed business field is empty, the assistant asks the operator in plain language for the specific values, saves them via seo_update_settings (group company / local / eeat), and then continues with the original task. Pointing the operator to the matching Settings tab is offered as an alternative, not the only path.

[3.3.4] - 2026-05-29

Fix a real correctness gap in the AI Assistant. The agent now sees the business identity instead of guessing it from page content, and is forbidden from inventing factual company data.

Added

- Company (legal name, address, phone, email, VAT/UID, founded year), Local SEO (NAP, opening hours, areas served, coords) and E-E-A-T (experience, expertise, authors, certifications) settings are now injected into the agent's cached site-context block on every run. - When a business field is empty, the context flags it as EMPTY and includes the exact Settings tab URL so the assistant can tell the operator where to fill it in.

Changed

- System prompt: the agent must use the BUSINESS IDENTITY block verbatim for any factual business detail and must NEVER invent the company name, address, phone, VAT, founded year, opening hours, services, authors or certifications. If a needed field is empty, it stops and points the operator at Settings.

Fixed

- The site-context cache is now invalidated when Company / Local / E-E-A-T settings are saved, so updates take effect on the next run.

[3.3.3] - 2026-05-29

AI Assistant chat redesigned in a Vercel/shadcn style.

Changed

- Empty state with a centered "How can I help today?" greeting and a bordered skills card whose rows show an icon, title, description and arrow. The skill card disappears on the first message and returns after "New chat". - Header is tighter with a model badge, a ⌘K keyboard hint, and an icon button for new chat. - Composer becomes a single framed control: textarea on top, a toolbar with mode select, post id, working indicator and a primary Send button with the ⌘⏎ keyboard hint at the bottom. - ⌘K / Ctrl+K focuses the composer; ⌘⏎ / Ctrl+Enter sends. - Refined typography (system stack, tighter letter spacing on titles), hairline borders, neutral palette with the teal accent kept only for the Plan / Apply panel and the live progress pulse.

[3.3.2] - 2026-05-29

Visual polish pass on the in-admin AI Assistant chat. Pulled the inline styles into a proper stylesheet, refined the type and colour palette, and tightened every component so the chat feels like a premium product instead of an admin form.

Changed

- Typography uses the system Inter stack with refined sizing, weights and letter-spacing. The whole chat reads as one piece, not a stack of cards. - A neutral colour palette (zinc-ish greys + the SEOWing teal accent used sparingly) replaces the ad-hoc inline colours. - Header: cleaner badge for the model, a refined custom-styled select for the Preview / Execute mode, and a quieter New chat button. - Bubbles: smaller rounded-square avatars (Du / AI), a small caption label, and content rendered through a proper typographic scale. Messages fade in. - Skill chips: pill style with hover state in the accent colour, always visible above the composer. - Composer: focus ring on the textarea and the post-id input, primary Send button with a hover accent. Working… shows a pulse, not a static string. - Plan / Apply block: highlighted accent panel with a tighter call-to-action.

[3.3.1] - 2026-05-29

UI polish for the in-admin AI Assistant chat.

Changed

- The assistant reply now renders a small subset of Markdown in the chat (paragraphs, bullet and numbered lists, bold, code and short ## headings). Horizontal-rule lines and ALL CAPS pseudo-headings are now explicitly discouraged in the system prompt, so the model no longer falls back to those workarounds. - Chat bubbles get role avatars (Du, AI) and a cleaner flex layout, with monospace styling for code spans so filenames and ids stand out. - The skill chips stay visible after the first message (no longer hidden), so the quick-action prompts remain one click away throughout the conversation.

[3.3.0] - 2026-05-29

Feature release. A major overhaul of the in-admin AI Assistant: it now works reliably and feels like a real chat product.

Added

- Conversation memory: the assistant keeps context across turns (follow-ups like "now make it shorter" work), with a "New chat" reset. - Preview to approve to apply: preview produces a concrete plan; the "Apply" button runs exactly those steps (no re-planning), with a per-run write cap. - Live progress: a tool-by-tool ticker shows what the assistant is doing in real time instead of a blank wait. - Run log and token tracking: every run records mode, steps, tokens, duration and result (shown under the AI Assistant settings). - Full chat UI: the AI Assistant page is now a large chat. Provider, model and API key configuration moved to Settings, AI tab. Integrated SEO and GEO skill shortcuts (site audit, page meta, schema, GEO/AEO, redirects, image alt text).

Changed

- Curated the tools exposed to the model (a high-value core set) for better tool selection and lower cost. - Stronger system prompt with injected site context and the SEO playbook. - Bigger step and token budgets; retries with backoff on transient API errors. - Refreshed default models (gpt-4.1, gemini-2.5-flash, claude-sonnet-4-6). - The assistant never writes em or en dashes and replies in plain text.

Fixed

- Gemini tool-call id collisions on parallel or repeated calls.

[3.2.0] - 2026-05-29

Feature release. In-admin AI assistant - make AI-driven SEO changes directly in wp-admin with your own model key, without Claude Code / MCP.

Added

  • AI Assistant (includes/ai/, SEOWing → AI Assistant). Add your own OpenAI / Anthropic / Gemini API key (stored encrypted) and chat with an assistant that edits the site for you.
  • Multi-provider LLM client with normalized tool-calling across all three providers, plus a connection test.
  • Agent loop that drives the model with the plugin's existing ~55 MCP tools as callable functions (MCP_Server::run_tool()), so the assistant can read and change meta, content, schema, images, redirects, etc. Step cap + result truncation guard against runaway loops/cost.
  • Gated: premium (License::can_use_premium()) and off until a key is configured - so unlicensed/unconfigured sites are unaffected.

Safety

  • Preview mode (default): the chat defaults to "Preview - plan only" - write tools are simulated (not executed) and the assistant lists exactly what it *would* change; switch to "Execute" to apply. Read tools still run so it can plan. Write vs. read is classified via the MCP scope map.
  • Dangerous tools blocked: seo_self_update and seo_delete_post are never exposed to the agent (filter seowing/ai/blocked_tools).
  • Step cap (default 8, seowing/ai/max_steps) + per-result truncation guard against runaway loops and token cost.

[3.1.16] - 2026-05-29

Fix release. The first-run setup wizard's "Skip" was broken and trapped admins.

Fixed

  • Setup wizard "Skip" now works (and no longer traps the admin). The wizard set a pending flag on activation and maybe_redirect_to_wizard() bounced *every* admin page back to the wizard until the flag cleared - but the flag only cleared on form submit, and "Skip" was a plain link that didn't clear it. Net effect: the admin couldn't reach any page (incl. Skip) without filling in and submitting the form. "Skip" is now a nonce-protected action that clears the pending flag and goes to Settings; the wizard is a one-time nudge again, not a wall.

[3.1.15] - 2026-05-29

Fix release. Removes a spammy-structured-data risk in FAQPage schema.

Fixed

  • FAQPage schema no longer fabricates Q&A from ordinary headings. The content fallback in FAQ_Page (class-faq-page.php) previously turned *any* <h3>/<h4> shorter than 200 characters into a fake FAQ "Question", so almost every page's headings could emit FAQPage mainEntity entries. That is "spammy structured markup" under Google's guidelines and an active manual-action risk. The fallback is now strict - only a heading that is itself a question (contains ?, ≥15 chars) followed by a real paragraph answer (≥40 chars) qualifies, matching the autopilot's extract_faq_pairs eligibility check. Pages with an explicit FAQ block, FAQ meta fields, or a literal "FAQ"/"Häufig gestellte Fragen" section are unaffected; pages without genuine Q&A simply emit no FAQ schema.

[3.1.14] - 2026-05-28

Feature release. License-based gating of the premium automation surface.

Added

  • License::can_use_premium() / License::enforced(): the gate primitive. When enforcement is on and the site is not licensed/activated, premium features are withheld.
  • MCP surface gate: check_permissions() now refuses the entire MCP endpoint (402) when premium is not allowed - the per-site MCP token is the automation kill-switch, now also tied to license state.
  • Admin notice when enforcement is on but no active license is present.

Important

  • Enforcement is OFF by default. Updating the plugin changes nothing on existing installs; the MCP keeps working. Turn it on per-site only after a license is active, via the SEOWING_LICENSE_ENFORCE constant, the seowing_license_enforce option, or the seowing/license/enforce filter. This mirrors the v3.1.5 rollout discipline - never batch-lock sites.
  • Frontend SEO output (meta, schema) is never gated: a lapsed license stops new automation but never breaks a site's existing, live SEO.

[3.1.13] - 2026-05-28

Feature release. Turns SEOWing into a licensed product with secure, self-hosted auto-updates (delivered from api.seowing.io to licensed sites only).

Added

  • License module (includes/license/): a License admin page under the SEOWing menu to enter and activate a per-site license key. The key is stored encrypted and never leaves the site except over HTTPS to the license server.
  • Per-site activation bound to the site's domain, with seat limits and expiry enforced server-side. "Deactivate" frees a seat so a license can move.
  • Licensed auto-updates via the bundled Plugin Update Checker library (includes/lib/plugin-update-checker/, v5.7). Licensed + activated sites see "Update verfügbar" in the WordPress admin and update with one click; the download is license-gated.
  • Daily status re-check (cron seowing/license/daily_check) with a 14-day grace window: if the license server is briefly unreachable, a valid license keeps working - an outage never bricks a paying customer's site.
  • Update URI header pointed at https://seowing.io so WordPress.org cannot hijack updates for the seowing slug.

Notes

  • The license key is the credential for all license/update API calls - no shared secret is embedded in the plugin.
  • License::is_active() / is_valid() are exposed for future feature gating.

[3.1.12] - 2026-05-28

Fix release. Hardens the author and navigation-menu tools added in 3.1.8 - 3.1.11.

Fixed

  • Invalid author no longer reintroduces the service-account byline. When a post is created via a token request and an explicit author is given but cannot be resolved (typo, wrong email/ID), the new post now still falls back to the first administrator instead of silently being attributed to the low-privilege seowing_mcp_service account - the exact byline bug 3.1.10 fixed.
  • Numeric author IDs are validated. A numeric author referencing a non-existent user is rejected (resolves to "not found") instead of being written as a dangling post_author.
  • seo_add_menu_item rejects broken object references. A post_type or taxonomy menu item now requires an object_id that references an existing post/page or term; previously a missing or invalid object_id created a dead menu entry pointing at object 0.

[3.1.11] - 2026-05-28

Feature release. Adds Media Library uploads via MCP.

Added

  • seo_upload_media (settings:write): uploads a base64-encoded file (image, PDF, Word/Office document, etc.) into the WordPress Media Library as a proper attachment and returns its ID and URL. Hardened: only get_allowed_mime_types() are accepted, an explicit dangerous-extension blocklist (php/js/html/exe/svg/…) is enforced, a 25 MB cap applies, and the written file's real content is re-verified against its extension. Registered in the scope map.

[3.1.10] - 2026-05-28

Fix. MCP-created posts showed the low-privilege service account as the public byline.

Added / Fixed

  • author parameter on seo_create_post (user ID, login, slug or email): sets the post author / public byline.
  • New posts no longer default to the MCP service account. When a post is created via a token request (running as the seowing_mcp_service user) and no author is given, it is attributed to the first administrator instead, so the service account never appears as the public author.

[3.1.9] - 2026-05-28

Feature release. Completes navigation-menu management with ordering.

Added

  • seo_reorder_menu (settings:write): reorders a menu by passing item IDs in the desired order; reassigns menu_order sequentially via a surgical wp_update_post that leaves the items' other fields untouched.
  • position parameter on seo_add_menu_item: place a new item at a specific order position instead of appending.

[3.1.8] - 2026-05-28

Feature release. Adds taxonomy and navigation-menu management so content can be fully categorized and linked from the MCP tools, without manual WP-admin steps.

Added

  • Categories, tags and custom taxonomy terms in seo_create_post. New categories, tags and terms parameters. Category/term names that do not exist are created; assignments replace existing terms and are guarded by the post type's registered taxonomies.
  • Navigation-menu tools. seo_get_menus (read) lists menus, their items and theme locations. seo_add_menu_item (settings:write) adds an item to a menu, creating the menu if it does not exist, and links a page/post, a taxonomy term, or a custom URL. Both are registered in the scope map (default-deny still applies to any future unmapped tool).

[3.1.7] - 2026-05-26

Admin UI bug-fix release. Found during a runtime functional audit of the wp-admin screens (view -> JS -> REST/AJAX wiring). These are pre-existing admin defects, independent of the 3.1.5/3.1.6 MCP security work.

Fixed

  • CRITICAL (data loss): Settings tabs silently reset to defaults on save. handle_settings_post() read inconsistent POST keys (e.g. $_POST['titles'] while the view posts seowing_titles[...]), so Titles & Meta, Social, Sitemap, Schema and the MCP form fields saved an empty array, which save_group_settings() then merged over with the group defaults, wiping the operator's input while showing a green "saved" confirmation. Replaced the per-group switch with one generic read (seowing_<group> first, bare <group> fallback).
  • Imagify quota showed "NaN undefined". The check-key AJAX returned the raw /users/me body instead of the normalized quota; now returns get_quota().
  • Local SEO "Business Info" tab rendered empty. Panels relied on a hidden toggle while the CSS only shows .seowing-tab-content.active; switched markup and JS to the .active convention.
  • Internal Links page unstyled + dead tabs. Added the missing assets/css/modules/internal-links.css (overview cards, stat rows, PageRank bar, depth, badges) and enqueued it; fixed the tab handler (.sw-tab / .active, was .nav-tab / .hidden).
  • Tools "Regenerate Sitemap" button did nothing. It sent the generic seowing_ajax nonce; the handler verifies the seowing_sitemap nonce in the nonce field. Passed it explicitly.
  • Sitemap: could not enable/disable individual types + settings never saved. Registered the missing seowing_save_sitemap_settings handler, added per-type toggle checkboxes (Authors, News, Videos, custom post types), and unified per-type on/off onto a single store (enabled_types) that every provider reads (Authors is no longer hardcoded off). Defaults preserve current behaviour until saved.

Verify on staging

Save each previously-broken settings tab and reload to confirm values persist; toggle a sitemap type (e.g. Authors) on and confirm it appears in the sitemap.

[3.1.6] - 2026-05-25

Patch on top of 3.1.5, found during staging verification of the per-site MCP key feature. Both issues block or obscure token issuance on real installs.

Fixed

  • Per-site token table was never created on existing installs. The {prefix}seowing_mcp_keys table was added in 3.1.5 (2f5eb6d) without bumping Database::DB_VERSION (last set to 1.2.0 in v1.5.29). On any site already at db_version 1.2.0, needs_update() returned false, so the upgrade path skipped create_tables() and the table was missing. Issuing a token then failed in MCP_Key_Store::create() ($wpdb->insert returns false → "Could not store the token."). Bumped DB_VERSION to 1.3.0 so the init upgrade routine creates the table automatically on next load - no reactivation required, on every site.
  • MCP settings UI collapsed every AJAX error to a bare "Failed." The script read res.data.message, but ajax_error() returns the message at top-level res.message. The issue/revoke/legacy-invalidate handlers now read both, so the real error surfaces instead of a generic "Failed."

[3.1.5] - 2026-05-25

Security release (P0). Replaces the MCP authentication model. This version also contains the fixes that were prepared as 3.1.4 but never released; there is no separate 3.1.4 build, so nothing is missing between 3.1.3 and 3.1.5.

Security

  • CRITICAL - MCP auth no longer grants full administrator. Previously a valid API key called wp_set_current_user( first administrator ), making every per-tool capability check cosmetic. Removed. Token/legacy requests now run as a dedicated low-privilege service user (seowing-mcp-service, custom role with only read), and authorization is decided by scopes.
  • CRITICAL - per-site hashed tokens replace the shared plaintext key. Tokens are stored only as SHA-256 hashes ({prefix}seowing_mcp_keys), compared with hash_equals(), shown once at creation, individually revocable. No clear-text round-trip. Issue/revoke from SEOWing -> Settings -> MCP.
  • Scope-based, default-deny authorization. Every one of the 55 MCP tools is mapped to a coarse scope (read, content:write, settings:write, self_update) in MCP_Scopes. A tool not in the map, or a credential lacking the scope, is rejected at the dispatch gate. The wildcard * never covers self_update. The 7 previously capability-less autopilot tools now each carry an explicit scope.
  • seo_self_update now requires the explicit self_update scope in addition to the existing SEOWING_ALLOW_SELF_UPDATE wp-config constant (double-gated).

Migration (dual-accept, no downtime)

  • During the migration window the server accepts BOTH the legacy shared key and new per-site tokens. Order: ship 3.1.5 everywhere -> issue + roll out per-site tokens -> only then invalidate the legacy key.
  • Invalidation encrypts a break-glass backup of the old key via the existing Encryption (AES-256) path, then clears it and blocks auto-recreation. A fail-safe purge (scheduled cron + opportunistic age check on admin load) destroys the backup after 7 days. Break-glass restore_legacy() works only within that window.
  • The admin UI guards invalidation behind a safety check: a new token must be warm (used) AND the legacy key cold (unused 3+ days). Override with force.

Fixed (carried from the unreleased 3.1.4)

  • seo_self_update: opt-in SEOWING_ALLOW_SELF_UPDATE gate + zip-slip guard.
  • seo_get_settings: redact api_key / imagify_api_key / semrush_api_key.
  • MCP key mismatch path no longer logs any portion of the key.
  • MCP per-IP rate limiter: transient fallback when no object cache is present.
  • seo_upload_file: dropped .htaccess and .js from the allowlist.

MUST verify on staging before any client site

  • Valid new token accepted; invalid/revoked rejected; revocation takes effect immediately.
  • Dual-accept (old + new) works during the transition.
  • seowing_mcp_keys stores only hashes (no clear text anywhere).
  • wp_set_current_user(admin) is gone: a settings:write tool called with a read-only token is correctly DENIED.
  • Each of the 7 autopilot tools (seo_full_site_audit, seo_get_playbook, seo_auto_setup, seo_fix_audit_issues, seo_fix_meta_bulk, seo_fix_norm_schema, seo_generate_schema) tested individually against its assigned scope, not sampled.
  • seo_self_update still blocked without both the constant and the scope.
  • Legacy invalidation: backup is encrypted; the fail-safe purge removes it after 7 days even if cron was missed.

[3.1.3] - 2026-05-12

Patch release. Fixes a long-standing bug where <meta name="description"> was missing from rendered HTML on most sites.

Fixed

- CRITICAL <meta name="description"> was missing from every page on sites where the theme fires wp_head() more than once (e.g. nexsas, many page-builder themes). Root cause was a str_replace() in Schema::cleanup_duplicate_meta_descriptions() that removed every duplicate of the meta description tag when the theme double-fired wp_head - including the one we wanted to keep. Replaced with preg_replace_callback() that keeps only the first occurrence, removes the rest by callback (no global string replacement). OpenGraph and Twitter descriptions were unaffected because they don't pass through this cleanup buffer.

  • MEDIUM Meta_Frontend::get_description() used get_the_ID() which can return 0 in wp_head before the Loop runs. Now prefers get_queried_object_id() (always reliable in wp_head on singular pages) with get_the_ID() as fallback. Without this fix, sites where the theme fires wp_head before the_post() would have had no description even before hitting the buffer bug.

Symptom on affected sites: third-party SEO checkers reported "Description is missing!" on every page even though the SEOWing UI showed the value as saved.

[3.1.2] - 2026-05-12

Patch release. Adds self-protection against meta wipes caused by foreign save_post events (Elementor REST saves, page-builder AJAX, etc.).

Added

- Meta_Guard component (includes/modules/meta/class-meta-guard.php). Captures non-empty _seowing_* meta before each save (pre_post_update priority 1) and restores any key that went from a real value back to empty during the same request (save_post priority 999 + elementor/document/after_save). Does not interfere with intentional changes - only restores wipes. - Filter seowing/meta/guard_enabled to opt out per post. - Action seowing/meta/guard_restored for monitoring/logging.

Fixed

- MEDIUM SEOWing meta (title, description, focus keyword, robots, canonical, OG/Twitter overrides) no longer disappears when a page is saved through Elementor's REST endpoint or any other code path that fires save_post without carrying the SEOWing nonce. Previously affected sites where the Elementor editor was opened on pages that already had MCP-set meta.

[3.0.0] - 2026-04-29

Major release. Three confirmed schema-rendering bugs are fixed, the production ZIP is 15× smaller, and the plugin gains a first-time setup flow.

Fixed

- CRITICAL Schema fallback in Frontend::get_organization_schema() / get_local_business_schema() no longer reads from the legacy seowing_general.company_* keys. Both methods now hydrate from the canonical seowing_company group, so telephone, foundingDate, vatID, geo, and sameAs actually render when the Schema module is disabled. - MEDIUM Local_Business::generate() now inherits address, phone, email, geo, and price range from seowing_company / seowing_local. Per-post LocalBusiness schemas no longer ship empty when the operator hasn't filled every field manually. - MEDIUM Local_SEO::get_default_business_info() no longer falls back to get_bloginfo('admin_email') and get_bloginfo('name'). The "ghost" LocalBusiness schema we saw on production sites (with the WP admin email leaking into JSON-LD) is gone - defaults now come from seowing_company / seowing_social / seowing_local.

Added

- bin/build-zip.sh reproducible production build script. Required before every release. Old ad-hoc zip -r invocations missed mcp-bridge/ and every *.md file, which is why pre-3.0 ZIPs shipped at 9.7 MB instead of ~500 KB. - Real Tailwind v4 build pipeline. assets/css/tailadmin.css is now generated from src/admin.css by the standalone Tailwind CLI (bin/install-tailwind.sh to vendor it locally; bin/build-zip.sh invokes it on every release). Result: 36 KB instead of 124 KB (−71 %), only the utilities actually referenced by includes/ and assets/js/ are emitted, custom shadow-theme-* tokens are preserved, and the CSS is reproducible from source.

Critical post-rollout patches

- Setup wizard rendered without styles because seowing_page_seowing-setup was missing from Admin::enqueue_assets()'s page whitelist. Added. - Every per-module stylesheet (assets/css/modules/*.css, assets/css/integrations/elementor.css) consumes 20+ --sw-* design tokens (--sw-brand, --sw-gray-50, --sw-radius-sm, --sw-success, --sw-ease, --sw-shadow-xs, etc.) that the pre-3.0 vendored TailAdmin dump declared but the new build never re-emitted - so every module page rendered colorless and unstyled. Restored in src/admin.css as first-class design tokens that alias the Tailwind theme tokens, so there is now one source of truth for color and spacing across utility classes AND hand-rolled module CSS.

Design / Visual fixes

- Restored full color palette in the Tailwind theme. The pre-3.0 vendored TailAdmin dump shipped bg-success-*, bg-warning-*, bg-error-* rules that referenced colors which the new build couldn't generate, leaving dashboard cards, badges, and notices visually broken (transparent backgrounds, invisible icons). All four palettes (brand / success / warning / error) are now declared with full 50-900 scales in src/admin.css so every utility resolves correctly. - Replaced 87 off-scale text-[13px] / text-[15px] / text-[11px] arbitrary classes with the standard text-xs / text-sm / text-base scale. Forms, descriptions, and labels now sit on the type system instead of breaking it. - Description text contrast bumped from text-gray-400 to text-gray-500 in 18 places - meets WCAG AA contrast for body copy on white. - Setup wizard re-styled from raw <table class="form-table"> to the same Tailwind card/grid system the rest of the admin uses. Hero gradient banner, numbered step badges, two-column responsive form, sticky action footer. - Page-load stagger animations (.sw-reveal + 6 delay tiers, pure CSS, prefers-reduced-motion respected). Dashboard hero, four metric cards, coverage bar, and two-column grid fade up on first paint. Wizard hero plus three steps stagger in. No JavaScript, no library; respects users who request reduced motion. - Custom inline SVG illustration for the "no active modules" empty state - isometric stack of plates with a brand-orange spark, replacing the generic dashicon-in-a-circle. Pure SVG, no external assets, follows the brand palette via currentColor. - Typographic polish via system-font OpenType features. The admin now opts into font-feature-settings: "ss01", "cv11", "case", "calt" and tabular-nums for a more refined feel - stats line up, headings get tighter letter-spacing (-0.02em), and we ship zero font files (no GDPR risk, no extra HTTP requests). - Settings_Keys constants class (includes/class-settings-keys.php) - single source of truth for settings group names and well-known field keys. Replaces magic strings like 'company.phone' and $general['company_phone']. - Setup_Wizard first-time onboarding flow at SEOWing → Setup. Triggered the first time an admin loads wp-admin after activation if seowing_company.name is empty. Captures Company info, basic E-E-A-T fields, and surfaces the MCP API token in one screen. - Module dependency validation - Module_Manager::load_modules() now reads Module_Base::$dependencies and skips modules whose required dependencies aren't loaded. Skipped modules surface via get_dependency_failures() for admin notices instead of failing silently. - Capability checks on the six previously-unguarded seo_* MCP tools in class-seo-tools.php (analyze_page, calculate_score, bulk_analyze, bulk_calculate_scores, get_suggestions, suggest_internal_links). All require edit_posts, matching the rest of the MCP write surface.

Removed

- 7 deprecated modules and their assets are gone - they were marked deprecated since v2.6.0 but still shipped: content-generator/, templates/, content-decay/, clusters/, entities/, link-opportunities/, experts/ (PHP, JS, CSS). Existing settings rows in wp_options are preserved; only the runtime classes are dropped. Sites that depend on these modules should pin to v2.x. - mcp-bridge/ is no longer bundled in the production ZIP. It's a developer tool, not a runtime dependency. Ships separately via GitHub releases. - All planning / audit Markdown files (PLANNING.md, IMPROVEMENT-PLAN.md, MCP-ECOSYSTEM.md, MCP-TOOLS.md, tool-dokumentation.md, CONTEXT.md, CONTRIBUTING.md, ISSUES.md, AUDIT*.md, CLAUDE.md) are no longer bundled in the production ZIP. They live in the repo for developers only. - phpunit.xml, root package.json, root composer.json, .gitignore are no longer bundled.

Notes for upgraders

- The Schema module remains the recommended (and default) renderer. If you rely on the Frontend fallback path, expect richer JSON-LD on the next page load - fields that were silently dropped in v2.x will now appear. - If you previously stored business info in seowing_local_business (the Local SEO module's parallel option), nothing changes for you. Operators who configured everything in seowing_company and never touched the Local SEO admin page will see the LocalBusiness schema light up correctly for the first time. - The ZIP exclude list is now strict. Don't ship bin/build-zip.sh either - the script excludes itself.

[2.5.65] - 2026-02-23

Changed

- Split class-admin.php god class (2,532 lines) into 3 focused files: - Admin - menu, pages, settings, meta boxes, columns, core AJAX (915 lines) - Audit_Engine - all SEO audit checks, AJAX handler, cron audit (1,337 lines) - Tools_Handler - export/import, cache, DB optimize, orphan cleanup, migration (363 lines) - Audit engine and tools handler register their own hooks via constructors - Deduplicated audit post-type exclusion logic into shared get_auditable_post_types() - Unified AJAX/cron audit execution via shared run_audit() method

[2.5.64] - 2026-02-23

Changed

- Split class-autopilot-tools.php god class (3,833 lines) into 7 focused sub-classes: - Site_Auditor - full site SEO audit (~800 lines) - Site_Configurator - auto-setup fix orchestration (~700 lines) - Data_Detector - missing info collection, auto-detect, PDF scan (~540 lines) - Autopilot_Schema - JSON-LD schema generation (~500 lines) - Autopilot_Content - meta title/description/keyword generation (~380 lines) - Playbook_Generator - SEO/GEO/AEO playbook (~260 lines) - Autopilot_Helpers trait - shared is_dach_site() and get_public_post_types() - Autopilot_Tools reduced to thin router (~280 lines) with lazy-initialized sub-classes - Autoloader updated with fallback for trait- prefix files outside the Traits folder

[2.5.63] - 2026-02-23

Fixed

- Race condition in sitemap rewrite rules flush - transient lock prevents concurrent flush_rewrite_rules() calls - Scroll-spy memory leak in Elementor TOC - singleton pattern + requestAnimationFrame throttling - SEO score cached forever - now invalidated on save_post so score recalculates after content changes - Glossary query without limit - capped at 500 terms to prevent memory overflow - Nonce validation with sanitize_key() - replaced with wp_unslash() to preserve nonce integrity - Dynamic tag empty output on 404/archive pages - added wp_get_document_title() fallback - TOC widget data-settings double-escaped - use single-quoted attribute to avoid esc_attr(wp_json_encode()) double encoding

Changed

- Cache bridge uses pattern-based tool matching instead of hardcoded list - new MCP tools auto-trigger cache purge

[2.5.62] - 2026-02-23

Changed

- Remove unused seowing_meta custom table - all SEO data uses wp_postmeta (saves DB overhead on install/upgrade) - Frontend meta fetching aggregated via get_meta() helper - pre-fetches all keys in one call instead of 12+ individual get_post_meta() calls per page - Admin SEO scoring now delegates to Analysis module when active (single source of truth) - Admin fallback scoring simplified - removed expensive apply_filters('the_content') call

Added

- Meta_Keys constants class (includes/class-meta-keys.php) - centralized meta key definitions - indexnow and imagify settings groups in Settings class with migration from individual options - Static cache for entity auto-linking query - prevents unbounded posts_per_page=-1 on every the_content call, limited to 200

Fixed

- Entity auto-linking performance: query now cached per request and limited to 200 entities

[2.5.61] - 2026-02-23

Security

- Fix SQL injection risk in uninstall routine - all 6 queries now use $wpdb->prepare() - Fix unescaped schema output in Breadcrumbs widget - now uses wp_kses()

Fixed

- strpos() logic bug in meta keyword analysis - false was cast to 0, causing false-positive keyword_at_start - Fatal error in deactivate_module() when accessing ->is_core on a failed (cached false) module load - Module loading retry loop - failed modules are now cached as false to prevent repeated instantiation attempts

Added

- CSS custom properties (:root block) for Elementor widget styles (--sw-gray-50, --sw-gray-200, --sw-duration-fast, --sw-ease, --sw-radius-sm, --sw-success, --sw-warning, --sw-error) - Cache invalidation (wp_cache_delete) after module activate/deactivate for Redis/Memcached compatibility

[2.5.60] - 2026-02-23

Fixed

- HTML entities (&amp; etc.) appearing in JSON-LD schema output - added html_entity_decode() in Local SEO, JSON-LD, and Graph Builder - CPT archive pages now get proper hreflang tags via wpml_permalink filter

Changed

- Schema Generator module is now always active (is_core = true)

[2.5.59] - 2026-02-23

Fixed

- WPML hreflang for CPTs - added wpml_object_id fallback when icl_get_languages() fails for custom post types - Default language now auto-syncs from WPML instead of hardcoded 'en'

Changed

- SEO coverage dashboard now counts all public post types (not just posts/pages) - Hreflang audit now includes enabled CPTs in coverage stats

[2.5.58] - 2026-02-22

Added

- Meta title, description, and canonical support for CPT archive pages

[2.5.57] - 2026-02-22

Fixed

- Robust WPML hreflang suppression on non-default language pages - Trailing slash consistency in hreflang URLs

[2.5.56] - 2026-02-22

Fixed

- WPML hreflang bug - wrong URLs generated on non-default language pages

[2.5.55] - 2026-02-22

Added

- seo_index_now MCP tool for IndexNow instant indexing

[2.5.54] - 2026-02-22

Fixed

- Removed Disallow: /wp-includes/ from robots.txt template (blocks CSS/JS needed for rendering)

[2.5.53] - 2026-02-21

Added

- ProfessionalService added to LocalBusiness schema types

Fixed

- priceRange and image fields in Organization schema

[2.5.52] - 2026-02-21

Added

- Default OG image fallback for pages without featured images

[2.5.51] - 2026-02-21

Fixed

- og:image was outputting attachment ID instead of URL - Added og_image parameter to seo_update_meta MCP tool

[2.5.50] - 2026-02-17

Added

- Author archive 301 redirect to homepage (configurable) - Taxonomy/category noindex controls via MCP settings - Admin CSS visual polish - 14 UI enhancements

[2.5.49] - 2026-02-17

Changed

- Complete CSS migration to Tailwind v4 theme system (43 files, 660+ lines migrated)

[2.5.48] - 2026-02-17

Fixed

- Missed JSON_HEX_TAG in schema-tools Elementor fix

[2.5.47] - 2026-02-17

Security

- Security hardening + audit quick wins

[2.5.46] - 2026-02-16

Fixed

- Service page detection - only use custom schemas as source of truth

[2.5.45] - 2026-02-16

Fixed

- Duplicate schema cleanup now detects @type inside @graph arrays

[2.5.44] - 2026-02-16

Added

- @graph Schema Builder for auto-generated rich JSON-LD

[2.5.43] - 2026-02-16

Fixed

- MCP schema settings now sync to module storage

[2.5.42] - 2026-02-16

Fixed

- Schema headline → name for non-Article types

[2.5.41] - 2026-02-16

Fixed

- Definitive archive title prefix fix with JS fallback

[2.5.40] - 2026-02-16

Fixed

- Regex fallback to strip archive title prefix

[2.5.39] - 2026-02-16

Fixed

- Archive title prefix filter moved to main class for reliable loading

[2.5.38] - 2026-02-16

Fixed

- Archive title prefix removal for glossary pages

[2.5.37] - 2026-02-16

Added

- wp_tagline/wp_blogname sync to WordPress core options

[2.5.36] - 2026-02-16

Added

- German labels for glossary post type and clean archive title

[2.5.35] - 2026-02-16

Added

- [norm_field] shortcode for Elementor Dynamic Tags

[2.5.34] - 2026-02-15

Added

- Expert email, phone, photo_url fields to norm meta

[2.5.33] - 2026-02-15

Changed

- Expert card: white background with dark text

[2.5.32] - 2026-02-15

Changed

- Experts module now always active (is_core = true)

[2.5.31] - 2026-02-15

Added

- Reusable Experts module with team CPT integration

[2.5.30] - 2026-02-15

Added

- Registered norm meta fields + custom_meta support in seo_create_post

[2.5.29] - 2026-02-15

Added

- Configurable HSTS header support

[2.5.28] - 2026-02-15

Fixed

- seo_generate_schema MCP tool now defaults to WebPage for pages (was overriding v2.5.27 fix)

[2.5.27] - 2026-02-15

Changed

- WordPress pages now default to WebPage schema instead of Article

[2.5.26] - 2026-02-15

Fixed

- Skip BreadcrumbList on homepage to avoid duplicate URL error

[2.5.25] - 2026-02-15

Fixed

- Redirect MCP tools column name mismatch with repository schema - Query-string redirect support (e.g. /?page_id=520 → /kontakt/)

[2.5.24] - 2026-02-15

Fixed

- Article schema: image fallback chain (featured → OG → content → site icon → theme logo) - Article schema: author fallback to Organization for generic usernames - Article schema: publisher logo URL resolution

[2.5.23] - 2026-02-15

Added

- Multiple Certification schemas allowed per page

[2.5.22] - 2026-02-15

Fixed

- OG tags using wrong module check - Schema internal deduplication (cleanup_duplicate_schemas) - WP core sitemap disabled (SEOWing generates its own) - @type case normalization (30+ mappings)

[2.5.21] - 2026-02-14

Added

- Auto-remove duplicate JSON-LD schemas from themes/plugins

[2.5.20] - 2026-02-14

Fixed

- Image audit: count unique files, file has alt if ANY post entry has it

[2.5.19] - 2026-02-14

Fixed

- WPML image audit: use LEFT JOIN for shared media without translation entries

[2.5.18] - 2026-02-14

Added

- WPML-aware image audit to exclude duplicate attachments

[2.5.17] - 2026-02-14

Added

- Quick Connect command on MCP settings page

[2.5.16] - 2026-02-14

Changed

- SEO-expert keyword generation from industry + search intent

[2.5.15] - 2026-02-14

Added

- Smart focus keyword generation for all page types

[2.5.14] - 2026-02-14

Added

- Intelligent auto-schema for homepage + CPTs

[2.5.13] - 2026-02-13

Added

- lang parameter to seo_auto_setup for WPML translations

[2.5.12] - 2026-02-13

Fixed

- Schema coverage audit now includes CPTs and custom schemas

[2.5.11] - 2026-02-13

Added

- Auto-setup fixes search engine visibility (noindex) setting

[2.5.10] - 2026-02-13

Changed

- Fetch rendered HTML for internal link audit (more accurate)

[2.5.9] - 2026-02-13

Removed

- "SEO by GoldenWing" backlink from frontend footer

[2.5.8] - 2026-02-13

Fixed

- Audit internal links by parsing Elementor JSON data directly

[2.5.7] - 2026-02-13

Added

- GEO Score Analyzer activated by default on existing installs

Fixed

- Audit internal links detection

[2.5.6] - 2026-02-13

Fixed

- Broken modal CSS on redirects page

[2.5.5] - 2026-02-13

Fixed

- Audit score calculation - Elementor internal links detection

[2.5.4] - 2026-02-12

Changed

- Exclude Elementor templates from CPT audit/auto-setup

[2.5.3] - 2026-02-12

Fixed

- All 9 remaining issues from biopower site audit

[2.5.2] - 2026-02-12

Fixed

- wp_generate_attachment_metadata() crash in REST context

[2.5.1] - 2026-02-12

Fixed

- MCP Streamable HTTP transport compatibility

[2.5.0] - 2026-02-12

Added

- Native MCP Streamable HTTP Transport

[2.4.0] - 2026-02-11

Changed

- Complete Tailwind CSS v4 migration - major UI overhaul

[2.3.2] - 2026-02-11

Changed

- Migrate meta and schema meta box views to Tailwind utilities

[2.3.1] - 2026-02-10

Added

- Auto-detect GMB, GPS coordinates, social profiles, and logo from site content

[2.3.0] - 2026-02-10

Added

- Major autopilot upgrade: module auto-enable, PDF scan, missing info prompts, backlink injection

[2.2.2] - 2026-02-09

Fixed

- Tools page: add spacing, implement all AJAX handlers

[2.2.1] - 2026-02-09

Fixed

- CSS/UI issues: audit layout, toggle duplication, spacing, overflow

[2.2.0] - 2026-02-09

Changed

- Smart Autopilot: seo_auto_setup now applies SEO/GEO best practices automatically

[2.1.1] - 2026-02-08

Fixed

- MCP parameter handling - accept both params and arguments keys

[2.1.0] - 2026-02-08

Added

- SEO Autopilot: seo_full_site_audit, seo_auto_setup, and seo_get_playbook MCP tools

[2.0.1] - 2026-02-07

Fixed

- Migrate missing CSS from legacy admin.css, then delete it

[2.0.0] - 2026-02-07

Changed

- Complete plugin overhaul: MCP split, CSS consolidation, deduplication, security hardening

[1.6.2] - 2026-02-06

Fixed

- Form field accessibility: add id/name to module toggles, fix label for separator

[1.6.1] - 2026-02-06

Changed

- TailAdmin UI integration - replace custom CSS with Tailwind v4

[1.5.42] - 2026-02-05

Security

- Deep audit: fix 57 issues across security, logic, and dead code

[1.5.39] - 2026-02-05

Added

- Improvement plan and automation ideas

[1.0.0 - 1.5.38] - 2026-01 to 2026-02

Added

- Initial release with full module system - Meta Manager, Schema Generator, Sitemap Engine, Redirect Manager - Breadcrumbs, Local SEO, Image Optimizer, International SEO (Hreflang) - Elementor + Gutenberg integrations - Cache Bridge (LiteSpeed, WP Rocket, W3TC) - WooCommerce SEO integration - Analysis module with Readability & E-E-A-T scoring - Content Decay Monitor, GEO & LLM Readiness modules - Topical Authority modules - Social Previews, IndexNow, AI Content Generator - MCP Bridge with 40+ SEO tools - Apple-inspired Admin UI

SEOWing

AI-first SEO for WordPress. One plugin instead of Yoast, RankMath and Imagify.

GOLDENWING Creative Studios e.U.
Czeikestrasse 4/21, 1100 Vienna, Austria

Product

  • Features
  • Pricing
  • FAQ
  • Changelog

Support

  • Documentation
  • Contact
  • Get started

Legal

  • Privacy Policy
  • Terms
  • Imprint
  • DPA
  • Sub-processors

© 2026 GoldenWing Creative Studios e.U. All rights reserved.

hello@goldenwing.at