Alcott

Loading site
Skip to content

2026-10-02 · 7 min · By Alcott Dube

How to add json-ld structured data search engines can trust

I use page content, stable identifiers and release checks to keep article, product and frequently asked question markup accurate enough for search engines to interpret.

Three translucent geometric forms connected to matching solid foundations with thin rods.

To add json-ld structured data search engines can trust, describe the content visitors can actually see, use the appropriate Schema.org types and satisfy Google's requirements for the intended search feature. Validate the rendered page and keep the markup current; correct structured data establishes eligibility, not a guarantee of enhanced search results.

Choose structured data that matches the visible page

I start with the page's purpose, not a list of rich results I want to acquire. An editorial post usually calls for Article or a more specific subtype such as BlogPosting. A page selling one identifiable item calls for Product. A page containing publisher-written questions and answers may fit FAQPage, although Google's display restrictions make that a narrow opportunity.

Schema.org defines the vocabulary. Google Search Central explains which parts Google supports for particular search appearances. Those aren't interchangeable. A property can be valid Schema.org markup without contributing to a Google feature, and a valid object can still lack information needed for that feature.

I map each proposed property to a content field before implementation. If the page doesn't contain a review, I don't add a review rating. If a product price changes by selected size, I decide which variant the page represents before describing its offer. This prevents valid-looking markup from making claims the page cannot support.

Add json-ld scripts without creating duplicate entities

I put the structured data in a script element with type="application/ld+json". Google can process it in the document head or body. My preference is server-rendered output generated from the same content record as the page, because it removes a dependency on client-side execution. Google can process dynamically injected markup, but I still test the rendered result.

I use a standard serialiser with safe handling for script embedding, rather than concatenating strings. An editor's quotation mark shouldn't break the object, and a literal closing script tag inside a content field must not escape the script element. The payload needs valid json: no comments, trailing commas or JavaScript expressions.

Before adding anything, I inspect output from the framework, commerce platform and search plugin. Two scripts aren't automatically a problem. Two Product objects describing the same item with different prices are. I assign one owner to each entity and use stable @id values when other objects need to reference it.

Paired rows of blocks with matching connections and one displaced block breaking the alignment.
The paired forms represent visible content and structured data staying aligned.

Mark up articles with authors, dates and images

For an article, I prioritise an accurate headline, author, publication date, meaningful modification date and representative image. Schema.org's Article type supports these properties. I use an author object rather than an unexplained string, and link it to a genuine profile page where available. The image address should resolve to an image that crawlers can access.

This is an illustrative starting point, not a production-ready payload. I replace every example value and add an image from the published page. I include a timezone when a timestamp is available, and I don't advance dateModified for every build or navigation change. It should reflect an actual editorial update. The visible byline and dates should tell the same story as the markup.

```html <script type="application/ld+json"> { "@context": "https://schema.org", "@type": "BlogPosting", "@id": "https://example.com/journal/cache-guide#article", "headline": "How I set cache headers", "author": { "@type": "Person", "name": "Alex Taylor", "url": "https://example.com/about" }, "datePublished": "2026-01-12T09:00:00+00:00", "dateModified": "2026-02-03T14:30:00+00:00" } </script> ```

Keep product offers tied to the displayed price

I separate the item from the transaction. Product describes the item through properties such as name, image, description and genuine identifiers. Its offers property can contain an Offer describing the price, currency, availability and purchase address. I never invent identifiers to satisfy a validator or convert an internal stock code into a manufacturer identifier.

For a simple product page, the pattern is a Product object with a nested Offer. I populate price with the numeric amount, priceCurrency with the three-letter currency code and availability with the appropriate Schema.org enumeration address. A displayed price of £49.00 becomes a price value of "49.00", not "£49.00". Both the visible price and structured offer should come from the same pricing function.

Google's product snippets and merchant listing experiences have different requirements, so I choose the intended feature before checking completeness. I also test sale transitions, sold-out items and selected variants. A cached offer that says an unavailable item is in stock is a data problem, not a formatting problem. I leave out ratings unless genuine review content supports them.

Use faq markup only when the page qualifies

Google limits faq rich results to well-known, authoritative government and health websites. I don't promise that adding FAQPage to a consultant's site or an online shop will produce expandable questions in search. Schema.org validity and Google's display eligibility are separate decisions. For most commercial sites, this work sits behind accurate article and product markup.

Where the type fits, the object pattern is FAQPage with a mainEntity array. Each entry is a Question with its full text in name and an acceptedAnswer object of type Answer containing text. Every marked-up question and answer must be available to visitors. Answers inside expandable sections can qualify when visitors can open them.

I don't use this pattern for advertising copy or a discussion where users submit alternative answers. Google's guidance points user-answer pages towards QAPage instead, subject to that type's requirements. I also avoid marking up the same repeated question across many pages. A shared footer should not become the structured-data centre of every document.

Validate the rendered page before release

I use Schema.org's validator to check vocabulary and object structure, then Google's Rich Results Test to check supported search features. These tools answer different questions. A passing syntax check doesn't establish Google's eligibility, and a passing rich results test doesn't certify the truth of a price or the quality of an article.

I test both a code sample and the deployed address. The live test can reveal rendering failures, inaccessible resources and markup missing from the actual template. I then compare the extracted values with the visible page. Required-property errors need fixing. Recommended-property warnings deserve a decision, not fabricated content inserted to make the report quieter.

My release sample includes awkward cases: an article without an author profile, a title containing quotation marks, a sold-out product and an expired discount. I check crawl access too. A page blocked from crawling, hidden behind authentication or excluded from indexing cannot be treated as a normal candidate for Google's rich results.

Monitor structured data after content changes

I treat structured data as a maintained output of the publishing system. Automated tests can parse the script, check expected types and compare critical fields with source records. Price, availability, canonical address and modification date are useful assertions. A test that merely confirms a script exists misses most meaningful failures.

After deployment, I use Search Console's inspection and relevant enhancement reports to investigate what Google has processed. Reporting isn't immediate, and not every Schema.org type has a dedicated report. When a template changes, I inspect representative pages rather than assuming that a clean report from last month still applies.

For measurement, I record the release date and compare eligible pages using available search appearance, impressions, clicks and click-through rate data. I keep ranking changes, seasonality and concurrent page edits in view. A rise in clicks doesn't establish that markup caused it. Operationally, I want fewer contradictory fields and less delay between a content update and its structured representation.

Questions people ask

Does json-ld structured data improve search rankings?

I wouldn't present it as a ranking boost. Google uses structured data to understand content and assess eligibility for supported search features, but adding it doesn't guarantee higher positions or rich results.

Should json-ld go in the head or body?

Google supports either location. I choose the placement the publishing system can maintain reliably, with server-rendered output as my default when it is practical.

Can I add multiple structured data types to one page?

Yes, when each type accurately describes something on that page. I might include an article and its publisher, using stable identifiers for references rather than creating conflicting copies of the same entity.

Why isn't my faq structured data showing in Google?

Google restricts faq rich results to well-known, authoritative government and health sites. Even eligible sites aren't guaranteed a display. I check eligibility before spending time changing markup that already validates.

Where I checked my thinking

Start a project