Dark green cover for the AIScan WordPress guide to shipping one h1, a title tag, a meta description and JSON-LD, with abstract mint and emerald bars at the right.
Dark green cover for the AIScan WordPress guide to shipping one h1, a title tag, a meta description and JSON-LD, with abstract mint and emerald bars at the right.
AI Readiness

How to ship one h1, title, meta description and JSON-LD on WordPress

On WordPress, C3 usually fails on the heading count, not the schema. Set one h1 in the Site Editor and let the plugin do title, description and JSON-LD.

AAsif Rahman 8 Sept 2026 7 min read
#WordPress#structured data#JSON-LD#AI readiness

This guide covers C3 · Content — for WordPress.

Table of contents

WordPress sites fail AIScan's C3 check more often than their owners expect, and almost never for the reason they expect. Across the 129 WordPress sites in our scan corpus, verified on 8 September 2026, 72 pass. Of the 57 that do not, 50 are missing on one signal alone: the heading count. Their title tag is present. Their meta description is present. Their schema is present. The page either has no <h1> at all or it has several, and no SEO plugin will fix that for you, because on WordPress the h1 belongs to the theme.

Quick summary

QuestionAnswer
What C3 wantsExactly one <h1>, a <title>, a meta description, and at least one JSON-LD block
What WordPress does for youThe <title>, on any theme that declares title-tag support
What your SEO plugin doesThe meta description and the JSON-LD
What nothing does for youThe <h1>, which is a block attribute stored in your theme's template
Where you change itAppearance > Editor > Templates, then the Title block
Time neededAbout ten minutes, no code on a block theme

The four signals, and the one combination that passes

C3's evidence string is four fields and nothing else. Grouped across all 498 sites in the corpus on 8 September 2026, exactly one combination returns a pass: h1: 1, title: true, meta description: true, JSON-LD: true, on 245 sites. Every other shape reports partial or fail, including a site with 83 <h1> elements on one page.

Narrowed to WordPress, the misses are lopsided:

C3 signalWordPress sites missing it (of 129)
Exactly one <h1>50 (39 with none, 11 with more than one)
Meta description24
JSON-LD18
<title>2

So the plugin-shaped part of C3 is mostly solved on WordPress already. The theme-shaped part is not.

Why the h1 goes missing on WordPress specifically

In a block theme the post title is not typed into the page, it is rendered by a block. According to the core blocks reference fetched from developer.wordpress.org on 8 September 2026, core/post-title carries the attributes isLink, level, levelOptions, linkTarget, placeholder and rel. The heading level is an attribute, saved in template markup, shipped by whoever built the theme. If they set it to 2, your posts have no h1 and there is nothing in the post editor that says so.

One naming trap first. WordPress's own documentation page for the Post Title block now says, verbatim: "Post Title block was renamed to Title block." The block is still core/post-title in markup, but the label you are hunting for in the editor sidebar reads Title.

The opposite failure has the same cause. core/site-title also carries level, so a header template part that renders the site name as an h1, on a template that also renders the post title as an h1, produces two. Ten sites in the corpus report exactly h1: 2.

Set the Title block to H1 in the Site Editor

The Site Editor guide on wordpress.org says, verbatim: "Once you install and activate a Block theme on your site, go to Appearance > Editor to open the Site Editor."

  1. Go to Appearance > Editor.
  2. Click Templates, and open the template WordPress uses for single posts.
  3. Select the Title block, and set its heading level to H1 in the block settings.
  4. Click Save.

The markup the editor writes into the template looks like this:

<!-- wp:post-title {"level":1,"isLink":true} /-->

If you edit theme files rather than using the editor, the same delimiter lives in the block template your theme provides for single posts. Which file that is depends on the template hierarchy, so open the template in Appearance > Editor first and confirm you are looking at the one your posts actually render through.

Remove the second h1 from the header

Same editor, different screen. Open Appearance > Editor > Patterns, open your header template part, select the Site Title block and set its level to something other than H1. A site name repeated on every page is not the subject of any page, so an h1 is the wrong tag for it whatever the scan says.

On a classic theme, the title tag is opt-in

Classic themes have a separate failure mode, and it explains the two corpus sites reporting title: false. Core prints the title tag from one small function, quoted verbatim from developer.wordpress.org:

function _wp_render_title_tag() {
	if ( ! current_theme_supports( 'title-tag' ) ) {
		return;
	}
	echo '<title>' . wp_get_document_title() . '</title>' . "\n";
}

No add_theme_support( 'title-tag' ) in your theme, no title tag from core. Add that line to the theme's functions.php inside an after_setup_theme callback and it appears. To change the text without a plugin, filter document_title_parts or document_title_separator; pre_get_document_title short-circuits the whole function if you return a non-empty string.

Meta description and JSON-LD come from one plugin, not three

ThinkRank is the one we recommend on WordPress, for a specific reason rather than a general one: it handles robots.txt, robots meta, schema, sitemaps and llms.txt from a single plugin, so nothing is left arguing over the same file. It migrates settings from Rank Math, Yoast, All in One SEO and SEOPress, so switching costs you no re-entry. Verified on 8 September 2026 by reading a live ThinkRank install's schema settings, it returns auto_generate_schema and auto_deploy switched on, with Organization, Person and WebSite in enabled_schema_types and breadcrumb markup as its own toggle. That is the JSON-LD half of C3 handled without touching a template.

The alternatives are honest choices and worth naming plainly:

PluginMeta descriptionJSON-LDSets your h1
ThinkRankYesYes, generated automaticallyNo
Yoast SEOYesYesNo
Rank MathYesYesNo
All in One SEOYesYesNo
SEOPressYesYesNo

Run exactly one of them. Two SEO plugins on one site is the reliable way to ship two meta descriptions and two competing graphs. And as the last column says, none of them touches your h1.

Verify it, and read the row that changed

Scan first, because it answers the whole check in one command:

npx aiscan-cli yoursite.com

Read the C3 row in the content dimension. Its evidence prints those same four fields, so you can see which one moved. Full check descriptions are on /docs/checks/content, and the WordPress-specific notes are on /docs/platforms/wordpress.

If you would rather check by hand:

URL=https://example.com/your-post/
curl -s "$URL" | grep -c '<h1'
curl -s "$URL" | grep -o '<title>[^<]*'
curl -s "$URL" | grep -c 'name="description"'
curl -s "$URL" | grep -c 'application/ld+json'

Expected output: 1, your post title, 1, and 1 or more. Plain curl is enough here because WordPress renders on the server, which is not true of every stack. Next.js and React sites need a different test.

Where AIScan fits, and where it doesn't

C3 is scored per page, on the URL you hand it. A passing homepage tells you nothing about your single-post template, so scan a real post as well. Our evidence string records JSON-LD: true or false and stops there: it does not report which type you declared, whether the graph validates, or whether the description matches the page. It also cannot tell you that your h1 says "Home". Counting the tag is not judging the wording.

If the scan still reports h1: 0

Four causes account for almost all of them. You edited the wrong template, and the hierarchy sends your posts somewhere else. A caching plugin or CDN is still serving yesterday's HTML, so purge and re-scan. The heading level is set inside a pattern rather than the template, and the pattern keeps re-applying it. Or the block you changed sits in a query loop that renders on archives, not on single posts.

After a theme switch or a major theme update, re-scan. Template markup ships with the theme, so a level you fixed can arrive back at 2 in an update you did not read. The rest of the WordPress checklist is in our WordPress setup guide, and what Google does with your snippets once the markup is right is covered in the AI Overviews guide.

Next step: run npx aiscan-cli on one published post, read the C3 row, and fix whichever of the four fields is false. The rest of the fix guides are at /guides.

Frequently asked questions

My scan says h1: 0 but I can see the post title on the page.

You are seeing a heading, just not an h1. In a block theme the Title block stores its heading level as a level attribute, and a theme that ships it as 2 renders a visually identical title inside an <h2>. Open Appearance > Editor > Templates, select the Title block on your single-post template, and set the level to H1.

AIScan reports h1: 2 on every page of my site. Where is the second one?

Almost always the header. The Site Title block carries the same level attribute as the Title block, so a header template part rendering the site name as an h1 adds one to every page on the site. Open Appearance > Editor > Patterns, edit the header template part, and give the Site Title block a level other than H1.

I installed an SEO plugin and C3 is still partial. Why?

Because SEO plugins write the title tag, the meta description and the JSON-LD, and none of them writes your h1. Across 129 WordPress sites in our corpus on 8 September 2026, 50 of the 57 that miss C3 miss it on the heading count alone. Run the scan again and read which of the four fields is still false.

My theme has no Appearance > Editor menu item. What do I do?

That menu appears only on block themes. On a classic theme the h1 lives in a PHP template file, usually a call to the_title() wrapped in a heading tag, and the title tag depends on the theme declaring add_theme_support( 'title-tag' ). Both are theme edits, so make them in a child theme so an update does not remove them.

Does the h1 have to match the title tag exactly?

No. C3 counts one h1 and checks that a title tag exists; it does not compare them. A title tag that adds the site name and an h1 that does not is normal and fine. What causes trouble is an h1 that describes the site rather than the page, which the scan cannot detect at all.

How many JSON-LD blocks should a single post carry?

At least one, and our check stops counting there: the evidence string records JSON-LD: true or false and nothing about type or validity. Most WordPress SEO plugins emit one graph containing several linked types. Two plugins emitting two separate graphs is the case worth avoiding.

Will changing the heading level change how the title looks?

It can, because themes usually style headings by level. Set the level first, then adjust the size on the block's typography settings if the visual result changes. The tag and the type size are separate controls in the block editor.

Does any of this apply if I build pages with a page builder?

The Site Editor path does not, because a builder renders its own templates rather than the block templates under Appearance > Editor. Set the heading tag on whichever element outputs the title in the builder. The verification commands in this guide are unchanged, and they are the fastest way to confirm which tag you actually shipped.

Related guides