Structured Data (JSON-LD) for AI and Search Engines in Astro

Every once in a while, I like to take another look at SEO strategies, since they change over time… And I realized I hadn’t done anything to embrace the current world of AI searches. The main thing I learned and added to my blogs is structured data using JSON-LD.

This makes for nicer looking Google results, better search previews, and all those good things.

Edit 09/09/25: In the first version, I didn’t escape the quotes, which was quickly spotted later in a security check. Oops!

How to Add JSON-LD in Astro

Add a <script type="application/ld+json"> block to your main head component. For a blog post, use the BlogPosting schema from schema.org.

⚠️ Security Note: Always use proper templating and escaping when adding dynamic data to JSON-LD. Never use plain string interpolation as it can lead to XSS vulnerabilities.

<script type="application/ld+json" set:html={JSON.stringify({
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": title,
"description": description,
"image": [
new URL('/og-default.jpg', Astro.url).href
],
"author": {
"@type": "Person",
"name": "Tim Eaton"
},
"publisher": {
"@type": "Organization",
"name": "yakbrother.dev",
"logo": {
"@type": "ImageObject",
"url": new URL('/favicon-96x96.png', Astro.url).href
}
},
"mainEntityOfPage": {
"@type": "WebPage",
"@id": Astro.url.href
}
})}
></script>

❌ Insecure Method (Don’t Use):

<!-- DON'T DO THIS - Vulnerable to XSS attacks -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": "{title}",
"description": "{description}",
"image": [
"{image ? image : '/og-default.jpg'}"
]
}
</script>

The secure method uses:

In general…

Done!

This was a quick and easy way to update my site for today’s searches. If you’re using Cursor, it can automatically add structured quite easily, taking the data entry work out of your day.