Dev.to WebDev 🛠 Dev 👁 0 📖 4 min read

Local schema for a Birmingham service business

Most local business sites either have no structured data or three conflicting copies of it, one from the theme, one from an SEO plugin and one pasted in years ago. Done properly, it is a small amount of JSON-LD that tell

Local schema for a Birmingham service business

Infographic: a LocalBusiness schema checklist covering business type, address, opening hours, service area, sameAs and keeping to one source of markup

Most local business sites either have no structured data or three conflicting copies of it, one from the theme, one from an SEO plugin and one pasted in years ago. Done properly, it is a small amount of JSON-LD that tells search engines who you are, where you work and when you are open. This walkthrough covers what to include, how to output it from WordPress with one small snippet, and the mistakes that cause most of the trouble.

One caveat first. Structured data does not guarantee a rich result, and Google has no special display for LocalBusiness markup on its own. What it does is remove guesswork. Your name, address, phone number and hours are stated in a format machines read reliably, and they can be checked against your Google Business Profile.

Pick the most specific type

LocalBusiness is a parent type with many children. Use the closest match, such as Plumber, Electrician, AccountingService, LegalService or HVACBusiness. If nothing fits, ProfessionalService is a sensible general choice. A vague type is not wrong, but a specific one says more.

The properties that matter

For most service businesses, these are enough:

  • name, url, telephone, image and logo, matching your site and profiles exactly.
  • address as a PostalAddress, even if you hide it on your Google profile because you travel to customers.
  • openingHoursSpecification, using the same hours you publish everywhere else.
  • areaServed, listing the places you cover, which matters for service area businesses.
  • sameAs, an array of your real profiles (Business Profile, LinkedIn, Facebook and so on).
  • @id, a stable identifier so other markup on the page can refer to the business.

An example for the home page

Here is a placeholder for a heating engineer in Birmingham. Swap in your own details, and keep every value identical to what customers see on the page.

{
  "@context": "https://schema.org",
  "@type": "HVACBusiness",
  "@id": "https://example-heating.co.uk/#business",
  "name": "Example Heating",
  "url": "https://example-heating.co.uk/",
  "telephone": "+44 121 000 0000",
  "image": "https://example-heating.co.uk/images/van.jpg",
  "address": {
    "@type": "PostalAddress",
    "streetAddress": "1 Example Street",
    "addressLocality": "Birmingham",
    "addressRegion": "West Midlands",
    "postalCode": "B1 1AA",
    "addressCountry": "GB"
  },
  "openingHoursSpecification": [{
    "@type": "OpeningHoursSpecification",
    "dayOfWeek": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
    "opens": "08:00",
    "closes": "17:30"
  }],
  "areaServed": [
    { "@type": "City", "name": "Birmingham" },
    { "@type": "City", "name": "Solihull" }
  ],
  "sameAs": ["https://www.linkedin.com/company/example-heating/"]
}

Output it from WordPress

A plugin can do this, but a short snippet keeps it in one place that you control. Put it in a small must-use plugin or your child theme, and only print it on the home page.

add_action( 'wp_head', function () {
    if ( ! is_front_page() ) {
        return;
    }
    $schema = array(
        '@context' => 'https://schema.org',
        '@type'    => 'HVACBusiness',
        '@id'      => home_url( '/#business' ),
        'name'     => 'Example Heating',
        'url'      => home_url( '/' ),
        'telephone' => '+44 121 000 0000',
        // ...address, hours, areaServed and sameAs as above.
    );
    echo '<script type="application/ld+json">'
        . wp_json_encode( $schema, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE )
        . '</script>' . "\n";
}, 20 );

Building the array in PHP and letting wp_json_encode handle escaping is safer than pasting a hand-written string, because an unescaped quote in a business name will break the whole block.

Mistakes to avoid

  1. Duplicate markup. View the page source and search for application/ld+json. If your SEO plugin, your theme and your snippet each print a LocalBusiness block, switch two of them off.
  2. Details that disagree. If your opening hours or phone number differ between the schema, the page and your Business Profile, you have created the confusion the markup was meant to remove.
  3. Marking up your own reviews. Google does not show review stars for a business that marks up reviews about itself, so leave aggregateRating out unless the reviews come from a third party and are shown on the page.
  4. Marking up things that are not visible. Structured data should describe content people can see.
  5. Never updating it. Change your hours, number or address in one place, then check the schema as part of the same job.

Test it

Paste the page address into the Schema Markup Validator at validator.schema.org to check the syntax and property names. Google's Rich Results Test is also worth a look, but it only reports types that qualify for rich results, so an empty result for LocalBusiness is normal. After any change, fetch the page again and confirm the output has exactly one business block.

Keep it in context

Schema is one small part of local visibility. It works best alongside a complete Business Profile, consistent details across directories and a useful page for each service and area. If you would like a second pair of eyes on the whole picture, our Birmingham SEO team works through all of it, starting with a free audit.

Rocky V is Head of Operations at DigitalCave, a digital marketing agency in Birmingham's Jewellery Quarter.

📰 Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.