Local Services GEO Guide
Most local service businesses are invisible to AI search. This guide shows you why, and how to fix it, whether you serve one postcode or an entire city.
JSON-LD schema markup, structured data, and location enrichment to make local service businesses visible in ChatGPT, Perplexity, and Google AI Overviews.
Without geo data
What AI sees: nothing matchable. Zero service area or proximity queries answered.
With GeoEnrich
What AI sees: matchable for 25+ query types including "plumber near me open now", "emergency electrician in De Pijp", "dentist accepting new patients in Oud-Zuid".
GeoEnrich generates the right column automatically from an address. One API call.
Quick Start
Add this JSON-LD to your local service website and you're immediately visible to AI search engines:
{
"@context": "https://schema.org/",
"@type": "Plumber",
"name": "Amsterdam Emergency Plumbing Co.",
"description": "24/7 emergency plumbing services in Amsterdam and surrounding areas. Specializing in burst pipes, blocked drains, and water heater repairs.",
"image": "https://example.com/logo.png",
"address": {
"@type": "PostalAddress",
"streetAddress": "Prinsengracht 123",
"addressLocality": "Amsterdam",
"postalCode": "1015 DJ",
"addressCountry": "NL"
},
"telephone": "+31 20 555 1234",
"areaServed": {
"@type": "GeoShape",
"geoMidpoint": {
"@type": "GeoCoordinates",
"latitude": 52.3676,
"longitude": 4.9041
},
"geoRadius": "15",
"addressCountry": "NL"
},
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.8",
"ratingCount": "247"
},
"priceRange": "€50-€250"
}
Want the full version with service areas, professional profiles, and location enrichment? See the complete local business schema in the examples below.
How People Search for Local Services Through AI
Your customers don't search "plumber Amsterdam" anymore. They ask conversational, intent-filled questions:
- "best plumber in Amsterdam available today"
- "emergency electrician near me open on Sunday at midnight"
- "dentist in Berlin that speaks English and takes my insurance"
- "affordable lawyer for rental disputes in Rotterdam with quick consultation"
- "dog groomer near Vondelpark with good reviews and availability this week"
- "heating engineer in Amsterdam who handles commercial buildings"
- "24/7 locksmith in Dutch that can come within an hour"
These queries have geographic intent (location), temporal intent (availability), service quality intent (reviews, credentials), and operational intent (hours, pricing).
AI models trained on structured data can answer these if your business information is clear. Vague business descriptions, missing hours, no service area, and hidden pricing make you invisible to AI search.
LocalBusiness Schema for Local Services
LocalBusiness is the foundation. It tells AI: "Here's a business that serves a geographic area."
Common Subtypes:
- Plumber, Electrician, Locksmith
- Dentist, LegalService, AutoRepair
- HairSalon, Florist, Photographer
- Cleaner, Contractor
Required Fields (Minimum):
@type: The subtype (e.g., "Plumber")name: Your business nameaddress: Full postal addresstelephone: Contact numberareaServed: Geographic coverage (neighborhoods, postcodes, or GeoShape)openingHoursSpecification: When you operate (important for 24/7, weekend, emergency services)
Highly Recommended Fields:
description: What you do and your specialtyaggregateRating: Review count and scorepriceRange: Cost indicator (€50-€200)paymentAccepted: How you take paymentknowsLanguage: Languages you speakhasOfferCatalog: Detailed pricing for specific servicesadditionalProperty: Response time, service area radius, certifications
Service Area Definition
Use GeoShape with geoRadius for the most precise service area definition. A 15km radius means you're honest about limitations. AI can't tell if you serve 1km or 50km without this field.
Service Schema: Define What You Offer
LocalBusiness tells AI you exist. Service schema tells AI what you actually do and how much it costs.
{
"@context": "https://schema.org/",
"@type": "Service",
"name": "Emergency Drain Unblocking",
"provider": {
"@type": "LocalBusiness",
"name": "Amsterdam Emergency Plumbing Co."
},
"serviceType": "PlumbingService",
"areaServed": {
"@type": "GeoShape",
"geoRadius": "15km"
},
"offers": {
"@type": "Offer",
"priceCurrency": "EUR",
"price": "85.00"
},
"hoursAvailable": {
"@type": "OpeningHoursSpecification",
"dayOfWeek": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
"opens": "00:00",
"closes": "23:59"
}
}
Local services often have variable pricing. Use hasOfferCatalog with specific service pricing tiers. AI models use this to answer "How much does it cost?" with specificity.
Professional Profile Schema
For service-based businesses where individual expertise matters (dentists, lawyers, hairdressers, mechanics), mark professionals with Person schema.
{
"@context": "https://schema.org/",
"@type": "Person",
"name": "Dr. Helena Mueller",
"jobTitle": "Dentist",
"worksFor": {
"@type": "Dentist",
"name": "Amsterdam Dental Clinic"
},
"hasCredential": [
{
"@type": "EducationalOccupationalCredential",
"name": "Doctor of Dental Medicine",
"issuingOrganization": {
"@type": "EducationalOrganization",
"name": "University of Amsterdam"
}
}
],
"knowsLanguage": ["en", "nl", "de", "fr"],
"description": "Specialized in cosmetic dentistry, implants, and restorative work. 12 years experience."
}
This tells AI: Dr. Mueller is qualified, speaks your language, has great reviews, and specializes in certain treatments.
Enriching Local Services with Location Data
Beyond basic address, AI wants context: Where are you in the city? What's nearby?
Combine GeoShape with semantic context and additionalProperty fields:
service_area_radius_km: Explicit radius you serveaverage_response_time_minutes: Critical for emergency services queriescustomer_parking_available: For services with a physical officenearest_public_transit: Accessibility contextaccessibility_score: Wheelchair accessible entrance, accessible vanservice_types_offered: Emergency, scheduled, preventativeindustries_served: Residential, Commercial, Industrialcertifications_held: Relevant professional certifications
Use MapAtlas GeoEnrich API to automatically enrich service area data: get neighborhood coverage in your radius, identify demographic segments served, find nearby amenities for context, and validate service area radius accuracy.
Content Structure for AI Readability
Structured data isn't enough. Your actual website content must match.
Homepage should include:
- Clear service description (H1), "24/7 Emergency Plumbing in Amsterdam and Zaandam"
- Service area callout, Map of coverage area or list of neighborhoods
- Hours and availability, "Available 24/7 including weekends"
- Pricing section, At least price range, ideally specific service pricing
- Reviews/testimonials, At least 10+ reviews visible
- Contact and CTA, Phone, email, online form
FAQ Content Structure
AI models learn from FAQ content. Include these Q&As:
- "Do you offer emergency service?", yes/no with callout fee
- "What areas do you cover?", specific neighborhoods
- "How quickly can you respond?", average response time
- "How much does X cost?", specific pricing
- "Are you available on weekends?", hours and rates
- "What languages do you speak?", specific languages
- "Do you handle commercial work?", yes/no
Each FAQ item should match your schema data. Don't contradict your JSON-LD in prose.
AI Citation Patterns
How do AI models decide which service business to recommend? Five factors dominate:
1. Review Signals (Highest Weight)
Review count, recency, rating, and specificity. The best reviews mention your service area, response time, and professionalism. Example: "Called at 2 AM with burst pipe. They arrived within 50 minutes from central Amsterdam. Fixed it properly, professional crew, reasonable pricing."
2. Availability and Operating Hours
AI models favor businesses that match the query intent. "Emergency plumber" searches prioritize services with 24/7 hours. "Sunday dentist" searches require Sunday hours in schema.
3. Pricing Transparency
Services with visible pricing rank higher than vague "call for quote" listings. Include price ranges and specific service pricing.
4. Credential Specificity
Licensed professionals rank over unlicensed. Certifications and specializations in schema + content build trust.
5. Service Area Clarity
Specific geographic service area beats "nationwide." GeoShape with radius beats text description. Named neighborhoods beat vague city coverage.
Common Mistakes
Mistake 1: No Service Area Defined
AI can't tell if you serve 1km or 50km from your office without areaServed.
Mistake 2: Missing Opening Hours
An emergency plumber with no 24/7 marking is invisible for "24/7 plumber" searches. Add full openingHoursSpecification for all days including weekends.
Mistake 3: No Pricing Information
Hidden pricing means trust loss. Add priceRange at minimum, or hasOfferCatalog with specific service pricing.
Mistake 4: No Credentials or Certifications
"Dr." is just a title. Add hasCredential with education and specialization details.
Mistake 5: Template Descriptions
"Providing quality dental care in a friendly environment" applies to 10,000 dentists. Describe your actual specializations and service area.
Mistake 6: Missing Response Time
"Emergency" means nothing without response time clarity. Add additionalProperty with average_response_time_minutes.
Mistake 7: Conflicting Data
If your schema says 9:00-17:00 but your website says "We're open 24/7 for emergency calls", AI models catch the contradiction and distrust your data.
Testing and Validation
Step 1: Validate JSON-LD Syntax
Use Schema.org validator at validator.schema.org to check for missing required properties, type mismatches, and syntax errors.
Step 2: Test AI Visibility with AEO Checker
Use AEO Checker at /ai-seo-checker to check if your business data is understood correctly, verify service area is recognized, confirm opening hours are parsed, and see how AI models will interpret your schema.
Step 3: Manual AI Testing
Ask ChatGPT or Perplexity:
- "What's the best plumber in Amsterdam available on Sunday?"
- "Find me an electrician in Amsterdam open at midnight"
- "Recommend a dentist in Berlin that speaks English"
See if your business appears and is described accurately.
Step 4: Check for Consistency
Does your JSON-LD match your website content? Are hours accurate across all channels (Google, website, schema)? Is pricing consistent?
Step 5: Monitor and Update
Review schema quarterly. Update opening hours if they change. Add new services to hasOfferCatalog. Refresh reviews in aggregateRating.
Automate this at scale
Writing schema manually works for one listing. What about thousands?
The MapAtlas GeoEnrich API adds coordinates, nearby POIs, transit access, neighbourhood context, and schema-ready geo data to every listing automatically, one API call per listing, at any scale.