---
title: "How to ship one h1, title, meta description and JSON-LD on WordPress"
slug: title-meta-schema-wordpress
published: 2026-09-08T13:25:29.5207+00:00
updated: 2026-09-08T13:25:29.5207+00:00
author: "Asif Rahman"
author_url: https://masifrahman.com
category: "AI Readiness"
tags: check:C3, platform:wordpress, WordPress, structured data, JSON-LD, AI readiness
description: "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."
url: https://aiscan.site/blog/title-meta-schema-wordpress
---

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

| Question | Answer |
|---|---|
| What C3 wants | Exactly one `<h1>`, a `<title>`, a meta description, and at least one JSON-LD block |
| What WordPress does for you | The `<title>`, on any theme that declares `title-tag` support |
| What your SEO plugin does | The meta description and the JSON-LD |
| What nothing does for you | The `<h1>`, which is a block attribute stored in your theme's template |
| Where you change it | **Appearance > Editor > Templates**, then the Title block |
| Time needed | About 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 signal | WordPress sites missing it (of 129) |
|---|---|
| Exactly one `<h1>` | 50 (39 with none, 11 with more than one) |
| Meta description | 24 |
| JSON-LD | 18 |
| `<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:

```html
<!-- 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:

```php
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](https://thinkrank.ai) 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:

| Plugin | Meta description | JSON-LD | Sets your h1 |
|---|---|---|---|
| ThinkRank | Yes | Yes, generated automatically | No |
| Yoast SEO | Yes | Yes | No |
| Rank Math | Yes | Yes | No |
| All in One SEO | Yes | Yes | No |
| SEOPress | Yes | Yes | No |

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:

```bash
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](https://aiscan.site/docs/checks/content), and the WordPress-specific notes are on [/docs/platforms/wordpress](https://aiscan.site/docs/platforms/wordpress).

If you would rather check by hand:

```bash
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](https://aiscan.site/blog/nextjs-react-invisible-to-ai-crawlers).

## 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](https://aiscan.site/blog/ai-readiness-setup-wordpress), and what Google does with your snippets once the markup is right is covered in [the AI Overviews guide](https://aiscan.site/blog/google-ai-overviews-what-you-can-control).

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](https://aiscan.site/guides).

