NorthLuma blog · · 8 min read
Local business website checklist: the details that turn visits into phone calls
A practical checklist for local business sites: NAP that matches your Google Business Profile, hours, directions, tel: links and LocalBusiness markup.
A local business website has one job most of the time: get someone who is standing in a kitchen with a leaking pipe, or deciding where to eat tonight, to call, book or turn up. Most of the work that serves that job is not design. It is getting a handful of facts right, keeping them identical everywhere, and making them easy to act on from a phone.
The checklist below is meant to be run before launch. Each item says what to check, why, and where the rule comes from, so you can explain it to a client who asks.
1. Name, address and phone match the Google Business Profile exactly
Pick one canonical version of the business name, address and phone number (NAP) and use it on the site, in the Google Business Profile, on invoices and on the van. Google's guidelines for representing your business ask owners to "represent your business as it's consistently represented and recognized in the real world across signage, stationery, and other branding", and say the name "should reflect your business's real-world name, as used consistently on your storefront, website, stationery, and as known to customers."
What to check:
- The business name on the site is the same string as on the profile. No "Best Plumber Springfield" keyword variant in one place and the legal name in another. The same guidelines list marketing taglines, service descriptions and location information as things the profile name must not include.
- The address is formatted the same way, including suite numbers.
- The phone number is the one on the profile. Google asks for "a local phone number instead of a central call center helpline number whenever possible" and says the number "must be under the direct control of the business."
Our recommendation: keep NAP in one file in the codebase and render it everywhere from there, so the footer, contact page and structured data cannot drift apart. The code sample below does this.
2. Hours, including holiday hours
Opening hours belong on the site in plain text, near the phone number, and they must match the profile. Google's own tips to improve your local ranking list "your business hours, including special store hours" as part of a complete profile, and state that "businesses with complete and accurate info are more likely to show up in local search results."
Holiday hours are where sites go stale. On the profile side, Google's help page on special hours lists holidays and special events as uses, and says "it's a good idea to confirm your hours for official holidays, even if they're the same as your regular hours." The same page says to mark the business as temporarily closed if it will be closed for 7 or more days in a row.
On the website side, put a dated note above the regular hours a week or two before each holiday, and remove it afterwards. Put the reminder in the client's calendar.
3. A map and a directions link that work on a phone
For a storefront, add a directions link that opens the user's maps app. Google Maps URLs give you a documented format for this: https://www.google.com/maps/dir/?api=1 plus a URL-encoded destination. The docs say "you don't need a Google API key to use Maps URLs" and that api=1 is required.
If the client wants an embedded map as well, Google Maps has a "Share or embed map" option that produces copy-and-paste HTML, described in the Maps help page on sharing. Opinion: the text link is the part people use on mobile, and an embed is an iframe that adds weight. If you embed one, put it lower on the contact page.
4. Click-to-call with a real tel: link
Every visible phone number should be a link with a tel: URL. MDN's anchor element reference lists telephone numbers among the URL schemes href supports and notes that "cellular devices autodial the number", while desktop operating systems may hand it to a calling app.
Use the international format with the country code in the href, and the locally familiar format in the visible text:
<a href="tel:+15415550142">(541) 555-0142</a>
Put the call link in the header on mobile, and once more next to the hours. A button that says "Call (541) 555-0142" is clearer than one that says "Contact", because it tells the visitor exactly what will happen when they tap.
5. The phone number is text, not part of an image
Phone numbers baked into a hero image or logo cannot be tapped, copied or read by a screen reader, and they do not resize. The WCAG success criterion on images of text puts it in four words: "use text instead of pictures of text." It exempts logotypes, so the logo can stay an image, but the phone number next to it should be live text with a tel: link.
6. Service area, stated plainly
Service businesses that travel to customers should say where they go. Google's service area help page says you can set "up to 20 service areas based on the cities, postal codes, or other areas you serve", that the overall area "shouldn't be more than about 2 hours of driving time from where your business is based", and that if you don't serve customers at your address you should remove it from the profile.
On the site, list the same towns in a sentence on the home page and the contact page. Opinion: a short list of real towns is more useful to a visitor than a radius on a map, and it gives you the words people actually search with.
7. Fast on a mid-range phone
Most of your client's visitors will be on mobile data. Google's Web Vitals guidance gives the targets: Largest Contentful Paint within 2.5 seconds, Interaction to Next Paint of 200 milliseconds or less, and Cumulative Layout Shift of 0.1 or less, measured at the 75th percentile of page loads. The usual offenders on small-business sites are an oversized hero photo, a slider, a chat widget and several font files. A static site with sized, compressed images and no carousel usually clears these without heroics.
8. A first screen that answers three questions
Opinion: on a phone, the first screen should say what the business does, where, and how to reach it, without scrolling. For a plumber that is a heading like "Plumber in Springfield, Eugene and Coburg", one sentence on what they fix, and a call button. Testimonials, the team photo and the company history can come after.
9. LocalBusiness structured data that matches the page
Structured data does not replace any of the above, but it states the same facts in a machine-readable form. Google's LocalBusiness structured data docs list name and address as the required properties, and telephone, url, openingHoursSpecification, geo and priceRange among the recommended ones. For telephone they say to "include the country code and area code" in the number. They also recommend using "the most specific LocalBusiness sub-type possible." Schema.org has many sub-types; a plumber is Plumber, under HomeAndConstructionBusiness.
For holiday closures, Google's docs show validFrom and validThrough on an OpeningHoursSpecification for seasonal closures. Schema.org also defines specialOpeningHoursSpecification, but it is not in Google's list of supported properties, so keep holiday hours current on the profile and the page itself.
Here is one way to do it in a Next.js App Router project. The Next.js JSON-LD guide recommends rendering a script tag in a page or layout component and replacing < with its unicode escape. This builds with output: "export" and the JSON in the generated HTML parses cleanly.
// lib/business.ts
// One source of truth for name, address, phone and hours.
// Copy these values from the Google Business Profile, character for character.
export const business = {
name: "Example Plumbing",
phoneDisplay: "(541) 555-0142",
phoneE164: "+15415550142",
street: "412 Harbor Road",
city: "Springfield",
region: "OR",
postalCode: "97477",
country: "US",
url: "https://www.example.com/",
serviceArea: ["Springfield", "Eugene", "Coburg"],
};
// app/page.tsx
import { business as b } from "../lib/business";
const address = `${b.street}, ${b.city}, ${b.region} ${b.postalCode}`;
const directionsUrl =
"https://www.google.com/maps/dir/?api=1&destination=" + encodeURIComponent(`${b.name}, ${address}`);
const jsonLd = {
"@context": "https://schema.org",
"@type": "Plumber",
name: b.name,
url: b.url,
telephone: b.phoneE164,
address: {
"@type": "PostalAddress",
streetAddress: b.street,
addressLocality: b.city,
addressRegion: b.region,
postalCode: b.postalCode,
addressCountry: b.country,
},
areaServed: b.serviceArea.map((name) => ({ "@type": "City", name })),
openingHoursSpecification: [
{
"@type": "OpeningHoursSpecification",
dayOfWeek: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
opens: "07:30",
closes: "17:30",
},
{
"@type": "OpeningHoursSpecification",
dayOfWeek: "Saturday",
opens: "09:00",
closes: "13:00",
},
],
};
export default function Home() {
return (
<main className="mx-auto max-w-3xl p-6">
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd).replace(/</g, "\\u003c") }}
/>
<h1 className="text-3xl font-bold">Plumber in Springfield, Eugene and Coburg</h1>
<p>Leaks, blocked drains and water heaters. Same-day visits on weekdays.</p>
<a href={`tel:${b.phoneE164}`} className="mt-4 inline-block rounded bg-blue-700 px-5 py-3 text-white">
Call {b.phoneDisplay}
</a>
<address className="mt-6 not-italic">
{b.name}
<br />
{address}
<br />
<a href={`tel:${b.phoneE164}`}>{b.phoneDisplay}</a>
<br />
<a href={directionsUrl}>Get directions</a>
</address>
</main>
);
}
The generated out/index.html contains the address-block call link and the directions link as plain HTML:
<a href="tel:+15415550142">(541) 555-0142</a>
<a href="https://www.google.com/maps/dir/?api=1&destination=Example%20Plumbing%2C%20412%20Harbor%20Road%2C%20Springfield%2C%20OR%2097477">Get directions</a>
Two cautions. First, the markup must describe what is on the page; Google's guidelines for this feature warn that violations can lead to a manual action. Second, Google lists address as required for LocalBusiness rich results. A service-area business that hides its address on the profile has to decide whether to publish it on the site at all. Our recommendation: keep the site, the markup and the profile consistent with each other, and do not publish an address you have deliberately hidden elsewhere.
After deploying, run the page through the Rich Results Test linked from Google's docs and fix any critical errors it reports.
The short version to paste into a launch ticket
- NAP identical on site, profile and structured data, rendered from one file
- Regular hours in text; holiday hours set on the profile and noted on the site
- Directions link using a Maps URL; embed optional and below the fold
- Every phone number is a
tel:link in international format - No phone numbers or hours inside images
- Service towns listed in text, matching the profile
- Core Web Vitals checked on a phone, not only on a desktop
- First screen: what, where, call button
- LocalBusiness JSON-LD with the most specific sub-type, validated after deploy
If you want a starting point that already keeps the site's text in one place, NorthLuma generates a small-business site from a short description, and says generating and previewing is free with no signup. The pricing page has the current price and availability of Pro Source. The docs describe all of the site's text living in a single lib/site-content.ts file, which suits the one-file habit described above.
Sources
- Google Business Profile Help: Guidelines for representing your business on Google
- Google Business Profile Help: Tips to improve your local ranking on Google
- Google Business Profile Help: How to set Special hours
- Google Business Profile Help: Manage your service areas for service-area and hybrid businesses
- Google Search Central: Local Business (LocalBusiness) structured data
- Schema.org: LocalBusiness
- Schema.org: Plumber
- MDN: The anchor element (tel: links)
- Google Maps URLs: Get started
- Google Maps Help: Share, send, or print directions from Google Maps
- W3C WAI: Understanding Success Criterion 1.4.5 Images of Text
- web.dev: Web Vitals
- Next.js docs: How to implement JSON-LD in your Next.js application
- NorthLuma builder
- NorthLuma docs
- NorthLuma pricing
NorthLuma team. Facts and sources last checked Oct 16, 2026; next review due by Jan 18, 2027. Found something out of date? Email [email protected].