Why Service Business Websites Don't Rank on Google (Fix Guide)
TL;DR: Service business websites usually fail to rank for one of nine reasons, and almost none of them are about "needing more content". The real killers are: a broken canonical setup, missing or wrong schema, slow Core Web Vitals, thin city pages, no internal linking, a weak Google Business Profile, JavaScript-rendered content Google cannot see, duplicate page templates, and missing review signals. Fix the technical foundation first, then write more — or you are pouring content into a leaky bucket.
Key takeaways
- The #1 cause of "my pages are in the sitemap but not indexed" is a canonical tag pointing the wrong way. We literally just shipped a fix for this on our own site this week.
- Service business sites built on React/SPAs without pre-rendering can lose 20–40% of their organic ceiling because Google can not reliably render JavaScript.
- Page speed is now ranking factor #1 for mobile local searches. Below 75 PageSpeed score, you are getting filtered.
- Google Business Profile drives ~60% of local organic visibility. A perfect website with a weak GBP still loses.
- "Write more content" is the most common — and least useful — advice given to service businesses with ranking problems.
Table of contents
- How to tell if you actually have a ranking problem
- Reason 1: Your canonical tags are broken
- Reason 2: Your site is a JavaScript SPA with no pre-rendering
- Reason 3: Missing or wrong schema markup
- Reason 4: Slow Core Web Vitals on mobile
- Reason 5: Thin or templated city pages
- Reason 6: Zero internal linking strategy
- Reason 7: A weak Google Business Profile
- Reason 8: Duplicate title tags and meta descriptions
- Reason 9: No review velocity signal
- The 30-day fix-everything plan
- Frequently asked questions
How to tell if you actually have a ranking problem
Before assuming Google hates you, check the data:
- Search Console → Performance. Sort by impressions, not clicks. If you have impressions for the searches you care about but no clicks, you are ranking — just below the fold. If you have zero impressions, you are not in the index for those terms.
- Search Console → Indexing → Pages. Compare "Indexed" count vs your sitemap count. A gap of 5-10% is normal. A gap of 20%+ means you have an indexing problem.
site:yourdomain.comin Google. Quick way to see what Google has. If the count is way below your real page count, you have a discovery or canonical issue.
Now, the nine real reasons.
Reason 1: Your canonical tags are broken
This is the silent killer. If every page on your site has a <link rel="canonical" href="https://yoursite.com/" /> pointing back to the homepage, Google treats every URL as a duplicate and consolidates them. Your blog post, your city page, your service page — all collapsed into one.
We fixed exactly this bug on our own site last week. The sitemap had 57 URLs, but Google was only indexing 49 — because the index.html template hardcoded the homepage as the canonical, and our SPA never overrode it fast enough for Googlebot.
How to check:
- Open any non-homepage URL on your site.
- View page source (Ctrl+U / Cmd+U).
- Search for
canonical. - The
hrefshould match the URL you are on. Not the homepage.
How to fix:
- Static HTML sites: Edit each page's
<head>to set the correct canonical. - WordPress: Yoast or Rank Math auto-handles this. Make sure neither is set to "canonical to homepage" by accident.
- SPAs (React, Vue): Pre-render each route to static HTML at build time, with the correct canonical baked in. Client-side
document.querySelectorupdates happen after Googlebot decides what the canonical is.
For the SPA fix specifically, see the next section.
Reason 2: Your site is a JavaScript SPA with no pre-rendering
If your site is built in React, Vue, or any other client-side framework without server-side rendering or pre-rendering, Google has to execute JavaScript to see your content. Google can do this, but:
- It is slow (your pages enter a separate render queue, often delayed days or weeks)
- It is unreliable (Googlebot has render budget limits — long pages or heavy JS gets skipped)
- It is the wrong default for an SEO-focused site
How to check:
- Go to Google Search Console.
- Use the URL Inspection tool on a blog post or service page.
- Click "Test Live URL" → "View Tested Page" → "Screenshot".
- If the screenshot is blank or shows a loading spinner, Googlebot can not render your content reliably.
How to fix:
Three options, in order of effort:
- Pre-render at build time. A small script that visits every URL during your deploy and saves the rendered HTML. Tools:
vite-plugin-prerender,react-snap,puppeteer+ a custom script. This is what we did for our own site — solves 80% of the problem in a half-day of work. - Static site generation (SSG). Migrate to a framework that pre-builds every page: Astro, Next.js with
output: 'export', Gatsby. Bigger change, better long-term. - Server-side rendering (SSR). Next.js or Remix with SSR. Best for dynamic content, more infrastructure complexity.
For a service business site that does not change minute-by-minute, option 1 (pre-render at build time) is usually the right answer.
Reason 3: Missing or wrong schema markup
Schema is how you tell Google what your page is, not just what it says. For local service businesses, two schema types are non-negotiable:
LocalBusiness schema — on every page that represents your business:
{
"@context": "https://schema.org",
"@type": "LocalBusiness",
"name": "Your Business Name",
"image": "https://yoursite.com/photo.jpg",
"telephone": "+1-555-555-5555",
"address": {
"@type": "PostalAddress",
"streetAddress": "123 Main St",
"addressLocality": "Phoenix",
"addressRegion": "AZ",
"postalCode": "85001",
"addressCountry": "US"
},
"geo": {
"@type": "GeoCoordinates",
"latitude": 33.4484,
"longitude": -112.0740
},
"url": "https://yoursite.com",
"priceRange": "$",
"openingHoursSpecification": [...],
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.9",
"reviewCount": "127"
}
}
Service schema — on each service page:
{
"@context": "https://schema.org",
"@type": "Service",
"serviceType": "Artificial Turf Cleaning",
"provider": { "@type": "LocalBusiness", "name": "Your Business Name" },
"areaServed": { "@type": "City", "name": "Phoenix" },
"description": "Professional artificial turf cleaning..."
}
How to check: Run any page through Google's Rich Results Test. It will tell you exactly what schema it found and what is missing.
Most common mistakes:
- Schema for "Organization" instead of "LocalBusiness" (organization gets you no local benefit)
- Missing
aggregateRating(the star rating is what wins SERP space) priceRangeleft as the default placeholder- Schema present on the homepage only, missing from service and city pages
Reason 4: Slow Core Web Vitals on mobile
Google has been ranking by Core Web Vitals since 2021 and tightened the screws in 2024. The thresholds:
| Metric | "Good" | "Needs improvement" | "Poor" |
|---|---|---|---|
| LCP | < 2.5s | 2.5–4.0s | > 4.0s |
| INP | < 200ms | 200–500ms | > 500ms |
| CLS | < 0.1 | 0.1–0.25 | > 0.25 |
If any metric is "poor", you lose ranking weight. If two or more are "poor", you lose significant ranking weight.
How to check:
- Go to PageSpeed Insights.
- Test your homepage and a service page and a blog post.
- Look at the mobile scores, not desktop. Desktop is irrelevant for local search.
The usual fixes:
- LCP > 2.5s: Hero image is too large. Compress to WebP, max 200KB. Lazy-load below-the-fold images.
- INP > 200ms: Too much JavaScript on the main thread. Defer third-party scripts (chat widgets, analytics).
- CLS > 0.1: Images or ads without explicit width/height attributes, causing layout shift as they load.
For a service business site, getting all three into "Good" on mobile is a 4–12 hour engineering job. Not weeks.
Reason 5: Thin or templated city pages
City pages are the highest-ROI SEO move for service businesses if you do them right. The wrong way kills you with Google's Helpful Content update.
The wrong way:
/service-area/phoenix
/service-area/scottsdale
/service-area/tempe
Each page has the same template with the city name swapped. 300 words. No real local content. No photos. No specific service details.
Google sees these as doorway pages and either ignores them or actively penalizes the whole site.
The right way:
Each city page needs:
- At least 800 words of original content specific to that city
- A real local photo (not stock)
- City-specific service notes (e.g., "Phoenix's intense UV cycle means we recommend quarterly cleaning vs the standard biannual")
- Neighborhood callouts (e.g., "We service Arcadia, Biltmore, Paradise Valley...")
- Local reviews if you have them (use a structured-data review widget)
- Driving directions or map embed for the closest service area
Start with your top 3–5 cities. Prove the model. Then expand.
For the playbook on how to make city pages work without triggering Helpful Content, see our local SEO for service businesses page.
Reason 6: Zero internal linking strategy
Most service business sites have a navigation menu and that is it for internal linking. Google uses internal links to:
- Discover pages (you have to link to them to get them crawled)
- Pass authority between pages (the "link juice" model is still real)
- Understand topical relationships (which pages support which)
The minimum internal linking structure for a service business:
- Every blog post links to at least 1 service page and 2 other related blog posts
- Every service page links to the relevant city pages and 2 supporting blog posts
- Every city page links to the relevant service pages and the contact page
- The homepage links to all top-level service pages and the top 5 blog posts
This sounds tedious. It is. It is also one of the highest-ROI SEO actions you can take, and almost no service business does it well.
Reason 7: A weak Google Business Profile
For "near me" searches and the local 3-pack, your Google Business Profile is roughly 60% of the ranking signal. The website is the other 40%. If your GBP is weak, no amount of website optimization will fix the gap.
GBP non-negotiables:
- Primary category set exactly right (not "Marketing Agency" if you are an SEO agency — specificity matters)
- Secondary categories filled (up to 9 — pick all that apply)
- Services list populated with every service you offer
- Photos uploaded weekly (Google rewards GBPs with consistent fresh photos)
- Posts published weekly (the Posts feature is underused — works like a mini-blog inside GBP)
- Reviews answered within 24 hours (yes, even the 5-stars)
- Q&A populated (write your own seed questions, get a customer to ask one, you answer it)
- Booking link added if you have one
The single biggest GBP move that nobody makes: upload a Google Maps screenshot of your service area as a photo, every month. Google's algorithm uses photo metadata for local relevance. Real geo-tagged photos = real local signal.
For the full GBP playbook, see turf cleaning Google Business Profile — the framework applies to any local service.
Reason 8: Duplicate title tags and meta descriptions
Every page needs a unique <title> and <meta name="description">. Most service business sites do not have this — they have either the same title on every page, or templated titles like "Service - Company Name" that look identical to Google.
How to check: In Google Search Console → Pages → Indexed. Click into any page and look at the title shown. Are 10 of your pages showing the same title? You have a duplicate title problem.
The fix:
- Each page's title:
[Primary Keyword] | [Modifier] | [Brand]— e.g.,Turf Cleaning Phoenix | Same-Week Service | TTM - Each page's description: 150–160 characters, unique, includes the primary keyword and a benefit/CTA
If you have 30+ pages and writing all those is daunting, batch it. One afternoon with a spreadsheet and you are done.
Reason 9: No review velocity signal
Google does not just look at how many reviews you have. It looks at the velocity — how many you got in the last 30/90 days. A business with 200 reviews from 5 years ago ranks worse than a business with 30 reviews all from the last 90 days.
The fix:
- Send a review request to every customer within 24 hours of job completion
- Use a tool that makes leaving a review one tap (NiceJob, Birdeye, or even a custom QR code)
- Target 4-6 new reviews per week. Velocity matters more than the all-time total.
- Respond to every review within 24 hours. Even the 5-stars. Google watches for engagement signals.
If you are doing 8+ jobs a week and getting 0 reviews, you do not have a Google problem — you have an asking problem. Fix the asking and the rankings follow within 60–90 days.
The 30-day fix-everything plan
If you do nothing else, do these in this order:
Week 1: Audit + foundations
- Run Search Console → check indexed count vs sitemap count
- Check canonical tags on 10 random pages
- Run PageSpeed Insights on mobile for 3 pages
- Audit GBP completeness (categories, services, photos)
- Pull a list of all current page titles + descriptions
Week 2: Technical fixes
- Fix canonical tags (or pre-render if SPA)
- Add LocalBusiness schema to every page
- Add Service schema to each service page
- Compress all hero images to <200KB WebP
- Defer non-critical JavaScript
Week 3: Content fixes
- Rewrite duplicate titles and descriptions
- Audit top 5 city pages — flesh out any under 800 words
- Add internal links (every blog → service + 2 blog; every service → cities + blogs)
Week 4: GBP + reviews
- Fully populate GBP (categories, services, photos)
- Set up weekly photo upload routine
- Set up review request automation
- Resubmit sitemap in Search Console
Expect to see indexing improvements in 1–2 weeks and ranking movement in 4–8 weeks. The compounding kicks in around month 3.
Frequently asked questions
My sitemap has 57 pages but Google only indexes 49. Why? Most likely a canonical issue or a JavaScript rendering issue. Check the canonical tag on a non-indexed page first — if it points to the homepage, that is your culprit. (Yes, this is exactly the bug we just shipped a fix for on our own site.)
How long until rankings improve after I fix all this? Indexing improvements: 1–2 weeks. Ranking improvements: 4–8 weeks for the easy wins, 90–180 days for competitive local terms. SEO is not slow because it is hard — it is slow because Google needs repeated crawls to confirm the changes are real.
Should I disavow bad backlinks? For 99% of service businesses, no. Google's algorithm is good enough now to ignore spammy links automatically. Disavow only if you have evidence of a manual penalty or a clear negative SEO attack.
What about AI-generated content for SEO? Google's March 2024 update specifically targets low-quality AI content. AI can draft, but the published page needs human expertise signals: real photos, real case studies, real specific pricing. AI-only city pages get hit hard.
Is local SEO worth it if I run a lot of paid ads? Yes. Paid stops the day you stop paying. Local SEO compounds. Most clients we work with end up at a 70/30 organic-to-paid mix within 18 months — the cheapest leads are organic, the paid layer is for scaling fast in new markets.
How much do I budget for SEO if I do it right? $300–$1,500/month for a single-location service business. Most of that goes to content production and link/citation building. The technical foundation is mostly one-time work — done right once, you only revisit it when Google changes the rules.
Want us to audit your site and fix the technical foundation? Our local SEO service starts with a free technical audit — we tell you exactly which of these 9 issues you have, prioritized by impact. Or book a free strategy call and we will walk it through live.
Related reading: