staccato 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -1,4 +1,6 @@
1
1
  module Staccato
2
+ # Extends OpenStruct with `[]` access method when
3
+ # the current version of ruby does not include it
2
4
  class OptionSet < OpenStruct
3
5
  unless OpenStruct.instance_methods.include?(:[])
4
6
  extend Forwardable
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -1,3 +1,4 @@
1
1
  module Staccato
2
- VERSION = "0.0.2"
2
+ # The current Staccato VERSION
3
+ VERSION = "0.0.3"
3
4
  end
@@ -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.2
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-10 00:00:00.000000000 Z
12
+ date: 2014-01-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler