<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[DigitalCave Dev Notes]]></title><description><![CDATA[DigitalCave Dev Notes]]></description><link>https://digitalcave.hashnode.dev</link><image><url>https://cdn.hashnode.com/uploads/logos/6adb807d998dc4e227bce568/45cf27bc-9882-4a5a-9eb6-bf0beff35c90.png</url><title>DigitalCave Dev Notes</title><link>https://digitalcave.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Wed, 28 Oct 2026 13:24:31 GMT</lastBuildDate><atom:link href="https://digitalcave.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[LocalBusiness structured data for small business sites: a working JSON-LD example]]></title><description><![CDATA[A working LocalBusiness JSON-LD example for small business websites, with what to include, what to leave out and how to validate it.]]></description><link>https://digitalcave.hashnode.dev/localbusiness-structured-data-for-small-business-sites-a-working-json-ld-example</link><guid isPermaLink="true">https://digitalcave.hashnode.dev/localbusiness-structured-data-for-small-business-sites-a-working-json-ld-example</guid><category><![CDATA[SEO]]></category><category><![CDATA[json]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[WordPress]]></category><dc:creator><![CDATA[DigitalCave]]></dc:creator><pubDate>Fri, 23 Oct 2026 15:47:55 GMT</pubDate><content:encoded><![CDATA[<p>Structured data will not lift a local business to the top of the map pack on its own. What it does is remove ambiguity. It tells search engines, in a format they do not have to guess at, exactly who the business is, where it is, when it opens and which other profiles belong to it. For a small business with a handful of directory listings, a Google Business Profile and a website, that consistency matters.</p>
<p>This post walks through a LocalBusiness JSON-LD block we would be happy to ship, explains each property, and covers the mistakes we see most often when auditing small business sites.</p>
<h2>Pick the most specific type you can</h2>
<p><code>LocalBusiness</code> is the parent type, but schema.org has dozens of more specific subtypes: <code>Dentist</code>, <code>Plumber</code>, <code>Bakery</code>, <code>AccountingService</code>, <code>HairSalon</code>, <code>AutoRepair</code> and many more. Use the most specific one that genuinely describes the business. If nothing fits, <code>LocalBusiness</code> itself is fine. Do not stack unrelated types to try to rank for more things.</p>
<h2>A complete example</h2>
<p>Here is a block for a fictional bakery. Swap the values for your own.</p>
<pre><code class="language-json">{
  "@context": "https://schema.org",
  "@type": "Bakery",
  "@id": "https://www.examplebakery.co.uk/#business",
  "name": "Example Bakery",
  "url": "https://www.examplebakery.co.uk/",
  "logo": "https://www.examplebakery.co.uk/images/logo-512.png",
  "image": [
    "https://www.examplebakery.co.uk/images/shopfront-1200x900.jpg",
    "https://www.examplebakery.co.uk/images/counter-1200x900.jpg"
  ],
  "description": "Independent bakery making sourdough, pastries and celebration cakes daily.",
  "telephone": "+44 121 000 0000",
  "email": "hello@examplebakery.co.uk",
  "address": {
    "@type": "PostalAddress",
    "streetAddress": "12 High Street",
    "addressLocality": "Birmingham",
    "addressRegion": "West Midlands",
    "postalCode": "B13 9AA",
    "addressCountry": "GB"
  },
  "geo": {
    "@type": "GeoCoordinates",
    "latitude": 52.4448,
    "longitude": -1.8869
  },
  "openingHoursSpecification": [
    {
      "@type": "OpeningHoursSpecification",
      "dayOfWeek": ["Tuesday", "Wednesday", "Thursday", "Friday"],
      "opens": "08:00",
      "closes": "16:00"
    },
    {
      "@type": "OpeningHoursSpecification",
      "dayOfWeek": "Saturday",
      "opens": "08:00",
      "closes": "14:00"
    }
  ],
  "areaServed": {
    "@type": "City",
    "name": "Birmingham"
  },
  "priceRange": "££",
  "sameAs": [
    "https://www.facebook.com/examplebakery",
    "https://www.instagram.com/examplebakery"
  ]
}
</code></pre>
<p>It goes inside a <code>&lt;script type="application/ld+json"&gt;</code> tag, ideally in the <code>&lt;head&gt;</code>, though Google reads it anywhere on the page.</p>
<h2>Property by property</h2>
<p><strong><code>@id</code></strong>: A stable identifier for the business entity, usually the homepage URL plus a fragment. It lets other blocks on the site (a <code>WebSite</code>, an <code>Organization</code>, an <code>Article</code> publisher) point to the same entity instead of redefining it. Keep it identical on every page.</p>
<p><strong><code>name</code></strong>: The real trading name, exactly as it appears on signage and your Google Business Profile. Adding keywords here ("Example Bakery Birmingham Best Cakes") is the structured data version of keyword stuffing your business name, and it creates a mismatch with your other listings.</p>
<p><strong><code>address</code></strong>: Use the same formatting you use everywhere else. <code>addressCountry</code> takes an ISO code, so <code>GB</code> rather than "UK" or "United Kingdom". If you are a service area business that does not serve customers at your address, think carefully about whether to publish a street address at all. You can include locality and postcode only.</p>
<p><strong><code>geo</code></strong>: Coordinates with at least four or five decimal places. Drop a pin on the actual entrance, not the centre of the postcode.</p>
<p><strong><code>openingHoursSpecification</code></strong>: More expressive than the older <code>openingHours</code> string. Group days that share the same hours. For seasonal or holiday hours, add extra entries with <code>validFrom</code> and <code>validThrough</code> dates.</p>
<p><strong><code>telephone</code></strong>: International format is the safest choice. Make sure it matches the number on your Business Profile and the visible footer.</p>
<p><strong><code>sameAs</code></strong>: Links to profiles that are unambiguously this business: social accounts, a Companies House page if you are a limited company, major directory listings. This is one of the most useful properties for entity recognition because it ties scattered mentions together.</p>
<p><strong><code>priceRange</code></strong>: Optional and freeform. A short string like <code>££</code> is fine. Leave it out if it does not make sense for your business.</p>
<h2>What to leave out</h2>
<p><strong>Reviews of yourself.</strong> Since 2019 Google has not shown review stars for <code>LocalBusiness</code> or <code>Organization</code> markup where the business is collecting and marking up reviews about itself on its own site. Adding <code>aggregateRating</code> from a testimonials widget will not produce stars and can be treated as spammy markup. Leave it off.</p>
<p><strong>Things not visible on the page.</strong> Structured data should describe content a visitor can see. If your opening hours are not shown anywhere on the site, add them to the contact page as well as the markup.</p>
<p><strong>Duplicate, conflicting blocks.</strong> WordPress sites often end up with an SEO plugin generating an <code>Organization</code> block, the theme generating a <code>LocalBusiness</code> block and a reviews plugin adding a third. Check the rendered source and keep one authoritative entity.</p>
<h2>Multiple locations</h2>
<p>Each physical location should have its own page with its own <code>LocalBusiness</code> block, its own <code>@id</code> (for example <code>https://www.examplebakery.co.uk/moseley/#business</code>), its own address, phone and hours. Link each one back to the parent brand with <code>parentOrganization</code> pointing at the main organisation's <code>@id</code>. Do not list every branch address in a single block on the homepage.</p>
<h2>Adding it in WordPress without a plugin</h2>
<p>If you would rather not rely on a plugin, a small function in a child theme or must use plugin does the job:</p>
<pre><code class="language-php">add_action( 'wp_head', function () {
    if ( ! is_front_page() &amp;&amp; ! is_page( 'contact' ) ) {
        return;
    }
    $data = json_decode( file_get_contents( __DIR__ . '/localbusiness.json' ), true );
    echo '&lt;script type="application/ld+json"&gt;' . wp_json_encode( $data, JSON_UNESCAPED_SLASHES ) . '&lt;/script&gt;' . "\n";
} );
</code></pre>
<p>Keeping the data in a JSON file makes it easy to review and update without touching PHP.</p>
<h2>Validate, then keep it in sync</h2>
<p>Test with two tools: Google's Rich Results Test (which tells you whether Google can parse it and whether any rich result features apply) and the Schema Markup Validator at validator.schema.org (which checks it against the full vocabulary). Fix errors; read warnings and decide case by case.</p>
<p>The part people forget is maintenance. When you change your phone number, move premises or adjust your hours, update the markup, the visible page, your Business Profile and your main directory listings on the same day. Inconsistent details across those sources are a far bigger problem than missing schema.</p>
<p>Local visibility is mostly earned through a complete Business Profile, genuine reviews and a site that answers local searchers' questions. Structured data is the tidy foundation underneath. If you want a wider view of how it fits together, we have written up how we approach <a href="https://digitalcave.uk/local-seo-service-birmingham">local SEO for Birmingham businesses</a>.</p>
<p><em>Rocky V, Head of Operations at DigitalCave</em></p>
]]></content:encoded></item></channel></rss>