Avatar photo

How We Used Keen To Change The Way People Measure Their Content

This is a guest post written by Kris Ciccarello, co-founder and CTO at Beegit.

At Beegit, we are driven by one question: How can you manage your content development process if you can’t effectively measure it?

To answer this question, we created a platform that lets people write, organize and communicate inside a single web application. But to further increase our customers’ content intelligence, we needed a way to provide easily-trackable metrics on the activity and efforts required to produce their content.

Building analytics for our customers

From the start, we wanted to give our customers insights into the content creation process, answering questions like: How much time does it take to write a post? How many rounds of revisions does it require? How many collaborators?

This meant we needed to capture unstructured data as people were writing in real-time. The challenge was that this data didn’t exactly fit inside our app’s primary data store. But we knew it would be a resource we and our customers could learn from.

After conducting some research, we had the following options to pick from:

  • Build an in-house solution
  • Use an off-the-shelf solution
  • Use Keen IO

The off-the-shelf solutions were too generic for our needs, and building our own was going to remove too much focus from our app development. We ultimately decided on Keen because it had the right amount of customization and the ability to handle our incoming events right away, at scale. Additionally, we got a nice freebie: Keen included dead simple query and visualization libraries that had us not only storing, but sharing our data with customers from our UI within a couple of days.

How we implemented Keen

Since we were using Node.js and already had winston set up to handle our logging and activity events, we made a transport for Keen IO and started sending events.

Here’s the gist of our Keen IO transport for Winston:

var Keen = exports.Keen = function(options) {
  this.name = 'keen';
  this.level = options.level || 'info';
  this.keenClient = keen.configure({
    projectId: options.projectId,
    writeKey: options.writeKey
  });
};

winston.transports.Keen = Keen;
util.inherits(Keen, winston.Transport);

Keen.prototype.log = function (level, msg, meta, callback) {
  this.keenClient.addEvent("api", {
    "level": level,
    "msg": msg,
    "meta": meta
  }, function(err) {
    if (err) {
      console.log("Adding keen log event failed");
      return callback(err, false);
    }
  });

  return callback(null, true);
};

Once we had the events shipping to Keen, we started providing customers specific information about their writing data using keen-js.

Keen Post Metrics User

Simple filters let them see aggregate and user-specific metrics about their time spent writing and file activity (words added and deleted).

Here’s an example of how quickly we were able to start showing our customers how much time they were spending daily in their content projects, both in aggregate time and grouped by user (example shows data for past 7 days).

function showTimeChart(projectId, scopedKey) {
  var keen = new Keen({
    projectId: projectId,
    readKey: scopedKey,
    protocol: 'https'
  });

  function prepareTimeQuery(options) {
    options = options || {};
    options.useGroupBy = options.useGroupBy || false;

    var keenOptions = {
      eventCollection: "user_content",
      targetProperty: "edit_session.duration",
      interval: "daily",
      timeframe: "this_7_days"
    };

    if (options.useGroupBy) {
      keenOptions.groupBy = "edit_session.user.login";
    }
    return new Keen.Query("sum", keenOptions);
  }

  keen.run(prepareTimeQuery(options), function() {
    var i;

    if (options.useGroupBy) {
        // Show time spent broken down by each user
        for (i = 0; i
Keen Post Metrics User

To make things even simpler and more secure, we’re taking advantage of Keen’s scoped keys feature. By generating keys dynamically on the server side when customers want to access their data, we’re able to automatically pre-filter the queries for each customer at run-time. Simply passing the generated scoped key to the client side then automatically points each of our visualization queries (like in the snippet above) at the right dataset. Keeping that logic out of the client-side queries is awesome!

The results have been so overwhelmingly positive that we are pursuing more ways to provide innovative and automated content intelligence to our users (e.g., sending automated email digests showing the week-over-week performance of a team using Keen’s open source Pushpop library).

The future of content intelligence

Our ultimate goal is to create the first industry benchmarks on data for content production. No one knows, on average, how long it takes an ad agency to write a press release. We get to be the ones who find out. Who knows what we’ll uncover.

As we do, Keen will play a critical role in collecting and sharing that information with our users.

Want to know more about what we are doing over here at Beegit? Check out our blog or sign up for a free trial.