Sales email system¶
Partly automated lead generation system for identifying and qualifying prospective clients from Google Maps, extracting contact details, and pushing qualified leads to Instantly email campaigns.
Overview¶
| Attribute | Details |
|---|---|
| Purpose | Scrape prospective leads from Google Maps, find email addresses, qualify leads, and push to Instantly campaigns, then push interested leads to Airtable |
| Data flow | Google Maps → Chrome Extension → Airtable → Python Script → Airtable → Instantly |
Components¶
| Component | Purpose |
|---|---|
| Google Maps Lead Scraper (Chrome Extension v1.5.x) | Scrapes business listings from Google Maps search results |
| Airtable | Leads scraped from Google Maps table in Sales emails base |
| Python Email Scraper (v2.1.2) | Visits websites and extracts published email addresses using Playwright |
| Airtable Automations | Data quality, deduplication, and Instantly integration |
| Instantly.ai | Email campaign delivery |
| Zapier | Pushes new Instantly campaigns to Airtable and pushes interested leads to Airtable |
Actors¶
| Actor | Role |
|---|---|
| Jordan/Glenn | Defines target verticals and locations |
| Glenn | Creates Instantly campaigns, reviews lead quality, qualifies leads |
| Sophie | Scrapes leads from Google Maps |
End-to-End Workflow¶
Step 1: Choose target (Jordan/Glenn)¶
Nominate target location and type (e.g. "childcare Rose Bay").
Step 2: Add campaign to Instantly (Glenn)¶
- Create campaign in Instantly (usually by duplicating an existing campaign)
- Write sequence (usually requires just a tweak of the duplicated campaign's sequence — the key is the list of clients)
- Enable ('Resume') the campaign
- Sync new campaign to Airtable by manually triggering the "Push new campaign to Airtable" zap (this zap runs automatically once per day at midday, but this may not be soon enough to push the campaign in time for Sophie to use it)
Step 3: Scraping Google Maps (Sophie)¶
- Search Google Maps — Search for prospective leads (e.g., "childcare chatswood")
- Open Chrome Extension — Click the Google Maps Lead Scraper extension icon
- Select campaign — Select the target Instantly campaign from the dropdown (campaigns are fetched from Airtable's 'Instantly campaigns' table)
- Click Scrape — Extension opens each result's details tile and scrapes: business name, address, street (parsed from address), suburb/city (parsed from address), post code, website, phone
- In-extension deduplication — Extension dedupes by business name within a single scrape (prevents duplicate sponsored listings)
- Review scraped data — Review the scraped results in the extension's grid view
- Save to Airtable — Click "Save to Airtable", which pushes records to the 'Leads scraped from Google Maps' table in the Sales emails base
Step 4: Finding Email Addresses (Sophie)¶
Manual review — Review the list in Airtable and manually fill any gaps (data the scraper failed to capture).
Run the email address scraper (on Windows):
- Open Command Prompt (press Win + R, type
cmd, press Enter) - Navigate to the script folder:
- Run the script:
Run on ChromeOS / Linux:
Script behaviour:
- Finds records where: Website exists, Email is empty, Status = "New"
- Uses Playwright (headless browser) to render JavaScript-heavy sites
- Visits homepage +
/contact,/contact-us,/about,/about-uspages - Extracts email addresses (prioritises
info@,contact@,enquiries@,hello@) - Handles obfuscated emails (e.g., "info [at] domain [dot] com")
- Updates each Airtable record with the found email
Step 5: Data Quality & Cleanup (Airtable Automation)¶
When an email address is added to a record, the 'Analyse, clean up and de-dupe list' automation runs. This executes three scripts in sequence:
Script 1: Client Match Checker — Checks if the lead matches an existing Organisation or Site in the Clients base:
- Exact email match
- Domain match (for franchise/chain detection, excludes generic domains like gmail.com)
- Fuzzy business name match
- If matched, sets
{Problem}field to "Past or present client"
Script 2: Dedupe by Email Address — Searches for any existing record with the same email address. If a duplicate is found, deletes the newer record (the one just updated).
Script 3: Flag Dodgy Emails — Validates whether the email address appears legitimate for the business:
- Checks if email contains the website domain
- Checks for business name initialism (e.g., "Gum Tree Cottage Preschool" → "gtcp")
- Checks for significant business name words
- Sets
{Email matches domain}field to "TRUE" or "FALSE"
Step 6: Manual check and handover (Sophie)¶
Check all leads in the 'Is it a lead?' view of the 'Leads scraped from Google Maps' table to ensure that all data looks good (especially names and email addresses, as these are critical to the email campaign).
Notify Glenn that the leads are ready for qualification.
Step 7: Lead Qualification (Glenn/Jordan)¶
Review leads in the 'Is it a lead?' view of the 'Leads scraped from Google Maps' table. This view shows records ready for qualification.
Qualify each lead:
- If YES (is a lead): Click the
{✓ YES}checkbox field - If NO (not a lead): Click the
{✗ NO}checkbox field
Step 8: Push to Instantly (Airtable automation)¶
If qualified as a lead:
- Record moves to the 'Add to Instantly' view
- 'Add lead to Instantly' automation triggers
- Script pushes lead to the Instantly campaign specified in the
{Instantly campaign}field - Sends: email, company_name, phone, website, and custom variables (suburb, street)
- Updates record:
{Status}= "Added to Instantly", unchecks{Add to Instantly}
If not a lead:
- Record moves to the 'Mark as not a lead' view
- 'Mark record as not a lead' automation triggers
- Updates record:
{Status}= "Not a lead"
Step 9: Email Sequence (Instantly)¶
Once added to the campaign, the lead automatically receives the configured email sequence.
Step 10: Add leads to Airtable (Zapier)¶
Interested leads are pushed from Instantly to Airtable automatically by the 'Push interested lead from Instantly to Airtable' zap, whenever a lead is marked as "Interested".
Installation instructions for Chrome scraping extension¶
Prerequisites¶
- Google Chrome browser
- Airtable Personal Access Token with
data.records:writescope - Access to the Sales emails base in Airtable
Step 1: Download the extension¶
- Create a new folder in your root (
C:\) directory, namedMCC_scraper - Download the zip file containing the extension to the above directory
- Unzip it
- You should now have a folder named "Google Maps search results scraper Chrome extension" containing:
manifest.json,popup.html,popup.js,options.html,options.js,icons/folder
Step 2: Install in Chrome¶
- Open Chrome and navigate to
chrome://extensions/ - Enable Developer mode (toggle in top-right corner)
- Click Load unpacked
- Navigate to
C:\MCC_scraper\ - Click the "Google Maps search results scraper Chrome extension" folder (single click to highlight, don't double-click)
- Click Select Folder
- The extension icon should appear in your toolbar
Step 3: Configure Airtable settings¶
- Right-click the extension icon in your toolbar
- Select Options
- Enter the following:
| Field | Value |
|---|---|
| Airtable Personal Access Token | patCgzwikWczEQ7KV.17e94a97d48232c0eb996e041d51b38a07886525d753484013040395492fecc4 |
| Airtable Base ID | appDaFRJSxle3TqBA |
| Airtable Table ID | tblQ8VYyUg1LsFKL1 |
- Click Save Settings
Installation instructions for Python Email Scraper¶
Scrapes email addresses from websites listed in Airtable and updates the records. Uses Playwright (headless browser) to handle JavaScript-rendered pages.
| Attribute | Details |
|---|---|
| Version | 2.2.0 |
| Purpose | Find email addresses from lead websites and update Airtable |
| Data flow | Airtable → Python script → Website → Airtable |
Windows Installation¶
Step 1: Install Python¶
- Go to python.org/downloads
- Download the latest Python 3.x installer for Windows
- Run the installer
- IMPORTANT: Tick the checkbox "Add Python to PATH" at the bottom of the first screen
- Click Install Now
- Wait for installation to complete, then click Close
- Verify Python installed correctly:
- Open Command Prompt (press Win + R, type
cmd, press Enter) - Type
python --versionand press Enter - You should see something like
Python 3.12.0 - If you see an error, Python wasn't added to PATH. Uninstall and reinstall, making sure to tick "Add Python to PATH".
Step 2: Download the script files¶
- If you haven't already, create a new folder in your root (
C:\) directory, namedMCC_scraper - Download the
Scrape_emailzip file to that folder - Unzip it
- The unzipped folder should contain:
scrape_emails.py(the main script),config.txt(configuration file),README.md(documentation)
Step 3: Install Playwright¶
- Open Command Prompt as Administrator:
- Press Win + S, type
cmd - Right-click Command Prompt and select Run as administrator
- Click Yes if prompted
- Run the following commands one at a time:
- Wait for it to finish, then run:
- This downloads the Chromium browser (~150MB). Wait for it to complete.
Airtable Table Structure (for scraped businesses)¶
Base: Sales emails | Table: Leads scraped from Google Maps
| Field | Type | Purpose |
|---|---|---|
| Business name | Single line text | Company name from Google Maps |
| Address | Single line text | Full address |
| Street | Single line text | Parsed street address |
| Suburb / city | Single line text | Parsed suburb |
| Post code | Single line text | Parsed postcode |
| Website | URL | Business website |
| Phone | Phone | Contact number |
| Scraped or manually entered email | ||
| Status | Single select | New / Added to Instantly / Not a lead |
| Instantly campaign | Linked record | Links to Instantly campaigns table |
| Problem | Single select | Issues flagged (e.g., "Past or present client") |
| Email matches domain | Single line text | TRUE/FALSE validation result |
| ✓ YES | Checkbox | Mark as qualified lead |
| ✗ NO | Checkbox | Mark as not a lead |
| Add to Instantly | Checkbox | Triggers push to Instantly |
Airtable Table Structure (for interested leads)¶
Base: Matthews Cleaning Company
Tables: Organisations, Sites, Contacts, Opportunities
Airtable Automations¶
| Automation | Trigger | Action |
|---|---|---|
| Analyse, clean up and de-dupe list | When {Email} field is populated |
Runs 3 scripts: Client match checker, Dedupe by email, Flag dodgy emails |
| Add lead to Instantly | When record enters 'Add to Instantly' view | Pushes lead to Instantly via API |
| Mark record as not a lead | When record enters 'Mark as not a lead' view | Sets {Status} = "Not a lead" |
Key Files & Scripts¶
| Asset | Version | Location/Notes |
|---|---|---|
| Google Maps Lead Scraper (Chrome Extension) | v1.5.x | Installed locally on Chromebox |
| Python Email Scraper | v2.1.2 | ~/Scrape_email/scrape_emails.py on Chromebox |
| Client Match Checker script | v1.2.2 | Airtable automation script |
| Dedupe by Email script | v1.0.2 | Airtable automation script |
| Flag Dodgy Emails script | v1.1 | Airtable automation script |
| Add Lead to Instantly script | v2.9 | Airtable automation script |
Technical Notes¶
Chrome Extension:
- Dedupes by business name within a single scrape
- Campaign dropdown fetches from Airtable 'Instantly campaigns' table
- Saves selected campaign as a linked record
Python Email Scraper:
- Uses Playwright for JavaScript-rendered content
- Requires Chromium browser installed
- Run with
--debugflag for troubleshooting - Config stored in
config.txt(API token, Base ID)
Instantly Integration:
- Uses API v2 (
https://api.instantly.ai/api/v2/leads) - Campaign ID passed from lookup field
- Custom variables:
{{suburb}},{{street}}available in email templates - Strips invisible Unicode characters from emails before sending
Zapier Zaps¶
Push new campaign to Airtable¶
Syncs Instantly campaigns to Airtable so the Chrome extension can display them in the campaign dropdown.
| Step | Action | Configuration |
|---|---|---|
| Schedule by Zapier | Every Hour | Time offset: 00, Weekends: No |
| Webhooks by Zapier | Custom Request | GET https://api.instantly.ai/api/v2/campaigns?limit=100 |
| Looping by Zapier | Create Loop From Line Items | Loops through each campaign (id, name), max 500 iterations |
| Airtable | Create or Update Record | Base: Sales emails, Table: Instantly campaigns, Lookup: field_ID |
What it does:
- Fetches all campaigns from Instantly API hourly
- For each campaign, creates or updates a record in the 'Instantly campaigns' table
- Uses the Instantly campaign ID as the primary lookup field (prevents duplicates)
- Stores the campaign name for display in the Chrome extension dropdown
Note: Does not run on weekends.
Push interested lead from Instantly to Airtable¶
Syncs Instantly leads (individuals) back to Airtable as soon as they reply with interest (and Instantly automatically changes their status to "Interested").