mirror of https://github.com/codefeathers/minnal
Muthu Kumar
7 years ago
commit
7693dfda07
7 changed files with 236 additions and 0 deletions
@ -0,0 +1,2 @@ |
|||
node_modules |
|||
client.html |
@ -0,0 +1,4 @@ |
|||
module.exports = { |
|||
host: "localhost:5000", |
|||
dashboardEndpoint: "/dashboard" |
|||
} |
@ -0,0 +1,25 @@ |
|||
{ |
|||
"name": "breeze-analytics", |
|||
"version": "0.0.1", |
|||
"description": "Web analytics like a breeze", |
|||
"main": "server.js", |
|||
"scripts": { |
|||
"test": "echo \"Error: no test specified\" && exit 1" |
|||
}, |
|||
"repository": { |
|||
"type": "git", |
|||
"url": "git+https://github.com/codefeathers/breeze-analytics.git" |
|||
}, |
|||
"keywords": [ |
|||
"breeze", |
|||
"analytics", |
|||
"website", |
|||
"monitoring" |
|||
], |
|||
"author": "Muthu Kumar (https://mkr.pw)", |
|||
"license": "MIT", |
|||
"bugs": { |
|||
"url": "https://github.com/codefeathers/breeze-analytics/issues" |
|||
}, |
|||
"homepage": "https://github.com/codefeathers/breeze-analytics#readme" |
|||
} |
@ -0,0 +1,106 @@ |
|||
// require Express and Socket.io
|
|||
var express = require('express'); |
|||
var app = express(); |
|||
var http = require('http').Server(app); |
|||
var io = require('socket.io')(http); |
|||
var path = require('path'); |
|||
var config = require('./config.js'); |
|||
|
|||
// the object that will hold information about the active users currently
|
|||
// on the site
|
|||
var visitorsData = {}; |
|||
|
|||
app.set('port', (process.env.PORT || 5000)); |
|||
|
|||
// serve the static assets (js/dashboard.js and css/dashboard.css)
|
|||
// from the public/ directory
|
|||
app.use(express.static(path.join(__dirname, 'public/'))); |
|||
|
|||
// serve the index.html page when someone visits any of the following endpoints:
|
|||
// 1. /
|
|||
// 2. /about
|
|||
// 3. /contact
|
|||
app.get(/\/(about|contact)?$/, function (req, res) { |
|||
res.sendFile(path.join(__dirname, 'views/index.html')); |
|||
}); |
|||
|
|||
// serve up the dashboard when someone visits /dashboard
|
|||
app.get('/dashboard', function (req, res) { |
|||
res.sendFile(path.join(__dirname, 'views/dashboard.html')); |
|||
}); |
|||
|
|||
io.on('connection', function (socket) { |
|||
if (socket.handshake.headers.host === config.host && |
|||
socket.handshake.headers.referer.indexOf(config.host + config.dashboardEndpoint) > -1) { |
|||
|
|||
// if someone visits '/dashboard' send them the computed visitor data
|
|||
io.emit('updated-stats', computeStats()); |
|||
|
|||
} |
|||
|
|||
// a user has visited our page - add them to the visitorsData object
|
|||
socket.on('visitor-data', function (data) { |
|||
visitorsData[socket.id] = data; |
|||
|
|||
// compute and send visitor data to the dashboard when a new user visits our page
|
|||
io.emit('updated-stats', computeStats()); |
|||
}); |
|||
|
|||
socket.on('disconnect', function () { |
|||
// a user has left our page - remove them from the visitorsData object
|
|||
delete visitorsData[socket.id]; |
|||
|
|||
// compute and send visitor data to the dashboard when a user leaves our page
|
|||
io.emit('updated-stats', computeStats()); |
|||
}); |
|||
}); |
|||
|
|||
// wrapper function to compute the stats and return a object with the updated stats
|
|||
function computeStats() { |
|||
return { |
|||
pages: computePageCounts(), |
|||
referrers: computeRefererCounts(), |
|||
activeUsers: getActiveUsers() |
|||
}; |
|||
} |
|||
|
|||
// get the total number of users on each page of our site
|
|||
function computePageCounts() { |
|||
// sample data in pageCounts object:
|
|||
// { "/": 13, "/about": 5 }
|
|||
var pageCounts = {}; |
|||
for (var key in visitorsData) { |
|||
var page = visitorsData[key].page; |
|||
if (page in pageCounts) { |
|||
pageCounts[page]++; |
|||
} else { |
|||
pageCounts[page] = 1; |
|||
} |
|||
} |
|||
return pageCounts; |
|||
} |
|||
|
|||
// get the total number of users per referring site
|
|||
function computeRefererCounts() { |
|||
// sample data in referrerCounts object:
|
|||
// { "http://twitter.com/": 3, "http://stackoverflow.com/": 6 }
|
|||
var referrerCounts = {}; |
|||
for (var key in visitorsData) { |
|||
var referringSite = visitorsData[key].referringSite || '(direct)'; |
|||
if (referringSite in referrerCounts) { |
|||
referrerCounts[referringSite]++; |
|||
} else { |
|||
referrerCounts[referringSite] = 1; |
|||
} |
|||
} |
|||
return referrerCounts; |
|||
} |
|||
|
|||
// get the total active users on our site
|
|||
function getActiveUsers() { |
|||
return Object.keys(visitorsData).length; |
|||
} |
|||
|
|||
http.listen(app.get('port'), function () { |
|||
console.log('listening on *:' + app.get('port')); |
|||
}); |
@ -0,0 +1,80 @@ |
|||
<!DOCTYPE html> |
|||
<html lang="en"> |
|||
|
|||
<head> |
|||
<meta charset="utf-8"> |
|||
<meta http-equiv="X-UA-Compatible" content="IE=edge"> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1"> |
|||
<title>Breeze Analytics Dashboard</title> |
|||
|
|||
<link rel="stylesheet" href="css/dashboard.css"> |
|||
</head> |
|||
|
|||
<body> |
|||
<nav class="navbar navbar-inverse navbar-fixed-top"> |
|||
<div class="container"> |
|||
<div class="navbar-header"> |
|||
<a class="navbar-brand" href="/">Breeze Analytics</a> |
|||
</div> |
|||
</div> |
|||
</nav> |
|||
|
|||
<div class="container"> |
|||
<div id="app"> |
|||
<div class="row"> |
|||
<div class="col-xs-3"> |
|||
<div class="well"> |
|||
<h1 class="dash-red">{{ activeUsers }} |
|||
<i class="glyphicon glyphicon-user"></i> |
|||
</h1> |
|||
<h3 class="text-muted">Active Users</h3> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-xs-9"> |
|||
<h2 class="sub-header">Active Pages</h2> |
|||
<div class="table-responsive"> |
|||
<table class="table"> |
|||
<thead> |
|||
<td>Page URL</td> |
|||
<td>Active Users</td> |
|||
</thead> |
|||
<tbody> |
|||
<tr v-for="(page, count) in pages"> |
|||
<td>{{ page }}</td> |
|||
<td>{{ count }}</td> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
|
|||
<h2 class="sub-header">Referrals</h2> |
|||
<div class="table-responsive"> |
|||
<table class="table"> |
|||
<thead> |
|||
<td>Referring Site</td> |
|||
<td>Active Users</td> |
|||
</thead> |
|||
<tbody> |
|||
<tr v-for="(referringSite, count) in referrers"> |
|||
<td>{{ referringSite }}</td> |
|||
<td>{{ count }}</td> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
|
|||
</div> |
|||
|
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.17/vue.js"></script> |
|||
<script src="/socket.io/socket.io.js"></script> |
|||
<!--<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.3/socket.io.js"></script>--> |
|||
<script src="js/dashboard.js"></script> |
|||
|
|||
</body> |
|||
|
|||
</html> |
@ -0,0 +1,2 @@ |
|||
<h1>Breeze Analytics Server</h1> |
|||
<a href='https://github.com/codefeathers/breeze-analytics'>Github</a> |
@ -0,0 +1,17 @@ |
|||
var socket = io(); |
|||
|
|||
var vm = new Vue({ |
|||
el: '#app', |
|||
data: { |
|||
pages: {}, |
|||
referrers: {}, |
|||
activeUsers: 0 |
|||
}, |
|||
created: function () { |
|||
socket.on('updated-stats', function (data) { |
|||
this.pages = data.pages; |
|||
this.referrers = data.referrers; |
|||
this.activeUsers = data.activeUsers; |
|||
}.bind(this)); |
|||
} |
|||
}); |
Loading…
Reference in new issue