Missing or malformed JSON-LD blocks Google's rich results pipeline entirely. When a directory listing omits a valid <script type="application/ld+json"> block with the correct schema-org LocalBusiness or Place @type, Google cannot generate rich snippets — star ratings, addresses, and hours never appear in SERPs. Listings that lack structured data are effectively invisible in the competitive layer where rich results dominate click-through rates. A JSON-LD object stored in an HTML data- attribute rather than the script's text content is the canonical hallucination failure for AI-generated code: it compiles and renders fine, but search engine parsers skip it completely.
Critical because misconfigured or absent JSON-LD eliminates the directory's structured-data eligibility entirely, directly suppressing rich-result visibility for every affected listing.
Add a reusable JsonLd component that injects the schema as the script element's inner text, not an HTML attribute. The dangerouslySetInnerHTML pattern is correct here — the input is always JSON.stringify() of a controlled object.
// components/json-ld.tsx
export function JsonLd({ schema }: { schema: object }) {
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
/>
);
}
Use it on every listing page template: <JsonLd schema={{ "@context": "https://schema.org", "@type": "LocalBusiness", ...listing }} />. Validate the output with Google's Rich Results Test.
ID: directory-listing-schema.structured-data.json-ld-valid
Severity: critical
What to look for: Enumerate every page that displays a business or listing. For each page, examine listing page templates or components for <script type="application/ld+json"> tags. Look for: (1) a <script type="application/ld+json"> element whose inner HTML (text content) contains a JSON object with @context and @type fields, (2) a dedicated JsonLd or StructuredData component that renders such a script. The JSON must be embedded as the script element's text content — not stored only in an HTML attribute like data-json or data-schema, which search engines cannot read. Accept: dangerouslySetInnerHTML pattern, direct JSX string child, or server-rendered inline script. Reject: JSON-LD object stored only in a data attribute with no text content. Validate the @type matches an appropriate Schema.org type for the listing domain (LocalBusiness, Place, ServiceArea, Organization, etc.).
Pass criteria: Every listing page contains a valid JSON-LD block with a correct Schema.org type matching the listing content domain. The schema JSON is embedded as the script element's text content (visible to search engine parsers) — 100% of listing pages must include syntactically valid JSON-LD with @type and @context fields. Report the count: "X listing pages found, all Y include valid JSON-LD."
Fail criteria: JSON-LD is missing; JSON is syntactically invalid; @type is incorrect or generic (e.g., "Thing"); JSON content is stored only in an HTML data attribute rather than the script's text content.
Skip (N/A) when: Never — structured data is essential for directory listings.
Cross-reference: The required-fields check verifies that all mandatory schema fields are populated.
Detail on fail: Specify the issue. Example: "No JSON-LD found on listing pages" or "JSON-LD present but uses @type 'Thing' instead of LocalBusiness or Place" or "JSON-LD has syntax error: missing closing brace" or "JsonLd component stores schema in data-json HTML attribute only — text content is empty, making it invisible to search engines"
Remediation: Add valid JSON-LD to listing page templates. The schema must be embedded as the script tag's text content. A reusable component pattern:
// components/json-ld.tsx — inject schema as inner HTML text content
export function JsonLd({ schema }: { schema: object }) {
const schemaString = JSON.stringify(schema);
// The __html key injects content as raw text — safe here because
// schema is always JSON.stringify() of a hardcoded or sanitized object
return (
<script
type="application/ld+json"
// Use innerHTML injection so text content is readable by search engines
{...{ dangerouslySetInnerHTML: { __html: schemaString } }}
/>
);
}