redis_analytics 0.1.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.md +12 -0
- data/CONTRIBUTING.md +33 -0
- data/Guardfile +10 -0
- data/README.md +105 -23
- data/Rakefile +3 -11
- data/TODO.md +12 -0
- data/bin/redis_analytics_dashboard +1 -1
- data/config.ru +13 -0
- data/lib/redis_analytics.rb +5 -1
- data/lib/redis_analytics/analytics.rb +17 -203
- data/lib/redis_analytics/api.rb +60 -0
- data/lib/redis_analytics/configuration.rb +47 -16
- data/lib/redis_analytics/dashboard.rb +28 -89
- data/lib/redis_analytics/dashboard/public/{favicon.ico → img/favicon.ico} +0 -0
- data/lib/redis_analytics/dashboard/public/javascripts/{bootstrap.min.js → vendor/bootstrap/bootstrap.min.js} +0 -0
- data/lib/redis_analytics/dashboard/public/javascripts/{jquery-1.9.1.min.js → vendor/jquery-1.9.1.min.js} +0 -0
- data/lib/redis_analytics/dashboard/public/javascripts/{jquery-jvectormap-1.2.2.min.js → vendor/jquery-jvectormap-1.2.2.min.js} +0 -0
- data/lib/redis_analytics/dashboard/public/javascripts/{jquery-jvectormap-world-mill-en.js → vendor/jquery-jvectormap-world-mill-en.js} +0 -0
- data/lib/redis_analytics/dashboard/public/javascripts/{morris.min.js → vendor/morris.min.js} +0 -0
- data/lib/redis_analytics/dashboard/public/javascripts/{raphael-min.js → vendor/raphael-min.js} +0 -0
- data/lib/redis_analytics/dashboard/views/activity.erb +7 -0
- data/lib/redis_analytics/dashboard/views/dialogs/unique_visits.erb +41 -0
- data/lib/redis_analytics/dashboard/views/dialogs/visits.erb +40 -0
- data/lib/redis_analytics/dashboard/views/footer.erb +1 -3
- data/lib/redis_analytics/dashboard/views/header.erb +17 -42
- data/lib/redis_analytics/dashboard/views/layout.erb +5 -22
- data/lib/redis_analytics/dashboard/views/visits.erb +38 -143
- data/lib/redis_analytics/dashboard/views/visits_js.erb +110 -247
- data/lib/redis_analytics/dashboard/views/widgets/bounce_rate.erb +3 -0
- data/lib/redis_analytics/dashboard/views/widgets/browsers_donut.erb +8 -0
- data/lib/redis_analytics/dashboard/views/widgets/first_visits.erb +3 -0
- data/lib/redis_analytics/dashboard/views/widgets/page_depth.erb +3 -0
- data/lib/redis_analytics/dashboard/views/widgets/referers_donut.erb +8 -0
- data/lib/redis_analytics/dashboard/views/widgets/total_page_views.erb +3 -0
- data/lib/redis_analytics/dashboard/views/widgets/total_visits.erb +3 -0
- data/lib/redis_analytics/dashboard/views/widgets/unique_visits_line.erb +26 -0
- data/lib/redis_analytics/dashboard/views/widgets/visit_duration.erb +3 -0
- data/lib/redis_analytics/dashboard/views/widgets/visit_spark.erb +23 -0
- data/lib/redis_analytics/dashboard/views/widgets/visitor_recency_slices.erb +39 -0
- data/lib/redis_analytics/dashboard/views/widgets/visits_area.erb +30 -0
- data/lib/redis_analytics/dashboard/views/widgets/visits_donut.erb +8 -0
- data/lib/redis_analytics/dashboard/views/widgets/world_map.erb +50 -0
- data/lib/redis_analytics/filter.rb +33 -0
- data/lib/redis_analytics/helpers.rb +36 -30
- data/lib/redis_analytics/metrics.rb +96 -0
- data/lib/redis_analytics/time_ext.rb +72 -2
- data/lib/redis_analytics/tracker.rb +13 -5
- data/lib/redis_analytics/version.rb +1 -1
- data/lib/redis_analytics/visit.rb +122 -0
- data/redis_analytics.gemspec +19 -14
- data/spec/lib/redis_analytics/analytics_spec.rb +59 -0
- data/spec/lib/redis_analytics/configuration_spec.rb +158 -0
- data/spec/lib/redis_analytics/dashboard_spec.rb +32 -0
- data/spec/lib/redis_analytics/filter_spec.rb +34 -0
- data/spec/lib/redis_analytics/tracker_spec.rb +20 -0
- data/spec/spec_helper.rb +13 -6
- data/spec/support/fakeredis.rb +1 -0
- data/wsd.png +0 -0
- metadata +268 -126
- data/lib/redis_analytics/config.ru +0 -10
- data/spec/redis_analytics_spec.rb +0 -57
@@ -1,29 +1,12 @@
|
|
1
1
|
<!DOCTYPE html>
|
2
2
|
<html lang="en">
|
3
3
|
<head>
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
<script src="<%=$template_prefix%>/javascripts/raphael-min.js"></script>
|
9
|
-
<script src="<%=$template_prefix%>/javascripts/morris.min.js"></script>
|
10
|
-
|
11
|
-
<script src="http://code.highcharts.com/stock/highstock.js"></script>
|
12
|
-
<script src="http://code.highcharts.com/stock/modules/exporting.js"></script>
|
13
|
-
|
14
|
-
<!-- jvectormap -->
|
15
|
-
<link rel="stylesheet" href="<%=$template_prefix%>/css/jquery-jvectormap-1.2.2.css" type="text/css" media="screen"/>
|
16
|
-
<script src="<%=$template_prefix%>/javascripts/jquery-jvectormap-1.2.2.min.js"></script>
|
17
|
-
<script src="<%=$template_prefix%>/javascripts/jquery-jvectormap-world-mill-en.js"></script>
|
18
|
-
|
19
|
-
|
20
|
-
<!-- Bootstrap -->
|
21
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
22
|
-
<link href="<%=$template_prefix%>/css/bootstrap.min.css" rel="stylesheet" media="screen">
|
23
|
-
<link href="<%=$template_prefix%>/css/bootstrap-responsive.min.css" rel="stylesheet">
|
24
|
-
|
4
|
+
<title>Redis Analytics - Dashboard</title>
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6
|
+
<%= css :application, :media => 'screen' %>
|
7
|
+
<%= js :app %>
|
25
8
|
</head>
|
26
|
-
<body>
|
9
|
+
<body onload="changeTimeFrame('<%=@range%>')">
|
27
10
|
<%= erb(:header, :layout => false) %>
|
28
11
|
<!-- start yield -->
|
29
12
|
<%=yield%>
|
@@ -1,176 +1,71 @@
|
|
1
1
|
<div class="container-fluid">
|
2
2
|
<div class="row-fluid">
|
3
3
|
<div class="span6">
|
4
|
-
|
5
|
-
<tr>
|
6
|
-
<td>
|
7
|
-
<p class="text-center"><b>Visits</b><a href="#visits_modal" data-toggle="modal"><i class="pull-right icon-search"></i></a></p>
|
8
|
-
<div id="visits_area" style="width:100%;height:160px;"></div>
|
9
|
-
</td>
|
10
|
-
</tr>
|
11
|
-
</table>
|
4
|
+
<%= erb :'widgets/visits_area' %>
|
12
5
|
</div>
|
13
6
|
<div class="span2">
|
14
|
-
|
15
|
-
<tr>
|
16
|
-
<td>
|
17
|
-
<p class="text-center"><b>Total Visits</b></p>
|
18
|
-
<div id="visits_donut" style="width:100%;height:160px;"></div>
|
19
|
-
</td>
|
20
|
-
</tr>
|
21
|
-
</table>
|
7
|
+
<%= erb :'widgets/visits_donut' %>
|
22
8
|
</div>
|
23
9
|
<div class="span2">
|
24
|
-
|
25
|
-
<tr>
|
26
|
-
<td>
|
27
|
-
<p class="text-center"><b>Traffic Sources</b></p>
|
28
|
-
<div id="referrers_donut" style="width:100%;height:160px;"></div>
|
29
|
-
</td>
|
30
|
-
</tr>
|
31
|
-
</table>
|
10
|
+
<%= erb :'widgets/referers_donut' %>
|
32
11
|
</div>
|
33
12
|
<div class="span2">
|
34
|
-
|
35
|
-
<tr>
|
36
|
-
<td>
|
37
|
-
<p class="text-center"><b>Browser Info</b></p>
|
38
|
-
<div id="browsers_donut" style="width:100%;height:160px;"></div>
|
39
|
-
</td>
|
40
|
-
</tr>
|
41
|
-
</table>
|
13
|
+
<%= erb :'widgets/browsers_donut' %>
|
42
14
|
</div>
|
43
|
-
|
44
15
|
</div>
|
45
16
|
|
46
17
|
<div class="row-fluid">
|
47
18
|
<div class="span6">
|
48
|
-
|
49
|
-
|
50
|
-
<td>
|
51
|
-
<p class="text-center"><b>Unique Visits - Current vs Previous <span id="compare_unit"><%=@range%></span></b><a href="#unique_visits_modal" data-toggle="modal"><i class="pull-right icon-search"></i></a></p>
|
52
|
-
<div id="unique_visits_line" style="width:100%;height:160px;"></div>
|
53
|
-
</td>
|
54
|
-
</tr>
|
55
|
-
</table>
|
56
|
-
</div>
|
57
|
-
|
19
|
+
<%= erb :'widgets/unique_visits_line' %>
|
20
|
+
</div>
|
58
21
|
<div class="span4">
|
59
|
-
|
60
|
-
<tr>
|
61
|
-
<td>
|
62
|
-
<p class="text-center"><b>Visitor Map</b></p>
|
63
|
-
<div id="world-map" class="info" style="width: 100%px; height: 160px"></div>
|
64
|
-
</td>
|
65
|
-
</tr>
|
66
|
-
</table>
|
22
|
+
<%= erb :'widgets/world_map' %>
|
67
23
|
</div>
|
68
24
|
|
69
25
|
<div class="span2">
|
70
|
-
|
71
|
-
<tr>
|
72
|
-
<td>
|
73
|
-
<p class="text-center"><b>Visit Recency</b></p>
|
74
|
-
<div style="height:160px;">
|
75
|
-
<div style="margin:5px;">
|
76
|
-
<%p @data[@range][:visitor_recency_slices].inspect %>
|
77
|
-
<% @data[@range][:visitor_recency_slices].each_with_index do |((k, v), i), c| %>
|
78
|
-
<% p = ((i.to_f/@data[@range][:visitor_recency_slices].map{|x| x[1]}.sum) * 100).round rescue '0' %>
|
79
|
-
<div id="recency_<%=c%>_num" title="<%=i.to_i%> visits">
|
80
|
-
<small class="muted"><%=(k == 0 ? 'Less than' : "#{k}")%> <%=('-' unless k == 0 or v == '*')%> <%=(v == '*' ? ' or more' : "#{v}")%> days (<span id="recency_<%=c%>_cent"><%=p%></span>%)</small>
|
81
|
-
<div class="progress" style="height: 8px; margin-bottom:10px;">
|
82
|
-
<div id="recency_<%=c%>" class="bar" style="width: <%=p%>%;"></div>
|
83
|
-
</div>
|
84
|
-
</div>
|
85
|
-
<% end %>
|
86
|
-
</div>
|
87
|
-
</div>
|
88
|
-
</td>
|
89
|
-
</tr>
|
90
|
-
</table>
|
26
|
+
<%= erb :'widgets/visitor_recency_slices' %>
|
91
27
|
</div>
|
92
28
|
</div>
|
93
29
|
|
94
30
|
<div class="row-fluid">
|
95
31
|
<div class="span6">
|
96
32
|
<table class="table table-bordered table-hover">
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
<!-- <td colspan="3"> -->
|
115
|
-
<!-- <div id="visits_spark" style="width:100%;height:90px;"></div> -->
|
116
|
-
<!-- </td> -->
|
117
|
-
<!-- </tr> -->
|
33
|
+
<colgroup>
|
34
|
+
<col style="width: 33%"></col>
|
35
|
+
<col style="width: 33%"></col>
|
36
|
+
<col style="width: 33%"></col>
|
37
|
+
</colgroup>
|
38
|
+
<tr>
|
39
|
+
<td><%= erb :'widgets/total_visits' %></td>
|
40
|
+
<td><%= erb :'widgets/total_page_views' %></td>
|
41
|
+
<td><%= erb :'widgets/page_depth' %></td>
|
42
|
+
</tr>
|
43
|
+
<!--
|
44
|
+
<tr colspan="3">
|
45
|
+
<td>
|
46
|
+
<%# erb :'widgets/visit_spark' %>
|
47
|
+
</td>
|
48
|
+
</tr>
|
49
|
+
-->
|
118
50
|
</table>
|
119
51
|
</div>
|
120
52
|
<div class="span6">
|
121
53
|
<table class="table table-bordered table-hover">
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
<h4 id="visit_duration"><%=Time.at(@data[@range][:avg_visit_time].round(2)).gmtime.strftime("%R:%S")%><br/><small class="muted">avg time spent</small></h4>
|
133
|
-
</td>
|
134
|
-
<td>
|
135
|
-
<h4 id="new_visits"><%=parse_float(((@data[@range][:total_new_visits].to_f/@data[@range][:total_visits].to_f)*100).round(2))%>%<br/><small class="muted">new visits</small></h4>
|
136
|
-
</td>
|
137
|
-
</tr>
|
54
|
+
<colgroup>
|
55
|
+
<col style="width: 33%"></col>
|
56
|
+
<col style="width: 33%"></col>
|
57
|
+
<col style="width: 33%"></col>
|
58
|
+
</colgroup>
|
59
|
+
<tr>
|
60
|
+
<td><%= erb :'widgets/bounce_rate' %></td>
|
61
|
+
<td><%= erb :'widgets/visit_duration' %></td>
|
62
|
+
<td><%= erb :'widgets/first_visits' %></td>
|
63
|
+
</tr>
|
138
64
|
</table>
|
139
65
|
</div>
|
140
|
-
|
141
|
-
</div>
|
142
|
-
|
143
|
-
|
144
|
-
</div>
|
145
|
-
|
146
|
-
<!-- Visits Modal -->
|
147
|
-
<div id="visits_modal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
|
148
|
-
<div class="modal-header">
|
149
|
-
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
150
|
-
<h3 id="myModalLabel">Daily Visits</h3>
|
151
|
-
</div>
|
152
|
-
<div class="modal-body">
|
153
|
-
<div id="visits_detail" style="width:900px;height:400px;"></div>
|
154
|
-
</div>
|
155
|
-
<div class="modal-footer">
|
156
|
-
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
|
157
|
-
<!-- <button class="btn btn-primary">Save changes</button> -->
|
158
|
-
</div>
|
159
|
-
</div>
|
160
|
-
|
161
|
-
<!-- Unique Visits Modal -->
|
162
|
-
<div id="unique_visits_modal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
|
163
|
-
<div class="modal-header">
|
164
|
-
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
165
|
-
<h3 id="myModalLabel">Daily Unique Visits</h3>
|
166
|
-
</div>
|
167
|
-
<div class="modal-body">
|
168
|
-
<div id="unique_visits_detail" style="width:900px;height:400px;"></div>
|
169
|
-
</div>
|
170
|
-
<div class="modal-footer">
|
171
|
-
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
|
172
|
-
<!-- <button class="btn btn-primary">Save changes</button> -->
|
173
66
|
</div>
|
174
67
|
</div>
|
175
68
|
|
176
|
-
|
69
|
+
<%# erb :'dialogs/visits' %>
|
70
|
+
<%# erb :'dialogs/unique_visits' %>
|
71
|
+
<%= erb :visits_js %>
|
@@ -1,262 +1,125 @@
|
|
1
1
|
<script type="text/javascript" language="text/javascript">
|
2
|
-
|
3
|
-
visits_area = Morris.Area({
|
4
|
-
element: 'visits_area',
|
5
|
-
xkey: 'date',
|
6
|
-
data: <%=@data[@range][:visits_new_visits_plot].to_json%>,
|
7
|
-
ykeys: ['new_visits', 'returning_visits'],
|
8
|
-
labels: ['New Visits', 'Returning Visits'],
|
9
|
-
ymax: 'auto',
|
10
|
-
//events: ['2013-03-02', '2013-03-03'],
|
11
|
-
grid: true,
|
12
|
-
eventStrokeWidth: 2,
|
13
|
-
eventLineColors: ['#ccc', '#eee'],
|
14
|
-
smooth: true,
|
15
|
-
hideHover: 'auto',
|
16
|
-
parseTime: false,
|
17
|
-
lineWidth: 1,
|
18
|
-
pointSize: 0,
|
19
|
-
// xLabels: 'day',
|
20
|
-
xLabelFormat: function(x) {return '';},
|
21
|
-
|
22
|
-
// hoverCallback: function(index, series)
|
23
|
-
// {
|
24
|
-
// h = series.data[index];
|
25
|
-
// d = Date(h.x);
|
26
|
-
// return(d + '<br>' + h.new_visits);
|
27
|
-
// },
|
28
|
-
pointFillColors: ['#fff'],
|
29
|
-
pointStrokeColors: ['#000'],
|
30
|
-
});
|
31
|
-
|
32
|
-
visits_donut = Morris.Donut({
|
33
|
-
element: 'visits_donut',
|
34
|
-
data: <%=@data[@range][:visits_new_visits_donut].to_json%>
|
35
|
-
});
|
36
|
-
|
37
|
-
referrers_donut = Morris.Donut({
|
38
|
-
element: 'referrers_donut',
|
39
|
-
data: <%=@data[@range][:referrers_donut].to_json%>
|
40
|
-
});
|
41
|
-
|
42
|
-
browsers_donut = Morris.Donut({
|
43
|
-
element: 'browsers_donut',
|
44
|
-
data: <%=@data[@range][:browsers_donut].to_json%>
|
45
|
-
});
|
46
|
-
|
47
|
-
unique_visits_line = Morris.Line({
|
48
|
-
element: 'unique_visits_line',
|
49
|
-
xkey: 'unit',
|
50
|
-
data: <%=@data[@range][:unique_visits].to_json%>,
|
51
|
-
ykeys: ['unique_visits_this', 'unique_visits_last'],
|
52
|
-
labels: ['Current', 'Previous'],
|
53
|
-
ymax: 'auto',
|
54
|
-
hideHover: 'auto',
|
55
|
-
parseTime: false,
|
56
|
-
lineWidth: 1,
|
57
|
-
pointSize: 0,
|
58
|
-
grid: true,
|
59
|
-
pointFillColors: ['#fff'],
|
60
|
-
pointStrokeColors: ['#000'],
|
61
|
-
// hoverCallback: function(index, series)
|
62
|
-
// {
|
63
|
-
// h = series.data[index];
|
64
|
-
// this_week_color = series.lineColors[0];
|
65
|
-
// last_week_color = series.lineColors[1];
|
66
|
-
// html = '';
|
67
|
-
// html += '<font style="color:' + this_week_color + '">This ' + h.unit + ': ' + h.unique_visits_this + '</font>';
|
68
|
-
// html += '<br/>';
|
69
|
-
// html += '<font style="color:' + last_week_color + '">Last ' + h.unit + ': ' + h.unique_visits_last + '</font>';
|
70
|
-
// return html;
|
71
|
-
// },
|
72
|
-
|
73
|
-
});
|
74
|
-
|
75
|
-
// visits_spark = Morris.Line({
|
76
|
-
// element: 'visits_spark',
|
77
|
-
// xkey: 'date',
|
78
|
-
// data: <%=@data[@range][:visits_page_views_plot].to_json%>,
|
79
|
-
// ykeys: ['visits', 'page_views'],
|
80
|
-
// labels: ['Visits', 'Page Views'],
|
81
|
-
// xLabelFormat: function(x){return '';},
|
82
|
-
// yLabelFormat: function(x){return '';},
|
83
|
-
// hoverCallback: function(i,x){return x.data[i].date + '<br/>' + 'Page Views: ' + x.data[i].page_views + '<br/>Visits: ' + x.data[i].visits;},
|
84
|
-
// ymax: 'auto',
|
85
|
-
// ymin: 0,
|
86
|
-
// smooth: true,
|
87
|
-
// hideHover: 'auto',
|
88
|
-
// parseTime: false,
|
89
|
-
// lineWidth: 2,
|
90
|
-
// pointSize: 0,
|
91
|
-
// grid: false,
|
92
|
-
// pointFillColors: ['#fff'],
|
93
|
-
// pointStrokeColors: ['#000']
|
94
|
-
// });
|
95
|
-
|
96
|
-
function setSessionCookie(name,value) {
|
97
|
-
document.cookie = name+"="+value+"; path=/";
|
98
|
-
}
|
99
|
-
|
100
2
|
function changeTimeFrame(range)
|
101
3
|
{
|
102
|
-
var mapObject = $('#world-map').vectorMap('get', 'mapObject');
|
103
|
-
switch(range)
|
104
|
-
{
|
105
|
-
<% Rack::RedisAnalytics.time_range_formats.
|
106
|
-
case '<%=range%>':
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
visits_donut = Morris.Donut({element: 'visits_donut', data: <%=@data[range.to_sym][:visits_new_visits_donut].to_json%>});
|
119
|
-
browsers_donut = Morris.Donut({element: 'browsers_donut', data: <%=@data[range.to_sym][:browsers_donut].to_json%>});
|
120
|
-
referrers_donut = Morris.Donut({element: 'referrers_donut', data: <%=@data[range.to_sym][:referrers_donut].to_json%>});
|
121
|
-
mapObject.series.regions[0].setValues(<%=@data[range.to_sym][:country_map].to_json%>);
|
122
|
-
|
123
|
-
$("#compare_unit")[0].innerHTML = '<%=range%>';
|
124
|
-
|
125
|
-
<% @data[range.to_sym][:visitor_recency_slices].each_with_index do |((k, v), i), c| %>
|
126
|
-
<% p = ((i.to_f/@data[range.to_sym][:visitor_recency_slices].map{|x| x[1]}.sum) * 100).round rescue '0' %>
|
127
|
-
<%= "$('#recency_#{c}')[0].style.width = '#{p}%';" %>
|
128
|
-
<%= "$('#recency_#{c}_num')[0].title = '#{i.to_i} visits';" %>
|
129
|
-
<%= "$('#recency_#{c}_cent')[0].innerHTML = '#{p}';" %>
|
130
|
-
<% end %>
|
4
|
+
var mapObject = $('#world-map').vectorMap('get', 'mapObject');
|
5
|
+
switch(range)
|
6
|
+
{
|
7
|
+
<% Rack::RedisAnalytics.time_range_formats.each do |range, unit, time_format| %>
|
8
|
+
case '<%=range%>':
|
9
|
+
setSessionCookie("_rarng", "<%=range%>");
|
10
|
+
|
11
|
+
// both time range graphs powered by time range data
|
12
|
+
$.ajax({
|
13
|
+
url: '<%=Rack::RedisAnalytics.api_endpoint + "/data?p=unique_visits,first_visits,repeat_visits&unit_count=#{(1.send(range)/1.send(unit)).round}&unit=#{unit}"%>',
|
14
|
+
dataType: "json",
|
15
|
+
success: function(data) {
|
16
|
+
visits_area.setData(data);
|
17
|
+
unique_visits_line.setData(data);
|
18
|
+
}
|
19
|
+
});
|
131
20
|
|
132
|
-
|
133
|
-
|
134
|
-
}
|
21
|
+
// aggregate data powers the 3 donuts
|
22
|
+
$.ajax({
|
23
|
+
url: '<%=Rack::RedisAnalytics.api_endpoint + "/data?p=first_visits,repeat_visits,browser,referrer,page_views,second_page_views,visit_time,recency&unit_count=#{(1.send(range)/1.send(unit)).round}&unit=#{unit}&aggregate=yes"%>',
|
24
|
+
dataType: "json",
|
25
|
+
success: function(data) {
|
26
|
+
|
27
|
+
// parse visits data from json
|
28
|
+
var visits_json_data = []
|
29
|
+
var first_visits = data[0].first_visits;
|
30
|
+
var repeat_visits = data[1].repeat_visits;
|
31
|
+
var total_visits = first_visits + repeat_visits;
|
32
|
+
var page_views = data[4].page_views;
|
33
|
+
var second_page_views = data[5].second_page_views;
|
34
|
+
var page_depth = (page_views/total_visits).toFixed(2);
|
35
|
+
var bounce_rate = (((total_visits - second_page_views)/total_visits) * 100).toFixed(2);
|
36
|
+
var percent_first_visits = ((first_visits / total_visits) * 100).toFixed(2);
|
37
|
+
var total_visit_time = data[6].visit_time;
|
38
|
+
var avg_visit_time = ((total_visit_time / total_visits)).toFixed(2);
|
39
|
+
var total_recency = data[7].recency;
|
40
|
+
|
41
|
+
if(total_visits != 0)
|
42
|
+
visits_json_data.push({'label': 'First Visits', 'value': first_visits});
|
43
|
+
if(total_visits != 0)
|
44
|
+
visits_json_data.push({'label': 'Repeat Visits', 'value': repeat_visits});
|
45
|
+
visits_donut = Morris.Donut({element: 'visits_donut', data: visits_json_data});
|
46
|
+
$("#total_visits")[0].innerHTML = total_visits + ' <small class="muted">visits</small>';
|
47
|
+
$("#total_page_views")[0].innerHTML = page_views + ' <small class="muted">page views</small>';
|
48
|
+
$("#page_depth")[0].innerHTML = (isNaN(page_depth) ? '?' : page_depth) + ' <small class="muted">pages per visit</small>';
|
49
|
+
$("#bounce_rate")[0].innerHTML = (isNaN(bounce_rate) ? '?' : bounce_rate + '%') + ' <small class="muted">bounce rate</small>';
|
50
|
+
$("#visit_duration")[0].innerHTML = (isNaN(avg_visit_time) ? '?' : avg_visit_time + ' sec') + ' <small class="muted">avg time spent</small>';
|
51
|
+
$("#first_visits")[0].innerHTML = (isNaN(percent_first_visits) ? '?' : percent_first_visits + '%') + ' <small class="muted">new visits</small></h4>';
|
52
|
+
|
53
|
+
// parse browser data from json
|
54
|
+
var browsers_json_data = [];
|
55
|
+
for(var i in data[2].browser)
|
56
|
+
{
|
57
|
+
var browser_data = {}
|
58
|
+
browser_data[i] = data[2].browser[i];
|
59
|
+
browser_data['label'] = i;
|
60
|
+
browser_data['value'] = data[2].browser[i];
|
61
|
+
browsers_json_data.push(browser_data);
|
62
|
+
}
|
63
|
+
browsers_donut = Morris.Donut({element: 'browsers_donut', data: browsers_json_data});
|
64
|
+
|
65
|
+
// parse referrer data from json
|
66
|
+
var referrers_json_data = [];
|
67
|
+
for(var i in data[3].referrer)
|
68
|
+
{
|
69
|
+
var referrer_data = {}
|
70
|
+
referrer_data['label'] = i;
|
71
|
+
referrer_data['value'] = data[3].referrer[i];
|
72
|
+
referrers_json_data.push(referrer_data);
|
73
|
+
}
|
74
|
+
referrers_donut = Morris.Donut({element: 'referrers_donut', data: referrers_json_data});
|
75
|
+
var rec_day = !isNaN(total_recency['d']) ? total_recency['d'] : 0;
|
76
|
+
var rec_week = !isNaN(total_recency['w']) ? total_recency['w'] : 0;
|
77
|
+
var rec_month = !isNaN(total_recency['m']) ? total_recency['m'] : 0;
|
78
|
+
var rec_other = !isNaN(total_recency['o']) ? total_recency['o'] : 0;
|
79
|
+
var rec_total = rec_day + rec_week + rec_month + rec_other;
|
80
|
+
|
81
|
+
if(rec_total > 0)
|
82
|
+
{
|
83
|
+
$("#recency_d_bar")[0].style.width = $("#recency_d_cent")[0].innerHTML = (rec_day/rec_total) * 100 + '%';
|
84
|
+
$("#recency_w_bar")[0].style.width = $("#recency_w_cent")[0].innerHTML = (rec_week/rec_total) * 100 + '%';
|
85
|
+
$("#recency_m_bar")[0].style.width = $("#recency_m_cent")[0].innerHTML = (rec_month/rec_total) * 100 + '%';
|
86
|
+
$("#recency_o_bar")[0].style.width = $("#recency_o_cent")[0].innerHTML = (rec_other/rec_total) * 100 + '%';
|
87
|
+
|
88
|
+
$("#recency_d")[0].title = rec_day + ' visits';
|
89
|
+
$("#recency_w")[0].title = rec_week + ' visits';
|
90
|
+
$("#recency_m")[0].title = rec_month + ' visits';
|
91
|
+
$("#recency_o")[0].title = rec_other + ' visits';
|
92
|
+
}
|
93
|
+
|
94
|
+
}
|
95
|
+
});
|
96
|
+
|
97
|
+
|
98
|
+
break;
|
99
|
+
<% end %>
|
100
|
+
}
|
135
101
|
}
|
136
102
|
|
137
|
-
// Map Overlay
|
138
|
-
|
139
|
-
var geoLocationData = <%=@data[@range][:country_map].to_json%>;
|
140
|
-
|
141
|
-
$(function(){
|
142
|
-
$('#world-map').vectorMap({
|
143
|
-
map: 'world_mill_en',
|
144
|
-
min: 0,
|
145
|
-
backgroundColor: '#fff',
|
146
|
-
regionStyle: {
|
147
|
-
initial: {
|
148
|
-
fill: '#ddd',
|
149
|
-
"fill-opacity": 1,
|
150
|
-
stroke: 'none',
|
151
|
-
"stroke-width": 0,
|
152
|
-
"stroke-opacity": 1
|
153
|
-
},
|
154
|
-
hover: {
|
155
|
-
fill: '#bbb',
|
156
|
-
"fill-opacity": 0.8
|
157
|
-
},
|
158
|
-
selected: {
|
159
|
-
fill: 'yellow'
|
160
|
-
},
|
161
|
-
selectedHover: {
|
162
|
-
}
|
163
|
-
},
|
164
|
-
series: {
|
165
|
-
regions: [{
|
166
|
-
scale: ['#C8EEFF', '#0071A4'],
|
167
|
-
values: geoLocationData,
|
168
|
-
normalizeFunction: 'polynomial'
|
169
|
-
}]
|
170
|
-
},
|
171
|
-
onLabelShow: function(e, el, code){
|
172
|
-
el.html(el.html()+' (GDP - '+geoLocationData[code]+')');
|
173
|
-
}
|
174
|
-
});
|
175
|
-
});
|
176
103
|
|
177
|
-
function
|
178
|
-
document.
|
179
|
-
encodeURIComponent(convertToCSV(<%=@data[@range][:visits_new_visits_plot].to_json%>));
|
104
|
+
function setSessionCookie(name,value) {
|
105
|
+
document.cookie = name+"="+value+"; path=/";
|
180
106
|
}
|
181
107
|
|
182
108
|
function convertToCSV(objArray) {
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
}
|
196
|
-
|
197
|
-
return str;
|
198
|
-
};
|
199
|
-
|
200
|
-
$('#visits_modal').on('show', function () {
|
201
|
-
|
202
|
-
colors = Highcharts.getOptions().colors;
|
203
|
-
|
204
|
-
// create the chart when all data is loaded
|
205
|
-
$(function(){
|
206
|
-
|
207
|
-
$('#visits_detail').highcharts('StockChart', {
|
208
|
-
chart: {
|
209
|
-
},
|
210
|
-
|
211
|
-
// tooltip: {
|
212
|
-
// pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.y}</b> ({point.change}%)<br/>',
|
213
|
-
// valueDecimals: 2
|
214
|
-
// },
|
215
|
-
yAxis: {
|
216
|
-
allowDecimals: false
|
217
|
-
},
|
218
|
-
xAxis: {
|
219
|
-
allowDecimals: false
|
220
|
-
},
|
221
|
-
|
222
|
-
series: [{
|
223
|
-
name: 'Visits',
|
224
|
-
data: <%=@data[:all_visits].to_json%>
|
225
|
-
}]
|
226
|
-
});
|
227
|
-
});
|
228
|
-
});
|
109
|
+
var array = typeof objArray != 'object' ? JSON.parse(objArray) : objArray;
|
110
|
+
var str = '';
|
111
|
+
for (var i = 0; i < array.length; i++) {
|
112
|
+
var line = '';
|
113
|
+
for (var index in array[i]) {
|
114
|
+
if (line != '') line += ','
|
115
|
+
line += array[i][index];
|
116
|
+
}
|
117
|
+
str += line + '\r\n';
|
118
|
+
}
|
119
|
+
return str;
|
120
|
+
};
|
229
121
|
|
230
122
|
|
231
|
-
$('#unique_visits_modal').on('show', function () {
|
232
|
-
|
233
|
-
colors = Highcharts.getOptions().colors;
|
234
|
-
|
235
|
-
// create the chart when all data is loaded
|
236
|
-
$(function(){
|
237
|
-
|
238
|
-
$('#unique_visits_detail').highcharts('StockChart', {
|
239
|
-
chart: {
|
240
|
-
},
|
241
|
-
|
242
|
-
// tooltip: {
|
243
|
-
// pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.y}</b> ({point.change}%)<br/>',
|
244
|
-
// valueDecimals: 2
|
245
|
-
// },
|
246
|
-
yAxis: {
|
247
|
-
allowDecimals: false
|
248
|
-
},
|
249
|
-
xAxis: {
|
250
|
-
allowDecimals: false
|
251
|
-
},
|
252
|
-
|
253
|
-
series: [{
|
254
|
-
name: 'Unique Visits',
|
255
|
-
data: <%=@data[:all_unique_visits].to_json%>
|
256
|
-
}]
|
257
|
-
});
|
258
|
-
});
|
259
|
-
});
|
260
123
|
|
261
124
|
</script>
|
262
125
|
|