We admit it: mistakes were made.
The front end of Reverb for Publishers (RFP) is a JavaScript application that can display links relevant to the page you are viewing, concepts derived from the current page or recent trending articles on your site. This is powered by Reverb APIs which ingest the site content, analyze the text, provide recommendations, and monitor traffic. The bulk of our users are running WordPress powered sites but you can install this free plugin on any platform.
While RFP is now highly performing and increases page views by presenting related links on thousands of sites, we did do some dumb things during development. Here’s what not to do when creating an application that’s supposed to run in someone else’s webpage.
Don’t require interaction
Initial versions of our application had fancy interactivity we thought was inviting. We tested several radically different designs which required rollover to bring up more details or had stuff following you around the screen on the sidebar.
But when we gathered usage statistics the results were clear: the simplest implementations always won. It’s better to display all the information cleanly right away and not expect to entice viewers to mouse over or interact in any way for more information.
Don’t expect users to use configuration options
We built a lot of optional functionality into our application which could only be accessed via administration screens. Tracking the usage of this showed us that it was extremely rare for people who installed our widget to even open the configuration options much less experiment with all the extra functionality we made available.
The lesson learned here was that we could please finicky customers by providing advanced features but with new installs you live and die by your default configuration. Most people will just evaluate your app on those features and uninstall if it doesn’t fulfill their expectations.
Don’t think your in-house testing has any relation to real user experiences
When we started monitoring the aggregate speed of our application on real users, the results were shocking. Our little widget was reporting a load time of several seconds which we never noticed during development or in-house testing on live sites. Instrumenting the code execution path exposed some serious bottlenecks we had created.
One assumption we made was that jQuery was probably installed on a lot of the sites so the first thing we did was check for a relatively recent version and only load it if necessary, delaying subsequent code execution until it was available. We saw this process adding over a full second to the load time in aggregate real user data. Any synchronous operation like this caused a visible delay in our aggregate load time data.
We started by using Mixpanel for reporting which was a really nice way to be able to record and view the data in real time. We eventually moved to an in-house solution when we were able to reproduce the important Mixpanel features so we could report directly to our APIs and could remove the Mixpanel library from the client side code we were delivering to everybody.
Don’t depend on way too many libraries
The initial version of our application included several open source libraries which allowed us to develop features quickly. But when we got serious about performance, we found that removing all these libraries allowed us to reduce total app size by 70%. Admittedly we went overboard during early development including not only jQuery but Atmosphere, Backbone, Underscore, etc. We still use EJS style templates but we precompile them during our build process and then no longer need to include a templating library in the client side code.
In order to support our target browser set (Android 2.3+, iOS4+, IE8+, last 3 versions of FF and Chrome) after dropping jQuery we needed to change our selector syntax to use querySelector instead of $:
element = document.querySelector('.wordnik_discovery');
In order to support IE8 which still represents 5% of traffic we need handle lack of addEventListener:
addEventListener: function(el,eventType,handler) {
if (el.addEventListener)
el.addEventListener(eventType, handler,false);
else if( el.attachEvent )
el.attachEvent ('on'+eventType,handler);
}
}
Don’t use defenseless CSS
Our design strategy with our widget was to let the host site’s styles shine through so we made sure not to override the colors of anything or type attributes. This worked pretty well and we were able to fit into a variety of designs smoothly. There were of course some styles that we need to be able to control and we were careful to tie important layout features like the float layout of template classes back to an ID reference for maximum specificity. But we weren’t careful enough. Site owners will do some things that even in retrospect seem difficult to have anticipated:
a { white-space: pre-wrap; }
This seems like a pretty strange rule but we actually encountered a site with this applied. Here is an example of the consequences. I overrode the pre-wrap with white-space:no-wrap on the middle item:

Don’t expect users to install updates
Although WordPress users are presented with update notifications when they view their plugins and updating is a one click process, a significant percentage of our userbase has better things to do with their time. In order to actually fix problems we encountered we designed our widget to load the main application code from our servers asynchronously on domready so we were able to push updates to our entire install base.
Don’t deliver unnecessary templates
Fully JavaScript-powered apps are able to take advantage of beautiful templating engines, but they usually deliver all the possible templates to the client whether or not they get used. In our case we were delivering all the optional templates when we knew a site could only choose a single display option per widget.
To avoid delivering unnecessary JavaScript template code, we’re currently moving towards the API response providing HTML fragments instead of pure data in a JSON object. Shifting the creation of the HTML fragment to the server allows us to slim down the delivered JavaScript app code by removing all previously client side templates. This would have created some difficulties if we weren’t able to use similar js templating code server side, but we are able to execute Mustache in a variety of languages and can get even better templating options by using Node.js to transform EJS style templates which provide the flexibility I personally find most comfortable.
Don’t have insufficient JavaScript encapsulation
WordPress can be a bit of a bad neighborhood front end wise so it is a wonderful place to see how your code will fare in unusual situations. It is not uncommon to see JavaScript errors caused by WordPress plugins on live sites whether from the plugin’s front end code, or a mishandled configuration. We were pretty careful to do no harm to the sites where we were installed so we didn’t add to the confusion. I’m not saying we were blameless but we followed recommended practices to keep our JavaScript unobtrusive. Everything is wrapped in an immediately executable function and our app is a single global object with all the required functions attached to it.
(function(){
var WRC = window._WRC = { version: "0.6.5"};
_WRC.extend(_WRC, {
DOM: {...
})()
[Photo Credit: CC BY 2.0 by velvettangerine]
{ 0 comments }












