User analytics for your Rails app, with Ahoy

Google Analytics provides solid, aggregate statistics for your Rails app. It answers questions like, “How many visitors do I receive a day?” and “Which parts of my app are most popular?”

It cannot track individual users over time, however. Questions like, “How long does the average user remain active over time?” or “How long does it take the average user to go from a free to a paid account” require user analytics.

Services like Mixpanel and KISSMetrics specialize in user analytics, offering robust tracking and reporting for a fee.

There is another option, a free, open-source Ruby gem (technically, a Rails engine) called Ahoy. In just a few minutes, you can have robust user analytics for your Rails app.

Let’s walk through an example; say that on our site we want to track visits and actions for each user.

First, install Ahoy and perform the post-installation steps. This takes only a few minutes.

Track visits

Visit tracking starts immediately after you install Ahoy. You can customize the length of each visit (i.e. after how long does one visit turn into two); it defaults to 4 hours.

Ahoy automatically ties each visit to a user. You not only know how many visits you receive each day, but which users visit the most. Already, we have user analytics.

Track events

Users do stuff in your app. If you have a todo list app, for instance, they add todo items. In modern-day apps, user actions may be processed on the server with Rails and/or on the client via JavaScript.

Ahoy lets you log user events in your Rails code or your JavaScript code.

For instance, if a user adds a to-do item on the front-end, log it with JavaScript:

If the user takes an action handled by your Rails code, log it with Ruby:

Reporting

Ahoy does not provide a dashboard for reporting, though it’s in the pipeline and they offer advice for building your own.

Third-party services vs. Ahoy

Mixpanel and KISSMetrics offer advanced reporting out of the box, but have a cost and require you to send your user data to a third party. If you choose to leave either service, extracting your data in a useful way is difficult.

Ahoy is free and your data stays local, but you’ll spend time creating a stats dashboard and reports.

There is no right answer, but while evaluating user analytics tools, be sure to consider Ahoy alongside the paid options.

The Engine Yard and Rails Survival Guide

Here are some hard lessons I’ve learned maintaining a Rails app on EngineYard. It’s an extremely reliable product with great support, but there are a few nuances. I’d love to save you time by telling you these up-front. I’ll update this over time.

First of all –

  • Do you host your app on GitHub? If so, link your GitHub account to EngineYard for breezy deploys. When we want to deploy, we click Deploy right from the EngineYard dashboard and it pulls our latest master from GitHub.
  • Hop onto your repositories by SSH on your computer, just to get that initial configuration out of the way. Use the “automated SSH link” discussed in the link.
  • Learn how to access the Rails console from SSH
  • Install the Engine Yard CLI.  You’ll need it to deal with some failed deploys.
    • Type gem install engineyard into the terminal if you’re on a Mac

Dealing with a failed deploy

  • Look at the log file.  If you’re lucky, you’ll see a message containing the word “relax.” This means that the deploy failed early enough to not affect your application.  Find the issue in the log and solve it.
  • If your application has the Engine Yard maintenance page up and it won’t away, use the CLI to get out of maintenance mode.
    • Type ey web enable into the terminal if you’re on a Mac

Learn how to clone your environment

We’re going to set up a staging server for Cook Smarts, and I’ll post about that. In the mean time, read over the cloning guide.  A couple of gotchas:

  • You may need to request an additional IP address if you don’t have any available, which you can do by clicking the + button near a region on this page
  • Remember to snapshot your environment right before you clone it. The clone takes your app and data from the latest snapshot.
  • Reasons to clone: you need a staging environment, or you need to test something quickly before you put it online.

Consider a staging environment, maybe

Do you need a separate staging server? Decide whether you want to keep it running all the time or just when you need to test new functionality. Choose a cheaper configuration for your staging server, particularly if you keep it running.

At Cook Smarts, we keep a separate staging environment but only have it on when we need it. This saves a significant amount of money.

Know what to do if you get this scary e-mail

We have received the following notification from Amazon that one or more of your Engine Yard Cloud instances may be affected by a maintenance period

Ack! What? These are rare but scary messages. They link to these horrifically named Replace Degraded Instances help page.

My only advice on this: clone your environment, and then test everything you are going to do to your production environment on the clone. This saved us.

More to come as we learn more…

Rails and external services: allow for failure

At Cook Smarts we rely on external services for payments, image processing, and more. Sometimes, the app will fail to reach a service. Perhaps the service is down or there’s a network error somewhere along the line.

How can we tolerate such errors with a minimum impact to the user?

Here’s an example of how we addressed a recurring error with an external service:

A user can export a recipe as a PDF, including an image of the meal.* We retrieve the appropriately-sized image form reSRC, our external image processor.

PDF exported recipe from Cook Smarts

Occasionally, the connection to retrieve the image times out, preventing the image from importing into the PDF. Before, this caused an exception, preventing the user from exporting the recipe at all.

For a better user experience, we now show a friendly error message in place of the image.

Exported PDF recipe from Cook Smarts with image error message

To show the friendly error instead of a fatal exception, we use ‘begin’ and ‘rescue’ in Ruby, in the midst of our Prawn PDF code.

Fault tolerance is crucial when using external services. Assume that your app and the services will clash sometimes, and plan accordingly.

* Eventually, we’ll cache these PDF’s, but for now they are generated whenever a user requests them.

A smarter nutrition label for the web

Ah, the humble nutrition label. Since it was introduced in the 1990’s (in the U.S., anyway), it’s been pretty much ubiquitous. We see them everywhere, whether we understand them or not.

They’re particularly puzzling on foods with multiple ingredients. Looking at a nutrition label and an ingredients list side-by-side, you might guess which ingredients contribute the most to each nutrient, but you may be wrong.

Why am I talking about nutrition on a web development blog?

We implemented nutrition labels for Cook Smarts meal planning app, and put a twist on the classic. In addition to showing a nutrition label for every recipe, we show which ingredients contribute the most to each nutrient.

For instance, below are the nutrition facts for Orange-Sesame Beef Stirfry. By expanding the total fat, I can see that the #1 and #2 contributors are the flank steak and the cooking oil.

If I were counting carbs, I could expand total carbs and perhaps cut back on the rice.

Nutrition label shows which ingredients contribute most to each nutrient

Since we integrated the USDA’s robust nutrition database into Cook Smarts’ recipe editor on the back-end, we had this per-ingredient data. Instead of just exposing the recipe’s total nutrition facts, we tried to think of ways to go a little deeper. This is our first attempt at doing so!

The USDA database is huge, so we brought it onto a separate server that we interface with using our own API. It’s working well, and keeping the extra load off of Cook Smarts’ primary app server. More on our first attempt at service-oriented architecture soon!

Special thanks to Chris Coyier for his nutrition label HTML and CSSMatt Beedle for his USDA nutrient database gem, and Cameron Dutro for his Active Nutrition gem.

Sending Mandrill e-mails from Rails, the MVC way

Update: For updated guidance, see E-mail in Rails with MailChimp and Mandrill, a comprehensive guide

Mandrill is a transactional e-mail service for developers. It allows you to quickly reach out to users from your app via e-mail, through SMTP or Mandrill’s  API.

Cook Smarts‘ transactional e-mails sometimes go to many users at once, and we quickly hit the limits of SMTP. It was time to use Mandrill’s API to send out e-mails from our Rails app.

Here’s how we moved from ActionMailer/SMTP to Mandrill’s API while staying true to the model-view-controller (MVC) nature of Rails.

Install the Mandrill gem

Add the Mandrill API to your gemfile.

Then run ‘bundle install’ from the same directory.

Send e-mail

Want the simple version of the code needed to send a message? Check out Mandrill’s documentation.

Below we’re going to cover Cook Smarts’ more complex use case.

We specify the subject, from name, and from e-mail above, which is pretty self-evident.

But – surprise! – we’re sending this particular e-mail to a ton of users at once, and we want to address each user by name.

Addressing the message

This message is going to all users with a subscription. We have a scope in our User class called ‘paid,’ which returns all the paid users.

We need to get these users’ e-mail addresses into an array for Mandrill. A class method, User.to_mandrill_to, takes care of this.

When we call ‘User.to_mandrill_to(User.paid),’ we get all our paid users’ e-mail addresses back as an array.

Merge tags

Mandrill uses merge tags to personalize messages. For instance, we want to say “Dear Mary” if the message is to Mary, and “Dear John” if it’s to John.

When we send multiple messages at once, we need to tell Mandrill which name is related to which e-mail address.

Our e-mail template, stored in a Rails view, contains a placeholders for the user’s name:

Another class method, User.to_mandrill_merge_vars, associates each user’s e-mail address with their first name:

This gets us the value we need for the ‘merge_vars’ argument of the API request above.

The message

As stated earlier, the e-mail template lives as a view in our Rails app.

We’ll use render_to_string to process the template and insert it into our API request.

The view should be a full HTML page, including and tags. We add ‘:layout => false’ to avoid bringing in other header/footer content from our app.

Avoid an embarrassing mistake

Remember to include ‘:preserve_recipients => false’ in your API request, unless you want all the people you’re e-mailing to appear in the To line in every message. Mandrill has the details.

MVC Summary

Our Users model provides the addressee information, the meal plan e-mail template/view provides the message, and the admin controller sends the actual e-mail.

All of this without the use of SMTP or Rails ActionMailer – just Mandrill’s API.

We’ve found that this solution has worked well for transactional e-mails with multiple recipients.

If you’re looking for tight Mandrill + ActionMailer integration, check out the Mandrill delivery method gem.

We’re starting a series called Mailing on Rails, which will cover all the bases to get you up and running with mail in your app. Want us to let you know when it’s up?

Gorgeous before-and-after pictures in WordPress

TwentyTwenty from Zurb makes it easy to show before-and-after pictures on a web page. As Zurb puts it, it showcases the differences between two images.

Now, it’s available as a WordPress plugin! Building it was fun, and I’ll post a plugin development tutorial soon based on the experience.

Here’s one example, the Blue Room in White House pre and post construction:

Images above courtesy Abbie Rowe / National Archives

And a makeover from a previous post on this blog:

Check out TwentyTwenty on the WordPress plugin directory, or watch this screencast to see how it works:

New: see a tutorial in Spanish, thanks to webempresa

Responsive images and the beauty of food

Food is beautiful, and Cook Smarts has plenty of it to show. The service provides a meal plan each week, with high-res photos of each meal.

The Cook Smarts archive, where you can view previous meal plans, did not take advantage of the pictures. It was far too text-y.

The old, text-based archives
The old, text-based archives

We started to think of a better way to incorporate the photos, and came up with a design for each week of meals.

Sketch of the new visual archive

We also thought of a more engaging way to welcome people who were trying out the service, with a personal message from Jess.

Sketch of call to action

Here’s how it actually came out:

New, visual archives

We faced a lot of challenges putting this together. Here are a few, and we how we solved them:

Respecting the user’s bandwidth

It was important to minimize load time, particularly for mobile users.

We used reSRC to serve the appropriate image size for each device, without having to generate thumbnails ourselves.

It saved a ton of time, and I encourage graphics-heavy site owners to check it out. Here’s a screencast showing reSRC in action.

Adjusting for mobile

Four images in one row would not work on mobile, so we went from four columns to one.

But the images were too tall. One meal took up nearly the entire iPhone screen, making it time-consuming to scroll through all of the plans.

Tall images make it time-consuming to scroll through meal plans on mobile

Too much scrolling!

Then someone had a genius idea: on mobile, show a slice from the middle of the image. You still got the idea, with far less scrolling. You can see the full image after clicking the meal.

Center-cropped images make it faster to scroll on mobile

By adding a simple parameter to the reSRC image URL, we cropped the images with the result above.

https://app.resrc.it/s=w400/c=w400,h133/http://cooksmartsapp.s3-us-west-2.amazonaws.com/meal_photos/20130115-FishTacos-04.jpg

In the reSRC image URL, we set the image’s width to 400px, and took a 133px slice through the middle of it.

Surely, we could also have done this with a tool on our server like ImageMagick, but using reSRC was faster than rolling our own thumbnails.

Showing different images on desktop and mobile

We had to find a way to load different images on desktop and mobile, in order to achieve the crop described above.

Image tags don’t support image swapping without JavaScript, so we instead used containers with background images. We applied media queries to the containers to serve a different background image depending on the screen width.

The default image is regular size:

The mobile image is center-cropped version:

Separate CSS for each image

Each meal needed a separate background-image style. That’s a lot of styles!

In Rails, we dynamically generate the style tags and place them under a <style> tag on top of the archives.

At first, we tried a separate <style> tag for each image, but this bombed on IE 9 and below, which place a limit on the number of style sheets and tags.

Making the image fit its background container

Our site is responsive, so the image widths change based on the user’s screen size.

With regular image tags, you can simply say…

… and they will scale to their containers.

Background images are a little different. We had to use…

… on the meal containers, in order for the meal images to scale properly.

To support older browsers, we included the background-size polyfill, and confirmed that everyone worked well using BrowserStack (not cheap, but excellent).

Preventing jumping around while loading

Images won’t load right away, particularly on a phone.

Unless you specify the width and height of an image in advance, the page will jerk around as each image loads.

We don’t not know the width and height of the image in advance since the site is responsive, but we still wanted to avoid page jerk.

We do know the proportion of the photos (the relationship between width and height), so we used the padding-bottom technique from Smashing Magazine. With this technique, knowing the proportion has the same effect as knowing the exact width and height, leaving the proper amount of room for the images before they load and eliminating page jerk.

On desktop:

… and on mobile, which is a bit different since we’re only taking a center crop:

To get the proportion (the % above), we divided the height by the width and multiplied by 100. The proportion is always the same no matter the image’s width.

In closing, content is paramount

Web projects are much more achievable when the content is great. In this case, I was lucky to have beautiful pictures of food. Had Jess not taken pictures of every Cook Smarts meal from the beginning, the visual archives would not have launched as quickly.

Want a screencast about the techniques above? Please leave a comment and let me know, or tweet me @coreyITguy.

To see the archives in their glory, sign up for a test drive account on Cook Smarts.

Full text search with Rails and Postgres, across multiple tables, quickly

This screencast shows how to make your Rails + Postgres app searchable, even with relational data across multiple tables.

This is based on the method outlined by thoughtbot.

There is also a GitHub repository, with the app we build in the screencast.

By the way, I have no idea the plural of a database field index is “indexes” or “indices,” as you can tell in the screencast!

Resources:

Responsive images made easy

When redesigning the Cook Smarts meal planning app, we knew we had to handle images in a smarter way. Pictures of food are very important to the site. They make it easier for people to navigate to familiar dishes, and give an idea of what to expect when cooking them.

We have hundreds of high-res images stored on Amazon S3. We were missing two things: thumbnail-sized images, and a way to determine which size image to serve based upon the user’s screen size.

reSRC took care of both of these needs for us. It is a service that sits between your high-res images and your users, scaling down your images to fit the users’ screens. We simply inserted the reSRC JavaScript, and that was about it.

I’ve prepared a screencast to show you how easy it is to implement reSRC.

Note: Here we are using Chrome’s JavaScript console to bring in reSRC. In the real world, you would place reSRC’s JavaScript into your code directly.

Plug-and-play solutions like this make it easy for any web site to use responsive images, without coding. We may eventually generate our own thumbnails and serve the proper sized images through media queries, but reSRC allowed us to go responsive with our images in less than an hour, for about $30/month. That is pretty remarkable.

For more possible solutions, check out Smashing Magazine’s article, Choosing a Responsive Image Solution.

Responsive, interactive video links

This is the first in a series of articles about the Cook Smarts redesign.  Try their meal plan service to experience the redesign for yourself.

The recipes on Cook Smarts include videos that explain techniques such as seasoning and tenderizing chicken, quick-cooking potatoes, and chopping eggplants.

Prior to the redesign, the videos were linked within the text of the recipe, bringing the user to the Vimeo page in a separate tab. On a phone, looking at a very quickly was a bit difficult, requiring switching back and forth between tabs.

We looked for a smoother way for people to enjoy videos, and found a few techniques that helped.

Label video links

We added a video icon after each video link, using a bit of CSS and FontAwesome.

a[href*='vimeo']:after, a[href*='youtube']:after, a[href*='youtu.be']:after {
content: "\f03d";
font-family: FontAwesome;
font-weight: normal;
font-style: normal;
display: inline-block;
text-decoration: inherit;
padding-left: 4px;
padding-right: 3px;
font-size: .9em;
}

This bit of code looks for a link to a YouTube or Vimeo video, and adds a video camera icon next to it. Screen Shot 2013-11-10 at 12.45.49 AMShow the video immediately, without leaving the page

Opening the YouTube or Vimeo page in a separate tab was a waste of the user’s time. Instead, we used FancyBox 2’s  media helper to open the videos in a modal popup.

When the user clicks a video link, the video pops up in the same page and immediately starts playing.

Video playing in a FancyBox 2 modal window

We added this functionality purely with JavaScript.

First, we add a class called fancybox-media to all video links. In the future, we may do this in the back-end rather than on the client, but this was much faster and takes care of past, current, and future recipes.

$('a[href*="vimeo"], a[href*="youtube"], a[href*="youtu.be"]').each(function() {
$(this).addClass("fancybox-media");
});

Next, we tell FancyBox to open a video popup when someone clicks on a link with the fancybox-media class.

$('.fancybox-media').fancybox({
openEffect : 'none',
closeEffect : 'none',
helpers : {
media : {}
}
});

That’s it!

Closing thoughts

The goal of this was to make video more seamless for the user. It works on desktop and mobile, thanks to FancyBox’s awesomeness and Vimeo’s and YouTube’s mobile support.

Embedding the videos on the page itself was of course another option, and we may still do that. But clearly-marked video links in the recipe, which do not require the user to leave the page, seemed to be a clear next step.