Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Airbnb's Journey Into Mobile Web

Airbnb's Journey Into Mobile Web

From BackboneConf 2012

Harrison Shoff

June 01, 2012

Other Decks in Programming


  1. So I’m a doodler, which means while I was making

    this presentation I kept trying to doodle the backbone logo. I was having a really hard time drawing it, until I noticed that it looked like two overlapping triangles...
  2. None
  3. None
  4. www.ocupop.com Turns out the Backbone logo was created by Ocupop.

    Ocupop has also done the logos for Bocoup, HTML5, and Ringmark. You’re probably wondering who starts out a talk with a discussion about logos?
  5. I’m Harry, I’m a frontend engineer at Airbnb out in

    San Francisco.
  6. At the heart of it, Airbnb is connecting people that

    are looking for a place to stay with people that have space to spare. This is the place that I’m staying at right now with my 2 co-workers Dave & Spike. This is our host Kate. She’s probably the nicest Host I’ve ever met. She has a million maps, knows all the cool places to eat and drink in the neighborhood, and has offered to take us grocery shopping at least 3 times.
  7. Here’s a heat map of Airbnb listings in San Francisco.

    On the left is 2008 and right is up till today.
  8. AMAZON WEB SERVICES EC2 ELB EMR S3 RDS CloudWatch Elasticache

    Servers Load Balancing Hadoop Machines Storage Database Metrics Managed Memcache We’re big fans of AWS and use most of their services. If you’re interested in finding out what happens when Amazon goes down, check out a blog post by Tobi Knaup: http:// nerds.airbnb.com/when-the-cloud-gets-dark-how-amazons-outage-a
  9. Rails Git Lucene Hadoop Redis MySQL CoffeeScript Backbone.js SASS StatsD

    Graphite Framework Version Control Search Data Warehouse Key/Value Store Database CS Language CS Framework Stylesheets Aggregates Metrics Store+Renders Metrics We’re a Rails shop. Built with MySql. We’re using Redis to power feeds and an internal tool we call Trebuchet for launching features at subsets of users without deploying. At the moment, Github says our code base is 2.2% CoffeeScript. Which is kind of neat. I only expect that number to grow. It’s not a requirement to write in CoffeeScript, most folks just like trying out. and then a lot of our newest features have been built with Backbone, which brings me to why I’m here today.
  10. november 2011 I thought I would start with a story.

    Our story begins back in November of last year. And it starts with a guy named Joebot.
  11. This is Joebot, he’s Head of Product at Airbnb. and

    one lovely November day Joebot comes over to my desk and asks me a question,
  12. Have you seen our mobile site? He asked, “have you

    seen our mobile site?”..and of course, being the inquisitive engineer that I am, I responded with a question
  13. Have you seen our mobile site? We have a mobile

    site? "We have a mobile site?"
  14. Turns out we did. It was just a simple bare

    bones mobile site. Where if you needed access to your messages or reservations on the go, you could.
  15. But when you compare it to the iphone app we

    had released a year before, you start to get a little sad.
  16. About 10% of current site traffic is from mobile devices.

    So then Joebot starts to pitch me on the idea mobile and dive into the numbers and tells me that 10% of our current traffic is coming from mobile devices.
  17. And they were all mostly coming from Social Media. Turns

    out people love to share links to cool places they find or places they booked. And friends would click through. This is scary when you start to think that one only get one shot at a first user experience.
  18. and our first user experience was this.

  19. 88% 12% Mobile-optimized site Full site So it’s probably not

    surprising that of all the people that were visiting the mobile optimized site, almost 90% of them would rather scroll to the bottom of the page, click on “View Full Site” and deal with the whole pinch/zoom/click mess of using our full site on a tiny screen.
  20. LOW EXPECTATIONS HIGH STANDARDS I tend to try to put

    things on a scale when I start a project, to kind of see where things lie. And basically with current Mobile Web site the bar was set very low, which was nice, because it felt like we just have to do better than khaki and blue links. At the same time, we love our iphone app and we should be striving to make a product as good or better than that.
  21. CTATIONS HIGH STANDARDS But I always get super excited at

    the beginning of new projects, so in my mind, I was putting the new mobile website here.
  22. mobile site? Enter Andrew Vilcsak (mobile lead) Enter Dave Augustine

    (Front-ender) At this point, Joebot says, I wouldn’t being doing it alone. And he brings over Andrew, who’s our mobile lead and was finishing up work on our internal API and Dave, another front ender.
  23. Enter Andrew Vilcsak (mobile lead) Enter Dave Augustine (Front-ender) Could

    you have it done by New Years? and he asks us if we could have it done by New Years. Historically, New Years is one of the biggest days of the year for Airbnb. With New Years only 6-weeks away, Joebot was looking ahead knowing that there would be a spike in traffic on new years from people sharing out where they are staying and just talking about Airbnb in general. So he asked, could be done in 6-weeks? And, you know, being the pessimistic engineers that we are, we responded
  24. done by New Years? Of course! Of course!

  25. Of course! Exit Joebot Exit Dave At this point, Joebot

    leaves the conversation. And then Dave let’s us know that he will be on vacation for the next 3 weeks in New Zealand.
  26. So it ended up just being Andrew and I sitting

  27. How’s the api coming? and I asked him “how’s the

    api coming?”
  28. Almost done. Have you made a mobile site before? and

    andrew said “almost done. Have you made a mobile site before?”
  29. No. You? No. You?

  30. Nope. Nope.

  31. Do we have a designer? Do we have a designer?

  32. Not yet. Not yet.

  33. And then Andrew and I shared a moment of silence

    as reality washed over us. In that moment I started to recalculate my mind scale.
  34. LOW EXPECTATIONS HIGH STANDARDS Realistically, we were looking at a

    project that was going to land here.
  35. How do we do this? After the moment of silence,

    andrew asked “How do we do this?”
  36. As all good engineers do, we asked google

  37. http://venturebeat.com/2011/08/16/linkedin-node/ Eventually I ended up on this article about LinkedIn’s

    new Mobile Site
  38. http://venturebeat.com/2011/08/16/linkedin-node/ And it said they used Backbone (and linked to

    it!) and I clicked the link.
  39. http://venturebeat.com/2011/08/16/linkedin-node/ Took me to the Backbone docs. Close your eyes

    and imagine Backbone 0.5.3 instead of 0.9.2. I zipped through the docs in one go. Scrolled back to the top and clicked download and told Andrew we were going to be using Backbone.
  40. So that was exciting, mobile web was going to be

    my first backbone project. Feeling ambitious, I proposed using CoffeeScript. I just sent Andrew a gchat message with a link to the coffeescript homepage and he replied “looks fun”. So we were going to build it with CoffeeScript as well. You’re probably wondering, why would you use two tools you’ve never used before when you have a crazy deadline for project you’ve never done before. The best way I can explain it is that we didn’t know better. I figured building this mobile site was going to be like jumping off a cliff and trying to build wings on the way down. Might as well try to learn something new while we were doing it. It ended up being less stressful because it was more exciting to be learning something new.
  41. So this is our office in San Francisco. We have

    a nice open floor plan.
  42. Open Floor plans have some problems when you’re in crunch

    mode. So our first order of business was fixing this.
  43. So we cleaned out what was the storage room and

    put up some white boards and made a nice home for 6-weeks. Unclear if this was an upgrade or not.
  44. And we started coding. Where do I get started? We

    started with the data layer since we had an API good to go.
  45. While we were building out the data layer we would

    take breaks and sketch out what this thing was going to look like. Which was super easy to do because we were separating out the data and the views. Avoiding the jquery spaghetti doom.
  46. We ended up getting it done by New Years. It

    turned out to be awesome to have Dave join back 3-weeks later because after 3- weeks of sprinting, I was fairly burnt out. Luckily Dave just came back from vacation, so he was ready to hit the ground running. So that was back in January. Since January we’ve been using Backbone in a lot of the latest products we’ve launched.
  47. airbnb.com/communities/12 One of the bigger Backbone Apps is still in

    “alpha” mode, it’s called Communities. it’s like messageboards 2.0 where folks post threads and other people can comment on the threads, you can thank comments/threads
  48. airbnb.com/match Match is a new booking process that makes searching

    and bookings rooms more efficient.
  49. airbnb.com/search For a long time, our Search page had lots

    of trouble with keeping the state of your search when you used the back button. We ended up solving this problem using a Backbone Router and Backbone History. So after each change to the state on /search, the app serializes every parameter and pushes the new state using Backbone.History.
  50. airbnb.com/search Now all search URLs are sharable/bookmarkable because they maintain

    a search state. Before, our search URLs would either be airbnb.com/search or airbnb.com/ search#modified=true.
  51. airbnb.com/reservation/change Even if you aren’t making “Apps” writing code that

    follows the Backbone structure is nice. You get a lot out of the box and your code base gets a lot cleaner.

  53. Namespacing // global namespace for apps var AIR = {

    Models: {}, Collections: {}, Views: { Playlists: {} }, Routers: {}, Apps: {} }; We went a simplest namespace possible. We thought that at some point we would want to share models/collections and weren’t sure if views were going to get shared anywhere. So we went with a simple global object that everything would live under. That way if we had multiple Backbone apps, we wouldn’t run into a name collision.
  54. Namespacing var AIR = { models: {}, collections: {}, views:

    {}, routers: {}, apps: {} }; Namespace mirrors folder structure This also has the nice benefit of mirroring our folder structure, which makes things easier to find.
  55. - Used for list of Reviews - Throws iterate, iterate:next,

    iterate:prev events - Works when resorted because it using indexOf - Can decorate models for easy model.next() model.prev() LINKED_BASE Turn collections into linked lists / evented enumerable lists

  57. None
  58. None
  59. - Adds new items to collection on page - Throws

    a 'page' event - Should throw a 'page:next' 'page:prev' event but doesn't now, as it isn’t in the use case - Has extra properties for page and offset that are passed with fetch PAGINATED_BASE Linked_Base collections suited for infinite scrolling / pagination

  61. None
  62. - Prerender(), render(), postrender() and associated events - Bindings() call

    just to clean up stuff and move it out of initialize - Template class variable for rendering JST[@template] convention - classifyAttributes = whitelist of model attributes that you add as classes on the el if they are true VIEW_BASE
  63. None
  64. None
  65. - Optimistic for nearly everything, pessimistic for big creates like

    reservations, messages, etc. - When model save fails, there is a global fail function that uses the AppViews.flash() method to display the error message ala a flash message in rails MODELS
  66. - Static view: look for /:name in JST[name] or use

    JST['error'] - Google analytics _trackPageview via the 'route' event - Trailing slash in URL www.airbnb.com/communities/:id/ won’t match https://github.com/documentcloud/backbone/issues/848#issuecomment-3449934 ROUTER
  67. Router Static View

  68. http://nerds.airbnb.com/how-to-add-google-analytics-page-tracking-to-57536 Google Analytics

  69. - On render / page view prefer in memory collection

    or model - Use local storage if no in memory object is present - Idea is to paint something right away - Meanwhile async fetch the data from the server - Do a deep comparison of the returned json with our most recent version in memory / localstorage (we do this via an overidden sync method) - If changes, replace and re-render CACHING
  70. - useful for throwing events when the whole app should

    care - locale / currency changes for example -- when locale changes, ajax fetch new set of translations a json object, replace our phrases and fire an event that re-renders the current view -- all subsequent views will have the new translations GLOBAL STATE MODEL
  71. - Use moment.js it is rad DATES

  72. Thanks!