Skip to content

Instantly share code, notes, and snippets.

@AlexNeises
Last active March 15, 2020 03:43
Show Gist options
  • Save AlexNeises/b4736b7a15ec6424a88bf7428d6c4558 to your computer and use it in GitHub Desktop.
Save AlexNeises/b4736b7a15ec6424a88bf7428d6c4558 to your computer and use it in GitHub Desktop.
Google Analytics real time dashboard via Node.js
DEVICES = 1000 * 15 # Only call the API once every 15 seconds.
path = require 'path'
google = require 'googleapis'
key = require './config/analytics.json' # This is the key Google Developer has you download upon service account creation.
express = require 'express'
http = require 'http'
https = require 'https'
analytics = google.analytics 'v3'
app = express()
server = http.createServer app
io = require('socket.io')(server) # We don't want users to have to refresh the dashboard for data updates.
port = process.env.PORT or 3000
app.use '/static', express.static path.join __dirname, 'node_modules'
app.get '/dashboard', (req, res) ->
res.sendFile path.join __dirname, 'dashboard.html'
SCOPES = [
'https://www.googleapis.com/auth/analytics.readonly'
]
jwtClient = new google.auth.JWT key.client_email, null, key.private_key, SCOPES, null
authorize = (metric, dimension, next) ->
jwtClient.authorize (err, tokens) ->
if err
console.error err
next err
request = analytics.data.realtime.get
'auth' : jwtClient
'ids' : 'ga:xxxxxx'
'metrics' : metric
'dimensions' : dimension
'output' : 'json'
next 'https://' + request.host + request.path + '&access_token=' + jwtClient.gtoken.raw_token.access_token
makeRequests = (url, next) ->
https.get url, (response) ->
buffer = ''
response.on 'data', (chunk) ->
buffer += chunk
response.on 'end', (err) ->
next JSON.parse buffer
setInterval authorize, DEVICES, 'rt:activeUsers', 'rt:deviceCategory', (response) ->
makeRequests response, (data) ->
io.emit 'devices', data: data
server.listen port, ->
console.log "Listening on port #{port}"
<html>
<head>
<script type="text/javascript" src="/socket.io/socket.io.js"></script>
<style>
h2.rightNow {
font-size: 28px;
font-family: sans-serif;
}
h2#onlineUsers {
font-size: 78px;
font-family: sans-serif;
}
span.rightNow {
font-size: 14px;
font-family: sans-serif;
}
</style>
</head>
<body>
<h2 class="rightNow">Right now</h2>
<h2 id="onlineUsers">0</h2>
<span class="rightNow">active users on site</span>
<canvas id="chart1"></canvas>
<script type="text/javascript" src="/static/jquery/dist/jquery.min.js"></script>
<script type="text/javascript" src="/static/chart.js/dist/Chart.bundle.min.js"></script>
<script type="text/javascript">
var socket = io();
socket.on('devices', function(data) {
$('.chartjs-hidden-iframe').remove();
$('#onlineUsers').text(data.data.totalsForAllResults['rt:activeUsers']);
var colors = [
[193, 57, 43],
[39, 174, 97],
[42, 128, 185],
[143, 68, 173]
];
var newdata = [
{
data: [],
backgroundColor: [],
borderColor: [],
borderWidth: 1
}
];
var labels = [];
for (var i = 0; i < data.data.rows.length; i++) {
newdata[0].data.push(Math.round((data.data.rows[i][1] / data.data.totalsForAllResults['rt:activeUsers']) * 100));
newdata[0].backgroundColor.push('rgba(' + colors[i][0] + ',' + colors[i][1] + ',' + colors[i][2] + ',.65)');
newdata[0].borderColor.push('rgb(' + colors[i][0] + ',' + colors[i][1] + ',' + colors[i][2] + ')');
labels.push(data.data.rows[i][0].charAt(0).toUpperCase() + data.data.rows[i][0].substr(1).toLowerCase() + ' (' + Math.round((data.data.rows[i][1] / data.data.totalsForAllResults['rt:activeUsers']) * 100) + '%)');
}
var ctx = $('#chart1');
var data = {
labels: labels,
datasets: newdata
};
var pieChart = new Chart(ctx, {
type: 'pie',
data: data,
options: {
tooltips: {
enabled: false
},
legend: {
display: true
},
animation: {
duration: 1
}
}
});
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment