3U

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:

Product page with JSON-LD
TypeScript
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:

BuilderSchema typeUse on
productJsonLd(product, options?)Product + OfferProduct pages — derives price, currency, and in/out-of-stock from the SDK product
organizationJsonLd({ name, url, logo?, sameAs? })OrganizationHome page / site-wide
webSiteJsonLd({ name, url, searchUrlTemplate? })WebSite + SearchActionHome page — enables the search sitelinks box
breadcrumbJsonLd(items)BreadcrumbListEvery page — pass { name, url } in display order
faqJsonLd(items)FAQPageFAQ / policy pages — pass { question, answer }
jsonLd(schema)anyEscape 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.

Home page site-level schema
TypeScript
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:

  1. Google Rich Results Test — paste a preview URL to confirm Product/Breadcrumb eligibility
  2. schema.org validator — validator.schema.org checks structural correctness
  3. Review requirement — marketplace review checks that product pages emit Product schema and that no schema contains hardcoded brand-specific data