Beskrivelse
DadsFam SEO is a complete, free SEO plugin for WordPress: on-page analysis, XML sitemaps, schema, OpenGraph, breadcrumbs and robots.txt, plus GEO (Generative Engine Optimization) tools that help AI answer engines such as ChatGPT, Google AI Overviews, Perplexity, Gemini and Claude find and cite your content. You can extend it with the optional DadsFam SEO Pro add-on plugin for AI tools, redirects and analytics — it plugs into the same dashboard.
Everything described below works on every site. Nothing is disabled, blurred out, time-limited or reduced.
Free Features
- On-Page SEO Analysis — 26-point weighted scoring engine covering keyword placement, density, content length, heading structure, internal/external links, image alt text, readability (Flesch-Kincaid, sentence length, passive voice, transition words) and more
- Category & Tag SEO — Full SEO panel on every category, tag, product category and custom taxonomy: title, description, focus keyword, canonical, noindex, live character counters and a Google preview
- hreflang — Automatic language tags for Polylang, WPML and TranslatePress, with x-default. Does nothing on single-language sites
- Site Health Tests — Five SEO checks added to WordPress’s own Tools Site Health, including detection of the “Discourage search engines” box that silently deindexes entire sites
- WP-CLI Commands —
wp dfseo doctor,audit,rescoreandsitemapfor bulk work and deploy scripts - SERP Preview — Real-time desktop and mobile search result preview with character counters
- Internal Link Suggestions — Finds related published content to link to, ranked by relevance to your focus keyword and title, and shows what you’ve already linked
- XML Sitemaps — Cached index sitemap with per-type sub-sitemaps, image sitemap, and search engine notification via IndexNow on publish
- Schema / Structured Data — JSON-LD for Article, WebPage, WebSite + SearchAction, Organisation, BreadcrumbList, and Speakable
- OpenGraph & Twitter Cards — Full social sharing meta tags with image support
- Canonical URLs — Auto-generated or custom per-post canonical
- Robots Directives — noindex, nofollow, noarchive, nosnippet per post
- Robots.txt Management — Live virtual robots.txt with custom rules support
- Breadcrumbs — Schema-enhanced breadcrumbs via
[dfseo_breadcrumbs]shortcode - Image SEO — Auto-inject focus keyword into alt text on upload
- Site Verification — Google, Bing, Yandex, Pinterest
- Instant Indexing — IndexNow submission (Bing, Yandex, DuckDuckGo, Seznam, Naver) with manual bulk submission and history
- SEO Score Column — Score column on posts, pages, and WooCommerce products
- Dashboard Widget — Quick SEO health overview on WP admin home
GEO — Generative Engine Optimization (Free)
Get discovered and cited by AI answer engines, the next frontier of search:
- llms.txt — Auto-generated AI content map served at
/llms.txt(the emerging llmstxt.org standard) - AI Crawler Controls — Allow or block 13 major AI bots (OpenAI GPTBot, ClaudeBot, Google-Extended, PerplexityBot, Applebot, Meta AI, CCBot, Bytespider and more) from robots.txt
- Speakable Schema — Marks content for voice assistants and AI read-aloud
- GEO Content Checks — Analysis flags question-style headings, lists/tables, and concise direct-answer openings that AI engines prefer to quote
Pro Features (DadsFam SEO Pro add-on)
Install the DadsFam SEO Pro add-on plugin alongside this one and activate your licence to unlock:
- AI Meta Generator — One-click SEO title and meta description generation using Claude AI
- AI Keyword Research — Relevant keyword suggestions with type, intent and difficulty
- AI Content Optimisation — Actionable content improvement recommendations
- AI Title Variants — Generate click-worthy title alternatives
- AI Content Outline — Full SEO-optimised content outline, insertable into the editor
- Real Keyword Data — Actual search queries, clicks, impressions, CTR and ranking position straight from the Google Search Console API
- Redirect Manager — 301, 302, 307, 410 redirects with hit tracking and regex support
- Auto-Redirect on URL Change — Automatically creates a 301 when a published post’s slug changes, with redirect-chain prevention
- Analytics Dashboard — Organic traffic trends, engine breakdown, and content decay detection over 7–90 day windows
- Bulk SEO Editor — Edit focus keyword, title, and description for hundreds of posts at once
- FAQ Schema — FAQ rich results with AI-assisted generation
- Local SEO — Full LocalBusiness schema with address, phone, geo-coordinates
- Data Import — One-click import from Yoast SEO, Rank Math, and All in One SEO
- WooCommerce — Product schema and integration
- News Sitemap — Google News-compatible sitemap
- Google Indexing API — Direct URL submission to Google
A word about PRO
Right, let me be straight with you, because I hate being sold to as much as you do.
Everything above is free and it stays free. The scoring engine, XML sitemaps, schema, OpenGraph, canonicals, robots directives, breadcrumbs, internal link suggestions, Instant Indexing and the whole GEO toolkit — none of those are premium features. Those are the things an SEO plugin should just do, and if I put them behind a paywall I would be taking the mickey.
There is a PRO add-on. It exists because I am a dad in Cape Town, and this is one of the things that puts food on the table at my house. That is the honest reason. Not “unlock your potential”, not “supercharge your workflow”. Just: if this plugin helped your work get found and you can spare it, PRO helps me keep building.
What PRO adds is the heavier lifting you reach for once the basics are in place — AI-written titles, descriptions and outlines, real keyword data from Google Search Console, a redirect manager that catches slug changes on its own, an analytics dashboard, bulk editing across hundreds of posts at once, and one-click import from Yoast, Rank Math or All in One SEO. That is time saved and depth added. It is not the plugin working properly, because the plugin already works properly.
So if the free one does everything you need, brilliant. Genuinely. Use it, and I hope it gets your work in front of the people looking for it. If you get to the point where the extra depth would save you real time, PRO is at plugins.dadsfam.co.za.
Either way, thanks for using something I built. — Zak, DadsFam
AI Powered by Claude
The DadsFam SEO Pro add-on can connect to the Anthropic Claude API for its AI features. Your API key is stored server-side and is never exposed to the browser.
External services
This plugin connects to third-party services. Nothing is sent anywhere until you switch the relevant feature on, and no personal data is transmitted by the free plugin.
IndexNow (instant indexing)
When “Instant Indexing” is enabled, the plugin tells participating search engines that a URL has been published or updated, so they can recrawl it sooner. It sends the public URL of the post, your site’s IndexNow key, and the public location of that key file. It sends no personal data and no post content.
This happens when you publish, update or delete a post with auto-submit enabled, and when you use the manual bulk-submit button. It is off until you generate an IndexNow key on the Indexing screen.
The requests go to:
- api.indexnow.org – the shared IndexNow endpoint, which distributes the notification to participating engines including Bing, Yandex, Seznam and Naver. Terms: https://www.indexnow.org/terms – Privacy: https://www.indexnow.org/faq
- www.bing.com/indexnow – Microsoft Bing’s own IndexNow endpoint, pinged directly as a fallback. Terms: https://www.microsoft.com/servicesagreement – Privacy: https://privacy.microsoft.com/privacystatement
Your own site
The Health Check screen requests pages on your own site and reads the HTML that comes back, so it can see what a search engine actually receives rather than trusting the settings. These requests go to your own domain only, and are made only while you are on that screen or running wp dfseo doctor.
The DadsFam SEO Pro add-on is a separate plugin and discloses its own services (Google Search Console, Google Indexing API and the Anthropic Claude API) in its own readme.
Installation
- Upload the
dadsfam-seofolder to/wp-content/plugins/ - Activate the plugin in Plugins Installed Plugins
- Navigate to DadsFam SEO Settings to configure
- Edit any post or page to see the SEO meta box below the editor
FAQ
-
What is GEO (Generative Engine Optimization)?
-
GEO is the practice of optimising your content to be found, understood, and cited by AI answer engines such as ChatGPT, Google AI Overviews, Perplexity, Gemini and Claude — as opposed to traditional SEO which targets the classic search results. As more people get answers from AI, GEO is becoming essential. DadsFam SEO includes an llms.txt generator, AI crawler controls, Speakable schema, and GEO-focused content checks.
-
Do I need a Google service account for keyword data?
-
To see real keyword data from Google Search Console (queries, clicks, impressions, position), yes — you add a Google service account (the same one used for the Google Indexing API) and grant it access in Search Console. The plugin walks you through it. IndexNow instant indexing for Bing and others works with no setup at all.
-
Will this conflict with another SEO plugin?
-
Run only one SEO plugin at a time. DadsFam SEO can import your existing data from Yoast, Rank Math, and All in One SEO so you can switch cleanly.
Anmeldelser
Der er ingen anmeldelser for denne widget.
Bidragsydere & udviklere
“DadsFam SEO” er open source-software. Følgende personer har bidraget til dette plugin.
BidragsydereOversæt “DadsFam SEO” til dit eget sprog.
Interesseret i udvikling?
Gennemse koden, tjek SVN repository, eller abonner på udviklerloggen via RSS.
Ændringslog
2.10.0
GEO and AEO:
- llms.txt now dates every article. Each entry carries its last-updated date, so an AI answer engine choosing between two similar pages can prefer the fresher one. The line stays valid llmstxt.org markdown.
- Article schema leads with the focus keyword. The
keywordsproperty now puts the phrase the page was written to answer first, ahead of the tags. Previously only tags were listed. - Fixed: the get-settings ability reported schema, Open Graph, breadcrumbs, speakable and search-engine pings as empty when they had never been saved — even though the plugin treats an unsaved toggle as ON. Any assistant reading that output would have concluded schema was switched off when it was live. It now reports what the site actually does.
- The “A word about PRO” note and the “nothing is disabled, blurred out, time-limited or reduced” line from 2.9.1 and 2.9.2 are included.
2.9.2
- Readme only: added the plain-English “A word about PRO” note the other DadsFam plugins carry — what stays free, why the optional add-on exists, and what it actually adds. Nothing was moved behind a paywall and no code changed.
2.9.1
- Readme only: added the line the other DadsFam plugins already carry — everything described works on every site, and nothing is disabled, blurred out, time-limited or reduced. No change to the plugin itself.
2.9.0
Security and compliance, from the WordPress.org plugin review:
- JSON-LD schema is now hardened against markup injection. The structured-data block is encoded with
JSON_HEX_TAG, so a post title or description containing</script>can no longer close the block early and have the rest of the page parsed as HTML. - The two analysis REST endpoints now check the right capability. They report on one specific post, but only checked the broad
edit_posts. They now requireedit_postfor the post being analysed, so a contributor or another author can no longer read back the title, description and content findings of a private or someone else’s draft. - Sitemap cache keys can no longer collide. The requested sitemap type was sanitised by stripping unexpected characters, which meant two different requests could map to one cache entry. Unknown types are now rejected with a 404, and the key is hashed.
- No more inline scripts or styles. Every
<script>and<style>block that was printed into a page — the health check, Instant Indexing, setup wizard, changelog, AI/GEO tab, category and tag fields, the product list column and the welcome notice — is now a properly registered and enqueued file, with data passed throughwp_localize_script(). - The welcome notice no longer follows you around. It appeared on every admin screen until dismissed; it now shows only on the Dashboard and the Plugins screen, and still only until the plugin is configured or you dismiss it.
- Removed the
Tested up toheader from the main plugin file. It belongs only in readme.txt, where having it in both places can make the plugin page advertise a version you did not intend. - Local file reads now go through
WP_Filesysteminstead offile_get_contents()with a silenced error, and the sitemap stylesheet is streamed withreadfile(). - Description tidied: dropped an unsupported “best-in-class” claim and the comparison to other plugins, and the add-on is now called DadsFam SEO Pro everywhere instead of switching between “Pro” and “Premium”.
2.8.1
Fixed:
- Instant Indexing log times were shown in the future. Entries were stored with
current_time( 'timestamp' ), which returns a UTC timestamp already shifted by your site’s timezone, and the screen then applied the offset a second time. On a UTC+2 site every row read two hours ahead of when it actually happened. New entries store true UTC, and the entries already on your site are corrected once on update — only the ones that are genuinely in the future are touched, so nothing correct gets moved.
2.8.0
Fixed:
- The analyser could not see headings inside a container. Two GEO checks — “chunkable sections” and “question-and-answer pairs” — only looked at the direct children of the content, so any page whose content sat inside a wrapper div, a Gutenberg Group or Columns block, or a page-builder container was told it had “no headings” and “no question-and-answer pairs” no matter how well it was structured. Pro’s automatic FAQ schema, which uses the same walker, never fired on those pages either. The walker now reads the document in order at any depth.
- Drafts always failed the URL check. An unpublished post’s permalink is still
?p=123, so “focus keyword in URL” failed on every draft. The check now also judges the slug WordPress will use — the saved slug, or the title’s slug before one exists.
Faster:
- Stopped loading an admin-only log on every page view. The Instant Indexing log reaches roughly 19 KB at its 100-entry cap, and it was in WordPress’s autoload set — meaning it was read from the database and unserialised on every single request on the site, including every front-end page view, purely so it could sit unused in memory. It is only ever displayed on its own settings screen. It is now excluded from autoload, and a one-time migration moves it on existing sites. On a measured install this cut the plugin’s autoloaded footprint from 21.1 KB to about 2 KB.
New:
- Find a setting. A search box above the Settings tabs filters the rows on the tab you are on, and when nothing matches it names the tabs whose subject does — “Try: Schema · Advanced” — so you are never left hunting.
- Live character counters under the homepage title and description, coloured for too short, just right, and “Google will cut this”.
- A save bar that tells you. The Save Settings bar now stays in view and lights up the moment something on the tab changes, and the browser warns before you leave with unsaved changes.
2.7.1
Fixed:
- Removed an invalid “Network” header from the plugin file. WordPress only accepts that header when it is set to true, and it should be left out otherwise. It had no effect on how the plugin ran, but it is not valid and WordPress.org’s automated scan rejects it.
- Shipped a proper translation template. The
/languagesfolder the plugin points at was empty, and empty folders do not reliably survive being unzipped — which would leave the plugin pointing at a folder that is not there. It now contains a real POT file covering all 761 translatable strings, so translators have something to work from.
2.7.0
Six new AI abilities, a fix to how content is measured, and WordPress.org submission hardening.
New:
- Test a draft before you save it. A new
analyse-draftability scores a hypothetical title, meta description, focus keyword or rewritten body and returns both scores plus every failing check, without writing anything. Get it right first, then save once. - Compare focus keywords.
compare-keywordsscores a page against up to ten candidate keywords and ranks them best-first, showing which keyword checks each one passes. Choosing a focus keyword was guesswork before this. - Site-wide GEO report.
get-geo-reportsamples your published content and tells you which GEO checks the whole site keeps failing, plus the average GEO score and the weakest pages. Answers “what do I fix everywhere”, not “how is this page doing”. - Internal link suggestions over the API.
suggest-internal-linksexposes the editor sidebar’s link engine, so an assistant can find related content and see what you have already linked. - Bulk SEO updates.
bulk-update-seoapplies titles, descriptions, keywords, schema types and robots flags across up to 50 posts in one call, re-scoring each. Rows apply independently, so one bad post id fails that row, not the batch. - Instant indexing status.
get-indexing-statusreports whether IndexNow is configured, whether it fires automatically, and what it recently submitted. - That takes the free plugin from 9 AI abilities to 15.
Fixed:
- Content measurement no longer welds words together. Stripping HTML replaced each tag with nothing, so
<h2>Key takeaways</h2><p>Costs...collapsed totakeawaysCosts— one nonsense token where there should be two words. On markup written without line breaks between blocks (page builders, imported content, anything minified) this undercounted the word total by roughly a quarter, skewed sentence and paragraph splitting, and made any check looking for a word at a block boundary silently miss. Tags are now replaced with a space, so word counts, readability and keyword matching are correct on every kind of content. - Five code-quality suppressions were silently doing nothing. They used an em dash where PHP_CodeSniffer requires a double hyphen before the reason, so the directive never parsed and the warnings stayed live. Now written correctly.
- An admin tab link was output without escaping. A URL built for the header tab strip skipped
esc_url(). Not exploitable in the shipped code, but it should never have been unescaped. - Every
$_GET,$_POSTand$_SERVERread is now unslashed before it is sanitised. WordPress adds slashes to superglobals, so sanitising without unslashing first can leave a stray backslash in stored values. Affected the setup wizard, the editor meta box, the indexing screen and the admin tab strip. parse_url()replaced withwp_parse_url()in three places. The PHP function returns different things on different PHP versions for edge-case URLs; the WordPress wrapper is consistent.- Translations no longer load early.
load_plugin_textdomain()has been unnecessary since WordPress 4.6 and on modern WordPress it triggers a “called incorrectly” notice. Removed — the same strings still translate, WordPress just loads them when they are first needed. - A sitemap suppression was cancelling itself out. An inline code-checker directive silently replaced the one on the line above it, leaving a warning live.
Improved:
- Documented every third-party service the plugin contacts, what it sends and when, in a new “External services” section — including the IndexNow endpoints and the fact that Health Check only ever requests your own site.
- Verified against WordPress.org’s own Plugin Check review rulesets with zero errors and zero warnings, and against PHP 7.4 through 8.4 with zero compatibility issues.
- Compatibility: tested up to WordPress 7.1.
2.6.0
A separate GEO score, five new AI-citability checks, and AI assistant support.
* New: a GEO score, scored separately from your SEO score. Classic SEO and getting quoted by AI answer engines are not the same job, and one number cannot tell you how you are doing at both. Every page now carries its own 0–100 GEO score alongside its SEO score, so you can see at a glance that a page is strong for Google and weak for ChatGPT — and fix exactly that. Stored per page, so you can sort your whole site by it.
* New: five additional GEO checks, each based on what AI answer engines actually quote:
* Concrete figures — pages carrying real numbers, percentages, prices and dates get cited far more often than vague prose.
* Question-and-answer pairs — a question heading followed by a short, self-contained answer is the single most quotable structure there is.
* Summary block — a “Key takeaways” or “In short” section gives an answer engine a ready-made extract instead of making it guess.
* Chunkable sections — AI systems split pages by heading, so a 900-word run with no subheading gets cut mid-thought and loses the context that made it worth quoting. This check finds those.
* Entity definition — if you never plainly say what your subject is, an answer engine may confidently answer about something else entirely.
* New: AI assistant support. If you connect an AI assistant to your site through an MCP plugin such as WPVibe, it can now do real SEO work: analyse a page and get back both scores plus every failing check in fix-this-first order, rewrite titles and meta descriptions (and see the new score immediately), find your weakest content by SEO or GEO score, run the site audit, re-score content in bulk, and manage your llms.txt and AI-crawler settings. Uses the WordPress Abilities API (WordPress 6.9 and newer).
* Security: every AI action requires the same permission the plugin’s own screens use.
* Fixed: the readme listed 8 tags. WordPress.org only indexes 5 and ignored the rest, so the list is now the 5 that matter.
* Compatibility: tested up to WordPress 7.0.
* On WordPress versions without the Abilities API, nothing changes and the plugin works exactly as before.
2.5.0
Category and tag SEO — the missing editor.
* The output engine has read _dfseo_title, _dfseo_meta_desc and _dfseo_noindex from term meta since v1.0 — in the title builder, the description resolver, the robots directives and the sitemap — but nothing ever wrote them. There was no editor anywhere on the site. Every category, tag and product category was stuck with whatever the automatic fallbacks produced.
* Every public taxonomy now has a full SEO panel: SEO title, meta description, focus keyword, canonical URL, noindex, live character counters and a Google preview.
* The term keys are now registered with WordPress, so they work over the REST API and WP-CLI too. Previously a meta payload sent to /wp/v2/categories/ was silently discarded while the request still returned 200.
* Term list tables gained an SEO column showing at a glance which archives are Set, Partial, Auto or Hidden.
* Terms can now carry their own canonical URL and their own social share image, with WooCommerce category thumbnails used as a sensible fallback.
hreflang for multilingual sites.
* Emits rel="alternate" hreflang tags plus x-default, detecting Polylang, WPML and TranslatePress automatically. Without these, a translated site serves several near-identical URLs per page and search engines have to guess which one to show to whom — frequently guessing wrong, or treating the set as duplicate content.
* Does nothing at all on single-language sites, so it is safe to leave switched on.
* New dfseo_hreflang_alternates filter for regional domains, headless setups, or any multilingual plugin not detected automatically.
WordPress Site Health integration.
* Adds five SEO tests to Tools Site Health, plus a DadsFam SEO panel on the Info tab that is copyable straight into a support request.
* The headline one: “Discourage search engines” detection. That single checkbox in Settings Reading adds a site-wide noindex, is invisible from Site Health unless something puts it there, and is routinely left on by accident after a site is built on staging. Sites sit deindexed for months behind it.
* Also checks: plain permalinks (which break /sitemap.xml and /llms.txt outright), a physical robots.txt overriding the plugin, missing homepage title/description, and other SEO plugins running at the same time.
WP-CLI command suite.
* wp dfseo doctor — full SEO health check over SSH, no browser needed.
* wp dfseo audit --post_type=product --missing=description --format=csv — export exactly what still needs writing.
* wp dfseo rescore --post_type=product — recalculate scores in bulk after an import, a migration, or a change to your title templates. There was no way to refresh stored scores from the dashboard; browser-based bulk work simply times out on a large catalogue.
* wp dfseo sitemap flush|list.
* Costs a normal page load nothing — the file returns immediately unless WP-CLI is actually running.
Other.
* The attachment-page redirect and hreflang now have visible toggles on the Advanced tab.
* Uninstall cleans up term meta and the new transients.
2.4.0
Structured data rebuilt as one connected graph.
* Every JSON-LD node now ships in a single @graph block instead of five separate scripts. Nodes reference each other by @id, so search engines read one entity model for the page rather than a pile of disconnected fragments.
* Fixed: the WebSite node had no @id at all, and was only output on the homepage — while every inner page pointed isPartOf at it. That reference resolved to nothing on every URL except one. WebSite and Organization are now emitted on every page.
* Archives, categories, tags, author pages and search results finally get a page-level node (CollectionPage / ProfilePage / SearchResultsPage). Previously only single posts and pages had one.
* Authors are now a proper Person node with a stable @id reused across the whole site, instead of an anonymous block repeated inside every article — the groundwork for author/E-E-A-T signals.
* Articles gained articleSection, keywords, wordCount, commentCount, thumbnailUrl and isAccessibleForFree.
* The page’s main image is now a referenced ImageObject with real dimensions.
* New dfseo_schema_graph filter for adding, removing or rewriting any node.
Meta descriptions no longer leak page-builder code.
* Auto-generated descriptions now strip shortcodes and block markup first. On Elementor, WPBakery, Divi and Fusion sites, descriptions could previously read [vc_row][vc_column width=1/2] — and that shipped straight into the meta tag and every social preview.
* Author archives fall back to the author bio; post type archives fall back to their registered description. Both used to ship with no description at all.
* Newlines are collapsed, so a description written across several lines no longer breaks the <head> open.
Title templates: 7 variables to 27.
* Added %excerpt%, %primary_category%, %tag%, %author%, %post_type%, %parent_title%, %id%, %date%, %modified%, %month%, %day%, %currentdate%, %pagenumber%, %pagetotal%, %term_title%, %term_description%, %searchphrase%, and WooCommerce %price%, %sku% and %currency%.
* A separator left stranded by an empty variable is now trimmed away, so templates degrade cleanly instead of rendering “– Site Name”.
* Paginated archives append “Page 2” automatically, so page 2 is no longer a byte-for-byte duplicate title of page 1.
Social tags.
* WooCommerce products now output product:price:amount, price:currency, availability and retailer_item_id. The plugin declared og:type=product and then said nothing about the product.
* A summary_large_image card with no image now correctly falls back to summary — the large card rendered as a bare text link on X.
* Content images are made absolute and mapped back to their attachment, recovering real width/height/alt. Relative sources were being handed to Facebook as-is and rejected.
* Added og:image:secure_url, profile:first_name/last_name on author pages, and a site-logo fallback so pages with no imagery still get a branded card.
* article:tag now appears in document order instead of above og:type.
Breadcrumbs.
* Custom post types now show their archive and taxonomy trail. WooCommerce products showed “Home › Product Name”; they now show “Shop › Category › Product”, picking the deepest category when a product sits in several.
* A separate posts page is included above blog posts.
* Added the dfseo_breadcrumbs() template function the docs have referenced since v1.0 but which was never actually defined.
* Fixed: a term whose taxonomy had been unregistered produced an href="Array" in the trail.
* New dfseo_breadcrumb_items and dfseo_breadcrumb_taxonomy filters.
Sitemaps.
* Taxonomy sitemaps now carry real lastmod dates taken from the newest post in each term. Previously every taxonomy file was stamped “now” on every single request, which told crawlers the whole taxonomy changed constantly.
* Empty taxonomies are no longer advertised in the index — that was generating “sitemap is empty” warnings in Search Console for nothing.
* Image entries are deduplicated, made absolute, and restricted to images this site actually hosts. Hotlinked and lazy-load placeholder images were being listed as ours.
* Password-protected posts are excluded.
* Sitemaps now send Cache-Control headers so CDNs can hold them.
* Fixed: robots.txt contained the Sitemap: line twice, and lost it entirely the moment you saved a custom robots.txt.
Image SEO.
* Alt text is now resolved per image from its own alt, title, caption or a cleaned-up filename. Every image missing an alt used to receive the same focus keyword — textbook keyword stuffing, and it told screen-reader users that eight different pictures were the same thing. The keyword is now used once, as a last resort.
* Filename-derived alt text strips -1024x768, -scaled, edit stamps and duplicate counters, and refuses to store meaningless camera serials like IMG_4821 as a description.
* Alt injection no longer runs during feeds or REST requests.
Other.
* Title, description and canonical are each resolved once per request instead of up to seven times.
* The Open Graph, Twitter Card and Structured Data on/off switches were saved but never actually read by anything. They now work, and have visible toggles on the Social and Schema tabs.
* Password-protected pages, noindexed terms, and attachment pages (when redirection is off) are now correctly set to noindex.
* The SEO panel’s schema type now runs through the same allowlist as the REST API — the admin form was the one path that skipped it.
* New filters: dfseo_title, dfseo_description, dfseo_canonical, dfseo_robots_directives, dfseo_template_variables, dfseo_social_meta_tags, dfseo_og_type, dfseo_article_post_types, dfseo_sitemap_posts.
2.3.3
- Fixed: the “Get Premium” / upgrade buttons pointed at pages that no longer exist. The purchase buttons now open the correct product page (product/dadsfam-wordpress-pro-license-keys), and the general upgrade/”Go Pro” links now open the plugins site at plugins.dadsfam.co.za. The old store URL (/plugins/dadsfam-seo) returned a 404.
- Fixed: the Documentation and Support links on the Plugins screen also pointed at dead pages (/docs/dadsfam-seo and /support both 404’d). Documentation now opens plugins.dadsfam.co.za and Support now opens an email to support@dadsfam.co.za.
2.3.2
- Improved: deleting the plugin now removes every option, transient and log it ever created — including the newer attachment-redirect and llms-full.txt settings, the IndexNow key and submission log, and setup-wizard bookkeeping. A public plugin should leave a site exactly as it found it.
2.3.1
- Fixed: the Health Check button did nothing when clicked. The page’s script read its settings before WordPress had printed them (they were output in the page footer, after the script had already run), so the first click failed silently. The settings are now printed directly above the script, the strings fall back to English if anything is ever missing, and if the essentials genuinely cannot be found the button says so plainly instead of doing nothing.
2.3.0
- New: Health Check — a new page under DadsFam SEO that checks your site and fixes what it safely can. It does not just read your settings: it loads your real pages the way Google does and reads the HTML that comes back, so it catches what a settings screen cannot — a caching plugin serving an old copy, a theme conflict, or a setting that looks saved but never reaches your pages. Every problem is explained in plain English with the reason it matters. Anything deterministic gets a one-click fix, or fix them all at once.
- New: Health Check deliberately refuses to guess. Your focus keywords, your homepage wording and your business address are never auto-filled — a wrong address is worse than a blank one, because Google cross-checks it against your Google Business Profile. Those are flagged “Needs you” with a link to the right screen instead.
- New:
dfseo_health_checksfilter, so add-ons and site-specific code can register their own checks and fixes. - New: thin attachment pages are now redirected. WordPress creates a near-empty page for every file you upload; they waste crawl budget and can rank instead of the real content the image belongs to. They now 301 to their parent post (or to the file itself when orphaned). On by default; switch off under Settings for the rare gallery site that genuinely uses them.
- New: llms-full.txt — the companion to llms.txt. Where llms.txt is a map of your content, llms-full.txt is the content itself, converted to clean markdown with headings, lists and link URLs preserved, capped in size, cached, and honouring noindex. This is what an AI answer engine ingests to actually quote and cite you rather than merely know you exist. Served at /llms-full.txt and advertised in robots.txt alongside the map.
- New: two more Health Checks — attachment page handling (with a one-click fix) and a live check that your llms.txt is genuinely being served to AI engines, not just switched on.
- Fixed: a meta description you write yourself is now output exactly as you wrote it. Anything over 160 characters was being silently cut short and given an ellipsis, even when you had deliberately written it that way. Auto-generated descriptions are still trimmed, which is all that was ever intended.
- Fixed: choosing FAQPage as a page’s schema type no longer puts two FAQPage entries on the page when that page also has FAQ items. The one carrying your actual questions is kept.
- Fixed: several changelog badges rendered unstyled because the markup used class names the stylesheet did not define.
- Fixed: publishing a WooCommerce product — or anything that is not a standard blog post — now notifies search engines through IndexNow. The ping was hooked to an event WordPress only fires for ordinary posts, so products and custom post types were published in silence. Re-saving something already published does not re-ping.
- Fixed: URLs are no longer submitted to IndexNow twice on publish. Both the sitemap module and the Indexing module were notifying search engines for the same event; the Indexing module now owns submission, and the sitemap ping only acts as a fallback when auto-submit is switched off.
- Fixed: relative links now count as internal links in the content analysis. A link written as /shop/ instead of the full address was counted as neither internal nor external, so pages using relative links failed the internal-links check despite doing everything right.
- Fixed: the setup wizard validates the Site Type it saves instead of storing free text into the option that types your site’s schema entity and gates the entire Local SEO output.
- Fixed: the sitemap index no longer advertises pages that would render empty. The page count included posts marked noindex even though the sitemap itself correctly leaves them out, so a site with enough noindexed content listed trailing sitemap files with nothing in them — which Search Console reports as errors.
- Fixed: the Home Title and Home Description settings had no effect on any site using a static homepage. A static front page is also a single page, so it was matched by the singular branch first and returned before the home branch was ever reached — leaving your homepage, the most valuable title on the site, rendering as “Home – Site Name” with a description auto-scraped from its own content. Both settings now apply, and a SEO title set on the homepage itself takes precedence over them.
- Fixed: SEO meta is now registered with WordPress, so the REST API can read and write it. Previously a
metapayload sent to /wp/v2// was silently discarded — the request still returned 200 OK while nothing was saved, which broke any automation and gave no indication why. Writes made outside the SEO panel (REST, WP-CLI, other plugins) now also run through the same sanitisers the panel uses. The score, grade and word count are exposed read-only; they are computed from your content, not set by the caller. - Fixed: Schema Type is now validated against an allowlist instead of accepting free text, and page types and article types are kept apart. Choosing “Article”, “Blog Post” or “News Article” retyped the page node itself, which placed a second, duplicate Article on the page alongside the real one already output for posts. Those choices now steer the article node, which is what the setting always meant. The page node stays a WebPage subtype, and unrecognised values fall back to the default rather than reaching @type.
- Fixed: LocalBusiness and Organization are no longer emitted as two competing nodes. With a local site type selected you got one node carrying the logo and social profiles but no address, and a second carrying the address but no @id — two entities for one business, neither complete. Local SEO data is now merged into the site’s single Organization node.
- Fixed: og:image:type no longer claims every image is a JPEG. The mime type is now read from the image itself, and the tag is omitted rather than guessed when it genuinely cannot be determined. PNG and WebP images — including any image taken from post content or used as the default social image — were previously all announced to Facebook, LinkedIn and X as image/jpeg.
- Improved: the Local SEO tab now warns you when its fields are not being output, and links straight to the setting that switches them on. Previously the whole panel accepted input and silently produced nothing whenever Site Type was left as “Organisation”, with no clue that a dropdown on another tab was the reason.
- New:
dfseo_organization_schemafilter, for adding to or overriding the site’s Organization / LocalBusiness node.
2.2.0
- Fixed: post type archives backed by a real page — most importantly the WooCommerce shop page — now use that page’s SEO title and meta description. WooCommerce renders /shop/ as a product archive rather than a page, so
is_singular()is false there and the shop page’s own SEO meta was never read: the title fell back to the archive label (“Shop – Site Name”) and no meta description was output at all, no matter what you saved on the page. The shop page’s title and description now flow through to the<title>tag, meta description, og:title, og:description, Twitter card and schema. - New:
dfseo_archive_page_idfilter, for pointing any other post type archive (portfolios, listings, directories) at a page whose SEO meta should drive that archive’s title and description.
2.1.0
- New: DadsFam SEO is now split into a fully free core plugin and a separate DadsFam SEO Pro add-on. Everything that was free stays free — full on-page analysis, sitemaps, schema, OpenGraph, breadcrumbs, robots.txt, GEO (llms.txt, AI-crawler controls, Speakable), and IndexNow instant indexing. Pro features (AI tools, Google Indexing API, redirects, analytics, Search Console keywords, bulk editor, local SEO, FAQ/HowTo/Video/Product/Event schema, Google News sitemap, WooCommerce schema, data import) now live in the Pro add-on, which plugs into the same dashboard — install both and it all appears in one place.
- New: public extension API for …
