/ โ† AI Schema Generator Fixes / Schema URL Errors
In this guide
  1. Where URLs hide in a generated block
  2. Why generated addresses go wrong
  3. Wrong and right, pattern by pattern
  4. A corrected block
  5. Checking every address at once
  6. The fix, step by step
  7. Platform notes
  8. Keeping addresses right
  9. Questions and answers

Where URLs hide in a generated block

It is easy to check url and forget the rest. These are the properties that hold addresses in the types generators most often produce, and what each one should point at.

PropertyShould point atMust it load?
@idA stable identifier built from the canonical address, often with a fragment such as #productNo; it names a thing rather than linking to it, but it should start with your real domain
urlThe canonical address of the page or entityYes, with a 200 status and no redirect
mainEntityOfPageThe page that is mainly about this entityYes
image, thumbnailUrlThe full-size image files, not a thumbnail or placeholderYes, and crawlable by Googlebot
logoYour actual logo fileYes
sameAsYour own profiles on other sitesYes, and they must really be yours
author.urlThe author's page on your site or a profile they ownYes
offers.urlThe page where this item can be bought or bookedYes
item in a breadcrumbEach level of the trailYes
contentUrl, embedUrlThe media file or the embeddable playerYes

The schema.org addresses used as values, such as https://schema.org/InStock, are fixed vocabulary terms. They are correct as written and do not need checking.

Why generated addresses go wrong

A language model does not browse your site. It is given the page's HTML or text and writes JSON-LD from it. Almost every URL fault traces back to something in that input, or to a gap the model filled.

๐Ÿ’ก Generate from the live, public, canonical address of the page. That single habit removes the staging, preview and tracking problems before they start.

Wrong and right, pattern by pattern

GeneratedCorrectedWhy
"/services/boiler-repair""https://www.example.co.uk/services/boiler-repair"Some parsers resolve a relative path against the page and some do not, and the block breaks if it is ever copied elsewhere.
"//cdn.example.co.uk/img/van.jpg""https://cdn.example.co.uk/img/van.jpg"Protocol-relative addresses are a leftover from mixed http and https sites; state the scheme.
"http://example.co.uk/about""https://www.example.co.uk/about"Match the scheme and host of your canonical, including or excluding www exactly as the site does.
"https://staging.example.co.uk/..."The live hostStaging hosts are usually blocked or password-protected, so every address fails.
"...boiler-repair?utm_source=newsletter""...boiler-repair"Tracking parameters create a second address for the same page.
"...boiler-repair/" when the canonical has no slashMatch the canonicalA trailing-slash mismatch is a redirect or a duplicate.
"...wp-content/uploads/van-300x200.jpg"The full-size fileThumbnails are often too small for image features.
"data:image/gif;base64,..."A real https image addressInline placeholder images are not files anyone can fetch.
"https://example.co.uk/Boiler Repair.jpg""https://example.co.uk/Boiler%20Repair.jpg"Spaces must be encoded; better still, rename the file with hyphens.

Addresses written with escaped slashes, such as https:\/\/www.example.co.uk\/about, are not an error. PHP's json_encode() writes them that way by default and every JSON parser reads them as ordinary slashes.

A corrected block

This is a generated Organization for a fictional heating firm after every address was corrected. The generator had written a relative logo path, a staging url and two guessed social profiles, one of which belonged to a different company.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Organization",
  "@id": "https://www.example.co.uk/#organization",
  "name": "Brightwell Heating",
  "url": "https://www.example.co.uk/",
  "logo": {
    "@type": "ImageObject",
    "url": "https://www.example.co.uk/assets/brightwell-logo-512.png",
    "width": 512,
    "height": 512
  },
  "image": "https://www.example.co.uk/assets/brightwell-van-1200x800.jpg",
  "sameAs": [
    "https://www.linkedin.com/company/example-brightwell-heating",
    "https://www.instagram.com/example_brightwell"
  ],
  "contactPoint": {
    "@type": "ContactPoint",
    "contactType": "customer service",
    "telephone": "+44 1632 960123",
    "url": "https://www.example.co.uk/contact"
  }
}
</script>

Note what was left out: the Facebook address the model suggested did not exist, so it went rather than being "fixed" to a guess of our own. A short sameAs list of real profiles is worth more than a long list with a dead entry.

Checking every address at once

Clicking through a dozen addresses by hand is slow and it is easy to miss the one in a nested object. This short Python script reads a generated block saved as a file, finds every string that looks like an address, and reports anything that is not absolute https, fails to load or redirects. It uses only the standard library.

import json, sys, urllib.request

def find_urls(node, path='$'):
    if isinstance(node, dict):
        for key, value in node.items():
            yield from find_urls(value, path + '.' + key)
    elif isinstance(node, list):
        for i, value in enumerate(node):
            yield from find_urls(value, '%s[%d]' % (path, i))
    elif isinstance(node, str) and node.startswith(('http', '/', 'data:')):
        yield path, node

block = json.load(open(sys.argv[1], encoding='utf-8'))
for path, url in find_urls(block):
    if url.startswith('https://schema.org/') or path.endswith('@context'):
        continue
    if not url.startswith('https://'):
        print('NOT ABSOLUTE HTTPS ', path, url)
        continue
    if path.endswith('@id'):
        continue
    req = urllib.request.Request(url, headers={'User-Agent': 'schema-url-check'})
    try:
        with urllib.request.urlopen(req, timeout=15) as r:
            moved = '' if r.geturl() == url else ' redirects to ' + r.geturl()
            print(r.status, path, url + moved)
    except Exception as err:
        print('FAILED', path, url, err)

Save the JSON without the script tags as block.json and run python3 check_urls.py block.json. Anything marked FAILED, NOT ABSOLUTE HTTPS or "redirects to" needs attention. A redirect usually means the canonical has a different host, scheme or trailing slash from the address in the markup.

โš ๏ธ A 200 status from your own computer does not prove Googlebot can fetch the file. Images on a host that blocks crawlers in robots.txt, or behind hotlink protection, fail for Google while loading fine for you. Test the live page with URL Inspection and look at the loaded resources.

The fix, step by step

Step 1

List every URL in the generated block

Go through the block property by property, including nested objects such as offers, author, logo and breadcrumb entries, and write down every string that is a web address. Include @id values and each entry in sameAs. Running the checking script above does this for you and prints the path to each address, which makes it easy to find the right line again when you come to edit the block.

Step 2

Make each address absolute and https

Rewrite every relative path such as /images/van.jpg as a full address beginning with https:// and your live domain. Replace protocol-relative addresses that start with // and any plain http:// addresses in the same way. If the block contains a staging, preview or localhost host, replace the host throughout with a single search and replace, then check the paths still exist on the live site.

Step 3

Swap in the canonical address

Open the page source and copy the address from the rel="canonical" link tag. Use exactly that for url and mainEntityOfPage, and as the base for any @id values, matching its www, trailing slash and letter case. Strip tracking parameters such as utm_source, gclid and fbclid. Keep query strings only where the canonical itself has them, which is rare outside filtered listing pages.

Step 4

Check that every address resolves

Request each address and confirm a 200 status with no redirect. Swap placeholders, inline data: images and small thumbnails for the full-size image file, which you can find in the data-src or srcset attribute in developer tools. Replace any address that redirects with its final destination, and remove any that returns 404 unless you can find the page or file at its new location.

Step 5

Replace guessed logo and profile links

Treat every sameAs, logo and author.url as unconfirmed until you have opened it and seen that it belongs to you. Profiles generated from the business name often point at a stranger or at nothing, and a logo path such as /logo.png may be a guess. Keep the ones you have verified, add real ones you know about, and delete the rest rather than guessing again.

Step 6

Fix the source so it stays fixed

Correcting one block does not stop the next one repeating the fault. Regenerate from the live canonical address, not a preview. Fix relative image paths in templates where you can, and make sure lazy-loaded images keep a real file in srcset. Where markup is built by a template, take the site address from one setting rather than typing it, then test the live URL in the Rich Results Test to confirm the corrected addresses render.

Platform notes

WordPress

The site address comes from Settings, General, and old posts may still hold http:// links from before the site moved to https. Image uploads have size variants with names like -300x200.jpg; the generator can pick one of these from the post body, so check that image points at the original file. Staging copies made by hosting tools use a different host, so never generate from the staging site and copy the markup across.

Shopify

Liquid's image_url filter returns a protocol-relative address that starts with //cdn.shopify.com. If you template generated markup in Liquid, add | prepend: 'https:'. The storefront can also be reached on its .myshopify.com address; make sure markup uses your primary domain, which the canonical_url object gives you.

Custom and static sites, frameworks

Build the site origin from a single environment variable or config value, and join paths to it when the markup is rendered, so a staging build writes staging addresses and a production build writes live ones. Check the production build's output, not the dev server, because many frameworks rewrite asset paths with hashes at build time.

Keeping addresses right

Questions and answers

1. Are relative URLs allowed in JSON-LD?

The JSON-LD format can resolve a relative address against the page it sits on, so a relative path is not strictly invalid. In practice, not every tool that reads structured data resolves it the same way, and a block copied to another page or served from another host changes meaning without warning. Writing every address in full, with https and your canonical host, removes that doubt and costs nothing. It is the safest choice for generated markup.

2. Does the @id have to be a working web page?

No. An @id is an identifier that lets different blocks refer to the same thing, such as your organisation or a product. It does not have to load, and it often ends with a fragment like #organization that no server sees. It should still start with your real, canonical domain, so it is clearly yours, and it must never change once published, because other markup on your site may point at it and would lose the connection.

3. Why does my schema image work in the browser but fail in Google?

Your browser and Googlebot are treated differently. The image may sit on a host whose robots.txt blocks crawlers, behind hotlink protection that refuses requests without your site as referrer, or on a CDN address with a signed token that expires. The generated block may also point at a lazy-load placeholder that your browser swaps for the real file. Use URL Inspection in Search Console to see which resources Google could load.

4. The generator added social profiles I never gave it. Should I keep them?

Only after you have opened each one and confirmed it belongs to your business. A model asked for a complete Organization will often produce profile addresses built from your business name because that pattern is common in the examples it learned from. Some point at nothing, others at a different company with a similar name. Keep verified profiles, delete the rest, and never replace a bad guess with another guess of your own.

5. Should schema URLs have a trailing slash?

They should match your canonical address exactly. If the canonical tag on the page ends with a slash, use the slash in url, mainEntityOfPage and @id. If it does not, leave it off. A mismatch means the markup names an address that redirects, or a duplicate of the page, which weakens the link between the markup and the page Google indexes. The same rule applies to www, https and letter case.

6. Is it a problem that my URLs have backslashes before the slashes?

No. Addresses such as https:\/\/example.co.uk\/about are standard JSON escaping, which PHP writes by default and some other encoders produce too. Every JSON parser, including Google's, reads them as ordinary slashes, so the markup is fine. If you want the block to be easier for people to read, PHP's JSON_UNESCAPED_SLASHES option leaves the slashes plain, but it makes no difference to search engines. Spend the time on the addresses themselves instead: whether they are absolute, canonical and actually load.

7. Do I need to update schema after moving my site to a new domain?

Yes, if any of it is stored as pasted text. Markup produced by a plugin or template from a site setting updates itself when the setting changes, but generated blocks stored in custom fields, page content or theme files keep the old host. After a move, search your database and theme files for the old domain, update every stored block, and test a sample of pages in the Rich Results Test.

Generate markup from the right address

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 before delivery, ready for you to review and publish.

Open AI Schema Generator Fixes โ†’
๐Ÿ’ฌ Got a problem?
Related Guides: All AI Schema Generator Fixes  ·  AI Schema Guide  ·  Schema Image Errors  ·  Canonical Tag Fixes  ·  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.