/ โ† AI Schema Generator Fixes / AI Schema in WordPress
In this guide
  1. Where generated markup can live in WordPress
  2. Working alongside Yoast SEO, Rank Math and similar plugins
  3. The output snippet
  4. The fix, step by step
  5. Handling a back catalogue with WP-CLI
  6. Page builders, block themes and WooCommerce
  7. Things that catch people out
  8. Questions and answers

Where generated markup can live in WordPress

There are four realistic homes for a generated block on a WordPress site. They differ in how reliable they are, who can edit them and whether they can be managed in bulk.

LocationWorks forMain drawback
Custom HTML block in the post contentA handful of pages edited only by administratorsScripts can be stripped when a user without the unfiltered_html capability saves the post; hard to find again later
A custom field output by a snippetPer-post markup at any scaleNeeds a few lines of code or a snippets plugin
Your SEO plugin's custom schema featureSites already using one that offers itAvailability depends on the plugin and often a paid tier; markup is tied to that plugin
Theme template fileThe same pattern on every post of a typeLost on theme updates unless you use a child theme; not per-post

For most sites the custom field route is the best balance. The markup sits alongside the post in the database, it is not mixed into the content editors work on, it can be read and written in bulk, and a single snippet controls how it is printed, so you can change that behaviour in one place.

Why pasted scripts disappear

WordPress filters post content for users who are not trusted with raw HTML. On a single site, administrators and editors normally have the unfiltered_html capability; authors and contributors do not. On a multisite network, only super admins have it. When a user without it saves a post, <script> tags are removed. So a block an administrator pasted can vanish the next time an author fixes a typo. Some hosts and security plugins also remove the capability for everyone, often by setting DISALLOW_UNFILTERED_HTML in wp-config.php.

โš ๏ธ If you have already pasted generated markup into posts, search the live pages for it. Posts that have been edited since by someone without raw HTML permission may have lost the script tags while keeping everything else. WordPress filtering removes tags rather than their contents, so the JSON can end up printed on the page as stray text, and nothing in the editor will tell you.

Working alongside Yoast SEO, Rank Math and similar plugins

An SEO plugin almost always outputs structured data already. Yoast SEO, Rank Math and All in One SEO each build a graph containing the site, the page, the organisation or person behind it, breadcrumbs and usually an Article for posts. WooCommerce adds Product markup to product pages, and recipe, event and review plugins add their own types.

The generator is most useful for what those plugins do not cover well: a Recipe on a site with no recipe plugin, Event details on a venue's news posts, a Service with prices, a Course description, or extra properties about a product. Before generating anything, decide which system owns each type, and remove types from the generated block that the plugin already handles. The duplicate schema guide covers resolving clashes in detail; the WordPress-specific point is that the plugin should keep the site-wide entities, because it updates them from your settings automatically.

Linking into the plugin's graph

Your generated entity should point at the plugin's entities rather than describe them again. View the page source, find the plugin's JSON-LD and copy the @id values it uses for the organisation, the web page and the author. Then use those as references in the generated block, for example "publisher": {"@id": "https://www.example.co.uk/#organization"}. Check the exact identifiers on your own site; they vary between plugins and settings.

Merging instead of printing separately

Developers can go one step further and add the generated entity into the plugin's own graph, so the page carries one combined block. Yoast SEO provides a wpseo_schema_graph filter and Rank Math provides a rank_math/json_ld filter for this. Their signatures and behaviour change between versions, so read the plugin's current developer documentation before using them. Printing a separate, well-linked block, as in the snippet below, is perfectly acceptable and easier to maintain.

The output snippet

This snippet reads a custom field called ai_schema_json on single posts and pages, checks that it contains valid JSON, and prints it in the head of the page. It re-encodes the JSON with wp_json_encode, which escapes forward slashes, so a stray closing script tag inside a text value cannot break out of the block. Add it through a code snippets plugin, a small site-specific plugin or a must-use plugin, not the parent theme's functions.php, which is replaced on update.

<?php
/**
 * Plugin Name: Example AI Schema Output
 * Description: Prints reviewed JSON-LD stored in the ai_schema_json custom field.
 */
add_action( 'wp_head', function () {
    if ( ! is_singular() ) {
        return;
    }
    $raw = get_post_meta( get_queried_object_id(), 'ai_schema_json', true );
    if ( ! is_string( $raw ) || '' === trim( $raw ) ) {
        return;
    }
    // Accept either bare JSON or JSON pasted with its script tags.
    $raw  = trim( preg_replace( '#</?script[^>]*>#i', '', $raw ) );
    $data = json_decode( $raw, true );
    if ( ! is_array( $data ) ) {
        return; // Invalid JSON: print nothing rather than a broken block.
    }
    echo "\n" . '<script type="application/ld+json">' . wp_json_encode( $data ) . '</script>' . "\n";
}, 20 );

A few notes on it:

๐Ÿ’ก If you want editors to see the field in a neater box, register it with register_post_meta and show_in_rest set to true, then add a small sidebar panel. For most small sites the built-in Custom fields panel is enough.

The fix, step by step

Step 1

Record what the site already outputs

Open a typical post, a page and, if you run WooCommerce, a product, then view the source of each and search for application/ld+json. Note which types appear, which plugin or theme prints each block, and the @id values used for the organisation, website, web page and author. Keep this list open while you work, because every later decision depends on knowing what WordPress already says about each page.

Step 2

Decide which types the generator will supply

Compare your list with what each kind of page needs. Leave site-wide entities, breadcrumbs and basic Article markup with the SEO plugin, and Product markup with WooCommerce, unless you plan to switch those off. Mark the gaps the generator should fill, such as Recipe, Event, Service or extra product properties. Write the decision down per post type so anyone generating markup later knows which types to keep and which to delete.

Step 3

Add a custom field and the output snippet

On a staging copy, add the output snippet through a code snippets plugin or a small must-use plugin rather than the theme. It reads the ai_schema_json field, validates the JSON and prints it in the head of single posts and pages. Add a test value to one draft post, preview it, and confirm the block appears once in the source. Then deploy the snippet to the live site.

Step 4

Generate, review and save markup for one post

Run the post's public address through the AI Schema Generator, choosing the type yourself if the post is ambiguous. Remove any type the plugin already owns, replace generated organisation and author details with references to the plugin's @id values, and delete any value you cannot see on the page. Paste the reviewed JSON into the post's ai_schema_json field and update the post.

Step 5

Test the post and clear the cache

Purge the page from your caching plugin, host cache or CDN, otherwise you may test an old copy. Load the live URL in the Rich Results Test and confirm the intended item is detected with no errors and that the plugin's own items still appear. Check the source once more for a second block of the same type. If nothing prints, check the field for invalid JSON, since the snippet deliberately stays silent in that case.

Step 6

Roll out to older posts in batches

Export a list of the posts that need markup, sorted by traffic or importance, and work through them in batches of twenty or so. Generate, review and save each one, or prepare reviewed JSON files and write them with WP-CLI. After each batch, test a sample in the Rich Results Test before continuing. Stopping between batches means a mistake in your review routine affects twenty posts, not four hundred.

Step 7

Recheck after plugin and theme updates

SEO plugins change their structured data output from time to time, and a new theme or page builder may add markup of its own. After major updates, view the source of two or three posts that carry generated markup and check that references still point at identifiers that exist and that no new duplicate has appeared. Keep an eye on the enhancement reports in Search Console for sudden drops or new errors.

Handling a back catalogue with WP-CLI

If you have shell access, WP-CLI makes it practical to apply reviewed markup to many posts without clicking through the editor. The work still needs a person to review each generated block; WP-CLI only speeds up the saving.

List candidate posts with their IDs and addresses:

wp post list --post_type=post --post_status=publish --fields=ID,post_title,url --format=csv > posts.csv

Save each reviewed block as a file named after the post ID, such as reviewed/1432.json, then write it to the post:

wp post meta update 1432 ai_schema_json "$(cat reviewed/1432.json)"

Or loop over a whole reviewed batch:

for f in reviewed/*.json; do
  id=$(basename "$f" .json)
  wp post meta update "$id" ai_schema_json "$(cat "$f")"
done

Before writing anything, take a database backup with wp db export. To see what a post currently holds, use wp post meta get 1432 ai_schema_json, and to remove markup from a post, wp post meta delete 1432 ai_schema_json.

๐Ÿ’ก Check every file is valid JSON before the loop runs. A quick way is for f in reviewed/*.json; do python3 -m json.tool "$f" > /dev/null || echo "bad: $f"; done. The output snippet would skip invalid files anyway, but you want to know about them.

Without shell access, a CSV import plugin that can write custom fields does the same job. Test it on two posts first and check that the plugin does not alter quotes or backslashes in the JSON.

Which older posts to start with

  1. Posts that already get search traffic and match a type with a rich result, such as recipes or events.
  2. Evergreen service and product-related posts that bring enquiries.
  3. Everything else, if it is worth doing at all. A short news post from years ago rarely gains anything from new markup beyond what the SEO plugin already outputs.

Page builders, block themes and WooCommerce

Page builders

Elementor, Divi and similar builders store layouts in their own format, and some put text into modules that are assembled when the page loads. The generator reads the public page, so this rarely matters for generation, but it does mean you should never paste markup into a builder's HTML widget as your storage method: it is hard to find in bulk, and builders can change how widget content is saved between versions. Keep the markup in the custom field and let the snippet print it.

Block themes and full site editing

Block themes still run the wp_head action, so the snippet works unchanged. Avoid placing markup in template parts through the Site Editor, because that applies it to every page using the template rather than to one post.

WooCommerce products

WooCommerce prints its own Product markup built from live product data, and many SEO plugins extend or replace it. Price and stock change constantly, so generated product markup stored in a field goes stale. Use generated output to identify extra properties worth adding, such as material or size details, and add those through the plugin or a filter on WooCommerce's structured data, leaving prices and availability to the live data.

Things that catch people out

For the general approach to JSON-LD problems on WordPress beyond generated markup, see fixing JSON-LD on WordPress.

Questions and answers

1. Can I paste AI-generated schema into a Custom HTML block?

You can, and if you are an administrator it will usually work at first. The risk is that script tags are removed when a user without the unfiltered_html capability later saves the post, such as an author fixing a typo, and nothing warns you. It is also hard to find and update pasted blocks across many posts. Storing the markup in a custom field and printing it with a small snippet avoids both problems.

2. Do I still need Yoast SEO or Rank Math if I use generated schema?

For most sites, yes. SEO plugins do much more than structured data, and even for schema they keep your site-wide entities such as the website, organisation and authors in step with your settings automatically. Generated markup works best as an addition for types the plugin does not handle well. Replacing the plugin's output entirely means taking on everything it did, including breadcrumbs and page entities, which is rarely worth the effort.

3. Where should the output code go?

Put it in a code snippets plugin, a small site-specific plugin or a must-use plugin in the wp-content/mu-plugins folder. Avoid adding it to the parent theme's functions.php file, because theme updates replace that file and your code would disappear. A child theme's functions.php is safer, but it still ties the markup to the theme, so changing themes later would silently remove it. A plugin keeps it independent of the design.

4. Will the generated block conflict with my SEO plugin's Article markup?

It will if the generated block also contains an Article or BlogPosting for the same post. Then the page has two descriptions of the same article that may disagree about the headline, dates or author. Delete the article type from the generated block and keep only the types the plugin does not provide, linking them to the plugin's entities with @id references. If you prefer the generated article, switch off the plugin's article output for that post type instead.

5. How do I add schema to hundreds of old posts?

Work in batches and never skip the review. Export a list of posts, prioritise the ones that get traffic and match a useful type, generate and review markup for a batch, then save it with WP-CLI or a CSV import plugin that writes custom fields. Test a sample after each batch. Bulk generation without review risks publishing invented values across hundreds of pages at once, which is much harder to undo than to prevent.

6. Why does my generated schema not show up on the live page?

The usual causes are a cached copy of the page, invalid JSON in the field that the snippet deliberately skips, a field name that does not match the one the snippet reads, or scripts stripped from post content if you pasted the block into the editor. Purge the cache, view the source, and check the field in a JSON validator. If you used a Custom HTML block, check whether the post was saved by a user without raw HTML permission.

7. Does WordPress keep a history of my schema field?

Not by default. WordPress stores revisions of the post title, content and excerpt, but custom field values are generally not included unless the field is registered with revisions support. If a reviewed block is overwritten by mistake, the earlier version may be gone. Keep reviewed JSON files in a folder or repository alongside your notes, which also makes bulk updates easier and gives you a record of what was checked and when.

Generate markup to drop into WordPress

The AI Schema Generator reads your page content with an AI model, writes JSON-LD tailored to the content type and validates it against schema.org and Google rich result criteria, ready to review and save in a custom field on your post.

Open AI Schema Generator Fixes โ†’
๐Ÿ’ฌ Got a problem?
Related Guides: All AI Schema Generator Fixes  ·  Duplicate Schema Generation  ·  JSON-LD on WordPress  ·  Building Schema in WordPress  ·  Learning Hub

About aiwebpageseo

aiwebpageseo.com is a data-driven SEO and AEO (Answer Engine Optimisation) platform providing a free suite of technical SEO tools. Rather than relying on AI-theorised assumptions, the platform analyses live URL performance, delivering objective diagnostics, page speed metrics, CLS debugging, and site crawl data alongside actionable technical tutorials.