SEO & JSON-LD Structured Data
Add schema.org structured data to theme pages so search engines and AI assistants understand your store.
Why Structured Data
JSON-LD structured data tells search engines and AI assistants exactly what a page is about — a product, its price and availability, the store behind it, the navigation path to it. Google uses it for rich results (price, stock, ratings in search listings), and answer engines increasingly rely on it when summarizing or recommending stores.
The Theme SDK ships typed schema.org builders and a TJsonLd component so every theme page can emit correct structured data with a few lines of code.
The TJsonLd Component
TJsonLd renders one or more schemas as a <script type="application/ld+json"> tag. Pass a single schema object or an array:
import { TJsonLd, productJsonLd, breadcrumbJsonLd, useBrand } from "threeu-sdk/theme";
export function ProductPage({ product }) {
const brand = useBrand();
return (
<>
<TJsonLd
schema={[
productJsonLd(product, {
url: `https://${brand.domain}/products/${product.slug}`,
brand: brand.name,
}),
breadcrumbJsonLd([
{ name: "Home", url: `https://${brand.domain}` },
{ name: product.name },
]),
]}
/>
{/* ...page content... */}
</>
);
}Schema Builders
All builders return plain schema.org objects with @context set, dropping empty fields automatically:
| Builder | Schema type | Use on |
|---|---|---|
productJsonLd(product, options?) | Product + Offer | Product pages — derives price, currency, and in/out-of-stock from the SDK product |
organizationJsonLd({ name, url, logo?, sameAs? }) | Organization | Home page / site-wide |
webSiteJsonLd({ name, url, searchUrlTemplate? }) | WebSite + SearchAction | Home page — enables the search sitelinks box |
breadcrumbJsonLd(items) | BreadcrumbList | Every page — pass { name, url } in display order |
faqJsonLd(items) | FAQPage | FAQ / policy pages — pass { question, answer } |
jsonLd(schema) | any | Escape hatch for any other schema.org type |
For non-React contexts (custom SSR, edge functions), serializeJsonLd(schema) returns the escaped JSON string to embed in your own script tag.
Site-Level Schema
Emit WebSite and Organization once, on the home page:
Injection-safe by design
serializeJsonLd escapes < and JS line separators, so user-generated content (product names, FAQ answers) can never break out of the script tag. Never build the script tag by hand with raw JSON.stringify.
import { TJsonLd, webSiteJsonLd, organizationJsonLd, useBrand } from "threeu-sdk/theme";
export function HomePage() {
const brand = useBrand();
const url = `https://${brand.domain}`;
return (
<TJsonLd
schema={[
webSiteJsonLd({ name: brand.name, url, searchUrlTemplate: `${url}/search?q={search_term_string}` }),
organizationJsonLd({ name: brand.name, url, logo: brand.logo }),
]}
/>
);
}Validating Your Markup
Before publishing:
- Google Rich Results Test — paste a preview URL to confirm Product/Breadcrumb eligibility
- schema.org validator — validator.schema.org checks structural correctness
- Review requirement — marketplace review checks that product pages emit
Productschema and that no schema contains hardcoded brand-specific data