hrpartner

SaaS Startup Founders: Are you talking to the right audience?

TOTALLY+MISSED.jpg

I have a confession to make. I am a developer, not a marketer, and in the nearly 4 years that I have been running my startup HR Partner, I have made a ton of mistakes in my ‘go to market’ strategy, and I hope to share a couple of them here with you.

I always naively thought that the coding of my SaaS product would be the hard part, and that the selling part would happen naturally and effortlessly. How wrong I was. In today’s noisy world, with a ton of competitive offerings, getting heard is nearly impossible, and finding people who will like, and more importantly, pay for your offering is painfully difficult.

Probably the biggest mistake we’ve made with our marketing was simply talking and selling to the wrong people. We never really stopped to look at who would be using our product but instead went for the scattergun approach to throw everything at the wall and see what would stick. Let me give you a brief history of what we did.

When I first built HR Partner back around 2016, I decided to release our Beta version to the world via a fanfare splash on the very popular ProductHunt website. It seemed to work, and we actually got hundreds of sign ups out of this one source. “Great!”, I thought - success and endless bags of cash shall now rain down on me.

Wrong. Pretty much 0% of those early signups stuck around. You see, ProductHunt is comprised mainly of programmers, designers and other small startup founders. They are very interested in tech, but have little or no interest in setting up HR policies and procedures, or managing a large team. They signed up purely out of interest sake, but had no reason to actually implement our system at their workplace.

Nevertheless, we doubled down on our failure to learn, and I embarked on a campaign of listing my HR system on various Beta announcement sites such as BetaList. Same results. A flurry of sign ups by curious people, but very little stickiness.

Of course, this spike in signups both times was great for my ego, but I couldn’t see that this was just a vanity metric that did nothing to help us get any real traction.

Next, we went completely broad based, by spending a ton of money on Google Ads. We even worked with a Google consultant to get our keywords and campaign ‘just so’. But while we saw a massive increase in traffic to our website, it didn’t result in many trial signups, and in fact, we got a TON of calls and emails from various employees asking us HR policy and payroll legislation questions! We quickly pulled the plug on this avenue.

At this point, and for the first time in over 6 months of trying, I actually sat down to think about where I was going wrong. It was pretty obvious actually. ProductHunt and BetaList are great sites, but really, they are ideally suited if you have early stage products that are geared to the programmers or designers of this world. Business owners are not renown for adopting concept stage or beta stage software - they want something proven and reliable. Coders and creative people however, are different and can’t wait to try the next shiny thing! We were talking to totally the wrong people.

So I began to think. Who would need HR systems? Well, the obvious answer is “HR Managers”, duh!

Thus began our next marketing push - cold outreach to anyone with the title “HR Manager” on LinkedIn. Initial observations were a mixed bag. We were having some great conversations with a lot of HR Managers on that platform, but very few would actually take the next step and sign up for a trial of HR Partner. It turns out that while these were the right people to talk to, they already had established systems they were happy with, and were not looking to buy.

We were getting closer - the right people, just in the wrong place & time. So how do we get them at the right time? Well, we’ve recently put some marketing effort on business software directories, such as Capterra or G2 Crowd. These are vast directories of SaaS offering that people can go to when, you guessed it, they are evaluating business software that they are thinking of buying.

Now we were getting somewhere. By promoting our offering on these platforms, we started to see a steady uptick of trial sign ups, and more importantly, paying customers.

This is all good news, but there is still so much more learning to be done here. For instance, we are finding that while it is the HR or Operations Managers we are mainly talking to, the actual buying decision is usually made by a different person in the chain.

HR Managers are coming to us with a specific set of problems - for example they may be drowning in paperwork or having trouble keeping employee qualifications and training up to date. Whereas the business owner may have a different set of issues they want solved, such as high turnover, or the high cost of recruiting new employees.

This means that we needed to address both areas. When talking to the HR Manager, we would focus on the problems they were experiencing, but when the decision went back up the line to the person who would sign off on the new software, we had to start from scratch and provide solutions for a whole different set of problems. We essentially had to sell our system twice, to practically two different audiences.

Did I say two? We actually discovered that we had a third audience that we had to sell to. These were the actual employees themselves within the organisations who bought HR Partner. Any great HR software is just going to languish if the employees don’t feel comfortable using it. All that the employees wanted to know was - how do I find out how many days leave I have available? How can I request some time off expediently? How can I find the contact email of another employee in a remote office? etc. A totally different set of problems and expectations than the other two audiences we had been dealing with!

Thus we refined our sales and marketing processes to deal with these three distinct audiences that our product had. Sure it is a lot harder to do, and is time consuming, but it has resulted in a far more effective and predictable process now - just by understanding who our audience was, and in our case, who our multiple audiences were that we had to talk to, understand, and solve problems for.

We are still learning and improving, and I am interested in hearing more from other startup founders and business owners out there. How did you find your real audience?

This article was originally written for the Catalysr Blog. I was a member of the Catalysr C18 cohort for migrapreneurs, an experience which was awesome and extremely beneficial to me and my startup. Find out more about them at catalysr.com.au.

Building a Status page for $5 per month

When we first built HR Partner, I wanted to have some sort of status page like most web apps do, to let our customers know about uptime availability and any scheduled maintenance that we had planned.

Our HR Partner status page at: status.hrpartner.io

Our HR Partner status page at: status.hrpartner.io

Looking at most of the commercially available offerings, I found that while excellent, they were quite expensive, when compared to the project management, accounting and bug tracking tools that we already subscribed to.  Being a relatively small, boot strapped startup, I didn't want to add to our already high monthly subscription burden too much at this stage.

Eventually, my search led me to Cachet, which is an open sourced version of a status page app, that seemed to have most of the features that the 'big boys' did.  End of the day, we managed to host Cachet on a virtual server for around $5 a month, and given that the cheapest commercial variant we found was $29 per month, I am happy that we got something working for a budget price that is hard to beat.

Given the buyout of one of the main commercial vendors StatusPage.io by Atlassian today, a lot of people have seen me post about my efforts and have emailed or PMd me to ask how we went about this, so this post will hopefully let you know the steps we took.

Hosting

Our main HR Partner web app is hosted by Amazon AWS, in their us-east-1 region.  Because we wanted some sort of redundancy in case of a major Amazon outage or regional catastrophe, we decided to host our status page on a Digital Ocean Droplet over on the West coast.  Different providers, different infrastructure, different areas.

So the first thing we did was to set up a VPS in Digital Ocean.  I picked the cheapest droplet they had, which was a $5 per month server running Ubuntu 14.04 (64 bit) with 512MB of RAM and 20GB of storage.  Cachet doesn't take much in the way of resources at all, so this was plenty for us.

The Stack

Once the Droplet was up and running, we just opened up a console to the server from within our DO control panel, and installed MySQL on it.  Digital Ocean have a great article on how to do this right here.  We simply followed the instructions step by step.

Next step was to follow the equally great instructions from the Cachet documentation right here to install Cachet on that VPS.

I believe the only tricky thing that we had to do was tweak the permissions within the Cachet folder.  I believe we had to chown the folder and all subfolders to the www-data user and group.

Configuring Cachet

Once we had Cachet installed as per above, we adjusted the .env file to use our preinstalled MySQL instance for the database, and also to use our normal Amazon SES service for the sending of emails.  I believe we had to also change the default queue driver for sending emails.  Here is what our config file looked like:

APP_ENV=production
APP_DEBUG=false
APP_URL=http://status.hrpartner.io
APP_KEY=***secret key here***

DB_DRIVER=mysql
DB_HOST=localhost
DB_DATABASE=cachet
DB_USERNAME=***yourdbusername***
DB_PASSWORD=***yourdbpassword***
DB_PORT=null

CACHE_DRIVER=apc
SESSION_DRIVER=APC
QUEUE_DRIVER=sync
CACHET_EMOJI=false

MAIL_DRIVER=smtp
MAIL_HOST=email-smtp.us-east-1.amazonaws.com
MAIL_PORT=25
MAIL_USERNAME=***yourSESuserIAM***
MAIL_PASSWORD=***yourSESkey***
MAIL_ADDRESS=status@hrpartner.io
MAIL_NAME="HR Partner Status"
MAIL_ENCRYPTION=tls

That was really about it!  (Oh, don't forget to let Amazon SES know about the email address that Cachet will be using to send emails as - in our case status@hrpartner.io.  Otherwise it won't pass the SES spam filtering).

Last thing was to tweak our Amazon Route 53 service to point status.hrpartner.io to our Digital Ocean VPS IP address.  Done!

Now it was all a matter of setting up Cachet with our components and needed to be reported on, and we were away.  All in all, I think the install and configuration took less than an hour to do.

BONUS: Auto update

Because HR Partner is a fairly complex app, with multiple sub apps for the API, reporting engine etc., deployment can take a while to do, and can result in slow performance for up to 15 minutes at a time while the virtual instances are updated and synchronised.

We use Amazon's Elastic Beanstalk command line tools to deploy changes, and at first our procedures meant that before we ran a deployment, we manually logged into our Cachet server to flag the services that would be down, then deployed, waited, and went back to Cachet to flag them 'green' again.

This was quite tedious, and I wondered if there was an automated way.  It turns out there is.  Cachet has a great JSON API, so what we did in our projects was to create a couple of files under the .ebextensions folder in our project folder.  These files contain the scripts that we wanted Elastic Beanstalk to run before and after deployment.  First, we created a file called 01_file.yml for the before script:

files:
"/opt/elasticbeanstalk/hooks/appdeploy/pre/02_cachetupdatestart.sh":
mode: "000755"
owner: root
group: root
content: |
#!/usr/bin/env bash
curl -H "Content-Type: application/json;" -H "X-Cachet-Token: [secret token]" -X PUT -d '{"status":2}' http://status.hrpartner.io/api/v1/components/2
curl -H "Content-Type: application/json;" -H "X-Cachet-Token: [secret token]" -X PUT -d '{"status":2}' http://status.hrpartner.io/api/v1/components/4
curl -H "Content-Type: application/json;" -H "X-Cachet-Token: [secret token]" -X PUT -d '{"status":2}' http://status.hrpartner.io/api/v1/components/5
curl -H "Content-Type: application/json;" -H "X-Cachet-Token: [secret token]" -X PUT -d '{"status":2}' http://status.hrpartner.io/api/v1/components/6
curl -H "Content-Type: application/json;" -H "X-Cachet-Token: [secret token]" -X PUT -d '{"status":2}' http://status.hrpartner.io/api/v1/components/8

Then we created a 02_file.yml for the after script:

files:
"/opt/elasticbeanstalk/hooks/appdeploy/post/02_cachetupdatefinish.sh":
mode: "000755"
owner: root
group: root
content: |
#!/usr/bin/env bash
curl -H "Content-Type: application/json;" -H "X-Cachet-Token: [secret token]" -X PUT -d '{"status":1}' http://status.hrpartner.io/api/v1/components/2
curl -H "Content-Type: application/json;" -H "X-Cachet-Token: [secret token]" -X PUT -d '{"status":1}' http://status.hrpartner.io/api/v1/components/4
curl -H "Content-Type: application/json;" -H "X-Cachet-Token: [secret token]" -X PUT -d '{"status":1}' http://status.hrpartner.io/api/v1/components/5
curl -H "Content-Type: application/json;" -H "X-Cachet-Token: [secret token]" -X PUT -d '{"status":1}' http://status.hrpartner.io/api/v1/components/6
curl -H "Content-Type: application/json;" -H "X-Cachet-Token: [secret token]" -X PUT -d '{"status":1}' http://status.hrpartner.io/api/v1/components/8
curl -H "Content-Type: application/json;" -H "X-Cachet-Token: [secret token]" -X POST -d '{"value":1}' http://status.hrpartner.io/api/v1/metrics/1/points

(Replace the [secret token] above with your unique Cachet API token.)

Now whenever we do an eb deploy command, the relevant status page components are marked 'yellow' for the duration of the deployment, then brought back up to 'green' again when completed.

Cheap As Chips

The only running cost for our status page is the $5 per month for the Digital Ocean hosting.  That is all.  We've been running this configuration for some months now with good results.  When revenue and usage gets to the point where we need to update this, then we may look at some of the commercial offerings, but for now, this setup works well for us.

I hope we have managed to inspire others to try the same.  As always, if you have feedback or suggestion on how we can do this better, I would love to hear from you.