Skip to content

Instantly share code, notes, and snippets.

@dustinlarimer
Last active December 30, 2015 16:19
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save dustinlarimer/7853815 to your computer and use it in GitHub Desktop.
Save dustinlarimer/7853815 to your computer and use it in GitHub Desktop.
Day/Hour PageView Heatmap for Keen.io
<!DOCTYPE html>
<html>
<head>
<title>PageView Grid</title>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.5.2/underscore-min.js"></script>
<script>
var Keen=Keen||{configure:function(e){this._cf=e},addEvent:function(e,t,n,i){this._eq=this._eq||[],this._eq.push([e,t,n,i])},setGlobalProperties:function(e){this._gp=e},onChartsReady:function(e){this._ocrq=this._ocrq||[],this._ocrq.push(e)}};(function(){var e=document.createElement("script");e.type="text/javascript",e.async=!0,e.src=("https:"==document.location.protocol?"https://":"http://")+"dc8na2hxrj29i.cloudfront.net/code/keen-2.1.0-min.js";var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t)})();
Keen.configure({
projectId: "<your-projectId>",
readKey: "<your-readKey>"
});
Keen.onChartsReady(function() {
var pageViews_hourly = new Keen.Series("pageView", {
analysisType: "count",
timeframe: "this_7_days",
interval: "hourly"
});
pageViews_hourly.getResponse(function(data){
stackedTimeline(data);
});
});
var stackedTimeline = function(data){
// data.result.value
// data.result.timeframe.start
// data.result.timeframe.end
var unit = 35
, width = 960
, height = 400;
var days = ['S', 'M', 'T', 'W', 'T', 'F', 'S'];
var day = d3.time.format('%w')
, hour = d3.time.format('%H')
, time = d3.time.format('%I:%M')
, format = d3.time.format.utc('%Y-%m-%dT%H:%M:%S.%LZ');
// Scale activity for Opacity
var heat = d3.scale.quantize()
.domain([0, d3.max(data.result, function(d){ return d.value; })])
.range(d3.range(100).map(function(d) { return d/100; }));
// Convert dates and scale activity
data.result.forEach(function(d){
var now = new Date();
var then = new Date(d.timeframe.start);
var iso = then.toISOString();
d.date = format.parse(iso);
var activity = heat(d.value);
if (activity > 0) {
d.fill = '#49c5b1';
d.stroke = '#d7d7d7';
d.alpha = activity;
} else if (now < then) {
d.fill = '#fff';
d.stroke = '#fbfbfb';
d.alpha = 1;
} else {
d.fill = '#fff';
d.stroke = '#f2f2f2';
d.alpha = 1;
}
})
var first_day = d3.min(data.result, function(d) { return d.date })
, timeframe = _.rest(days, day(first_day))
, offset = days.length - timeframe.length
, remainder = days.slice(0,offset)
, date_range = timeframe.concat(remainder);
// console.log(date_range);
var svg = d3.select("#pageview_grid")
.append("svg")
.attr('width', width)
.attr('height', height)
var intervals = svg.append("g")
.attr('class', 'intervals')
.attr('transform', 'translate(' + unit + ',' + (unit/2) + ')')
var date_label = intervals.selectAll('g.dates')
.data(date_range)
.enter().append('g')
.attr('class', 'dates')
.attr('transform', function(d,i){ return 'translate(' + -1*unit + ',' + (i*unit) + ')' })
.append('text')
.attr('dy', unit/2*1.3)
.attr('dx', unit/2)
.attr('font-size', unit/2*1.2)
.attr('font-weight', 'bold')
.attr('text-anchor', 'middle')
.text(function(d){ return d })
var time_label = intervals.selectAll('g.times')
.data(['12a', '3a', '6a', '9a', '12p', '3p', '6p', '9p'])
.enter().append('g')
.attr('class', 'times')
.attr('transform', function(d,i){ return 'translate(' + (i*(unit*3)) + ',' + unit*7.5 + ')' })
.append('text')
.attr('dy', 0)
.attr('dx', unit/2*.8)
.attr('fill', '#808080')
.attr('font-size', unit/2*1.1)
.attr('font-weight', 'normal')
.attr('text-anchor', 'middle')
.text(function(d){ return d })
var interval = intervals.selectAll('g.day')
.data(data.result)
.enter().append('g')
.attr('class', 'day')
.attr('transform', function(d) {
var vertical_offset = day(d.date) - (offset);
var y = 0;
if (vertical_offset < 0){
//y = timeframe.length-1 + Math.abs(vertical_offset);
y = timeframe.length + parseInt(day(d.date));
} else {
y = vertical_offset
}
return 'translate(' + hour(d.date) * unit + ',' + (y * unit) + ')';
})
.append('rect')
.attr('shape-rendering', 'crispEdges')
.attr('fill', function(d){ return d.fill })
.attr('fill-opacity', function(d){ return d.alpha })
.attr('stroke', function(d){ return d.stroke })
.attr('stroke-weight', 1)
.attr('width', unit*.8)
.attr('height', unit*.8);
interval.append('svg:title').text(function(d){
return time(d.date) + ' | ' + d.value;
});
}
</script>
<style>
body { font-family: Helvetica, Arial, sans-serif }
</style>
</head>
<body>
<div id="pageview_grid"></div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment