What custom JSON-LD on Shopify means
Custom JSON-LD on Shopify is structured data the merchant adds to the theme above and beyond what Shopify auto-emits. Shopify's SEO overview confirms themes auto-emit Product schema. Custom JSON-LD covers everything else — Organization, WebSite, BreadcrumbList, Article on the blog, FAQPage on the FAQ hub, plus the Product fields the theme's auto-emission leaves out (itemCondition, hasMerchantReturnPolicy, shippingDetails, and gtin on themes that don't print it). The injection pattern is a <script type='application/ld+json'>…</script> block placed in theme.liquid or a per-template section file.
Three placement scopes
JSON-LD on Shopify lives in one of three scopes: (1) theme.liquid <head>, for site-wide entities like Organization and WebSite, printed on the home page where Google reads them. (2) Per-template section files (main-product.liquid, main-list-collections.liquid, main-article.liquid, page.liquid), for entities that need template-specific Liquid context. (3) Schema apps via Script Tag API or app blocks, for merchants who prefer a managed app to writing Liquid by hand.
theme.liquid placement
theme.liquid is the layout file that wraps every storefront page. Its <head> section is the canonical place for site-wide JSON-LD. Open Online Store > Themes > Actions > Edit code > Layout > theme.liquid. Find the closing </head> tag. Add the Organization and WebSite blocks immediately before </head>, inside a home-page condition: Google requires WebSite on the home page and recommends the home page for Organization. Save. On Dawn and Horizon, delete the theme's own Organization (and on Dawn, WebSite) block in sections/header.liquid so the home page carries one of each.
Per-template section files
Modern Shopify themes (Dawn-derivative and similar) follow Online Store 2.0 architecture: each template (product, collection, article, page) is composed of sections, and the section file for the dominant section carries the template's structured data. Open Online Store > Themes > Actions > Edit code > Sections. Find main-product.liquid (for the PDP Product + BreadcrumbList block), main-list-collections.liquid (for the collection BreadcrumbList block), main-article.liquid (for the Article block). Dawn's main-product.liquid and main-article.liquid already print {{ product | structured_data }} and {{ article | structured_data }}; replace those lines with your block rather than adding a second one. Elsewhere, paste your JSON-LD inside the section, typically near the bottom before any closing tags.
The @graph pattern for one block per page
A Shopify page can carry multiple JSON-LD blocks (the theme's Product, plus your blocks for BreadcrumbList, Article, etc.), and Google says it understands multiple items whether they're nested or in separate blocks. The cleaner pattern is one script tag per page containing a @graph array of the entities. @id is what connects them: Google's guidelines use @id to link related items, so when your Product's Offer names its seller by the Organization's @id, the reference points at the same node wherever that node is defined. What @id is not documented to do is merge two separate descriptions of one entity, so describe each entity once.
Deploying via Theme Editor, Shopify CLI, or GitHub
Three deployment paths in 2026. (1) Theme Editor: edit theme.liquid and section files directly in Online Store > Themes > Actions > Edit code. Saves are live immediately on the published theme; merchants should use a draft theme for risky changes. (2) Shopify CLI: shopify theme pull to download a local copy, edit, shopify theme push to deploy. CLI is the modern recommendation. (3) GitHub integration: connect a repo, commit theme changes, Shopify auto-deploys. Best for teams; requires the Online Store Theme version control feature.
Validation workflow
After deploying, validate one URL per template type. PDP: submit one product URL to Rich Results Test. Collection: submit one collection URL. Blog post: submit one article URL. Homepage: submit shop.url. Expected pass-fail per template: PDP detects Product + Offer + BreadcrumbList (zero errors); Collection detects BreadcrumbList; Blog post detects Article + BreadcrumbList; Homepage detects Organization. The test won't show WebSite: site names aren't supported in the Rich Results Test, so check that block in the Schema Markup Validator. For any errors, edit the relevant section file or theme.liquid, redeploy, re-validate.
Shopify gotchas on custom JSON-LD
Five gotchas. First: curly (smart) quotes in the JSON. They don't come from Shopify's code editor; they come from drafting or pasting code through a word processor, a document editor or a chat app, which swap straight quotes for curly ones. A curly quote isn't a JSON string delimiter, so the block stops parsing. Copy code from a plain-text source such as a code editor or the raw file. Second: printing Liquid text variables (product.title, shop.name, article.title) inside quote marks instead of through | json. A double quote or line break in the value breaks the JSON, and | escape doesn't help: it is an HTML filter. Third: putting Product schema in theme.liquid (where product.* is unbound off PDPs). Fourth: putting Organization schema in a section file (where it fires per-template instead of site-wide). Fifth: missing the application/ld+json mime type on the script tag — the block is then ignored by validators.