active_analytics 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +27 -6
- data/app/assets/images/active_analytics.png +0 -0
- data/app/assets/images/active_analytics_screenshot.png +0 -0
- data/app/assets/javascripts/active_analytics/application.js +13 -0
- data/app/assets/stylesheets/active_analytics/application.css +1 -19
- data/app/assets/stylesheets/active_analytics/charts.css +80 -2262
- data/app/assets/stylesheets/active_analytics/style.css +161 -0
- data/app/controllers/active_analytics/application_controller.rb +12 -0
- data/app/controllers/active_analytics/pages_controller.rb +10 -7
- data/app/controllers/active_analytics/referrers_controller.rb +6 -4
- data/app/controllers/active_analytics/sites_controller.rb +5 -2
- data/app/helpers/active_analytics/application_helper.rb +3 -0
- data/app/helpers/active_analytics/sites_helper.rb +3 -0
- data/app/models/active_analytics/views_per_day.rb +26 -7
- data/app/views/active_analytics/pages/_table.html.erb +31 -19
- data/app/views/active_analytics/pages/index.html.erb +4 -7
- data/app/views/active_analytics/pages/show.html.erb +18 -15
- data/app/views/active_analytics/referrers/_table.html.erb +21 -14
- data/app/views/active_analytics/referrers/index.html.erb +4 -3
- data/app/views/active_analytics/referrers/show.html.erb +14 -9
- data/app/views/active_analytics/sites/_histogram.html.erb +15 -19
- data/app/views/active_analytics/sites/index.html.erb +12 -7
- data/app/views/active_analytics/sites/show.html.erb +12 -12
- data/app/views/layouts/active_analytics/_footer.html.erb +45 -3
- data/app/views/layouts/active_analytics/_header.html.erb +47 -21
- data/app/views/layouts/active_analytics/application.html.erb +15 -14
- data/db/migrate/20210303094108_create_active_analytics_views_per_days.rb +1 -1
- data/lib/active_analytics.rb +2 -4
- data/lib/active_analytics/version.rb +1 -1
- metadata +7 -4
@@ -0,0 +1,161 @@
|
|
1
|
+
body {
|
2
|
+
padding: 0;
|
3
|
+
margin: 0;
|
4
|
+
width: 100%;
|
5
|
+
}
|
6
|
+
|
7
|
+
body > header nav {
|
8
|
+
width: 100%;
|
9
|
+
max-width: 1280px;
|
10
|
+
margin: 0 auto;
|
11
|
+
padding: 24px;
|
12
|
+
display: flex;
|
13
|
+
flex-wrap: wrap;
|
14
|
+
align-items: center;
|
15
|
+
min-height: 88px;
|
16
|
+
}
|
17
|
+
|
18
|
+
header nav .menubutton {
|
19
|
+
margin-left: auto;
|
20
|
+
}
|
21
|
+
|
22
|
+
header .logo {
|
23
|
+
margin-right: 8px;
|
24
|
+
}
|
25
|
+
|
26
|
+
header .logo svg {
|
27
|
+
width: 24px;
|
28
|
+
height: 24px;
|
29
|
+
fill: none;
|
30
|
+
stroke: rgba(var(--color-blue-500), 1);
|
31
|
+
stroke-width: 1;
|
32
|
+
}
|
33
|
+
|
34
|
+
header .is-link {
|
35
|
+
text-transform: none;
|
36
|
+
text-decoration: none;
|
37
|
+
font-size: 1rem;
|
38
|
+
letter-spacing: 0;
|
39
|
+
font-weight: 400;
|
40
|
+
padding: 0 16px;
|
41
|
+
margin: 0;
|
42
|
+
min-height: 24px;
|
43
|
+
color: rgba(var(--color-grey-700), 1);
|
44
|
+
}
|
45
|
+
|
46
|
+
header .is-link:hover {
|
47
|
+
background: rgba(var(--color-grey-50), 1);
|
48
|
+
}
|
49
|
+
|
50
|
+
main {
|
51
|
+
width: 100%;
|
52
|
+
max-width: 1280px;
|
53
|
+
margin: 0 auto;
|
54
|
+
padding: 0 24px;
|
55
|
+
}
|
56
|
+
|
57
|
+
main h2 {
|
58
|
+
word-break: break-word;
|
59
|
+
}
|
60
|
+
|
61
|
+
section {
|
62
|
+
margin-bottom: var(--space-4x);
|
63
|
+
}
|
64
|
+
|
65
|
+
.grid-auto {
|
66
|
+
--col-min-width: calc(var(--space) * 38);
|
67
|
+
}
|
68
|
+
|
69
|
+
.tooltip-date {
|
70
|
+
color: rgba(var(--color-grey-100), 1);
|
71
|
+
}
|
72
|
+
|
73
|
+
.card {
|
74
|
+
position: relative;
|
75
|
+
overflow: visible;
|
76
|
+
}
|
77
|
+
|
78
|
+
.card h3 {
|
79
|
+
display: flex;
|
80
|
+
}
|
81
|
+
|
82
|
+
.card h3 a {
|
83
|
+
margin-left: auto;
|
84
|
+
font-weight: 400;
|
85
|
+
font-size: 1rem;
|
86
|
+
}
|
87
|
+
|
88
|
+
.card table {
|
89
|
+
margin: 0 -24px;
|
90
|
+
width: calc(100% + 48px);
|
91
|
+
}
|
92
|
+
|
93
|
+
.card table.charts-css {
|
94
|
+
margin-bottom: -24px;
|
95
|
+
}
|
96
|
+
|
97
|
+
tr td:first-of-type {
|
98
|
+
padding: 12px 0px 12px 24px;
|
99
|
+
}
|
100
|
+
|
101
|
+
tr td:last-of-type {
|
102
|
+
padding: 12px 24px 12px 0;
|
103
|
+
}
|
104
|
+
|
105
|
+
td a {
|
106
|
+
word-break: break-word;
|
107
|
+
}
|
108
|
+
|
109
|
+
td.number {
|
110
|
+
text-align: right;
|
111
|
+
font-variant-numeric: tabular-nums;
|
112
|
+
}
|
113
|
+
|
114
|
+
.referer-favicon {
|
115
|
+
width: 16px;
|
116
|
+
height: 16px;
|
117
|
+
display: inline-block;
|
118
|
+
position: relative;
|
119
|
+
top: 3px;
|
120
|
+
margin-right: 4px;
|
121
|
+
}
|
122
|
+
|
123
|
+
div.is-empty {
|
124
|
+
display: flex;
|
125
|
+
align-items: center;
|
126
|
+
justify-content: center;
|
127
|
+
height: calc(100% - 72px);
|
128
|
+
width: 100%;
|
129
|
+
color: rgba(var(--color-grey-300), 1);
|
130
|
+
}
|
131
|
+
|
132
|
+
body > footer {
|
133
|
+
max-width: 1280px;
|
134
|
+
margin: 48px auto 0;
|
135
|
+
padding: 24px;
|
136
|
+
}
|
137
|
+
|
138
|
+
body > footer ul {
|
139
|
+
margin: 0;
|
140
|
+
list-style-type: none;
|
141
|
+
padding: 0;
|
142
|
+
}
|
143
|
+
|
144
|
+
body > footer .card {
|
145
|
+
margin: 0;
|
146
|
+
background: rgba(var(--color-grey-50), 1);
|
147
|
+
}
|
148
|
+
body > footer .card p {
|
149
|
+
padding: 0 0 2px;
|
150
|
+
color: rgba(var(--color-grey-400), 1);
|
151
|
+
}
|
152
|
+
|
153
|
+
@media (max-width: 480px) {
|
154
|
+
header nav .menubutton {
|
155
|
+
margin-top: 24px;
|
156
|
+
}
|
157
|
+
|
158
|
+
[role="dialog"] {
|
159
|
+
min-width: 280px;
|
160
|
+
}
|
161
|
+
}
|
@@ -1,4 +1,16 @@
|
|
1
1
|
module ActiveAnalytics
|
2
2
|
class ApplicationController < ActionController::Base
|
3
|
+
|
4
|
+
private
|
5
|
+
|
6
|
+
def require_date_range
|
7
|
+
if params[:from].blank? || params[:to].blank?
|
8
|
+
redirect_to(params.to_unsafe_hash.merge(from: 7.days.ago.to_date, to: Date.today))
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def current_views_per_days
|
13
|
+
ViewsPerDay.where(site: params[:site]).between_dates(params[:from], params[:to])
|
14
|
+
end
|
3
15
|
end
|
4
16
|
end
|
@@ -4,19 +4,22 @@ module ActiveAnalytics
|
|
4
4
|
class PagesController < ApplicationController
|
5
5
|
include PagesHelper
|
6
6
|
|
7
|
+
before_action :require_date_range
|
8
|
+
|
7
9
|
def index
|
8
|
-
scope = ViewsPerDay.where(site: params[:site]).
|
9
|
-
@histogram = ViewsPerDay::Histogram.new(scope.order_by_date.group_by_date)
|
10
|
+
scope = ViewsPerDay.where(site: params[:site]).between_dates(params[:from], params[:to])
|
11
|
+
@histogram = ViewsPerDay::Histogram.new(scope.order_by_date.group_by_date, params[:from], params[:to])
|
10
12
|
@pages = scope.top(100).group_by_page
|
11
13
|
end
|
12
14
|
|
13
15
|
def show
|
14
|
-
|
15
|
-
|
16
|
-
@
|
16
|
+
dates_scopes = ViewsPerDay.between_dates(params[:from], params[:to])
|
17
|
+
page_scope = dates_scopes.where(site: params[:site], page: page_from_params)
|
18
|
+
@histogram = ViewsPerDay::Histogram.new(page_scope.order_by_date.group_by_date, params[:from], params[:to])
|
19
|
+
@referrers = page_scope.top.group_by_referrer_site
|
17
20
|
|
18
|
-
@next_pages =
|
19
|
-
@previous_pages =
|
21
|
+
@next_pages = dates_scopes.where(referrer_host: params[:site], referrer_path: page_from_params).top(100).group_by_page
|
22
|
+
@previous_pages = dates_scopes.where(site: params[:site], page: page_from_params).where.not(referrer_path: nil).top(100).group_by_referrer_page
|
20
23
|
end
|
21
24
|
end
|
22
25
|
end
|
@@ -2,15 +2,17 @@ require_dependency "active_analytics/application_controller"
|
|
2
2
|
|
3
3
|
module ActiveAnalytics
|
4
4
|
class ReferrersController < ApplicationController
|
5
|
+
before_action :require_date_range
|
6
|
+
|
5
7
|
def index
|
6
|
-
scope = ViewsPerDay.where(site: params[:site])
|
8
|
+
scope = ViewsPerDay.where(site: params[:site]).between_dates(params[:from], params[:to])
|
7
9
|
@referrers = scope.top(100).group_by_referrer_site
|
8
|
-
@histogram = ViewsPerDay::Histogram.new(scope.order_by_date.group_by_date)
|
10
|
+
@histogram = ViewsPerDay::Histogram.new(scope.order_by_date.group_by_date, params[:from], params[:to])
|
9
11
|
end
|
10
12
|
|
11
13
|
def show
|
12
|
-
scope = ViewsPerDay.where(site: params[:site], referrer_host: params[:referrer])
|
13
|
-
@histogram = ViewsPerDay::Histogram.new(scope.order_by_date.group_by_date)
|
14
|
+
scope = ViewsPerDay.where(site: params[:site], referrer_host: params[:referrer]).between_dates(params[:from], params[:to])
|
15
|
+
@histogram = ViewsPerDay::Histogram.new(scope.order_by_date.group_by_date, params[:from], params[:to])
|
14
16
|
@previous_pages = scope.top(100).group_by_referrer_page
|
15
17
|
@next_pages = scope.top(100).group_by_page
|
16
18
|
end
|
@@ -2,13 +2,16 @@ require_dependency "active_analytics/application_controller"
|
|
2
2
|
|
3
3
|
module ActiveAnalytics
|
4
4
|
class SitesController < ApplicationController
|
5
|
+
before_action :require_date_range, only: :show
|
6
|
+
|
5
7
|
def index
|
6
8
|
@sites = ViewsPerDay.after(30.days.ago).order_by_totals.group_by_site
|
9
|
+
redirect_to(site_path(@sites.first.host)) if @sites.size == 1
|
7
10
|
end
|
8
11
|
|
9
12
|
def show
|
10
|
-
scope =
|
11
|
-
@histogram = ViewsPerDay::Histogram.new(scope.order_by_date.group_by_date)
|
13
|
+
scope = current_views_per_days
|
14
|
+
@histogram = ViewsPerDay::Histogram.new(scope.order_by_date.group_by_date, params[:from], params[:to])
|
12
15
|
@referrers = scope.top.group_by_referrer_site
|
13
16
|
@pages = scope.top.group_by_page
|
14
17
|
end
|
@@ -2,6 +2,7 @@ module ActiveAnalytics
|
|
2
2
|
class ViewsPerDay < ApplicationRecord
|
3
3
|
validates_presence_of :site, :page, :date
|
4
4
|
|
5
|
+
scope :between_dates, -> (from, to) { where("date BETWEEN ? AND ?", from, to) }
|
5
6
|
scope :after, -> (date) { where("date > ?", date) }
|
6
7
|
scope :order_by_totals, -> { order(Arel.sql("SUM(total) DESC")) }
|
7
8
|
scope :order_by_date, -> { order(:date) }
|
@@ -33,21 +34,37 @@ module ActiveAnalytics
|
|
33
34
|
end
|
34
35
|
|
35
36
|
class Histogram
|
36
|
-
attr_reader :bars
|
37
|
+
attr_reader :bars, :from_date, :to_date
|
37
38
|
|
38
|
-
def initialize(scope)
|
39
|
+
def initialize(scope, from_date, to_date)
|
39
40
|
@bars = scope.map { |day| Bar.new(day.day, day.total, self) }
|
41
|
+
fill_missing_days(@bars, Date.parse(from_date.to_s), Date.parse(to_date.to_s))
|
42
|
+
end
|
43
|
+
|
44
|
+
def fill_missing_days(bars, from, to)
|
45
|
+
i = 0
|
46
|
+
while (day = from + i) <= to
|
47
|
+
if !@bars[i] || @bars[i].label != day
|
48
|
+
@bars.insert(i, Bar.new(day, 0, self))
|
49
|
+
end
|
50
|
+
i += 1
|
51
|
+
end
|
52
|
+
@bars
|
40
53
|
end
|
41
54
|
|
42
55
|
def max_value
|
43
56
|
@max_total ||= bars.map(&:value).max
|
44
57
|
end
|
45
58
|
|
59
|
+
def total
|
60
|
+
@bars.reduce(0) { |sum, bar| sum += bar.value }
|
61
|
+
end
|
62
|
+
|
46
63
|
class Bar
|
47
64
|
attr_reader :label, :value, :histogram
|
48
65
|
|
49
66
|
def initialize(label, value, histogram)
|
50
|
-
@label, @value
|
67
|
+
@label, @value, @histogram = label, value, histogram
|
51
68
|
end
|
52
69
|
|
53
70
|
def height
|
@@ -91,10 +108,12 @@ module ActiveAnalytics
|
|
91
108
|
end
|
92
109
|
|
93
110
|
def self.append(params)
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
111
|
+
params[:site] = params[:site].downcase if params[:site]
|
112
|
+
params[:page] = params[:page].downcase if params[:page]
|
113
|
+
params[:referrer_path] = nil if params[:referrer_path].blank?
|
114
|
+
params[:referrer_path] = params[:referrer_path].downcase if params[:referrer_path]
|
115
|
+
params[:referrer_host] = params[:referrer_host].downcase if params[:referrer_host]
|
116
|
+
find_or_create_by!(params) if where(params).update_all("total = total + 1") == 0
|
98
117
|
end
|
99
118
|
end
|
100
119
|
end
|
@@ -1,21 +1,33 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
1
|
+
|
2
|
+
<% if pages.empty? %>
|
3
|
+
<div class="is-empty">
|
4
|
+
<span>no data</span>
|
5
|
+
</div>
|
6
|
+
<% else %>
|
7
|
+
<table>
|
8
|
+
<% for page in pages %>
|
9
|
+
<tr>
|
10
|
+
<td>
|
11
|
+
<% if page.host == params[:site] %>
|
12
|
+
<% if page.path.present? %>
|
13
|
+
<%= link_to page.path, page_path(site: page.host, page: page_to_params(page.path), from: params[:from], to: params[:to]) %>
|
14
|
+
<% else %>
|
15
|
+
<%= site_icon page.host %>
|
16
|
+
<%= link_to page.host, site_path(site: page.host, from: params[:from], to: params[:to]) %>
|
17
|
+
<small>(page not provided <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy#strict-origin-when-cross-origin">?</a>)</small>
|
18
|
+
<% end %>
|
19
|
+
<% elsif page.host.present? && page.path.present? %>
|
20
|
+
<%= link_to(referrer_path(site: params[:site], referrer: page.host, from: params[:from], to: params[:to])) { site_icon page.host } %>
|
21
|
+
<%= link_to page.url, referrer_path(site: params[:site], referrer: page.host, from: params[:from], to: params[:to]) %>
|
22
|
+
<% elsif page.host.present? %>
|
23
|
+
<%= site_icon page.host %>
|
24
|
+
<%= page.host %>
|
8
25
|
<% else %>
|
9
|
-
|
10
|
-
<small>(page not provided <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy#strict-origin-when-cross-origin">?</a>)</small>
|
26
|
+
(None or direct)
|
11
27
|
<% end %>
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
<td><%= page.total %></td>
|
19
|
-
</tr>
|
20
|
-
<% end %>
|
21
|
-
</table>
|
28
|
+
</td>
|
29
|
+
<td class="number"><%= format_view_count page.total %></td>
|
30
|
+
</tr>
|
31
|
+
<% end %>
|
32
|
+
</table>
|
33
|
+
<% end %>
|
@@ -1,12 +1,9 @@
|
|
1
|
-
<section>
|
2
|
-
<
|
3
|
-
</section>
|
4
|
-
|
5
|
-
<section>
|
1
|
+
<section class="card">
|
2
|
+
<h3><%= format_view_count @histogram.total %> views</h3>
|
6
3
|
<%= render "/active_analytics/sites/histogram", histogram: @histogram %>
|
7
4
|
</section>
|
8
5
|
|
9
|
-
<section>
|
10
|
-
<h3>
|
6
|
+
<section class="card">
|
7
|
+
<h3>Top pages</h3>
|
11
8
|
<%= render "/active_analytics/pages/table", pages: @pages %>
|
12
9
|
</section>
|
@@ -2,22 +2,25 @@
|
|
2
2
|
<h2><%= page_from_params %></h2>
|
3
3
|
</section>
|
4
4
|
|
5
|
-
<section>
|
6
|
-
<h3
|
5
|
+
<section class="card">
|
6
|
+
<h3><%= format_view_count @histogram.total %> views</h3>
|
7
7
|
<%= render "/active_analytics/sites/histogram", histogram: @histogram %>
|
8
8
|
</section>
|
9
9
|
|
10
|
-
<
|
11
|
-
<
|
12
|
-
|
13
|
-
</
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
10
|
+
<ul class="grid-auto">
|
11
|
+
<li class="card">
|
12
|
+
<!-- <section>
|
13
|
+
<h3>Top sources</h3>
|
14
|
+
<%= render "/active_analytics/referrers/table", referrers: @referrers %>
|
15
|
+
</section> -->
|
16
|
+
<section>
|
17
|
+
<h3>Previous page</h3>
|
18
|
+
<%= render "table", pages: @previous_pages %>
|
19
|
+
</section>
|
20
|
+
</li>
|
19
21
|
|
20
|
-
<
|
21
|
-
|
22
|
-
|
23
|
-
</
|
22
|
+
<li class="card">
|
23
|
+
<h3>Next page</h3>
|
24
|
+
<%= render "table", pages: @next_pages %>
|
25
|
+
</li>
|
26
|
+
</ul>
|