<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: CleverUtils</title>
    <description>The latest articles on DEV Community by CleverUtils (@cleverutils_seo_4d16eef75).</description>
    <link>https://dev.to/cleverutils_seo_4d16eef75</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4003635%2Fbb4938a9-0627-41c3-84ad-44c169ac709c.png</url>
      <title>DEV Community: CleverUtils</title>
      <link>https://dev.to/cleverutils_seo_4d16eef75</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cleverutils_seo_4d16eef75"/>
    <language>en</language>
    <item>
      <title>Writing JSON-LD structured data by hand, and when to stop</title>
      <dc:creator>CleverUtils</dc:creator>
      <pubDate>Fri, 26 Jun 2026 08:51:02 +0000</pubDate>
      <link>https://dev.to/cleverutils_seo_4d16eef75/writing-json-ld-structured-data-by-hand-and-when-to-stop-31jn</link>
      <guid>https://dev.to/cleverutils_seo_4d16eef75/writing-json-ld-structured-data-by-hand-and-when-to-stop-31jn</guid>
      <description>&lt;p&gt;I maintain a handful of small marketing sites, and for years my structured-data workflow was embarrassing: copy a JSON-LD block from an old project, find-and-replace the values, paste it into the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;, and hope. It worked until it didn't — a trailing comma here, a wrong &lt;code&gt;@type&lt;/code&gt; there, and the rich result silently disappears for a month before anyone notices.&lt;/p&gt;

&lt;p&gt;Structured data is one of those things that's easy to add and genuinely hard to add &lt;em&gt;correctly&lt;/em&gt;. These are the notes I wish someone had handed me earlier.&lt;/p&gt;

&lt;h2&gt;
  
  
  What JSON-LD actually is
&lt;/h2&gt;

&lt;p&gt;JSON-LD is just a &lt;code&gt;&amp;lt;script type="application/ld+json"&amp;gt;&lt;/code&gt; block that describes your page in a vocabulary search engines understand (&lt;a href="https://schema.org/" rel="noopener noreferrer"&gt;schema.org&lt;/a&gt;). It doesn't change what a human sees; it changes what a machine is allowed to say about your page — the star ratings, the FAQ accordions, the breadcrumb trails that show up in results.&lt;/p&gt;

&lt;p&gt;A minimal Article block is unintimidating:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@context"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://schema.org"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Article"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"headline"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Writing JSON-LD by hand"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"datePublished"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-06-26"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"author"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Person"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Jane Dev"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The trouble starts when you have five page types, each needing a slightly different shape, and you're maintaining all of them by hand across a dozen templates.&lt;/p&gt;

&lt;h2&gt;
  
  
  The three mistakes I kept making
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Invalid JSON.&lt;/strong&gt; A trailing comma after the last property, a smart-quote that snuck in from a CMS, an unescaped quote inside a string. The block looks fine to a human and is invisible garbage to a parser. Worst of all, nothing errors — the page just renders without the markup.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Schema that disagrees with the page.&lt;/strong&gt; If your markup claims a &lt;code&gt;Product&lt;/code&gt; has a &lt;code&gt;4.8&lt;/code&gt; rating but there's no visible review anywhere on the page, you're not getting a rich result — you're risking a manual action. Markup has to describe what's actually on the page, not what you wish were on it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Invented properties.&lt;/strong&gt; &lt;code&gt;@type: "Article"&lt;/code&gt; does not have a &lt;code&gt;readingTime&lt;/code&gt; field no matter how much you want it to. Made-up properties are silently ignored, which means you think you shipped something you didn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I work now
&lt;/h2&gt;

&lt;p&gt;Two changes fixed most of it.&lt;/p&gt;

&lt;p&gt;First, I stopped writing the JSON by hand for new page types. I reach for &lt;a href="https://cleverutils.net/tools/schema-markup-generator-json-ld-structured-data/" rel="noopener noreferrer"&gt;a JSON-LD generator&lt;/a&gt; that knows the required-versus-recommended fields per type when I need a clean block for a type I don't add often, because it won't let me forget a required property or typo an &lt;code&gt;@type&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Second, I validate in two passes, because "valid JSON" and "valid schema" are different questions. For the first, any &lt;a href="https://cleverutils.net/tools/json-formatter/" rel="noopener noreferrer"&gt;browser-based JSON formatter&lt;/a&gt; flags a stray comma or bad nesting in a second. For the second, Google's &lt;a href="https://search.google.com/test/rich-results" rel="noopener noreferrer"&gt;Rich Results Test&lt;/a&gt; tells you whether the block is actually &lt;em&gt;eligible&lt;/em&gt; for a rich result, which is the only thing that matters in the end.&lt;/p&gt;

&lt;h2&gt;
  
  
  A workflow that survives contact with reality
&lt;/h2&gt;

&lt;p&gt;Here's the checklist I actually follow now, in order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Generate or hand-write the block for the page type.&lt;/li&gt;
&lt;li&gt;Paste it through a JSON validator — catch the syntax errors first, they're the cheap ones.&lt;/li&gt;
&lt;li&gt;Run it through the Rich Results Test against the live (or staged) URL.&lt;/li&gt;
&lt;li&gt;Eyeball that every claim in the markup is &lt;em&gt;visibly true&lt;/em&gt; on the page.&lt;/li&gt;
&lt;li&gt;Only then ship it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It sounds like a lot. It takes about ninety seconds once it's a habit, and it has saved me from shipping broken markup more times than I'd like to admit.&lt;/p&gt;

&lt;h2&gt;
  
  
  When NOT to bother
&lt;/h2&gt;

&lt;p&gt;Structured data isn't free — it's another thing you have to keep in sync with the page. If your content changes often and your markup doesn't, you'll drift into the second mistake above, and &lt;em&gt;wrong&lt;/em&gt; schema is worse than &lt;em&gt;no&lt;/em&gt; schema. For a brochure page that never changes, mark it up once and forget it. For a fast-moving page nobody will maintain, sometimes the honest call is to skip it.&lt;/p&gt;

&lt;p&gt;None of this is advanced. It's mostly about treating markup like code — generate it from something that knows the rules, validate it before it ships, and never claim something the page doesn't actually show.&lt;/p&gt;

</description>
      <category>seo</category>
      <category>webdev</category>
      <category>json</category>
      <category>html</category>
    </item>
  </channel>
</rss>
