# JSON-LD Production Fieldbook

Use this working document to design, release, and maintain Schema.org JSON-LD as a publishing system. Duplicate it for each site or implementation program. Record evidence links instead of relying on a green validator alone.

## 1. Implementation record

| Field | Value |
|---|---|
| Site / property | |
| Environment | Production / staging / local |
| Technical owner | |
| Editorial owner | |
| SEO owner | |
| Security reviewer | |
| Repository / project | |
| Start date | |
| Target release | |
| Last reviewed | |
| Next scheduled review | |

## 2. Page-family inventory

Create one row per template, not one row per URL. Add representative normal, empty, edge, and error-state URLs.

| Page family | URL pattern | Representative URL | Main page purpose | Primary entity | Current JSON-LD source | Owner | Status |
|---|---|---|---|---|---|---|---|
| Article | `/insights/:slug` | | Editorial article | `BlogPosting` | | | Not started |
| Product | `/products/:slug` | | One product / offer | `Product` | | | Not started |
| Location | `/locations/:slug` | | One physical location | `LocalBusiness` subtype | | | Not started |
| Event | `/events/:slug` | | One scheduled event | `Event` | | | Not started |

### Injection-point inventory

| System | Can emit JSON-LD? | Node types emitted | Rules / configuration | Owner | Keep, change, or remove |
|---|---:|---|---|---|---|
| Theme / frontend | | | | | |
| SEO plugin | | | | | |
| Ecommerce app | | | | | |
| CMS integration | | | | | |
| Tag manager | | | | | |
| Edge / personalization layer | | | | | |

**Ownership rule:** Each node type has one authoritative generator. Multiple blocks are allowed only when their ownership and relationships are documented and non-conflicting.

## 3. Current feature-support check

Check documentation on the date of the release. Schema.org vocabulary validity and search-feature support are separate decisions.

| Type / feature | Accurately describes page? | Schema.org reference | Current Google feature reference | Applicable policies reviewed? | Review date | Reviewer | Decision |
|---|---:|---|---|---:|---|---|---|
| | | | | | | | Model / feature target / do not use |

Official starting points:

- Schema.org vocabulary: <https://schema.org/docs/full.html>
- Google Search Gallery: <https://developers.google.com/search/docs/appearance/structured-data/search-gallery>
- Google structured data policies: <https://developers.google.com/search/docs/appearance/structured-data/sd-policies>
- Google Search documentation updates: <https://developers.google.com/search/updates>

### Feature expectation

- Intended machine-readable description:
- Intended supported search feature, if any:
- What this implementation explicitly does **not** promise:
- Evidence that the page itself satisfies content and access policies:

## 4. Visible-fact and source-field contract

Every material property needs an authoritative source and a user-visible or directly verifiable counterpart.

| JSON-LD path | Type | Authoritative source and field | Visible location | Transform rule | Empty-state rule | Owner | Automated parity test | Evidence URL |
|---|---|---|---|---|---|---|---|---|
| `headline` | Text | | H1 | Normalize whitespace | Fail | | | |
| `datePublished` | Date | | Dateline | ISO 8601 | Fail for article | | | |
| `dateModified` | Date | | Updated dateline | Material update only | Omit when unavailable | | | |
| `author.@id` | URL | | Byline / profile | Resolve directory ID | Defined fallback or fail | | | |
| `image[]` | URL[] | | Representative image | Absolute public URL | Omit invalid asset | | | |
| `offers.price` | Number | | Visible offer | Decimal, no localized formatting | Fail for applicable offer | | | |
| `offers.priceCurrency` | Text | | Visible offer | ISO 4217 code | Fail with price | | | |
| `offers.availability` | URL | | Stock state | Controlled status map | Fail with offer | | | |

### Claims that must not be invented

- [ ] Ratings and review counts originate in genuine, accessible records.
- [ ] Offers, prices, and availability reflect a real visible offer.
- [ ] Event dates, attendance mode, location, and status are current.
- [ ] Author and publisher identities match visible bylines and company data.
- [ ] `dateModified` reflects a material content change, not every build.
- [ ] No hidden question, answer, product, review, or event exists only in JSON-LD.

## 5. Stable `@id` registry

Use one stable absolute URI per entity. Record aliases and migrations; do not silently create a second ID.

| Entity | Type | Canonical `@id` pattern | Defined on | Referenced by | Previous ID / alias | Owner | Migration note |
|---|---|---|---|---|---|---|---|
| Publisher | `Organization` | `https://example.com/#organization` | | | | | |
| Website | `WebSite` | `https://example.com/#website` | | | | | |
| Article | `BlogPosting` | `{canonical}#article` | | | | | |
| Web page | `WebPage` | `{canonical}#webpage` | | | | | |
| Author | `Person` | `{profileCanonical}#person` | | | | | |
| Product | `Product` | `{canonical}#product` | | | | | |

ID acceptance checks:

- [ ] Absolute and based on the public canonical origin.
- [ ] Unique for distinct entities.
- [ ] Reused wherever the same entity appears.
- [ ] Stable across deployments, locales, and template refactors unless a documented migration requires change.
- [ ] Locale strategy is explicit: shared entity ID or locale-specific page ID.

## 6. Graph relationship plan

| Subject node | Property | Object node | Why the relationship is true | Defined or referenced? | Test fixture |
|---|---|---|---|---|---|
| Article | `publisher` | Organization | Publisher of the visible article | Reference by `@id` | |
| Article | `author` | Person | Matches visible byline | Reference by `@id` | |
| Article | `mainEntityOfPage` | WebPage | Article is the page's main entity | Reference by `@id` | |

Graph review:

- [ ] The primary node matches the page's real purpose.
- [ ] Each edge has a plain-language justification.
- [ ] Repeated entities are references, not near-duplicate embedded objects.
- [ ] Optional nodes add truthful meaning rather than graph volume.
- [ ] Canonical URL, page `@id`, and `mainEntityOfPage` follow one documented rule.

## 7. Serialization and HTML-boundary controls

### Implementation

| Control | Selected approach | Owner | Test |
|---|---|---|---|
| JSON serializer | | | |
| HTML-safe embedding | | | |
| Framework-approved sanitizer / serializer | | | |
| Trusted Types / CSP considerations | | | |
| CMS input validation | | | |
| Type definitions | | | |

Required adversarial fixtures:

- [ ] Title containing double quotes.
- [ ] Text containing `<`, `>`, and `&`.
- [ ] Text containing a script-like closing sequence.
- [ ] Unicode and non-Latin names.
- [ ] Line and paragraph separators.
- [ ] Missing optional nested object.
- [ ] URL containing encoded query characters.
- [ ] Large but valid text value.

Record the exact serialized output for each fixture and confirm it remains one inert `application/ld+json` block in the rendered HTML.

## 8. Four-layer validation matrix

| Layer | Tool / method | What it proves | What it does not prove | Result | Evidence | Owner |
|---|---|---|---|---|---|---|
| JSON syntax | JSON parser / unit test | Serialized output parses | Vocabulary or policy compliance | | | |
| Schema.org vocabulary | <https://validator.schema.org/> | Recognized types and properties | Google feature eligibility | | | |
| Google feature | <https://search.google.com/test/rich-results> | Eligibility checks for supported feature | Actual display in Search | | | |
| Live render + parity | Public URL fetch, rendered DOM, field comparison | Script delivery and visible-value agreement | Guaranteed ranking or citation | | | |

### Live URL evidence

- URL:
- HTTP status:
- Canonical:
- Number of JSON-LD blocks:
- Parsed node types and IDs:
- Missing expected nodes:
- Duplicate or conflicting nodes:
- Critical visible-value mismatches:
- Anonymous / crawler access issue:
- Screenshot or crawl artifact:

## 9. CI and automated release gates

- [ ] Builder unit tests pass for normal, empty, and adversarial fixtures.
- [ ] Every JSON-LD block parses.
- [ ] Expected primary node exists once per representative route.
- [ ] Shared entities retain registered IDs.
- [ ] Dates are valid ISO values.
- [ ] URLs are absolute, canonical, public, and use the intended protocol.
- [ ] Price, currency, availability, title, author, and update date pass parity assertions.
- [ ] Empty values, `undefined`, and unintended empty arrays are omitted.
- [ ] Server-rendered or prerendered HTML contains the final block.
- [ ] Client navigation does not retain metadata from the previous route.
- [ ] No plugin, theme, app, or tag manager creates a conflicting node.
- [ ] Relevant Rich Results Test issues are resolved or documented as inapplicable.

### Representative route fixtures

| Page family | Normal | Missing optional data | Changed state | Unicode / unsafe text | Error / unavailable | CI job |
|---|---|---|---|---|---|---|
| | | | | | | |

## 10. Release record

| Field | Value |
|---|---|
| Release ID / commit | |
| Date and time | |
| Implementer | |
| Reviewer | |
| Changed page families | |
| Changed node types / fields | |
| Sample size crawled | |
| Validation evidence | |
| Search Console annotation | |
| Rollback trigger | |
| Rollback owner and procedure | |

Release sign-off:

- [ ] Staging and production URLs tested separately.
- [ ] Cache / CDN behavior verified after deployment.
- [ ] Representative production crawl completed.
- [ ] Owners notified of new fields and update responsibilities.
- [ ] Monitoring and alert routing enabled.
- [ ] Rollback is feasible without removing unrelated metadata.

## 11. Drift monitoring

| Signal | Method | Scope / sample | Frequency | Threshold | Owner | Response |
|---|---|---|---|---|---|---|
| Missing block | Crawl / rendered test | | | | | |
| Parse failure | Crawl / CI | | | | | |
| Visible-value mismatch | Field comparator | | | | | |
| Duplicate ID or node | Graph inventory | | | | | |
| New feature warning | Validator / Search Console | | | | | |
| Documentation change | Official update review | | | | | |

### Incident log

| Detected | Symptom | Affected URLs / template | Root cause | User-visible impact | Fix | Retest evidence | Preventive change | Owner | Closed |
|---|---|---|---|---|---|---|---|---|---|
| | | | | | | | | | |

## 12. Change-control record

Use this section when a CMS field, URL pattern, currency, author system, plugin, or schema builder changes.

- Proposed change:
- Reason:
- Affected page families:
- Affected source fields:
- Affected nodes and IDs:
- Backward-compatibility risk:
- Data migration:
- Test fixtures to add or update:
- Rollout sequence:
- Rollback plan:
- Owner and approver:
- Post-release evidence:

## 13. 30 / 60 / 90-day review

### Day 30: delivery and parity

- [ ] Re-crawl representative templates.
- [ ] Compare critical visible and structured values.
- [ ] Review parse failures, duplicates, and rendering gaps.
- [ ] Confirm editors understand field ownership.
- Decision and actions:

### Day 60: eligibility and operational quality

- [ ] Review Search Console enhancement reports for supported features.
- [ ] Re-run applicable live Rich Results Tests.
- [ ] Check official documentation updates.
- [ ] Sample changed products, events, articles, authors, and locations.
- Decision and actions:

### Day 90: maintain, improve, or retire

- [ ] Confirm the implementation still serves its documented purpose.
- [ ] Remove unsupported, duplicative, or unowned output.
- [ ] Prioritize gaps by user and operational impact—not property count.
- [ ] Approve the next review date and owner.
- Decision: maintain / improve / migrate / retire
- Evidence:

## Final sign-off

- Technical owner:
- Editorial owner:
- SEO owner:
- Security reviewer:
- Release approved on:
- Next review on:

The release is complete only when the graph is accurate, safely embedded, present on the live page, aligned with visible content, and assigned to an owner who will keep it current.
