📝
Form
💾
Output
JSON-LD
Microdata
📋
Copy
⬇️
Download
✓
Validate JSON
in your ', }, zh: { toolTitle: 'Schema 结构化数据生成器', toolDesc: '为 15+ 种 Schema 类型生成有效的 JSON-LD 结构化数据 — 文章、产品、FAQ、食谱、本地商家、活动、人物、组织等。复制粘贴到 即可解锁 Google 富文本搜索结果。', form: '表单', output: '输出', copy: '复制', download: '下载', validate: '校验 JSON', validJson: '✓ JSON-LD 有效', invalidJson: '✗ JSON-LD 无效', example: '加载示例', clear: '清空', step1: '从上方芯片选择 Schema 类型(文章、产品、FAQ、食谱等)', step2: '填写必填字段和任何要包含的可选详情', step3: '右侧的 JSON-LD 预览实时更新 — 检查并调整', step4: '复制 JSON-LD,粘贴到 中的 标签内', } }); const { $, copyText, t } = GZ; const SCHEMAS = { Article: { fields: [ {k:'headline', l:'Headline *', t:'text'}, {k:'description', l:'Description', t:'textarea'}, {k:'image', l:'Image URL', t:'text'}, {k:'author', l:'Author Name', t:'text'}, {k:'datePublished', l:'Date Published', t:'text'}, {k:'publisher', l:'Publisher Name', t:'text'}, {k:'logo', l:'Publisher Logo URL', t:'text'}, {k:'url', l:'Page URL', t:'text'}, ], build: v => { const o = { '@context':'https://schema.org', '@type':'Article', headline:v.headline||'' }; if (v.description) o.description = v.description; if (v.image) o.image = v.image; if (v.author) o.author = {'@type':'Person', name:v.author}; if (v.datePublished) o.datePublished = v.datePublished; if (v.publisher) o.publisher = {'@type':'Organization', name:v.publisher, logo: v.logo?{'@type':'ImageObject', url:v.logo}:undefined}; if (v.url) o.mainEntityOfPage = {'@type':'WebPage', '@id':v.url}; return o; } }, Product: { fields: [ {k:'name', l:'Product Name *', t:'text'}, {k:'description', l:'Description', t:'textarea'}, {k:'image', l:'Image URL', t:'text'}, {k:'sku', l:'SKU', t:'text'}, {k:'brand', l:'Brand', t:'text'}, {k:'price', l:'Price', t:'text'}, {k:'currency', l:'Currency', t:'text'}, {k:'availability', l:'Availability', t:'select', opts:['InStock','OutOfStock','PreOrder','Discontinued']}, {k:'ratingValue', l:'Rating Value (1-5)', t:'text'}, {k:'reviewCount', l:'Review Count', t:'text'}, ], build: v => { const o = {'@context':'https://schema.org','@type':'Product', name:v.name||''}; if (v.description) o.description = v.description; if (v.image) o.image = v.image; if (v.sku) o.sku = v.sku; if (v.brand) o.brand = {'@type':'Brand', name:v.brand}; if (v.price) { o.offers = {'@type':'Offer', price:v.price, priceCurrency:v.currency||'USD', availability:'https://schema.org/'+(v.availability||'InStock'), url: v.url||undefined}; } if (v.ratingValue) { o.aggregateRating = {'@type':'AggregateRating', ratingValue:v.ratingValue, reviewCount:v.reviewCount||1}; } return o; } }, FAQ: { fields: [ {k:'q1', l:'Question 1 *', t:'text'}, {k:'a1', l:'Answer 1 *', t:'textarea'}, {k:'q2', l:'Question 2', t:'text'}, {k:'a2', l:'Answer 2', t:'textarea'}, {k:'q3', l:'Question 3', t:'text'}, {k:'a3', l:'Answer 3', t:'textarea'}, ], build: v => { const items = []; if (v.q1 && v.a1) items.push({'@type':'Question', name:v.q1, acceptedAnswer:{'@type':'Answer', text:v.a1}}); if (v.q2 && v.a2) items.push({'@type':'Question', name:v.q2, acceptedAnswer:{'@type':'Answer', text:v.a2}}); if (v.q3 && v.a3) items.push({'@type':'Question', name:v.q3, acceptedAnswer:{'@type':'Answer', text:v.a3}}); return {'@context':'https://schema.org','@type':'FAQPage', mainEntity: items}; } }, Recipe: { fields: [ {k:'name', l:'Recipe Name *', t:'text'}, {k:'description', l:'Description', t:'textarea'}, {k:'image', l:'Image URL', t:'text'}, {k:'prepTime', l:'Prep Time (ISO 8601, e.g. PT15M)', t:'text'}, {k:'cookTime', l:'Cook Time (ISO 8601)', t:'text'}, {k:'servings', l:'Servings', t:'text'}, {k:'calories', l:'Calories', t:'text'}, {k:'ingredient1', l:'Ingredient 1', t:'text'}, {k:'ingredient2', l:'Ingredient 2', t:'text'}, {k:'ingredient3', l:'Ingredient 3', t:'text'}, ], build: v => { const ings = [v.ingredient1,v.ingredient2,v.ingredient3].filter(Boolean); const o = {'@context':'https://schema.org','@type':'Recipe', name:v.name||''}; if (v.description) o.description = v.description; if (v.image) o.image = v.image; if (v.prepTime) o.prepTime = v.prepTime; if (v.cookTime) o.cookTime = v.cookTime; if (v.servings) o.recipeYield = v.servings; if (v.calories) o.nutrition = {'@type':'NutritionInformation', calories:v.calories}; if (ings.length) o.recipeIngredient = ings; return o; } }, LocalBusiness: { fields: [ {k:'name', l:'Business Name *', t:'text'}, {k:'description', l:'Description', t:'textarea'}, {k:'street', l:'Street', t:'text'}, {k:'city', l:'City', t:'text'}, {k:'state', l:'State/Region', t:'text'}, {k:'zip', l:'Postal Code', t:'text'}, {k:'country', l:'Country', t:'text'}, {k:'phone', l:'Phone', t:'text'}, {k:'url', l:'Website', t:'text'}, {k:'priceRange', l:'Price Range (e.g. $$)', t:'text'}, ], build: v => { const o = { '@context':'https://schema.org', '@type':'LocalBusiness', name:v.name||'', address: {'@type':'PostalAddress', streetAddress:v.street, addressLocality:v.city, addressRegion:v.state, postalCode:v.zip, addressCountry:v.country} }; if (v.description) o.description = v.description; if (v.phone) o.telephone = v.phone; if (v.url) o.url = v.url; if (v.priceRange) o.priceRange = v.priceRange; return o; } }, Event: { fields: [ {k:'name', l:'Event Name *', t:'text'}, {k:'description', l:'Description', t:'textarea'}, {k:'startDate', l:'Start Date * (ISO)', t:'text'}, {k:'endDate', l:'End Date (ISO)', t:'text'}, {k:'location', l:'Location Name', t:'text'}, {k:'address', l:'Address', t:'text'}, {k:'url', l:'Event URL', t:'text'}, {k:'price', l:'Price', t:'text'}, {k:'currency', l:'Currency', t:'text'}, ], build: v => { const o = { '@context':'https://schema.org','@type':'Event', name:v.name||'', startDate:v.startDate||'', location: v.location?{'@type':'Place', name:v.location, address:v.address||undefined}:undefined }; if (v.description) o.description = v.description; if (v.endDate) o.endDate = v.endDate; if (v.url) o.url = v.url; if (v.price) { o.offers = {'@type':'Offer', price:v.price, priceCurrency:v.currency||'USD'}; } return o; } }, Person: { fields: [ {k:'name', l:'Full Name *', t:'text'}, {k:'jobTitle', l:'Job Title', t:'text'}, {k:'url', l:'Website', t:'text'}, {k:'email', l:'Email', t:'text'}, {k:'image', l:'Photo URL', t:'text'}, {k:'worksFor', l:'Works For (organization)', t:'text'}, ], build: v => { const o = {'@context':'https://schema.org','@type':'Person', name:v.name||''}; if (v.jobTitle) o.jobTitle = v.jobTitle; if (v.url) o.url = v.url; if (v.email) o.email = v.email; if (v.image) o.image = v.image; if (v.worksFor) o.worksFor = {'@type':'Organization', name:v.worksFor}; return o; } }, Organization: { fields: [ {k:'name', l:'Organization Name *', t:'text'}, {k:'url', l:'Website', t:'text'}, {k:'logo', l:'Logo URL', t:'text'}, {k:'description', l:'Description', t:'textarea'}, {k:'email', l:'Contact Email', t:'text'}, {k:'phone', l:'Phone', t:'text'}, {k:'sameAs1', l:'SameAs (social URL 1)', t:'text'}, {k:'sameAs2', l:'SameAs (social URL 2)', t:'text'}, ], build: v => { const sa = [v.sameAs1,v.sameAs2].filter(Boolean); const o = {'@context':'https://schema.org','@type':'Organization', name:v.name||''}; if (v.url) o.url = v.url; if (v.logo) o.logo = v.logo; if (v.description) o.description = v.description; if (v.email) o.email = v.email; if (v.phone) o.telephone = v.phone; if (sa.length) o.sameAs = sa; return o; } }, WebSite: { fields: [ {k:'name', l:'Site Name *', t:'text'}, {k:'url', l:'Site URL *', t:'text'}, {k:'searchUrl', l:'Search URL Template (e.g. https://example.com/?q={search_term_string})', t:'text'}, ], build: v => { const o = {'@context':'https://schema.org','@type':'WebSite', name:v.name||'', url:v.url||''}; if (v.searchUrl) o.potentialAction = {'@type':'SearchAction', target:v.searchUrl, 'query-input':'required name=search_term_string'}; return o; } }, HowTo: { fields: [ {k:'name', l:'How-To Title *', t:'text'}, {k:'description', l:'Description', t:'textarea'}, {k:'step1', l:'Step 1 Name', t:'text'}, {k:'step1text', l:'Step 1 Text', t:'textarea'}, {k:'step2', l:'Step 2 Name', t:'text'}, {k:'step2text', l:'Step 2 Text', t:'textarea'}, {k:'step3', l:'Step 3 Name', t:'text'}, {k:'step3text', l:'Step 3 Text', t:'textarea'}, ], build: v => { const steps = []; if (v.step1) steps.push({'@type':'HowToStep', name:v.step1, text:v.step1text||''}); if (v.step2) steps.push({'@type':'HowToStep', name:v.step2, text:v.step2text||''}); if (v.step3) steps.push({'@type':'HowToStep', name:v.step3, text:v.step3text||''}); const o = {'@context':'https://schema.org','@type':'HowTo', name:v.name||''}; if (v.description) o.description = v.description; if (steps.length) o.step = steps; return o; } }, Breadcrumb: { fields: [ {k:'item1', l:'Item 1 Name *', t:'text'}, {k:'url1', l:'Item 1 URL *', t:'text'}, {k:'item2', l:'Item 2 Name', t:'text'}, {k:'url2', l:'Item 2 URL', t:'text'}, {k:'item3', l:'Item 3 Name (current)', t:'text'}, {k:'url3', l:'Item 3 URL', t:'text'}, ], build: v => { const items = []; if (v.item1) items.push({'@type':'ListItem', position:1, name:v.item1, item:v.url1}); if (v.item2) items.push({'@type':'ListItem', position:2, name:v.item2, item:v.url2}); if (v.item3) items.push({'@type':'ListItem', position:3, name:v.item3, item:v.url3}); return {'@context':'https://schema.org','@type':'BreadcrumbList', itemListElement:items}; } }, SoftwareApp: { fields: [ {k:'name', l:'App Name *', t:'text'}, {k:'description', l:'Description', t:'textarea'}, {k:'image', l:'Image URL', t:'text'}, {k:'url', l:'App URL', t:'text'}, {k:'os', l:'Operating System', t:'text'}, {k:'category', l:'Category', t:'text'}, {k:'price', l:'Price (0 for free)', t:'text'}, {k:'currency', l:'Currency', t:'text'}, {k:'ratingValue', l:'Rating (1-5)', t:'text'}, {k:'reviewCount', l:'Review Count', t:'text'}, ], build: v => { const o = { '@context':'https://schema.org','@type':'SoftwareApplication', name:v.name||'', operatingSystem:v.os||'Web', applicationCategory:v.category||'UtilitiesApplication' }; if (v.description) o.description = v.description; if (v.image) o.image = v.image; if (v.url) o.url = v.url; if (v.price!==undefined && v.price!=='') { o.offers = {'@type':'Offer', price:v.price, priceCurrency:v.currency||'USD'}; } if (v.ratingValue) { o.aggregateRating = {'@type':'AggregateRating', ratingValue:v.ratingValue, reviewCount:v.reviewCount||1}; } return o; } }, Video: { fields: [ {k:'name', l:'Video Title *', t:'text'}, {k:'description', l:'Description', t:'textarea'}, {k:'thumbnailUrl', l:'Thumbnail URL', t:'text'}, {k:'contentUrl', l:'Content URL', t:'text'}, {k:'embedUrl', l:'Embed URL', t:'text'}, {k:'uploadDate', l:'Upload Date (ISO)', t:'text'}, {k:'duration', l:'Duration (ISO 8601, e.g. PT2M30S)', t:'text'}, ], build: v => { const o = {'@context':'https://schema.org','@type':'VideoObject', name:v.name||''}; if (v.description) o.description = v.description; if (v.thumbnailUrl) o.thumbnailUrl = v.thumbnailUrl; if (v.contentUrl) o.contentUrl = v.contentUrl; if (v.embedUrl) o.embedUrl = v.embedUrl; if (v.uploadDate) o.uploadDate = v.uploadDate; if (v.duration) o.duration = v.duration; return o; } } }; let currentType = 'Article'; let currentTab = 'json'; function getValues() { const v = {}; $('#form').querySelectorAll('[data-k]').forEach(el => { v[el.dataset.k] = el.value; }); return v; } function setValues(v) { $('#form').querySelectorAll('[data-k]').forEach(el => { if (v[el.dataset.k] !== undefined) el.value = v[el.dataset.k]; else el.value = ''; }); renderOutput(); } function renderForm() { const schema = SCHEMAS[currentType]; const html = schema.fields.map(f => { const id = 'f-'+f.k; let input; if (f.t === 'textarea') { input = `
`; } else if (f.t === 'select') { input = `
${f.opts.map(o=>`
${o}
`).join('')}
`; } else { input = `
`; } return `
${f.l}
${input}
`; }).join(''); $('#form').innerHTML = html; } function renderOutput() { const v = getValues(); const obj = SCHEMAS[currentType].build(v); // Remove undefined values const clean = JSON.parse(JSON.stringify(obj, (k, val) => val === undefined ? undefined : val)); const pretty = JSON.stringify(clean, null, 2); if (currentTab === 'json') { $('#output').textContent = `