totalizer 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +36 -10
- data/lib/tasks/totalizer.rake +12 -4
- data/lib/totalizer/base.rb +10 -0
- data/lib/totalizer/factory.rb +9 -2
- data/lib/totalizer/message.rb +14 -7
- data/lib/totalizer/version.rb +1 -1
- data/spec/lib/totalizer/factory_spec.rb +30 -8
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4168eb566d3334c9710a3f461640552537773c8f
|
4
|
+
data.tar.gz: 40691a8c784e3d4ab21e40bb2321545dd9333b3f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 19fa70b6a453e6d137cebb9da4da276f16e4d5c6a50c730afb96928852a0dccc9a49484710d079f70df51a3d3202692f020aeaa841f2c7c49500071706cc3737
|
7
|
+
data.tar.gz: c3ed4b77d762ff54cf27b97c108e93be3d00eca03d3b8f5e8a4067c5fd60136fd8ea7d9f77310c754f27861187aa247df41fa16d1c7026e0e42cf0dc53fee251
|
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
# Totalizer - Calculate and share
|
1
|
+
# Totalizer - Calculate and share product and engagement metrics in your Rails application.
|
2
2
|
|
3
|
-
Totalizer makes it easy for Ruby on Rails developers to report on
|
3
|
+
Totalizer makes it easy for Ruby on Rails developers to report on Product and Engagement metrics.
|
4
4
|
|
5
|
-
By defining
|
5
|
+
By defining three metrics, Growth, Vanity and Key Activity, you can generate reports on Acquisition, Activity, Vanity, Activation, Engagement, Retention and Churn.
|
6
6
|
|
7
7
|
Metrics are only worthwhile if your team sees them so Totalizer includes notifiers for Slack and email.
|
8
8
|
|
@@ -28,6 +28,7 @@ You need to define your Growth Metric and Key Activity Metric in order to use To
|
|
28
28
|
# config/initializers/totalizer.rb
|
29
29
|
|
30
30
|
Totalizer.growth_metric = Totalizer::Metric.new model: User
|
31
|
+
Totalizer.vanity_metric = Totalizer::Metric.new model: Post
|
31
32
|
Totalizer.activity_metric = Totalizer::Metric.new model: Post, map: 'user_id'
|
32
33
|
```
|
33
34
|
|
@@ -139,20 +140,21 @@ This will generate the following report:
|
|
139
140
|
|
140
141
|
```
|
141
142
|
Acquisition
|
142
|
-
Yesterday: 20 (∆ 10%)
|
143
|
-
Last 7 days: 100 (∆ 7%)
|
144
143
|
Signed up this period (with rate of change)
|
144
|
+
Yesterday: 20 (∆ 10%)
|
145
|
+
Vanity
|
146
|
+
Total this period (with rate of change)
|
147
|
+
Yesterday: 15 (∆ 5%)
|
145
148
|
Activity
|
146
|
-
Yesterday: 60 (∆ 9%)
|
147
|
-
Last 7 days: 120 (∆ 8%)
|
148
149
|
Key activities this period (with rate of change)
|
150
|
+
Yesterday: 60 (∆ 9%)
|
149
151
|
```
|
150
152
|
|
151
153
|
### Weekly
|
152
154
|
|
153
|
-
Every week it
|
155
|
+
Every week it's important to review your important metrics to ensure you are trending in the right direction.
|
154
156
|
|
155
|
-
Totalizer generates your Activation, Engagement, Retention and Churn for the previous week and previous month.
|
157
|
+
Totalizer generates your Acquisition, Vanity, Activity, Activation, Engagement, Retention and Churn for the previous week and previous month.
|
156
158
|
|
157
159
|
```
|
158
160
|
$ rake totalizer:weekly
|
@@ -161,6 +163,18 @@ $ rake totalizer:weekly
|
|
161
163
|
This will generate the following report:
|
162
164
|
|
163
165
|
```
|
166
|
+
Acquisition
|
167
|
+
Signed up this period (with rate of change)
|
168
|
+
Last 7 days: 77 (∆ 7%)
|
169
|
+
Last 30 days: 444 (∆ 10%)
|
170
|
+
Vanity
|
171
|
+
Total this period (with rate of change)
|
172
|
+
Last 7 days: 92 (∆ 4%)
|
173
|
+
Last 30 days: 412 (∆ 5%)
|
174
|
+
Activity
|
175
|
+
Key activities this period (with rate of change)
|
176
|
+
Last 7 days: 120 (∆ 8%)
|
177
|
+
Last 30 days: 250 (∆ 6%)
|
164
178
|
Activation
|
165
179
|
Created this period and did key activity
|
166
180
|
Last 7 days: 77 → 58 (75.32%)
|
@@ -179,6 +193,18 @@ Churn
|
|
179
193
|
Last 30 days: 3.29% (34/1032)
|
180
194
|
```
|
181
195
|
|
196
|
+
To change the descriptions for each metric you can add the following to your
|
197
|
+
initializer:
|
198
|
+
|
199
|
+
```ruby
|
200
|
+
Totalizer.descriptions.acquisition = "New users"
|
201
|
+
Totalizer.descriptions.vanity = "Posts created"
|
202
|
+
Totalizer.descriptions.activity = "Users who created post"
|
203
|
+
Totalizer.descriptions.engagement = "Existing users who created post"
|
204
|
+
Totalizer.descriptions.retention = "Existing user who created post again"
|
205
|
+
Totalizer.descriptions.churn = "Existing user who did not do key activity"
|
206
|
+
```
|
207
|
+
|
182
208
|
### Combined
|
183
209
|
|
184
210
|
You can also run a single rake task every day which will run execute the daily
|
@@ -198,7 +224,7 @@ To change the week day add the following line to your initializer:
|
|
198
224
|
Totalizer.weekly_day = 0 #(0-6, Sunday is zero)
|
199
225
|
```
|
200
226
|
|
201
|
-
|
227
|
+
---
|
202
228
|
|
203
229
|
In addition to Metric, you can also use the following underlying objects.
|
204
230
|
|
data/lib/tasks/totalizer.rake
CHANGED
@@ -2,13 +2,15 @@ namespace :totalizer do
|
|
2
2
|
task validate: :environment do
|
3
3
|
abort '! Growth metric not defined. Please define your growth metric before running this task. See https://github.com/micdijkstra/totalizer' unless Totalizer.growth_metric
|
4
4
|
abort '! Activity metric not defined. Please define your growth metric before running this task. See https://github.com/micdijkstra/totalizer' unless Totalizer.activity_metric
|
5
|
+
abort '! Vanity metric not defined. Please define your vanity metric before running this task. See https://github.com/micdijkstra/totalizer' unless Totalizer.vanity_metric
|
5
6
|
end
|
6
7
|
|
7
8
|
task daily: :validate do
|
8
9
|
Totalizer.logger.info "Totalizer: Daily"
|
9
10
|
messages = {
|
10
|
-
acquisition: [Totalizer.generate(:acquisition, 1)
|
11
|
-
|
11
|
+
acquisition: [Totalizer.generate(:acquisition, 1)],
|
12
|
+
vanity: [Totalizer.generate(:vanity, 1)],
|
13
|
+
activity: [Totalizer.generate(:activity, 1)],
|
12
14
|
}
|
13
15
|
Totalizer.notify messages
|
14
16
|
end
|
@@ -16,6 +18,9 @@ namespace :totalizer do
|
|
16
18
|
task weekly: :validate do
|
17
19
|
Totalizer.logger.info "Totalizer: Weekly"
|
18
20
|
messages = {
|
21
|
+
acquisition: [Totalizer.generate(:acquisition, 7), Totalizer.generate(:acquisition, 30)],
|
22
|
+
vanity: [Totalizer.generate(:vanity, 7), Totalizer.generate(:vanity, 30)],
|
23
|
+
activity: [Totalizer.generate(:activity, 7), Totalizer.generate(:activity, 30)],
|
19
24
|
activation: [Totalizer.generate(:activation, 7), Totalizer.generate(:activation, 30)],
|
20
25
|
engagement: [Totalizer.generate(:engagement, 7), Totalizer.generate(:engagement, 30)],
|
21
26
|
retention: [Totalizer.generate(:retention, 7), Totalizer.generate(:retention, 30)],
|
@@ -25,7 +30,10 @@ namespace :totalizer do
|
|
25
30
|
end
|
26
31
|
|
27
32
|
task combined: :validate do
|
28
|
-
|
29
|
-
|
33
|
+
if DateTime.now.wday == Totalizer.weekly_day
|
34
|
+
Rake::Task["totalizer:weekly"].invoke
|
35
|
+
else
|
36
|
+
Rake::Task["totalizer:daily"].invoke
|
37
|
+
end
|
30
38
|
end
|
31
39
|
end
|
data/lib/totalizer/base.rb
CHANGED
@@ -3,6 +3,16 @@ module Totalizer
|
|
3
3
|
NOTIFIERS = { log: 'Totalizer::LogNotifier', action_mailer: 'Totalizer::ActionMailerNotifier', mandrill_mailer: 'Totalizer::MandrillMailerNotifier', slack: 'Totalizer::SlackNotifier' }
|
4
4
|
attr_reader :growth_metric, :activity_metric
|
5
5
|
|
6
|
+
def descriptions
|
7
|
+
@descriptions ||= OpenStruct.new acquisition: "Signed up this period (with rate of change)",
|
8
|
+
vanity: "Total this period (with rate of change)",
|
9
|
+
activity: "Did key activity this period (with rate of change)",
|
10
|
+
activation: "Created this period and did key activity",
|
11
|
+
engagement: "Created before this period and did key activity this period",
|
12
|
+
retention: "Did key activity the previous period and again this period",
|
13
|
+
churn: "Did key activity last period but not this period over the total who did key activity last period plus new users"
|
14
|
+
end
|
15
|
+
|
6
16
|
def growth_metric= metric
|
7
17
|
@growth_metric = validate_metric(metric)
|
8
18
|
end
|
data/lib/totalizer/factory.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
module Totalizer
|
2
2
|
class Factory
|
3
|
-
attr_accessor :growth_metric, :activity_metric, :date, :duration
|
3
|
+
attr_accessor :growth_metric, :activity_metric, :vanity_metric, :date, :duration
|
4
4
|
|
5
|
-
def initialize growth_metric, activity_metric, params={}
|
5
|
+
def initialize growth_metric, activity_metric, vanity_metric, params={}
|
6
6
|
self.growth_metric = growth_metric
|
7
7
|
self.activity_metric = activity_metric
|
8
|
+
self.vanity_metric = vanity_metric
|
8
9
|
self.date = params[:date] || DateTime.now.change(hour: 0)
|
9
10
|
self.duration = params[:duration] || 7
|
10
11
|
validate_attributes!
|
@@ -15,6 +16,11 @@ module Totalizer
|
|
15
16
|
AcqusitionMessage.new(growth_metric, duration)
|
16
17
|
end
|
17
18
|
|
19
|
+
def vanity
|
20
|
+
vanity_metric = Totalizer::Metric.new self.vanity_metric.attributes.merge(date: date, duration: duration)
|
21
|
+
VanityMessage.new(vanity_metric, duration)
|
22
|
+
end
|
23
|
+
|
18
24
|
def activation
|
19
25
|
growth_metric = Totalizer::Metric.new self.growth_metric.attributes.merge(date: date, duration: duration)
|
20
26
|
activity_metric = Totalizer::Metric.new self.activity_metric.attributes.merge(date: date, duration: duration)
|
@@ -52,6 +58,7 @@ module Totalizer
|
|
52
58
|
def validate_attributes!
|
53
59
|
raise Errors::InvalidMetric unless growth_metric.kind_of?(Totalizer::Metric)
|
54
60
|
raise Errors::InvalidMetric unless activity_metric.kind_of?(Totalizer::Metric)
|
61
|
+
raise Errors::InvalidMetric unless vanity_metric.kind_of?(Totalizer::Metric)
|
55
62
|
raise Errors::InvalidDate unless date.kind_of?(DateTime)
|
56
63
|
raise Errors::InvalidDuration unless duration.kind_of?(Integer)
|
57
64
|
end
|
data/lib/totalizer/message.rb
CHANGED
@@ -18,21 +18,28 @@ module Totalizer
|
|
18
18
|
class MetricMessage < Message
|
19
19
|
def initialize metric, duration
|
20
20
|
self.duration = duration
|
21
|
-
self.text = "#{period_string}: #{metric.value} (∆ #{percentage_string(metric.rate)})"
|
21
|
+
self.text = "#{period_string}: #{metric.value} (∆ #{percentage_string(metric.rate)} | Σ #{metric.finish})"
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
25
|
class AcqusitionMessage < MetricMessage
|
26
26
|
def initialize metric, duration
|
27
27
|
super
|
28
|
-
self.description =
|
28
|
+
self.description = Totalizer.descriptions.acquisition
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class VanityMessage < MetricMessage
|
33
|
+
def initialize metric, duration
|
34
|
+
super
|
35
|
+
self.description = Totalizer.descriptions.vanity
|
29
36
|
end
|
30
37
|
end
|
31
38
|
|
32
39
|
class ActivityMessage < MetricMessage
|
33
40
|
def initialize metric, duration
|
34
41
|
super
|
35
|
-
self.description =
|
42
|
+
self.description = Totalizer.descriptions.activity
|
36
43
|
end
|
37
44
|
end
|
38
45
|
|
@@ -40,7 +47,7 @@ module Totalizer
|
|
40
47
|
def initialize step, duration
|
41
48
|
self.duration = duration
|
42
49
|
self.text = "#{period_string}: #{step.start} → #{step.finish} (#{percentage_string(step.rate)})"
|
43
|
-
self.description =
|
50
|
+
self.description = Totalizer.descriptions.activation
|
44
51
|
end
|
45
52
|
end
|
46
53
|
|
@@ -50,7 +57,7 @@ module Totalizer
|
|
50
57
|
|
51
58
|
existing_active = (growth_metric.start_ids & activity_metric.ids).size
|
52
59
|
self.text = "#{period_string}: #{percentage_string existing_active.to_f / growth_metric.start.to_f} (#{existing_active}/#{growth_metric.start})"
|
53
|
-
self.description =
|
60
|
+
self.description = Totalizer.descriptions.engagement
|
54
61
|
end
|
55
62
|
end
|
56
63
|
|
@@ -58,7 +65,7 @@ module Totalizer
|
|
58
65
|
def initialize step, duration
|
59
66
|
self.duration = duration
|
60
67
|
self.text = "#{period_string}: #{percentage_string(step.rate)} (#{step.finish}/#{step.start})"
|
61
|
-
self.description =
|
68
|
+
self.description = Totalizer.descriptions.retention
|
62
69
|
end
|
63
70
|
end
|
64
71
|
|
@@ -70,7 +77,7 @@ module Totalizer
|
|
70
77
|
lost_existing = (previous_activity_metric.ids - this_activity_metc.ids).size
|
71
78
|
final = new_and_existing - lost_existing
|
72
79
|
self.text = "#{period_string}: #{percentage_string lost_existing.to_f / new_and_existing.to_f} (#{lost_existing}/#{new_and_existing})"
|
73
|
-
self.description =
|
80
|
+
self.description = Totalizer.descriptions.churn
|
74
81
|
end
|
75
82
|
end
|
76
83
|
end
|
data/lib/totalizer/version.rb
CHANGED
@@ -3,29 +3,34 @@ require 'spec_helper'
|
|
3
3
|
describe Totalizer::Factory do
|
4
4
|
let(:growth_metric) { Totalizer::Metric.new model: User }
|
5
5
|
let(:activity_metric) { Totalizer::Metric.new model: Post, map: 'user_id' }
|
6
|
+
let(:vanity_metric) { Totalizer::Metric.new model: Post }
|
6
7
|
let(:duration) { nil }
|
7
8
|
let(:date) { nil }
|
8
|
-
let(:factory) { Totalizer::Factory.new growth_metric, activity_metric, date: date }
|
9
|
+
let(:factory) { Totalizer::Factory.new growth_metric, activity_metric, vanity_metric, date: date }
|
9
10
|
|
10
11
|
describe "Validate" do
|
11
12
|
it "requires metrics" do
|
12
|
-
expect{ Totalizer::Factory.new('fake', 'metric') }.to raise_exception(Totalizer::Errors::InvalidMetric)
|
13
|
+
expect{ Totalizer::Factory.new('fake', 'metric', 'here') }.to raise_exception(Totalizer::Errors::InvalidMetric)
|
13
14
|
end
|
14
15
|
|
15
16
|
it "requires activity metric" do
|
16
|
-
expect{ Totalizer::Factory.new(growth_metric, 'metric') }.to raise_exception(Totalizer::Errors::InvalidMetric)
|
17
|
+
expect{ Totalizer::Factory.new(growth_metric, 'metric', vanity_metric) }.to raise_exception(Totalizer::Errors::InvalidMetric)
|
17
18
|
end
|
18
19
|
|
19
20
|
it "requires growth metric" do
|
20
|
-
expect{ Totalizer::Factory.new('fake', activity_metric) }.to raise_exception(Totalizer::Errors::InvalidMetric)
|
21
|
+
expect{ Totalizer::Factory.new('fake', activity_metric, vanity_metric) }.to raise_exception(Totalizer::Errors::InvalidMetric)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "requires vanity metric" do
|
25
|
+
expect{ Totalizer::Factory.new(growth_metric, activity_metric, 'here') }.to raise_exception(Totalizer::Errors::InvalidMetric)
|
21
26
|
end
|
22
27
|
|
23
28
|
it "requires a valid datetime" do
|
24
|
-
expect{ Totalizer::Factory.new(growth_metric, activity_metric, date: 'Whenever') }.to raise_exception(Totalizer::Errors::InvalidDate)
|
29
|
+
expect{ Totalizer::Factory.new(growth_metric, activity_metric, vanity_metric, date: 'Whenever') }.to raise_exception(Totalizer::Errors::InvalidDate)
|
25
30
|
end
|
26
31
|
|
27
32
|
it "requires a duration" do
|
28
|
-
expect{ Totalizer::Factory.new(growth_metric, activity_metric, duration: 'Whatever') }.to raise_exception(Totalizer::Errors::InvalidDuration)
|
33
|
+
expect{ Totalizer::Factory.new(growth_metric, activity_metric, vanity_metric, duration: 'Whatever') }.to raise_exception(Totalizer::Errors::InvalidDuration)
|
29
34
|
end
|
30
35
|
end
|
31
36
|
|
@@ -37,6 +42,17 @@ describe Totalizer::Factory do
|
|
37
42
|
it "defaults to 7 day acquisition duration" do
|
38
43
|
expect(factory.duration).to eq 7
|
39
44
|
end
|
45
|
+
|
46
|
+
it "defaults description text" do
|
47
|
+
expect(factory.vanity.description).to eq "Total this period (with rate of change)"
|
48
|
+
end
|
49
|
+
|
50
|
+
it "overrides description text" do
|
51
|
+
original = Totalizer.descriptions.vanity
|
52
|
+
Totalizer.descriptions.vanity = "Sites created"
|
53
|
+
expect(factory.vanity.description).to eq "Sites created"
|
54
|
+
Totalizer.descriptions.vanity = original
|
55
|
+
end
|
40
56
|
end
|
41
57
|
|
42
58
|
describe "Calculate" do
|
@@ -58,13 +74,19 @@ describe Totalizer::Factory do
|
|
58
74
|
|
59
75
|
describe "Acquisition" do
|
60
76
|
it "returns text" do
|
61
|
-
expect(factory.acquisition.text).to eq "Last 7 days: 2 (∆ 50%)"
|
77
|
+
expect(factory.acquisition.text).to eq "Last 7 days: 2 (∆ 50% | Σ 6)"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "Vanity" do
|
82
|
+
it "returns text" do
|
83
|
+
expect(factory.vanity.text).to eq "Last 7 days: 2 (∆ 50% | Σ 6)"
|
62
84
|
end
|
63
85
|
end
|
64
86
|
|
65
87
|
describe "Activity" do
|
66
88
|
it "returns text" do
|
67
|
-
expect(factory.activity.text).to eq "Last 7 days: 2 (∆ 25%)"
|
89
|
+
expect(factory.activity.text).to eq "Last 7 days: 2 (∆ 25% | Σ 5)"
|
68
90
|
end
|
69
91
|
end
|
70
92
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: totalizer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Dijkstra
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-10-
|
11
|
+
date: 2016-10-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|