← All posts
October 18, 2026 · 8 min read · The LeadMerlin Team

How to Qualify Local Business Leads Using Website Tech Stack Signals

Use CMS, chat widgets, analytics and ad pixels detected on a business's website to decide who to contact and what to say. Includes a simple scoring script.

A list of 500 roofers is not a pipeline. A list of 60 roofers who run Google Ads, have no chat widget and sit on a GoDaddy site builder is, if you sell conversion-focused websites or chat. The fastest way to get from one to the other is to look at what is installed on each business’s website.

This post covers which signals are worth using, what they actually mean for local businesses, and how to turn them into a score.

What can be detected from a homepage

LeadMerlin fingerprints each business’s homepage HTML and response headers during enrichment. The result is in web.tech on every enriched lead:

"tech": {
  "cms": "wordpress",
  "cdn": "cloudflare",
  "server": "nginx",
  "chat": "crisp",
  "analytics": ["google_analytics"],
  "frameworks": [],
  "advertising": ["google_ads"],
  "other": ["schema_org"]
}

What each key can contain today:

KeyValues detected
cmswordpress, wix, squarespace, shopify, godaddy, webflow, duda, drupal, joomla, or null
chatcrisp, intercom, tawk, drift, podium, livechat, or null
analyticsgoogle_analytics, hotjar, microsoft_clarity
advertisinggoogle_ads, facebook_pixel
frameworksjquery, next_js, react, vue, angular
otherschema_org, recaptcha, hcaptcha
cdn / servere.g. cloudflare, fastly, cloudfront, akamai; server from the response header

Detection is pattern-based on the homepage, so read the results as strong hints, not proof. A tracking tag loaded only on a thank-you page, or injected by a tag manager after load, won’t show up. null means “not detected”, not “definitely absent”.

Two more fields help a lot alongside the tech stack: web.has_blog, and web.pages[].text, the crawled text of the homepage and up to four subpages such as contact, about and services.

Signals that actually mean something

1. Advertising pixels = they already pay for customers

advertising containing google_ads or facebook_pixel is the strongest buying signal on a local business site. The owner has already decided that marketing is worth money. That makes them a good fit for:

  • PPC management, landing pages and conversion-rate work
  • Call tracking and lead attribution
  • Chat or answering services that convert paid clicks

A pixel with no analytics is a particularly useful combination: they’re spending but can’t measure.

2. No chat widget on a lead-driven business

For plumbers, HVAC, law firms and med spas, a site visitor is a potential customer right now. chat: null on those sites is an opening for chat, chat-to-text, or after-hours answering. chat: "podium" tells you the opposite: they already pay for messaging, so pitch something complementary rather than a competing tool.

3. DIY site builders

cms of wix, godaddy, squarespace or duda usually means the owner (or a relative) built the site. That’s not automatically a bad site, but it is the classic profile for redesign, local SEO and “we’ll manage it for you” offers. wordpress is ambiguous: it could be anything from a $200 theme to a custom agency build. Use the page text and the presence of analytics to tell them apart.

4. No structured data

other lacking schema_org is a small, visual local-SEO quick win. You can show the business exactly what’s missing in one screenshot of Google’s Rich Results Test.

5. Old front-end, nothing else

frameworks: ["jquery"] alone with no analytics, no pixels and a site-builder CMS suggests a site nobody has touched in years. Combine it with reputation.reviews to separate “established business with a neglected site” (good prospect) from “barely active business” (poor prospect).

6. What the site says, not just what it runs

Some of the best signals are words, not scripts. Search web.pages[].text for:

  • “book online”, “schedule” → they already take online bookings
  • “financing”, “membership”, “maintenance plan” → how they compete
  • “24/7”, “emergency” → after-hours demand, so chat and answering matter
  • “family owned”, “since 19xx” → tone for your opener

A simple scoring script

Here is a small, readable scoring function for an agency selling websites plus chat to home-service businesses. Adjust the weights for your own offer.

// leads = results.businesses from GET /v2/jobs/:id/results
function score(lead) {
  const t = lead.web?.tech ?? {};
  const text = (lead.web?.pages ?? []).map((p) => p.text).join(' ').toLowerCase();
  const best = lead.contact.all_emails.find((e) => e.email === lead.email);
  let s = 0;

  if (t.advertising?.length) s += 3;                       // already pays for leads
  if (t.advertising?.length && !t.analytics?.length) s += 2; // spending blind
  if (!t.chat) s += 2;                                       // no instant response
  if (['wix', 'godaddy', 'squarespace', 'duda'].includes(t.cms)) s += 2;
  if (!t.other?.includes('schema_org')) s += 1;
  if (text.includes('24/7') || text.includes('emergency')) s += 1;
  if ((lead.reputation?.reviews ?? 0) >= 30) s += 1;         // real, active business
  if (best?.status === 'verified' && !best.is_role_based) s += 2; // reachable owner-level inbox

  return s;
}

const shortlist = leads
  .map((l) => ({ ...l, score: score(l) }))
  .filter((l) => l.score >= 7)
  .sort((a, b) => b.score - a.score);

If you use an AI agent with the LeadMerlin skill, you don’t need the script. Describe the rule (“prioritize leads running Google Ads with no chat widget and a site-builder CMS; skip anything without a verified email”) and let the agent apply it to the results.

Turning the signal into the first line

The signal should become the reason for the email. Compare:

  • ❌ “I help businesses like yours grow online.”
  • ✅ “Noticed you’re running Google Ads for drain cleaning, but the site has no way to reach you after hours except the phone number.”

The second one is checkable, specific and about them. Keep every claim verifiable: say what you saw, not what you assume about their revenue.

Caveats

  • Franchises and multi-location brands share a corporate site, so the tech stack reflects headquarters, not the local owner.
  • Booking platforms and directory pages used as a “website” will show that platform’s stack.
  • Signals change. Re-enrich before a campaign if your list is more than a month or two old. LeadMerlin re-uses enrichment for a domain for up to 30 days, then crawls fresh.

Want to see the full lead shape first? The demo endpoints return sample businesses with every field populated. No key needed.

Try LeadMerlin free.

Search any niche across one city or many. First 100 leads free — no credit card.

Start free