← Back to Blog

Making JSON-LD visible — the schema graph visualizer I wish Schema App didn't charge for

Making JSON-LD visible — the schema graph visualizer I wish Schema App didn't charge for

Part of the AEO / GEO / AI-search audit tool stack. See the pillar post for the full catalog of sibling audits and where this one fits in the lineup.

If your page has a Person schema nested inside an Article schema, pointing at a Review with its own itemReviewed link, that's a four-node graph. You can't see it in raw JSON unless you've mapped graphs in your head for a living. Most people can't.

The Schema Graph Visualizer draws it.

What the tool does

  1. Fetches the URL
  2. Parses every <script type="application/ld+json"> block
  3. Recursively walks each object, assigns @id to anonymous nodes, tracks edges (which property of which node points to which other node)
  4. Renders the flattened graph as SVG — concentric rings, top-tier types at center (Organization, WebSite), deeper types in outer rings
  5. Color-codes nodes by @type — Organization green, Article amber, Person purple, Product pink, FAQ teal, etc.
  6. Labels each edge with the property name ("author", "publisher", "mainEntityOfPage", "reviewedProduct")
  7. Reports: disconnected nodes (orphans in the graph), blocks missing @context, weak connectivity (too many anonymous nodes)

Why the graph view catches issues text doesn't

Three common schema problems that are invisible in raw JSON but obvious in the graph:

1. Orphan nodes. You emitted a Person block with name + jobTitle + sameAs, but nothing on the page references the Person via @id. The Person floats alone. Google doesn't connect it to your Article authorship. Graph view: Person is a red disconnected circle. Text view: looks fine.

2. @context scatter. Some blocks declare @context: "https://schema.org", others are inside a @graph that declares context once, others don't declare at all. The last category is technically broken — Google may not parse types correctly. Graph view: flags block-level missing context. Text view: you'd have to check each block individually.

3. Weak connectivity. If half your nodes are anonymous (no @id), the graph has no way to reference them from other blocks. They exist but can't be linked. Graph view: shows the anonymous node count and recommends adding @id everywhere. Text view: looks normal.

How it flattens

The flattener walks each block recursively:

  • Object with @id → use it as the node ID
  • Object without @id → generate a stable anonymous ID (_anon:N:type)
  • Array inside an object → visit each item with the array key as edge label
  • Scalar value → skip (it's data on the parent node, not a child)

Edges capture the parent→child path, with the key name as the edge label. This produces a clean DAG in 99% of real-world JSON-LD.

How the SVG layout works

I don't use a full force-directed graph library (would add 60-100 KB). Instead, a ring-based layout:

  • Center ring (0-1 nodes): Top-tier types — Organization, WebSite
  • Inner ring (3-4 nodes): Page-level types — WebPage, Article
  • Middle ring (8-10 nodes): Content types — BreadcrumbList, FAQPage, Product, Person
  • Outer ring (everything else): Leaf content — ListItem, Question, Answer, Offer

This gives a clean, readable layout even for dense schema pages. Hover a circle, the browser's native <title> tooltip shows the full @id and @type.

How to use it

  1. Go to /tools/schema-graph-visualizer/
  2. Paste your URL
  3. Click Run
  4. Inspect the graph. Hover any circle for node details. Scroll for the type distribution table + raw parsed blocks.

Typical runtime: ~2-4 seconds per page.

What it pairs with

The limits

  • Static HTML only. If your JSON-LD is injected post-hydration (React / Vue / Svelte with no SSR), the tool can't see it. Use the Prerender vs Hydration Parity audit to fix that separately.
  • No spec validation. The tool shows structure, not whether each @type has the right required fields. For that, use the Rich Results Eligibility Audit.
  • No external-link resolution. If your schema references an external @id (say, a Wikidata Q-number), the tool shows the reference but doesn't follow it.

Related reading

Fact-check notes and sources

This post is informational, not SEO-consulting advice. Mentions of Schema App, Yoast, Google, schema.org, and similar products are nominative fair use. No affiliation is implied.

← Back to Blog

Accessibility Options

Text Size
High Contrast
Reduce Motion
Reading Guide
Link Highlighting
Accessibility Statement

J.A. Watte is committed to ensuring digital accessibility for people with disabilities. This site conforms to WCAG 2.1 and 2.2 Level AA guidelines.

Measures Taken

  • Semantic HTML with proper heading hierarchy
  • ARIA labels and roles for interactive components
  • Color contrast ratios meeting WCAG AA (4.5:1)
  • Full keyboard navigation support
  • Skip navigation link
  • Visible focus indicators (3:1 contrast)
  • 44px minimum touch/click targets
  • Dark/light theme with system preference detection
  • Responsive design for all devices
  • Reduced motion support (CSS + toggle)
  • Text size customization (14px–20px)
  • Print stylesheet

Feedback

Contact: jwatte.com/contact

Full Accessibility StatementPrivacy Policy

Last updated: April 2026