Playing on Easy Mode

Playing on Easy Mode

Whenever I give advice to first-time software entrepreneurs, I tell them to play on easy mode:

  1. B2B not B2C
  2. Recurring revenue
  3. SaaS not self-hosted
  4. Established tech stack
  5. Make your version of an existing product

Number 5 is often overlooked because people love to invent new things. Resist the urge to make something completely new. David Cancel calls this Innovation, Not Invention.

Innovating on an existing idea is one of the best ways to increase your likelihood of making something people want.

Build yet another bug tracker. Build forum software. Build a help desk tool. Find a space where the existing products are ordinary and make something remarkable.

There are existing patterns for this. Here are a few:

  • The Lightweight Product. Fewer features, but much better UX (Drip, Buffer)
  • The Delightful Product. Give your product a personality and focus on the little details that make people smile (Freckle, Slack)
  • The Single-Purpose Product. Do one thing exceptionally well with zero distractions (Pinboard, TinyLetter)
  • The Opinionated Product. Take a strong stance on how a problem should be solved (e.g., YNAB forces you to manually enter expenses so you’re conscious of your spending)

Very few software markets are winner-take-all. Find your niche and take your share.

You can build a formidable business off of a small twist on an existing paradigm with built-in assurance that that you’re solving a real problem.

The only variable on easy mode is your execution.

Munchkin Report: September 2015

It’s been a while since I posted a status update for Munchkin Report, but we’ve probably made more progress in the past 2 months than ever before. Here’s where we stand.

Munchkin Stickers!

Recently Finished


  • Wrote a functional spec and made screen mockups for our iOS app
  • Finished coding and documenting our logging API, which was a necessity for the iOS app
  • Interviewed a bunch of iOS developers and finally found one that fit

Sales & Marketing

  • Created a 12-slide pitch deck that we can use for live and web demos with schools
  • Wrote a script for a quick start tutorial video that people will see when they start their trial
  • Ordered stickers to give away in our intro kit for schools (part of our offline marketing efforts)
  • Prioritized our launch list based on size (i.e., franchises, small schools, parents) and activity
  • Drafted our behavioral emails for trial onboarding, activation, trial expiration, cancellation, etc.
  • Planned out a partnership with a foundation that helps underprivileged children in developing counties, which is a central part of our company’s mission

Quotes for the iOS app ranged from $7,000 to $40,000. It was ALL over the place. I swear some of the devs I talked to had no idea what they were talking about. I didn’t tell them I was an engineer, and the bastards tried to fleece me. It must be scary for non-technical founders trying to navigate this process.

I did a short chat with the people over at Their process is very streamlined. I sent them my spec and a few minutes later I was chatting with someone. The chat went like this:

Gigster: I looked at your spec and your app will cost $30,000 and take 6 weeks.

Me: You sure? It’s just CRUD. All the API work is done.

Gigster: OK, $15,000.

Me: That still seems high. The app is literally 8 screens.

Gigster: Yes, but you have email and that’s complicated.

Me: The email is handled server-side. It’s just another API endpoint you have to hit when the user taps a button.

Gigster: OK, $10,000.

This didn’t sit well. You also can’t talk to, select, or vet the developer they give you. It’s really intended to be a hands-off, premium offering. For me, that just didn’t work. Not a great option for bootstrappers, IMO. We had the best luck with indie developers. I’m not giving away the one I found (yet) because he’s awesome. :)

Up Next

  • Plan and write our email launch sequence
  • Formalize our partnership with a foundation that we plan to donate a portion of our profits to
  • Work with our iOS developer to build and test the app (starting Oct 19!)
  • Record quick start tutorial video
  • Start compiling marketing ideas aimed at school/daycare directors
  • Make a checklist of all channels/tactics, etc. we want to use for launch day
  • Add attendance tracking to the product

Tracking Form Submission Events the Right Way

The best place to track form submission events is on your “thank you” page.

Why? Because if someone has landed on your thank you page, it means they’ve successfully completed the form. They got past any client- or server-side validation. No oddball errors occurred. The event really happened.

However, if you want to include all that rich form field data in the event you’re sending to tools like KISSmetrics, Mixpanel, etc., event tracking from the thank you page probably won’t work.

Let me explain.

Landing page tools

If you use HubSpot or Unbounce or MailChimp or ANY third-party tool for your forms, your form submission flow looks something like this:

HubSpot Form Flow

The problem is that the custom redirect URL that these apps let you enter doesn’t receive any of the original form submission data. They could let you pass it in the URL’s query string args, but they don’t (and probably for good reason).

So what are your options?

Option #1 is to track the event on your thank you page anyway, and just leave out the form properties. This is fine if you only care about what happened and you’re not concerned with who did it.

analytics.track('Downloaded a resource', {
  resourceName: 'Daily Activity Sheet'

Of course you’ll have the who did it information in HubSpot or whatever application processed the form, but if you want to distribute that information to other tools, you’re kinda screwed.

What I really want is:

analytics.track('Downloaded a resource', {
  resourceName: 'Daily Activity Sheet',
  firstName: 'Nymeria',
  lastName: 'Sand',
  email: '',
  company: 'Martell',
  location: 'Dorne'

Option #2 is to track the event on the form page at the time of submission. This is the option I use.

It’s trickier than it sounds, though. Think about it. You’re filling out a form and you click Submit, what happens? The page changes.

So, your event tracking has to happen in the milliseconds after the button was clicked and before the page transitions.

To account for this, many analytics vendors (Segment, KISSmetrics, Mixpanel) have written JavaScript helpers that are designed to intercept form submission events, pause to do tracking stuff, and then and only then let the form submit proceed.

Awesome, right?

Eh, not so fast.


Helping the helpers

What I’ve found is that most of these JavaScript helper functions assume that if the button was clicked, the form will definitely be submitted. This isn’t true!

HubSpot landing pages, for example, use client-side form validation by default. If you forget to fill out a required field and you click the submit button, HubSpot will prevent the submission and display an error message, but the analytics code will kick in anyway.

If the user bails out and never completes the form, your analytics will still show 1 form event instead of 0. If the user tries again and completes the form, your analytics will show 2 form events instead of 1.

This can be a very bad thing. Trust me. I over-reported trial signups for MONTHS before realizing this.

As of today, here’s the behavior of the 3 tools I mentioned above when an invalid form is submitted:

  • Segment’s trackForm helper will track the event as if it happened and submit the incomplete form.
  • KISSmetrics’ trackSubmit helper will track the event but not submit the form.
  • Mixpanel’s track_forms helper will track the event but not submit the form.

Note: I filed an issue on Github about Segment’s helper because submitting a prevented form could be much more problematic than over-reporting events.

Ugh, now what?

All is not lost, people!

jQuery provides a neat function, event.isDefaultPrevented(), that tells you whether a form submission has been prevented by someone else. All we have to do is check that value before firing the analytics events.

So we can do something like this:

// Grab a reference to our form
var form = $('.hs-form');

// Setup a handler to run when the form is submitted
form.on('submit', function(e) {

  // If some client-side validation kicked in and wants to prevent
  // the form from submitting, bail out now without calling track or identify
  if ( e.isDefaultPrevented() ) {

  // If we got here, it's okay to fire our events and submit the form      

  // Stop the form from submitting...for now

  // Identify this visitor using their email address as a distinct ID
  // and as a new property
  var email = form.find('[name=email]').val();
  if (email) {
    analytics.identify(email, {
      email: email

  // Track the event and include values from the form to our event props
  analytics.track(eventName, formValuesToProps(form));

  // Submit the form now that all our analytics stuff is done

The one BIG caveat is that your handler (i.e., line 5) has to be attached higher in the DOM than the page’s form validation handler because if your code runs before the form validation does, it’ll always run. The trick is to get your code to run last.

Hopefully this helps people avoid the same issues I was having and, despite not being a perfect solution, perhaps some of the default helpers will try to incorporate event.isDefaultPrevented() to mitigate against false reporting. The tough thing is that there are a million ways to implement form validation, so it’s a cat-and-mouse game for the devs at KISS and Segment.

A note on HubSpot landing pages

For HubSpot landing pages, the isDefaultPrevented solution worked well…for a time. Then the forms team at HubSpot decided to call preventDefault always, even if the form was completely valid, presumably because they’re submitting the form via AJAX.

Thankfully when I reached out to the HubSpot forms team they had a good solution for me. They fire a custom event called hsvalidatedsubmit that I can listen for instead of listening to the default form submit event:

// Grab a reference to our form
var form = $('.hs-form');

// Setup a handler to run when the form passes validation
form.on('hsvalidatedsubmit', function(e) {

  // Identify this visitor using their email address as a distinct ID
  // and as a new property
  var email = form.find('[name=email]').val();
  if (email) {
    analytics.identify(email, {
      email: email

  // Track the event and include values from the form to our event props
  analytics.track(eventName, formValuesToProps(form));   

$9 Marketing Stack: A Step-by-Step Guide

“Just tell me what to do so I can stop worrying about tools and start making money.”

When it comes to setting up a marketing stack (analytics, email, automation, etc.), you can quickly become paralyzed by choice, especially if it’s your first time.

I’ve written about our industry’s need for default marketing stacks that prescribe which components to use and how best to use them, so you can get up and running quickly, avoid common mistakes, and focus on your business.

Below is a step-by-step guide to setting up what I call the Boostrapper’s Stack. I’m going to walk you through the exact steps I used to configure this stack for my SaaS app Munchkin Report.

What’s in the stack?


A/B Testing

Marketing Automation (opt-in forms, email marketing, automation, and CRM)

With this stack, I can:

  • Track visitors and events
  • Analyze my funnel (AARRR)
  • Capture leads
  • Send one-off email campaigns
  • Send drip campaigns and behaviorial emails
  • A/B test my site AND my emails
  • Do marketing automation (workflows, tags, etc.)


What’s missing?

Not much, to be honest! The goal is to keep the stack pretty lean. If you’re starting off with more than this, you’re probably overdoing it.

If money were no object, I’d swap ActiveCampaign out for HubSpot in a heartbeat. Then I could drop Optimizely. Alas, AC is $9/mo for what I need and HubSpot is definitely NOT $9/mo.

This particular stack doesn’t include a nice landing page creation tool like you’ll find in HubSpot, so I simply create landing pages like I would any other page on my sales site and embed an ActiveCampaign form. Pretty easy. The cost/overhead of adding a tool like Unbounce or LeadPages to the mix outweighs the benefit, IMO.


Other super-cheap or free marketing tools you’ll catch me using for Munchkin Report, but I consider outside the scope of my core marketing stack include:

Now that I’ve described what is in the Bootstrapper’s Stack, feel free to wander off and experiment on your own. However, if you also want to know exactly how I use the stack, stick around.

Some context

Before I dive into the detailed setup steps, I think it’s important understand Munchkin Report as a business. Munchkin Report is web-based SaaS with monthly and yearly subscription revenue.

Munchkin Report

It is used by parents who want to track their child’s activities at home (perhaps with a nanny) and daycare centers / preschools that want to ditch paper tracking sheets, improve communication with families, and differentiate themselves.

Users track naps, food, diaper changes, moods, photos, etc. The information helps parents make better decisions day-to-day, spot trends in their child’s behaviors and habits, and stay in-sync with caregivers during the day.

The north star metric for Munchkin Report is the number of parents who receive an activity report per day.

The app also serves as a memory book with pictures and a milestone timeline, but that’s a secondary benefit for most people.

Now that you know the business, let’s take a look at the marketing machinery behind it.

Step 1: Create a tracking plan

The first part of the stack to setup is analytics, which is a foundational element. But before you install analytics, it’s crucial to think through what you REALLY need to track. I highly recommend that you go through this exercise.

Here’s the outline for Munchkin Report’s tracking plan.

Our core lifecycle events are:

  • Signed Up (Acquisition)
  • Logged Activity (Activation)
  • Started Subscription (Revenue)

Our second-tier lifecycle events are:

  • Downloaded Resource (Acquisition)
  • Invited User (Referral)
  • Added Munchkin (Activation)
  • Sent Daily Report (Activation)

We want to track the following key pages:

  • Blog (Home)
  • Blog (Post)
  • Tour
  • Pricing
  • Signup

We will identify users on:

  • All logged-in application pages
  • List opt-in (e.g., resource download) on the sales site

Step 2: Setup Segment

Segment is only the best invention EVER.

Install Segment and it becomes the One True Interface to all your third-party apps. You send data to Segment and it takes care of mapping and routing that data to the apps you enable.

It simplifies your setup, makes it trivial to enable new apps, and it’s more efficient. It also a cool replay feature (business plan only) which lets you send HISTORICAL data to a newly-enabled tools.

Virtually all of our setup tasks for analytics and tracking will be done via Segment.

To start, create a free account and start a new project for your app.

2.1 Install the JavaScript Library

On the Setup Project page, you’ll find both your API Write Key and the analytics.js code snippet to include on your sales site.

Segment - Project Settings

Make sure you add your API Write Key to the default code snippet.

Segment - analytics.js

Add the code to your website’s header template so that it loads on every page. You should start seeing pageview events in your live debugger now.

Add it to your web app, too!

If you also want to make client-side tracking calls from your web app (and you should), you’ll need to install the analytics.js library in your application source code as well.

For Munchkin Report, which is is a Rails app, I created a file called /app/vendor/assets/javascripts/analytics.js that contains the same snippet of code I used on my sales site.

Tip: to ensure that this library is loaded on all pages of the app, validate that your application.js file contains the following line:

# /app/assets/javascripts/application.js

//= require_tree ../../../vendor/assets/javascripts/


2.2 Install a server-side library (optional)

If you want to make server-side HTTP calls to Segment, you’ll want a server-side library. Luckily, Segment has a whole bunch of ’em.

They also have a great article which answers the question: “When should I use client vs. server tracking?

I’m using the Ruby library, which I installed by adding a gem to my Gemfile:

# /Gemfile

gem 'analytics-ruby', '~> 2.0.0', :require => 'segment/analytics'

And then I created an initializer:

# /config/initializers/analytics_ruby.rb

Analytics ={
  write_key: 'YOUR_WRITE_KEY',
  on_error: { |status, msg| print msg }



2.3 Install the WordPress plugin (optional)

If you have a blog on a separate platform or codebase, you’ll want to add analytics.js there, too.

While is a static HTML site, the blog runs on its own WordPress instance. Segment has a handy WordPress plugin that automagically tracks everything you’d want to track. You can install it by searching for “segment” in the WordPress plugin search tool.

Segment - WordPress Plugin


2.3 Implement the tracking plan

Now we need to drop in bits of code to tell Segment when key things happen, according to our tracking plan.

Page Tracking

I have 3 key pages I want to track, so on each of them I’ll add a one-liner to indicate that the visitor is viewing a key page.

Add a page call to my Tour page:

<!-- /pricing/index.html -->'Tour');

Add a page call to my Pricing page:

<!-- /pricing/index.html -->'Pricing');

The signup page is hosted in the app itself, not the sales site, so I add the page call to the JavaScript on the signup page in my Rails project:

# /app/views/devise/registrations/new.html.erb

<%= javascript_tag do %>'Sign Up');
<% end %>

Identifying Users

Segment automatically cookies every new visitor to your site with an anonymous ID. When a user becomes known–via opt-in or sign up/in–calling identify links that identity to all the previously anonymous activity you’ve collected.

Managing identities can be a major source of pain with analytics tools, so pay close attention to this.

There are 2 points in my funnel where I’m going to identify a user: when they’re logged into the app and after they download a resource.

Here’s what the identify code looks like when someone lands on any of my app’s internal pages after logging in:

# /app/views/shared/_analytics.html.erb

<% if current_user %>
  // Segment
  analytics.identify('<%= %>', {
    name: '<%= current_user.full_name %>',
    email: '<%= %>'
<% end %>

To see how I’m identifying users after a resource download, read the section below titled Downloaded Resource.

Lifecycle Event Tracking

The Signed Up event is called from the app as well:

# /app/views/shared/_analytics.html.erb

<% if params[:init] == "true" %>
  analytics.alias('<%= %>');
  analytics.track('Signed Up', {
    userLogin: '<%= %>',
    type: 'organic',
    accountId: '<%= %>'
<% end %>

The Logged Activity event triggers whenever a user (parent or teacher) adds activitiy for a child. Since I have multiple controllers for each activity type, I have a concern that includes all of the shared methods for those controllers.

# /app/controllers/concerns/eventable_controller.rb

def track_logged_activity(activity_type)
    event: 'Logged Activity',
    properties: {
      type: activity_type,

Then in each of the 5 activity controllers, I add a method call to track_activity within the create action:

# /app/controllers/meals_controller.rb

def create
  @meal =

  respond_to do |format|
      # Send "Logged Activity" event to Segment
      track_logged_activity controller_name.classify.singularize

Downloaded Resource

For resource downloads I use a single modal form at to collect leads. When someone clicks the submit button, I have some JavaScript that pauses the submission, assigns some hidden field values, and then reports to Segment before the request transitions to the “thank you” page.

<!-- /resources/index.html -->

<!-- Set the right resource name in the modal -->
$(function () {
  // Set resource name when the modal form opens up
  $('a.resource-item').click( function () {
    var resourceName = $(this).attr('data-resource-name');
    return true

  // Grab a reference to our form
  form = $('form');
  // Run the function when the form submits
  form.on('submit', function(e) {
    // Stop the form from submitting... for now
    // Get the email address the user has entered
    email = $('[name=email]').val();
    name = $('[id=resourceName]').val();
    // Identify this visitor using their email address as a distinct ID
    // and as a new property
    analytics.identify(email, {
      email: email
    analytics.track("Downloaded Resource", {
      resourceName: name
    // Submit the form now that all our analytics stuff is done


function setResourceName(resourceName) {
  $('form input#resourceName').val(resourceName);
  $('#resourceModal #myModalLabel').text(resourceName);

Note: if I had a landing page for each resource, I would use Segment’s trackForm helper. But because I have to dynamically set and read the hidden resourceName field on-the-fly, I had to roll my own.

Invited User

# /app/controllers/parents_controller.rb

def track_invited_user
    event: 'Invited User',
    properties: {

Added Munchkin

# /app/controllers/munchkins_controller.rb

def track_added_munchkin
    event: 'Added Munchkin',
    properties: {
      creatorType: current_user.type,

Sent Daily Report

# /app/controllers/munchkins_controller.rb

def track_sent_daily_report(to_list)
    event: 'Sent Daily Report',
    properties: {
      recipientList: to_list,
      reportDate: @selected_date.strftime('%Y-%m-%d'),

2.4 Enable integrations

Now I’m going to enable 3 integrations:

  1. Google Analytics
  2. Mixpanel
  3. Optimizely

At this point, I’ve created accounts for the tools listed above, but I haven’t touched them yet. Instead of “installing” these tools, I’m simply going to enable them in Segment.

Segment - Integrations

The foundation I laid with Segment’s analytics.js and the track, page, and identify calls will start paying off.

Ah, the beauty of Segment.

Step 3: Google Analytics reports

There’s not much to configure in GA since Segment handles your tracking code and will automatically log GA events for each track call:

Google Analytics Events created by Segment

3.1 Configure Goals

Goals are important to setup because they add vital context to many built-in GA reports. For example, it’s nice to know which channels generate the most traffic to your site (via your Channels report), but it’s critical to know which traffic sources convert the best. You can’t do that without Goals.

Channels report (now with Goals!)

Since I already have my key conversion events coming in via Segment, it takes no time to setup Goals based on them.

I’m not going to setup a Goal for every event that I track. That’d be overkill. I’m only going to set them up for the following core lifecycle events (for now):

  • Signed Up (Acquisition)
  • Logged Activity (Activation)
  • Started Subscription (Revenue)
  • Downloaded Resource (Acquisition)

Just go to Admin and under your View section, click on Goals and create a new goal based on an Event:

Google Analytics goals based on events

3.2 Enable Demographic and Interest Reporting

I like to turn on the Demographic and Interest Reporting feature (via Segment, which will handle the GA tracking code update for you automatically):

Demographics Reporting

And then enable those report features in my GA property settings:

Demographics Reports setting in Google Analytics

Because who doesn’t want to know their audience demographics and interests?! Age, gender, and categorical interest data will now be visible under the Audience tab.

Other things I look at frequently in Google Analytics:

  • Overall traffic trends
  • Channel breakdowns
  • Top referrers
  • Site speed
  • Landing pages with high traffic and high bounce rates (candidates for optimization)
  • Stickiness (time on site, pages/visit)
  • Technology (mobile, browsers)

I like Portent’s Perfect GA Dashboard.

Step 4: Mixpanel reports

I use Mixpanel for two core features: funnels and cohorts.

Mixpanel has already been receiving events from Segment, so I can create funnels on-the-fly:

Resource download funnel

I’ve created funnels to visualize the steps people take towards critical events:

  • Visited Homepage → Viewed Sign Up Page → Signed Up
  • Visited Resource Page → Viewed Resource Form → Downloaded Resource
  • Signed Up → Created Munchkin → Logged Activity

And so on.

The other report I like to use in Mixpanel is the Retention report, which tells me which cohorts of users are sticking around and continually using my app. You can segment by any property to get a really granular view of things. For example, you can easily get a breakdown of retention rates for each subscription plan.

I haven’t really used the people reporting and notification features in Mixpanel yet, but they look pretty cool.

Step 5: Optimizely

Create an Optimizely account, grab their JavaScript snippet and add it to your sales site in the <head> tag before any other JavaScript tags. That’s all you have to do to start A/B testing pages on your site. The interface is super intuitive, so go ahead and create a simple test, perhaps with your homepage headline.

I have a confession to make: I lied to you.

You have to install Optimizely’s JS code OUTSIDE of Segment. Why? Well, because Optimizely does some crazy page modification magic that stipulates that it loads synchronously and before anything else. This is the only exception, I promise!

You should STILL enable the Optimizely integration in Segment because they’ll send custom events through to Optimizely to help you measure A/B test conversions and pass the A/B test experiment variations through to Mixpanel for better analysis.

Also, this integration isn’t supported on the Startup plan, but if this specific feature (i.e., sending the experiment info to Mixpanel) is important to you, Optimizely and Mixpanel have a free integration of their own that does the same thing.

Custom goals

You probably should track your Optimizely experiment against a custom goal (versus just looking at engagement)–probably one of the lifecycle events we defined earlier like Signed Up or Downloaded Resource.

Make the name of the Optimizely goal event exactly match the corresponding Segment event name.

Optimizely Goals

Then trigger the Optimizely event right after the Segment event in your codebase:

# /app/views/shared/_analytics.html.erb

<% if current_user %>
  <% if params[:init] == "true" %>
    // Segment
    analytics.track('Signed Up', {
      userLogin: '<%= %>',
      type: 'organic',
      plan: '<%= current_user.account.plan %>',
      accountId: '<%= %>',
      accountSubdomain: '<%= current_user.account.subdomain %>'

    // Optimizely
    window['optimizely'] = window['optimizely'] || [];
    window.optimizely.push(["trackEvent", "Signed Up"]);

  <% end %>
<% end %>

Step 6: ActiveCampaign

ActiveCampaign is a very solid, well-designed marketing automation tool. They’re not as comprehensive as HubSpot, but they honestly have no business away so much functionality for $9/month.

Right now I use ActiveCampaign for the following things:

  1. Capture leads via forms (and the API)
  2. Send email nurture sequences (one for leads, one for trials)

Capturing leads via forms

I created a form for my Leads list, configured the fields, and placed the emebed code on the resources page on my site.

I don’t like ActiveCampaign’s double opt-in process, so I did some additional customization:

  1. Un-check the box under Opt-in confirmation email to disable double opt-in.

ActiveCampaign - Disable Double Opt-in

  1. Click on Form settings and edit the subscription confirmation page. I redirect submissions to a plain old HTML page that I control completely.

ActiveCampaign - Custom URL

When a visitor fills out the Resource Form, they are added to the Leads list and redirected to my generic resource “thank you” page.

An automation is triggered which emails them the resource they asked for and tags them with “Resource: {resourceName}”. If they’re a brand new lead, they are also enrolled in my content funnel automation and will receive all our best content over time.

Email nurture automation

Capturing leads via the API when a trial is started

My trial signup form posts to the Rails app, not ActiveCampaign, but I DO want these users in my marketing database so I can send them an onboarding email sequence, tag them, etc.

So, after a new user signs up, organically or by accepting an invite from another user, I sync them to ActiveCampaign via the API.

There is a third-party Ruby wrapper for the ActiveCampaign API, but it didn’t work for me and I didn’t feel like writing my own, so I used Zapier instead.

Here’s the method I wrote on the User class:

# /app/models/user.rb

def update_marketing_contact(signup_type, tags)
  params = {
    first_name: self.first_name,
    last_name: self.last_name,
    subdomain: self.account.subdomain,
    plan: self.account.plan,
    signup_type: signup_type,
    tags: tags
  Zapier.zap(:contact_sync, params)
rescue => error
  logger.error error

After a new trial user is “zapped” into ActiveCampaign from my app, they’ll enter the onboarding email sequence which sends helpful emails about how to use them app.

Wow. That was A LOT, huh?

This just goes to show that laying a solid foundation for analytics and marketing automation takes foresight and planning, some technical chops, an analytical mindset, and some trial and error. And my app is small potatoes compared to many of the businesses you guys are dealing with.

I hope this guide can serve as a step-by-step implementation plan for those that want to use this precise stack, and for those that want to mix it up, maybe you can use my setup as a loose template.

Feeling overwhelmed? No worries, I’ve got your back.

Analytics X-Ray

Featured image credit (cc):

Marketing Stacks

Marketing Stacks

One of my favorite things about Ruby on Rails is that it’s a very opinionated framework. It makes key decisions up and down the technology stack so that I don’t have to. As DHH puts it, Rails is omakase:

A team of chefs picked out the ingredients, designed the APIs, and arranged the order of consumption on your behalf according to their idea of what would make for a tasty full-stack framework.

As a result, it’s remarkably easy for beginners to get started and actually ship something useful without getting bogged down with infrastructure details.

Rails is by no means the only framework like this. The concept of default “stacks” is extremely common in all corners of software development.

Some stacks aren’t wrapped up with a bow like Rails is; rather, they’re written prescriptions of what to use together (e.g., the “LAMP” stack: Linux, Apache, MySQL, PHP).

While not automated, this still achieves the goal of eliminating up-front research by giving you defaults that Just Work™ and will drastically cut down your time to delivering value.

It’s time for marketing stacks

With the proliferation of marketing tools over the past few years, I think we’re desperately in need of some default marketing stacks.

You can quickly become paralyzed by choice when trying to setup a full-fledged marketing stack. There’s so much to consider: lead capture, analytics, email marketing, contact management, behavioral automation, A/B testing, social media, and more.

Wouldn’t it be awesome if someone just gave you a shopping list and how-to guide for all the components that work really well together for your particular scenario, be it SaaS, e-commerce, enterprise, or whatever?

Wait, doesn’t marketing automation software solve this problem?

To be blunt: no.

Marketing automation suites like HubSpot attempt to be all-in-one solutions, but none of them does everything I need. Even if I had the budget for HubSpot or Marketo, I’d still want to supplement with Segment, Mixpanel, and Google Analytics at minimum.

What’s more, these massive suites tend not to be as opinionated as they should be. They provide so much flexibility and power that it’s easy to get lost down a rabbit hole. This is exactly why I decided to write Mastering HubSpot. I wanted to remove all the decision-making and provide readers with a detailed prescription for how to use the software to get the best results.

A low-cost marketing stack that I love

I put together a powerful, yet cost-effective stack for my SaaS app Munchkin Report. It literally costs me $9 per month.

This stack is ideal for pre-revenue bootstrappers who don’t want to invest a ton of money but want to be poised for growth.

What’s in the stack?


A/B Testing

Marketing Automation (opt-in forms, email marketing, automation, and CRM)

Bam. 9 bucks per month.

I’m writing a highly detailed setup guide that will walk you through how to best configure and tune this stack end-to-end for your business, so stay tuned for that!

Other super-cheap or free marketing tools you’ll catch me using for Munchkin Report, but I consider outside the scope of my core marketing stack include:

Keep in mind, while the philosophy of a stack is to dictate sensible defaults, you should feel free to substitute when the need or desire arises.

What does your marketing stack look like? Leave a comment and let me know!

Need help planning and implementing your marketing stack? Let’s talk.


Note: I have zero affiliation with the tools I mentioned in this post.

Nathan Barry

A Detailed Summary of Nathan Barry’s Book: Authority

Here are my detailed notes on Nathan Barry’s money-minting book Authority.


Before you read my notes, please keep in mind this is a quick-and-dirty summary that will hopefully encourage you to take your first steps towards self-publishing. The book itself is orders of magnitude more valuable than this blog post.

My favorite thing about Authority is that it prescribes EXACTLY what to do to be successful in researching, writing, and selling your book.

It eliminates all the guesswork and decision-making, which saves you time and reduces risk of failure.

Authority is the most useful book I’ve ever purchased.

I’m using everything I learned to write and publish my next book, Mastering HubSpot, and I can’t wait to share the results with you.

(By the way, for those wondering, I cleared this post with Nathan.)


On Writing

Teach everything you know.

You don’t have to be an expert to teach.

Teaching, by itself, will establish you as an expert.

“When faced with writer’s block, lower your standards and keep going.” –Sandra Tsing Loh

Set a daily goal to write 1,000 words a day and track your progress in an app like Lift or Commit.

Finding an audience

Ask yourself:

  1. What do people ask me for help with?
  2. If I teach people this skill, will it help make them money?
  3. Can I reach those people online?

Basic Marketing

Host all of your books on a single domain. Why?

  • All Google juice goes to a single domain
  • People browsing for book A can easily find book B

Setup a landing page to test demand.

What do you need?

  • Headline
  • Description
  • Picture of a real book
  • Opt-in form (this is key!)

Host the landing page on WordPress with a premium theme or use something like Unbounce or ConvertKit which are turnkey.

Tell everyone about it. Ask friends to share the link (provide them with a sample chapter).

Write (at least) 3 epic blog posts on your book’s topic and promote them. This should help you capture emails with your opt-in form and build your launch list.

Don’t let your list die. Email them once a week or once every other week.

Writing, Lots of Writing

What do we have to write?

  • The book: 30,000 words (cut down to 25,000)
  • 3 epic blog posts (1,000 words each)
  • 7-10 guest blog posts (1,000 words each)
  • 3 emails to your launch list (500 words each)


  1. Add chapters and sub-topics as sections in Scrivener (don’t worry about order)
  2. When starting a writing session, skim the list for a topic that you feel inspired to write about and start
  3. Remember: there’s plenty of time to go back and edit, so don’t try to be perfect

Pro-tip for focusing: stand up.

Read other books on your topic to a.) learn b.) ensure you don’t miss any key points.

At about 18,000 of your 25,000 word goal, take a step back and review. What are you missing? What content is overlapping? What doesn’t make sense?

Cutting Content

For things that don’t quite fit, remove them. Don’t waste your reader’s time. However, try to repurpose that content for a blog post or tutorial.


Clearly communicate your value proposition. Focus on outcomes.

  • Mastering _____
  • The _____ Handbook
  • Step-by-Step _____
  • The _____ Bible
  • Learn _____ from Scratch
  • The Essential Guide to _____

Pricing & Packaging

Price based on value delivered. Don’t anchor yourself to traditional book prices or Amazon’s pricing model.

$39 to $49 seems like a good price for a 25,000 word eBook provided you’re delivering real value.

Use Packages

Example packages:

  1. Book $39
  2. Book + Videos $79
  3. The Complete Package $169

Charging a lower price isn’t always a bad idea, though. If you sell your book for $9, you might make less $ but you could end up with a larger customer list, which you could leverage to sell your next book at $49.

Try including the same material across multiple media (e.g., PDF, audio, video).

It’s hard to justify creating a higher tier package that only includes additional text content (why wasn’t that in the book?). When the added content is video or audio or source code, the perceived value of that tier is much higher.

Example extras:

  • Short video tips
  • Video Interviews
  • Text interviews
  • Design resources
  • Sample code
  • Explanation screencasts
  • Video lessons (video of the expert talking)
  • Photoshop files

You can even get away with making an eBook that curates free material you’ve previously published on your blog. People place value on saving time by having everything in one place.


Interviewing experts in your niche elevates your status and it’s a compliment to them. But make sure that you don’t make them do any work. 30 minutes is good enough. Don’t offer to pay them–that will muddy the incentives.


Don’t do DRM. Forget about piracy. Now.

Design & Formatting

Outputting to multiple formats is painful. Release only as PDF and maybe consider .mobi and .epub if people are demanding it, but know that the formatting might not be ideal.

Nathan evaluated tons of methods for creating PDF eBooks. He settled on iBooks Author. I will, too.


Cover art isn’t that important since your book won’t be on a shelf, so go with something simple: a solid color or a pattern with clear, easy-to-read text and perhaps an icon.

Prepping for Launch

Not using platforms like Amazon and iBooks to sell forces you to do your own marketing. Those platforms take a big cut of your profits, too.

Stay connected with your audience

Once every other week or so, drip out content to your launch list. Don’t go dark on them. Send them your epic blog posts or sample chatpers. Give them a time-limited discount for being on the launch list.

Nathan has a specific course on Mastering Product Launches. Do not skip this! It’s a magic formula.

Getting Guest Blog Posts

Make a list of the blogs you’d like to write for.

Build the relationship over time by posting comments on their posts or sending an email like this:

I really enjoyed your last post on ____________. As I researched the topic more I came across this post that provides some more detail and approaches the problem from a different angle. Here you go: ___________________
Thanks again,

When you email them to ask about a blog post, give them an easy out. Don’t use a hard sell.

Hopefully this will help

Preview Copies & Testimonials

Give away preview copies and ask for feedback and testimonials. Write the quote for them and let them edit it.

The sales page

Use the pain-dream-fix method of copywriting.


  • Why someone should care
  • Sample chapter
  • Table of contents
  • Social proof
  • About the author
  • Listing of packages
  • A purchase link
  • FAQ to overcome objections
  • Another purchase link


Use Gumroad.

Launch & Beyond

Email your list the day before you launch to let them know what’s coming. When the launch day email hits their inbox, they’ll already know whether they want to purchase.

Make sure your sales page, e-commerce, and analytics are setup and working before launch day.

On launch day:

  • Publish a blog post that says what the book is and has a strong CTA
  • Email your list at 8:00am ET

Ask for shares

Hey ______,
Thanks so much for your help and support through this process. It means a lot! The book is finally live and sales have started to roll in. You can check out the site here:


Would you mind helping me promote the book? Tweets, Facebook posts, and Hacker News sub- missions are all welcome. I appreciate all the help. :)

Let me know if I can help on your next project. 


The Dip

Inevitably sales will dip after your big launch day/week. To cure this, keep teaching and writing about your book topic with purchase CTAs to reach new people in your target audience.

Also, creating automated email courses ensure that all new subscribers get all of your best content from the past dripped out over time vs. only getting the new stuff.

Take your best content and arrange it into a sequence:

  1. Educate
  2. Educate
  3. Educate w/ soft sell
  4. Educate
  5. Educate
  6. Educate w/ hard sell
  7. Educate
  8. Educate w/ soft sell

Releasing updates

Don’t underestimate how time-consuming updates can be, especially for technical books.

Should you charge for updates? Fixes and minor updates should be free. New editions should be 50% off for existing customers.


Wait at least 6 months after launch before you offer a deal. You don’t want to upset your most loyal customers who purchased on day 1.


Just give ’em and move on. Only worry if your refund rate is over 5%.

Closing thoughts

The advice bundled in this book has changed Nathan’s lifestyle in a big way. If you follow the advice in the book and put in consistent daily effort, you can have a similar impact on your own life.

Please do yourself a HUGE favor and buy the book!

Rules of Growth, Debunked

Austen Allred wrote a creative, yet somewhat link bait-y, post called Rules of Growth. I really enjoyed the rapid fire format and I think you’ll find it to be a super-fun read. Check it out and come back.

I think Austen was trying to be hyperbolic to increase virality, which is smart. But, me being me, I had to humbly refute some of his rules. :)

1. No one really cares about your product

So Apple did care about Beats headphones, the product, when it paid $2.6 billion for it? Do people shop at Whole Foods because they like high prices? Do I care if HubSpot stops releasing features and I have to spend 2 months switching away?

2. No one really cares about you

I guess define “you”–if “you” is the marketer then I agree; if “you” is the brand, then I disagree, kinda for the same reasons above.

8. The marketing tactics people complain about are the ones that work

Work sometimes or really work? Cold calling on the whole doesn’t work.

9. Everyone clicks on ads

Every data point I’ve seen shows otherwise, but I think this was just hyperbole.

12. Proxies solve any scaling problem

I don’t quite understand this one.

17. Good marketers cheat

Define cheat. I don’t think I’m cheating. Or maybe I’m not good. :)

20. The greatest companies have all grown on the backs of spam

Zappos, Amazon, Dropbox?

23. All press is good press

I’ve seen bad press damage reputation and cause massive headaches and create time sinks for execs. Ask Godaddy, Uber, or Sony about this.

End-of-Year Update on Munchkin Report

The new year is fast-approaching and I’m laser-focused right now.

As you’ve may have seen with my prior status reports, one of my goals with Munchkin Report is to publicly document everything I’m doing both with product and marketing, so that when I hit a revenue or customer goal, you can actually trace back every action I took to get there.

Hopefully that’s helpful.

What’s new?


We just finished drafting our email course on data-driven parenting. Anyone who downloads our printable daily tracking sheet PDF will be enrolled in the course.

Right now it’s only 3 emails, but we’ll add more as we write them. The important thing is that we stay in contact with people who come into ecosystem.

Here’s a link to the full email series in case you’re interested in how it looks.


I finished the notes and photos feature so you can attach free form comments and photos to a daily report (in addition to all the structure stuff like meals, naps, moods).

I also added the ability to mark any note or photo as a milestone and built a rudimentary milestone timeline which lets you browse all the biggest moments in one place. It’s kinda crappy, but perfect is the enemy of done, right?

Mobile will be the death of me

It’s like watching a horror movie where you know the girl is going to get straight-up murdered because she’s drunk and wandering into the woods to meet her boyfriend and you’re SCREAMING at the TV: “NOOOOOOO!!!!”

A little voice in my head is screaming “MAKE A GODDAMNED MOBILE APP ALREADY!”

I know Munchkin Report will die if I don’t have mobile support, but mobile is virgin territory for me. My hope is that the web version can provide enough value to get people excited and get us a little traction that affords me the time to come up with a mobile strategy in Q1 and ship something in Q2.



I have some analytics setup to do to prepare for our public launch in January when we take down the “Request an invite” CTA and let anyone start a free trial. I want to ensure that I have crystal clear visibility into my funnel and what’s working to acquire and activate customers.

I’ll document all this here on the blog so other people running a low-cost SaaS can copy my setup.

Explainer video

I want to make a video for the sales site that quickly explains the value prop. I also want to make some quick onboarding screencasts.

Helpful resources:

Onboarding email sequence

I have to write and setup a welcome email sequence that helps get new trial customers headed in the right direction.

Helpful resource:

‘Til next time.

Stacking the bricks

Stacking the Bricks in 2015

Amy Hoy wrote a fantastic essay last year with advice on how to REALLY launch in 2014.

I read it from start to finish but, foolishly, I didn’t take any action. I didn’t apply her advice, which was THE WHOLE FREAKIN’ POINT of the essay.

So, I’m doing it now. For realz.

My F%ck THIS! moment

I’m tired of short-changing my personal projects.

It pains me that I have the talent but I’m not using it to improve my situation.

I accept that I’m severely time-constrained with a high pressure full-time job and 2 very young kids, yada, yada (Hey, Amy said my F THIS moment is supposed to be a bitchfest!)…

BUT I know that if I seriously focus and build momentum I can ship all the things in 2015.

There is no such thing as an overnight success. There is only stacking the bricks.

Amy says:

One tiny win won’t do it. Neither will five. No, success is made up of the accumulation of hundreds of tiny wins — and to get that many, you need to work at it over & over & over again.

I will stack a brick every week. Every. Single. Week. But how? By breaking my bad habits and replacing them with good ones!

Before I go to sleep each night, I’ll make sure I know the next 3 physical actions I need to take to make forward progress.

When I sit down at my computer I will be deliberate. I will write, or I will code, or I will design.  If I’m not doing one of those 3 actions, I’m cheating myself.

Motivation is a racket

The Oatmeal: Just Do It Later

As Amy points out, the prevailing wisdom is to try and bottle up a motivational feeling, which has nothing to do with taking action. Manipulating feelings is a fool’s game. Instead, create structures and habits.

Show up. Do the work. Plain and simple.

You know perfectly well how to achieve without motivation or grit. Your kids or pets don’t starve when you’re having a bad day.

Amy also writes about why blacksmiths are better at startups than you. The parallel example I like to use is professional fighting.

Fighter Conor McGregor has a mantra that I love: always move forward. It refers to his fighting style in the cage, but it also encapsulates the tiny daily wins—showing up at the gym, putting on the gloves, and getting a little bit sharper every day. 

The only way Conor or any mixed martial artist can win fights is through grueling, repetitive, bloody work. If he can wake up every morning and literally get the shit kicked out of him for 3 months straight to prepare for a 15-minute fight, I think I can buckle down and ship some software and a book in 2015.

Further reading on the topic of inch-by-inch success:


8 Simple Rules to Avoid Email Hell

I just listened to an episode of in which Thomas Knoll describes why he decided to ban internal email at his company. It’s a great episode, go give it a listen.

I dislike email as much as the next guy, and I totally agree with Thomas on keeping institutional knowledge and TODOs out of email, but I’m going to take a somewhat contrarian view on this. I think banishing internal email entirely can have negative side effects. Email is very good for asynchronous communication when used appropriately.

It’s not email (the tool) that’s the problem, it’s the people who abuse it.

I don’t like chat as a substitute for email, either. I’ll quote my previous boss, Michael Pryor (Trello, Fog Creek):

So rather than taking a shotgun approach, try implementing a simple rules to keep email sane.

Here are the guidelines we use:

  1. Think hard before you hit send on an email. Can you do it yourself with just a little more time and effort?

  2. Email is not a world-writeable TODO list. Just because someone emailed you and asked you to do something doesn’t mean you should do it. We want to be helpful and courteous, but we are accountable to our team goals first and foremost.

  3. Don’t email a group and expect an action to occur. This diffuses responsibility. Email one person and cc others if absolutely necessary.

  4. Think before you cc someone. Do they really need to know about it?

  5. Don’t expect people you cc to read your email.

  6. Keep your emails short (3 to 5 sentences) and always highlight what needs to by done, by whom, and when.

  7. Don’t send “thank you” emails. It’s implied and they waste time.

  8. Keep institutional knowledge and TODOs out of email (and in Basecamp, Trello, etc.).