Author Archive

Quick & Dirty Referral Tracking

Ever wondered where people came from to sign up for your web app? Recently I wanted to track referrals for Tender and wanted something quick and dirty. The only problem? Our setup page is on a different domain than our marketing site. This meant I couldn’t use Google Analytics since it thought every “goal” came from exactly one place: the marketing site.

So instead, what I did was hack together a quick referral script using Javascript to track where people came from and add that to a field on the Site model (each install of Tender is considered a ‘Site’). The Javascript (in MooTools):

var Tracker = new Class({
  tracker: null,

  initialize: function(){
    this.initCookie();
    this.updateCookie();
    this.markLinks();

    var field = $('site_referral');
    if (field){
      field.value = this.tracker;
    }
  },

  initCookie: function(){
    this.tracker = Cookie.read('tracker');
    if (!this.tracker || this.tracker == "") this.setTracker();
  },

  // Order of precidence
  // 1. ?source= from in the URL
  // 2. ?utm_campaign= in the URL
  // 3. Referrer / Direct
  setTracker: function(){
    var final_source = document.referrer ? document.referrer : "direct";
    var args = $get();
    if (args.utm_campaign && args.utm_campaign.trim() != '') final_source = args.utm_campaign;
    if (args.source && args.source.trim() != '') final_source = args.source;
    Cookie.write('tracker', final_source, {duration:1});
    this.tracker = final_source;
  },

  // Updates the cookie if another ?source or ?utm_campiagn is set
  updateCookie: function(){
    var final_source = null;
    var args = $get();
    if (args.utm_campaign && args.utm_campaign.trim() != '') final_source = args.utm_campaign;
    if (args.source && args.source.trim() != '') final_source = args.source;
    if (final_source){
      Cookie.write('tracker', final_source, {duration:1});
      this.tracker = final_source;
    }
  },

  markLinks: function(){
    $$('a.signup-link').each(function(el){
      el.href += "?source=" + this.tracker;
    }, this);
  }
});

function $get(key,url){  
   if(arguments.length < 2) url =location.href;  
   if(arguments.length > 0 && key != ""){  
       if(key == "#"){  
            var regex = new RegExp("[#]([^$]*)");  
        } else if(key == "?"){  
            var regex = new RegExp("[?]([^#$]*)");  
        } else {  
            var regex = new RegExp("[?&]"+key+"=([^&#]*)");  
        }  
        var results = regex.exec(url);  
        return (results == null )? "" : results[1];  
    } else {  
        url = url.split("?");  
        var results = {};  
            if(url.length > 1){  
                url = url[1].split("#");  
                if(url.length > 1) results["hash"] = url[1];  
                url[0].split("&").each(function(item,index){  
                    item = item.split("=");  
                    results[item[0]] = item[1];  
                });  
            }  
        return results;  
    }  
}

The way this works is the following:

  1. If someone comes with ?source=something or ?utm_campain=something (a Google Analytics keyword), it stores that value in a cookie called ‘tracker’
  2. If no ?source or ?utm_campaign can be found, it stores the referrer
  3. If no referrer can be found, it stores the value ‘direct’
  4. Every URL that has the class signup-link gets ?source=trackerhere appended, so that the referral gets tracked over to our setup domain.
  5. If it finds a field with the id of site_referral (the rails default for Site#referral field), it sets that value to whatever is stored in the tracker cookie.

Now when people sign up, I can see where they came from in the admin panel:

Referral Screen

Having fun with the Lighthouse API

I’ve been using Lighthouse since it’s inception, but now that I’m working with the ENTP folks I get to thinking about what to do with Lighthouse a lot more. I’ve had a few ideas on ways to play with the API and I finally got around to implementing one of those ideas with Burndown.

Burndown is a simple little app that adds a new dimension to Lighthouse – Time. It shows you a burndown chart for each milestone in your project, recording the number of open tickets each day so you can see the progress of your milestone. If you’re running in short iterations, it’s a good way to measure your team’s velocity all agile and whatnot. You can see an example for Tender’s current milestone. As a bonus, you can keep tabs on our development on Lighthouse and Tender for the sample install :)

Screenshot

Miniapps are fun

Burndown is what I’d call a miniapp — it can’t survive on it’s own, doesn’t have fancy permissioning, security or even the best code. It just gets the job done. For me, it was a way to play with a lot of new technologies I haven’t played with before. It’s currently running on Heroku, powered by Sinatra & Datamapper, with the front-end powered by jQuery & Raphael. I haven’t touched a single one of these, but the app still only took about a week to build.

If you want to try it out, I’d suggest opening up an account over at Heroku. From there, it should take a few minutes to get your own Burndown instance running.

Some thoughts on the tech

Since this was an all new experience I thought I might share some of my thoughts on the tech I used to build Burndown.

Heroku… rocks

I’d heard great things about Heroku, but never really had a need to play around with it. My first reaction: holy crap this is awesome. Getting the app up and deployed was easier than setting up Wordpress on Dreamhost. That says a lot. That being said, there were definitely some rough patches debugging the app, and I’m really not sure what was causing them. I’m guessing it’s whatever database they’re using, but can’t be certain. Weird ordering with my records.

Datamapper… I’ll take AR, thanks

Datamapper was definitely a struggle. I’m not down with the way conditions work at all. I understand what they’re trying to do here, but :age.gte => 15 is freakin weird lookin Ruby no matter how you slice it. I also ran into quite a few random bugs where my association finders weren’t getting scoped (want an example of a really hard bug to track down?). All in all, I’ll take my ActiveRecord over it any day.

Sinatra… rocks, reloading does not

Sinatra is an awesome little framework. I’ve played around with it in the past to the extent of hacking other people’s code, but never deployed something for myself. It’s a pretty rockin framework, and with PassengerPrefPane it exists seamlessly in my dev environment. Unfortunately the lack of code reloading is really a pain. Can’t tell you how many times I typed in touch tmp/restart.txt

Raphael is awesome, if a bit obfuscated

I wanted to play around with a more powerful graphing library, so I ended up choosing Raphael. The end result is smooth, awesomely extendable, and fast. Unfortunately the sample code is really hard to understand. A few comments in this file would have gone miles. So would have using regular hex color values instead of crazy hue math. There is also zero documentation from what I can tell. Yes, there’s a documentation page… it does not show you how to use it.

When you HTTParty, you must party hard!

My first turn when interacting with the Lighthouse code base was to turn to the Lighthouse API gem, but because of the ActiveSupport dependency — and quite frankly gem conflicts I didn’t want to deal with — I decided to go the HTTParty route. Honestly, it’s just too easy to use. It made dealing with the API a breeze.

Go forth and create Lighthouse miniapps!

Feel free to fork / steal the source (including the design!) and create more miniapps for Lighthouse. Everyone uses bug trackers differently, and sometimes the best idea is to just build the interface / chart / feature you need. This app should cover the basics of saving / validating API keys, as well as some simple examples of how to sync data locally through cron jobs.


Stop complaining about App Store approval times

I’m getting kind of tired of all these web developers complaining about the time it takes to get updates to their apps up on the iTunes App Store. The truth is this complaining has some merit. But you have to realize that these people are not making web applications, they’re making installable applications. The problem is not Apple. The problem is lack of QA testing.

Your application will have many bugs

The first rule of development: your code is going to have a lot of bugs. I don’t care if you’ve got 3 days experience or 30 years experience in the industry. Your code will have bugs. This isn’t a pride issue, it’s a fact of life. Good developers know this and rely on testing (code, user-acceptance, performance) to expose bugs so they can fix them.

Bugs will appear after your code is deployed

Whether it’s the Y2k bug, deprecation of a technology, or your application getting blacklisted from a web service — some bugs are going to show up after your code is deployed. This is something you should expect. Again, this is not negotiable. It is going to happen.

The web makes us lazy

The truth is, developing web applications makes us lazy. I can fix a bug, deploy, and it’s fixed in about 15 seconds. This is why I love working on hosted web applications. You’ve got such immense power over the deployment process. Some things that rock about web apps:

  • You can be really lazy with UAT (User Acceptance Testing). Users will do your UAT for your and you can fix it on the fly.
  • You can be really lazy with bugs that will appear after deploy. If a web service changes, you fix it and redeploy. Done.
  • You only need one computer to test your application. No need to purchase multiple hardware platforms, video cards, or install multiple operating systems!

You can’t be lazy with installable applications

I once worked on a desktop application that was being sent out on millions of machines. This application was going to be the first thing that started up when the user booted the machine. It also meant we didn’t have the option to issue updates for the application after deployment. We spent tons of time doing user testing on dozens of machines. And then the client did user testing. And then the client’s QA department did even more testing. And then the client’s QA department did more testing throughout the whole time they were writing hard drives.

Remember the days when you updated applications with CDs or floppy disks? My god, for a while there it just wasn’t feasible to update installable applications over the internet. The end result? Software development firms spent a lot of time and money on QA. Same goes for game development companies.

My point is: if you know that one of your restraints is updating can be slow or impossible, you spend more time testing the application.

The App Store is slow

It’s true the App Store is slow when it comes to delivering updates. To me, this is just a known variable. Wouldn’t it be awesome if they had 24 hour turnaround? Sure would be. But it’s one of those tradeoffs you get with a closed system. If you want to trade it for an open system — build a web application. It’s not that hard.

I know it sucks testing your application. I know as a lone developer you don’t have the money to hire testers.

But think of the rewards. The App Store is something of a gold rush right now. A small group of people have made obnoxious profits off very little effort. There’s almost no overhead ($100 application fee? psh) — and anyone can submit apps. It’s a shitty closed ecosystem controlled by Apple. But it’s a shitty closed ecosystem of chocolate-filled pools lined with gold and supermodels dressed in nothing but $100 bills if you strike it rich.


Working Remote

For about a year now, I’ve been working from my house — working on stuff for entp and the occasional contract here and there. Overall, I think it’s been an immensely positive move.

The good things

Let’s start off with what’s been working out great. First off: I get to focus when I want. Previously, I was one of those “9 to 5″ workers, meaning I got into work at 8:30am and left around 6:30pm or later. My problem is that my greatest focus time is generally around 7-9pm and 11-2am. The time I was at home. So now I get to work when I want, which means I get far more done in less time.

This whole focus thing can’t be exaggerated enough. I do not function in the mornings. Sure, I can force myself to wake up, get dressed, get to work, pound some coffee, but I just don’t get the work done I do later on in the day. Don’t give me the “you’ll get used to it” speech, because I did this 8-6 thing for 5 straight years. My body just doesn’t function in the mornings.

The second best part of working from home is controlling my nutrition. When I worked at an office, my diet was pretty horrid. I was constantly grabbing quick food from various places, for lunch, for dinner, for a breakfast snack. But now I get to wake up, make some coffee and enjoy a bowl of fruit or oatmeal as I catch up on the day. It’s also a lot easier to make several smaller meals throughout the day. I’ve also been able to exercise a lot more — I don’t have to wait until getting off work, or worry about bringing my gym bag, etc — I just go for a run when I have some spare time.

Lastly, I tend to waste a lot less time when I set down to work. I spend much less time in meetings (meetings used to consume an ungodly amount of my time at an office). I can close myself off in my room, put on some headphones and just get things done. Nobody to come by my desk and annoy me, or useless meetings to attend. Less talking, more doing.

The not so good things

My biggest problem right now is separation of work from home life. My desk sits opposite my bed right now, which means my computer’s always there in my bedroom. My next place I’d like to try and get a loft or something where there’s a really clear separation between sleeping space and working space. (Let me know if you know of an awesome loft opening up in San Francisco around July)

The second problem for me has been not working human hours. I have a few friends downtown who try and get me to go have beers with them at 5 when they get off. Unfortunately by then sometimes I’ve only clocked in a couple of hours for work — so I have to stay home and work through. This is of course directly in battle with my productive times, so it’s hard to find a clear winner here.

The future, perhaps?

Back in the late nineties, it seemed as though everyone thought telecommuting was going to be the future. I wonder if maybe we’re swinging back towards that now. Traffic of course only gets worse — while people’s homes are getting larger and further from city centers. About half of entp works from remote (from Tennessee to Uruguay) right now and we seem to get things done alright.

There’s no denying having an office is awesome, but I have a feeling it’s going to move from the “necessity” column over to the “nice to have” column in the next decade or two. Especially for professions like design & programming which take a certain amount of closed-off concentration to get things done. The problem is that people in our profession work well in small groups — and much worse in large groups. A small group breeds healthy debate and conversation, while a large group breeds endless arguments and criticism.

In any case, I wish more companies would try out having less strict hours for working in offices. It’s crystal clear to me that forcing people to work 9-5 only breeds a culture where your effort is measured in hours spent, and not work produced. It’s easy for someone to put in 8 hours of programming and get less done than another person who puts in 1 hour of work. It all has to do with breeding work conditions that work towards their advantage.


Ruby Training in Atlanta, April 1-3

entp’s Jeremy McAnally is teaming up with Ruby Power and Light (that’d be the very David Black) to put on a three day Ruby training session in Atlanta April 1st-3rd. Early bird pricing ends March 11th (three days from now!) so get on it while the going’s good!

More info at Hoth


  •   
  • Copyright © 1996-2010 BlogmyQuery - BMQ. All rights reserved.
    iDream theme by Templates Next | Powered by WordPress