Skip to main content
M Mika Leonard

WordPress plugin · version 0.10.1

SEO Health Check

A plugin that checks every page of a WordPress site for the SEO mistakes that are easy to miss: missing meta descriptions, images without alt text, wrong headings, thin content and broken links. Everything lands in one overview in the dashboard, with a score per page and a direct link to the page you need to fix. Alt texts, titles and descriptions can even be fixed right from the overview, and on a schedule it scans by itself and emails you the report.

129 KB · WordPress 6.0+ (tested up to 7.1) · PHP 7.4+ · Works with Yoast SEO and Rank Math · In English and Dutch · GPL-2.0

603

pages scanned in testing, without a single time-out

9

checks on every page

27

launch checks for the whole site

0

warnings from the WordPress Coding Standards

What it checks

Per page, automatically

Titles and meta descriptions are read straight from Yoast SEO or Rank Math, including their templates. Without an SEO plugin, the WordPress defaults are used.

  • 01

    Title

    Missing, too long for Google, or used by more than one page.

  • 02

    Meta description

    Not filled in, too long or duplicated. Without a description, Google picks a snippet of text itself.

  • 03

    Alt texts

    Images without a description, including the featured image. Bad for Google and for blind visitors.

  • 04

    H1 heading

    No main heading, or more than one. Takes themes into account that already show the title as an H1.

  • 05

    Thin content

    Pages with fewer words than the minimum you set yourself.

  • 06

    Broken internal links

    Links to pages that do not exist (anymore), are in the trash or are still a draft.

  • 07

    Heading order

    Headings that skip a level, for example an H2 followed straight by an H4. Google and screen readers use that order to understand the page.

  • 08

    Heavy images

    Images above the maximum you set yourself, because they make a page slow. This check is off until you fill in a maximum.

  • 09

    Pages without links

    Pages that no other page and no menu links to. Google finds them hard to reach, and so do visitors.

Track your progress

See what every scan achieves

A score per page, and for every issue whether it is new, unchanged or fixed. So you can see what your work actually did: the plugin keeps a history of your scans, and the main numbers are on your WordPress dashboard too. Existing results keep working: the database is upgraded automatically when you update.

  • 01

    A score per page

    Every page gets a score from 0 to 100, on its own screen with the worst pages first. 80 and up is good, 50 to 79 needs work, and below 50 needs attention. An extra column shows how much the score changed since the previous full scan.

  • 02

    New, Unchanged or Fixed

    Every issue says what the last scan did with it: found for the first time, still there, or fixed. Solved issues do not quietly disappear, they stay visible until the next scan. The status filter shows just the ones you want to see.

  • 03

    A history of your scans

    A separate Scans screen keeps the last twenty scans: when each one ran and how long it took, the average score, the number of issues, and how many appeared or were solved. Per kind of problem you can see whether things are really improving, or only the titles.

  • 04

    Fix it in the overview

    Type alt texts, SEO titles and meta descriptions straight into the list, with a character counter. The page is rescanned the moment you save, so the row updates itself.

  • 05

    On your dashboard

    A widget on the WordPress home screen shows the average score, the number of issues and what the last scan added or solved, with a link to each screen. No need to go looking for the results.

Automatic scan

It scans by itself, you get the report

Pick the days and the time, fill in one or more email addresses, and the plugin scans the site on its own from then on. You see how the site is doing every week, without having to think about it.

  • 01

    You choose the moment

    One or more days a week and a time, in the time zone of the site. Even when the clocks go back, it scans at the right moment.

  • 02

    The report in your inbox

    With the score, the totals, what appeared and what was solved, the most common issues and the last few scans. The full list is attached as a CSV file.

  • 03

    Only once the scan is done

    The email goes out when the scan has really finished, so with the new numbers and not last week's. A scan you start yourself does not email anyone.

  • 04

    Reports kept, safely

    A copy of each report stays on the site, shielded from visitors and downloadable by administrators only. Send a test report shows right away whether sending works, and if not, why.

  • Automatic scan

    Default: off

    Switch it on under SEO Health → Automatic scan and it scans the site at the chosen moments, then sends the report.

  • Days and time

    Default: Friday at 09:00

    Pick as many days as you like. The time is in the time zone of your WordPress site.

  • Send the report to

    Default: empty

    One or more email addresses, separated by commas. Without an address it still scans, but no report is sent.

  • Keep reports

    Default: 12

    How many reports stay on the site so you can look back at them. Older ones are deleted. Use 0 to keep none; the report is then only emailed.

Installation

Done in three minutes

  1. 01

    Download the zip

    With the button at the top of this page. Do not unzip it.

  2. 02

    Upload it in WordPress

    Go to Plugins, Add New Plugin and click Upload Plugin. Choose the zip, then click Install Now and Activate.

  3. 03

    Start the scan

    Open SEO Health in the menu and click Start full scan. You can leave the page, the scan keeps running in the background.

    SEO Health → Issues → Start full scan

  4. 04

    Updates come by themselves

    When a new version is out, WordPress says so on the Plugins screen, just like for plugins from the official directory. Updating is one click from there.

How it works

Built for large sites

  1. 01

    Scanning in small batches

    Twenty pages at a time in the background, through WP-Cron or Action Scheduler. The dashboard stays fast and there are no time-outs.

  2. 02

    Stored in its own tables

    One row per issue, indexed by page and type. Filtering and sorting stay fast, even with thousands of results.

  3. 03

    An overview in the dashboard

    Sort and filter by issue type, post type, severity and status, with a direct link to the edit screen.

  4. 04

    Export

    The filtered list as a CSV file, including the status of every issue, ready to open in Excel or send to a client.

Launch checks

The go-live checklist, automated

A separate page checks the settings that come back with every launch, split into before, at and after go-live. Manual work such as testing forms or emailing the client stays manual, the plugin does the rest.

  • ✓Search engines may index the site
  • ✓HTTPS is set up
  • ✓WWW and HTTPS redirects
  • ✓XML sitemap is reachable
  • ✓A real 404 status
  • ✓Favicon present
  • ✓No "Home" in the homepage title
  • ✓Featured image on the homepage
  • ✓A clean URL structure
  • ✓No links left to the development site
  • ✓WordPress, plugins and themes up to date
  • ✓Standard plugins installed
  • ✓No inactive plugins
  • ✓Cookie consent active
  • ✓Google Analytics or Tag Manager present
  • ✓Credit in the footer
  • ✓Menus only link to published pages
  • ✓Search Console verification on the homepage
  • ✓SPF, DMARC and DKIM for the domain's mail
  • ✓No default "admin" login left
  • ✓Mail can really leave the site
  • ✓Forms mail to the client
  • ✓Thank you pages for forms
  • ✓Spam protection on forms
  • ✓Custom login screen
  • ✓Development site redirects to the live site
  • ✓The client has an account of their own

Settings

Sensible defaults, all adjustable

The defaults work for most sites. If you want something different, change it under SEO Health → Settings. The bottom of that screen also shows which version is running, which SEO plugin the titles come from and whether scans run through Action Scheduler or WP-Cron.

  • Post types

    Default: posts and pages

    Which kinds of content are scanned. Custom post types, such as projects or products, can be switched on too.

  • Content source

    Default: automatic

    On automatic it scans the normal post content, and the page as visitors see it when that content is empty, as with page builders. You can also always use the post content (fastest) or always the rendered page (most accurate).

  • Theme H1

    Default: on

    For themes that show the post title as an H1 themselves. Switch it off if your theme does not.

  • Minimum word count

    Default: 300

    Pages with fewer words are reported as thin content. Set it to 0 to turn this check off.

  • Maximum title and description length

    Default: 60 and 160 characters

    Anything longer gets cut off by Google in the search results.

  • Maximum image size

    Default: off

    In KB. Images in your uploads folder above this size are reported; 300 is a sensible start. It starts out off, because on a site with many photos it can report a lot at once.

  • Pages without links

    Default: on

    Reports pages that nothing links to. It counts links in the content of other pages and in your menus, not in a sidebar, footer or widget.

  • Batch size

    Default: 20

    The number of pages per background step. Lowering it helps on slow hosting.

  • Rescan on save

    Default: on

    When you save a page, it is rescanned in the background right away. The overview stays up to date without a full scan.

  • Footer credit text

    Default: empty

    Text that must appear on the homepage, for example "Website by Agency". Leave it empty and the launch check skips it.

  • Development domains

    Default: empty

    Your test or staging domains, separated by commas. After launch it checks that the content no longer links to them.

  • DKIM selector

    Default: empty

    The selector your mail server signs with, for example "default" or "google". Your mail provider knows it. Fill it in and the mail check covers DKIM too.

  • Measurement code

    Default: empty

    The Google Analytics or Tag Manager code the site should use, for example G-ABC123DEF4. Fill in the one from the old site and it checks that exactly that code was carried over, not just any code.

  • Your own email domains

    Default: empty

    Your agency's domain, for example "youragency.com". It then spots forms that still mail to you instead of the client, and whether the client has an administrator account of their own.

Safe and tidy

The way a plugin should be

  • Administrators only

    Every action checks the user's capabilities and a nonce. Fixing from the overview also checks that you are allowed to edit that one page. Nobody from outside can start a scan, export or change.

  • Clean input, safe output

    All input is sanitized and all output is escaped. Database queries go through prepared statements.

  • Cleans up after itself

    Deactivating stops all background work. Delete the plugin and its tables, settings and cached data go with it.

  • WordPress standard

    Checked with PHPCS and the WordPress Coding Standards, and translatable. A Dutch translation is included.

For developers

Extend it with hooks

Add your own checks, calculate the score differently or decide who sees the results: there are filters and an action for that. The code is open on GitHub.

  • seo_health_check_capability

    The capability needed to use the plugin. Defaults to manage_options, so administrators only.

  • seo_health_check_issue_types

    Register an issue type of your own.

  • seo_health_check_post_issues

    Add or remove issues for a page. Together with the previous hook, this is how you build a custom check.

  • seo_health_check_post_html

    Change the HTML that is scanned.

  • seo_health_check_seo_meta

    Change the resolved title and description, for example to support another SEO plugin.

  • seo_health_check_page_score

    Calculate a page's score differently.

  • seo_health_check_inline_fields

    Choose which issues can be fixed straight from the overview.

  • seo_health_check_required_plugins

    The plugins the launch check expects on a delivered site.

  • seo_health_check_linked_post_ids

    Name pages that should count as linked, for example posts that are only listed on an archive page.

  • seo_health_check_scan_finished

    An action that fires when a full scan is done, handy for a notification or report.

  • seo_health_check_forms

    Add other form plugins to the form checks. Contact Form 7, WPForms and Gravity Forms are read already.

  • seo_health_check_check_for_updates

    Return false and the site never asks GitHub about new versions.

  • seo_health_check_docs_url

    Point the link to the manual somewhere else.

Fair is fair

What it does not do

  • —It only checks internal links. External links to other websites are out of scope.
  • —With page builders such as Oxygen and Elementor it scans the page the way a visitor sees it. The site then has to be able to reach itself, and that is slower than reading the normal content.
  • —It does not fix everything for you. Alt texts, SEO titles and meta descriptions can be edited in the overview, but headings, thin content and broken links live inside the content itself. You fix those in the edit screen.
  • —On a site without visitors, WP-Cron does not run. Keep the overview page open in that case, it pushes the scan forward itself.

Frequently asked questions

Good to know

  • Do I need Yoast SEO or Rank Math?

    No. It works without an SEO plugin too, but then it reports a missing meta description on every page, because WordPress does not add one by itself.

  • How long does a scan take?

    Usually a few minutes for 500 pages. On slow hosting you can lower the batch size under Settings.

  • Does the plugin change my content?

    Scanning never changes anything: it only reads and stores its findings in three tables of its own. Only when you fix something yourself in the overview does it write that one field: the SEO title or description in Yoast or Rank Math, or the alt text of that one image. The rest of the page is left untouched.

  • Why does it report "multiple H1s" when I only have one?

    Most themes already show the page title as an H1, so an H1 in your content is the second one. If your theme does not do that, switch off the Theme H1 setting.

  • How is the score calculated?

    A page starts at 100. Every kind of issue costs 20 points for an error and 10 for a warning. When the same issue appears more often, each repeat costs 2 points extra, up to 10. Ten images without alt text therefore hurt, but less than ten different problems.

  • What do New, Unchanged and Fixed mean?

    They tell you what the last scan did with an issue. New: that scan found it for the first time. Unchanged: it was already there. Fixed: the scan no longer found it. The plugin remembers when it first saw each issue, so something that has been there for months does not count as new again.

  • Which issues can I fix straight from the overview?

    Missing alt texts, SEO titles and meta descriptions, because each is stored in a field of its own. Titles and descriptions need Yoast SEO or Rank Math, since that is where the value is written. Headings, thin content and broken links live inside the text, so those link through to the edit screen.

  • The scan does not move forward. What now?

    The scan runs on WP-Cron, which only runs when someone visits the site. Keep the overview page open and it pushes the scan forward itself. If your host has disabled WP-Cron, set up a real cron job that calls wp-cron.php.

  • Why is a page in my footer reported as having no links?

    The scan reads the content of your pages and the items in your WordPress menus. It deliberately skips the site header, footer, sidebar and navigation, otherwise every page would look linked from everywhere. A page that is only reachable from a widget or a footer built in a page builder is therefore reported. So are posts that are only listed on an archive page. Switch the check off under Settings, or use the hook to have those pages count as linked.

  • Why does the image size check report nothing?

    It is off until you fill in a maximum under Settings; 300 KB is a sensible start. Only images inside your own uploads folder can be measured, because their file is read from disk. Images served from a CDN or another site are skipped rather than downloaded.

  • Why does the automatic scan start later than the time I set?

    WordPress runs planned jobs when someone visits the site, so on a quiet site nothing happens until the first visitor arrives after that moment. To make it exact, have your host call wp-cron.php from a real cron job and set DISABLE_WP_CRON to true.

  • The report never arrives. What now?

    Use Send a test report on the Automatic scan screen. If it fails, the reason is shown right below it. Most hosts cannot send mail through PHP at all; an SMTP plugin that sends through a real mailbox solves that. Also check the spam folder: a message from a site nobody knows yet often lands there.

  • Where are the kept reports stored?

    In wp-content/uploads/seo-health-check/. They list every page of the site and what is wrong with it, so the folder gets an .htaccess that denies access, and every file gets an unguessable name for servers that ignore .htaccess. Downloading goes through WordPress, which checks that you are allowed to. Deleting the plugin removes the folder.

  • How does the plugin know about updates?

    Once a day it asks GitHub which release is the newest. If that is newer than what you have, WordPress shows its usual "new version available" line on the Plugins screen, and you update it there like any other plugin. The answer is cached for twelve hours, so a site asks twice a day at most. A release without a proper zip is skipped on purpose, otherwise WordPress would install the wrong file and switch the plugin off.

Changelog

What changed in each version

  • 0.10.1

    Current version

    A link to the manual, on the Plugins screen next to Settings and at the bottom of the settings screen.

  • 0.10.0

    The Plugins screen now says when a newer release is available, and updating works from there, the same way it does for plugins from the official directory. The version details window shows the release notes.

  • 0.9.0

    Three new launch checks: whether the old development site really sends visitors to the live one, whether the client has an administrator account of their own, and whether a plugin replaced the WordPress login screen.

  • 0.8.0

    Three launch checks about forms: where they send their mail, which ones have a thank you page, and whether any spam protection is active. Reads Contact Form 7, WPForms and Gravity Forms.

  • 0.7.0

    A new check whether mail can really leave the site. The DNS check now covers DKIM too, and the analytics check can compare against the measurement code you expect.

  • 0.6.0

    Four new launch checks: menu items that lead to a page which is not published (with a reminder about pages still waiting for their text), the Google Search Console verification tag on the homepage, SPF and DMARC records in DNS so mail from the site does not end up in spam, and whether the default "admin" login still exists.

  • 0.5.2

    The bottom of the settings screen now shows which version is running, the database version, which SEO plugin the titles come from and whether scans run through Action Scheduler or WP-Cron. With a link to the project page, so you can see whether a newer version is out.

  • 0.5.1

    The hint in the email field is an example address again, instead of the real address of the site administrator.

  • 0.5.0

    Scan on a schedule: choose the days and the time, in the time zone of the site. A report by email after every scheduled scan, with the full list attached as CSV. Reports are kept on the site, shielded from visitors, with a download link and a limit you set. And a Send a test report button that shows why sending failed, instead of failing quietly.

  • 0.4.0

    Three new checks: headings that skip a level, heavy images and pages that nothing links to. A widget on the WordPress dashboard with the main numbers, and a Dutch translation. Links between pages are stored in a third table, which is removed again when you delete the plugin.

  • 0.3.0

    Every issue is marked New, Unchanged or Fixed, with a status filter in the overview, and solved issues stay visible until the next scan. A new Scans screen with the last twenty scans and a comparison per kind of problem. The page scores show the change since the previous full scan, and the CSV export has a Status column.

  • 0.2.0

    A score from 0 to 100 per page, a comparison with the previous scan with new issues marked, and alt texts, SEO titles and meta descriptions editable straight from the overview. Fixed: duplicate titles reported by mistake when Yoast or Rank Math returned their template instead of the real title.

  • 0.1.1

    Improvements after testing on a site with 600 pages, and the author name set.

  • 0.1.0

    First version: per-page scan, overview, CSV export, launch checks and settings.

Try it on your own site

Free and open source. Installing takes three minutes.

Download the plugin (.zip)