How I integrated Keen IO and Ducksboard

Share on facebook
Share on twitter
Share on pinterest

Michelle here again. In my previous blog post, I described how I used Keen IO’s analysis query builder to answer questions about the health of our business. In fact there are about 15 queries I run throughout the day to monitor our progress. Queries such as the number of events posted in the past seven days and counts for each of the analysis methods being used.

As an example, here’s a select unique HTTPS query which gives me a list of users who logged in today:<projID>/queries/select_unique?api_key=<key>&event_collection=login&

Because Keen IO’s analysis capabilities are exposed via a REST API like this, you can use them programmatically: in custom reports, workflows, dashboards, or a metrics tab in your mobile app.

My goal was simply to use the analysis API to display usage stats in our office. We already had a Ducksboard dashboard displaying our site traffic and social media growth, so I simply added a few widgets to display custom stats from our backend. I made a little ruby program that runs through a list of my Keen IO saved queries and pushes the results to the ducksboard widgets.

I’d thought I’d share some of my code here in case others find it useful. I also put it on github. Note: I just started learning Ruby and this is the first code I have ever shared… be nice!

My program runs through an array of about twenty different queries (the code sample below shows two of them).

require 'rubygems'
require 'net/http'
require 'uri'
require 'json'
require 'date'

# This program takes Keen IO query URLS, fetches results from Keen IO, then pushes them to existing Ducksboard widgets. 
# It also outputs results to Terminal.
# Each query requires the following information
# 1. Description of the Query.
# 2. Query URL
# 3. Required Ducksboard Formatting (number, series, list)
# 4. Ducksboard Widget ID. You need to log into Ducksboard to get this for each widget. 

#Ducksboard API Key. Get this from ducksboard. The program assumes you are only sending data to a single ducksboard account.
dbkey = "abcdefghijklmnopqrtsuv"

#List of Queries. Add new ones to the bottom. This is the only place you need to make updates for new queries (besides creating the ducksboard widget). 
queries = [{
          "description" => "Count of Unique Orgs with Analysis Queries",
          "keen_query_url" => "",
          "format" => "numeric",
          "db_widget_ID" => 84409
          "description" => "Count of unique logins (all time)",
          "keen_query_url" => "",
          "format" => "numeric",
          "db_widget_ID" => 68658

Here is a function I made which performs a simple HTTP request to get the query result from

def get_keen_value(keen_query_url)

   uri = URI.parse(keen_query_url)
   http =, uri.port)
   http.use_ssl = true
   http.verify_mode = OpenSSL::SSL::VERIFY_NONE

   response = http.start() {|http|
     response = http.get(uri.request_uri)

   keenresult = JSON.parse(response.body)
   result = keenresult['result']

  return result

This second function formats the result data based on query type, then pushes it to ducksboard.

def send_to_ducksboard(db_widget_ID, dbkey, value, format)

   uri = URI.parse("{db_widget_ID}")
   http =, uri.port)
   http.use_ssl = true
   request =
   request.basic_auth(dbkey, "password")

   if format == "numeric"

     db_value = {"value" => value}

   elsif format == "series"
     series_array = value
     final_array =[]

     series_array.each {|x| 
           keentimestamp = DateTime.parse x['timeframe']['start']
           unixtime = keentimestamp.to_time.to_i
           keenvalue = x['value']

           newhash = {:timestamp => unixtime,
                      :value => keenvalue}

           final_array << newhash

     db_value = final_array

   elsif format == "list"
     list_array = value
     leader_array = []

     list_array.each {|i| 
           leaderboard_row = {:name => i,:values => [],}
           leader_array << leaderboard_row

     db_value = {:value => {:board => leader_array}}

     print "error - specify a valid format"


   request.body = db_value.to_json
   response = http.request(request)

 return response

This code loops through all the queries, gets results, prints them to terminal, and sends them to ducksboard.

queries.each do |query|
 puts "========================================"
 puts query['description']
 puts keen_result = get_keen_value(query['keen_query_url'])
 unless query['db_widget_ID'] == "none"
 send_to_ducksboard(query['db_widget_ID'], dbkey, keen_result, query['format'])

Final result? Our dashboard gives us a great snapshot of recent user activity. Note: this screenshot is a bit outdated. Want to see goofy pics of our team and make that facebook fan number go up? Here you go.



This post is Part 3 in Michelle’s Analytics Showcase. Here are some links to other posts in the series:

Part 1: Logins

Part 2: Filtering & Saved Queries

Share this post with your friends

Share on facebook
Share on google
Share on twitter
Share on linkedin

Subscribe to our Newsletter

Leave a Reply

Your email address will not be published. Required fields are marked *