Make Animations For Users NOT Developers

I love nothing more than going big with a full screen, sweeping, sliding and stomach-churning animation. But I’ve come to the painful realisation that when I’ve used these in the past I’ve added them for myself and NOT for the user.

Recently, I’ve been working on bringing more animation to Eventbrite, so I wanted to share three lessons I’ve learnt about how to get the most out of animations: Animation should provide affordance, reduce friction, and delight the user.

1. Animations should provide affordance

By using animation you are already wielding one of the most powerful tools in a designer’s arsenal: affordance. The official definition is the “Relationship between an object or an environment and an organism, that affords the opportunity for that organism to perform an action”.

An example of affordance is a door knob. When you see a door knob you know that if you were to turn it you would open the door.

An example of an animation creating affordance is using a slide effect when navigating through a web application flow. By sliding the next view in from the right the user feels like they are progressing forward. Inversely, when the user needs to go to a previous step we slide the next view in from the left, giving a feeling for going backwards.

We’ve used this in our mobile app, Neon, our iOS app for organisers, to give users a sense that they’re making progress through the application.

view-slide

2. Animations should reduce friction

Closely related to this is reducing user friction.

I think the best way to talk about how animations reduce user friction is through interpretive role play. So grab a friend and get involved!

Cast:
Hermione – An event organizer
Harry – An event attendee

Scene [club night]:
Hermione is organising an amazing event using the world’s greatest self-service events platform (Eventbrite, of course).
It is the night of the event and Hermione is checking people off the guest list on the door. Things are getting busy!

Hermione
Good evening, can I see your ticket?

Harry
Sorry, I’ve forgotten it, can I give you my name instead? It’s Harry Forgotter.

Hermione
I’ll just look you up.

[FREEZE FRAME]
Hermione opens the Neon app. When you tap on the check-in screen in Neon you are greeted by a bouncing animation, which indicates that by swiping to the right you can check in the attendee. Then when the attendee is checked in their row changes to green and slides back to the left. Without the animations the app would have to provide a couple of notifications or pop-ups; one explaining that you need to swipe to check someone in, and another notifying you that the check-in was successful.

neon-checkin

[CONTINUES]

Hermione
I have checked you in. Have a great night!

Harry
Thank you, I will!

3. Animations should delight

When it comes to delighting users, the devil’s in the detail. It’s all the tiny things that add up to a great experience.

It’s the difference between a motion-activated light above your front door, and one that you need to flick a switch to turn on. You only notice how annoying flicking a switch was when you get the motion-activated light installed and you’re no longer fumbling for your keys in the dark.

At Eventbrite, we’re trying to use animations to deliver an experience that just feels better, even if users don’t know why. One of my favourite examples is the toggle switches in our forms. When your mouse passes over the switch the button eases in the direction it will slide if you click. When you click, the button slides to the left (or right) and the colour fades from grey to green, to indicate a change in state.

toggle-switch

Summary

Technically brilliant, sweeping, sliding, and stomach-churning animations are a lot of fun to make, but the reality is they don’t accomplish much, except perhaps kudos from your peers.

So don’t forget, make animations for users NOT developers!

Have thoughts or feedback? Let me know @albybarber & @evbeng

Gratuitous animation by Joshua Price

Tech Talk: Db Anti-Patterns and Service Integration

Last week we teamed up with SF Python Meetup to host another great Python Night. 180 Pythonistas, 71 pizzas and a full keg of beer later, we’d say it was a great night.

We kicked things off with lightning talks by Safia Abdalla on Data Wrangling with Python and Alison Alvarez on 2-D Spatial Data using Shapely.

Managing Identities: LDAP, Google Directory, and Django

Scot Hacker, a web application developer at the California College of Arts and creator of bucketlist.org, took the stage first with a talk on the Django-based system they’ve created at the California College of Arts to help end-users and staff create and manage identities, passwords, groups, and permissions. Scot demonstrated how the system is unusual in that it uses almost no data modeling of its own, relying instead on communication via python-ldap, Google and Workday APIs, and old-school file shuffling to negotiate communications with other systems.

Dubious Database Design

Eventbrite’s very own Andrew Godwin, Senior Software Engineer, Django core developer and the author of South, the Django migrations framework. Andrew took us through advice and war stories (and failures) he’s faced in database design.  From re-implementing indexes to rendering templates purely in the database, we walked away from Andrew’s talk with red flags to look for and hopefully a few less real life failures we’ll need to learn from.

Building Eventbrite’s New Listing Page

Eventbrite has just released its new event Listing page. Built for the company’s focus on ramping up our two-sided marketplace, it features a modern and responsive user interface designed to work across all mobile devices. It is a layout that strives for clarity and cleanliness across all event listings. Let’s take a look at the Front End aspects of this project, how we built it, and the Responsive Web Design techniques we used.

I had just joined the Eventbrite team when this project kicked off, it was a high priority product that took a lot of planning and resource gathering by the team from lots stakeholders across the company. I had worked on responsive projects previously, but none that had as much care and focus on best practices as this one.

Why Update Event Pages?

There are lots of reasons why we wanted to update the event pages (I won’t try to cover them all here), but the primary focus of the project was to improve the mobile experience.

Anyone who has bought a ticket on Eventbrite through our mobile web interface (not our fantastic native apps) will agree that the experience wasn’t perfect, we’re the first to admit it. Our less-than-great mobile interface was using a completely different code base, with a different stack (jQuery mobile). This led to several undesired consequences, not least having to constantly maintain two codebases, so when we wanted to implement a change we had to do it twice (and often in two different ways).

Add to this the fact that the classic desktop UI has aged since its original inception, the need to unify the interface into a responsive design, and to improve conversion rates for our organizers, we knew we had our work cut out for us. Our mission was to create a Responsive, Performant, Accessible and A/B testable listing page with a cleaner codebase.

Our Workflow

At Eventbrite, we work in 2 week sprints, in small “one pizza” teams. These teams typically include a Product Manager, Engineering Manager, QA Engineer, Product Designer, UX Engineer and several Engineers.

Our code quality processes include regular code reviews, and lately we have been enforcing more code consistency with ESLint. We also focus on extensive test coverage throughout the stack: unit tests for our Django code, unit/integration tests with Jasmine and Sinon on the Front End, and an extensive suite of integration/acceptance tests with Selenium’s Webdriver to ensure quality control of the whole product.

Prototype Phase

Once the initial design was approved we created an HTML prototype using the components already available on Eventbrite’s internal style guide which is a living document of patterns and components that we use across the site.

This basic implementation allowed us to build up the frontend and work with the final design from day one, gathering feedback from the product team, customer support, and real users with UX experiments. That feedback was overwhelmingly positive, so we moved forward to the real implementation.

HTML and CSS Implementation

Our next task involved defining the styles of the new components as an iterative process, and for that we started moving the inline styles first to tags, and later to their respective files or style guide definitions.

We actually kept all our HTML and CSS in the same file as long as possible, giving us a chance to look at the markup as a whole, refactoring styles and enforcing semantic markup. We only started slicing the HTML into include files once we were happy with the results and we had the Schema.org properties in place for Microdata support. This turned out to be a great move as we were able to focus in the markup quality and accessibility first.

The Front End team collectively maintains a living style guide that contains our current UI components. We use SASS to keep the consistency of our styles and KSS to generate this style guide, and once we had the components well defined and with the desired responsive behavior, we moved them into a repository as new components.

We are testing a workflow that involves working on components in the style guide initially, and moving them into our production code later. We are still playing around with the best way to to implement this, and if you’re also working on exploratory styleguides, I’d suggest checking out this article about different style guide workflows.

Modularizing our JS

We use Backbone and Marionette for our client side logic. However, we do render our DOM on the server side, powered by our Django based apps and APIs. Our current JavaScript architecture looks like this:

We use a Marionette application object to control the lifecycle of our modules, some of which we initialize selectively depending on the circumstances. Because of this, we use a functional mixin which, added to the application object, allows us to load modules when the DOMContentLoaded event is triggered or when a given DOM element becomes visible on the viewport.

The configuration for all the components are passed from the Back End by setting values into a “Mediator” object loaded by the app and component modules. Under the hood, we use RequireJS to load the app dependencies, and we have asynchronous versions of some of them in order to load them conditionally.

Components

Our components are contained within Marionette modules, and they are responsible for instantiating the views and entities for that features. Let’s take a closer look to some of them:

Map Component

Currently we are passing some parameters to modules like the map, that receives information about the viewport width. This way we can load a different kind of map (a static image with the location or a fully interactive map) depending on the screen real state we have available.

This module was largely inspired by Airbnb’s map and its huge appeal to us as users, although they have gone the extra mile by styling it a bit. If you are in a desktop browser you should be able to drag the “yellow little man” into the map and turn on street view!

Sticky Header

This component involved some work due to its complexity and we are still in the polishing stage. It was born out of the necessity of keeping the main page call to action always visible. It turned out to be a bit tricky, partly because of our ambitious goal of showing the global navigation as a second fixed bar when users scroll up, and partly because of the still precarious (thinking of you, Apple) support of ‘position: fixed’ across the board.

Performance

On the performance side, we integrated some grunt tasks to create a tool that keeps track of the webpagetest.org scores of a set of event listing pages. We run this tests daily thanks to a Jenkins task and store the results, so we can access to the historical performance of our pages. I am planning to talk about this little tool in another post soon.

We are also tracking user timing data, storing rendering time values of the hero image and register form. And regarding that new hero image, we are using a safe bet solution as our Responsive Images implementation: Picturefill.

Next Steps

We are currently working on improving the feature support of this new listing page, so we can support more event types and configurations. We are also having conversations about how we can make the page more performant and in-lining the above the fold CSS styles to improve our critical path. We also want to implement a new modal component that will enhance the mobile experience.

Summary

The launching process of the new listing has been pretty smooth, and we think we have achieved a modern looking, accessible and performant listing page. Still, we want to know what do you think about it, so feel free to reach out to me directly to chat further.

This is just the first iteration of the product, and we all know several version are typically needed to achieve a truly great product. Future iterations will be based heavy on A/B tests, so keep an eye out to see what we roll out next!

Event Page Examples

Building a Marketplace — Search and Recommendation at Eventbrite

These are exciting times for Eventbrite! Since our beginning Eventbrite has served a platform for event organizers. We allow organizers to market their events, message their attendees, and most importantly we take care of the hassles associated with selling tickets. But recently we have began to take a more active role of connecting potential attendees to the events that they will enjoy and in doing so, we are becoming the marketplace of events!

Personalized Discovery – the Center of the Marketplace

And at the heart of this transition to a marketplace of events is the notion of discovery – the ability for users of our site to serendipitously discovery events that they will enjoy. At Eventbrite, we think of discovery as occurring in two predominant modes: search and recommendation. In search, the user is actively telling us what type of event they are looking for, and it is our job to return results that are most relevant to their search. In recommendation, Eventbrite will provide passive users with recommendations for events that they might be interested in. Personalization is an important aspect of discovery as we hope to provide users not only with recommendations of popular events or search results that match their query, but we also want to tune our recommendations and search results to match individual user preference based upon their previous interactions with Eventbrite and the things that they have explicitly told us about themselves.

But this is no small undertaking, and Eventbrite has some interesting challenges to overcome. A chief concern is that, unlike movies or consumer goods, events are an unusually short-lived type of product. Netflix and Amazon use customer interactions to build rich recommendation models of their products through a technique called collaborative filtering. But when an event is published to Eventbrite there is no user interaction data and by the time the event is finished we may have only started to adequately understand how an event may be matched to our users. Though this situation will be challenging, we believe that is can be overcome via a hybrid approach – a combination of collaborative filtering and content-based recommendation and search. Read on…

Blueprints for Personalized Discovery

We are still in the early stages of building out our discovery platform, but we have some good ideas about where we want to go and how we plan to get there.

A major component of our strategy is collaborative filtering. By watching how users interact with the events in our inventory (for instance through clicks, purchases, shares, etc.) we can build a model of user-to-event affinity. Currently we are using this affinity model to send personalized event recommendations to users that receive our event follow-up emails. And right now we are rolling out a new “related events” feature on our event landing pages that is driven by this same user-to-event affinity model. The model is quite flexible, so in the future we may use it to recommend events customized for a group of users (think “night out on the town” with friends), or we might tune our related events feature so that it the related events are further personalized for the viewing user.

But, as alluded to above, one of the short-comings of collaborative filtering is that building a model requires quite a bit of user interaction data, and at the moment an event goes live there is no interaction data and thus no chance that the new event will be recommended. Because of this we will also rely upon content-based strategies for recommendation and search. Initially this will be based largely upon the organizer-specified categorization for the events and the text we find in the title and description fields (along with filters on things like location). But we are also looking at creating an event tagging system which will allow for much more finely tuned categorization of events. We are also building up user profile pages and we may eventually allow users to tag themselves with the same system being used for events. This would make content-based recommendation as simple as finding events that have the same tags as the user.

There are some problems though in having two competing recommendation systems. How do you combine the results provided by each system? Is it really a good idea to maintain two competing systems which probably have their own technology stacks? And do you really want to query both systems every time a recommendation is required? We think this seems silly. So, we’ve decided to roll both collaborative-filtering and content-based recommendation into one system and we’re doing this with search technologies. Think about it this way, search engines are natively good at content-based search and recommendation – you just store the text and categorization for each event in the search engine and then you query it as you normally would. Then, if we want to combine this with collaborative-filtering, we have to find a way of including a new field or making a new type of query that incorporates the information from the user-to-event affinity model. As it turns out, there are a few different ways to do this; but that’s a discussion for a different blog post! Once content and collaborative filtering information are in the search engine then the two sources of information can be balanced in much the same way that matches in the title and description field would be balanced in more mundane uses of search. Ultimately search and recommendation become one and the same thing and both are all the more relevant because they incorporate content-based and collaborative filtering strategies.

Will it Work?

Well, this is the most exciting question of all, because we don’t know yet if this will all work as we’ve planned. In a previous life as a search consultant I built a prototype that closely resembles the system we’re working right now, and the results were very encouraging. But this time we’re building for much larger scale. However I have seen search engines perform some amazing feats of scaling in the past and I have a strong suspicion that search technologies will not let us down here.

If you’d like to see how we’re progressing, then check back in to the Eventbrite engineering blog from time to time. In the coming months I plan to blog fairly regularly about our progress. So pull up a chair, you’ll have a front-row seat to all of the action.


 

P.S. In case you’re interested in the broader discussion of search relevance, then you should check out Taming Search, a book I’m writing with Doug Turnbull. The techniques I’m using here will be covered in depth in a later chapter of the book. If you decided to buy the book, then please be sure to use the code mlturnbull to get 50% off the price of the book.

Type python, press enter. What happens?

Philip James and Asheesh Laroia discussed how the Python interpreter starts, from the perspective of the operating system (OS). Together, we will see the ins & outs of processes: fork(), exec(), stdin, and stdout.

It focused on OS concepts and requires no background knowledge, using analogies to Python data structures. (The talk does not discuss Python’s own initialization, such as site.py or global variables.)

Finding Spammers & Scammers through Rate Tracking with Python & Redis

We made it back from PyCon to the considerably warmer climate we’re accustomed to in San Francisco. Mica Swyers and Jay Chan from the Eventbrite Integrity team provides an introduction to rate tracking as well as an explanation of a particularly cool way to implement it. They go over what rate tracking is, why you would want to do it, and then how you can use build a Redis-backed “velocity engine” in Python to do just that.

D3.js Resources to Level Up

I have gotten a lot better at D3.js development over the past few years, and can trace most of my improvement to coming across a few key tutorials, blogs, books and other resources on the topic. They’ve been a huge help for me, and I’ve gathered a bunch of my favorites in this post to hopefully help others improve their D3 experience.

Here it goes:

Assessing your level

First, let’s define four general D3.js levels:

  • Complete Beginner: You have no previous experience with D3.js or any front end technologies (HTML/CSS).
  • Basic: You have some HTML/CSS/JS skills and have played around with some D3.js examples, but don’t completely understand the patterns and mechanics it uses.
  • Intermediate You know how to customize D3.js graphs using examples found in search engines, but you struggle to reuse them and aren’t quite happy with the quality of the code itself.
  • Proficient: You have build a lot of different graphs, tests and integrated them with different technologies or libraries. You’ve even created packages to easily share logic between projects.

Complete Beginner

Books

Scott Murray’s Interactive Data Visualization for the Web. Available free online through O’Reilly, it covers most of the basics needed for building your first interactive graphs.

Tutorials and Hands-on Learning
Reference links

Christophe Viau’s D3.js Gallery, is a pretty extensive list of charts made on D3 and sorted by graph type (bars, pie, bubble, etc.)

Courses

Udacity’s Data Visualization with D3.js, Communication with Data. It’s free and looks sweet, what else can you ask for?!

D3 Pie Chart

This chart employs a number of D3 Features: d3.csv, d3.scale.ordinal, d3.svg.arc & d3.layout.pie. From bl.ocks.org

 

Basic

Books

Getting started with D3.js: a short introduction (under 100 pgs) targeted for web developers.

Tutorials and Hands-on Learning

Introductions & Core Concepts sections of the D3 wiki tutorials.

Reference links
This simple bar chart is constructed from a TSV file storing the frequency of letters in the English language. The chart employs conventional margins and a number of D3 features. From bl.ocks.org

This simple bar chart is constructed from a TSV file storing the frequency of letters in the English language. The chart employs conventional margins and a number of D3 features. From bl.ocks.org

Intermediate

Books
Tutorials and Hands-on Learning

Introductions & Core Concepts section of the D3 wiki tutorials

Reference links
Videos

Ian Johnson’s bayd3 youtube playlist

coenraets.org

coenraets.org

 

Proficient

Books

Some of the content in Mastering D3.js may be new for you, but I haven’t found a lot published at this level.

Tutorials and Hands-on Learning

Check out the Specific Techniques section of the D3 wiki tutorials.

Reference links
Blogs
Interactive D3 chart from the NY TImes

Interactive D3 chart from the NY Times

I hope this roundup of links will help level up your D3.js skills. This is by no means an exhaustive list, if you have others you’ve found useful share them with me on twitter @golodhros. I hope this is a great starting point to get you started and building more exciting visualizations!

Eventbrite Engineering at SXSW 2015

Photo by CleftClips on Flickr

Photo by CleftClips on Flickr

If you are at SXSW this year you are undoubtedly already aware Eventbrite has a huge presence ticketing most of the parties, what you may not know though is that some of our engineering team are also out in Austin flying the eventbrite flag.

Our very own Daniel ‘Cubes’ Silverstein is giving a talk tomorrow (17th March) at 11am with Katie Dill, Head of Experience Design at Airbnb in the JW Marriot Salon C.

The Remaking of Airbnb and Eventbrite

IMG_0305_4x5In mid-2014 Airbnb and Eventbrite both underwent major redesigns of their websites. These efforts touched virtually every page on the sites and affected every person in each company. Find out why each company made it a priority to undertake such massive efforts, and how design, engineering, and product teams came together to accomplish these feats. This panel will include Daniel C. Silverstein from Eventbrite and Katie Dill from Airbnb to tell the inside story of why and how they did it.

If you are staying on for SXSW Music, we recommend checking out South Fry South Friendy’s, a gig hosted by the multi talented Eventbrite Nashville Engineer Jesse Keogh

If you are at SXSW we hope you get chance to eat lots of BBQ food, drink Margaritas and most importantly get to see Dan’s talk and Jesse’s gig! Have fun in Austin!

CSSConf Oakland review

The inaugural CSSConf Oakland took place at The New Parkway Theater in December 2014. It was expertly co-ordinated by Mikeal Rogers, Karolina Szczur, Kristina Schneider and Alex Sexton as part of JSFest, a week long series of front-end events in Oakland, California.

The relaxed setting meant it felt like chilling in the tatty sofas of a cosy living room, hanging out with 100 or so close personal friends. The sessions were excellently curated to form a well rounded agenda, with healthy diversity in the lineup and women representing seven out of 12 speakers.

Tab Atkins of the CSS working group spoke with such bubbling enthusiasm for new capabilities coming to CSS that we couldn’t help but be carried on a journey to the glittering future. A future where an image can be the output of a function, you can create source-order independent layouts with flexbox and even programatically adjust colour values live in the core language. Even media queries are getting a facelift with the ability to target the accuracy of the pointer or if a device has hover capabilities.

Two other highlights were talks bourne of experience gleaned through hard graft on real-world projects. Jessica Dillon told the story the implementation of Bugsnag, a visual CSS testing framework. Jennifer Wong shared pitfalls and lessons learned in her quest for beautiful responsive emails. Both talks elegantly encapsulated their respective projects and presented valuable take-home lessons.

Unequivocally my favourite session came from Elyse Holladay, Front-End Architect at RetailMeNot, whose eloquent and raw talk spoke directly to the soul of everyone there. Holladay mused that as we gain experience we are no longer safely coddled in the confidence of inexperience, we panic about what we know we don’t yet know. She proposes that instead of agonising over not yet being good at something, we should be kind to ourselves, relish the challenge of learning and always stay curious.

Photo of Jessica Dillon by Karolina Szczur

Originally published in the April edition of Net Magazine, written by Natalie Downe photo credit to Karolina Szczur