Skip to content

Instantly share code, notes, and snippets.

@ESeufert
Created February 4, 2013 19:44
Show Gist options
  • Save ESeufert/4709085 to your computer and use it in GitHub Desktop.
Save ESeufert/4709085 to your computer and use it in GitHub Desktop.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<title>
Minimum Viable Metrics dashboard template - ufert.se
</title>
<link href="https://raw.github.com/ESeufert/MVM-Dashboard-Template/master/nvd3-master/src/nv.d3.css" rel="stylesheet" type="text/css">
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.21/jquery-ui.min.js"></script>
<script src="https://raw.github.com/ESeufert/MVM-Dashboard-Template/master/nvd3-master/lib/d3.v2.js"></script>
<script src="https://raw.github.com/ESeufert/MVM-Dashboard-Template/master/nvd3-master/nv.d3.js"></script>
<script src="https://raw.github.com/ESeufert/MVM-Dashboard-Template/master/nvd3-master/src/tooltip.js"></script>
<script src="https://raw.github.com/ESeufert/MVM-Dashboard-Template/master/nvd3-master/src/utils.js"></script>
<script src="https://raw.github.com/ESeufert/MVM-Dashboard-Template/master/nvd3-master/src/models/legend.js"></script>
<script src="https://raw.github.com/ESeufert/MVM-Dashboard-Template/master/nvd3-master/src/models/axis.js"></script>
<script src="https://raw.github.com/ESeufert/MVM-Dashboard-Template/master/nvd3-master/src/models/scatter.js"></script>
<script src="https://raw.github.com/ESeufert/MVM-Dashboard-Template/master/nvd3-master/src/models/line.js"></script>
<script src="https://raw.github.com/ESeufert/MVM-Dashboard-Template/master/nvd3-master/src/models/lineChart.js"></script>
<script src="https://raw.github.com/ESeufert/MVM-Dashboard-Template/master/nvd3-master/src/models/multiBar.js"></script>
<script src="https://raw.github.com/ESeufert/MVM-Dashboard-Template/master/nvd3-master/src/models/multiBarChart.js"></script>
<script src="https://raw.github.com/ESeufert/MVM-Dashboard-Template/master/nvd3-master/src/models/historicalBar.js"></script>
<script src="https://raw.github.com/ESeufert/MVM-Dashboard-Template/master/nvd3-master/src/models/pie.js"></script>
<script src="https://raw.github.com/ESeufert/MVM-Dashboard-Template/master/nvd3-master/src/models/pieChart.js"></script>
<script>
function getRandomInt (min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function getYesterday() {
var date = new Date();
date.setDate(date.getDate() - 1);
return date;
}
function generateData(numDays, endDay, keys, min, max) {
var data = [];
var i = 0;
endDay = new Date(endDay);
for (i = 0; i < keys.length; i++) {
var item = {};
item["key"] = keys[i]["name"];
item["values"] = [];
item["color"] = keys[i]["color"]
if (keys[i]["disabled"]) {
item["disabled"] = true;
}
if (keys[i]["area"]) {
item["area"] = true;
}
var k = 0;
for (k = 0; k < numDays; k++) {
var thisValue = [];
var thisDate = new Date(endDay.getFullYear(), endDay.getMonth(), endDay.getDate()-k);
//console.log("THIS DAY: " + thisDate);
thisValue.push(thisDate);
thisValue.push(getRandomInt(min, max));
//console.log("THIS VALUE: " + thisValue);
item["values"].push(thisValue);
}
item["values"].reverse();
//console.log(item);
data.push(item);
}
return data;
}
//K-FACTOR
nv.addGraph(function() {
data = generateData(15, getYesterday(), [{"name":"K-Factor", "color":"#218359"}], .8, 2.0);
var chart = nv.models.multiBarChart()
.x(function(d) { return d[0] })
.y(function(d) { return d[1] })
.stacked(true)
.showControls(false);
chart.margin({bottom: 60});
chart.yAxis
.tickFormat(d3.format(',.1f'));
chart.xAxis
.tickFormat(function(d) {
return d3.time.format('%x')(new Date(d))
})
.rotateLabels(-45);
d3.select('#k-factor svg')
.datum(data)
.transition().duration(500)
.call(chart);
nv.utils.windowResize(chart.update);
return chart;
});
//Revenue
nv.addGraph(function() {
data = generateData(15, getYesterday(), [{"name":"Revenue", "color":"#FF7640", "area":"true"}], 300000, 800000);
//console.log("DATA: " + data);
var chart = nv.models.lineChart()
.x(function(d) { return d[0] })
.y(function(d) { return d[1]/100 })
.color(d3.scale.category10().range());
chart.xAxis
.tickFormat(function(d) {
return d3.time.format('%x')(new Date(d))
})
.rotateLabels(-45);
chart.yAxis
//.tickFormat(d3.format(',.1%'));
.tickFormat(d3.format(',.2f'));
d3.select('#revenue svg')
.datum(data)
.transition().duration(500)
.call(chart);
//TODO: Figure out a good way to do this automatically
nv.utils.windowResize(chart.update);
//nv.utils.windowResize(function() { d3.select('#chart1 svg').call(chart) });
return chart;
});
//DNU
nv.addGraph(function() {
data = generateData(15, getYesterday(), [{"name":"DNU", "color":"#BF5930", "area":"true"}], 1000, 2000);
//console.log("DATA: " + data);
var chart = nv.models.lineChart()
.x(function(d) { return d[0] })
.y(function(d) { return d[1]/100 })
.color(d3.scale.category10().range());
chart.xAxis
.tickFormat(function(d) {
return d3.time.format('%x')(new Date(d))
})
.rotateLabels(-45);
chart.yAxis
//.tickFormat(d3.format(',.1%'));
.tickFormat(d3.format(',.2f'));
d3.select('#daily_new_users svg')
.datum(data)
.transition().duration(500)
.call(chart);
//TODO: Figure out a good way to do this automatically
nv.utils.windowResize(chart.update);
//nv.utils.windowResize(function() { d3.select('#chart1 svg').call(chart) });
return chart;
});
//retention
nv.addGraph(function() {
data = generateData(15, getYesterday(), [{"name":"D1","color":"#FF9B73", "area":false},{"name":"D3","color":"#FF4900"},{"name":"D7","color":"#A62F00"},
{"name":"D14","disabled":true,"color":"#A62F00"},{"name":"D28","disabled":true,"color":"#A62F00"},
{"name":"D90","disabled":true,"color":"#A62F00"},{"name":"D365","disabled":true,"color":"#A62F00"}
], 10, 50);
var chart = nv.models.lineChart()
.x(function(d) { return d[0] })
.y(function(d) { return d[1] / 100 })
chart.xAxis
.tickFormat(function(d) {
return d3.time.format('%x')(new Date(d))
})
.rotateLabels(-45);
chart.yAxis
.tickFormat(d3.format(',.1%'));
d3.select('#retention svg')
.datum(data)
.transition().duration(500)
.call(chart);
//TODO: Figure out a good way to do this automatically
nv.utils.windowResize(chart.update);
//nv.utils.windowResize(function() { d3.select('#chart1 svg').call(chart) });
return chart;
});
//DAU
nv.addGraph(function() {
data = generateData(15, getYesterday(), [{"name":"DAU","area":"true","color":"#218359"}], 10000, 50000);
var chart = nv.models.lineChart()
.x(function(d) { return d[0] })
.y(function(d) { return d[1] });
chart.margin({bottom: 60});
chart.xAxis
.tickFormat(function (d) {
return d3.time.format('%x')(new Date(d))
})
.rotateLabels(-45);
chart.yAxis
//.axisLabel('Voltage (v)')
.tickFormat(d3.format(',.2f'));
//var xTicks = d3.select('.nv-x.nv-axis > g').selectAll('g');
//xTicks
// .selectAll('text')
// .attr('transform', function(d,i,j) { return 'translate (-10, 25) rotate(-90 0,0)
d3.select('#daily_active_users svg')
.datum(data)
.transition().duration(500)
.call(chart);
nv.utils.windowResize(chart.update);
return chart;
});
//conversion
nv.addGraph(function() {
data = generateData(15, getYesterday(), [{"name":"Conversion","area":"true","color":"#36D792"}], 0, 20);
var chart = nv.models.lineChart()
.x(function(d) { return d[0] })
.y(function(d) { return d[1] });
chart.margin({bottom: 60});
chart.xAxis
.tickFormat(function (d) {
return d3.time.format('%x')(new Date(d))
})
.rotateLabels(-45);
chart.yAxis
//.axisLabel('Voltage (v)')
.tickFormat(d3.format(',.2f'));
//var xTicks = d3.select('.nv-x.nv-axis > g').selectAll('g');
//xTicks
// .selectAll('text')
// .attr('transform', function(d,i,j) { return 'translate (-10, 25) rotate(-90 0,0)
d3.select('#conversion svg')
.datum(data)
.transition().duration(500)
.call(chart);
nv.utils.windowResize(chart.update);
return chart;
});
//ARPU
nv.addGraph(function() {
data = generateData(15, getYesterday(), [{"name":"ARPU","area":"true","color":"#FF7640"}], 0, 40);
var chart = nv.models.multiBarChart()
.x(function(d) { return d[0] })
.y(function(d) { return d[1] })
.stacked(true)
.showControls(false);
chart.margin({bottom: 60});
chart.xAxis
.tickFormat(function (d) {
return d3.time.format('%x')(new Date(d))
})
.rotateLabels(-45);
chart.yAxis
//.axisLabel('Voltage (v)')
.tickFormat(d3.format(',.2f'));
d3.select('#arpu svg')
.datum(data)
.transition().duration(500)
.call(chart);
nv.utils.windowResize(chart.update);
return chart;
});
//ARPPU
nv.addGraph(function() {
data = generateData(15, getYesterday(), [{"name":"ARPPU","color":"#FF7640", "area":true},
], 30, 50);
var chart = nv.models.multiBarChart()
.x(function(d) { return d[0]; })
.y(function(d) { return d[1]; })
.stacked(true)
.showControls(false);
chart.margin({bottom: 60});
chart.xAxis
.tickFormat(function(d) {
return d3.time.format('%x')(new Date(d))
})
.rotateLabels(-45);
chart.yAxis
.tickFormat(d3.format(',.1f'));
d3.select('#arppu svg')
.datum(data)
.transition().duration(500)
.call(chart);
nv.utils.windowResize(chart.update);
return chart;
});
//AVG and MEDIAN session lengths
nv.addGraph(function() {
data = generateData(15, getYesterday(), [{"name":"Average Session Length","color":"#BF5930", "area":true},
{"name":"Median Session Length","color":"#218359","disabled":"true", "area":true}], 30, 50);
var chart = nv.models.lineChart()
.x(function(d) { return d[0] })
.y(function(d) { return d[1] })
chart.margin({bottom: 60});
chart.xAxis
.tickFormat(function(d) {
return d3.time.format('%x')(new Date(d))
})
.rotateLabels(-45);
chart.yAxis
.tickFormat(d3.format(',.1f'));
d3.select('#sesslen svg')
.datum(data)
.transition().duration(500)
.call(chart);
nv.utils.windowResize(chart.update);
return chart;
});
//AVG and MEDIAN session per user
nv.addGraph(function() {
data = generateData(15, getYesterday(), [{"name":"Average Sessions per User","color":"#FF7640", "area":true},
{"name":"Median Sessions per User","color":"#36D792","disabled":"true", "area":true}], 30, 50);
var chart = nv.models.lineChart()
.x(function(d) { return d[0]; })
.y(function(d) { return d[1]; });
chart.margin({bottom: 60});
chart.xAxis
.tickFormat(function(d) {
return d3.time.format('%x')(new Date(d))
})
.rotateLabels(-45);
chart.yAxis
.tickFormat(d3.format(',.1f'));
d3.select('#chart6 svg')
.datum(data)
.transition().duration(500)
.call(chart);
nv.utils.windowResize(chart.update);
return chart;
});
var maxDate = getYesterday();
var numDays = 15;
</script>
<style>
body {
font-family:arial;
font-size:11px;
overflow-y:scroll;
padding-top: 10px;
padding-left: 20px;
padding-right: 20px;
padding-bottom: 10px;
margin-bottom: 30px;
}
.clear {clear:both}
#nav_div {
width: 100%;
float: left;
font-size: 32px;
font-weight: bold;
color: #000000;
}
#charts_div {
margin-left: 20px;
margin-right: 20px;
margin-top: 10px;
margin-bottom: 40px;
float: left;
width: 99%;
height: auto;
}
svg {
display: block;
width: 100%;
}
.chartBlock {
margin: 6px 6px 6px 6px;
float: left;
height: 150px
}
.chartRow {
width: 98%;
margin: 6px 6px 6px 6px;
background-color: #FFFFFF;
float: left;
padding: 2px 0px 40px 6px;
}
.console_item {
margin-left: 5px;
margin-right: 5px;
width: 80px;
float: left;
}
</style>
</head>
<body>
<h2>A Minimum Viable Metrics dashboard template</h2>
<div id="charts_div">
<div class="chartRow" style="background-color: #EDEDE3; border: 1px solid #000000;">
<div id="retention" class="chartBlock" style="width: 100%;">
<h2 style="float: left; margin-bottom: 2px;">Retention</h2>
<svg></svg>
</div>
</div>
<div class="chartRow">
<div id="daily_new_users" class="chartBlock" style="width: 49%;">
<h2 style="float: left; margin-bottom: 2px;">Daily New Users</h2>
<svg></svg>
</div>
<div id="daily_active_users" class="chartBlock" style="width: 49%;">
<h2 style="float: left; margin-bottom: 2px;">Daily Active Users</h2>
<svg></svg>
</div>
</div>
<div class="chartRow" style="background-color: #EDEDE3; border: 1px solid #000000;">
<div id="revenue" class="chartBlock" style="width: 100%;">
<h2 style="float: left; margin-bottom: 2px;">Revenue</h2>
<svg></svg>
</div>
</div>
<div class="chartRow">
<div id="conversion" class="chartBlock" style="width: 49%;">
<h2 style="float: left; margin-bottom: 2px;">Conversion</h2>
<svg></svg>
</div>
<div id="arpu" class="chartBlock" style="width: 49%;">
<h2 style="float: left; margin-bottom: 2px;">ARPU</h2>
<svg></svg>
</div>
</div>
<div class="chartRow" style="background-color: #EDEDE3; border: 1px solid #000000;">
<div id="arppu" class="chartBlock" style="width: 49%;">
<h2 style="float: left; margin-bottom: 2px;">ARPPU</h2>
<svg></svg>
</div>
<div id="k-factor" class="chartBlock" style="width: 49%;">
<h2 style="float: left; margin-bottom: 2px;">K-Factor</h2>
<svg></svg>
</div>
</div>
<div class="chartRow">
<div id="sesslen" class="chartBlock" style="width: 49%;">
<h2 style="float: left; margin-bottom: 2px;">Session Lengths</h2>
<svg></svg>
</div>
<div id="chart6" class="chartBlock" style="width: 49%;">
<h2 style="float: left; margin-bottom: 2px;">Sessions per User</h2>
<svg></svg>
</div>
</div>
</div>
<div id="bottom" style="height: 100px; width: 100%;">&nbsp;</div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment