Building Switchman

How I solved a testing problem by building my first real Rails app.


I was about to run some tree tests on OptimalWorkshop to evaluate a few navigation concepts when I ran into a problem.

We were recruiting through email and social channels, so we needed a single URL to send out. But because I had three versions of the test, I had three different URLs.

I needed a way to send out one link that would redirect participants to one of the three tests.

Extended Googling turned up nothing useful. My coworker, Jackson, had run into the same problem before and had solved it using Google Content Experiments. Ingeniously, he created an A|B test that sent users to one of many versions of a web page, which then forwarded them to the destination using Javascript.

Users didn’t see any of this complexity. They simply visited a link, saw a brief blip of content, then were sent to the final destination. A little clunky perhaps, but still pretty neat.

How the Google Content Experiments version worked conceptually. Randomized assignment was the key problem.

But this approach had flaws.

First, it assigned users to variations randomly. With small numbers of participants, the algorithm would often send too many people to one test and not enough to the others.

Second, it was hard to confirm that it was working properly. Google assigns users a cookie in order to show them the same test on subsequent visits. This behavior is useful for A|B tests, but wasn’t necessary for my situation. Even when checking the URL in incognito mode and in multiple browsers, it was often unclear if things were running properly. Scary.

Rolling my own solution

I needed much more control and assurance over how participants were assigned to tests than Google Content Experiments would allow. Switchman is my answer to that.

At its core, Switchman is a URL redirector. As an administrator, you create a custom URL and give it one or many destination URLs. When the first user hits the URL, it sends them to the first destination and updates an index. When the second user hits the URL, it sends them to the second destination. And so on, following a round-robin format.

Switchman relies on round-robin assignment to ensure even distribution among the destinations.
The main editing screen. Users can customize the URL that’s shared with participants. An arbitrary number of destinations can be added.

At any point, destinations can be turned on or off temporarily by toggling the “Active” checkbox. This is helpful in those cases when you want to send more traffic to certain tests to correct for abandonments.

What I learned

The best part about this project wasn’t the functionality, but the experience building an app from scratch, solo.

I’m not a developer. At all. But I have massive amounts of respect for developers and feel it’s my duty as a designer — and as a technical professional—to develop literacy and empathy.

I gained a great deal of technical knowledge through this exercise, but the biggest takeaways were more high-level. Here are four points that stand out.

Test driven development is requisite to iterating.

Before, I blindly assumed writing tests was a Good Thing but I didn’t really get why they mattered. It crystallized for me when I started to add and refactor functionality. Being able to run a test suite and know I didn’t break anything — as opposed to clicking through the site like a savage — was hugely liberating.

Plus, the boost I got from making a big change and seeing the tests run successfully was a huge motivator.

TDD matters to UX folks because if your team is not in this habit, your ability to improve the experience will be diminished.

Take the easiest path first, and improve where the experience sucks the most.

The first iteration of this app was hard-coded in Sinatra. This lightweight framework proved to me that round-robin assignment would be valuable.

From there, I chose Rails because it gave me so much for free — particularly database integration. It’s not as contemporary as some other frameworks, but it was perfect for this case.

All authentication is done through HTTP Auth, not formal user accounts. That’s fine for me since it solved the security problem in about five minutes, including time spent googling “add HTTP auth to Heroku”. I’m ok sharing my password with other team members if they want to use the app.

I started to build the UI in ActiveAdmin, but quickly found that customizing the UI to fit my needs was complicated. Therefore, I chose to build a custom UI using Rails views and this took a lot more time but gave me something closer to my ideal. But here as well I took the path of least resistance, using Zurb Foundation for the UI. It’s not bespoke and front-end developers might criticize that decision, but it looks and works good enough for me.

Complexity increases geometrically.

Off-the-cuff features like “verify whether a URL has a valid format” become unexpectedly complicated, especially when you consider the need to write tests and explore all edge cases. Quickly I found that approaches on StackOverflow and in some older Ruby Gems weren’t usable since they didn’t account for newer top-level domains. Building the right functionality would mean needing to do much more research and test many more situations. So I shelved the feature.

Designers should develop, and vice versa.

Occasionally, the question comes up, “Should designers code?” to which I reply, “Yes. And developers should design.”

I don’t believe everyone should become a generalist or be able to pinch-hit for anyone else. The amount of knowledge needed to become expert in one discipline is staggering, much less a few.

But by practicing each other crafts, we’re afforded deep insight into the challenges and motivations of our peers. This helps develop empathy, which is critical to collaboration and negotiation. We’re also able expand our vocabulary outside of our domain, which lets us to communicate precisely and with less chance of misinterpretation.


So I put it this challenge to everyone: spend time doing your teammate’s jobs so that you can do your’s better.