Making Statistical Social Validation Fast
One of the challenges we have at RecruitMilitary is that there is a perception that there are lots of companies out there that "prey on veterans" and there is skepticism that we are who we say we are.
Why do it?
We know we're for real, but how do we communicate that quickly and effectively?
I've been pushing us to just show the numbers... while we're always pushing for improvement, on the whole I'm proud of our activity and just showing visitors our numbers in real time, I believe, should be convincing. Here's a screenshot of the finished product:

You can visit the site (during business hours is best) to see the stats bar in action.
The technical nitty-gritty
We knew that we'd end up with people sitting and watching the stats increment, so we wanted to make sure the request was fast. We use Resque as our background processing system, and along with it came Redis. We basically took the ideas in Resque's stat module and implemented a very fast way to get the counters from our system.
However, the data is actually coming from a different Rails app than our marketing site, so we rolled a simple little jsonp service. Here's the controller:
module Api::V1
class StatsController < BaseController
caches_action :index, :expires_in => 10.seconds
def index
@stats =
Board::Stat::DAILY_STATS.inject({}) do |h, stat|
h[stat] = Board::Stat[stat]
h["#{stat}_today"] = Board::Stat["#{stat}_today"]
h
end
render_json(@stats)
end
end
end
In the destination page, we drop in a simple div that is filled in with javascript:
<div id="stats" class="hidden wide bordered">
</div>
The controller response was quick, but we were getting so many hits to it, we had to optimize further.
We did two 2 things:
- Define an explicit
jsonpCallbackproperty. It turned out that the way we had jsonp setup, it was generating a unique callback string with each request in the URL, effectively nullifying our cache of 10 seconds. - We found that requests were happing around the clock, people were leaving our page up in a browser window. A quick check on
($("html").is(".blurred"))did the trick—we stopped updating the stats if the browser window wasn't active.
The refined javascript:
$.fn.boardStatisticize = function() {
var stat_box = this;
$.ajax({
cache: true,
dataType: "jsonp",
jsonpCallback: "statsicizer",
success: handleResponse,
url: "https://board.recruitmilitary.com/api/v1/stats"
});
function handleResponse(data) {
var stats = data;
var displayed_stats = ["active_jobs", "job_views",
"candidate_accounts", "candidate_profile_views"];
for (i = 0; i < displayed_stats.length; i++) {
insertStat(displayed_stats[i],
stats[displayed_stats[i]]);
}
function insertStat(key, value) {
$("<div></div>")
.addClass("block")
.append(blockLabel())
.append(totalCount())
.append(todayCount())
.attr("id", key)
.css("width", (stat_box.innerWidth() / 4) - 22)
.appendTo(stat_box);
function blockLabel() {
return $("<h3></h3>")
.addClass("label")
.text(BR.board_stat_labels[key]);
}
function totalCount() {
return $("<span></span>")
.addClass("total-count")
.data("count", value)
.text(commafyNumber(value));
}
function todayCount() {
return $("<span></span>")
.addClass("today-count")
.data("count", stats[key + "_today"])
.text("+" +
commafyNumber(stats[key + "_today"]) +
" today");
}
}
$("#candidate-form .job-count")
.text(commafyNumber(stats["active_jobs"]));
stat_box.removeClass("hidden");
}
window.setInterval("updateBoardStats()", 10000);
return this;
};
function updateBoardStats() {
if ($("html").is(".blurred"))
return;
$.ajax({
cache: true,
dataType: "jsonp",
jsonpCallback: "statsicizer",
success: handleResponse,
url: "https://board.recruitmilitary.com/api/v1/stats"
});
function handleResponse(data) {
var stats = data;
var displayed_stats = ["active_jobs", "job_views",
"candidate_accounts", "candidate_profile_views"];
for (i = 0; i < displayed_stats.length; i++) {
updateStat(displayed_stats[i],
stats[displayed_stats[i]]);
}
function updateStat(key, value) {
var total = $("#" + key + " .total-count");
var today = $("#" + key + " .today-count");
if (total.data("count") !== value) {
total
.addClass("updated")
.data("count", value)
.text(commafyNumber(value))
.switchClass("updated", "", 5000);
today
.addClass("updated")
.data("count", stats[key + "_today"])
.text("+" + commafyNumber(stats[key +
"_today"]) + " today")
.switchClass("updated", "", 5000);
}
}
$("#candidate-form .job-count")
.text(commafyNumber(stats["active_jobs"]));
}
}
Great work from Michael and Jason on this, we continue to get daily complements on our new home page, and I know this feature is central to the great experience.
