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