staccato 0.0.2 → 0.0.3
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/README.md +8 -0
- data/lib/staccato.rb +15 -0
- data/lib/staccato/event.rb +4 -0
- data/lib/staccato/exception.rb +4 -0
- data/lib/staccato/hit.rb +48 -9
- data/lib/staccato/option_set.rb +2 -0
- data/lib/staccato/pageview.rb +4 -0
- data/lib/staccato/social.rb +4 -0
- data/lib/staccato/timing.rb +6 -0
- data/lib/staccato/tracker.rb +69 -0
- data/lib/staccato/transaction.rb +4 -0
- data/lib/staccato/transaction_item.rb +4 -0
- data/lib/staccato/version.rb +2 -1
- data/spec/lib/staccato/pageview_spec.rb +20 -0
- metadata +2 -2
data/README.md
CHANGED
@@ -78,6 +78,14 @@ events that are not directly the result of a user's interaction.
|
|
78
78
|
|
79
79
|
The option `non_interactive` is accepted for all methods on `tracker`.
|
80
80
|
|
81
|
+
# Tracking an Experiment
|
82
|
+
# useful for tracking A/B or Multivariate testing
|
83
|
+
tracker.pageview({
|
84
|
+
path: '/blog',
|
85
|
+
experiment_id: 'a7a8d91df',
|
86
|
+
experiment_variant: 'a'
|
87
|
+
})
|
88
|
+
|
81
89
|
## Google Documentation
|
82
90
|
|
83
91
|
https://developers.google.com/analytics/devguides/collection/protocol/v1/devguide
|
data/lib/staccato.rb
CHANGED
@@ -5,7 +5,18 @@ require 'securerandom'
|
|
5
5
|
|
6
6
|
require "staccato/version"
|
7
7
|
|
8
|
+
# The `Staccato` module namespace
|
9
|
+
#
|
10
|
+
# @author Tony Pitale
|
8
11
|
module Staccato
|
12
|
+
# Build a new tracker instance
|
13
|
+
# If the first argument is explicitly `nil`, a `NoopTracker` is returned
|
14
|
+
# which responds to all the same `tracker` methods but does no tracking
|
15
|
+
#
|
16
|
+
# @param id [String, nil] the id provided by google, i.e., `UA-XXXXXX-Y`
|
17
|
+
# @param client_id [String, Integer, nil] a unique id to track the session of
|
18
|
+
# an individual user
|
19
|
+
# @return [Staccato::Tracker] a new tracker is returned
|
9
20
|
def self.tracker(id, client_id = nil)
|
10
21
|
if id.nil?
|
11
22
|
Staccato::NoopTracker.new
|
@@ -14,10 +25,14 @@ module Staccato
|
|
14
25
|
end
|
15
26
|
end
|
16
27
|
|
28
|
+
# Build a new random `client_id`
|
29
|
+
#
|
30
|
+
# @return [String] a random value suitable for use as a `client_id`
|
17
31
|
def self.build_client_id
|
18
32
|
SecureRandom.uuid
|
19
33
|
end
|
20
34
|
|
35
|
+
# The tracking endpoint we use to submit requests to GA
|
21
36
|
def self.tracking_uri
|
22
37
|
URI('http://www.google-analytics.com/collect')
|
23
38
|
end
|
data/lib/staccato/event.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
module Staccato
|
2
|
+
# Event Hit type field definitions
|
3
|
+
# @author Tony Pitale
|
2
4
|
class Event
|
5
|
+
# Event field definitions
|
3
6
|
FIELDS = {
|
4
7
|
category: 'ec',
|
5
8
|
action: 'ea',
|
@@ -9,6 +12,7 @@ module Staccato
|
|
9
12
|
|
10
13
|
include Hit
|
11
14
|
|
15
|
+
# event hit type
|
12
16
|
def type
|
13
17
|
:event
|
14
18
|
end
|
data/lib/staccato/exception.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
module Staccato
|
2
|
+
# Exception Hit type field definitions
|
3
|
+
# @author Tony Pitale
|
2
4
|
class Exception
|
5
|
+
# Exception field definitions
|
3
6
|
FIELDS = {
|
4
7
|
description: 'exd',
|
5
8
|
fatal: 'exf'
|
@@ -12,6 +15,7 @@ module Staccato
|
|
12
15
|
options[:fatal] = 1 if options[:fatal]
|
13
16
|
end
|
14
17
|
|
18
|
+
# exception hit type
|
15
19
|
def type
|
16
20
|
:exception
|
17
21
|
end
|
data/lib/staccato/hit.rb
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
module Staccato
|
2
|
+
# The `Hit` module enables a class to track the appropriate parameters
|
3
|
+
# to Google Analytics given a defined set of `FIELDS` in a map between
|
4
|
+
# the option name and its specified GA field name
|
5
|
+
#
|
6
|
+
# @author Tony Pitale
|
2
7
|
module Hit
|
8
|
+
# this module is included into each model hit type
|
9
|
+
# to share the common behavior required to hit
|
10
|
+
# the Google Analytics /collect api endpoint
|
3
11
|
def self.included(model)
|
4
12
|
model.extend Forwardable
|
5
13
|
|
@@ -10,37 +18,68 @@ module Staccato
|
|
10
18
|
end
|
11
19
|
end
|
12
20
|
|
21
|
+
# sets up a new hit
|
22
|
+
# @param tracker [Staccato::Tracker] the tracker to collect to
|
23
|
+
# @param options [Hash] options for the specific hit type
|
13
24
|
def initialize(tracker, options = {})
|
14
25
|
self.tracker = tracker
|
15
26
|
self.options = OptionSet.new(options)
|
16
27
|
end
|
17
28
|
|
29
|
+
# return the fields for this hit type
|
30
|
+
# @return [Hash] the field definitions
|
18
31
|
def fields
|
19
32
|
self.class::FIELDS
|
20
33
|
end
|
21
34
|
|
35
|
+
# collects the parameters from options for this hit type
|
22
36
|
def params
|
23
|
-
{
|
24
|
-
'v' => 1,
|
25
|
-
'tid' => tracker.id,
|
26
|
-
'cid' => tracker.client_id,
|
27
|
-
'ni' => non_interactive,
|
28
|
-
't' => type.to_s
|
29
|
-
}.merge(Hash[
|
30
|
-
fields.map {|field,key| [key, options[field]]}
|
31
|
-
]).reject {|_,v| v.nil?}
|
37
|
+
base_params.merge(global_options_params).merge(hit_params).reject {|_,v| v.nil?}
|
32
38
|
end
|
33
39
|
|
40
|
+
# is this a non interactive hit
|
41
|
+
# @return [Integer, nil]
|
34
42
|
def non_interactive
|
35
43
|
1 if options[:non_interactive] # defaults to nil
|
36
44
|
end
|
37
45
|
|
46
|
+
# post the hit to GA collection endpoint
|
47
|
+
# @return [Net::HTTPOK] the GA api always returns 200 OK
|
38
48
|
def track!
|
39
49
|
post(Staccato.tracking_uri, params)
|
40
50
|
end
|
41
51
|
|
52
|
+
private
|
53
|
+
# @private
|
42
54
|
def post(uri, params = {})
|
43
55
|
Net::HTTP.post_form(uri, params)
|
44
56
|
end
|
57
|
+
|
58
|
+
# @private
|
59
|
+
def base_params
|
60
|
+
{
|
61
|
+
'v' => 1,
|
62
|
+
'tid' => tracker.id,
|
63
|
+
'cid' => tracker.client_id,
|
64
|
+
'ni' => non_interactive,
|
65
|
+
't' => type.to_s
|
66
|
+
}
|
67
|
+
end
|
68
|
+
|
69
|
+
# @private
|
70
|
+
def global_options_params
|
71
|
+
{
|
72
|
+
'dr' => options[:referrer],
|
73
|
+
'de' => options[:encoding],
|
74
|
+
'ul' => options[:user_language],
|
75
|
+
'xid' => options[:experiment_id],
|
76
|
+
'xvar' => options[:experiment_variant]
|
77
|
+
}
|
78
|
+
end
|
79
|
+
|
80
|
+
# @private
|
81
|
+
def hit_params
|
82
|
+
Hash[fields.map {|field,key| [key, options[field]]}]
|
83
|
+
end
|
45
84
|
end
|
46
85
|
end
|
data/lib/staccato/option_set.rb
CHANGED
data/lib/staccato/pageview.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
module Staccato
|
2
|
+
# Pageview Hit type field definitions
|
3
|
+
# @author Tony Pitale
|
2
4
|
class Pageview
|
5
|
+
# Pageview field definitions
|
3
6
|
FIELDS = {
|
4
7
|
hostname: 'dh',
|
5
8
|
path: 'dp',
|
@@ -8,6 +11,7 @@ module Staccato
|
|
8
11
|
|
9
12
|
include Hit
|
10
13
|
|
14
|
+
# pageview hit type
|
11
15
|
def type
|
12
16
|
:pageview
|
13
17
|
end
|
data/lib/staccato/social.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
module Staccato
|
2
|
+
# Social Hit type field definitions
|
3
|
+
# @author Tony Pitale
|
2
4
|
class Social
|
5
|
+
# Social field definitions
|
3
6
|
FIELDS = {
|
4
7
|
action: 'sa',
|
5
8
|
network: 'sn',
|
@@ -8,6 +11,7 @@ module Staccato
|
|
8
11
|
|
9
12
|
include Hit
|
10
13
|
|
14
|
+
# social hit type
|
11
15
|
def type
|
12
16
|
:social
|
13
17
|
end
|
data/lib/staccato/timing.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
module Staccato
|
2
|
+
# Timing Hit type field definitions
|
3
|
+
# @author Tony Pitale
|
2
4
|
class Timing
|
5
|
+
# Timing field definitions
|
3
6
|
FIELDS = {
|
4
7
|
category: 'utc',
|
5
8
|
variable: 'utv',
|
@@ -9,10 +12,13 @@ module Staccato
|
|
9
12
|
|
10
13
|
include Hit
|
11
14
|
|
15
|
+
# timing hit type
|
12
16
|
def type
|
13
17
|
:timing
|
14
18
|
end
|
15
19
|
|
20
|
+
# tracks the timing hit type
|
21
|
+
# @param block [#call] block is executed and time recorded
|
16
22
|
def track!(&block)
|
17
23
|
if block_given?
|
18
24
|
start_at = Time.now
|
data/lib/staccato/tracker.rb
CHANGED
@@ -1,64 +1,133 @@
|
|
1
1
|
module Staccato
|
2
|
+
# The `Tracker` class has methods to create all `Hit` types
|
3
|
+
# using the tracker and client id
|
4
|
+
#
|
5
|
+
# @author Tony Pitale
|
2
6
|
class Tracker
|
7
|
+
# sets up a new tracker
|
8
|
+
# @param id [String] the GA tracker id
|
9
|
+
# @param client_id [String, nil] unique value to track user sessions
|
3
10
|
def initialize(id, client_id = nil)
|
4
11
|
@id = id
|
5
12
|
@client_id = client_id
|
6
13
|
end
|
7
14
|
|
15
|
+
# The tracker id for GA
|
16
|
+
# @return [String, nil]
|
8
17
|
def id
|
9
18
|
@id
|
10
19
|
end
|
11
20
|
|
21
|
+
# The unique client id
|
22
|
+
# @return [String]
|
12
23
|
def client_id
|
13
24
|
@client_id ||= Staccato.build_client_id
|
14
25
|
end
|
15
26
|
|
27
|
+
# Track a pageview
|
28
|
+
#
|
29
|
+
# @param options [Hash] options include:
|
30
|
+
# * path (optional) the path of the current page view
|
31
|
+
# * hostname (optional) the hostname of the current page view
|
32
|
+
# * title (optional) the page title
|
33
|
+
# @return [<Net::HTTPOK] the GA `/collect` endpoint always returns a 200
|
16
34
|
def pageview(options = {})
|
17
35
|
Staccato::Pageview.new(self, options).track!
|
18
36
|
end
|
19
37
|
|
38
|
+
# Track an event
|
39
|
+
#
|
40
|
+
# @param options [Hash] options include:
|
41
|
+
# * category (optional)
|
42
|
+
# * action (optional)
|
43
|
+
# * label (optional)
|
44
|
+
# * value (optional)
|
45
|
+
# @return [<Net::HTTPOK] the GA `/collect` endpoint always returns a 200
|
20
46
|
def event(options = {})
|
21
47
|
Staccato::Event.new(self, options).track!
|
22
48
|
end
|
23
49
|
|
50
|
+
# Track a social event such as a Facebook Like or Twitter Share
|
51
|
+
#
|
52
|
+
# @param options [Hash] options include:
|
53
|
+
# * action (required) the action taken, e.g., 'like'
|
54
|
+
# * network (required) the network used, e.g., 'facebook'
|
55
|
+
# * target (required) the target page path, e.g., '/blog/something-awesome'
|
56
|
+
# @return [<Net::HTTPOK] the GA `/collect` endpoint always returns a 200
|
24
57
|
def social(options = {})
|
25
58
|
Staccato::Social.new(self, options).track!
|
26
59
|
end
|
27
60
|
|
61
|
+
# Track an exception
|
62
|
+
#
|
63
|
+
# @param options [Hash] options include:
|
64
|
+
# * description (optional) often the class of exception, e.g., RuntimeException
|
65
|
+
# * fatal (optional) was the exception fatal? boolean, defaults to false
|
66
|
+
# @return [<Net::HTTPOK] the GA `/collect` endpoint always returns a 200
|
28
67
|
def exception(options = {})
|
29
68
|
Staccato::Exception.new(self, options).track!
|
30
69
|
end
|
31
70
|
|
71
|
+
# Track timing
|
72
|
+
#
|
73
|
+
# @param options [Hash] options include:
|
74
|
+
# * category (optional) e.g., 'runtime'
|
75
|
+
# * variable (optional) e.g., 'database'
|
76
|
+
# * label (optional) e.g., 'query'
|
77
|
+
# * time (recommended) the integer time in milliseconds
|
78
|
+
# @param block [#call] if a block is provided, the time it takes to
|
79
|
+
# run will be recorded and set as the `time` value option
|
80
|
+
# @return [<Net::HTTPOK] the GA `/collect` endpoint always returns a 200
|
32
81
|
def timing(options = {}, &block)
|
33
82
|
Staccato::Timing.new(self, options).track!(&block)
|
34
83
|
end
|
35
84
|
|
85
|
+
# Track an ecommerce transaction
|
86
|
+
# @return [<Net::HTTPOK] the GA `/collect` endpoint always returns a 200
|
36
87
|
def transaction(options = {})
|
37
88
|
Staccato::Transaction.new(self, options).track!
|
38
89
|
end
|
39
90
|
|
91
|
+
# Track an item in an ecommerce transaction
|
92
|
+
# @return [<Net::HTTPOK] the GA `/collect` endpoint always returns a 200
|
40
93
|
def transaction_item(options = {})
|
41
94
|
Staccato::TransactionItem.new(self, options).track!
|
42
95
|
end
|
43
96
|
end
|
44
97
|
|
98
|
+
# A tracker which does no tracking
|
99
|
+
# Useful in testing
|
45
100
|
class NoopTracker
|
101
|
+
# (see Tracker#initialize)
|
46
102
|
def initialize(*); end
|
47
103
|
|
104
|
+
# (see Tracker#id)
|
48
105
|
def id
|
49
106
|
nil
|
50
107
|
end
|
51
108
|
|
109
|
+
# (see Tracker#client_id)
|
52
110
|
def client_id
|
53
111
|
nil
|
54
112
|
end
|
55
113
|
|
114
|
+
# (see Tracker#pageview)
|
56
115
|
def pageview(*); end
|
116
|
+
# (see Tracker#event)
|
57
117
|
def event(*); end
|
118
|
+
# (see Tracker#social)
|
58
119
|
def social(*); end
|
120
|
+
# (see Tracker#exception)
|
59
121
|
def exception(*); end
|
122
|
+
# (see Tracker#timing)
|
60
123
|
def timing(*)
|
61
124
|
yield if block_given?
|
62
125
|
end
|
126
|
+
# (see Tracker#transaction)
|
127
|
+
def transaction(*)
|
128
|
+
end
|
129
|
+
# (see Tracker#transaction_item)
|
130
|
+
def transaction_item(*)
|
131
|
+
end
|
63
132
|
end
|
64
133
|
end
|
data/lib/staccato/transaction.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
module Staccato
|
2
|
+
# Transaction Hit type field definitions
|
3
|
+
# @author Tony Pitale
|
2
4
|
class Transaction
|
5
|
+
# Transaction field definitions
|
3
6
|
FIELDS = {
|
4
7
|
transaction_id: 'ti',
|
5
8
|
affiliation: 'ta',
|
@@ -11,6 +14,7 @@ module Staccato
|
|
11
14
|
|
12
15
|
include Hit
|
13
16
|
|
17
|
+
# transaction hit type
|
14
18
|
def type
|
15
19
|
:transaction
|
16
20
|
end
|
@@ -1,5 +1,8 @@
|
|
1
1
|
module Staccato
|
2
|
+
# Item Hit type field definitions for Transactions
|
3
|
+
# @author Tony Pitale
|
2
4
|
class TransactionItem
|
5
|
+
# Item field definitions
|
3
6
|
FIELDS = {
|
4
7
|
transaction_id: 'ti',
|
5
8
|
name: 'in',
|
@@ -12,6 +15,7 @@ module Staccato
|
|
12
15
|
|
13
16
|
include Hit
|
14
17
|
|
18
|
+
# item hit type
|
15
19
|
def type
|
16
20
|
:item
|
17
21
|
end
|
data/lib/staccato/version.rb
CHANGED
@@ -75,4 +75,24 @@ describe Staccato::Pageview do
|
|
75
75
|
})
|
76
76
|
end
|
77
77
|
end
|
78
|
+
|
79
|
+
context "with experiment_* options" do
|
80
|
+
let(:pageview) do
|
81
|
+
Staccato::Pageview.new(tracker, {
|
82
|
+
experiment_id: 'ac67afa889',
|
83
|
+
experiment_variant: 'c'
|
84
|
+
})
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'has require params' do
|
88
|
+
pageview.params.should eq({
|
89
|
+
'v' => 1,
|
90
|
+
'tid' => 'UA-XXXX-Y',
|
91
|
+
'cid' => '555',
|
92
|
+
't' => 'pageview',
|
93
|
+
'xid' => 'ac67afa889',
|
94
|
+
'xvar' => 'c'
|
95
|
+
})
|
96
|
+
end
|
97
|
+
end
|
78
98
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: staccato
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-01-
|
12
|
+
date: 2014-01-21 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|