Evaluated citeworthyio/seo-agent for reusable process knowledge. Relevant to this fleet's WordPress content sites (granja travel news, content-agent pipeline): a crawl-diagnose-approve-recrawl-measure loop for SEO metadata changes, a three-layer AI-crawler accessibility audit (robots policy, bot delivery, readable content), and a fail-closed method for generating and safely injecting Article JSON-LD. Keyword research and citation-probe pieces of the source repo were skipped as underdeveloped or too infra-coupled to be reusable here. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
62 lines
3.0 KiB
Markdown
62 lines
3.0 KiB
Markdown
---
|
|
name: grounded-article-jsonld
|
|
description: Use when generating, reviewing, storing, or injecting Article JSON-LD from page content. Prevent fabricated machine-readable claims and script-context injection while preserving existing structured data.
|
|
license: MIT
|
|
source: adapted from https://github.com/citeworthyio/seo-agent/blob/b78bb487f2819c3c7cc2ba6f3f5626ea0b841840/README.md#structured-data-json-ld and src/overrides.ts
|
|
---
|
|
|
|
# Grounded Article JSON-LD
|
|
|
|
Structured data is a factual publication, not decorative copy. An invented
|
|
author or date becomes a machine-readable claim under the site's name and may
|
|
be consumed without a reader ever seeing and correcting it.
|
|
|
|
## Generate only from observed page facts
|
|
|
|
Give the generator only the page content actually fetched: title, description,
|
|
canonical, visible article content, and explicit author/date/image fields. Tell
|
|
it to omit anything it cannot point to in that material. Never infer an author,
|
|
publisher, organization, date, image, rating, price, or other plausible default.
|
|
|
|
For an article page missing structured data, a minimal correct `Article` object
|
|
with `@context`, `@type`, and a grounded headline is better than a rich-looking
|
|
object containing guesses. Keep automated generation narrow to page-level types
|
|
such as `Article`; organization, product, rating, and similar business claims
|
|
need their own authoritative data source and review process.
|
|
|
|
## Validate at every boundary
|
|
|
|
Use the same fail-closed validator for generated drafts, manual proposals, and
|
|
the final publishing write:
|
|
|
|
1. Parse as JSON.
|
|
2. Accept one object or a non-empty array of objects, never primitives or null.
|
|
3. Require every node to have an `@context` referencing `schema.org` and a
|
|
non-empty `@type`.
|
|
4. Enforce a bounded canonical serialization (the source implementation uses
|
|
8,192 characters).
|
|
5. Reject the value rather than storing it if any check fails.
|
|
|
|
Using one validator matters: otherwise a draft can pass review and fail at
|
|
publish time, or a manual path can bypass the protections applied to AI output.
|
|
|
|
## Canonicalize for safe script embedding
|
|
|
|
Store JSON text without a `<script>` wrapper. After parsing, serialize it again
|
|
and replace literal `<` and `>` in the serialized bytes with JSON escapes
|
|
`\u003c` and `\u003e`. A JSON parser reconstructs the original characters, but
|
|
the stored bytes cannot close an enclosing script element or open an HTML
|
|
comment—even when the input expressed `<` through a JSON escape.
|
|
|
|
Do not use HTML entities such as `<` inside JSON: they change the data rather
|
|
than safely encoding JSON for a script context. At injection time, reject any
|
|
stored value that unexpectedly contains a literal `<`; it did not pass the
|
|
canonical write path.
|
|
|
|
Add the validated block alongside existing JSON-LD instead of replacing it.
|
|
Multiple blocks are valid, while overwriting an origin block can silently erase
|
|
publisher-authored facts. Verify the public response contains a parseable block
|
|
of the intended type; presence proves less than byte-for-byte comparison, so do
|
|
not overstate what that check establishes.
|
|
|