Life of a Ticket

by Emre Ozdemir

At the end of 2012, a cumulative total of over 4 million guests had stayed on Airbnb.

This was huge! It took us nearly four years to get our first million total guests — now over 2 million guests stay on Airbnb every month. With this growth comes the challenge of scaling marketplace operations which is the task that my team aims to improve.

I work on a team called Internal Products which is comprised of two areas, Product Excellence and Service Excellence. We’re tasked with building tools to improve the ability for our guests and hosts to help themselves, as well as increase the productivity of our Customer Experience specialists.

As Yishan Wong says, “your operating efficiency … [is] directly impacted by the ingenuity of your internal products.” At Airbnb, we want to offer the best customer service in the world, so we take this very seriously and have an entire team dedicated to it.

Our team gets to spend its time directly with its customers, the Customer Experience (CX) team, understanding their needs and fixing problems. Our team has a tight feedback loop with our CX specialists which results not only building tools that are tailored to their needs, but improving by iterating quickly.

One of the clear issues our team uncovered — was how to speed up processing a customer support ticket. The best way to share our solution is to show you our approach to the problem by examining the lifespan of a ticket.

There are 3 channels to get in touch with a specialist at Airbnb:

  • Voice: by calling our support number. In this scenario, when a person calls our support line, we will gather what we know about them based on their phone number. This is where we assign them to a specific agent based on their current state (if they have a current reservation, if they’re a host, a guest, etc.).
  • Email: in this scenario, a person will have to contact us via our contact page. They will be asked to select their reservation first (if relevant) and what they need help with (their issue), after which we magically display some troubleshooting tips, based on their current state as well. If this does not answer their question, they will have the opportunity to send us an email.
  • Chat: similar to the email flow above, after selecting their issue, they will have the option to start a chart with one of our CX specialists or with a community member.

After calling, starting a chat or sending the email, a ticket will be created with us. This ticket eventually gets assigned to an Airbnb CX specialist, where the guest/host and the specialist correspond. When the issue is resolved, the specialist solves the ticket, and the case is closed.

Our team was put in charge of improving two areas while working on the ticket flow:

  • whenever we magically display the troubleshooting tips with the Contact Page Editor
  • whenever a ticket is processed with the ticket backend (Admin Console)

The Contact Page Editor

Let’s rewind to 2012 for a moment. At the time, when a person needed to contact us, they would simply select an issue on the contact page, fill out the form and submit. We aim to be accessible, but we want to make sure we prioritize the most urgent requests. In order to do this we needed to give certain people and issues priority, and reduce the priority of issues that could be handled by people themselves. We needed an application that would enable our content team to make the necessary changes, rather than needing engineers every time we had a product update or workflow change.

We set to turn our contact page into a troubleshooting wizard; something that could provide custom content depending on the issue you choose, as well as add robust tagging and routing in the event a ticket needed to be created.

For example, if someone contacts us about how to upload their profile picture, we could display some FAQs on how to upload their profile picture, provide a link to the upload page and if this still didn’t help, give them the option to contact Airbnb.

And you could go even deeper by displaying content based on the person’s platform, whether they are a host or a guest, whether they have a reservation within the next 3 days, etc.

Our team and I built the necessary tools for our content team so they can personalize each issue where we would ask the right question, display the right help content, put you in touch with a CX specialist. We call it the Contact Page Editor and it looks like this:

The left section of this screenshot shows what the Contact Page Editor looks like (admin side) whereas the right section shows the same content but on the contact page.

The backend relies on a simple decision tree that contains different types of nodes. There are three types of nodes:

  • Content nodes: they will only display content like a list of FAQs, a text or a linked button.
  • Contextual nodes: they will display content based on the person’s state. For example if a guest/host has a reservation starting within 3 days, if they use an iPhone or Android, etc.
  • Action nodes: they contain other nodes and they will display content based on the person’s interactions like a select option dropdown.

By asking the right kind of question to our guest/host, each and every issue becomes more personalized, which helps speed up person/CX specialist interaction since there would be less back and forth.

By building a flow of custom and more personalized content on the contact page, we were able to help 15% more people in 2013.

Admin Console

The admin console is our Customer Experience tool tailored to our Customer Experience specialists needs. We have observed and analyzed the work being done by our specialists to design a tool that will not only automate tasks that a computer can do faster, but also surface the information that is needed only when it’s needed.

The admin console is a Rails application with a very heavy front-end. We started the project with 2 engineers. The goal here was to build a tool to boost productivity in solving tickets coming from the contact page for our Customer Experience team.

I was in charge of the front-end and at the time we were only using Backbone. Since the admin console is very dynamic, the content changes constantly, I decided to use knockout.js for data-binding, thus letting us not manipulate the DOM directly with a library like jQuery, but allowing the use of data-binding for DOM manipulation and so removing extra complexity by having only one single source of truth in the code. The code snippets below show an example of how a typical Backbone/Knockout component was built.

<!-- template.hbs -->
<div id='myComponent'>
<span data-bind='text: name'></span>
<!-- ko foreach: listings -->
<li data-bind='text: name'></li>
<!-- /ko -->
// view.js
var Backbone = require('backbone');
var ko = require('knockout');
var _ = require('underscore');
var data = {
name: 'John Doe',
listings: [{
name: 'Quiet room in Duboce Triangle'
var userModel = new Backbone.Model(data);var userViewModel = {
name: ko.observable(userModel.get('name')),
listings: ko.observableArray(userModel.get('listings'))
userModel.on('change', function() {
_.each(userViewModel, function(value, key) {
if (userModel.has(key)) {
}, this);

Over time, we added more functionality to the admin console and it didn’t scale very well. The pages got slower and the code harder to read. It was time to move away from Backbone/Knockout and look for other alternatives … and React came along. The application became much faster, more responsive and cleaner thanks to its Shadow DOM and the combination of the template and javascript in a single file. As for the engineers, they have a more enjoyable developer experience, less prone to have buggy code, a cleaner architecture (eq. less code duplication, readability, modularity) and can work faster because React makes your rethink how to write your code.

The code below shows the same Backbone/Knockout component from above written in ES6 syntax and built with React and flux.

// Modules
const React = require('react');
// Data
const data = {
name: "John Doe",
listings: [{
id: 1,
name: "Quiet Room in Duboce Triangle"
// Components
class ListingView extends React.Component {
constructor(props) {
this.state = data;
render() {
return (
{ => {
return <li key={}>{}</li>;
export default ListingView;

Our team was the first one to experiment with React. We used it in the admin console and in the Resolution Center. This successful experiment of React on the Resolution Center gave our front-end team the confidence to make React part of the front-end stack at Airbnb. We still have some Backbone code for routing, models, and collections in older apps, but we are moving away from it. New applications are being written with Alt for unidirectional data flow and react-router for routing.

Our team is a great playground for any engineer who wants to experiment with new technologies, since we are building products for our friends and fellow employees. Due to the interplay of teams, our roadmap can be more flexible than other groups. One weekend in 2012, I decided to build an internal chat, called Tin Can. I built it with with node.js, websockets and redis. All new technologies that I had never used. I presented it to the team the following Monday and shipped it a week later after feedback. Tin Can is now used by all Customer Experience agents and processes 70k messages a day, improving our specialists productivity every day. We have since rewritten the code to scale the product but this is a great example of quickly an idea can become a product on our team.

These are only two of the many projects my team has been working on to improve our customers’ experience. We help people get in touch with an Airbnb specialist when needed, but we also improve our specialists’ ability to help our guests and hosts by building tools that are faster, more thoughtful, and more intuitive. All of which is done with fun and colored pants in the pony lounge.

Check out all of our open source projects over at and follow us on Twitter: @AirbnbEng + @AirbnbData

Originally published at on August 25, 2015.



Creative engineers and data scientists building a world where you can belong anywhere.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store

Creative engineers and data scientists building a world where you can belong anywhere.