DEV Community

NexGenData
NexGenData

Posted on

How to Score and Qualify Google Maps Leads Automatically

How to Score and Qualify Google Maps Leads Automatically

If you're in B2B lead generation, you've probably felt the pain of working through a list of 500 Google Maps listings where 400 of them are dead leads. Wrong contact info. Closed businesses. Outdated phone numbers. Low-quality listings that waste your time.

The difference between a great lead and a dead lead isn't always obvious from a listing title. You need to score them systematically. This post walks through building a lead scoring algorithm that automatically separates signal from noise, so your sales team focuses on opportunities that can actually convert.

What Makes a High-Quality Lead?

Before you can score leads, you need to define what "quality" means in your context. Generally, a high-quality business lead has these characteristics:

Verified Contact Information: An email address, phone number, and website all present and current. If you can't reach them through multiple channels, the lead is essentially worthless.

Positive Review Profile: Businesses with 4.2+ star ratings and 50+ reviews are generally established and customer-focused. A business with three 1-star reviews and no response pattern is a red flag.

Social Media Presence: Active social profiles (Instagram, LinkedIn, Facebook) suggest the business is actively managed and has marketing infrastructure. A business with zero social presence might be dormant.

Website Quality: A recent website with current content signals a business that's actively operating. Lots of 404 errors or outdated copyright years suggest a dead lead.

Verification Signals: Google reviews, business photos, Q&A activity, and recently updated business info all indicate active management.

In practice, you're looking for businesses that meet most (not necessarily all) of these criteria. A B2B service business might not have an Instagram, but they should have a LinkedIn. A local service might be thriving without an elaborate website.

The Scoring Framework

Here's a practical scoring model you can implement immediately. Each criterion gets weighted based on its predictive power for conversion.

Contact Information (Weight: 30 points)

  • Email address present: 10 points
  • Phone number present and valid: 10 points
  • Website URL present: 10 points

Review Profile (Weight: 25 points)

  • Rating 4.5+: 10 points
  • Rating 4.0-4.5: 7 points
  • Rating 3.5-4.0: 4 points
  • Rating below 3.5: 0 points
  • 50+ reviews: 10 points
  • 20-50 reviews: 6 points
  • 5-20 reviews: 2 points
  • Under 5 reviews: 0 points

Activity Indicators (Weight: 25 points)

  • Website detected and current: 8 points
  • Response to recent reviews: 8 points
  • Active social profiles (Facebook OR Instagram): 5 points
  • Active LinkedIn profile (B2B): 4 points

Data Recency (Weight: 20 points)

  • Last business info update within 30 days: 7 points
  • Last update within 90 days: 4 points
  • Last update within 6 months: 2 points
  • Last update over 6 months ago: 0 points
  • Business open for 5+ years: 7 points
  • Business open 1-5 years: 4 points
  • Business open under 1 year: 2 points (startup signal)

Total Possible Score: 100 points

Lead Tiers:

  • 80-100: Tier 1 (Hot) - Immediate outreach
  • 60-79: Tier 2 (Warm) - Standard nurture sequence
  • 40-59: Tier 3 (Cool) - Research or alternate outreach
  • 0-39: Tier 4 (Dead) - Archive or skip

This model is intentionally heavy on contact information and recency because these directly impact whether you can actually reach the lead and whether they're still operating.

JSON Data Structure Example

Here's what output from the Google Maps Lead Generator looks like, and how you'd augment it with scores:

{
  "business_id": "0x8644a7e8c8e8e8e8",
  "name": "Austin Solar Installations",
  "type": "Solar energy service",
  "address": "123 Oak Street, Austin, TX 78704",
  "phone": "+1-512-555-0147",
  "website": "https://austinsolarpro.com",
  "email": "contact@austinsolarpro.com",
  "google_rating": 4.7,
  "review_count": 87,
  "latitude": 30.2672,
  "longitude": -97.7431,
  "opening_hours": {
    "monday": "09:00-17:00",
    "tuesday": "09:00-17:00",
    "wednesday": "09:00-17:00",
    "thursday": "09:00-17:00",
    "friday": "09:00-17:00",
    "saturday": "10:00-14:00",
    "sunday": "closed"
  },
  "business_status": "OPERATIONAL",
  "last_updated": "2026-03-28T14:30:00Z",
  "social_profiles": [
    {
      "platform": "facebook",
      "url": "https://facebook.com/austinsolar",
      "follower_count": 1240,
      "verified": true
    },
    {
      "platform": "instagram",
      "url": "https://instagram.com/austinsolarpro",
      "follower_count": 3891,
      "verified": false
    }
  ],
  "website_status": "active",
  "last_website_check": "2026-04-01T08:00:00Z",
  "response_rate_to_reviews": 0.92,
  "years_in_business": 8,
  "lead_score": {
    "contact_info_score": 30,
    "review_profile_score": 25,
    "activity_score": 23,
    "recency_score": 18,
    "total_score": 96,
    "tier": "Tier 1 (Hot)",
    "reasoning": [
      "Complete contact information",
      "4.7 rating with 87 reviews",
      "Active website and social presence",
      "92% response rate to reviews",
      "Updated within 4 days"
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

Notice the lead_score object at the end. This is the synthesized data that tells you at a glance whether this lead is worth pursuing.

Python Implementation

Here's how to implement this scoring algorithm:

import json
from datetime import datetime, timedelta
import re

class LeadScorer:
    def __init__(self):
        self.weights = {
            'contact_info': 0.30,
            'review_profile': 0.25,
            'activity': 0.25,
            'recency': 0.20
        }

    def score_lead(self, lead_data):
        contact_score = self._score_contact_info(lead_data)
        review_score = self._score_reviews(lead_data)
        activity_score = self._score_activity(lead_data)
        recency_score = self._score_recency(lead_data)

        total = (
            contact_score * 30 +
            review_score * 25 +
            activity_score * 25 +
            recency_score * 20
        ) / 100

        return {
            'contact_info_score': contact_score,
            'review_profile_score': review_score,
            'activity_score': activity_score,
            'recency_score': recency_score,
            'total_score': round(total),
            'tier': self._get_tier(total),
            'reasoning': self._explain_score(lead_data, total)
        }

    def _score_contact_info(self, lead):
        score = 0
        reasoning = []

        if lead.get('email') and self._validate_email(lead['email']):
            score += 10
            reasoning.append("Valid email present")

        if lead.get('phone') and self._validate_phone(lead['phone']):
            score += 10
            reasoning.append("Valid phone number")

        if lead.get('website'):
            score += 10
            reasoning.append("Website URL present")

        return min(score, 30)

    def _score_reviews(self, lead):
        score = 0
        rating = lead.get('google_rating', 0)
        review_count = lead.get('review_count', 0)

        # Rating tier
        if rating >= 4.5:
            score += 10
        elif rating >= 4.0:
            score += 7
        elif rating >= 3.5:
            score += 4

        # Review volume
        if review_count >= 50:
            score += 10
        elif review_count >= 20:
            score += 6
        elif review_count >= 5:
            score += 2

        return min(score, 25)

    def _score_activity(self, lead):
        score = 0

        # Website status
        if lead.get('website_status') == 'active':
            score += 8

        # Review response rate
        response_rate = lead.get('response_rate_to_reviews', 0)
        if response_rate > 0.8:
            score += 8

        # Social presence
        social_profiles = lead.get('social_profiles', [])
        platforms = [p['platform'] for p in social_profiles]

        if 'facebook' in platforms or 'instagram' in platforms:
            score += 5

        if 'linkedin' in platforms:
            score += 4

        return min(score, 25)

    def _score_recency(self, lead):
        score = 0

        # Last update recency
        last_updated = lead.get('last_updated')
        if last_updated:
            days_since = self._days_since(last_updated)
            if days_since <= 30:
                score += 7
            elif days_since <= 90:
                score += 4
            elif days_since <= 180:
                score += 2

        # Years in business
        years = lead.get('years_in_business', 0)
        if years >= 5:
            score += 7
        elif years >= 1:
            score += 4
        elif years > 0:
            score += 2

        return min(score, 20)

    def _get_tier(self, score):
        if score >= 80:
            return "Tier 1 (Hot)"
        elif score >= 60:
            return "Tier 2 (Warm)"
        elif score >= 40:
            return "Tier 3 (Cool)"
        else:
            return "Tier 4 (Dead)"

    def _explain_score(self, lead, total_score):
        reasons = []

        if lead.get('phone') and lead.get('email') and lead.get('website'):
            reasons.append("Complete contact information")

        rating = lead.get('google_rating', 0)
        review_count = lead.get('review_count', 0)
        if rating >= 4.5 and review_count >= 50:
            reasons.append(f"Strong reputation ({rating} stars, {review_count} reviews)")

        if lead.get('response_rate_to_reviews', 0) > 0.8:
            reasons.append("Responsive to customer feedback")

        last_updated = lead.get('last_updated')
        if last_updated:
            days_since = self._days_since(last_updated)
            if days_since <= 30:
                reasons.append(f"Recently active (updated {days_since} days ago)")

        years = lead.get('years_in_business', 0)
        if years >= 5:
            reasons.append(f"Established business ({years} years)")

        return reasons

    def _validate_email(self, email):
        pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
        return re.match(pattern, email) is not None

    def _validate_phone(self, phone):
        digits = re.sub(r'\D', '', phone)
        return len(digits) >= 10

    def _days_since(self, timestamp_str):
        dt = datetime.fromisoformat(timestamp_str.replace('Z', '+00:00'))
        return (datetime.now(dt.tzinfo) - dt).days

# Usage
scorer = LeadScorer()
leads = json.load(open('google_maps_leads.json'))

scored_leads = []
for lead in leads:
    lead_score = scorer.score_lead(lead)
    lead['lead_score'] = lead_score
    scored_leads.append(lead)

# Filter to Tier 1 and Tier 2
hot_and_warm = [l for l in scored_leads
                if l['lead_score']['tier'] in ['Tier 1 (Hot)', 'Tier 2 (Warm)']]

print(f"Total leads: {len(scored_leads)}")
print(f"High-quality leads: {len(hot_and_warm)}")
print(f"Conversion target: {len(hot_and_warm)} leads")

# Export for outreach
with open('qualified_leads.json', 'w') as f:
    json.dump(hot_and_warm, f, indent=2)
Enter fullscreen mode Exit fullscreen mode

This implementation gives you a repeatable, transparent process. You can adjust weights based on what actually converts for your business.

Refining Your Scoring Model

The framework I've shared is a starting point. You'll want to refine it based on your actual conversion data.

Track these metrics for every lead you reach out to:

  • Did they respond?
  • Did they qualify as a real opportunity?
  • Did the deal close?
  • What was their revenue?

Then, compare these outcomes against the score tiers. You might find that your Tier 1 leads convert at 25%, Tier 2 at 12%, and Tier 3 at 3%. This tells you exactly which leads are worth your time.

You might also discover that a factor you didn't weight heavily (like social media follower count) is actually highly predictive. Adjust accordingly.

Data Sources and Automation

The Google Maps Lead Generator from Apify outputs the data structure you need. Set it to run on a schedule (weekly or monthly depending on your market), and automatically pipe the output through your scoring algorithm.

This creates a self-refreshing lead list. Every week, you get new leads scored and tiered. Dead leads automatically drop off as their data grows stale. New businesses get picked up and scored.

Practical Integration

Here's how you might integrate this into your workflow:

Daily: Your sales team checks the "Hot" leads from yesterday's run. They make first contact using your preferred channels (email, phone, LinkedIn).

Weekly: You run the scraper and scoring process on Friday afternoon. By Monday, you have a fresh list of qualified leads for the coming week.

Monthly: You review conversion data. Which leads actually closed? Which tiers are performing? Adjust your scoring weights.

Quarterly: You reassess your market. Have new competitors emerged? Are your leads coming from different industries? Update your scraper parameters and scoring criteria.

The Real Win

The biggest value of automated lead scoring isn't getting a perfect score. It's eliminating obviously bad leads so your team can focus on real opportunities. If you go from reviewing 500 leads to reviewing 150, and the 150 are significantly better quality, you've just multiplied your sales efficiency.

Start scoring your Google Maps leads today. The Google Maps Lead Generator makes collection easy. The algorithm above makes qualification systematic. The rest is execution.

Top comments (0)