Introducing Britecharts: Eventbrite’s reusable charting library based on D3

The usual workflow when developing interactive data visualizations with D3.js is based on the significant number of examples that the D3 community provides. They are broad and useful, but they are still not ideal. Most of the time, they require a lot of effort to integrate into your code and to make them production-ready.

In a previous series of posts about Leveling Up D3, I talked about a different way of building D3.js charts, using the Reusable API, building our components via TDD and improving them with events and refactorings. Following those ideas, and with the help of Eventbrite’s design team, we have been working on our chart library, and now we want to share it with you. It’s called Britecharts.

What is Britecharts?

Britecharts is a client-side reusable Charting Library based on D3.js v4 that allows an easy and intuitive use of charts and components that can be composed, creating beautiful visualizations.

The idea behind Britecharts is twofold: first, we want to allow developers and designers with little experience with D3.js to build great interactive charts with little initial effort. Second, we want to propose a framework for helping D3.js developers to create new D3.js charts by following standards like the Reusable API and Test Driven Development.

What problem does Britecharts solve?

The project is just an implementation of the Reusable Chart API. As such, it solves the problems of regular D3.js charts, namely, lack of modularity, high complexity, low re-usability and poor testability.

We also wanted to accomplish this with an eye for aesthetics so that anybody could have a beautiful chart working out of the box. Our project also offers the set-up necessary to create charts on a TDD basis as well as a playground for polishing and manually testing them.

Rendering your first BriteChart

For installing the library, you can use NPM or Bower to install the individual JavaScript files and CSS stylesheets (we are getting ready a bundled version to be downloaded via CDN). Here we see an example using NPM:

npm install britecharts
npm install d3

Then, you will load the dependencies this way on your ES2015 project:

import * as d3 from 'd3';
import bar from 'britecharts/dist/umd/bar.min.js';

Next up we will create your first chart. We will start with the data definition. Here, we have a piece of data:

const data = [
        {
            "name": "Radiating",
            "value": 0.08167
        },
        {
            "name": "Opalescent",
            "value": 0.0492
        },
        {
            "name": "Shining",
            "value": 0.02782
        },
        {
            "name": "Vibrant",
            "value": 0.04253
        },
        {
            "name": "Vivid",
            "value": 0.02702
        },
        {
            "name": "Brilliant",
            "value": 0.02288
        }
    ];

This data is the result of an imaginary poll we made around our team at Eventbrite. As it is category data, we will use a horizontal bar chart to represent it.

Once we choose the chart type, we want to check out the required data entries for it. We do this by navigating to the global section of the docs and searching for the bar chart. Here, we see that the right data format should be:

[
    {
        value: 1,
        name: 'glittering'
    },
    {
        value: 1,
        name: 'luminous'
    }
]

Our original data format is pretty much the same, so we won’t need to transform the data. To plug our chart inside a container div that we previously created on our HTML, we will need to type:

let barChart = new bar();
let barContainer = d3.select(‘.js-container’);
let containerWidth = barContainer.node() ? barContainer.node().getBoundingClientRect().width : false;

barChart
   .margin({
        left: 120,
        right: 20,
        top: 20,
        bottom: 5
    })
   .horizontal(true)
   .usePercentage(true)
   .percentageAxisToMaxRatio(1.3)
   .width(containerWidth)
   .height(300);

barContainer.datum(data).call(barChart);

And using a template that includes Britecharts styles and the chart container:

<head>
    [...]
    <link rel="stylesheet" href="node_modules/britecharts/dist/css/britecharts.min.css">
</head>
<body>
    <div class="js-container"></div>
</body>

the previous code will render:

Every chart has a series of properties that are public, in this case: horizontal, width, valueLabel and height. You can find them on each chart’s API menu on the docs homepage. Here is the Bar Chart API.

Responsive Charts

Once we have our data visualization rendering, we usually want to make our charts responsive. In order to achieve this, we will first set up a listener to the ‘window.resize’ event and trigger a redraw when that happens.

const redrawCharts = () => {
    let barContainer = d3.select(‘.js-container’);
    let newContainerWidth = barContainer.node() ? barContainer.node().getBoundingClientRect().width : false;
    
    // Setting the new width on the chart
    barChart.width(newContainerWidth);

    // Rendering the chart again
    barContainer.datum(data).call(barChart);
};
const throttledRedraw =  _.throttle(redrawCharts, 200);  

window.addEventListener("resize", throttledRedraw);

It is also useful to throttle that event so that we don’t redraw our chart a considerable number of times, as this event triggers many times with every resize event. For this, we will use a util library like underscore or lodash.

Advanced Settings

Now that we have a responsive chart, we will use other components to add more functionality. In this case, we will add a tooltip to our chart.

The bar chart and other Britecharts have some mouse events attached to their elements and exposed through custom named events. This way, when we hover with our mouse (or tap on mobile devices), a custom event will be triggered. We can easily hook up a handler function, whose code will look like this:

...
import miniTooltip from 'britecharts/dist/umd/mini-tooltip.min.js';

let tooltip = new miniTooltip();
let barChart = new bar();
let barContainer = d3.select('.js-bar-chart-container');
let containerWidth = barContainer.node() ? barContainer.node().getBoundingClientRect().width : false;

barChart
    .margin({
        left: 120,
        right: 20,
        top: 20,
        bottom: 5
    })
    .horizontal(true)
    .usePercentage(true)
    .percentageAxisToMaxRatio(1.3)
    .width(containerWidth)
    .height(300)
    .on('customMouseOver', tooltip.show)
    .on('customMouseMove', tooltip.update)
    .on('customMouseOut', tooltip.hide);

let tooltipContainer = d3.select('.bar-chart .metadata-group');
tooltipContainer.datum([]).call(miniTooltip);

And that’s it! The tooltip is working!

Styling

Depending on the number of charts you will use, you could either load the whole bundle of styles or load the styles of different charts plus the common styles. The bundled configurations and split charts and styles can be found in the dist/ folder.

We can add additional styles to our chart in different ways. Britecharts provides some color palettes that you can use for the bars, and you can also style the SVG elements with CSS, either overriding the original styles or by simply starting again from scratch.

Let’s see an example:

import colors from 'britecharts/dist/umd/colors.min.js';

[...]
barChart.colorSchema(colors.colorSchemas.extendedOrangeColorSchema);
[...]
barContainer.datum(data).call(barChart);

Will render an orange themed bar chart:

Remember that you could also create animations for the SVG paths, using dashed lines or making them move, grow or anything else that you can think of! Read more in this great article by Sara Soueidan

When Britecharts is not for you

We have tried to achieve a healthy balance between ease of use for both nontechnical people and D3.js specialists alike. Still, if you are going to need just one chart to customize deeply and never use again, maybe the example-based approach will work better for you.

Looking ahead

We are super excited about the launch of Britecharts and want to hear your opinions on it!
Any feedback about the documentation, complexity, customization options and ease of use are highly appreciated.

With Britecharts, we hope to help newcomers to the D3 community to structure their charts and test them efficiently. Our goal is for it to become a library of high-quality, tested data visualizations.

Resources

Contributing

If you are excited about Britecharts, want to add more configurable properties or even create your own chart, please check our Contributing Guide. In it, we walk you through the development environment setup, run our docs and demos and create new Pull Requests.

5 good practices I follow when I code using Git

Nowadays using Git is almost a rule and of course tools like GitHub, GitLab and Bitbucket are almost a standard.

To me, it really doesn’t matter the size of the project that I am coding, it could be for my current job, a freelance one or my personal apps: I always use Git.

I think that habit is like a cane to walk the road to perfection. That’s why I do not just use Git but also always follow some best practices that I have learned.

TL;DR

  1. Use branches for features, AB tests, fixes, etc.
  2. Commit often.
  3. Use clear commit messages.
  4. Always use pull requests.
  5. Keep master releasable.

1. Use branches for features, AB tests, fixes or whatever

This allows me to make much more atomic changes, not getting distracted, identify branches easily and of course translate all these advantages into pull requests afterward. I usually use this convention: feature/name-of-feature, abtest/name-of-abtest, fix/name-of-fix

2. Remember the old checkpoints: commit often

     Screenshot of Cisco Heat: All American Police Car Race. Image from Moby Games

Do you remember the checkpoints on the games you play? Every time you screw it up you’re able to start again from your last checkpoint. Commits to me are the same thing.

Just started coding a feature? Make the initial commit. Improved a little bit the feature? Make a commit. Wanna try a different approach? Commit what you have done until that moment and then refactor whatever you want.

By doing this, I avoid having comments, messy and commented code and things that I will need to clean later but more importantly I can always go back to stable states of my code.

3. The clearer the commit message is, the better

I always use descriptive titles for my commits. Also, if I have been working for a while and/or have touched many classes, I write a short title and then summarize the changes with bullet points.

Thanks to git commit –amend you can easily commit your changes and describe them without having tons of commit lines.

Another good practice related to this is to squash your commits down into one that summarizes all the changes you have made.

4. Always use pull requests, always

It doesn’t matter if I work with other people or on my own, I find great to use pull requests every time I want to merge my code with my base branches. By doing it I can detect issues, wrong code style, commented lines, mistakes, things to improve, etc.

5. Backups are important, keep master releasable

I usually use at least two different base branches: develop and master.

Master is the codebase that reflects the releasable product. This is very handful when you have to release hot-fixes on production because you just create the fix branch from master. It always has to remain releasable.

Develop on the other hand is the base branch where I merge all my feature, fix and AB test branches. After I integrate everything, do the proper testing, I am sure it is releasable and make the RC from it, I merge develop into master.

6 Unsuspecting Problems in HTML, CSS, and JavaScript – Part 2

Welcome to part 2 of our series covering six unsuspecting problems and scenarios that one may come across in HTML, CSS, and JavaScript. In part 1 we talked about the Block Formatting Context and Margin Collapsing. In this post, we will be covering DOM reflow and event delegation, and how they affect the performance of your application.

DOM Reflow

DOM reflow is the drawing or redrawing the layout of all or part of the DOM. This is an expensive process, but unfortunately easily triggered. This could cause a noticeable performance degradation of a web app that requires a lot of user interactivity i.e. drag & drop and WYSIWYG editors. If you are developing a highly interactive web app, then you will most likely at some point trigger a DOM reflow.

Eventbrite’s switch to ReactJS is one answer to the poor performing native DOM. ReactJS creates its own virtual DOM, which optimizes which parts of the web page needs to be re-rendered.

Common Causes

  • Inserting DOM elements
  • Removing DOM elements
  • Moving elements
  • Animating elements
  • Resizing the Window

One cool trick of optimization that I use for inserting new DOM elements is to do all of my processing in memory before appending the new element to the DOM. JavaScript has an API class, which explicitly address this problem called Document Fragments; however, this class is not necessary to achieve the optimization. Simply put, whenever you dynamically create DOM nodes via JavaScript, make sure you do all of the manipulations on that node before appending it to the DOM tree.

A real world scenario is creating a popup modal, which contains a list of names. You could dynamically create and append the modal to the DOM, then in a for-loop, iterate over an array of names appending them inside of the modal. This is not an efficient solution because on every iteration of the for-loop you are causing a DOM reflow. It would be better to create the modal dynamically, append the names to the modal node, then append the modal along with its names to the DOM at once resulting in only 1 DOM reflow.

Event Delegation

Event delegation is the process of taking advantage of the DOM’s event propagation process to handle events at the parent (or ancestor) level versus directly on child nodes. Proper use of event delegation can net a highly performant interactive web app. Improper use could cause noticeable lagging for web pages that involve a lot of user interaction such as drag & drop and WYSIWYG editors. The probability of performance degradation increases with the number of DOM nodes on a given page.

I once worked on a project that involved building a WYSIWYG editor from scratch with its main mode of interaction being drag & drop. Users could drag & drop elements like tables, lists, paragraphs, images, etc. in the DOM, and reorder them at will. Before starting on this project, I was unaware of event delegation, event propagation, DOM reflow, and document fragments. Needless to say, my single-page app had a serious lag problem, and my laptop’s fan sounded like a helicopter. After adding event delegation, document fragments, and these other optimization techniques, the page lag and overall user interaction improved to a smooth experience.

Before I continue I will first explain the concept of event propagation. Event Propagation is the process of multiple events firing on DOM nodes and their descendants and ancestors. For instance, tables have several descendants, table-rows and table-cells. Let’s say you want to place a background highlight on the table-cells when they are clicked. If you hover a table-cell the DOM will fire an event not only on the table-cell, but the table-row and table itself.

There are two event propagation models: bubbling and capturing. These two define the order in which the events are fired. In a bubbling model, when an element is clicked, the event firing starts at the child then eventually bubbles up to the top most ancestor by recursively triggering chained click events to the next parent. In a capturing model, the event firing starts firing at the parent then down to its descendants, then bubbles back to the top. In most modern browsers, except for IE9, event capturing is used. Sometimes it may be necessary to stop the event propagation all together, and that can be done with event.stopPropagation.

Let’s say you have a list of blog posts rendered on a web page, and you decide to add event handlers to every list-item. You want to perform some action when a user clicks one of the blog posts.

<ul id="parent">
<li class="blog-item">Post 1</li>
<li class="blog-item">Post 2</li>
<li class="blog-item">Post 3</li>
<li class="blog-item">Post 4</li>
<li class="blog-item">Post 5</li>
</ul> 

Now, let’s say you dynamically add a 6th post to that list without refreshing the page. What happens when you click on the new post that was just added to the list? You would expect the do_something() function to be triggered, but instead nothing happens. Why?

The answer is that even though a new list-item with the class name “blog-post” was added to the list, a new event listener was not explicitly assigned to that new item. Using event delegation, you can simply assign the event listener to the parent element, and allow the event propagation to listen for clicks on any of its descendants including newly added items. Here at Eventbrite we implicitly take advantage of event delegation via React. React utilizes event delegation underneath the hood by attaching an event listener to the top-level document element.

From a performance perspective, this is more efficient as well. Imagine having a list of a 1000 items. You’ll need to invoke 1000 event listeners on the page whereas you can simply invoke one event listener on the parent element, and handle the event during propagation.

6 Unsuspecting Problems in HTML, CSS, and JavaScript – Part 1

HTML, CSS, and JavaScript are known for having various quirks and unsuspecting behavior causing developers to jump through hoops, climb mountains, and perform Houdini-esque magic tricks to fix them. I made a list of six solutions to common head-scratchers that I’ve run across while dabbling in the DOM, so you won’t have to.

This is the first of a three part series. We will begin by tackling two fundamental concepts that exist in HTML and CSS, which may help you reason out solutions to tricky scenarios that exist in the Wild Wild West that is front-end development.

Block Formatting Context

Block formatting context is a fundamental component to how elements in web pages are rendered. It describes how they stack and interact with each other resulting in the final visual output of the webpage.

Multiple block formatting contexts can exist on a single page. A new block formatting context is created in one of the following cases:

  1. Absolutely positioned elements
  2. Floated elements
  3. Inline-block elements (display: inline-block)
  4. Block level elements where their overflow property has a value other than its default of visible (overflow: auto, hidden, scroll, etc.)
  5. Table cells or elements with their display set to table-cell (display: table-cell)
  6. Table cells or elements with their display set to table-caption (display: table-caption)

Understanding block formatting context may not be intuitive at first without a proper use case, but it will help make sense of several common quirks in CSS where elements do not align according to the developers expectation: margin-collapsing, multi-column layouts, non-text-wrapping floats, etc.

Below, we will address a common quirk that you may run across due to block formatting context known as margin collapsing. The big take-away from this section is that if you ever come across a problem pertaining to layout rendering such as margin collapsing or improper alignment due to floated elements, one solution is to try to create a new block formatting context by following one of the rules above.

References

  1. W3C, Block Formatting Context, https://www.w3.org/TR/CSS2/visuren.html#block-formatting
  2. Ritesh Kumar, Understanding Block Formatting Contexts in CSS, https://www.sitepoint.com/understanding-block-formatting-contexts-in-css/
  3. MDN, Block Formatting Context,
    https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Block_formatting_context

Margin Collapsing

Margin Collapsing is one of those CSS head scratchers that I mentioned in the block formatting context section. I discovered this quirk while giving a live presentation on web design for beginners. I was telling the audience how simple it was to create a nice layout with a background image in the header, a navigation menu that sits on top push a few pixels from the top of the web page with CSS margins. Below is an example of this scenario, which you might run across as well.

The goal was to move the navigation menu down half the height of the header background in order to appear vertically centered (50px).


.navigation {

margin-top: 50px;

}

The above code-block is what the “obvious” choice of CSS would be, but guess what the actual result was:

Actual

Expected

The actual result is due to the CSS rendering quirk known as margin-collapsing. Simply put, margin collapsing is when the top and/or bottom (vertical) margins of two elements in the same block formatting context merge as one. The W3C lists all of the scenarios in which margins collapse, but there are two major cases that you will most likely run across: adjacent siblings and parent-child block elements. In our case above, we are dealing with the latter. There are multiple fixes to prevent margin collapsing. I will list a few, but there you can find more by following the links in the reference list below.

The overall solution is to break one of the cases that causes margin-collapse such as creating a new box formatting context, which separates the parent’s context from the child’s. The full list can be found in the W3C’s section covering margin collapse.


Margin-Collapse Cases

  1. The top and bottom margins of in-flow siblings.
  2. The top and bottom margins of a parent and it in-flow children.
  3. Empty blocks if there are no border, padding, height, or min-height that separates a blocks top and bottom margins

Solutions

  1. Use padding in either the parent element or child element instead of margin on the child element.
  2. Set the parent’s to overflow value to something other than visible (hidden, auto, scroll, etc).
  3. Set either the parent or the child’s position value to absolute (position: absolute)
  4. Set either the parent or child element’s display value to inline-block (display: inline-block)

References

  1. MDN, Mastering Margin Collapsing, https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Mastering_margin_collapsing
  2. Adam Roberts, Collapsing Margins, https://www.sitepoint.com/web-foundations/collapsing-margins/
  3. Joe Seifi, Understanding & Taming Collapsing Margins in CSS, http://www.seifi.org/css/understanding-taming-collapsing-margins-in-css.html
  4. W3C, Collapsing Margins, https://www.w3.org/TR/CSS2/box.html#collapsing-margins

6 Unsuspecting Problems in HTML, CSS, and JavaScript – Part 3

Finally, we arrive at part 3 of our three part series covering six unsuspecting problems in HTML, CSS, and JavaScript, and their solutions. In the previous part of this series we covered two concepts that will help make a noticeable performance improvement in your application: DOM reflow and event delegation. In this final part of the series we will cover two common scenarios involving layouts: horizontally and vertically centering a DOM element, and creating a table with a fixed header.

Horizontally & Vertically Centering an Element

You’d think this would be a straightforward task, but surprisingly this is not as simple as the name implies. Vertical alignment in particular is tricky because CSS’s vertical-align style only works for table-cells and inline-block elements. I ran across this problem when designing the DatePicker used in the Eventbrite Design System (EDS). The DatePicker is a calendar where each row is a week, and each day in the week is the shape of a square. The numbers representing that day of the week needed to be vertically and horizontally centered.

 

Eventbrite Design System Calendar

 

There are many ways to center elements, and all come with their drawbacks. To choose the correct combination depends on the use case.

Solutions

  1. Add equal padding to the top, right, bottom, left sides of an element.
  2. Horizontal: Place a wrapper div around a group of children and set the text alignment value of that parent div to center. Child elements must either be inline or inline-block elements with a set width.
    Vertical: Set the parent wrapper’s display value to inline-block, its vertical-align value to middle, and its height.
  3. Horizontal: Have a wrapper div. Explicitly the child element’s width, then set the margin property of that element where its top and bottom margins are 0 and the left and right margins is set to auto (margin: 0px auto).
    Vertical: Set the parent wrapper’s display value to inline-block, its vertical-align value to middle, and its height.
  4. Vertical: Nest three divs, and set the two outer div class names to table, cell respectively. In CSS, you will set the styles of each of these class names to display: table and display: table-cell, respectively. Table cell elements have access to the vertical-align property, so add vertical-align: middle to the parent whose display value is set to table.
    Horizontal: For the third nested div, give it a fixed width, and set its margin to margin: 0px auto.
  5. Horizontal: Given a div, set its dimensions to an equal width and height. Set its text alignment to center if it’s the child is text-only. If the child is another div then you can fix its width and give it a margin of margin: 0px auto.
    Vertical: Set the line-height value to equal the height of the div.
  6. Use Flex boxes.

For EDS’s DatePicker, I used solution #5. This will be backwards-compatible with most old browsers. Now that we are mainly offering support for modern browsers, it’s a safe bet just to use CSS3 flex boxes, which was made to avoid hacking solutions for layout quirks presented in CSS.

Reference

  1. MDN, Using CSS Flexible Boxes

Fixed Table Header w/ Scrollable Body

Live Demo

Source Code

Here is one last tip to out maneuver those pesky browser quirks that make you think, “Why wasn’t this functionality added in the first place?” If given the task of creating a table that will eventually be populated with data that spans more than the height of your browser window or at least the height of some design requirement, it would be nice to be still able to see the column headers as you scroll down the long table of data. One would think this would be trivial.

My goal was to create a table with a fixed header and scrollable content where the table could be positioned anywhere on the page, and no JavaScript involved. A live demo can be found on the JSFiddle link, and the source code is available on both JSFiddle and Github.

There are multiple solutions to achieving the desired effect, and each having their drawbacks. I will explain the approach I took. Ironically, to have a fixed header, I never used the CSS position: fixed style. In most cases, position: fixed is the go-to solution for giving elements fixed positioning in the user’s window. Unfortunately for our use-case, it breaks child elements from the flow of their containing parent making its positioning relative to the window rather than the parent. This would be a problem if I wanted to move the entire table as a group.

Fixed table header diagram

The secret to this technique is to use two separate tables instead of one. The header row that contains the title of each column is one table, and the actual body of data is another table. Since we want the final table to be grouped together allowing it to be moved
across the page as one unit, I wrapped both tables in a div (black dotted line).

Now, to the main task of fixing the header to the top of the wrapper div. I could not set the header table to position: fixed because it would cause the header to break from being contained by the wrapper div as explained earlier.

I needed the header table to be at the top of the page, and the body content to flow past it without the header it self moving. This can be done with position: absolute. Set the header to position: absolute causing it to align itself at the top of its parent container. I needed to set the wrapper div’s positioning to position: relative in order to force its absolutely positioned child’s left and top margins to 0 align relative to the parent div and not the browser window. Absolutely positioned elements are no longer apart of the natural flow of the pages layout or its containing box; therefore, not matter how it’s sibling or other elements on the page move it will not move. Viola! We now have a fixed table header.

Now, that the hard part is out of the way, we need to make the data in the table body scrollable. In order to make scrollable content in HTML, we can make use of the overflow: scroll style. For the data body, I created a second table element. I wrapped the second table inside a wrapper div (red solid line). In order for the overflow: scroll style to activate, I needed to set a fixed height on the body wrapper div. Whenever it’s child (data table) overflows it, the scroll bar will appear.

Now, we need to properly vertically align the data table with the header. Since the header is absolutely positioned, the top part of the data table will render beneath the header. It would be best to set a fixed height on the header, and place a margin-top styling on the data table equal to the height of the header. This will vertically align the top of the data table just below the header revealing all of the data rows that were once covered.

The last major problem that needs to be addressed it ensuring the width of the header columns equally align with the width of the columns in the data table. The header table should have the exact same number of columns as the data table, and each corresponding column between the two tables should have the same width.

This is the gist of everything. The rest is styling to the final product look appealing. Take a look at the source code linked below to see the full implementation, as well as the demo. Thanks for following along this tutorial series, and hopefully a few more tools were added to your tool belt. 

Live Demo

Source Code

Cowboys and Consultants Don’t Need Unit Tests

As a developer, my understanding and respect for software testing has been slow coming because in my previous work I have been an engineer and a consultant, and in these roles it wasn’t yet obvious how important testing really is. But over the past year I have finally gained an appropriate respect and appreciation for testing; and it’s even improving the way I write code. In this post I will explain where I’ve come from and how far I’ve traveled in my testing practices. I’ll then list out some of the more important principles I’ve picked up along the way.

Engineers are cowboys … and cowboys don’t need no stinkin’ tests.
I got my start as an Aerospace engineer. And as an engineer, if you do any programming at all, testing is probably not part of it. Why? Because engineers are cowboy coders. As engineering students, we are taught just enough to implement whatever algorithm we have in mind, make some pretty graphs, and then we graduate.

It wasn’t much better at my first job. I had shown an interest in software development and so, in one particular project, I was given the task or reworking and improving the project codebase. We were developing autonomous aircraft control algorithms and it soon became apparent that after months of work, no one had thought to run the simulation using different starting conditions. After finally trying different starting conditions we found that our control system was generally better at crashing the plane rather than flying it. This should have been the biggest hint in my early career that testing might be important. But it would still be quite a while before I learned that lesson.

Continue reading

Isomorphic React Sans Node

React is JavaScript library for building user interfaces that has taken the web development industry by storm. Its declarative syntax and DOM abstraction for components not only make client-side development simple, but also enables server-side rendering of those same components, which enables improved SEO and initial browser load time. But how do you render JavaScript React components server-side if your backend doesn’t run on Node? Learn how Eventbrite successfully integrated React with their Python/Django backend so that you can do the same in yours.

React + ES.next = ❤

JavaScript is evolving quickly. The ES6 specification was released in 2015 and is quickly being implemented by modern browsers. New versions of ECMAScript will now be released on a yearly basis. We can leverage ES6 and functionality slated for future versions right now to write even clearer and more concise React code.

Experience with React will help you get the most out of this session, but you don’t have to have a JavaScript black belt to leave feeling confident in using ES6 with React. Senior Front-End Engineer Ben Ilegbodu covers how to write cleaner code using the new spread operator, classes, modules, destructuring, and other tasty syntactic sugar features being introduced into ECMAScript. Oh, and don’t worry if you don’t understand all of those terms — you soon will after this video.

The Elevator Pitch from a Data Strategist

When people asked what I do for a living at conferences or parties, I told them I run data strategy. Their first response was “oh, that’s cool”. Then they paused for a moment and asked “what do you do exactly?”

After spending fifteen minutes explaining all the aspects of my job, I either totally confused my audience or bored them to death.

So I set out to develop an elevator pitch, something as punchy as “I am a photographer who specializes in marine life”. I thought I could get some help from online job postings. Searching “data strategy” on LinkedIn returned 84 listings. Few of them described what I do. By contrast, the search on “data scientist” returned 40 times more results.

I was not hired per a job description. I was lucky to convince Eventbrite to create the role for me.

My argument was pretty simple: think of all the data-related challenges the company faces, how many of them are technical, how many are organizational?

Most data-driven organizations have the following data pipeline.
Data Pipeline

These functions are owned by different groups. Many problems arise from the lack of cross-function understanding of data. For example, analysts complain about the variations of a single metric. They feel they have little influence over the engineering team to impose consistent tagging. Engineers, on the other hand, complain about analysts’ incomprehension of the technical complicity.

Such friction can be reduced by someone who operates on the “full stack” – someone who has the domain knowledge in each area, as well as the organizational skill to connect the dots. Data strategist is one of those people.

Data strategy development reverses the data pipeline. It starts by asking what data and insight are critical to the business’s short, medium, and long-term growth. Though the cost of storing and processing data gets cheaper, the cost of generating insights increases as more and more operations become data driven. Data strategy should be aligned with the business strategy, prioritized to address the biggest opportunities and highest risks. First, data strategist thinks like a business operator.

Business opportunity for a web-based eCommerce company can be developing mobile user experiences (both mobile web and app). Increasing competition from mobile-only competitors poses significant risk. Data strategist, together with engineering and analytics, decides on the success metrics to measure the new mobile products. The metrics are then translated into data needs; and data needs into technical requirements for tracking. Data strategist can help to enforce the consistency across devices, so user experiences on different platforms can be compared side by side. Data strategist, secondly, is an analyst. She or he understands what questions to ask; and how data becomes metrics and then insights.

Once the mobile products are available, marketing decides to launch a few mobile campaigns. One of the campaigns is a banner on the homepage, encouraging web users to download the app. Marketing would like to know the effectiveness of this campaign compared to another campaign they purchased from an app ad network. This request poses some real technical challenges. The traditional cookie based web tracking no long applies to app. Data strategist works with engineering to explore the technical workarounds, and evaluates external tools that may provide a solution. She or he also partners with legal to make sure the privacy policy is updated. Data strategist, thirdly, is a technologist. The technical knowhow helps to make tradeoffs; avoiding making data collection a burden on the engineering resources.

Multiple functions, competing priorities, tight resources, various teams touching one data point…data strategy cannot operate unless cross-function processes are established. A company-wide data roadmap is an example of such process. Data strategist, fourthly, is an organizer.

Lastly, data strategist is a communicator. She or he is the broker of domain knowledge from one function to another. She or he funnels the downstream constraints to the decision makers; and translates the overall strategy down to individual data stakeholders. She or he champions for the investment in data infrastructure and personnel. When issues arise, she or he assembles a team and coordinates the efforts. Best practices are shared, training held to distribute the understanding of data evenly across the organization.

If I have to summarize all these responsibilities into one sentence, I’d say my job is to help organizations managing their data assets, and finding the best ways to surface insights from the data. Still not as punchy as the underwater photographer. For the fellow data strategist out there, if you have a better version I would love to hear it!

Engineering + Accounting for Marketplace Businesses

Eventbrite Principal Product Manager Ryan D’Silva and Chief Architect Adam Sussman cover how there’s a deep product need where engineering and finance meet, particularly if you’re a marketplace. While there are solutions available, none do the job particularly well and most marketplaces have built their own solutions at great cost. We’d like to shed some light on the problem and share what we’ve learned so far.