Peter Nixey

I'm Peter, a Rails developer and entrepreneur. I'm an ex-computer vision researcher, the former CEO of Clickpass and a YC alum. I now work with an awesome team building Copyin - Email Knowledge Capture

The shower problem

The team and I are out in San Francisco warming up our landing before moving the company here in January. We’re staying in a nice little AirBnB in Northbeach and have plenty of space but all share the same bathroom.

One of my little luxuries in life is nice shower gel and I brought a bottle of Lime Source out with me. It’s not particularly expensive but it’s awesome. It smells so good you want to lick yourself after using it. If you washed your hands with it you could make a Gin and Tonic taste better just for stirring it with your finger. 

The problem is that it smells so good that two people will cut a bottle down a fortnight. The three of our team would easily hammer it in a week. So when we arrived at the house I wanted it within reach but not so obvious that it ended up gone. 

I was rather pleased to discover then that at the far end of the bathtub was a discrete shelf.

The shelf is open and visible to anyone in the bathroom but occluded from someone in the shower. The perfect place to store some tasty shower gel.  

Not only that but our landlord provided three standard-issue dispensers with shower gel, shampoo and conditioner. Even if a showerer were to notice the luxuriant gel on the way into the shower, their urge for shower gel would likely be sated by the convenient dispensers in front of them. 

It was only on the second day of showering and revelling in my (somewhat mean) smugness that I realised that the same thing that was protecting my shower gel was also choking the green shoots of our software. 

Over the past two months we’ve built some pretty cool stuff. I’ve used a lot of software and built a fair chunk so I’m jaded enough to be cynical but this is good. It’s eight weeks old and we’ve been using it constantly for the past six. It’s totally integrated with email and completely natural to use. 

Except that you have to remember to use it. Like the Lime Source it kicks the pants of the alternative. Like the Lime Source though you don’t have a taste for it until you have actually tasted it. We’re only two weeks into customer development but it’s clear that while people love the idea of it, they completely forget to use it.

We needed to solve the shower problem. We’d packed 40 limes worth of software into one bottle that makes you want to lick yourself after using it. The problem is that when they you reach for an email address, the one that stares back at you is not ours. 

So with that in mind we’re building a simple Chrome extension that modifies the send button on GMail to include the our email adresses. We are going to get up and in our users’ faces (as they don’t say where I come from).

If I put the shower gel out right beside the other dispensers it’ll get hit. So too the email address.

We’re looking forward to seeing how this goes. I’m bullish about our engagement but, post-publication, bearish about my shower gel. 

You can follow my posts on Twitter

Using Struct and Serialize to get flexibility in ActiveRecord

I can’t claim any credit for this piece of lovely insight, it all belongs to JAKUB GŁUSZECKI who’s basically written exactly what I’m about to replicate here. However it’s a sweet solution and I wanted to share it. 

The problem

You’ve got a bunch of model attributes that you need to store in the database but don’t really deserve their own column. For instance, there are a number of client-specific strings associated with the Q&A panels on Pingpanel. At the time of writing you can see these at diy-advice.ratedpeople.com.

The descriptions of what the panel is about, the types of questions you can ask there etc. all belong in the database but don’t really merit messing up the schema by occupying a complete column.

What I want to do is to store all of these model attributes (which will never need searching or indexing) in lump which I can pull or update when I need to.

The solution part 1: Serialize

Rails offers a nice serialize method which will roll up a structured object (e.g. a hash), put it into a database column and then unroll it back into the original object when you need it. 

class Org
    serialize :descriptions
end

This now allows me to dump an arbitrary array of attributes into descriptions which can be added to or altered at future dates.

Solution part 2: OpenStruct

That’s all well and good but I’d prefer to use object notation for accessing the attributes so instead of it being:

@org.descriptions[‘strapline’]

I would prefer:

@org.descriptions.strapline

Happily, serialize allows us to enforce that only a particular class can be passed and OpenStruct is a class that basically does exactly what I need. It wraps a hash up into object notation: 

class Org
    …
    serialize :descriptions, OpenStruct
end

which lets us do

@org.descriptions.strapline

Solution part 3: Struct

Now although I don’t want to mess the database up with arbitrary columns I still want some accountability. I’m going to have a problematic time debugging if I can read and write whatever I chose.

Let’s say I pump

@org.descriptions.strapline

into the view but save

@org.descriptions.tagline

back into the database. I’ve got a setup which looks sensible in both places but is evidently going to lead to problems very quickly. OpenStruct will do this without blinking which is a little dangerous.

The solution is Struct which is the same thing as OpenStruct but with a limited set of defined attributes. 

We can create a new class derived from Struct with the attributes we want and then pass it to serialize as the enforced object:

class Org
    …
    class Descriptions < Struct.new(:strapline, :panel_intro) 
    end
    serialize :descriptions, Descriptions
end

The new Descriptions object will allow @descriptions.strapline to be set and read but will throw an error if you try to write @descriptions.tagline.

Edit: Migrations. Beware.

On further thinking, while this approach has its strengths, it also has one serious weakness which is migrations and specifically what happens if you change the name of the attributes on the Struct. 

The struct is stored as a string in the database:

”#<struct Org::Guidance strapline=nil, panel_intro=nil>”

When you change the name of ‘strapline’ to ‘tagline’ none of the existing, serialized strings in the database get changed (i.e. the data’s still there) but we’ll find that when we load our object the new @org.strapline attribute is now set to nil.

As soon as we save @org the previous string will be overwritten and our old data is lost. 

What to do about this? TBH I don’t know. You could always write some sort of migration script but with that decoupled from the migration itself (i.e. just changing the model) we’re in dangerous territory. Perhaps it’s just best to stick with to good tools ActiveRecord has given us. Thoughts appreciated.

You can follow my posts on Twitter

The multiplicative slowdown effect of testing

I recently read an article by Tom Blomfield which touched on something I’ve felt for a while. That is that tests can slow you down. Badly.

It took me about eight months to write the first version of Pingpanel, which was not a disastrously long dev time but still far too slow.

Part of what slowed it down was testing. Everything was tested. And I mean Everything. I had unit tests, integration tests and deployment tests and I spoke to anyone and everyone who would listen about how great they were and how solid my code was.

It was solid: rock solid. If something went wrong I knew about it. But like the Segway it was rock solidly the wrong product. I was running more tests than there were user interactions on the site. Not more test-runs; more tests. I had about 500 tests and and the site had about 15 questions on it. Bad ratio!

The multiplicative slow-down of test writing

  1. You have to write tests (maybe 30-50% of dev time)
  2. You have to wait for the tests to run (a chunk of time)
  3. You attempt to get things like Spork to speed your tests up (0.3 x a chunk of time)
  4. You have to finish reading all the tabs you opened from Hacker News while your tests were running (many chunks of time)
  5. You start feeling subconsciously disheartened because your velocity has dropped and you know you’re spending too much time reading articles about suspiciously alpha founders
  6. You hear yourself saying things like “probably best to delay Facebook integration, I’ve no idea how we’ll test it”
  7. Your so bored with your dev cycle you goto (3).
  8. You fear writing new code because of the tests it’ll break and subconsciously switch to refactoring instead
  9. Green dots mean more to you than user interactions
  10. <shame>You realise you’re developing features slower than a big company. </shame>

Even with all of this overhead I still surged on like a skinny white Jonah Lomu.

What brought me to my knees was the realisation that Pingpanel was not a destination site but a white-label service. Even then it was only my futile attempts to test emails coming anywhere other than example.com that finally put me on the ground.

What was the effect of dropping testing?

It sped up my development and it didn’t have much effect on the reliability of the site. Sounds trite but it was true. Occasionally things broke but never badly and not in a way that couldn’t be quickly fixed.

The client site doesn’t have a vast amount of traffic but it certainly gets enough to flush any issues. There are about 500 visitors and about 50-100 questions and answers each day.

The main effect of dropping the tests is that the site is really good. Little things like adding auto-login from emails, which massively increased question-answering rate, were knocked out in a few days rather than the weeks they’d have taken before.

The site is much, much better today than it would have been had I continued testing. Not only that but I’m several times more enthused about it (a fact not lost on investors or clients).

Why was dropping tests the right thing to do?

TDD/BDD implicitly assumes that the cost of code breakage is higher than the cost of missing or incorrect code. This is not true for most consumer startups where the major risk is building the wrong thing or the right thing in a less-than-usable fashion. If it breaks then in many cases you can just send your users an email or phone them up and say sorry.

Bear in mind that I’m creating social software, not Stripe. If I was doing payments or control code for nuclear power stations that cost ratio would be completely different. The point is that for me, while losing a database would be bad, faulty functionality is no biggie. An unusable site though is a complete killer.

Will I carry on without testing?

No. There are some things that are calling out for tests and I’m just about to bring new team members on board which will invariably amplify demand.

However, in order qualify, any potential test will have to pass one or more of the following finger-in-the-air checks:

  1. The consequence of the broken test should be bad enough that I’d get up in the middle of the night to fix it
  2. The test (including its maintenance) promises to speed up future releases. There are a few places where I’m now wasting unnecessary time doing manual integration testing which could be easily automated
  3. Unit tests should be restricted to code that actually does complex stuff that could easily be broken during refactoring (e.g. making sure that authorisation rules are never accidentally ignored). I won’t be unit testing 4-line controller actions.

I’m also going to restrict tests to high-cost, high-probability interactions e.g. If I’m testing a signup flow I’ll test that you can signup, not what happens when you submit an invalid email. I’m interested in verifying that the motorway is open, not the hard shoulder.

Should you write tests?

Only you can answer that. For what it’s worth here is my advice:

1. Don’t write things for which the cost of failure is lower than the cost of writing and maintaining the test. I had tests to make sure that nav elements were highlighted which was just daft. Don’t underestimate the cost of maintaining and running tests either, even if it’s quick to write, running and maintaining it will take a lot of cumulative time.

2. Try not to write tests for imaginary stuff: the dumb future-developer who accidentally future-deletes the line of code you just wrote or the low-cost edge case user-screwup. Both these things will lead you down the rabbit hole. Keep it to stuff you actually care about and assume you won’t hire dummies.

3. Complement your tests with monitoring. It’s not immediate but each day I get a Mixpanel email containing all the critical metrics from the previous day. If there aren’t any questions asked on the site, any answers given or any thanks offered it’s probably worth me double checking what’s going on. Google Analytics alerts can give you even earlier warnings than this. Also you could try giving users your phone number and let them ring you directly. You’ll soon find out if and when you mess up.

I don’t know what the right balance is but what’s reassuring is that no other developers seem to either. The answer is undoubtedly that it’s whatever works for you. Bear in mind though that, like funding, too much testing can kill you just as surely as too little.

You can follow my posts on Twitter

Viewing stats from just today, yesterday or last week in Google Analytics

I’m a big fan of Google analytics but it’s a source of regular frustration that it defaults to showing the last month of data. Traffic spikes for earlier in the month swamp my reports and make the nuances of the last few days hard to discern. 

I finally decided to write a bookmarklet that lets you go directly to whichever window you want to see. Want to see just today, just yesterday, the last week or the last two weeks? No problem just create a new bookmarklet.

Instructions and code on GitHub and below:

You can follow my posts on Twitter

Write the story you want to tell

Every time I pitched my last company, Clickpass, I ached to be telling a story I hadn’t written. I desperately wanted to say how “we did this and learned that so we did the other”, the problem was, we hadn’t. We spent a long time building something that we didn’t expose quickly enough to the public and weren’t fast enough to change once we did. 

One day, in the hope it would make our investment story a little more interesting, Mike Maples sent me and Immad to the IMVU offices where we listing avidly to the (not yet famous) Eric Ries as he told his now fabled account of their beginnings.

Unlike most startups from whom you hear little except funding and exit, the IMVU story was written in its middle. Authors worry a lot about the last paragraph and as entrepreneurs we worry a lot about the final exit. You live a story in the two thousand paragraphs of the middle, not the last one and you live a company in its building, not its exit. 

IMVU was fascinating because it was a shaky start, a great middle and I don’t even know what the ending was but I sure as hell remember the story. If there was success to be had in the market, their strategy made that success almost unavoidable and exit a detail rather than a destination.

IMVU made me want to take control of our narrative. I yearned to show how we too were making success inevitable. Unfortunately, the story we’d written was dull and our success was anything but inevitable.

And when I say “we’d written”, I mean “I’d written”. My team was good. Extraordinarily good. So good I groan at not having had the experience to realise as much at the time. Immad was the best developer I’ve ever worked with and David was a simply incredible designer.

I was however not the best CEO. Not the worst but not the best. I was very inexperienced and, like many CEOs, very, very frightened. I’d forgotten just how consistently frightened until meeting an old friend with whom I’d hung out in our YC summer of 2007. She laughed when I made some reference to feeling more relaxed this time round and reminded me how I’d once mentioned waking up every single day that summer feeling utterly terrified.

She was right. I was scared. Very scared. I was scared for a lot of reasons but the main one was that I didn’t know where we were going. I didn’t know where to lead us and so I couldn’t. I didn’t know what story I was writing.

So in building my new company, Pingpanel, I’ve taken to writing the story of the company as it grows. Every time something interesting happens, a big release, new customer, a potential new hire, fundraising etc., I write it down and on the first of every month I tell the story via email to my angel investors.

The interesting effect of telling the story is that it forces you to write it and not just write it but write it well. Everyone wants to tell a gangbuster of a story and knowing you have to tell one creates a back-pressure that forces you to write one. Too often we thread our narrative retrospectively, an apologetic answer to a forlorn pitch deck. 

By building the pitch deck live I build the deck, and the company I want to present. What have I done this month that’s worth a bullet, worth a slide? Would I really want to explain how those four weeks disappeared without even a footnote to show for them? Not that I’m focussed on investment, far from it but there’s nothing like asking someone to part with their cash to clarify the reasons why they should.

When in doubt as to what I should prioritise, I now ask myself what will make the most compelling retelling. Is the audience really baying for a montage of coding or is it clear to all that I’m just avoiding cold-calling? Is the order-book overflowing and should I really keep selling or would the rational listener not just ask me why I didn’t get out and recruit? 

I can always rationalise the work I’d like to be doing but the pride or guilt that accompanies an imagined retelling is a great indicator of the work I should be doing.

It was therefore with a smile that I read Pixar story-boarder, Emma Coat’s 22 Rules of Storytelling. If you haven’t read them, do so: they’re great. They’re also incredibly applicable to a startup. Or to life. If only to avoid Ben Mezrich adding his own dramatic falsifications, I recommend becoming the author of your own narrative.

If you liked this you might also enjoy: The 22 rules of Startup Storytelling

You can follow my posts on Twitter

The 22 rules of Startup storytelling

I just finished reading the excellent 22 rules of storytelling as described by Pixar storyboard artist, Emma Coats. They’re brilliant and give a glimpse of what feeds the magic of Pixar.

image

I’ve occasionally ruminated that just as persuading folks to join or invest in a startup requires storytelling, so the corollary is that startup-building means story-writing. Thinking about writing a good story is a surprisingly helpful tool to ensure you tell one.

A good startup should therefore be a good story. It made me laugh to see that the converse may also be true - a good story makes a good startup. With the exception of the first one, Emma’s points were remarkably salient.

Emmas guide to storytelling and its startup-building corollaries:

1. You admire a character for trying more than for their successes.

Unfortunately this might be the one point that doesn’t ring true. Buzz will always attract more press and capital than Woody. Woody will probably ultimately make more money (and lose less of other people’s) but Buzz got his name for a reason. The point to (maybe) take from this is that you’ll get more press from success but more success from trying.

2. You gotta keep in mind what’s interesting to you as an audience, not what’s fun to do as a writer. They can be v. different.

G+

2. Trying for theme is important, but you won’t see what the story is actually about til you’re at the end of it. Now rewrite.

You’ll only really discover what your product is after you release it.

4. Once upon a time there was ___. Every day, ___. One day ___. Because of that, ___. Because of that, ___. Until finally ___.

Once upon a time there were 100,000 potential customers. Every day they used to do X. One day 1,000 of them clicked through to us from a link at Y. Because of Z, 100 of them signed up. Because we’re wonderful they were able to do X better/quicker/cheaper/more pleasurably. Until finally 3 paid us.

5: Simplify. Focus. Combine characters. Hop over detours. You’ll feel like you’re losing valuable stuff but it sets you free.

You already know what this means

6: What is your character good at, comfortable with? Throw the polar opposite at them. Challenge them. How do they deal?

Do something you love and that fits you. But don’t put off the stuff you don’t like but which has to be done. Don’t just code or design, get out, cold-sell and obsessively talk to customers and users. If you only do the stuff you like you’ll die.

7. Come up with your ending before you figure out your middle. Seriously. Endings are hard, get yours working up front.

Vision. Real, tangible vision. No “we’re going to own X-market ” fluff, that’s easy and meaningless. Something people can get behind.

8. Finish your story, let go even if it’s not perfect. In an ideal world you have both, but move on. Do better next time.

Release yo.

9. When you’re stuck, make a list of what WOULDN’T happen next. Lots of times the material to get you unstuck will show up.

What would a large company do?

10. Pull apart the stories you like. What you like in them is a part of you; you’ve got to recognize it before you can use it.

Figure out companies and leaders you admire and identify with (not Steve). When you get stuck think “What would Larry/Drew/Mark do”?

11. Putting it on paper lets you start fixing it. If it stays in your head, a perfect idea, you’ll never share it with anyone.

Talk to people incessantly and try to prove yourself wrong. Come back and write code after you’ve worked and reworked your ideas so much it appears the new ones may actually be right. Talk to customers, peers, strangers, competitors. Not just your girlfriend.

12: Discount the 1st thing that comes to mind. And the 2nd, 3rd, 4th, 5th – get the obvious out of the way. Surprise yourself.

Do something different but delightful. It’s hard to inspire people with an also-ran.

13. Give your characters opinions. Passive/malleable might seem likeable to you as you write, but it’s poison to the audience.

Make your brand and your company stand for something. Be Louise Thornton to your Matt Santos. Smart and cute is better than dumb and fat but not as good as Hope.

14. Why must you tell THIS story? What’s the belief burning within you that your story feeds off of? That’s the heart of it.

What she said.

15. If you were your character, in this situation, how would you feel? Honesty lends credibility to unbelievable situations.

Tell the truth and ideally the whole truth to customers, employees and investors. They will respect you more for it.

16. What are the stakes? Give us reason to root for the character. What happens if they don’t succeed? Stack the odds against.

Do something Big, Hairy and Audacious but believable. Also, someone’s going to want to see that your money and career are on the line before they stake theirs. 

17. No work is ever wasted. If it’s not working, let go and move on - it’ll come back around to be useful later.

Never stop moving. Always better to be doing something, discovering something, talking to people. Always build value but don’t chase diminishing returns..

18. You have to know yourself: the difference between doing your best & fussing. Story is testing, not refining.

You’re still not Steve. Release. See what people like. Cut the rest, expand the best (see also Jim Collins)

19. Coincidences to get characters into trouble are great; coincidences to get them out of it are cheating.

The world will expect you to have a Pez-dispenser story explaining why you started your company. Pez dispensers won’t make you money though. For that you’ll need power sellers. Who are your power sellers?

20. Exercise: take the building blocks of a movie you dislike. How d’you rearrange them into what you DO like?

Take a product/service people already use and pay for and make it better (also try to always map  your service into an existing budget category. It’s far easier to get people to re-allocate an existing budget than to have them pay for something new)

21. You gotta identify with your situation/characters, can’t just write ‘cool’. What would make YOU act that way?

Color

22. What’s the essence of your story? Most economical telling of it? If you know that, you can build out from there.

Larry! Fancy meeting you over this brief and confined journey….

You can follow my posts on Twitter

My parents - the nun and the monk

Very proud. A wonderful story, beautifully told by my sister, Catherine. 

Unfortunately I can’t repost either the audio or the article here but it is in the Times today. if you have a subscription, you can find the article here.

You can follow my posts on Twitter

Overspeccing may be strangling your project

A little while back I was project-managing a team of seven developers building some new social software. As the team’s product manager there was always pressure on me to make sure that “engineering was kept busy”. “Make sure you’ve got enough stuff in the backlog for them, it doesn’t look good if the engineers aren’t coding”. 

“Keeping engineering busy” is, for many reasons, a terrifically dangerous business, however even that aside there was something else about this that bothered me. 

Each new story added to the backlog caused the entire team to die a little. I could see it, everyone else could see it but I didn’t have any logic substantial enough to halt the trucking and dumping. And engineering needed to be kept busy. 

Months later, having left, I realised the problem was the implicit assumption that specs are inert and can be accumulated like like gold or LinkedIn Recommendations. The reality is different. Specs are alive and like all-male safari parks, you shouldn’t cultivate them casually.

The job of the Product Team is to nurture ideas from seed to sapling. We cultivate rows of beautiful greenery, swaying gently in in the nursery. Vital and fresh, full of potential and promise. Once a fortnight the dev team wanders through, grabs an armful of specs and heads out to the fields to farm new features for ravenous users to devour and drop back out onto Twitter.

I prefer to think of specs less as baby flowers and more as adolescent Triffids. Farm them carefully, keep your wits about you and you’ll get a nice ongoing supply of oil-cake to keep your project fed. Lose attention even for a minute and the fuckers will set off a blinding firework display of discussion while they eat you alive at the whiteboard.

Designs and stories are alive. They set down roots and grow. They soak up discussion time in meetings and they seduce and manipulate team members to love and protect them. Try and get rid of a fully specced piece of software that’s been sitting in the backlog for six weeks and you’ll find yourself pulling up roots that run down through your design and UX team and finish up gut-deep in the CEO or worse, the board.

Even if you can control the numbers, you’ll need more bonsai artists than Kyoto to deal with volume. What started out as a seed is now a yearling with the entire biz-dev team picnicking underneath. How the hell did that happen? Who knows but you’re sure as hell not building that API anytime soon.

Nurturing ideas isn’t bad in itself. The problem is the logic behind which ones get nurtured. The ideas that matter are the ones your users want. The ones that get picked are the ones that look pretty, “this one’s wonderful - we shall care for and encourage her and we shall call her Medusa”. 

Treat your specs like fresh, possibly sapient, vegetables. Cook them fresh for tasty software or chuck ‘em out before they infect the entire project.

« Previous post Cook something or get out of the kitchen

You can follow my posts on Twitter

Cook something or get out of the kitchen

I seem to have a lot of conversations recently with people who find themselves in the kitchen but without the means to cook anything. 

As a cook myself they often ask me how to go about finding themselves a chef who can cook something for them. I ask them why they want to do that and they tell me they’ve got a great idea for a cuisine only they don’t usually have a recipe and, as mentioned, they never have a chef. 

This is all happening more frequently since Google built a beautiful new kitchen in East London and it’s driving me a little nuts. 

Cook something, learn how to cook something or get out of the kitchen. Standing around for six months trying to recruit a chef to cook a meal you don’t have a recipe for is barmy. Hoping that you’re going to outsell Jamie Oliver on the basis of your recipe-in-a-head is crazier still. 

That doesn’t mean you can’t do something else - front of house, marketing, renting restaurants, anything except the job you’re not qualified to do which is to cook. I appreciate that you want to be a wealthy, celebrity chef but you know what the celebrity chefs all have in common? They know how to cook!

You may also be wondering whether you can convince a chef to bring his own ingredients and pans, cook the food and serve it all up on the basis that it’s going to be so brilliant he can take his pay once the customers have paid double the going rate for your nouveau cuisine. Ideally he’d even do it out of his own kitchen, that way you could keep the overheads down and then convince someone to lend you a restaurant once the food’s cooked. 

Kind of makes you wonder why he wouldn’t do that himself though doesn’t it? Perhaps it’s that recipe in your head that you’ve not written down or trialled with anyone yet? Must be pretty tasty. 

Trial your crazy recipe; throw it together as best you can and show that all-dough pizzas are the new black and you’ve got a different story. Use Twitter to line a queue of customers up outside that beat-up old caravan you borrowed to hack the meal together in and you might find someone ready to cook for you. Hell they’ll probably ask if they can do it for a cut of ownership.

Otherwise, get a job. You numpty.

« Previous post: A simple way to use Mixpanel with Rails

You can follow my posts on Twitter

Using Mixpanel (or GA events) with Rails

It’s been too long coming but I’ve finally had an excuse to start using Mixpanel. It’s excellent. Really sweet and their event streams are *exactly* what you need in the early stages of a product. 

Avoiding the normal integration - javascript listeners and callbacks

Most people probably do mixpanel their event logging (Mixpanel, GA, Kissmetrics) in the view layer and add callbacks to their forms etc. to fire a “signup” event or such. It’s a Javascript API so why not do it all in JS right?

Well maybe but I’ve seen some people have problems with that approach and waste lots of time fiddling around to ensure that it played well with a Javascript-submitted from and didn’t block anything. 

I also felt that it didn’t quite feel right to have the “signup” event fire on form submission since the submission of the form is no guarantee that it validated or that the user completed the signup process.

My preferred approach - server-triggered, client-logged

The logic for whether the signup event happened really exists in the controller (possibly even in the model but that proved to be too much hassle). I therefore wanted to fire my Mixpanel event after the controller signed someone up i.e.

class UsersController < ApplicationController

  …

  def create

    @user = User.new(params[:user])

    if @user.save

      flash[:notice] = ‘User was successfully created.’

      mixpanel_track( ‘Signup’, {mp_note: ‘signed up’} )

    end

    respond_with @user

  end

end

The beauty of this approach is that regardless of how you implement your forms, you know (as you’ll see in a minute) that the event is going to be tracked. You can also track it whether you’re responding_with JSON or HTML.

However, although I wanted to trigger events serverside I didn’t want it to be fired serverside. Serverside calls would have involved setting up messaging queues and a load of unnecessary server-load. What I wanted to do was stage the event logging on the server but then let the client deal with firing it off to Mixpanel. 

Log the event on the server but then write it back into the page

Summary:

  1. Call a wrapper method from the controller and pass the Mixpanel event properties
  2. Use the wrapper method to translate the arguments into a Javascript method string
  3. Concatenate all such event strings and store them ready to be plucked off by the view
  4. Write the concatenation of all those strings back into the document head when it’s sent down the wire
  5. (Remember that some events involve redirects) Since the most interesting events (:create, :destroy, :update) usually involve a redirect I don’t store the events in an instance variable (@mixpanel_events) but instead store them in a session variable (session[:mixpanel_events]). That way they can be pulled off the session by the next view load and won’t get wiped out by a redirect.

Code

In order to do this I created a few methods in my application controller that mirrored the mixpanel javascript methods. These methods take the event, translate it into javascript and then queue it to be written back into the page:

class ApplicationController < ActionController::Base

  …

  private

    def mixpanel_track(*args)

      json_array = args.to_json.strip

      json_args = json_array.slice(1, json_array.length-2)

      (session[:mixpanel_events] ||= “”)  « “mixpanel.track( #{json_args} );”

    end

end

I can call this method using regular ruby arguments:

 mixpanel_track( ‘Signup’, {mp_note: ‘signed up’} )

The method then just splats the arguments and  translate them to a json array which looks something like this:

”["Signup",{"mp_note":"signed up"}]” 

It strips the array braces off either end (the slice line) and sticks the arguments into the appropriate mixpanel event:

“mixpanel.track( #{json_args} );”

(which expanded looks like:)

“mixpanel.track( "Signup",{"mp_note":"signed up"} );” 

This whole string is then stored in the session ready for the view to pull it out.

Application.html.erb

All the application view then has to do is pull the events into the next page load and clear the session variable:

<html>

  <head>

    …

    <script>

      <%= session.delete :mixpanel_events %>

    </script>

  </head>

</html>

Et voila. Nice reliable events that fire regardless of how you setup your forms.You can easily pull these events off the session and stick just them into a JSON response too. 

It goes without saying that this approach isn’t limited to Mixpanel - it’s a nice way to log events for whatever your system is, GA, Kissmetrics or anything else. You’ve got fewer points to debug and less code for your event. 

UPDATE

There is a danger in the above technique that if the variables you place in the session are for whatever reason not dumped into the page that you will start aggregating them in session until they overrun your cookie capacity. In order to avoid this just use the Rails flash array instead. This will be managed on your behalf and cleared out as appropriate.

You can follow my posts on Twitter