Every roofer I talk to has the same story. They do great work, their customers love them, but the phone isn’t ringing from Google. Joshua Holmes was no different — except he’d already spent money trying to fix it and gotten burned.

This is what happened when we stopped guessing and started building.

The problem

Holmes Roofing is a San Antonio-based roofing and exteriors company. Joshua runs about three concurrent jobs at any given time, does roughly $1M in annual revenue, and built his reputation on word-of-mouth and referrals. The work speaks for itself — 20 Google reviews, every single one at 5 stars.

But Google didn’t care.

When someone searched “roofing contractor san antonio,” Holmes didn’t show up. Not in the Map Pack, not on page one, not anywhere a homeowner would find them. His biggest competitor, Rhino Roofers, had over 1,300 reviews and hundreds of indexed pages. Holmes had 15 service pages, one location page, and zero blog posts.

His previous marketing agency, Tegna (a CBS media company), charged $1,100 a month and produced exactly zero leads. Not low-performing leads — zero. His web design firm, LeadHub, dropped him after signing a competing roofer who wanted market exclusivity. The contact form on his website had 11 submissions over months of operation. Every single one was spam.

Joshua wasn’t failing at marketing. He’d never had anyone actually do it.

What we built

We started in late April 2026 with a 90-day plan focused on three things: making Holmes findable on Google, building a review engine that compounds over time, and fixing the website so it actually converts visitors into calls.

Google Business Profile overhaul

The GBP listing had basics but was underoptimized. Hours were set to open at 9 AM, which meant Google showed “Closed” to anyone searching before that — including the early-morning homeowners checking their phone after a storm. We expanded hours to {{GBP_HOURS_NEW}}, added {{GBP_CATEGORIES_ADDED}} additional service categories beyond the single “Roofing contractor” listing, rewrote the business description with location-specific keywords, and started a weekly posting schedule.

28 city pages

Holmes serves the entire San Antonio metro, but Google only knew about one location. We drafted and published 28 city-specific landing pages — Selma, Boerne, New Braunfels, Schertz, Cibolo, and 23 others — each with unique content about roofing conditions, local building codes, and the specific services Holmes offers in that area. This gives Google a reason to show Holmes when someone in Boerne searches “roofer near me” instead of only matching San Antonio searches.

Review velocity system

Twenty reviews at 5.0 stars is excellent quality but insufficient volume. We built a review request system with QR code cards for job sites, a post-job SMS sequence, and response templates so Joshua could reply to every review within 24 hours. The goal: go from {{REVIEWS_VELOCITY_BEFORE}} new reviews per month to a sustainable {{REVIEWS_VELOCITY_TARGET}} per month without triggering Google’s spam filter.

Directory citation cleanup

We audited Holmes across 80+ business directories and found {{CITATION_ISSUES_COUNT}} listings that were either missing, had inconsistent information, or used an old phone number. We submitted corrections and new listings to {{CITATIONS_SUBMITTED}} directories to build the kind of consistent NAP (name, address, phone) presence that Google uses as a trust signal.

Website fixes

The contact form notifications were sending from an old agency’s email address (server@leadhub.net), which meant they were landing in spam. We fixed the email routing, simplified the form, and added call tracking so Joshua could see exactly which leads came from the website versus other channels.

The results

After {{TIMEFRAME}} of work:

Google visibility

Reviews

Leads and revenue

AI search presence

What it cost

Holmes Roofing pays $1,100 per month for ongoing local SEO management. That’s the same amount they were paying Tegna for zero results. The difference is that every dollar now goes toward building assets Holmes owns — their Google listing, their website content, their review profile, their directory presence. If they stopped working with us tomorrow, all of that stays.

At an average roofing job value of ${{AVG_JOB_VALUE}}, Holmes needs {{JOBS_TO_BREAK_EVEN}} additional job per month from Google to more than cover the investment. Based on {{TIMEFRAME}} of data, they’re getting {{MONTHLY_LEADS_FROM_GOOGLE}} qualified leads per month from channels that didn’t exist before we started.

The takeaway

Holmes Roofing didn’t need a bigger marketing budget. They needed someone to actually build the foundation — the boring, unsexy work of optimizing a Google listing, writing city pages, fixing email routing, and building review momentum one customer at a time.

The flashy stuff (AI phone systems, storm-triggered ad campaigns, automated direct mail) is coming in Phase 2. But none of it works without the foundation. And for most local service businesses, the foundation is what’s missing.

If your phone isn’t ringing from Google, it’s probably not because your work is bad. It’s because Google doesn’t know you exist. That’s fixable. And it doesn’t cost $90,000 a year.

Not sure where you stand? Run a free audit — it takes 30 seconds and shows you exactly what Google sees when customers search for your business.