Don’t punish old trials and former customers

A common pattern in SaaS apps is to allow a free trial period of 2 weeks or 1 month, and then to require a credit card to use it any longer.

Either out of curiosity or out of a genuine need for a tool that some SaaS service is offering, I will often sign up for a free trial soon after learning about it in order to check it out. For a variety of reasons by the time the free trial is up, I’m not ready to purchase.

It could be because I was just poking around. But more often it’s because I got too busy. Or my reason for signing up didn’t stay a high enough priority to be ready to purchase and fully implement some solution. Or maybe because the product just wasn’t far enough developed to satisfy what I was looking for.

What I find happening is that 3, 6, 12, or 18 months later I’ll find myself thinking about this tool. Perhaps the problem that led me to originally check out tools of the service has become more pressing than ever before. Or perhaps I’m fed up with another tool I chose, and am searching again for a better option. Or I’m hoping that the product has evolved more. Or whatever.

When logging back into your previously-created account, what you typically see is something like this:

Your free trial expired. Please enter your credit card to continue.

At this point, it’s far too easy to just close the tab. I’ve done it many times, even when I actually was in need (and willing to purchase) a tool in their category.

Savvy users will email the site’s sales or support team and can usually get a trial extended, but this often takes a few hours, which sucks. When a user gives you enough attention to want to check out your product right now, you should always take advantage of that. It’s too easy for that attention to get lost if you make the user wait.

Similarly some users will just use another email address, which is really bad for understanding your marketing funnel and metrics, and is a bad user experience overall. Plus, this may mean losing whatever progress was made on the first trial.

Let’s stop punishing our older trials.

I always thought this was a bad user experience, but I knew we were guilty of doing the same thing at Not anymore. Now if you login to a trial that has been expired for long enough (i.e. you haven’t checked out the product in a long time), we give you a single click to get started again.

Screenshot 2015-08-04 14.50.22

The same applies for former customers. Once you’ve been around a while, it won’t be uncommon for an early adopter to have churned and then want to give you another shot a year later. We should welcome this!

It’s a super easy change to make and within minutes of pushing this change we already saw its effects pushed to our chat.

Screenshot 2015-08-07 16.53.17

Don’t treat old users worse than new trials!

Comments (10)

Why you should Archive your emails when you’re done with them

There are two types of people in this world:

  1. People who archive incoming emails when they are finished with them, and try to achieve “inbox zero”
  2. People who leave all incoming email in their “inbox” forever but use “Mark as Unread” or Star/Flag message to indicate items still requiring action

If you’re a Type #1 person, you can stop reading now.

If are a “never archive anything” type person, I’d like to make a case for why you should become an “inbox zero” type person and archive emails when you’re done with them.

Read the rest of this entry »

Add A Comment

HackToStart Podcast

I got interviewed for my first podcast recently. It’s called HackToStart, and it’s one that I’ve been listening to for a while now, so I was excited to be a guest on the show. Check it out here:

Hack To Start | Phil Freo, Full Stack Developer,

In the show we also discuss one of my latest blog posts: The last 20% before shipping.

Add A Comment

The last 20% before shipping

What makes a new feature or product update “done” versus what makes it “really done”? At we developed our own process to answer this question, based on years of shipping new features for our sales communication platform. Today, we want to share this checklist with you.

As soon as a new feature you’ve built is running and working on your development server, there’s a strong temptation to think it’s “done”. You want to ship it. After all, the code is working, and you know many of your users would benefit immediately from the change.

It’s important to stop and ask yourself: What else should we do other than just making a new feature functional? How can I improve the experience for users or make this feature more accessible and maintainable?

We’ve learned that when you’ve only gotten a feature working, you are at most “80% done” and that the last 20% really makes all the difference. In fact, sometimes the “last 20%” of polishing a feature can take just as long to get right as the “first 80%”, however it also is what separates good from great.

Here’s our internal checklist that we use before launching significant new features or changes. Whether for launching a new reporting feature or migrating our database to a different cluster, we’ve found this list to be really helpful.


  • Is it fast?
  • Are the database queries optimized?
  • Will it scale for a large number of records?

Code quality

  • Is the code cleaned up, organized, and properly abstracted?
  • Is it well commented / documented? Assume someone else will have to maintain it.
  • Are there relevant unit tests?

Edge cases

  • Do you consider and properly handle edge cases and invalid inputs?
  • Did you test the first time experience / no-data-yet case?
  • Is it localized? Consider timezones for anything date specific, and unicode.
  • Did you test in all the supported browsers / platforms?
  • Have you tested for potential security vulnerabilities?


  • Does the UI look polished? Is it consistent or better than the rest of your application?
  • Does the UI react to various edge cases properly?
  • Is any written text as good as it can be? Did you check for typos?


  • Does it need any special deployment process, and is the process well documented? Any data or schema migrations necessary?
  • Is everything backwards compatible? If not, did you communicate the change to users?
  • Should it be deployed/visible to employees only to dogfood/test for a while?


  • Are the relevant API docs complete?
  • Do any FAQ docs need to be updated or written?
  • Did you write a blog post announcement, if appropriate?

There you have it. Run through this list before shipping something new and you’re guaranteed to have a better launch.

Do you have anything to add to the list? Let me know!

Add A Comment

Solve multiple problems at once

Startup engineering teams face many decisions about what to build. At, many areas compete for the focus of our small engineering team. Customers often have one little thing they really need. Our team envisions the next big thing to move the product forward. There are poor UX workflows to optimize. We have an idea on how to grow our customer base faster. And of course there are always bugs to fix. The list is endless!

A small engineering team doesn’t have the time or resources to regularly improve every part of a product. It’s not uncommon for a section of an app, once launched, to remain untouched for a year or longer. We usually work to solve a problem or empower customers in a new way or fix a pain point, and then we move on to something else.

One reason I believe our super small team at has been successful is that we often solve multiple problems at once. When a feature needs to be built, we often expand the scope a bit to include other related problems or features that naturally go together with the first one.

Another way to phrase this idea is: rather than solving a problem, solve an entire class of problems.

While this advice may sound obvious, there’s enormous pressure to finish a project as quickly as possible. There’s always the next important feature, bug fix, or redesign from the roadmap to move on to. Shipping even the smallest version of a feature on time can be difficult enough already, since software schedule estimating is never easy. But there’s great value in not just shipping a feature or fix in the smallest form possible.

Application: Fixing Bugs

Let’s start with a simple real-world application: you notice a bug that needs fixing. After some investigation you figure out what the problem is and how to fix it. You fix it and maybe even add a unit test for this case. Time to move on, right?

NO! If you stop there, you’re making a crucial mistake.

At a minimum, you should try to figure out if the same bug exists anywhere else in the codebase. Often a single ack search is enough to find the same bug in many places. Next, consider if there might be other conceptually similar versions of this bug elsewhere. Ideally you’d also follow The Five Whys and discover how this bug got introduced, how it got past code review and QA, etc.

Again, this advice may seem obvious, but consider someone’s natural instinct when a user complains. These complaints usually come in the form of a vague problem (e.g. “it won’t let me change my email address”). First you figure out what the real bug is (e.g. “The form for changing email addresses doesn’t show a confirmation message”). Bugs usually come in very specific forms like this. It’s not uncommon for a programmer to simply fix the bug and move on. But it’s important to stop and consider if similar bugs may exist elsewhere (e.g. “how form confirmation messages work throughout every part of the app”).

It’s the sign of a mature programmer to ask “why” and consider preventing future bugs of a similar type.

Example: A broken URL on

I recently noticed a problem with a specific URL on our site was not working. I discovered the cause was that two Python view functions in our Flask app shared the same name, which just silently breaks one of them. My first instinct was to rename the broken view with a unique name, and move on.

But I remembered it wasn’t the first time this had happened and I recognized it likely wouldn’t be the last, so I thought about the problem more broadly. I knew a syntax issue like this should be detectable, so I spent some time setting up pylint and reviewing its results. Pylint uncovered another case of the same error, as well as other types of logical errors elsewhere, which I fixed. Finally, I added pylint to our continuous integration system to automatically detect any Python syntax issues in the future.

So rather than fixing the broken URL, I fixed all cases where URLs were broken for the same reason. I also found and fixed other unrelated instances of “detectable” syntax issues. And I also automated this process so that this entire class of issues can never happen again. Do you see how much more powerful this type of fixing can be?

Once you’ve discovered the specific causes of a bug, there’s no better time to find and fix other similar bugs. Even when the roadmap begs you to move on, the benefits of squashing related problems are even stronger:

  1. It’s good practice to fix bugs before writing other code (#5 in The Joel Test)
  2. If you can discover and fix bugs before more users experience and report them, you’re preventing user pain.
  3. You’ve already done the hard part of figuring out the specifics of the problem. If you don’t completely resolve it, you’re forcing a teammate or your future self to have to waste time relearning the same thing!

Don’t just fix bugs. Fix an entire class of bugs.

Application: Designing Features

The temptation to solve a single problem at once is even larger when it comes to features. Features are often a response for solving a user’s pain point, or an idea designed to empower your users in a new way. Naturally, the team is excited to ship as soon as possible.

Furthermore, a good product designer will optimize a feature to be as simple as possible for the specific workflow it’s designed for.

The problem is that over time, rather than designing one cohesive experience, you’ve glued a bunch of individual features together. If you’re only thinking about solving one specific problem at a time, you’re missing the bigger picture of how everything will fit together.

Software written in this way turns out to be super complex because hundreds of small problems were solved separately rather than a few big problems being solved elegantly.

Don’t design a single feature; always be designing for the bigger picture.

Example 1: Search & Filtering

An example where I think our team nailed this early was with search and filtering. From ElasticSales we knew that salespeople would want to slice and dice their leads in a million ways.

When starting it would have been understandable if we solved this initially by just slapping a couple of the most commonly requested filter options, like “Lead Status”.

However we knew that this was a narrow and short-term solution. It wouldn’t be enough to last and wouldn’t be enough to “wow” people. Quickly, power users would outgrow our simple filters and we would be forced to keep adding additional one-off filters and complexity. We’d have to keep redesigning as the number of filters grew and redesigning again for each new idea like exclusion filters or nested “OR” conditions. We would have started fast but slowed very quickly.

Instead, we designed a framework to solve the larger problem. We invented a search language and then UI to allow filtering by a very large number of useful sales attributes and combine them together with boolean and/or/not keywords. It took longer to do it this way than just adding a couple basic filters. But we established a paradigm of how searching and filtering worked in that has powered innumerable use cases our customers needed and has lasted 2+ years. Our customers rave about its power, and PandoDaily wrote about it.

I’m definitely not saying we had to build this feature to 100% completion from day 1 (and we didn’t – we still iterate on it today – and in many ways it’s very far from complete). But thinking through a scalable solution for this problem rather than slapping on a few quick filters has given us a big advantage. Having an end goal in mind allowed us build a version 1 that didn’t have to be thrown away when we built v2 and v3. We have ideas for what an amazing version 5 and 10 may look like, and we won’t have to start over – all because we planned ahead to solve search & filtering more broadly.

Example 2: Reporting

Some of our competitors have dozens of individual “reports”. They tack on a new report every few weeks because users always want more reporting. was really far behind in reporting but the thought of adding dozens of reports made us want to cry. So instead we built one super powerful charting tool (Explorer) that, in one fell swoop, allows you to visualize almost any attribute of your teams’s sales activity.

Example 3: Bulk Actions

We needed to build a way for users to “bulk delete” all their leads. Rather than building this alone, we designed a system that would work for not only Bulk Delete but also Bulk Edit and Bulk Email (two other features we knew we wanted to build). Because of designing for this, we were able to later launch the additional two features within a very short period of time. Coding the two additional features became much simpler and the UX for all bulk actions was considered together rather than tacked on without cohesion.

Architect your product to solve an entire class of problems at once.

If you don’t, you’ll end up with software that’s missing important features and users will quickly outgrow the one thing you helped them with. Or you’ll keep tacking on additions in a non-cohesive way which makes a complex product over time.

Said another way: it’s easier to end up with both successful users and a cohesive UI & UX if you solve and design for a few big problems rather than a bunch of individual little ones.

Application: Refactors

Technical debt can clearly become a big problem and slow development. But it almost never feels worth rewriting something just for the sake of code quality. The benefit of doing projects solely to “pay back” technical debt is hard to justify.

The best time to solve technical debt, refactor code, etc. is in the midst of making other changes to that part of the system. When you’re working on an improvement involving a problematic part of the codebase and you’re considering making bad code even worse… go ahead and take the extra time to refactor and improve it. There’s no better time to do so, since you’re already having to grok how it works and carefully test those parts related to your improvement.

Application: Redesigns

When redesigning how one part of your product works, consider how the rest of your product works. It may be easier to solve multiple problems that relate to each other all at once.

Example: Onboarding Process & Email Setup

We wanted to introduce a set of onboarding steps for new users. One step would be an easier way to connect your email account (for our 2-way email syncing to work) rather than having users do so later in Settings. What we did is build and launch a few features all at once:

  • Onboarding steps for new users
  • Simplify getting email account credentials by:
    • Auto-detecting your email service, IMAP/SMTP hostname, port, etc. when possible
    • Consolidating setup of incoming & outgoing email settings into one step
    • Use OAuth instead of passwords when a Gmail / Google Apps account is detected
  • Support for multiple email accounts & identities per user

Not all of these features were crucial for the main priority at the time, which was to improve onboarding and make it easier to setup email. But they made a lot of sense to build together, since they were interrelated. We would have had to redesign, recode, and retest the Email Settings page regardless so it was the perfect time to design it to support setting up multiple accounts.

Supporting multiple accounts is a valuable feature that we always planned on building. But if we hadn’t built it alongside these other features, it likely wouldn’t have become a big enough priority to get built on its own for quite some time. By building to solve multiple problems at once, we were able to do more, faster, than had we been trying to solve independent problems in serial.

Risks & Rewards

You may now be thinking, “Isn’t this scope creep, and isn’t scope creep a bad thing?”

Indeed, if you keep expanding the scope of your projects to solve more and more problems you will never ship or meet deadlines.

But I’m actually advocating for more planning. More deliberateness in your design decisions and planning. More hesitation before starting projects that only solve only one problem. Design your product with end goals in mind. Design code and processes with your future team in mind.

Expand a project scope opportunistically where it makes sense. Reschedule items onto the roadmap sooner if they are easier to build alongside whatever your current priority is. Often you won’t return to a problem for many months or even years. So if you can put an entire set of problems to rest all at once, do it even if it takes a bit longer.

The principles I’ve been talking about should help you make a much better product over time. When you solve one problem, it’s not that much harder to solve a bigger class of the problem.

The way to keep from turning this advice into scope creep is to slow down. Not slow down in the sense that your team & product shouldn’t be moving quickly. But slow down in the sense that you should do less, but better. Do fewer things, but more that have longterm impact. You can’t do this for everything, but try to do it for the important parts.

So the next time you design a feature, fix a bug, or otherwise try to improve your product, ask yourself, “Can I solve multiple problems at once?”

Comments (1)

My mobile workstation setup

Since my wife got a nursing job in Stockton, I’ve drastically increased the time I spend working while traveling, in coffee shops or hotels where I don’t have my typical desk and monitor setup. Since I get a ton of compliments and questions about it when I’m working from Starbucks all day, I thought I’d share my ultimate mobile workstation guide.

Read the rest of this entry »

Add A Comment

How one of my tweets landed a $585/month customer

One of my tweets is featured in an article on

How Closed $585 in Monthly Revenue from 1 Tweet.

Check it out!

Add A Comment

Launched: – integration between Pocket & Umano to hear your saved articles read aloud

I built a quick mashup/integration between two services that I love using, that I thought would be “better together”. It’s live at

I use Pocket to save a queue of any article (blog post, news story, etc.) that I see on Hacker News, Twitter, Facebook, etc. There’s a web & mobile browser extensions for saving articles you see, and Mac & iOS apps for reading these articles later all in one place, even offline.

Using Pocket can be good for productivity because you may see a headline that interests you, but you really shouldn’t be reading it now. By saving it to Pocket you know you can easily find and read it later. I’ve got a few hundred articles saved from over the past couple years. I often read a few articles at a time, but they still build up.

I also use Umano, which is a service that has professional voice actors record narrated articles from across the web. It’s perfect for commuting. Many of the articles are only a few minutes long, so even a quick trip to the store or walking to the train can be enough to hear an article or two about something that interests you. Tech, current news, etc.

Umano has some article discovery built in (a “popular” page and a way to see which articles your Facebook friends on Umano liked), however they have thousands of articles already recorded and so finding what you really want to listen to is still difficult.

Then I realized that all the articles I wanted to read or listen to were already saved in my Pocket queue, so during part of a couple weekends I put together this site to do a few things:

  • Look through my Pocket queue and identify which articles were already on Unman
  • Allow me to very easily add matching articles to my “playlist” in Umano
  • Also allow me to “Vote” in Umano for the articles that are already in my queue
  • Add “tags” into Pocket for articles that were added to my Umano playlist, so I can easily archive those in Pocket

Umano does have a Chrome extension (and generic bookmarklet) for “voting” for articles, but I wanted my primary queue to be something like Pocket, which is better built for general purpose article saving, I didn’t want to have to save every article to two places, and I mostly wanted to listen to the articles that were already in my queue.

Check it out:

Feedback is welcome.

Built using Python/Flask and Bootstrap.

Future improvements I’d like to make: It should continually monitor a Pocket queue for new articles ongoing – looking for matches and adding them to Umano without any user interaction. At the moment you just have to login to the site occasionally.

Comments (2)

The Elements of User Onboarding

I just finished reading “The Elements of User Onboarding” by Samuel Hulick. I discovered the book through the excellent site which has chronicled every screen in the onboarding process of several web and mobile apps and added great commentary (positive & negative) on each screen.

If you help make a web/desktop/mobile app, I highly recommend going through a few of these teardowns, as they alone will make you re-think some parts of your onboarding process. These teardowns together with the book have given me lots of great ideas for drastically improving the liklihood that a new user of will become successful.

For each chapter, I wrote down a brief summary or simply something that stood out to me. By all means, this isn’t a replacement for getting the book – but a teaser and reminder to myself what I read!

Read the rest of this entry »

Add A Comment

My interview on Sales4Startups about

Sales 4 Startups published an interview with me about

Interview: Phil Freo, Engineering Lead

Sales4StartUpsTell us about the story. How was it started? What problem were you trying to solve?

Phil: was developed as an internal product to make our own salespeople at ElasticSales more efficient. Our company was doing sales for a bunch of companies (with different types of sales processes and needs) and through all these difference sales campaigns we recognized a lack of good software geared at the day-to-day tasks a salesperson faces. Our team needed to be able to make many phone calls quickly, send more emails, and see a history of sales activity for any given lead without having to do a bunch of manual data entry, and surprisingly none of the solutions we tried seem to actually be designed to make salespeople’s lives better in these ways.

After several of our customers asked if their salespeople could use our software (since they saw our productivity improvements from it), we decided to focus on productizing it, and was born.

Read the entire post.

Add A Comment

« Previous entries Next Page » Next Page »