Hate your bank? Use a credit union

Bankteller
Photo by Ronn Ashore

I spent several years suffering with grotty customer service at Citibank, and then I was hit by a check fraud that spiraled into a kafka-esque nightmare. A house-mate snuck into my room, stole a check, forged my signature (poorly) and then cashed it for $1000. Einstein that he was, he'd had to write his driver's license and social security number on the back, which showed up when I got the photocopy back. Not wanting to tip him off, me and the other housemates contacted the police, who were very helpful and interested. Now all we needed was the location where the check was cashed, which didn't show up on the statement.

After 3 months of both me and the police constantly calling and visiting Citibank, they refused to provide us with any details. I was constantly fobbed off with bogus excuses, since the case was allegedly in the hands of their fraud department who must live on an island somewhere in the south Atlantic with no means of communicating with the outside world, since I was never able to get a phone number or address to contact them. I finally received a refund after blowing my top at the local branch, and then promptly closed my account, threw the house-mate's possessions out on the front lawn and sent a copy of the forged check to his parents.

I was reminded of that when I saw this article on someone being hit with a $888,888.88 bank charge, with no explanation or help from the bank staff. It sounds like exactly the same sort of organizational failure that stymied my efforts to get help. From what I can see, the big banks have spent the last decade trying to build automated systems and procedures so they can get rid of expensive staff. That mostly works for routine operations, but as soon as something unusual happens you need somebody with judgement and authority to make decisions.

So what's the answer? I moved my account to a credit union eight years ago and I've been incredibly happy with them ever since:

– The customer service has been fantastic. They have trained, motivated bank staff able and willing to sort out problems for me, both in the branch and on the phone.

– I pay zero ATM fees, even when I'm traveling, since I can use any other credit union's machine for free.

– They don't gouge me with any other fees either. The big banks make nearly 40% of their revenue from 'non-interest income', and the bigger they are, the more they rely on them. Even worse, the 20% of households who pay the majority of overdraft fees (ie the poorest) pay 80% of those, averaging around $1300 each annually.

– I also get a warm glow inside because my deposits are funding straight-forward loans to local people and businesses, not financial speculation or empire building by bank CEOs. I'd rather be helping George Bailey than Gordon Gekko.

My personal account is with Keypoint Credit Union, and my business one with Lockheed, and they've both been stellar. If you're sold on the idea, there's almost certainly one that you can join, either because of where you live or the industry you work in. If you're current with a large bank, you won't regret switching.

Super-simple A/B testing in PHP

Alphabeta
Photo by Roadside Pictures

To really learn about what your users want you need to see how they respond to the different alternatives. Running A/B tests is a great way to do this, but even though the concept is simple, I always felt like it would require some complex coding and database setup to implement. I was wrong: inspired by Eric Ries's tips from a recent workshop I've been getting a lot of valuable feedback using just a 32-line PHP module and plain old logging to a file.

To use it yourself, all you need to do is think up a name for your test, and surround your alternatives with an if (should_ab('yourtestname', $userid)). That's it. I've deliberately made it so there's zero configuration, you can just pick an arbitrary test name, to encourage myself to test early and often. It's best if you have a proper user id to supply to the test function, but if you omit it, the client IP address will be used instead.

Now when your users load up a page they should see one version or another based on who they are, but how do you gather the information about which one worked? I'm logging all my user events to a file on the server using my custom_log() function, so whenever a user views a page I want to store what options they viewed it with. To do that, the only other function in the module returns an array containing what A/B choices were made for the current page. With that appending as a JSON string to each log entry, I can run analytics on the user's subsequent behavior, to tell which version of a front page led to the most conversions for example. The only tricky part of this approach is that you need to make sure you're logging the event at the end of the page, after all the choices have been made.

If you want to dive deeper, there's lots of strong frameworks out there for split-testing (I particularly like kissmetrics' approach), but even using something as brain-dead as my 32 line module will be a massive leap forward if you're a non-split-tester like I was.

[Update – Doh! I got the random generator wrong, it only returned true about 30% of the time using the md5 test. I've switched it over to crc32 below and in the file]

Download abtesting.php

<?php
// A module to let you do simple A/B split testing.
// By Pete Warden ( http://petewarden.typepad.com ) – freely reusable with no restrictions

// An array to keep track of the choices that have been made, so we can log them
$g_ab_choices = array();

function should_ab($testname, $userid=null) {
    // If no user identifier is supplied, fall back to the client IP address
    if (empty($userid))
        $userid = $_SERVER['REMOTE_ADDR'];
   
    global $g_ab_choices;
    if (isset($g_ab_choices[$testname]))
        return $g_ab_choices[$testname];
       
    $key = $testname.$userid;
    $keycrc = crc32($key);
   
    $result = (($keycrc&1)==1);
   
    $g_ab_choices[$testname] = $result;
   
    return $result;
}

function get_ab_choices()
{
    global $g_ab_choices;
    return $g_ab_choices;
}
?>

How to log to custom files from PHP

Logcabin
Photo by Old Shoe Woman

I needed a function in PHP that worked like error_log(), but appended to a set of custom files rather than to the standard error_log. I wanted to have an easier way to organize the different types of information, so that important messages weren't buried in an avalanche of less-crucial warnings, but this sort of thing is also great fodder for analytics if you write user events to their own file.

The result is custom_log(). It takes two arguments, a category name that determines which file to write to, and the message you want to log. The message gets written to that file, prefixed with the time and client IP. You can download the code as customlog.zip or it's included below:

<?php

// A module to write out events to a set of log files. Similar to error_log(),
// but with multiple output files.
//
// You'll need to set up a directory that the process running PHP (eg Apache) has
// permission to write to. You'll also need to keep an eye on the size of the log
// files, rotate out old ones once they get too large, etc.
//
// By Pete Warden ( http://petewarden.typepad.com ) – freely reusable with no restrictions

// Edit this to set it to the folder on your server where you want the logs to live
//define('CUSTOM_LOG_ROOT_DIRECTORY', '/private/var/log/apache2/'); // OS X default Apache log directory

define('CUSTOM_LOG_ROOT_DIRECTORY', '/var/log/httpd/'); // Red Hat Linux default Apache log directory

$g_custom_log_categories = array();
$g_custom_log_shutdown_registered = false;

// This function works like error_log(), but takes an extra category argument that
// determines which file the message is appended to.
function custom_log($category, $message)
{
    global $g_custom_log_categories;
   
    // If the file hasn't been opened for appending yet, create a new file handle
    if (!isset($g_custom_log_categories[$category]))
    {
        // Make sure there's no shenanigans with special characters like ../ that
        // could be abused to write outside of the specified directory
        $sanitizedcategory = preg_replace('/[^a-zA-Z0-9]/', '_', $category);
        $filename = CUSTOM_LOG_ROOT_DIRECTORY.$sanitizedcategory;
        $filehandle = fopen($filename, 'a');
        if (empty($filehandle))
        {
            error_log("Failed to open file '$filename' for appending");
            return;
        }

        // To close any open files once the script is done, and so ensure that
        // all the messages are written to disk, register a global shutdown
        // function that fclose()'s any open handles
        global $g_custom_log_shutdown_registered;
        if (!$g_custom_log_shutdown_registered)
        {
            register_shutdown_function('custom_log_on_shutdown');
            $g_custom_log_shutdown_registered = true;
        }
       
        // Urghh, this is required to prevent a spew of warnings when more recent
        // PHP versions are set to strict errors
        if (!ini_get('date.timezone'))
            date_default_timezone_set('UTC');
       
        $g_custom_log_categories[$category] = array('filehandle' => $filehandle);
    }

    // Create the full message and append it to the file
    $categoryinfo = $g_custom_log_categories[$category];   
    $filehandle = $categoryinfo['filehandle'];
   
    $timestring = date('D M j H:i:s Y');
    $ipaddress = $_SERVER['REMOTE_ADDR'];
    $fullmessage = "[$timestring] [$category] [client $ipaddress] $message\n";
   
    fwrite($filehandle, $fullmessage);
}

// A clean-up function called to make sure all open file handles are closed
function custom_log_on_shutdown()
{
    global $g_custom_log_categories;
    foreach ($g_custom_log_categories as $category => $categoryinfo)
        fclose($categoryinfo['filehandle']);
}

?>

Balsamiq: So simple, even a programmer can use it

Balsamiqshot

Mock me mercilessly, I deserve it, but I've really been struggling to prototype on paper before I code. Back at Apple there was always a white-board handy and a bunch of colleagues and customer-surrogates I had to collaborate with on any feature, so I did plenty of documentation before doing any serious engineering. As a lone founder, it's seriously tempting to think I have a good enough picture in my head to just go ahead and try it out.

Wrong, wrong, wrong! For one thing I end up involving users way too late in the process, since it takes a whole bunch of coding effort before I can show them something. Even ignoring that, I've never thought things through as completely as I think I have. Just a few minutes trying to sketch out the result I'm trying to achieve will always show me something I'd missed, and that's a lot cheaper than spending hours of programming to get to the same conclusion.

One of my mental blocks to prototyping is that I couldn't find a method I felt comfortable with. I'd tried the Pencil Sketch Firefox plugin, but it just didn't work the way I wanted. OmniGraffle is fantastic for creating beautiful diagrams, but it's painful to build something that looks like a UI sketch out of it's primitives. I've fallen back to using pen and paper, but it's really hard to alter and evolve hard copy, and you have to scan it in to share it remotely. Finally I tried out Balsamiq last week, and I'm in love.

I could rhapsodize about its ease of use, but the single best feature is that it looks like a sketch. This visual metaphor is really important, it clearly marks the results out as conceptual designs, not detailed blue-prints. This stops both other people and myself from focusing on nit-picking the look-and-feel, and forces a focus on the big questions about content and placement. I don't spend hours obsessing about aligning elements, because they naturally look a bit wonky, so I'm freed to think about what the overall content should be.

You can give it a try for yourself with the online version, and the full desktop product is $79, though I got it for $40 with a Techstars discount. If you're at all involved in product development, I think you'll end up buying it too.

Blogs I’m reading now

Booklist
Photo by MargoLove

Paul Jozefak just posted a list of the startup-related blogs he's reading, and that reminded me that I'd been intending to highlight some of my favorites too. I'm skipping the obvious ones (Brad, Fred, Eric Ries) to focus on lesser-known gems I'd love to see more widely read.

Bill Flagg

Bill's a Boulder entrepreneur with several great companies under his belt, but what really makes him stand out is that he's a boot-strapper. During TechStars he was a great counter-point to the focus on raising money, and he posts some awesome advice on building a company that actually generates cash. How about a billing department that encourages customers to mark down their invoices if they didn't feel like they got their money's worth? It's working for RegOnline.

Rick Segal

I love Rick's blog because of his willingness to risk offending people. I actually got fairly irate at a post he did last year, but I wouldn't have him any other way. What's even more interesting is that he's recently started on a journey from VC to startup founder, so there's been lots of great "Eat your own dogfood" posts, including a mea culpa on ever uttering the words 'lifestyle business' as a VC.

Highway 12 Ventures

Mark and George were very active in TechStars, but I never realized they blogged until Mark's stellar "Don't let the bastards grind you down". Since then I've been working through their archive, and they're chock full of other great posts, even tips from a hostage negotiator!

Jay Parkhill

Talking of negotiations, Jay's latest post on telling who wants to actually do a deal and who's just there to argue is a must-read. He's a lawyer specializing in startups, so there's loads of other great advice like how to cope with the loss of co-founders without sinking the business.

Accidental Haiku

Haikushot

I've always been fascinated by haiku, and the launch of Drunken Haiku by a good friend gave me a brain wave. There's a massive number of updates on Twitter, some of them must be unintentional haiku!

A couple of hours later, Accidental Haiku was born. It sits on Twitter looking for messages with the right syllable patterns. It's not always perfect at counting the sounds, and being Twitter there's lots of fluff, but if you watch it update I guarantee some gems.

It's all pulled together from open source components and you can download the modified phirehose code here. Now if I could just learn to write good haiku myself…

Haikushot2

Information wants to be free, even at WalMart

 Walmart
Photo by El Neato

I was reading The Wal-Mart Effect when I came across a passage that summed up exactly how I want to change the world. Sara Lee had a business relationship with Wal-Mart, and as one of the negotiators recalls:

Senior officials were always coming down there [to Bentonville] for meetings, and they always had their sheets of paper bent up so the Wal-Mart person couldn't see them. The idea was, why didn't we just put the sheets of paper on the table?

So they opened up traditionally closed information, and immediately discovered ways of saving money that benefited both companies. Wal-Mart had empty trucks returning from Florida that could transport Sara Lee's stock after it was shipped from South America. Underwear cartons were too large, Wal-Mart wasted time and money splitting them to send the contents to different stores, so Sara Lee shrank the carton size. As the book puts it, all of these efforts eliminated pure waste, the equivalent of turning off a light in an empty room.

I spent years in a corporate environment where I saw hundreds of opportunities to save money and make the world better for everyone, if only people would talk and share information. I was surprised to see I had that in common with Wal-Mart, but it makes sense given their fanatical approach to efficiency. If you're really trying to be productive, it just doesn't pay to be secretive.

Are there downsides to this? One of the biggest hurdles is trust. Knowledge is power, so you're handing over power to people who's interests may not align with yours. Wal-Mart is the 800lb gorilla with a history of using its market power ruthlessly, and one of the strengths of the book is its detail on the negative side of their dominance. I'd argue that this trust argument is usually a cop-out, hiding worries about turf and control. In most cases it's clear that it's not in the other party's best interest to screw you over, and if it is, why are you dealing with them at all? The worst cases I saw were between departments within the same company, often we shared more information with competitors than the guys down the hall.

Once you're in a business relationship, there's a lot to be gained by putting all the sheets of paper on the table.

A lovely little online icon editor

Iconfushot

My design skills are non-existent, but I often need functional little buttons or badges. Using Photoshop for that sort of thing is like taking a sledgehammer to a nut, so I was extremely happy when I found iconfu.

It appears to be pure Javascript, which is impressive just as a technical feat, but it's also an extremely usable and surprisingly full-featured tool for building tiny icons. It's got undo, nicely anti-aliased primitives and some handy filters. Even better, it's completely free for up to 16×16 images. It's no Photoshop so don't expect to see layers or freehand, but that's part of what I love about it. It takes me back to the paint programs I'd use in the late 80's, and the hours I spent clicking individual pixels to create a massive 320×240 demo background.

The only drawback is that Internet Explorer is not supported, but if doing any web design work I'm sure you'll have a better an alternative browser installed anyway.

Get visual bug reports with SnapABug

Ladybug

Photo by Hamed Saber

One of the most frustrating parts of trying to fix a customer's problem is trying to understand what on earth the problem is. I've spent enormous amounts of time bouncing emails back and forth, or talking on the phone, just to get enough information to start debugging. I've long been a fan of tools like CrossLoop that let you share screens with a remote user, but I'm really excited to see what my fellow Techstars alumni Timzon have come up with.

SnapABug is a small widget you can include in any web page, and it gives users a button they can press to take a screenshot and email it off to your support team along with some notes. Dead simple but incredibly useful! Jerome, Jerome and Tony have done an awesome job of identifying a great market for their technology, I can definitely see this appearing on a lot of sites and becoming a valuable product.

A coming privacy freakout?

People don’t know how much information about them is freely available on the internet. I was reminded of that by this thread on the WebFinger list about a prototype YQL implementation that lets you look up information about any Yahoo user from their email address. I’ll quote Kaliya:

I went and tried the page out to see what it exposed about me.

Both for my “public” use around the web a lot yahoo handle and another one
that I have explicitly kept my “real name” not attached to in any public
forums.

My name listed in both accounts was Kaliya however when you expose people’s
“profile names” in web finger you might be exposing information people don’t
think is public on the web.  Needless to say I went in and immediately
changed my profile name in my more private account.

I just shared this with guy friend who has several yahoo accounts – one of
them for dating.  I said do you have your “regular name” listed in the
“profile name” – he thought he might. It sort of made him cringe that this
was now exposed.

I think you might have a real uproar from users by exposing their profile
names publicly on the web without letting them know you are doing this. It
would be good to send people a note asking telling them this information
will be exposed to ANYONE WHO ASKS before you make it available via
webfinger.

I was thinking about the difference between twitter and almost everyone
else.  Twitter starts at Radically Open and explicitly so – so as a user I
know what bargain I am striking in using the tool.

Everyone else is trying to go from “closed” as the default and move towards
more open and pulling users along is a challenge – it is changing the rules
of the space and it needs to be well thought out or it will back fire badly.

The response from the developers has been ‘Silly user with your expectations of privacy! Didn’t you know there’s been a Yahoo profile page with that information up for years?’ That’s my instinct too, there’s so many wonderful new services we can build with more open profile information, and we’ll never get anything done if we spend all our time sitting around worrying about potential problems.

From talking to people outside the bubble though, I do wonder if there will be trouble ahead. They don’t know that Facebook puts up a public profile for them by default, with pictures, your location and some of your friends all open to the world. Services like Flickr, Amazon, Google, AIM, Vimeo all provide APIs to look up information about someone based on their email address. Rapleaf claims to have social network infomation on 375 million people. If you’re interested in the information that’s available on you, try this example:
http://web.mailana.com/labs/findbyemail/

The worst case is that we plow ahead with what’s technologically possible, trigger a moral panic and we end up with restrictive legislation, but even a mild backlash would cause providers to neuter their APIs and remove access to all that lovely data. So what’s the answer? I’d love to see something like the apparently defunct attentiontrust.org pledge to help us self-police our use of the data, before someone else comes in to police us!