DEV Community

Luke Fryer
Luke Fryer

Posted on • Originally published at aipromptarchitect.co.uk

JSON-LD Structured Data for React Apps: Complete Implementation Guide

        <p>Structured data is the bridge between your content and how search engines — and AI answer engines — understand it. JSON-LD (JavaScript Object Notation for Linked Data) is the format Google, Bing, and AI crawlers prefer. For React single-page applications, implementing it correctly requires specific patterns that differ from traditional server-rendered sites.</p>

        <h2>Why JSON-LD Matters for React SPAs</h2>
        <p>React SPAs render content client-side. While Googlebot can execute JavaScript, not all crawlers can. JSON-LD in a <code>&lt;script type="application/ld+json"&gt;</code> tag is the fastest, most reliable way to communicate page semantics to <strong>every</strong> crawler, including GPTBot, ClaudeBot, and Perplexity.</p>
        <p>Key benefit: JSON-LD is a <strong>data island</strong>. It exists independently of your rendered HTML, so crawlers don't need to parse your component tree to understand your page. This makes it the single most important AEO technique for SPAs.</p>

        <h2>Setting Up a Reusable SEO Component</h2>
        <p>The best approach is a single, reusable <code>&lt;SEO&gt;</code> component that handles all meta tags, Open Graph data, and JSON-LD injection. Here's the pattern we use at AI Prompt Architect:</p>
        <pre><code>import { Helmet } from 'react-helmet-async';
Enter fullscreen mode Exit fullscreen mode

interface SEOProps {
title: string;
description: string;
canonicalUrl: string;
jsonLd?: Record<string, unknown>;
ogImage?: string;
}

export const SEO: React.FC<SEOProps> = ({ title, description, canonicalUrl, jsonLd, ogImage }) => (
<Helmet>
<title data-rh="true">{title}</title>
<meta name="description" content={description} data-rh="true" />
<link rel="canonical" href={canonicalUrl} />
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
{ogImage && <meta property="og:image" content={ogImage} />}
{jsonLd && (
<script type="application/ld+json">
{JSON.stringify(jsonLd)}
</script>
)}
</Helmet>
);

The data-rh="true" attribute is critical — it tells react-helmet-async to manage the tag, preventing duplicates when navigating between pages.

        <h2>Schema Types You Should Implement</h2>

        <h3>1. Article / BlogPosting</h3>
        <p>For every blog post, generate an <code>Article</code> or <code>BlogPosting</code> schema. This tells Google and AI engines the author, publish date, and content structure.</p>
        <pre><code>{
Enter fullscreen mode Exit fullscreen mode

"@context": "https://schema.org",
"@type": "Article",
"headline": "Your Article Title",
"description": "Meta description here",
"author": {
"@type": "Person",
"name": "Author Name"
},
"datePublished": "2026-03-13",
"dateModified": "2026-03-13",
"publisher": {
"@type": "Organization",
"name": "AI Prompt Architect",
"url": "https://aipromptarchitect.co.uk"
}
}

        <h3>2. FAQPage</h3>
        <p>If your page has an FAQ section, wrap it in <code>FAQPage</code> schema. This is one of the highest-impact schemas for AEO because AI engines frequently pull FAQ answers into their responses.</p>
        <pre><code>{
Enter fullscreen mode Exit fullscreen mode

"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "What is prompt engineering?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Prompt engineering is the practice of..."
}
}
]
}

        <h3>3. HowTo</h3>
        <p>Tutorial and guide pages should use <code>HowTo</code> schema. Each step becomes a discrete, extractable unit that AI engines can cite independently.</p>

        <h3>4. SoftwareApplication / Product</h3>
        <p>For your product or pricing pages, use <code>SoftwareApplication</code> with <code>offers</code> to surface pricing and feature data directly in search results and AI summaries.</p>

        <h3>5. Organization</h3>
        <p>Your homepage should always include <code>Organization</code> schema with your logo, social profiles, and contact information. This establishes entity identity — a foundational concept in modern SEO and AEO.</p>

        <h2>Dynamic Schema Generation in React</h2>
        <p>Don't hardcode JSON-LD. Build it dynamically from your page data. For a blog post component:</p>
        <pre><code>const articleSchema = {
Enter fullscreen mode Exit fullscreen mode

'@context': 'https://schema.org',
'@type': 'Article',
headline: post.title,
description: post.description,
author: { '@type': 'Person', name: post.author.name },
datePublished: post.datePublished,
dateModified: post.dateModified,
publisher: {
'@type': 'Organization',
name: 'AI Prompt Architect',
url: 'https://aipromptarchitect.co.uk'
},
mainEntityOfPage: {
'@type': 'WebPage',
'@id': https://aipromptarchitect.co.uk/blog/${post.slug}
}
};

return <SEO jsonLd={articleSchema} ... />;

This pattern scales effortlessly — every new blog post automatically gets correct Article schema without any additional work.

        <h2>Validating Your Structured Data</h2>
        <p>Use Google's <a href="https://search.google.com/test/rich-results" target="_blank" rel="noopener noreferrer">Rich Results Test</a> and the <a href="https://validator.schema.org/" target="_blank" rel="noopener noreferrer">Schema.org Validator</a> to check your implementation. Common mistakes to avoid:</p>
        <ul>
            <li><strong>Missing required fields:</strong> Every schema type has required properties. Omitting them renders the entire schema invalid.</li>
            <li><strong>Duplicate schemas:</strong> Only include one schema of each type per page. Multiple <code>Article</code> schemas on a single page confuse crawlers.</li>
            <li><strong>Mismatched content:</strong> Your JSON-LD <code>headline</code> must match your visible <code>&lt;h1&gt;</code>. Google penalises discrepancies as potentially deceptive.</li>
        </ul>

        <h2>Implementation at AI Prompt Architect</h2>
        <p>Every page on aipromptarchitect.co.uk uses this exact pattern. Our unified <code>&lt;SEO&gt;</code> component generates the correct schema type per page context — <code>Article</code> for blog posts, <code>FAQPage</code> for competitor comparison pages, <code>SoftwareApplication</code> for pricing, and <code>Organization</code> for the homepage. The result: <strong>161+ indexed URLs</strong> with rich structured data that AI answer engines can parse, attribute, and cite.</p>

        <p>Structured data is especially powerful when sent from a Node.js server like Express. See our guide on <a href="/docs/express-mongodb-prompt">scaffolding Express.js &amp; MongoDB APIs</a> to learn how to build the backend that serves this data.</p>
Enter fullscreen mode Exit fullscreen mode

This article was originally published with extended interactive STCO schemas on AI Prompt Architect.

Top comments (1)

Collapse
 
seogeotech profile image
SeoGeo Tech

Great guide. One issue I’ve seen in React apps is that teams add JSON-LD correctly on initial render, but forget to update it when client-side routing changes the page content.

For dynamic routes, it’s important to make sure the structured data always matches the visible page and that old schema markup is removed or replaced rather than duplicated.

Do you generally recommend handling JSON-LD at the route level, or centralizing it in a shared SEO component?