You’re reading Signal v. Noise, a publication about the web by Basecamp since 1999. Happy !

All the oxygen trapped in a bubble

David
David wrote this on 54 comments

There are many good reasons to be concerned about whether the internet industry is in another bubble. Once shaky, unproven businesses hit the NASDAQ, the chance that granny is going to lose her pension fund goes up big time. That’s the direct economic consequence that you’ve probably heard already.

What hasn’t been discussed as much are some of the secondary effects that a bubble has on the industry. Like how it gets harder to hire good people as a consequence. Sure, you may have heard of The War for Talent, but it’s much deeper than that. This is not simply about the latest tech darling not being able to find programmers in the Valley.

When bubbles inflate as fast as the most recent one, support infrastructure can’t cope. There just aren’t enough programmers, designers, operations people, and other warm bodies to man all the hot air balloons. So you have a predictable effect: Rapidly increasing demand for an only steadily increasing supply. Thus, inflation.

All this new demand is being fueled by the endless flows of cheap cash being pumped into the Valley (and everywhere else it can go). So the circle goes like this:

And every time we do a round, more talent gets trapped in the bubble, chasing things that can be flipped for the most money. Now in theory this is all good and well. Resources are allocated to the pursuits with the most economic value. So if Instapintora is worth $2 billion, of course they deserve to be able to hire 1,000 web builders, right?

That’s the same argument you’ll find for bridges to nowhere and other pursuits void of inherent economic and public value. Sure, people are being employeed, money is changing hands, but come Monday morning, the hangover is that we spent a bundle to build a lot of shit that’s not going anywhere.

As a result, we missed out on doing other worthwhile things. All those smart and talented heads, and all those benjamins, didn’t progress the economic base in a way we’re going to care about tomorrow. And that’s a damn shame.

Three quick Rails console tips

Nick
Nick wrote this on 15 comments

I was bouncing around the Rails API documentation yesterday, and I noticed a few rails console tricks I haven’t seen before. There’s been plenty of posts about irb and Rails before, but I’m hoping you’ll learn something new here. The following console samples were taken with Basecamp Next on Rails version 3.2.3.

Dive into your app

Running the app method in rails console gives you an integration session instance, so you can use it just like when you’re a normal integration test for Rails.

>> app.class
=> ActionDispatch::Integration::Session

Generating routes was always a hassle. What module did I need to include again? Did you remember to set the default_url_options? Stop googling and just use app:

>> app.project_path(Project.first)
=> "/projects/130349783-with-attachments"

It can make requests inside of your app as well:

>> app.get "/735644780/projects/605816632-bcx.atom"
=> 200

>> app.response.body
=> "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<feed xml:lang=\"en-US\"  ...

Check out ActionDispatch::Integration::Session and ActionDispatch::Integration::RequestHelpers to see what else this object can help you with.

Try out a helper

Getting a console session bootstrapped with Rails’ helpers is also a pain, which helper can fix for you! You could also use it to play with building HTML tags, or any existing Rails helper that ActionView knows about.

>> helper.truncate("Testing", length: 4)
=> "T..."

>> helper.link_to "Home", app.root_path
=> "<a href=\"/\">Home</a>"

One gotcha with helper is using instance variables inside of helper methods. Yes, I’m aware this is a Bad Idea™ with helpers in general, but I haven’t worked in a single Rails app without one. Here’s a small example of a method with one:

def title_tag(title = nil)
  if @project.present? && title.nil?
    content_tag :title, @project.name
  elsif @project.present?
    content_tag :title, "#{@project.name}: #{title}"
  else
    content_tag :title, title
  end
end

We can use our old friend Object#instance_variable_set to violate a core principle of OOP and let us try this helper out in the console:

>> helper.title_tag "Testing!"
=> "<title>Testing!</title>"

>> helper.instance_variable_set :@project, Project.first
=> #<Project id: 130349783, ...

>> helper.title_tag
=> "<title>With attachments!</title>"

>> helper.title_tag "Posts"
=> "<title>With attachments!: Posts</title>"

Dealing with a helper that uses params is also not straightforward. However, we can trick ActionView into listening to us with a tiny hack. This is the console, after all! Let’s say we have this helper method:

def javascript_debugging_options
  if params[:javascript_debugging] == "enabled"
    { debug: true, digest: false }
  else
    {}
  end
end

Usually ActionView needs an entire ActionDispatch::Request from the controller to figure out what parameters came in from the user. We can trick it with a little OpenStruct instead:

>> helper.controller = OpenStruct.new(params: {})
=> #<OpenStruct params={}>

>> helper.javascript_debugging_options
=> {}

>> helper.controller = OpenStruct.new(params: {javascript_debugging: "enabled"})
=> #<OpenStruct params={:javascript_debugging=>"enabled"}>

>> helper.javascript_debugging_options
=> {:debug=>true, :digest=>false}

Where does that method come from?

Hunting down the exact location of a given method isn’t always easy. Luckily, Ruby can point you in the right direction with Method#source_location:

>> Project.instance_method(:trash).source_location
=> ["/Users/qrush/37s/apps/bcx/app/models/project.rb", 90]

Whoa! You’ll get back an array with the full path of where the method was defined along with that method’s line number in the file.

I’ve used this when looking for code buried inside of gems as well. Let’s try it on app:

>> app.method(:get).source_location
=> ["/Users/qrush/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/bundler/gems/rails-7d95b814583b/actionpack/lib/action_dispatch/testing/integration.rb", 32]

This tip has saved me from an immense amount of source diving. Try it out!

More tips

Looking for more tips? JEG2 gave a neat talk at RailsConf about some of the hidden parts of Rails you might not know about. If you have some of your own, please share!

We're hiring: Help us significantly improve conversion and retention

Jason Fried
Jason Fried wrote this on 39 comments

We’re looking for another teammate. This time we’re looking for someone who is completely focused on improving conversion and retention. You love moving the needle, one small step at a time. This job is all about seeing untapped potential.

Conversion could be financial (get more people to start a trial or complete it – what we consider a “sale”), or outcome-based (inspire people to create more Basecamp projects by showing them creative ways to use Basecamp they never thought of before). Or something else.

Retention could be reducing cancellations, or reducing unsubscribes from our mailing list, or increasing the number of people who log into Basecamp every day. Or something else.

You should…

You should be great at figuring out which words or phrases hook people instead of letting them get away. We believe the right words at the right time can make all the difference.

You should look at a sign up form like… …and already know three ways to significantly improve conversion.

You should be great at understanding what motivates people. This requires deep insight into the decision making process. You should know why people buy, why people don’t buy, why people buy more of something they already have, and why people who bought decide not to buy any more.

You should look at a screen like… …and think to yourself – “if they rearranged this, highlighted that, or renamed this other thing, they’d increase sales by at least 25%.”

You should be great at knowing how to help people find value in something they already have. There are always more ways to use something than the ways you already use it.

You should look at a new project like… …and say “no, no, no… a better way to get someone started on a new project is like this…”

Or you should look at an email like… …and think “You’re missing a big opportunity to get more people to take action here. If we…”

Ideas and execution

This is not just a job for an idea person – it’s about ideas and execution. You’ll be expected to write the copy. You’ll be expected to implement the designs. You’ll be expected to shepherd ideas from start to finish – not just to toss them out there for other people to worry about.

You should love to propose, experiment, implement, execute, and measure. You may not be able to take everything on 100% yourself, but you try your best before you hit your limits and have to ask for help.

The challenge: Double our sales

We’d like to double sales over the next 12 months without making deep material changes to our products. We don’t believe it’s possible. Change our minds. Convert us.

Can you do it?

If this sounds like something you’re great at, we’d love to talk to you. This is a new position at 37signals, so you’ll be in charge of making it work.

You’ll be part of the best overall team in the business. From ops, to programming, to design, to support, to data, to video – we’re ready to work together to see your bright ideas through.

To apply

Send an email titled [Conversion] to [email protected] telling us why you’re the one. How you tell us is up to you.

Our office is based in Chicago, but our team is spread out all over the world. You can work from anywhere. We just require a few trips to Chicago a year when the whole company gets together.

We’ll be accepting applications until June 4.

This is a chance to do the best work of your career. We know you’re out there. Get in touch.

Taking the Pain Out of MySQL Schema Changes

John
John wrote this on 19 comments

A common obstacle we face when releasing new features is making production schema changes in MySQL. Many new features require additional columns or indexes. Running an “ALTER TABLE” in MySQL to add the needed columns and indexes locks the table, hanging the application. We need a better solution.

Option 1: Schema Change in Downtime
This is the simplest option. Put the application into downtime and perform the schema change. It requires us to have the application down for the duration of the “ALTER TABLE”. We’ve successfully used this option for smaller tables that can be altered in seconds or minutes. However, for large tables the alter can take hours making it less than desirable.

Continued…

Basecamp in Antarctica

Shaun
Shaun wrote this on 14 comments

We have customers around the world doing extraordinary things with our software, but Ben Saunders is taking it to a whole new level.

Ben and his team are using Basecamp to organize an expedition to the South Pole and back, unsupported and on foot. This is the same journey Captain Robert Scott died trying to achieve 100 years ago, and no one has attempted it since.

Ben has been a professional polar explorer for more than 10 years and is one of only three people to complete a solo journey to the North Pole. He will be joined by Alastair Humphreys, who has cycled 46,000 miles around the world, and renowned nature photographer Martin Hartley.

You can follow the expedition, which launches this October, at Scott2012.org and be sure to follow @polarben on Twitter.

Special thanks to Temujin Doran for letting us use his amazing arctic footage.

Sortfolio: Going once, going twice...

Jason Fried
Jason Fried wrote this on 113 comments

A year ago we put Sortfolio up for sale.

We entertained a variety of offers, met with a few potential suitors in person, and negotiated numbers. Ultimately nothing came together. Then we shelved the process so we could focus all of our efforts on designing and building the new Basecamp.

Sortfolio continued to run itself for another year, generating over $200,000 in profit for us during that time.

Our paying customer count continues to hover consistently in the 170s, each paying $99/month to be listed as a premium member.

The price

We’ve put Sortfolio on the clock: We either sell it by July 1, or we close it down. And we’ll make it easier this time so there’s no guessing: The price is $480,000, cash. No special deals, no partial payments now the rest later, no equity in your company, etc. $480,000 cash and it’s yours. Considering how much hands-off free cash flow it generates, we think that’s a very fair price. We just want it to go to a good home.

We’ve put next to no effort into it over the last year… If you put some effort in you should see significantly higher sales. With over 10,000 free accounts, there’s tons of untapped opportunity here in the existing customer base. And of course plenty more on the outside or in entirely different industries.

What you get

You get the design, the branding, the code (it’s a Rails app), the customers, and the steady cash flow. Since Sortfolio is hooked up to our centralized billing system, you’ll need to write your own code to charge customers. Also, since Sortfolio is hosted on our server cluster, no hardware is included (but you can run it on a cheap server or two – the hardware requirements are next to nothing). We’ll also be happy to announce the sale here on SvN and on our very well subscribed email newsletter.

Interested?

If you’re interested at $480,000, please email me direct at jason@37signals… Thanks.

Keynote by David from RailsConf 2012 on progress, curiosity, fear, and the danger of easy-bake ovens.

New in the all new Basecamp: Email-in!

Jason Fried
Jason Fried wrote this on 64 comments

This is going to be a big one. Now you can post messages, to-do lists, files, and text documents to the all new Basecamp just by sending an email.

First, some background

In Basecamp Classic, you can post a new message by sending an email directly to Basecamp. This feature is especially useful if you’re on the road and want to post a message to the project from your phone. Just fire up your email app, address the email to Basecamp, and it’s immediately posted as a message to the project.

Initially, the all new Basecamp didn’t launch with this feature. Like everything else in the new Basecamp, we wanted to approach it fresh, take our time to think it through, explore a variety of ideas, and make it even better than before.

Better than before

In Classic you could only post a message via email. You couldn’t make a to-do list, start a text document (called Writeboards in Classic), or upload a file via email.

But in the all new Basecamp, you can do all these things and more. Plus, it’s easier, clearer, and more powerful than before.

Here’s how it works

At the bottom right corner of every project you’ll see a link that says “Email content to this project”.

When you click that link, you’ll see a sheet pop up that looks like this:

You’ll see five icons at the top of the page. Each icon describes a different email-in feature. Starting discussions, making to-do lists, creating documents, uploading files, and forwarding emails. Clicking any one of those icons shows you the simple steps to follow for each feature.

Below the steps we show an example of an email and how that content will look when it’s posted to Basecamp.

When Basecamp receives your email and posts your content to the project, it immediately sends you an email receipt letting you know it worked.

For most content types, the email also includes a link to let you notify others on the project letting them know that you just added something to the project. If you click that link you’ll see:

Since we expect a lot of people to email in from their mobile phones, we made a mobile optimized version of the notifications screen too:

And a bonus feature

In addition to allowing you to start discussions, make to-do lists, create text documents, and upload files via email, we also allow you to forward in any existing email to Basecamp. This is especially useful if there was a conversation going on outside of Basecamp. Just forward that email thread into Basecamp and it’s stored along with everything else on the project. Easy peasy.

Forwarded emails get collected into a “Forwarded emails” section at the bottom of the project.

And if the email was an HTML email, we show the full HTML email, too:

So many uses

There are so many interesting ways to use this new email-in feature in Basecamp.

One of the things I’ve loved about it so far is that I can sketch an idea on the whiteboard/chalkboard in a meeting room in our office, take a picture of it with my iPhone, and email it directly to a Basecamp project. It’s such a great way to get the physical results of a brainstorm, meeting, or sketch session right into Basecamp. And now that it’s in Basecamp, I can erase the whiteboard and not worry about ever losing that idea.

Email-in is also a great little “poor-man’s API”. You can have your apps send emails direct into Basecamp whenever you make a sale, get survey results from a customer, or who knows what. The opportunities are endless. We’re eager to see what sorts of things people come up with.

Thanks again

We’re thrilled with the feature and we think you’ll feel the same way. Thanks again for using Basecamp!

A/B Testing: It's not about the results, and it's definitely not about the why

Noah
Noah wrote this on 8 comments

In college, I worked for a couple of years in a lab that tested the effectiveness of surgical treatments for ACL rupture using industrial robotics. Sometimes, the reconstructions didn’t hold. The surgeons involved were sometimes frustrated; it can be hard to look at data showing that something you did didn’t work. But for the scientists and engineers, all that mattered was that we’d followed our testing protocol and gathered some new data. I came to learn that this attitude is exactly what it takes to be a successful scientist over the long term and not merely a one-hit wonder.

Occasionally, when we’re running an A/B test someone will ask me what I call “success” for a given test. My answer is perhaps a bit surprising to some:

  • I don’t judge a test based on what feedback we might have gotten about it.
  • I don’t judge a test based on what we think we might have learned about why a given variation performed.
  • I don’t judge a test based on the improvement in conversion or any other quantitative measure.

I only judge a test based on whether we designed and administered it properly.

As an industry, we don’t yet have a complete analytical model of how people make decisions, so we can’t know in advance what variations will work. This means that there’s no shame in running variations that don’t improve conversion. We also lack any real ability to understand why a variation may have succeeded, so I don’t care much whether or not we understood the results at a deeper level.

The only thing we can fully control is how we set up the experiment, and so I judge a test based on criteria like:

  • Did we have clear segmentation of visitors into distinct variations?
  • Did we have clear, measurable, quantitative outcomes linked to those segments?
  • Did we determine our sample size using appropriate standards before we started running the test, and run the test as planned, not succumbing to a testing tool’s biased measure of significance?
  • Can we run the test again and reproduce the results? Did we?

This might sound a lot like the way a chemist evaluates an experiment about a new drug, and that’s not by accident. The way I look at running an A/B test is much the same as I did when I was working in that lab: if you run well-designed, carefully implemented experiments, the rest will take care of itself eventually.

You might hit paydirt this time, or it might take 100 more tests, but all that matters is that you keep trying carefully. I evaluate the success of our overall A/B testing regimen based on whether it improves our overall performance, but not individual tests; individual tests are just one step along what we know will be a much longer road.

"Sign up in seconds" ... and then what?

Ryan
Ryan wrote this on 34 comments

Today I saw a familiar pattern on a website for an analytics product. The home page pitched the product, and then above the signup form there was a headline: “Sign up in seconds.”

I see this all the time on signup forms and it makes me wonder: why did the designer put that there? My best guess is that they were trying to relieve some anxiety the customer might have. Like, “don’t worry, it’ll be over soon!”

I’ll bet that the time-to-signup isn’t an important anxiety factor. When’s the last time you shopped for a software product under intense time pressure, where every second counts?

When I evaluate web products I often feel uncertain about what will happen after the quick signup. Sure it takes seconds to create an account, but then what?

I had an idea to address this uncertainty. You could preview the workflow steps that come after the signup so it’s clear how much of a gap there is between signing up and getting value out of the product.

Check out this sketch. It shows “what happens” after you signup. Once you sign up, you get a Javascript code, paste it into your website, and then you can watch real live graphics of traffic come to your website. Sounds pretty easy right? Why not try it?

I haven’t tested this approach on any sites. Intuitively I like how it integrates the call to action with the sales pitch in a single flow. What do you think?