SEO

Free JSON-LD schema markup generator

By Charles Summers · Updated · Free, no signup

Short answer

This builds a valid JSON-LD block for the schema type you choose, serialised through JSON.stringify so quotes and special characters are escaped correctly, then separates the properties Google lists as required for that type from the ones it merely recommends. Anything you did not supply is left in the output as a labelled TODO with an example of a valid value, so you can see exactly what still blocks rich result eligibility instead of discovering it in Search Console three weeks later.

Use the schema markup generator

What does this tool actually do?

This builds a valid JSON-LD block for the schema type you choose, serialised through JSON.stringify so quotes and special characters are escaped correctly, then separates the properties Google lists as required for that type from the ones it merely recommends. Anything you did not supply is left in the output as a labelled TODO with an example of a valid value, so you can see exactly what still blocks rich result eligibility instead of discovering it in Search Console three weeks later..

It runs entirely in your browser. Nothing you type is sent to a server, no account is required, and there is no usage limit, because there is no cost per run to control.

Required, recommended, and the gap between valid and eligible

Schema.org is a vocabulary, and vocabularies do not have mandatory fields. Almost every property on almost every type is optional as far as schema.org is concerned, which is why the schema.org validator will happily pass a block that Google will not use for anything. Google publishes a separate, much stricter subset per search feature, and that subset is the one that decides whether a rich result appears. Two validators, two different questions: is this well-formed vocabulary, and does this qualify for a specific result type.

The consequence is a split you have to hold in your head while writing markup. Miss a required property and Search Console logs an Error against the item, and the item is ineligible for the enhancement entirely, not partially. Miss a recommended property and you get a Warning, the item stays eligible, and the result usually renders with fewer elements in it, so a product loses its price line or an event loses its date. Warnings are not decorative but they are not disqualifying, and treating them as equally urgent is how teams spend a sprint on markup that changes nothing.

The split is also per feature rather than per type, which trips up people who learn it once and generalise. Product is the clearest case: to be eligible for a plain product snippet you effectively need a name, while merchant listing experiences want image and a fully specified offer with price, currency and availability. Same @type, same page, two different bars. Article sits at the other extreme and has no required properties at all, which sounds like good news and is not: a valid Article block with nothing but a headline tells a parser nothing it could not already read from the H1.

What each of these types actually earns you in the results

Markup is worth writing in proportion to what Google does with it, and that varies enormously across the seven types here. Being clear-eyed about which ones still render saves you from shipping accordions that nobody will ever see.

  • FAQPage. In August 2023 Google restricted FAQ rich results to well-known authoritative government and health sites. Your markup is still valid and still parsed, but on a normal commercial site the collapsible questions no longer appear. HowTo went further and lost its rich result altogether.
  • BreadcrumbList. One of the most reliable renderers. It replaces the raw URL line above your title with a labelled path, which costs nothing and works on almost every site that emits it correctly.
  • Product. The type with the most visible payoff (price, availability, rating) and the strictest requirements, because the data feeds shopping surfaces where a wrong price is a real-world problem.
  • Event. Requires a start date and a location, and the location has to be a Place with an address or a VirtualLocation with a URL. Half the broken event markup on the web is an online event modelled as a physical one.
  • LocalBusiness. Produces no rich result by itself. It supports entity understanding and the knowledge panel, while the map pack is driven by your Business Profile. Useful, but not the lever people think it is.
  • SoftwareApplication. Documented as limited support, and rating data is part of the requirement, so a free tool with no reviews cannot qualify no matter how complete the rest of the block is.
  • Article. No required properties, and no standalone rich result for most publishers. Its value is as a clean statement of author, publisher and dates for anything parsing your page.

Where the block goes, and why hand-written JSON breaks

A JSON-LD script tag is valid in the head or anywhere in the body; Google supports both and there is no ranking difference between them. What does differ is injection method. Markup written into the server response is read on the first pass. Markup injected by a tag manager only exists after JavaScript runs, so it depends on your page being rendered, which happens on a later pass and can lag by days on a large site. It works, and it is a reasonable stopgap when you cannot get a template change deployed, but it should not be the permanent home for anything you depend on.

The most common failure has nothing to do with SEO and everything to do with string handling. JSON is unforgiving: one unescaped double quote inside a product description, one curly quote pasted from a word processor into a numeric field, one literal closing script tag inside a text value, and the entire block is discarded silently. There is no error in the console, no warning in Search Console, and no partial credit. The markup simply does not exist as far as any parser is concerned, and the only way you find out is by running the page through a testing tool. This generator builds a real object and serialises it, which is why the quotes in your inputs come out escaped rather than breaking the block.

Dates are the second silent killer. Every date property expects ISO 8601, and a timezone offset matters for events. A string like 14 September 2026 is not parsed, it is ignored, and the property behaves as though you never supplied it. If you have more than one entity on a page, multiple script blocks are fine and are easier to maintain than one deeply nested object; when you do want them explicitly connected, give each an @id and reference that URI from the other block rather than duplicating the whole entity.

Markup describes the page, it does not decorate it

Google’s general structured data guidelines are blunt about this: the marked-up content has to be present and visible to a user on that page. Marking up questions that are not on the page, ratings that are not shown, or a price that differs from the one in the cart is the exact behaviour the spammy structured data manual action exists for, and it is applied at the site level rather than the page level. Review markup has its own specific restriction, which is that self-serving reviews about a business or organisation on its own page do not qualify.

It is also worth being honest about what markup does for ranking, which is nothing directly. Structured data is a parsing shortcut. It converts facts you have already published in HTML into a form that requires no inference, and the payoff arrives as eligibility for a result format and the click-through rate that format earns, not as a position change. The realistic case for spending an afternoon on it is that a breadcrumb path and a price in the result are worth more attention than another round of title rewriting on the same page.

That parsing-shortcut framing is also why the work has aged well as answer engines have taken over part of the query mix. A model summarising your page has to decide who wrote it, when it was updated, what it costs and who sells it. Those facts are recoverable from prose, expensively and unreliably. In a JSON-LD block they are stated once, unambiguously, in a format that is trivial to consume. You are not gaming anything, you are removing the need to guess.

Numbers worth knowing

MetricTypicalWhat it means
Required properties for ArticlenoneGoogle lists no required properties for Article types. Valid markup and useful markup are different bars: without author, publisher and both date fields the block restates your H1 and nothing else.
FAQ rich result eligibilitygov and health sitesNarrowed in August 2023 to well-known authoritative government and health sites. Everyone else can keep the markup for parsing value, but should stop expecting the accordion.
Effect of one unescaped quotethe whole block is droppedJSON parse failure is all-or-nothing and silent. No console error, no Search Console warning, just an item that never appears in the enhancement report.
Accepted date formatISO 8601 onlyDates with a timezone offset for events. Human-readable dates are ignored rather than rejected, so the property fails exactly as if it were absent.
Where the script tag belongshead or body, eitherBoth are supported. The real variable is server-rendered versus tag-manager injected, because injected markup is only seen once the page is rendered on a later crawl pass.

Mistakes that quietly cost you results

Marking up FAQs, ratings or prices that do not appear on the page
This is the specific behaviour the spammy structured data manual action covers, and it is applied site-wide, not to the one URL. If a value is not visible to a user on that page, it does not belong in the block, however true it is elsewhere.
Hand-building the JSON string by concatenating your CMS fields
One apostrophe rendered as a curly quote, one double quote in a product name, and the parser discards everything. Serialise from an object, or at minimum run the finished block through a JSON parser before it ships.
Putting aggregateRating for your own company on every page
Self-serving reviews about the business itself on its own site are excluded from review rich results, and copying one site-wide rating block across a thousand URLs is the easiest version of that to detect. Rate the product, not yourself.
Giving the last breadcrumb an item URL
The final crumb is the page the user is already on, so it takes a position and a name but no item. Including it is not fatal, but the pattern Google documents omits it, and consistency here is free.
Assuming a green Rich Results Test means the enhancement will show
The test answers whether you are eligible. Whether Google chooses to render it depends on the query, the device, the result type and whether that feature still exists for sites like yours. Eligibility is necessary, not sufficient.

What does the output look like?

This is the exact output the tool produces from the example inputs. It is generated by the same code that runs when you click the button, so what you see here is what you get.

SCHEMA TYPE: Product TARGET PAGE: https://example.com/shop/merino-base-layer JSON-LD (paste into the head, or anywhere in the body) <script type="application/ld+json"> { "@context": "https://schema.org", "@type": "Product", "name": "Merino Base Layer, Mens Long Sleeve", "description": "A 200gsm merino base layer built for cold-weather hiking, with flatlock seams and a longer body.", "image": [ "https://example.com/img/merino-base-layer.jpg" ], "brand": { "@type": "Brand", "name": "Northfell" }, "sku": "TODO: your internal SKU, must match the one you send to Merchant Center", "offers": { "@type": "Offer", "url": "https://example.com/shop/merino-base-layer", "price": "89.00", "priceCurrency": "USD", "availability": "https://schema.org/InStock", "priceValidUntil": "TODO: ISO 8601 date the price is good until, e.g. 2026-12-31" } } </script> REQUIRED BY GOOGLE FOR PRODUCT [ok] name supplied [ok] offers.price 89.00 [ok] offers.priceCurrency USD (inferred from the currency symbol you used) [ok] image supplied [ok] offers.availability defaulted to InStock, change it if that is wrong RECOMMENDED (eligible without these, thinner result with them missing) [ok] brand.name taken from the brand field [ok] description supplied [TODO] sku left as a TODO [TODO] aggregateRating only add this if real reviews are visible on the page [TODO] review only add this if real reviews are visible on the page [TODO] priceValidUntil left as a TODO TODO MARKERS LEFT IN THE BLOCK: 2 Search the block for TODO: and replace each one. Every TODO string is currently a literal value, so the JSON parses but the property is wrong. NOTE ON THIS TYPE A plain product snippet needs little more than a name. Merchant listing experiences are the strict case, and that is where image and a fully specified offer become required rather than advisory. BEFORE YOU SHIP 1. Every value above must also be visible to a user on the page. Invisible markup is what the spammy structured data manual action is for. 2. Test the rendered page, not the source, if anything on it is injected by JavaScript. 3. Check the enhancement report in Search Console a week later. Errors mean ineligible; warnings mean eligible but thinner.

Frequently asked questions

Does schema markup improve my rankings?

Not directly, and anyone who tells you otherwise is selling something. Structured data makes facts you already published machine-readable, which qualifies the page for specific result formats such as breadcrumb paths, product prices and event dates. The gain shows up as click-through rate on the results you already rank for, plus cleaner interpretation by anything summarising your page. If a page is on the third result page, markup will not move it.

Head or body, and does it matter if my tag manager injects it?

Either location works and Google has said so explicitly. Injection method matters more than placement: markup in the server response is available immediately, while tag-manager markup only exists after JavaScript executes, so it is only picked up when the page is rendered, which happens on a later pass. Use the tag manager to test or to unblock yourself, then move it into the template.

Why does the output contain TODO strings?

Because a property left out entirely is easy to forget, and a property with a visible TODO in it is not. Every field this tool could not fill from your inputs is emitted with a label describing exactly what a valid value looks like, and the summary below the block counts them. The JSON still parses, so you can paste it, test it, and fill the gaps in place rather than rebuilding the structure from scratch.

Can I put more than one JSON-LD block on a page?

Yes, and it is usually cleaner than nesting everything into a single object. A product page commonly carries a Product block and a BreadcrumbList block. If two entities genuinely need to reference each other, give each one an @id set to a stable URI and point at that from the other block instead of duplicating the entity in both places.

The Rich Results Test says valid but nothing shows in Search. Why?

Validity means eligible, not guaranteed. Google decides per query and per device whether to render an enhancement, and some features have been withdrawn for most sites, FAQ rich results being the obvious current example. Also check that the URL is indexed at all, that the markup survives rendering, and that the values match what a user sees on the page.

Related free tools

Some links on this site are affiliate links, which means Hacking Demand may earn a commission if you buy through them at no extra cost to you. This does not influence which tools are listed. The tools on this page are free and have no affiliate relationship of any kind.