20
18 Comments

How Cold Emailing Grew My B2B Startup To $100k MRR

Cold outreach: The art and science of making people not only aware of you, but interested in you and what you have to offer. Cold emailing specifically has been key to growing my B2B startup, Proxycurl.

I previously wrote this post talking about what I did to grow to $1MM ARR in 18 months. That was at the beginning of 2023, and it's nearly the end of 2023 already. We have our eyes set on $5M ARR now.

Cold email still remains fundamental to the growth of Proxycurl as we've continued to scale. Any startup founder should be utilizing cold outreach, especially B2B startups.

For a founder, cold outreach is ultra-relevant when it comes to gaining initial traction and hitting that big $100,000 monthly recurring revenue milestone while you're bootstrapping it still. No one else is going to know a product better than the founder, therefore, no one else is going to be able to sell it as well as the founder.

In my last post, I told the story of what I was doing to grow my startup, Proxycurl, to $1MM ARR. After publishing, I received quite a few questions asking me specifically how I did my cold emailing, my processes, etc.

So, today I'm going to be showing you how I used cold email to grow my B2B startup to $100,000 (and beyond) MRR...

First, though, we need to talk about:

Why cold outreach is especially important for B2B startups

Customer acquisition for a B2C company is vastly different from a B2B.

It's understandable why when you put it in the lens of comparing something like a $15.49 per month Netflix subscription to something like a $1,000 per month bill to Amazon Web Services just to power your business.

The sales cycle on something that costs $1,000 per month is going to take longer than a product that costs $15.49. It's simply harder to sell higher-priced products and services.

It's a scary thought for B2B founders knowing it takes a significant amount of effort to close a deal. They can't mass advertise to broad audiences with low-ticket products and offers like a B2C brand could.

Advertising frequently results in money lost for B2B startups. It's not as easy as making a Facebook or YouTube ad and linking directly to a sales page.

At Proxycurl we've primarily relied on two channels:

  • Cold email
  • SEO

Almost all of our initial traction came from me sending out cold emails. It got us to our first million dollars in revenue.

My only problem with cold emailing was that it worked a little bit too well! The biggest constraint was time and human resources.

Cold email is especially relevant for B2B startups for three very simple reasons:

1. Email is still incredibly relevant.

Your audience is going to have an email they check multiple times a day. Plus, you're not relying on a platform like LinkedIn that can ban you.

It's built into the internet and will continue to be here.

2. It's very cheap to do.

Anyone can afford to do cold outreach.

3. B2B offers often take a bit more convincing.

This sounds like a con, and it is, but it's also a pro...

I sent out thousands of emails to different companies to schedule hundreds of video calls. I'd get on the calls and explain what we did, address objections, and eventually, I'd get a few of them to try Proxycurl. Rinse and repeat.

I was able to convince people to try us because as a founder I had an extensive level of product knowledge, given I designed the entire product.

The very nature of B2B requires you to be a bit more hands-on to deliver specific solutions to businesses, so, a cold outreach sales process allows you to do that more than a standard B2C sales funnel would.

The one con to cold emailing

The con is it does take time, and a certain level of sales skills (as any founder should have), but can certainly be outsourced with a bit of effort, as you scale.

I'd like to note I'm also a very introverted programmer by nature. If I'm able to hop on sales calls then I guarantee you that you can, too.

The pro of a more hands-on sales process with a specific problem/solution fit for businesses with your product is that it allows you to ask for higher prices.

Understanding the B2B sales cycle

The B2B sales cycle puts an emphasis on building high-value long-term relationships with decision makers.

You're not putting broad ads out on YouTube like a B2C business, and asking for a payment today with a post-purchase upsell to match.

Instead, with B2B, you're identifying a specific target audience with a problem and reaching out to them directly with a tailor-made solution.

So, yes, the con is it does take more effort - but the pro is one client can be worth the same as a hundred, even a thousand B2C clients.

For a bootstrapped startup, the ability to pursue fewer clients that bring more reoccurring money is major. One enterprise client can practically fund the entire development of your B2B business.

With a B2C SaaS for instance, while the sales cycle is more transactional, it's not uncommon to see companies paying $50 per free trial conversion that they don't even break even on for 6 months.

There's a reason why new B2B startups are born every day, and there's a reason why you're reading this right now.

As Microsoft, Salesforce, HubSpot, and beyond have shown us.... the B2B space is very lucrative when done right.

Before we even get to sending cold emails, it's important you're 100% clear on a single question.

What problem are you solving?

Think about it...

What problem is your product truly solving? Who is it solving for?

I'll give you an example. In Proxycurl's case, we have a couple of different B2B products:

  • LinkDB (very large LinkedIn dataset, enterprise)
  • Proxycurl API (LinkedIn scraping API, anyone tech savvy could use it)
  • Sapiengraph (get fresh and rich data pulled into Google Sheets, anyone at all could use it)

Ultimately, all of our products do the same thing; provide rich data about people and companies. They just serve different audiences.

When it came to thinking of who I needed to get in front of to get my product sold, what I asked was: Who could use my product in the most profitable way?

For me, that was:

This list is likely different for you.

You'll need to identify what painful problem you're truly solving, and who you're solving it for before you waste a single second on cold emailing. That's step one.

If your product truly makes people's lives easier and solves a problem, that's 50% of the selling done for you before you ever send an email.

Build your prospecting list

Pick one ideal customer profile that you think would have a good problem/solution fit with your product.

Create a list of candidates that match this ICP. There are a couple of different ways to do this. When I first started Proxycurl I used Crunchbase Pro to seed my email list.

Now that Proxycurl is a mature product, though, we can build our own prospecting lists entirely through our own product - and so can you!

Proxycurl Search API demo

Here's how code using Proxycurl's Person Search Endpoint might look. In this example, we're targeting real-estate agents to pitch a product that can help them book showings more easily. We're primarily B2B focused, so we're looking to secure contracts with agencies.

Therefore, we'll reach out to individual real estate agents - who work at agencies.

Crucial when making a search like this is the exhaustive list of company industries on LinkedIn. We provide this list for free, and it's directly linked from our documentation in the current_company_industry explanation. In the following code sample, we're using Real Estate, but you might want to get a bit more specific than that.

Here's sample Python code:

import json, os, requests
api_key = os.environ['PROXYCURL_API_KEY']
headers = {'Authorization': 'Bearer ' + api_key}

person_endpoint = 'https://nubela.co/proxycurl/api/search/person'
params = {
    'country': 'US',
    'current_role_title': '(?i)real estate',
    'current_company_industry': '^Real Estate$',
}
response = requests.get(person_endpoint, params=params, headers=headers)
result = response.json()
print(json.dumps(result, indent=2))

This gets us a LOT of results - maybe too many. One way to refine it might be with the parameters current_company_employee_count_min or current_company_employee_count_max if you want to target a company of a particular size. You could also look for more mature companies or perhaps more recently-founded ones using current_company_founded_before_year and current_company_founded_after_year.

But another parameter that might interest you is current_role_after - if someone has recently joined a new company, they're more likely to be open to doing things a new way. They may also be recently promoted to a new role they haven't held before. Try adding that to your queries.

Here's an updated set of params (the rest of the query is omitted for brevity):

params = {
    'country': 'US',
    'current_role_title': '(?i)real estate',
    'current_role_after': '2023-01-01',
    'current_company_industry': '^Real Estate$',
}

Keep in mind, you can always run multiple Search queries and reach out to their results. Just make sure you de-duplicate your results in case someone showed up twice.

What do I do with a list of prospects?

There is a parameter in the Search API called enrich_profiles=enrich. You probably do not want to do this, because what you need is someone's personal or work email, not their entire profile. So there is another step.

You have two options - either Proxycurl or Sapiengraph, our Google Sheets product. Either one can be used to fetch a personal email, but at this time, only Proxycurl supports fetching work emails.

Personal emails with Proxycurl

We'll use the Personal Email Lookup Endpoint this time.

Because we need to make many small requests (as opposed to before, when we made one large request), we're going to use proxycurl-py, Proxycurl's async library, for help. We'll do this in both this and the next example. Our LinkedIn profiles are listed one per line in a file called example.csv (in the same directory as our code) with no headings and nothing else in the file.

Here's what example.csv looks like right now:

https://www.linkedin.com/in/williamhgates/
https://www.linkedin.com/in/barackobama/

And here's how we'll get personal emails:

import asyncio, import csv, import os

from proxycurl_py.asyncio import Proxycurl, do_bulk

try:
    asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
except AttributeError:
    pass

proxycurl = Proxycurl(api_key=os.environ['PROXYCURL_API_KEY'])

bulk_linkedin_person_data = []
with open('example.csv', 'r') as file:
    reader = csv.reader(file)
    for row in reader:
        bulk_linkedin_person_data.append(
            (proxycurl.linkedin.person.personal_email, {
                'linkedin_profile_url': row[0],
            })
        )
results = asyncio.run(do_bulk(bulk_linkedin_person_data))
print(results)

Each item in results is a Result, a type that you can import from proxycurl_py.asyncio and then work with further. Here's how the response looks:

[
  Result(
    success=True,
    value={
      'emails': ['billg@microsoft.com', 'bill.gates@gatesfoundation.org'],
      'invalid_emails': []
    },
    error=None
  ), 
  Result(
    success=True,
    value={
      'emails': ['slanghinrichs@barackobama.com'],
      'invalid_emails': []
    },
    error=None
  )
]

Work emails with Proxycurl

This last one is a bit more complicated - work emails are returned asynchronously via a webhook. You can set up your own system if you're looking to build stable in-house tooling, or you can use https://webhook.site for free and copy-paste a bunch. In this example, we'll use https://webhook.site for convenience.

Here is the code, using the Work Email Lookup Endpoint and still using proxycurl-py:

import asyncio, csv, os

from proxycurl_py.asyncio import Proxycurl, do_bulk

try:
    asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
except AttributeError:
    pass

proxycurl = Proxycurl(api_key=os.environ['PROXYCURL_API_KEY'])

bulk_linkedin_person_data = []
with open('example.csv', 'r') as file:
    reader = csv.reader(file)
    for row in reader:
        bulk_linkedin_person_data.append(
            (proxycurl.linkedin.person.lookup_email, {
                'linkedin_profile_url': row[0],
                'callback_url': 'https://webhook.site/faea124b-f152-480e-87df-8dbd8e0eeba5'})
        )
results = asyncio.run(do_bulk(bulk_linkedin_person_data))

Personal emails with Sapiengraph

You can also check out Sapiengraph, our new product that lets you fetch the very same LinkedIn data that Proxycurl offers - directly in Google Sheets.

In this case, let's put the LinkedIn URLs in column A, and the emails in column B. The formula we're using is:

=SG_PERSONAL_EMAILS(A2)

And here's how our spreadsheet looks:

Google Sheets enrich for personal emails with Sapiengraph

But wait! There are multiple emails there! What if we want only one? No problem. Let's use the built-in formula SPLIT. We don't want to send duplicate emails to the same person anyway, so we can take the first column.

The formula we've used is:

=SPLIT(B2,",")

And here's an updated screenshot:

Google Sheets enrich for personal emails with Sapiengraph - split emails

When using Sapiengraph, always remember to convert your formulas to text once you're done modifying them so you avoid accidental charges!

(This won't touch SPLIT - only the Sapiengraph formulas are affected.)

Verify your emails

After you've sourced your data, you'll want to verify the contact information you have is valid.

We offer a Disposable Email Address Check Endpoint for entirely free over at Proxycurl.

import json, os, requests
api_key = os.environ['PROXYCURL_API_KEY']
headers = {'Authorization': 'Bearer ' + api_key}

api_endpoint = 'https://nubela.co/proxycurl/api/disposable-email'
params = {
    'email': 'colton@nubela.co',
}
response = requests.get(api_endpoint, params=params, headers=headers)
result = response.json()
print(json.dumps(result, indent=2))

With a little bit of Python, you can extremely quickly verify if the email addresses you've sourced are:

  1. Free email addresses.
  2. Disposable email addresses.

...and dispose of them. Saving yourself the time and effort of doing cold emails to people that have less than a 1% chance of ever buying your product.

Time for execution

With a now double-checked high-quality prospecting list, it's time to work on sending emails.

Right now we're using three main tools for cold emailing:

  1. Google Suite ($6 per user per month)
  2. Amazon Simple Email Service ($0.10 for 1000 emails)
  3. Self-hosted Sendy (one payment of $69)

At Proxycurl, we also use:

  • Calendly for booking meetings
  • Google Meet for the actual meetings

Create a new domain and email specifically for cold emails

The first step is to create an email you'll be sending from.

I suggest a domain different from your main domain name. The reason I say this is sometimes cold emailing can lead to deliverability issues for your main domain, something you wouldn't want from a support email address for instance.

In my case, I created a new email in Google Suite, "steven@proxycurl.com" to forward to "steven@nubela.co" – that way I can receive the replies back to my cold emails while protecting the deliverability of my main domain.

Make sure you have your DNS configured properly with SPF records, etc, so that you're actually inboxing. Review your score on mail-tester.com.

Once you have your email situated, we'll need to make sure we have web hosting before moving on to the next step.

A web server

To host Sendy, you'll need a capable web host that provides the ability to create a MySQL database and supports both .htaccess and PHP.

That means you can't use Nginx. It has to be on Apache, LiteSpeed, or OpenLiteSpeed. Most popular web hosts use LiteSpeed.

For testing or starting out, you can get by with a traditional shared host like DreamHost. Just make sure they have at least one CPU core and at least 1GB of ram.

Optional extra information on hosting

Sendy isn't a huge resource hog, but it depends on how much you're sending.

Eventually, it may be worth getting a VPS or dedicated server from someone like Vultr, Hetzner, or OVH.

You can install your own panel afterward like cPanel or DirectAdmin so that you don't have to do any real system administration, too.

Do NOT fall into the trap of trying to avoid "technical debt" here. If you spend very little time on your first setup, then you haven't wasted anything early on. Keep things simple and don't allow yourself to overcomplicate things too early.

Setting up Sendy

The process for obtaining a Sendy license requires only that you pay them $69 and you'll receive a license in your email.

Then you'll enter your license key:

Screenshot of entering a license key

Afterward, you'll receive a .zip folder with everything you need inside.

We'll take that .zip and upload it to /public_html on our web server.

sendy.zip

Then extract the sendy.zip file, open it up, and look for /includes:

sendy includes

Open it up and look for config.php:

chrome_hRucOXlScY

You'll need to replace some information here, including your installation URL and your MySQL database.

/*  Set the URL to your Sendy installation (without the trailing slash) */
	define('APP_PATH', 'https://your_sendy_installation_url');
	
	/*  MySQL database connection credentials (please place values between the apostrophes) */
	$dbHost = ''; //MySQL Hostname
	$dbUser = ''; //MySQL Username
	$dbPass = ''; //MySQL Password
	$dbName = ''; //MySQL Database Name

Once you've verified all of the information in config.php is correct, go ahead and go to the URL you've installed Sendy at.

Then it'll ask for a couple of things like your license and the email you'd like to use for the admin login.

Success! Now time to link AWS SES with Sendy...

Upon the first login, you'll see this:

aws ses sendy

We'll go ahead and add our first brand...

sendy brand

Fill out the information here accordingly. Make sure the address used in both the from/reply-to is valid and functional. You'll need to verify it.

We'll then see our new brand created. I went ahead and named it "Real Estate" to go along with the example given above.

real estate

On the top right, click your name and then "Settings", alternatively just go to /settings.

We'll need to integrate AWS SES with Sendy now. The first thing you need to do is select the closest AWS region to your server.

In my case, it's North Virginia or us-east-1, so I've gone ahead and selected that accordingly:

ses

Next, you'll need to create AWS IAM credentials. The link to do that is right here.

Give the new IAM user AmazonSNSFullAccess permissions and copy both the public and secret keys over to Sendy:

amazonsnsfullaccess

Now you've successfully installed Sendy with the ability to send emails. Great job!

Importing your prospecting list into Sendy

We've created our brand, but we still need to import our list.

Click on your new brand and click "Add a new list", name it, and then you can keep all of the other settings default like single or double opt-in. It won't matter to us.

prospecting list

If you click "Add subscribers"

add subscribers

You'll see a page that looks like this:

real estate csv

The part at the bottom there about setting up a cron job is important and I would recommend it.

A cron is simply a job scheduler for Linux systems. It'll automatically do things for us at timed intervals.

So, for example, we could use the following cron:

* * * * * php /home/your_user_here/web/SendyInstallation.com/public_html/sendy/import-csv.php > /dev/null 2>&1

To run every minute.

If we wanted to be a bit more cautious about restarting, we could restart every five minutes, and run something like this (every minute, divided by 5):

*/5 * * * * php /home/your_user_here/web/SendyInstallation.com/public_html/sendy/import-csv.php > /dev/null 2>&1

The command part of the cron tells PHP to reliably import our .CSV. No worries about timeouts. Most hosts have a UI on their web hosting panel to add cron jobs; if you're using the command line, then type crontab -e to access it.

As you continue using Sendy, you'll notice the first time you use certain features, it'll recommend setting up a cron.

By default, Sendy supports importing:

  • Full name
  • Email

custom sendy fields

But you can also add "custom fields" that serve different segmentation and personalization purposes.

For example, we could import the business name as well:

custom fields

Or whatever else you'd like to import. The more data you have, the better.

BUT WAIT! Do not import manually

I'm a big fan of automation. I want to configure predetermined autoresponders to automatically send on my behalf. I want to load different ICPs into Sendy and have it "just work."

It turns out that Sendy will not allow manually-imported emails to automatically be placed into an autoresponder. But that's ok, because we can instead use the Sendy API to import our email list; and then we'll be able to automate everything in the future.

In your Sendy installation, create a new folder named /import, then create the following file named index.php:

<?php

//-------------------- EDIT HERE -----------------------//
$sendy_url = 'https://SendyInstallation.com';
$api_key = 'xxxxxxxxxxxxxx';
$list_id = 'xxxxxxxxxxxxxx'; 
$csv_file = 'file.csv';	
//------------- STOP EDITING HERE --------------------//
ini_set('auto_detect_line_endings',TRUE);
$file_handle = fopen($csv_file, "r");
$ch = curl_init();
 
while (!feof($file_handle) ) {
set_time_limit(0);
 
$line_of_text = fgetcsv($file_handle, 1024);
 
$fields = array(
	'name' => urlencode($line_of_text[0]),
	'email' => urlencode($line_of_text[1]),
//------------------ EDIT HERE ------------------------//
// add as many custom params as you want to your csv
// they must be capitalized the same way as they are in Sendy
// remember to increment the index in the brackets!
// delete or comment this one if you aren't using "Business"
    'Business' => urlencode($line_of_text[2]),
//------------- STOP EDITING HERE --------------------//
	'api_key' => urlencode($api_key),
	'list' => urlencode($list_id)
);
 
foreach($fields as $key=>$value) { $fields_string .= $key.'='.$value.'&'; }
rtrim($fields_string, '&');
 
curl_setopt($ch,CURLOPT_URL, $sendy_url.'/subscribe');
curl_setopt($ch,CURLOPT_POST, count($fields));
curl_setopt($ch,CURLOPT_POSTFIELDS, $fields_string);
 
if ($line_of_text[0] != ''){
        curl_exec($ch);
        sleep(5);
}
 
echo $line_of_text[1];
echo '<br>';
 
}
 
fclose($file_handle);
curl_close($ch);
//------------------------------------------------------//

?>

You'll need to update the following to their real values, but don't edit anything else about the script.

  • $sendy_url = 'https://SendyInstallation.com';
  • $api_key = 'xxxxxxxxxxxxxx';
  • $list_id = 'xxxxxxxxxxxxxx';
  • $csv_file = 'file.csv';

Your Sendy $api_key is available under the settings tab we went to earlier.

Your $list_id is available under your brand:

Where to find list_id

The csv file should be in the same folder as the script. It should be formatted like this:

Example of a properly-formatted CSV

Remember to keep your custom fields in order! They should NOT have headers or an empty line at the start. Data only.

Importing more than just name and email

If you want to import information like business name, phone number, or more, we can also do this.

Just make sure your custom field is already added in Sendy and we can modify the above script like this:

<?php

//-------------------- EDIT HERE -----------------------//
$sendy_url = 'https://SendyInstallation.com';
$api_key = 'xxxxxxxxxxxxxx';
$list_id = 'xxxxxxxxxxxxxx'; 
$csv_file = 'file.csv';	
//------------- STOP EDITING HERE --------------------//
ini_set('auto_detect_line_endings',TRUE);
$file_handle = fopen($csv_file, "r");
$ch = curl_init();
 
while (!feof($file_handle) ) {
set_time_limit(0);
 
$line_of_text = fgetcsv($file_handle, 1024);
 
$fields = array(
	'name' => urlencode($line_of_text[0]),
	'email' => urlencode($line_of_text[1]),
//------------------ EDIT HERE ------------------------//
// add as many custom params as you want to your csv
// they must be capitalized the same way as they are in Sendy
// remember to increment the index in the brackets!
// delete or comment this one if you aren't using "Business"
    'Business' => urlencode($line_of_text[2]),
//------------- STOP EDITING HERE --------------------//
	'api_key' => urlencode($api_key),
	'list' => urlencode($list_id)
);
 
foreach($fields as $key=>$value) { $fields_string .= $key.'='.$value.'&'; }
rtrim($fields_string, '&');
 
curl_setopt($ch,CURLOPT_URL, $sendy_url.'/subscribe');
curl_setopt($ch,CURLOPT_POST, count($fields));
curl_setopt($ch,CURLOPT_POSTFIELDS, $fields_string);
 
if ($line_of_text[0] != ''){
        curl_exec($ch);
        sleep(5);
}
 
echo $line_of_text[1];
echo '<br>';
 
}
 
fclose($file_handle);
curl_close($ch);
//------------------------------------------------------//

?>

You'll need to update your .csv accordingly to add the extra field:

EXCEL_3GmBHzb0aw

It'll import any extra fields you pass it, so for instance your emails can say: "Hi [name] at [business]". Personalization helps quite a bit in terms of response rates.

Anyways, go ahead and upload your .csv to SendyInstallation.com/import/ and then in your browser, open up SendyInstallation.com/import/index.php - that will then, with a 5-second delay, import your list.

The reason for the 5-second delay is so that it doesn't crash Sendy as it's periodically adding these new leads to your autoresponder. Depending on the size of your list, it may take a while before you see anything returned.

When it's completed, you'll see the following:

chrome_YV4rg0RtBu

Now, when we go back to Sendy...

chrome_BV0OpcVEPs

We can see our recently imported prospects:

chrome_bmSAuu6K1w

Notably, imported via API which means they'll automatically be added to our autoresponder:

chrome_KyFxKs7KxY

When it comes time to import your next prospecting list, you'll just need to replace the .CSV, and maybe the list ID.

But before the autoresponder we just set up is ready, we need to set up our autoresponder cron (this is different from the previous one).

Setting up autoresponders on Sendy

When it comes to creating autoresponders in Sendy, we'll need to add another cron:

* * * * * php /home/your_user_here/web/SendyInstallation.com/public_html/sendy/autoresponders.php > /dev/null 2>&1

That'll run the above command every minute to check the MySQL database mentioned earlier if there are any more automated emails to send.

Sendy will not let you proceed with setting up an autoresponder without setting up a cron, because the cron is the mechanism by which anything actually happens.

Once you've got that configured, refresh and Sendy will let you create an autoresponder:

sendy autoresponder

Now we can create a couple of emails to send out to our prospects:

autoresponder

Writing and sending cold emails

People receive tons of emails every day. How are you not only going to stand out, but convince them to give you some of their precious time?

Your cold emails should be written as short as possible while still catching attention. Tell them about their problem and how you can solve it concisely.

Here's an example of the first email in one of my autoresponder sequences:

Hi, is this [Name,fallback=] at [Business,fallback=]?
Do you guys scrape Linkedin profiles? Can you connect me with your CTO? I can help with scraping 1M Linkedin profiles a day.
Let me know!
Steven Goh,
Proxycurl.

You could use a first name, a business name, or both. It's up to you.

I set my first email in my autoresponder to send immediately:

chrome_NVxHhfxc3R

Then, usually, I'll have an email the next day, and 3 days after the first email.

You'll never want just one email. You'll want a couple. Many people don't respond to the first.

Sendy will handle opting out for us, so no worries there.

You can keep them simple with the following sequential emails looking something like this:

  1. Hi [Name,fallback=]! Following up from my last email. Any thoughts about it?

  2. [Name,fallback=], checking in again. Any thoughts about my last email? I think [Business,fallback=] really stands to benefit. No high pressured sales or anything like that.

sendy autoresponder

In my case, I also quoted the content in the original email so it was clear what I was referring to. These aren't responses to the original email, but new emails.

You can change it up a bit and think about what you want to write specifically. I suggest deviating from my cold emails.

If I received a response to my emails, I would answer any questions and move the conversation to get a video call booked on Google Meet through Calendly.

Don't try to sell over email. The point of the cold email is to catch attention, once you've caught attention you should move the conversation towards a call or video call as the sales medium.

Further automation

You could set up automation using Zapier to integrate Calendly and Sendy. Zapier natively integrates with everything.

So instead of manually removing people from your sequence after they book a meeting, Zapier can automatically remove people from your Sendy automation.

Of course, you could also systemize with human resources and outsourcing.

You could train people how to automate sourcing different prospect lists with different ICPs through Proxycurl, how to import that data to Sendy, and then how to move responses received via email from prospects to book a meeting.

That's pretty much all there is to it.

At that point, all you'd have to do is hop on meetings... or you could train someone to do sales for you too!

Enjoy being booked two weeks out

Providing your problem/solution and ICP fit works, enjoy being booked out for two weeks and having zero time.

Cold emailing is very boring and entirely unsexy... but it works. It's not going anywhere, it's 100% worth investing your time and energy into.

If you're looking to obtain high-quality data about people and companies for your startup, consider giving Proxycurl API a try.

You can click here to sign up for free to Proxycurl today.

Thanks for reading.


P.S. If the idea of an API scares you...

As I mentioned earlier, Sapiengraph is powered by the Proxycurl API and requires zero programming knowledge.

You can also give it a try for free here.

on August 25, 2023
  1. 3

    I really liked the article it was well-written :). How did you come up with Proxycurl and how do you come up with potential b2b SaaS ideas?

    1. 1

      Thanks! :) mainly just observing the market for demand. Think about where you're observing different workflow issues and think about what you could do to fix that (while charging for a worthy solution).

      1. 1

        Ok thank you! I have always thought about opening my own Development as a Service "Firm", but always thought that I should try making my own SaaS first but all of the ideas I do have already have multiple big companies doing it. :(

  2. 1

    Hey Steven,

    I just wanted to reach out and say great job on growing your startup to $100k MRR through cold emailing! I've been following your journey on Indie Hackers for awhile now and it's been really inspiring to see your progress.

    Reaching that $100k milestone is a huge achievement, especially as a solo founder. You should be really proud of what you've accomplished.

    Your tips on prospecting, outreach, and sales processes are super helpful for other founders too. Sharing your learnings transparently is so valuable for the community. It's awesome that you're paying it forward to help others succeed as well.

    Keep crushing it man! I have no doubt Proxycurl will continue growing exponentially. Excited to see where things go from $1M ARR to $5M now. You clearly have a winning strategy figured out.

    Keep up the great work!

    Marian

    1. 1

      Hey Marian, I appreciate that very much. Thank you.

  3. 1

    Hey - thanks for the detailed post, I tried to use the person search API but seems it requires 35 credits to run, is there a way to try it out first before purchasing any credit?

    1. 1

      Unfortunately, it does cost us to provide our Search API; so we can't provide it for free.

      $10 will yield you 100 credits, which I believe should be plenty for you to evaluate the service.

      In our early days, we offered free trial credits to everyone who asked. It turned out that almost everyone that we gave additional free "evaluation" credits never followed up with a purchase.

      On the flip side, serious (paying) customers have never hesitated to make small top-ups for evaluation.

      We do not provide trial credits beyond the first 10 credits that are added to your account when you first register an account.

      However, the following API endpoints are entirely free:

      For example, Using our Disposable Email Address Check Endpoint, you could check all of the emails used for your prospecting lists.

      It's as simple as feeding our Disposable Email Check Endpoint your emails you want to check as follows:

      import json, requests
      
      headers = {'Authorization': 'Bearer ' + 'Your_API_Key_Here'}
      api_endpoint = 'https://nubela.co/proxycurl/api/disposable-email'
      params = {
          'email': 'steven@nubela.co',
      }
      response = requests.get(api_endpoint, params=params, headers=headers)
      result = response.json()
      print(json.dumps(result, indent=2))      
      

      And then you'll be returned if the email is a free email (not business) or a disposable email entirely (junk).

  4. 1

    This was an extremely well written and detailed blog. Absolutely love it. Thank you very much for sparing the time to write this in so much detail. Wish more blogs were like this.

  5. 1

    Thank you for sharing. 
    But it seems like part with Sendy is quite complicated and looks unnecessary for those who are just starting. You can easily utilize tools such as Quickmail, Woodpecker and achieve a good result in cold emailing.

    1. 3

      In my opinion, the tech really doesn't matter that much. There are wayyy bigger problems than the tooling needed to send cold emails.

  6. 1

    Congrats and thanks for sharing detailed info. I have couple of questions:

    1. I see that you have no social media presence, i.e I don't see a company LinkedIn page. When cold emailing, do you feel that having no social media presence has an impact on your response rates? How do you build trust with a prospect?

    2. Have you tried cold calling prospects? Or only cold email?

    3. What is the delay between each email step, and how many steps are present in a single email campaign?

    1. 1

      Hey aditodkar,

      1. We do have social media accounts. However, LinkedIn does not like us and banned us from their platform. Good thing we don't need a Proxycurl account to scrape LinkedIn.

      For example: https://twitter.com/proxycurl

      We're not as active as we should be, but that's because we don't use social media as a major growth mechanism.

      1. No cold calling. I only use cold email because I think writing is a much better form of communication.

      We're only really starting to grow our sales team now, prior to to that it was practically only me. There wouldn't have been enough time in the day to go down these lists cold calling people.

      Loading it up in Sendy and focusing solely on getting a call booked as always worked out for me better. Then do the selling on the call.

      1. In the one given above:

      Email 1: instantly
      Email 2: 24 hours later
      Email 3: 48 hours later

      You can add more, but if you go over 7 emails or so and they still haven't responded or booked a call... they probably aren't ever. Make sure you give them at least a day between emails.

      1. 1

        I have observed prospects usually do some research before jumping on demo call. How are you handling this situation? (Currently they cannot find any info about your company and you on LinkedIn)

        Do you feel no social media presence has any impact on reply rates and demo call closing ratio?

        1. 1

          Funny you asked because recently I sent out thousands of emails to headhunt for an account executive to kickstart a sales team. And the the top 2 responses are:

          1. Is this real? You do not even have an email signature.
          2. I can't seem to find you guys on the social media.

          So, maybe it does affect us but I can't measure the improvement until we actually get more professional.

          In terms of growth, we have been tremendously focused on consistently delivering value and making it super easy for users to just get started. I mean, just register and there's an API key for you to try it.

          Why do you need social proof when it just works?

          ---

          That said, I completely accept that we should have some social proof and it's on our marketing roadmap.

    2. 1

      i have the same questions too .and we are also release our product last month,but we are still very cautious about cold email.

      1. 1

        Let's wait for his response here. Otherwise, I will ask him on twitter via DM.

Trending on Indie Hackers
Meme marketing for startups 🔥 User Avatar 11 comments 40 open-source gems to replace your SaaS subscriptions 🔥 🚀 User Avatar 1 comment After 19,314 lines of code, i'm shutting down my project User Avatar 1 comment Need feedback for my product. User Avatar 1 comment We are live on Product Hunt User Avatar 1 comment Don't be a Jerk. Use this Tip Calculator. User Avatar 1 comment