/ โ† Migration Audit Fixes / Schema After Migration
In this guide
  1. Why structured data goes missing in a move
  2. Building an inventory of the old markup
  3. Which lost types matter most
  4. The fix, step by step
  5. Getting identifiers and URLs right
  6. Where to rebuild it, by platform
  7. Keeping it from happening again
  8. Questions and answers

Why structured data goes missing in a move

Content is migrated deliberately: someone exports posts and products and imports them. Structured data usually is not, because it was never stored as content. It was assembled at page-render time from settings and fields by whatever software ran the old site. Change that software and the output changes with it.

Old sourceWhat happens in a migration
SEO plugin (for example Yoast or Rank Math on WordPress)The plugin is not installed on the new site, or is installed with default settings, so the Organization details, logo, social profiles and article types it produced are gone or generic.
Theme markup, often microdataA new theme does not include the itemprop attributes the old one had, so product or review markup vanishes with the redesign.
E-commerce app or extensionReview and product apps on Shopify, WooCommerce or Magento inject their own markup. The app is not reinstalled, or the new theme lacks the block where it inserted it.
Tag manager injectionA JSON-LD tag in Google Tag Manager was tied to CSS selectors or data-layer variables that no longer exist on the new templates.
Hand-written blocks in contentCustom HTML blocks were stripped by the importer or sanitised by the new editor.
A headless or custom front endNothing is generated automatically; if the developers did not build it, there is none.

Even when markup survives, it can carry the old site with it. Identifiers such as @id, url, logo and image may still use the old domain or the staging host, which quietly breaks the links between entities.

Building an inventory of the old markup

The migration audit compares structured data before and after, but to restore it you need to know exactly what each type of page carried. Work by template, not by URL: a site with forty thousand pages may have only eight templates.

  1. List the templates: home, category, product, article, author, location, contact, FAQ-style help pages and so on.
  2. Pick two or three representative URLs for each from the old crawl or a saved copy.
  3. For each, record the schema types present, the key properties, whether it was JSON-LD or microdata, and what produced it.

If the old site is already gone, saved crawl exports that included structured data extraction, cached copies in the Internet Archive and old Search Console enhancement reports (which list the types Google detected) will fill most of the gaps.

A short script can pull JSON-LD types from a list of addresses, which makes before-and-after comparisons quick when both versions are still reachable, for example the old site on a backup host.

import json, re, sys, requests

def types(url):
    html = requests.get(url, timeout=20).text
    found = []
    for block in re.findall(r'<script[^>]*application/ld\+json[^>]*>(.*?)</script>', html, re.S):
        try:
            data = json.loads(block)
        except ValueError:
            found.append("INVALID JSON"); continue
        items = data.get("@graph", [data]) if isinstance(data, dict) else data
        found += [str(i.get("@type")) for i in items if isinstance(i, dict)]
    return sorted(found)

for line in open(sys.argv[1]):
    old, new = line.split()
    a, b = types(old), types(new)
    if a != b:
        print(new, "missing:", sorted(set(a) - set(b)), "added:", sorted(set(b) - set(a)))

The script only sees JSON-LD in the HTML the server sends. Microdata and markup added by JavaScript need a crawler that renders pages, or a check in the Rich Results Test, which renders like Google.

Which lost types matter most

Not every missing block has the same effect. Prioritise by what the markup did in search results and what depends on it.

๐Ÿ’ก Do not rebuild markup just because the old site had it. FAQ rich results are now limited to well-known authoritative government and health sites, and HowTo rich results were removed in 2023. The markup is still valid, but restoring it will not bring those features back for most sites.

The fix, step by step

Step 1

Inventory the old markup by template

List every page template on the old site and choose two or three example URLs for each. From the pre-migration crawl, saved page source or archived copies, record which schema types each template carried, the important properties such as price, rating, author and dates, and whether the format was JSON-LD or microdata. Save the old blocks themselves in a folder, one file per template, because you will want to compare them property by property later.

Step 2

Trace what generated each block

For each template, work out which software produced the markup: an SEO plugin, the theme, a review or product app, a tag manager tag or hand-written HTML. Plugin output usually carries a comment or a recognisable @id pattern, and app output often sits inside the app's own container. Knowing the source tells you whether the fix is a setting, an app reinstall, a template change or custom code on the new platform.

Step 3

Compare the new templates against the inventory

Run the same example pages, now at their new addresses, through the Rich Results Test or a comparison script, and note for each template which types and properties are missing, changed or new. Check the rendered result, not just the raw source, because some platforms inject markup with JavaScript. Mark each gap by priority, putting shop products, ratings and breadcrumbs first, then articles and the site-wide organisation details.

Step 4

Rebuild the missing markup in the new templates

Generate the markup in the page template from real fields, so every product, article or location gets it automatically, rather than pasting blocks into individual pages. Prefer JSON-LD rendered on the server. Use the new platform's equivalent plugin, app or theme setting where one exists, and custom template code where it does not. Make sure every value in the markup, such as price, rating and dates, matches what is visible on the page.

Step 5

Replace old-domain and staging URLs inside the markup

Search the rendered source of every template for the old domain and the staging host. Update @id, url, logo, image, sameAs and breadcrumb item addresses to the new canonical URLs with https and the chosen host. Keep @id values stable from now on, and make sure that references between entities, such as an article's publisher pointing to the organisation, use exactly the same identifier on every page.

Step 6

Validate one page of every template

Test at least one live URL per template in the Google Rich Results Test to see which features Google can find, and in the Schema Markup Validator to check the vocabulary more generally. Fix errors first, then warnings that concern properties you actually have data for. Test a second example from each template with unusual data, such as a product with no reviews or an article without an image, to catch templates that output empty or broken values.

Step 7

Watch the Search Console enhancement reports

In the new Search Console property, open the reports under Shopping and Enhancements, such as Product snippets, Merchant listings, Breadcrumbs and Review snippets, and check that valid item counts climb back towards the old property's figures as pages are recrawled. Investigate any new error type straight away, because it usually affects a whole template. Rerun the Site Migration Audit to confirm the structured data comparison no longer shows missing types.

Getting identifiers and URLs right

Modern markup often uses a connected graph: the WebSite, the Organization, the WebPage and the Article each have an @id, and they refer to each other. After a migration those identifiers must be rebuilt on the new domain, and they must be identical everywhere they are used.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@graph": [
    {
      "@type": "Organization",
      "@id": "https://www.example.co.uk/#organization",
      "name": "Brightwater Garden Supplies",
      "url": "https://www.example.co.uk/",
      "logo": "https://www.example.co.uk/images/logo-512.png"
    },
    {
      "@type": "WebSite",
      "@id": "https://www.example.co.uk/#website",
      "url": "https://www.example.co.uk/",
      "name": "Brightwater Garden Supplies",
      "publisher": { "@id": "https://www.example.co.uk/#organization" }
    },
    {
      "@type": "BreadcrumbList",
      "@id": "https://www.example.co.uk/tools/pruning/#breadcrumb",
      "itemListElement": [
        { "@type": "ListItem", "position": 1, "name": "Home", "item": "https://www.example.co.uk/" },
        { "@type": "ListItem", "position": 2, "name": "Tools", "item": "https://www.example.co.uk/tools/" },
        { "@type": "ListItem", "position": 3, "name": "Pruning", "item": "https://www.example.co.uk/tools/pruning/" }
      ]
    }
  ]
}
</script>

Where to rebuild it, by platform

WordPress to WordPress (new theme)

Keep the same SEO plugin and export its settings from the old site, so the organisation details, logo and content type settings carry over. Check that the new theme does not add its own conflicting markup; two Organization or Product blocks from different sources is a common result of a redesign.

Moving to Shopify

Themes add basic Product markup, but the level of detail varies. Reviews usually come from an app, which must be reinstalled and connected to the theme. Compare a product page against the inventory, especially offers, availability, brand and identifiers such as GTIN.

Headless and custom front ends

Build a small set of functions that turn CMS fields into JSON-LD for each template, and render the result on the server. Treat the inventory from step one as the specification for that work. The headless migration guide covers rendering checks in more detail.

โš ๏ธ Markup must describe what the page shows. Do not copy old ratings or prices into static JSON-LD to "restore" rich results; if reviews were not migrated, show them on the page first, then mark them up.

Keeping it from happening again

Questions and answers

1. Why did my star ratings disappear from Google after the redesign?

Most often the review markup came from the old theme or a review app, and the new theme or platform does not output it. Check a product page with the Rich Results Test: if no Review or AggregateRating appears, the markup is missing. If it is present but not shown, Google may still be recrawling, or it may have chosen not to show stars for that page. Rich results are never guaranteed, even with valid markup, but they cannot appear without it.

2. How long does it take for rich results to come back after fixing schema?

It depends on how quickly Google recrawls the affected pages. Important pages that are crawled often may show updated results within days, while deeper pages can take weeks. The Search Console enhancement reports update as pages are recrawled, so watch the valid item counts rise. Requesting indexing for a few key URLs through URL Inspection can help for those pages, but it is not a way to speed up a whole site.

3. Should I use the same schema plugin on the new site?

If the new site runs on the same CMS, keeping the same plugin is usually the simplest way to preserve the markup, because its settings can often be exported and imported. If you change platform, there is no need to copy the tool, only the output. Use the inventory of the old markup as the target, then choose whatever the new platform does best, whether that is a built-in feature, an app, or template code.

4. Do the @id values in my schema have to change when the domain changes?

They should. An @id is an identifier, and most sites build it from the page URL, such as the home page address followed by #organization. After a domain move, identifiers on the old domain still work as labels, but they no longer match the canonical URLs of the new site and are easily mixed with new ones. Choose new identifiers on the new domain, use them consistently on every page, and do not change them again.

5. Is microdata from my old theme still acceptable, or must I switch to JSON-LD?

Google supports JSON-LD, microdata and RDFa, so microdata is still valid. JSON-LD is usually easier to maintain after a migration because it sits in one block that the template produces, separate from the visible HTML, so a redesign is less likely to break it. If you are rebuilding the markup anyway, JSON-LD is the sensible choice. Avoid outputting the same entity in both formats at once, because search engines then see two separate descriptions of one thing.

6. The Rich Results Test shows my markup but Search Console reports are empty. Why?

Search Console reports only include pages Google has crawled since the markup appeared, and a new property starts with no history. After a migration, the enhancement reports in the new property fill up gradually as pages are recrawled. If the test is clean and weeks pass with no growth, check that the pages are indexed, that they are not blocked or noindexed, and that the markup is in the HTML Google renders rather than added after a user action.

Compare your structured data before and after

The Site Migration Audit compares your pre-migration crawl with the live site and verifies that structured data survived the move, so you can see which templates lost their markup.

Open Migration Audit Fixes โ†’
๐Ÿ’ฌ Got a problem?
Related Guides: All Migration Audit Fixes  ·  Schema Drift Guide  ·  Fixing Deleted Schema  ·  Fixing Headless Migration Issues  ·  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.