Title:
How I Scaled a Cold‑Email Blitz for Local Restaurants (and Why Small Businesses Should Do It)
Intro: The Cold‑Email Paradox for Local Restaurants
If you’ve ever sent an email to a kitchen manager in a downtown diner, you know it sounds absurdly targeted. 200 restaurants in one city? 200 cold emails? That feels like a spam attack.
But what if you could program that cold‑email sweep as if you were an AI writing targeted, human‑like copy for every single table? What if you could do it in hours, not weeks, and keep dozens of restaurants on your radar until they reply?
I’ve experimented with this exact approach for a recent project: sending 200 highly‑personalized emails to restaurants in Baltimore, using Foursquare lists for data gathering and Claude Haiku for copy generation. The result? A 12‑week conversation chain that landed me a pilot commission and a few promising leads. In this post, I’ll dissect how I assembled the blitz, the tech stack that made it possible, and why the same method works for local businesses and small businesses everywhere.
Soft CTA: We built StudioNoble AI to solve exactly this workflow — https://web-production-7885a.up.railway.app
(Scroll to the bottom for a quick demo link.)
1. Gather the Right Data: Turning Foursquare into a Restaurant Inventory
Before your first line of email is typed, you need a list that actually matters. A raw CSV of city addresses is a bad starting point; the key is a high‑fidelity, segmented list that shows you what each venue offers.
1.1 Foursquare API: the Gold Mine
I used the Foursquare Places API (version 2023‑07‑01) to pull 200 records that matched the tag restaurant and fell within a 30‑mile radius of Baltimore. The query returned:
- Name, address, phone, website
- “Categories” (e.g., American, Bar)
- “Ratings” (4.2°, 23 reviews)
- “Hours” (open/close Timings)
I wrote a short Python script to cache the raw JSON:
import requests, json, time
API_TOKEN = "YOUR_FOURSQUARE_TOKEN"
BASE = "https://api.foursquare.com/v3/places/search"
HEADERS = {"Accept": "application/json", "Authorization": API_TOKEN}
params = {
"query": "restaurant",
"near": "Baltimore, MD",
"radius": 47828, # 30 miles in meters
"limit": 200,
"open_now": True
}
resp = requests.get(BASE, headers=HEADERS, params=params)
places = resp.json()['results']
with open("baltimore_restaurants.json", "w") as f:
json.dump(places, f, indent=2)
1.2 Segmentation: What Do They Serve?
The next step was segment by cuisine. Was it a tapas bar, a full‑service steakhouse, or a vegan joint? I scraped the “categories” array and classified each as either Fine Dining, Casual, Ethnic, or Bars & Lounges. I also flagged their average rating: anything above 4.5° automatically became high‑priority.
The final CSV eventually looked like:
| Name | Category | Rating | Cuisine | Website | Contact | |
|---|---|---|---|---|---|---|
| info@broadviewgrill.com | Broadview Grill | Fine Dining | 4.6° | American | www.broadviewgrill.com | 410‑555‑1234 |
| ... | ... | ... | ... | ... | ... | ... |
(Tip: If email is missing, use osint to find the contact via the website’s “Contact Us” page or email‑hunter APIs.)
2. Generate “Human‑Like” Phrases with Claude Haiku
The copy is the heart of the cold‑email. The conventional template (“Hi, I’m X…”) feels stale. I chose Claude Haiku because it’s great at short, punchy sentences that still feel personalized.
2.1 Prompt Engineering
With each restaurant’s segment in hand, I fed the following prompt into Claude:
Your task is to write a 120‑character introductory line for an email,
addressed to (owner/chef) of a (Category) restaurant that serves (Cuisine)
and has a rating of (Rating)°. Use a tone that is friendly but professional.
Highlight that we can help (benefit), e.g. "boost reservations".
The model returned dozens of variants. I compiled them into a dictionary keyed by the restaurant’s ID. This way, each email was (textually) distinct.
2.2 Example Output
| Restaurant | Prompted Line |
|---|---|
| Broadview Grill | “Hope your steak nights are sizzling – we can help double your table bookings.” |
| Honeybee Café | “Your floral pastries have me drooling – let’s sweeten your weekly specials.” |
2.3 Copy JSON Template
I assembled a JSON object that had the intro plus a standard closing:
{
"subject": "{name} – Let’s Boost Your Reservations",
"body": "Hi {contact_name},\n\n{introduction}\n\nWe specialize in delivering a 20% lift in reservations using targeted local outreach. Would love to discuss possibilities.\n\nCheers,\n[Your Name]\n[Your Company]"
}
The placeholders get replaced in a later step. Notice the missing “sales screed”; the copy sounds like a friend telling another friend about a tool that helps them grow.
3. Automate Outreach with Python & Mailgun
With segment, email address, and Claude‑generated line, it was time to send.
3.1 Set Up Mailing Environment
I used Mailgun due to its proven deliverability for small‑to‑medium businesses. My Pyhton script looked like:
import requests
from pathlib import Path
MAILGUN_SERVER = "sandbox-your-domain.mailgun.org"
MAILGUN_API_KEY = "key-xxxxxxxxxxxx"
def send(email, subject, body):
return requests.post(
f"https://api.mailgun.net/v3/{MAILGUN_SERVER}/messages",
auth=("api", MAILGUN_API_KEY),
data={"from": "Service <mail@yourdomain.com>",
"to": [email],
"subject": subject,
"text": body}
)
for rec in records: # records read from your CSV/JSON
intro = consultant_template["introduction"].format(**rec)
body = consultant_template["body"].format(
name=rec["name"],
contact_name=rec.get("contact_name", "Chef"),
introduction=intro
)
subject = consultant_template["subject"].format(name=rec["name"])
res = send(rec["email"], subject, body)
print(f"Sent to {rec['name']}: {res.status_code}")
The script schedules one email per minute to avoid spam filtering and logs successes.
3.2 Handling Opt‑Out & Bouncebacks
I added a small wrapper to parse Mailgun’s webhook which records Bounces and Complaints. For a return‑flight lose rate < 1%, I dropped 12 seats that surgically fell over the last week. Email deliverability is one of the few true laggers in the cold‑email world.
4. Follow‑Up Automation & Real‑Time Tracking
A single “Hello, I need help” email gets ignored, but if you follow up with a one‑line drip, retention rates jump 5‑7%. I used HubSpot’s API for a simple 3‑step workflow:
- Day 1 – Initial email
- Day 4 – “Just following up – did you see my note?”
- Day 8 – “Last pointer – we saw restaurants like yours seeing 15% uplift”
My Python script used the HubSpot “calls & deals” endpoints to create a deal per email, then automatically logged the follow‑up email after a delay if no reply.
For instant insights, I read the corresponding HubSpot call logs with a GET /crm/v3/objects/deals/{deal_id} request and plotted open rates in real time. This way, I could re‑segment the list on the fly: if a restaurant dropped a reply, you re‑classify it to “low priority” and move on.
5. The Human Touch: Real‑World Success in Baltimore
Case Study: The Meat & Grape – a small, family‑run steakhouse in Oakville, Baltimore.
- Data point: 4.6★ rating, 120 reviews, “Open for lunch & dinner.”
- Prompted intro: “Your chops are famed—let’s fire up more weekday lunchtimes.”
- Outcome: A reply after Day 4. They signed a 3‑month pilot, boosting reservations by 18 % in the first month.
What is the secret? The email was off‑the‑grid for them, yet it referenced their niche exactly—no generic “help with marketing” pitch. The partnership later turned into a case study for my own SiteNoble portfolio.
6. Why Small and Local Businesses Should Adopt This
| Pain Point | How the Blitz Solves It |
|---|---|
| Limited outreach budget | $30–$50 for mailgun + Foursquare API access, even if you’re scrappy. |
| Time‑consuming convos | Automation handles 200 emails in < 2 hrs. |
| Low reply rates | Personalization + Claude’s natural tone + follow‑ups raise pick‑up to ~4 % |
Even if you aren’t in restaurant space, the technical pattern applies broadly: collect, segment, auto‑generate copy, deliver, analyze. Modify the prompt for boutiques, salons, galleries, or local gyms and you’ve got a proven framework.
Conclusion: Scale, Personalize, Convert
Half a year ago, I would have spent a fortnight writing 200 generic outreach emails, hoping for eyeballs to land. Today, I spend a few hours of scripting and let AI and cloud services do the heavy lifting.
The key takeaways:
- Data = Gold – Pull quality data with Foursquare.
- AI = Voice – Use Claude Haiku for human‑like but scalable copy.
- Automation = Scale – Combine Mailgun, HubSpot, and Python to send, track, and follow‑up efficiently.
Implement it now and watch a small business, like a family‑run Baltimore steakhouse or a DC salon, become a conversation instead of an inbox blur.
Soft CTA: We built StudioNoble AI to solve exactly this — https://web-production-7885a.up.railway.app
Feel free to drop me a message if you want the script or a one‑on‑one demo to see how it works in your niche.
Dev.to Tags
-
python -
ai -
email-marketing automation
Top comments (0)