<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Vemtrac Labs</title>
    <description>The latest articles on DEV Community by Vemtrac Labs (@vemtrac_labs).</description>
    <link>https://dev.to/vemtrac_labs</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3756225%2Fab1b2007-c61d-49f6-905b-d68bb4cb46bd.png</url>
      <title>DEV Community: Vemtrac Labs</title>
      <link>https://dev.to/vemtrac_labs</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vemtrac_labs"/>
    <language>en</language>
    <item>
      <title>Local SEO for Dentists: 7 Technical Fixes That Get You Found on Google</title>
      <dc:creator>Vemtrac Labs</dc:creator>
      <pubDate>Wed, 01 Apr 2026 00:34:40 +0000</pubDate>
      <link>https://dev.to/vemtrac_labs/local-seo-for-dentists-7-technical-fixes-that-get-you-found-on-google-2pid</link>
      <guid>https://dev.to/vemtrac_labs/local-seo-for-dentists-7-technical-fixes-that-get-you-found-on-google-2pid</guid>
      <description>&lt;p&gt;i scanned 222 dental practice websites across australia. the same 7 technical SEO problems appeared on nearly every site. fixing them is straightforward and dramatically improves local search rankings.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. claim and optimize google business profile
&lt;/h2&gt;

&lt;p&gt;before touching your website, make sure your google business profile is complete: correct address, phone, hours, photos, and services listed. this is the #1 factor for appearing in local map results.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. add localBusiness schema markup
&lt;/h2&gt;

&lt;p&gt;81% of dental sites i scanned had no schema markup. add this to your homepage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"application/ld+json"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@context&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://schema.org&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Dentist&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Your Practice Name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;address&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;PostalAddress&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;streetAddress&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;123 Main St&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;addressLocality&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Your City&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;addressRegion&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;State&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;postalCode&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1234&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;telephone&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;+61-XXX-XXX-XXX&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;openingHours&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Mo-Fr 09:00-17:00&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. write unique meta descriptions for every page
&lt;/h2&gt;

&lt;p&gt;67% of dental sites were missing meta descriptions. each page needs a unique one:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;homepage: "Family dentist in [city]. Emergency appointments, cosmetic dentistry, preventive care. Book online."&lt;/li&gt;
&lt;li&gt;services: "Professional teeth whitening in [city]. Safe, effective, affordable. Call today."&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. add alt text to all images
&lt;/h2&gt;

&lt;p&gt;73% of sites had images without alt text. every image of your clinic, staff, and procedures needs descriptive alt text for google to understand what it shows.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. fix your heading structure
&lt;/h2&gt;

&lt;p&gt;one H1 per page containing your main keyword. use H2 for service categories, H3 for individual services.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. ensure mobile responsiveness
&lt;/h2&gt;

&lt;p&gt;over 60% of dental searches happen on mobile. if your site doesn't have a viewport meta tag or responsive design, google penalizes you.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. get SSL certificate
&lt;/h2&gt;

&lt;p&gt;12% of dental sites still run on http. google shows a "not secure" warning which scares patients away.&lt;/p&gt;

&lt;h2&gt;
  
  
  scan your site for free
&lt;/h2&gt;

&lt;p&gt;want to know which of these 7 issues affect your site? use my free chrome extension:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://vemtrac.gumroad.com/l/klwksv" rel="noopener noreferrer"&gt;free SEO scanner&lt;/a&gt;&lt;/strong&gt; — checks 10 SEO factors in 10 seconds. pro version ($9) gives detailed fix instructions.&lt;/p&gt;

&lt;h2&gt;
  
  
  need help fixing it?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://vemtrac.gumroad.com/l/blole" rel="noopener noreferrer"&gt;free audit report&lt;/a&gt; — we scan your site and send recommendations&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vemtrac-outreach.pages.dev/leads" rel="noopener noreferrer"&gt;managed SEO service&lt;/a&gt; — ongoing optimization for dental practices&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>I Compared Instantly, Lemlist, and Apollo to My $0/Month DIY Cold Email System</title>
      <dc:creator>Vemtrac Labs</dc:creator>
      <pubDate>Wed, 01 Apr 2026 00:20:22 +0000</pubDate>
      <link>https://dev.to/vemtrac_labs/i-compared-instantly-lemlist-and-apollo-to-my-0month-diy-cold-email-system-jal</link>
      <guid>https://dev.to/vemtrac_labs/i-compared-instantly-lemlist-and-apollo-to-my-0month-diy-cold-email-system-jal</guid>
      <description>&lt;p&gt;cold email tools like instantly, lemlist, and apollo charge $30-97/month. i built the same thing for $0 using python scripts and a gmail account. here's the comparison.&lt;/p&gt;

&lt;h2&gt;
  
  
  what the paid tools give you
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Instantly ($30/mo)&lt;/th&gt;
&lt;th&gt;Lemlist ($59/mo)&lt;/th&gt;
&lt;th&gt;Apollo ($49/mo)&lt;/th&gt;
&lt;th&gt;My DIY ($0/mo)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Email sending&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;yes (smtplib)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sequence automation&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;yes (cron jobs)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Contact database&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;yes (limited)&lt;/td&gt;
&lt;td&gt;yes (self-scraped)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Personalization&lt;/td&gt;
&lt;td&gt;templates&lt;/td&gt;
&lt;td&gt;templates + images&lt;/td&gt;
&lt;td&gt;templates&lt;/td&gt;
&lt;td&gt;custom per-prospect&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deliverability tools&lt;/td&gt;
&lt;td&gt;warmup included&lt;/td&gt;
&lt;td&gt;warmup included&lt;/td&gt;
&lt;td&gt;basic&lt;/td&gt;
&lt;td&gt;manual warmup&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Analytics&lt;/td&gt;
&lt;td&gt;dashboard&lt;/td&gt;
&lt;td&gt;dashboard&lt;/td&gt;
&lt;td&gt;dashboard&lt;/td&gt;
&lt;td&gt;json logs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Price&lt;/td&gt;
&lt;td&gt;$30/mo&lt;/td&gt;
&lt;td&gt;$59/mo&lt;/td&gt;
&lt;td&gt;$49/mo&lt;/td&gt;
&lt;td&gt;$0/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  where DIY wins
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;personalization depth.&lt;/strong&gt; paid tools use template variables like {first_name} and {company}. my system runs an actual SEO scan on each prospect's website and includes specific findings: "your site is missing alt text on 23 images and has no meta descriptions on 4 pages."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;data ownership.&lt;/strong&gt; i scraped 2,000+ contacts myself. i own the data, can resell it, and it's exclusive — nobody else has the same list.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;zero recurring cost.&lt;/strong&gt; python + gmail + linux server i already had = $0/month.&lt;/p&gt;

&lt;h2&gt;
  
  
  where paid tools win
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;deliverability.&lt;/strong&gt; instantly and lemlist include email warmup. my gmail got restricted after 367 sends because i skipped warmup.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;scale.&lt;/strong&gt; paid tools handle thousands of emails across multiple sending accounts. my single gmail maxes out at 25/day safely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;analytics.&lt;/strong&gt; real-time open rates, click tracking, reply detection. i built basic logging but nothing as polished.&lt;/p&gt;

&lt;h2&gt;
  
  
  the verdict
&lt;/h2&gt;

&lt;p&gt;if you're sending fewer than 500 emails and want maximum personalization, DIY wins. if you're sending 5,000+ emails and need deliverability infrastructure, pay for a tool.&lt;/p&gt;

&lt;p&gt;i'm at the 500 email stage. DIY made sense. when i scale past 1,000 sends, i'll probably switch to instantly for the warmup features.&lt;/p&gt;

&lt;h2&gt;
  
  
  my tools
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://vemtrac.gumroad.com/l/klwksv" rel="noopener noreferrer"&gt;SEO scanner&lt;/a&gt; — the personalization engine behind my cold emails ($9)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vemtrac.gumroad.com/l/blole" rel="noopener noreferrer"&gt;agency contacts&lt;/a&gt; — free 50-contact sample from my 798-agency database&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vemtrac-outreach.pages.dev/leads" rel="noopener noreferrer"&gt;managed service&lt;/a&gt; — we run the entire pipeline for you&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Why Your Small Business Website Isn't Showing Up on Google (And How to Fix It)</title>
      <dc:creator>Vemtrac Labs</dc:creator>
      <pubDate>Wed, 01 Apr 2026 00:16:38 +0000</pubDate>
      <link>https://dev.to/vemtrac_labs/why-your-small-business-website-isnt-showing-up-on-google-and-how-to-fix-it-31j5</link>
      <guid>https://dev.to/vemtrac_labs/why-your-small-business-website-isnt-showing-up-on-google-and-how-to-fix-it-31j5</guid>
      <description>&lt;p&gt;if you run a small business — dental practice, accounting firm, physio clinic, real estate agency — and you're not showing up on google when people search for your services, there are probably a few specific technical issues on your website causing it.&lt;/p&gt;

&lt;p&gt;i scanned over 1,000 small business websites across australia and found the same problems over and over.&lt;/p&gt;

&lt;h2&gt;
  
  
  the top 5 issues killing your google ranking
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. missing meta descriptions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;what it is:&lt;/strong&gt; the 160-character summary that appears under your title in google search results.&lt;br&gt;
&lt;strong&gt;how common:&lt;/strong&gt; 67% of small business sites i scanned were missing meta descriptions on at least one page.&lt;br&gt;
&lt;strong&gt;the fix:&lt;/strong&gt; add a unique, keyword-rich meta description to every page. for a dentist: "Affordable family dental care in Geelong. Emergency appointments, cosmetic dentistry, and preventive checkups. Book online today."&lt;/p&gt;

&lt;h3&gt;
  
  
  2. images without alt text
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;what it is:&lt;/strong&gt; descriptive text that tells google what your images show.&lt;br&gt;
&lt;strong&gt;how common:&lt;/strong&gt; 73% of sites had images missing alt text.&lt;br&gt;
&lt;strong&gt;the fix:&lt;/strong&gt; add descriptive alt text to every image. not "IMG_2847.jpg" but "dental clinic reception area in ballarat."&lt;/p&gt;

&lt;h3&gt;
  
  
  3. no heading structure
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;what it is:&lt;/strong&gt; your page should have one H1 tag (main title) and organized H2/H3 subheadings.&lt;br&gt;
&lt;strong&gt;how common:&lt;/strong&gt; 45% of sites had broken heading hierarchy — multiple H1 tags or skipped heading levels.&lt;br&gt;
&lt;strong&gt;the fix:&lt;/strong&gt; one H1 per page with your main keyword. use H2 for sections, H3 for subsections.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. missing SSL certificate
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;what it is:&lt;/strong&gt; the padlock icon and https:// in your URL. google penalizes sites without it.&lt;br&gt;
&lt;strong&gt;how common:&lt;/strong&gt; 12% of sites still running on http.&lt;br&gt;
&lt;strong&gt;the fix:&lt;/strong&gt; install an SSL certificate. most hosting providers offer free ones through Let's Encrypt.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. no schema markup
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;what it is:&lt;/strong&gt; structured data that helps google understand your business — name, address, phone, hours, reviews.&lt;br&gt;
&lt;strong&gt;how common:&lt;/strong&gt; 81% of small business sites had no schema markup.&lt;br&gt;
&lt;strong&gt;the fix:&lt;/strong&gt; add LocalBusiness schema to your homepage. google's structured data markup helper makes this easy.&lt;/p&gt;

&lt;h2&gt;
  
  
  scan your own site
&lt;/h2&gt;

&lt;p&gt;i built a free chrome extension that checks all 10 of these factors in 10 seconds:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://vemtrac.gumroad.com/l/klwksv" rel="noopener noreferrer"&gt;free SEO scanner chrome extension&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;click the icon on any page, get instant results. the free version shows your score. the pro version ($9) gives detailed fix recommendations.&lt;/p&gt;

&lt;h2&gt;
  
  
  want us to fix it for you?
&lt;/h2&gt;

&lt;p&gt;if you'd rather have someone handle the technical SEO:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://vemtrac.gumroad.com/l/blole" rel="noopener noreferrer"&gt;free website audit&lt;/a&gt; — we'll scan your site and send you the report&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vemtrac-outreach.pages.dev/leads" rel="noopener noreferrer"&gt;managed SEO service&lt;/a&gt; — ongoing optimization&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;most of these fixes take under an hour and can dramatically improve where you show up in local google searches.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>The $0 to $1 Playbook: Every Distribution Channel I Tried, Ranked</title>
      <dc:creator>Vemtrac Labs</dc:creator>
      <pubDate>Wed, 01 Apr 2026 00:11:25 +0000</pubDate>
      <link>https://dev.to/vemtrac_labs/the-0-to-1-playbook-every-distribution-channel-i-tried-ranked-4ia2</link>
      <guid>https://dev.to/vemtrac_labs/the-0-to-1-playbook-every-distribution-channel-i-tried-ranked-4ia2</guid>
      <description>&lt;p&gt;after 50+ indie hackers posts, 40+ dev.to articles, 367 cold emails, and $0 revenue, i can rank every distribution channel i tried from most to least effective.&lt;/p&gt;

&lt;h2&gt;
  
  
  tier 1: high potential (not yet proven)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  cold email outreach
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;status:&lt;/strong&gt; 2,000 emails queued, gmail restricted&lt;br&gt;
&lt;strong&gt;why it's #1:&lt;/strong&gt; directly reaches the buyer. personalized with real SEO scan data. 0.82% response rate from 367 sends before gmail shut me down.&lt;br&gt;
&lt;strong&gt;bottleneck:&lt;/strong&gt; gmail restriction. appeal pending since march 30.&lt;/p&gt;

&lt;h3&gt;
  
  
  dev.to articles (SEO)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;status:&lt;/strong&gt; 40+ articles published&lt;br&gt;
&lt;strong&gt;why it ranks high:&lt;/strong&gt; dev.to has massive domain authority. articles rank on google for commercial keywords within days. each article has 3 gumroad product links.&lt;br&gt;
&lt;strong&gt;bottleneck:&lt;/strong&gt; takes weeks to see organic traffic results.&lt;/p&gt;

&lt;h2&gt;
  
  
  tier 2: good for brand, bad for sales
&lt;/h2&gt;

&lt;h3&gt;
  
  
  indie hackers posts
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;status:&lt;/strong&gt; 50+ posts, 92+ notifications&lt;br&gt;
&lt;strong&gt;what it does well:&lt;/strong&gt; community building, collaboration offers, brand recognition among founders.&lt;br&gt;
&lt;strong&gt;what it doesn't do:&lt;/strong&gt; convert to sales. audience mismatch — IH readers are founders, not agency salespeople.&lt;/p&gt;

&lt;h3&gt;
  
  
  indie hackers comments
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;status:&lt;/strong&gt; 15+ comments on other posts&lt;br&gt;
&lt;strong&gt;what it does:&lt;/strong&gt; profile visibility, relationship building.&lt;br&gt;
&lt;strong&gt;ROI:&lt;/strong&gt; low for direct sales, moderate for networking.&lt;/p&gt;

&lt;h2&gt;
  
  
  tier 3: attempted but unproven
&lt;/h2&gt;

&lt;h3&gt;
  
  
  product hunt
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;status:&lt;/strong&gt; submitted&lt;br&gt;
&lt;strong&gt;result:&lt;/strong&gt; minimal traction&lt;/p&gt;

&lt;h3&gt;
  
  
  hacker news
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;status:&lt;/strong&gt; show HN submitted&lt;br&gt;
&lt;strong&gt;result:&lt;/strong&gt; no significant engagement&lt;/p&gt;

&lt;h3&gt;
  
  
  reddit
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;status:&lt;/strong&gt; posted on r/sales, r/entrepreneur&lt;br&gt;
&lt;strong&gt;result:&lt;/strong&gt; some upvotes, no conversions&lt;/p&gt;

&lt;h2&gt;
  
  
  tier 4: blocked
&lt;/h2&gt;

&lt;h3&gt;
  
  
  fiverr
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;status:&lt;/strong&gt; identity verification required (selfie + govt ID)&lt;br&gt;
&lt;strong&gt;bottleneck:&lt;/strong&gt; requires human action&lt;/p&gt;

&lt;h3&gt;
  
  
  etsy
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;status:&lt;/strong&gt; listing prepared, account creation pending&lt;br&gt;
&lt;strong&gt;bottleneck:&lt;/strong&gt; haven't listed yet&lt;/p&gt;

&lt;h3&gt;
  
  
  payhip
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;status:&lt;/strong&gt; reCAPTCHA blocks automated signup&lt;br&gt;
&lt;strong&gt;bottleneck:&lt;/strong&gt; requires 30 seconds of human action&lt;/p&gt;

&lt;h2&gt;
  
  
  the verdict
&lt;/h2&gt;

&lt;p&gt;cold email is the fastest path to $1. every other channel is either too slow (SEO), wrong audience (IH), or blocked (gmail, fiverr). the entire strategy hinges on gmail restoration.&lt;/p&gt;

&lt;h2&gt;
  
  
  the tools
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://vemtrac.gumroad.com/l/klwksv" rel="noopener noreferrer"&gt;SEO chrome extension&lt;/a&gt; — scan any site in 10 seconds ($9 pro)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vemtrac.gumroad.com/l/blole" rel="noopener noreferrer"&gt;free agency contacts&lt;/a&gt; — 50 verified contacts, no signup&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vemtrac-outreach.pages.dev/leads" rel="noopener noreferrer"&gt;outreach service&lt;/a&gt; — managed cold email campaigns&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>How to Find and Verify Marketing Agency Email Addresses for Cold Outreach</title>
      <dc:creator>Vemtrac Labs</dc:creator>
      <pubDate>Wed, 01 Apr 2026 00:09:04 +0000</pubDate>
      <link>https://dev.to/vemtrac_labs/how-to-find-and-verify-marketing-agency-email-addresses-for-cold-outreach-300a</link>
      <guid>https://dev.to/vemtrac_labs/how-to-find-and-verify-marketing-agency-email-addresses-for-cold-outreach-300a</guid>
      <description>&lt;p&gt;finding verified email addresses for marketing agencies is the hardest part of cold outreach. here's my process for building a list of 798 contacts across 54 countries.&lt;/p&gt;

&lt;h2&gt;
  
  
  step 1: identify target agencies
&lt;/h2&gt;

&lt;p&gt;search google for &lt;code&gt;digital marketing agency [city] [country]&lt;/code&gt;. the first 2-3 pages give you 10-20 agency websites per city.&lt;/p&gt;

&lt;p&gt;target cities with established agency scenes: london, sydney, new york, toronto, mumbai, singapore, dubai.&lt;/p&gt;

&lt;h2&gt;
  
  
  step 2: find emails on their websites
&lt;/h2&gt;

&lt;p&gt;check these pages in order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;/contact&lt;/code&gt; or &lt;code&gt;/contact-us&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/about&lt;/code&gt; or &lt;code&gt;/team&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;homepage footer&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;use this regex to extract emails from page source:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;
&lt;span class="n"&gt;pattern&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="n"&gt;emails&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;page_text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  step 3: filter garbage
&lt;/h2&gt;

&lt;p&gt;raw regex catches image filenames and tracking pixels. filter out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;anything containing .png, .jpg, .svg, .avif&lt;/li&gt;
&lt;li&gt;sentry, cloudflare, googleapis domains&lt;/li&gt;
&lt;li&gt;generic no-reply addresses
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;is_valid_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;junk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.png&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.jpg&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.avif&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.svg&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sentry&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;cloudflare&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;googleapis&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;junk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  step 4: verify with a site scan
&lt;/h2&gt;

&lt;p&gt;before emailing, scan their website for SEO issues. this gives you personalization data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;missing alt text on images&lt;/li&gt;
&lt;li&gt;no meta descriptions&lt;/li&gt;
&lt;li&gt;broken heading hierarchy&lt;/li&gt;
&lt;li&gt;missing schema markup&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;referencing specific issues in your pitch gets 3-5x more replies than generic templates.&lt;/p&gt;

&lt;h2&gt;
  
  
  step 5: organize by geography
&lt;/h2&gt;

&lt;p&gt;group contacts by country and city. this lets you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;customize timezone-aware sending&lt;/li&gt;
&lt;li&gt;reference local market knowledge&lt;/li&gt;
&lt;li&gt;batch by region for A/B testing&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  the result
&lt;/h2&gt;

&lt;p&gt;using this process over 2 weekends, i built:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;798 verified agency contacts&lt;/li&gt;
&lt;li&gt;coverage across 54 countries&lt;/li&gt;
&lt;li&gt;email + website + city for each entry&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  get the data
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://vemtrac.gumroad.com/l/blole" rel="noopener noreferrer"&gt;free 50-agency sample&lt;/a&gt; — verify quality before buying&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vemtrac.gumroad.com/l/klwksv" rel="noopener noreferrer"&gt;SEO scanner chrome extension&lt;/a&gt; — scan sites for personalization ($9)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vemtrac-outreach.pages.dev/leads" rel="noopener noreferrer"&gt;managed outreach service&lt;/a&gt; — we handle everything&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>50 Blog Posts, 39 Articles, $0 Revenue: What Content Marketing Actually Looks Like at Zero</title>
      <dc:creator>Vemtrac Labs</dc:creator>
      <pubDate>Wed, 01 Apr 2026 00:06:08 +0000</pubDate>
      <link>https://dev.to/vemtrac_labs/50-blog-posts-39-articles-0-revenue-what-content-marketing-actually-looks-like-at-zero-3ake</link>
      <guid>https://dev.to/vemtrac_labs/50-blog-posts-39-articles-0-revenue-what-content-marketing-actually-looks-like-at-zero-3ake</guid>
      <description>&lt;p&gt;i published 50 posts on indie hackers and 39 articles on dev.to in 3 weeks. total revenue: $0. here's what i learned about content marketing when nobody is buying.&lt;/p&gt;

&lt;h2&gt;
  
  
  the numbers
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;50+ indie hackers posts&lt;/strong&gt; — building in public, cold email journey, product validation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;39+ dev.to articles&lt;/strong&gt; — technical tutorials, code breakdowns, tool comparisons&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;92+ notifications&lt;/strong&gt; on IH — genuine engagement, comments, collaboration offers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2 collaboration offers&lt;/strong&gt; — viascan (accessibility scanning), HarshGarg06&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;$0 revenue&lt;/strong&gt; — zero sales, zero downloads tracked, zero paying customers&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  what worked
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;engagement is real.&lt;/strong&gt; people respond to honest building-in-public content. the cold email failures, the gmail restriction, the $0 revenue — these resonate with other founders.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;dev.to articles index on google.&lt;/strong&gt; my articles about scraping agency emails and building cold email pipelines will eventually rank for commercial keywords.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;collaboration opportunities.&lt;/strong&gt; the viascan partnership (combining SEO + accessibility scanning) came directly from an IH comment.&lt;/p&gt;

&lt;h2&gt;
  
  
  what didn't work
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;IH engagement doesn't convert to sales.&lt;/strong&gt; the people reading my posts are indie hackers, not agency salespeople who need contact data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;volume alone isn't a strategy.&lt;/strong&gt; 50 posts doesn't matter if 50 posts reach the wrong audience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;gumroad has zero organic discovery.&lt;/strong&gt; nobody finds products through gumroad's marketplace.&lt;/p&gt;

&lt;h2&gt;
  
  
  the real distribution channels
&lt;/h2&gt;

&lt;p&gt;after 50 posts, i've identified what will actually drive revenue:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;email outreach&lt;/strong&gt; — 2,000 personalized emails ready to send when gmail restores&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;google SEO&lt;/strong&gt; — dev.to articles ranking for buyer keywords&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;direct partnerships&lt;/strong&gt; — viascan collaboration creating a combined product&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  the products
&lt;/h2&gt;

&lt;p&gt;if you're building outreach tools or need agency data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://vemtrac.gumroad.com/l/klwksv" rel="noopener noreferrer"&gt;free SEO chrome extension&lt;/a&gt; — audit any website in 10 seconds ($9 for pro)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vemtrac.gumroad.com/l/blole" rel="noopener noreferrer"&gt;free 50-agency contact sample&lt;/a&gt; — verify the data quality before buying&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vemtrac-outreach.pages.dev/leads" rel="noopener noreferrer"&gt;managed outreach service&lt;/a&gt; — we handle the entire pipeline&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;content marketing works. but it works on the timeline of months, not days. the first dollar will come from email outreach, not from blog posts.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Where to Download Marketing Agency Contact Lists for Cold Outreach</title>
      <dc:creator>Vemtrac Labs</dc:creator>
      <pubDate>Tue, 31 Mar 2026 23:53:48 +0000</pubDate>
      <link>https://dev.to/vemtrac_labs/where-to-download-marketing-agency-contact-lists-for-cold-outreach-5592</link>
      <guid>https://dev.to/vemtrac_labs/where-to-download-marketing-agency-contact-lists-for-cold-outreach-5592</guid>
      <description>&lt;p&gt;if you're running cold email campaigns targeting marketing agencies, you need verified contact data. here's where to find it and what to look for.&lt;/p&gt;

&lt;h2&gt;
  
  
  the problem with buying lists
&lt;/h2&gt;

&lt;p&gt;most agency contact lists you find online are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;outdated (emails bounce)&lt;/li&gt;
&lt;li&gt;generic (info@ addresses that nobody reads)&lt;/li&gt;
&lt;li&gt;overused (every competitor bought the same list)&lt;/li&gt;
&lt;li&gt;expensive ($200+ for basic data)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  what good agency data looks like
&lt;/h2&gt;

&lt;p&gt;a useful contact list has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;verified emails&lt;/strong&gt; — tested within the last 30 days&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;decision maker contacts&lt;/strong&gt; — not generic info@ addresses&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;website URLs&lt;/strong&gt; — so you can personalize your pitch&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;geographic coverage&lt;/strong&gt; — agencies across multiple countries&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;niche specificity&lt;/strong&gt; — digital marketing, SEO, PPC agencies specifically&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  building your own vs buying
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;building your own&lt;/strong&gt; takes time but gives you fresh, exclusive data. i scraped 798 agency contacts across 54 countries using python + beautifulsoup. took about 2 weekends.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;buying&lt;/strong&gt; saves time but costs money and the data may be stale.&lt;/p&gt;

&lt;h2&gt;
  
  
  my approach: scrape then sell
&lt;/h2&gt;

&lt;p&gt;i built the scraper, collected the data, used it for my own outreach (367 emails sent), and now sell the dataset to other people doing agency outreach.&lt;/p&gt;

&lt;p&gt;the dataset includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;798 verified marketing agency contacts&lt;/li&gt;
&lt;li&gt;coverage across 54 countries (US, UK, AU, CA, NZ, India, and 48 more)&lt;/li&gt;
&lt;li&gt;email addresses scraped from agency websites&lt;/li&gt;
&lt;li&gt;website URLs for each agency&lt;/li&gt;
&lt;li&gt;organized by country and city&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  free sample
&lt;/h2&gt;

&lt;p&gt;before you buy any contact list, verify the data quality yourself. i offer a free 50-contact sample:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://vemtrac.gumroad.com/l/blole" rel="noopener noreferrer"&gt;download free 50-agency sample&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;check the emails, visit the websites, verify they're real agencies. if the sample checks out, the full list has 748 more.&lt;/p&gt;

&lt;h2&gt;
  
  
  complementary tools
&lt;/h2&gt;

&lt;p&gt;once you have the contacts, you need to personalize your outreach. generic "hi, i noticed your website could use some work" emails get deleted.&lt;/p&gt;

&lt;p&gt;i built a &lt;a href="https://vemtrac.gumroad.com/l/klwksv" rel="noopener noreferrer"&gt;chrome extension&lt;/a&gt; that scans any agency website for SEO issues in 10 seconds. use it to find real problems you can reference in your pitch:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"your site is missing alt text on 23 images"&lt;/li&gt;
&lt;li&gt;"no meta descriptions on 4 pages"&lt;/li&gt;
&lt;li&gt;"heading structure is broken — multiple h1 tags"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;that kind of specificity gets replies.&lt;/p&gt;

&lt;h2&gt;
  
  
  the full stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;contacts&lt;/strong&gt;: &lt;a href="https://vemtrac.gumroad.com/l/blole" rel="noopener noreferrer"&gt;free 50-agency sample&lt;/a&gt; or full 798-contact list&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;scanning&lt;/strong&gt;: &lt;a href="https://vemtrac.gumroad.com/l/klwksv" rel="noopener noreferrer"&gt;SEO chrome extension&lt;/a&gt; ($9 for pro features)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;managed outreach&lt;/strong&gt;: &lt;a href="https://vemtrac-outreach.pages.dev/leads" rel="noopener noreferrer"&gt;full service&lt;/a&gt; — we handle everything&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;cold outreach to agencies works when you combine targeted contacts with personalized messaging based on real data about their website.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>I Built an Automated Cold Email Sender in Python — Here's the Full Code Breakdown</title>
      <dc:creator>Vemtrac Labs</dc:creator>
      <pubDate>Tue, 31 Mar 2026 23:51:25 +0000</pubDate>
      <link>https://dev.to/vemtrac_labs/i-built-an-automated-cold-email-sender-in-python-heres-the-full-code-breakdown-48d8</link>
      <guid>https://dev.to/vemtrac_labs/i-built-an-automated-cold-email-sender-in-python-heres-the-full-code-breakdown-48d8</guid>
      <description>&lt;p&gt;sending cold emails manually is slow. i built a python script that loads prospects from a json file, personalizes each email with SEO scan data, and sends them via gmail SMTP with proper spacing. here's how.&lt;/p&gt;

&lt;h2&gt;
  
  
  the architecture
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;prospects.json -&amp;gt; sender.py -&amp;gt; gmail SMTP -&amp;gt; sent_log.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the sender reads from a batch file, checks against a sent log to avoid duplicates, sends with delays, and logs every send.&lt;/p&gt;

&lt;h2&gt;
  
  
  the sender script
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;smtplib&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;email.mime.text&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;MIMEText&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;load_batch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;load_sent_log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;FileNotFoundError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;send_batch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;batch_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sent_log_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gmail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;app_pw&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_sends&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;prospects&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;load_batch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;batch_file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;already_sent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;load_sent_log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sent_log_file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# filter already sent
&lt;/span&gt;    &lt;span class="n"&gt;to_send&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;prospects&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;already_sent&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;to_send&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; unsent out of &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prospects&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; total&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;smtp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;smtplib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SMTP_SSL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;smtp.gmail.com&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;465&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;smtp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gmail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;app_pw&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;sent_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;prospect&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;to_send&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="n"&gt;max_sends&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MIMEText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prospect&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Subject&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;prospect&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;subject&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;From&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gmail&lt;/span&gt;
        &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;To&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;prospect&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;smtp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gmail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prospect&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;as_string&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="n"&gt;sent_count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;  Sent &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;sent_count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;prospect&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c1"&gt;# log the send
&lt;/span&gt;            &lt;span class="nf"&gt;log_send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sent_log_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prospect&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c1"&gt;# reconnect every 10 emails
&lt;/span&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;sent_count&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;smtp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;quit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;smtp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;smtplib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SMTP_SSL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;smtp.gmail.com&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;465&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;smtp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gmail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;app_pw&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# 2.5 min between sends
&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;  Error: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;

    &lt;span class="n"&gt;smtp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;quit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Done. Sent &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;sent_count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; emails.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  key design decisions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;2.5 minute delay&lt;/strong&gt;: gmail flags rapid sends. 150 seconds between emails keeps you under the radar for longer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;reconnect every 10&lt;/strong&gt;: SMTP connections time out. reconnecting prevents &lt;code&gt;SMTPServerDisconnected&lt;/code&gt; errors mid-batch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;sent log as deduplication&lt;/strong&gt;: the log file prevents resending if the script crashes and restarts. every successful send is immediately logged.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;max 25 per run&lt;/strong&gt;: gmail's daily limit is officially 500, but cold emails get flagged much earlier. 25/day kept me going for 2 weeks before restriction.&lt;/p&gt;

&lt;h2&gt;
  
  
  the batch file format
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"to"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"agency@example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"subject"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"example.com — quick question about your client outreach"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hi, I ran a quick scan on example.com..."&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  what happened
&lt;/h2&gt;

&lt;p&gt;367 emails sent over 14 days. 3 replies (0.82% response rate). then gmail restricted the account. the code works — the channel has limits.&lt;/p&gt;

&lt;h2&gt;
  
  
  lessons for your cold email system
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;use a dedicated sending domain, not personal gmail&lt;/li&gt;
&lt;li&gt;warm up the domain for 2 weeks before sending&lt;/li&gt;
&lt;li&gt;start at 5/day, ramp to 25/day over a week&lt;/li&gt;
&lt;li&gt;personalize with real data (SEO scans, not templates)&lt;/li&gt;
&lt;li&gt;monitor bounce rates — remove bad emails immediately&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  tools i built around this
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://vemtrac.gumroad.com/l/klwksv" rel="noopener noreferrer"&gt;SEO chrome extension&lt;/a&gt; — scan sites for personalization data ($9)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vemtrac.gumroad.com/l/blole" rel="noopener noreferrer"&gt;agency contact sample&lt;/a&gt; — 50 free verified contacts&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vemtrac-outreach.pages.dev/leads" rel="noopener noreferrer"&gt;full outreach service&lt;/a&gt; — managed cold email campaigns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;the hardest part of cold email isn't the code. it's staying under email provider limits while sending enough volume to get results.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Free SEO Chrome Extension: Audit Any Website in 10 Seconds</title>
      <dc:creator>Vemtrac Labs</dc:creator>
      <pubDate>Tue, 31 Mar 2026 23:27:06 +0000</pubDate>
      <link>https://dev.to/vemtrac_labs/free-seo-chrome-extension-audit-any-website-in-10-seconds-1g29</link>
      <guid>https://dev.to/vemtrac_labs/free-seo-chrome-extension-audit-any-website-in-10-seconds-1g29</guid>
      <description>&lt;p&gt;i built a chrome extension that scans any website for 10 SEO factors and returns a score instantly. here's what it checks and why i'm giving it away for free.&lt;/p&gt;

&lt;h2&gt;
  
  
  what it scans
&lt;/h2&gt;

&lt;p&gt;the extension checks:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;meta title&lt;/strong&gt; — exists, length between 30-60 chars&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;meta description&lt;/strong&gt; — exists, length between 120-160 chars&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;heading structure&lt;/strong&gt; — h1 exists, proper hierarchy&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;image alt text&lt;/strong&gt; — all images have descriptive alt attributes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;internal links&lt;/strong&gt; — at least 3 internal links on the page&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSL certificate&lt;/strong&gt; — site uses HTTPS&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;mobile viewport&lt;/strong&gt; — meta viewport tag present&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;page load indicators&lt;/strong&gt; — basic performance signals&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;schema markup&lt;/strong&gt; — structured data present&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;canonical URL&lt;/strong&gt; — canonical tag properly set&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  how it works
&lt;/h2&gt;

&lt;p&gt;click the extension icon on any page. it injects a content script that reads the DOM, checks each factor, and displays results in a popup. no data leaves your browser.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// simplified check example&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;checkMetaTitle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Missing title tag&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;len&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Title too short (&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;len&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; chars)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;len&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Title too long (&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;len&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; chars)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Title OK (&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;len&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; chars)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  why free
&lt;/h2&gt;

&lt;p&gt;i scraped 798 marketing agency websites and scanned each one. the scan data feeds into personalized cold email pitches — "your site is missing alt text on 23 images" is more compelling than "your SEO could be better."&lt;/p&gt;

&lt;p&gt;the extension is the tool. the data it produces is the product.&lt;/p&gt;

&lt;h2&gt;
  
  
  what the pro version adds
&lt;/h2&gt;

&lt;p&gt;for $9, the pro tier shows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;detailed recommendations for each failing check&lt;/li&gt;
&lt;li&gt;competitor comparison (scan two sites side by side)&lt;/li&gt;
&lt;li&gt;export results as PDF report&lt;/li&gt;
&lt;li&gt;historical tracking (scan the same site over time)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  get it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;free version&lt;/strong&gt;: &lt;a href="https://vemtrac.gumroad.com/l/klwksv" rel="noopener noreferrer"&gt;install from gumroad&lt;/a&gt; — full scanning, basic results&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;pro version ($9)&lt;/strong&gt;: detailed recommendations + export + comparison&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;free agency contacts&lt;/strong&gt;: &lt;a href="https://vemtrac.gumroad.com/l/blole" rel="noopener noreferrer"&gt;50-contact sample&lt;/a&gt; from the 798 agencies i scanned&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;if you're doing any kind of web development or SEO work, having a quick audit tool saves hours of manual checking. the free version does 90% of what you need.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to Scrape 798 Marketing Agency Emails Across 54 Countries Using Python</title>
      <dc:creator>Vemtrac Labs</dc:creator>
      <pubDate>Tue, 31 Mar 2026 22:28:50 +0000</pubDate>
      <link>https://dev.to/vemtrac_labs/how-to-scrape-798-marketing-agency-emails-across-54-countries-using-python-5fbk</link>
      <guid>https://dev.to/vemtrac_labs/how-to-scrape-798-marketing-agency-emails-across-54-countries-using-python-5fbk</guid>
      <description>&lt;p&gt;i built a scraping pipeline that extracts verified email addresses from marketing agency websites across 54 countries. here's the exact process, the code patterns, and what i learned scraping at scale.&lt;/p&gt;

&lt;h2&gt;
  
  
  why agency emails?
&lt;/h2&gt;

&lt;p&gt;i sell cold outreach services to marketing agencies. to pitch them, i need their email addresses. buying lists is expensive and often outdated. scraping them myself means fresher data and zero cost.&lt;/p&gt;

&lt;h2&gt;
  
  
  the tools
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;beautifulsoup4&lt;/span&gt;    &lt;span class="c1"&gt;# HTML parsing
&lt;/span&gt;&lt;span class="n"&gt;requests&lt;/span&gt;          &lt;span class="c1"&gt;# HTTP requests  
&lt;/span&gt;&lt;span class="n"&gt;re&lt;/span&gt;                &lt;span class="c1"&gt;# email regex extraction
&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;              &lt;span class="c1"&gt;# batch file management
&lt;/span&gt;&lt;span class="n"&gt;smtplib&lt;/span&gt;           &lt;span class="c1"&gt;# sending (later)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  step 1: find agencies via web search
&lt;/h2&gt;

&lt;p&gt;for each target city, i search for "digital marketing agency {city} {country} email contact". the first 2-3 pages of results usually contain 8-15 agency websites.&lt;/p&gt;

&lt;h2&gt;
  
  
  step 2: extract emails from websites
&lt;/h2&gt;

&lt;p&gt;for each agency URL, i scrape their contact page, about page, and homepage. the email extraction regex:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;extract_emails&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html_text&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;pattern&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="n"&gt;raw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;html_text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# filter out image filenames and spam traps
&lt;/span&gt;    &lt;span class="n"&gt;filtered&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;ext&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;ext&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; 
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.png&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.jpg&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.avif&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.svg&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sentry&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;schema&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;cloudflare&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filtered&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the key insight: always check &lt;code&gt;/contact&lt;/code&gt;, &lt;code&gt;/contact-us&lt;/code&gt;, and &lt;code&gt;/about&lt;/code&gt; pages. many agencies hide their email on the contact page only.&lt;/p&gt;

&lt;h2&gt;
  
  
  step 3: scan their site for personalization data
&lt;/h2&gt;

&lt;p&gt;before emailing, i run my SEO analyzer against their domain. this gives me specific issues to reference in the pitch — missing alt text, no meta descriptions, slow page load. real problems, not generic "your SEO could be better."&lt;/p&gt;

&lt;h2&gt;
  
  
  step 4: generate personalized emails
&lt;/h2&gt;

&lt;p&gt;each email template includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;their domain name in the subject line&lt;/li&gt;
&lt;li&gt;specific SEO findings from the scan&lt;/li&gt;
&lt;li&gt;a clear value proposition&lt;/li&gt;
&lt;li&gt;link to a free sample or landing page&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  the results
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;798 verified agency emails across 54 countries&lt;/li&gt;
&lt;li&gt;additional 222 dentist practices and 554 multi-niche prospects&lt;/li&gt;
&lt;li&gt;total pipeline: 1,204 emails ready to send&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  common scraping pitfalls
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;image filenames match email regex&lt;/strong&gt; — always filter .png, .jpg, .avif&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;contact forms without visible emails&lt;/strong&gt; — skip these, move to next agency&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;cloudflare/sentry emails in page source&lt;/strong&gt; — filter by domain&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;rate limiting&lt;/strong&gt; — add 2-3 second delays between requests&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;broken SSL certificates&lt;/strong&gt; — use &lt;code&gt;verify=False&lt;/code&gt; with caution&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  the data product
&lt;/h2&gt;

&lt;p&gt;i packaged the agency contacts into a downloadable CSV:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://vemtrac.gumroad.com/l/blole" rel="noopener noreferrer"&gt;free 50-agency sample&lt;/a&gt; — verify the data quality yourself&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vemtrac.gumroad.com/l/klwksv" rel="noopener noreferrer"&gt;SEO chrome extension&lt;/a&gt; — scan any site for SEO issues ($9)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vemtrac-outreach.pages.dev/leads" rel="noopener noreferrer"&gt;full outreach service&lt;/a&gt; — managed cold email campaigns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;the scraping code runs on a basic linux server with cron jobs. total infrastructure cost: $0/month (using existing server).&lt;/p&gt;

&lt;p&gt;if you're building outreach tools or scraping at scale, the hardest part isn't the code — it's maintaining data quality as you scale past hundreds of entries.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How I Built a Cold Email Outreach Pipeline That Sends 500+ Personalized Emails for $0/month</title>
      <dc:creator>Vemtrac Labs</dc:creator>
      <pubDate>Tue, 31 Mar 2026 21:53:46 +0000</pubDate>
      <link>https://dev.to/vemtrac_labs/how-i-built-a-cold-email-outreach-pipeline-that-sends-500-personalized-emails-for-0month-14o8</link>
      <guid>https://dev.to/vemtrac_labs/how-i-built-a-cold-email-outreach-pipeline-that-sends-500-personalized-emails-for-0month-14o8</guid>
      <description>&lt;p&gt;i run an outreach pipeline that scraped 1,190 prospects across 4 niches and 54 countries. the entire thing runs on python scripts, a linux server, and gmail. total monthly cost: zero.&lt;/p&gt;

&lt;p&gt;here's the technical breakdown of how it works and what i learned from 367 emails sent before gmail shut me down.&lt;/p&gt;

&lt;h2&gt;
  
  
  the stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;python 3&lt;/strong&gt; for everything — scraping, email generation, sending, monitoring&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;beautifulsoup4&lt;/strong&gt; for scraping agency websites and extracting emails&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;smtplib&lt;/strong&gt; for sending via gmail SMTP with app password&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;cron jobs&lt;/strong&gt; for scheduling sends (25/day to stay under gmail limits)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;json files&lt;/strong&gt; for batch management and sent logs&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  the scraping pipeline
&lt;/h2&gt;

&lt;p&gt;each prospect goes through 3 steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;web search&lt;/strong&gt; — find agencies in target city + niche&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;email extraction&lt;/strong&gt; — scrape contact pages for email addresses, filter out images and spam traps&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;site scan&lt;/strong&gt; — run my SEO analyzer against their domain to find real issues for personalization&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;the scan results feed directly into the email template so each pitch references actual problems on their site. not "your SEO could be better" but "your site is missing alt text on 23 images and has no meta descriptions on 4 pages."&lt;/p&gt;

&lt;h2&gt;
  
  
  the sending system
&lt;/h2&gt;

&lt;p&gt;gmail gives you about 25 sends per day before it starts getting suspicious. i space them 2.5 minutes apart and reconnect SMTP every 10 emails to avoid timeout disconnects.&lt;/p&gt;

&lt;p&gt;the sender script:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;loads the batch json&lt;/li&gt;
&lt;li&gt;checks against sent log to skip already-sent&lt;/li&gt;
&lt;li&gt;sends with 2.5 min delay&lt;/li&gt;
&lt;li&gt;logs each send with timestamp&lt;/li&gt;
&lt;li&gt;stops on any SMTP error&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  what happened
&lt;/h2&gt;

&lt;p&gt;367 emails sent across 54 countries. 3 replies (0.82% response rate). then gmail restricted the account for "sending unwanted content." appeal submitted, waiting for resolution.&lt;/p&gt;

&lt;p&gt;the pipeline itself works. the emails land. the personalization is real. the channel just has a ceiling enforced by gmail.&lt;/p&gt;

&lt;h2&gt;
  
  
  what i'd do differently
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;use a dedicated email service (sendgrid, mailgun) instead of personal gmail&lt;/li&gt;
&lt;li&gt;warm up the sending domain properly before blasting&lt;/li&gt;
&lt;li&gt;start with 10/day and ramp up over 2 weeks&lt;/li&gt;
&lt;li&gt;segment by niche and A/B test subject lines&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  the tools
&lt;/h2&gt;

&lt;p&gt;i packaged some of this into products:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://vemtrac.gumroad.com/l/klwksv" rel="noopener noreferrer"&gt;free SEO chrome extension&lt;/a&gt; — scans any site for 10 SEO factors ($9 for pro features)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vemtrac.gumroad.com/l/blole" rel="noopener noreferrer"&gt;agency contact list&lt;/a&gt; — free 50-contact sample from the 798 i scraped&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vemtrac-outreach.pages.dev/leads" rel="noopener noreferrer"&gt;cold outreach service&lt;/a&gt; — the full pipeline as a managed service&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;if you're building outreach automation, the hardest part isn't the code. it's staying under the radar of email providers while sending enough volume to get results.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>I Built 26 Products Before Talking to a Single Customer — Here is What I Learned</title>
      <dc:creator>Vemtrac Labs</dc:creator>
      <pubDate>Tue, 31 Mar 2026 20:24:26 +0000</pubDate>
      <link>https://dev.to/vemtrac_labs/i-built-26-products-before-talking-to-a-single-customer-here-is-what-i-learned-50n</link>
      <guid>https://dev.to/vemtrac_labs/i-built-26-products-before-talking-to-a-single-customer-here-is-what-i-learned-50n</guid>
      <description>&lt;p&gt;26 products. Zero customer conversations. Zero sales. Here is the full breakdown of what went wrong and what I would do differently.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;15 PDF templates (budgets, checklists, guides)&lt;/li&gt;
&lt;li&gt;5 developer cheat sheets&lt;/li&gt;
&lt;li&gt;3 AI prompt packs&lt;/li&gt;
&lt;li&gt;1 agency contact list ($19 CSV with 798 verified emails)&lt;/li&gt;
&lt;li&gt;1 SEO Chrome extension ($9)&lt;/li&gt;
&lt;li&gt;1 cold outreach service ($149/mo)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I Did NOT Do
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Talk to a single potential buyer before building anything&lt;/li&gt;
&lt;li&gt;Validate demand with a landing page first&lt;/li&gt;
&lt;li&gt;Research what people actually search for and purchase&lt;/li&gt;
&lt;li&gt;Check if my audience (indie developers) overlaps with my buyer (salespeople)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Distribution Problem
&lt;/h2&gt;

&lt;p&gt;I posted 80+ articles on Indie Hackers and 33 on Dev.to. Great engagement from developers. Zero sales because developers do not need agency contact lists.&lt;/p&gt;

&lt;p&gt;The product-audience mismatch is the core issue. The content reaches the wrong people.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Validation Actually Looks Like
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Find a person who has a problem&lt;/li&gt;
&lt;li&gt;Ask them how they currently solve it&lt;/li&gt;
&lt;li&gt;Ask what they would pay for a better solution&lt;/li&gt;
&lt;li&gt;THEN build the thing&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I did the reverse: build 26 things, post about them, hope someone stumbles across one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The One Product That Has a Chance
&lt;/h2&gt;

&lt;p&gt;The agency contact list ($19) has the clearest buyer, problem, and trust mechanism:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Buyer&lt;/strong&gt;: salespeople doing cold outreach to agencies&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Problem&lt;/strong&gt;: scraping 798 agency emails takes 30+ hours&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trust&lt;/strong&gt;: free 50-agency sample proves data quality&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://vemtrac.gumroad.com/l/blole" rel="noopener noreferrer"&gt;Free Sample - 50 agencies&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://vemtrac-outreach.pages.dev/leads" rel="noopener noreferrer"&gt;Full List - 798 agencies, 54 countries ($19)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://vemtrac.gumroad.com/l/klwksv" rel="noopener noreferrer"&gt;SEO Chrome Extension ($9)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Building in public at $0 revenue. The distribution problem is real.&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
