ga_events 3.0.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2da2467a5f1cf24ef9fdcd30dfea8130a6e5a1c2a8ce6e0903143a909215e30d
4
- data.tar.gz: b617a6d911b6666a8b1f0dabae680950565f956adccf26850a443a3109602c23
3
+ metadata.gz: af13dc202f2b24f7fa7ba45345d90fea5158e4b50c5e55fbb6bbc68752c6083b
4
+ data.tar.gz: bbd3f2173bba05a2ce2d1dc4315a288b83b469810327dd2cbccd30799f6e595a
5
5
  SHA512:
6
- metadata.gz: 805237d9af985bd8c4cb9d696626f4949d953dcabb3669b1b80771209811f13402f27e25aa618eda39bce2cfdf767ae9f74fa8336f789e5a5ee79a82e59e8026
7
- data.tar.gz: 428a307570718be7d541f3c8883cc73141e88e7861e87a98ed5a4263ef8f41f657028220203298ea4ab5053fdbe9e1e85dc9fec59e26b50223ba5a94a0855a0a
6
+ metadata.gz: cb529a2794580ae3c52a2a226c620b94ba79b278dc1171fcda5a27bdc511901b95f2d9243028285484a2a8d66af2feeb6a40539e82e5def320ed0974bf62e74e
7
+ data.tar.gz: 9b9adf95d667f066198b222cb45e233b83b03420e84a6743cd93cfba70b90bbaed7982b070d552f37e69c148a21800159a18223af176d6dac955049fe8f02971
data/.gitignore CHANGED
@@ -1,5 +1,8 @@
1
1
  *.gem
2
+ bin/rspec
2
3
  .bundle
3
4
  Gemfile.lock
4
5
  pkg
5
6
  vendor
7
+ .ruby-version
8
+ .tools-version
data/CHANGELOG.md CHANGED
@@ -64,3 +64,29 @@ The format suggested at http://keepachangelog.com/ is used.
64
64
  - Universal Analytics Adapter can be configured to use a custom name for the
65
65
  analytics object (defaults to `window.ga()` for `analytics.js` and
66
66
  `window.gtag()` for `gtag.js`)
67
+
68
+ ## 4.0.0 - 2023-08-xx
69
+
70
+ ### Added
71
+ - Support for GA4 using the `GTagAdapter`
72
+
73
+ ### Breaking
74
+ - Dropped support for older rubies. The gem requires at least ruby 3.2 now
75
+ - UniversalAnalyticsAdapter and GoogleAnalyticsAdapter removed
76
+ - The `GaEvent::Event` constructor changed to conform to the new newer
77
+ GA4 event interface.
78
+
79
+ ```ruby
80
+ # 3.x and before
81
+ GaEvents::Event.new('category', 'action', 'label', 'value')
82
+
83
+ # 4.x onwards
84
+ GaEvents::Event.new('event_name', {
85
+ custom_dimension: 'xxx',
86
+ custom_dimension2: 'yyy'
87
+ })
88
+ ```
89
+ - Events that should be kept on redirects are no longer mixed into rails
90
+ flashes. Redirect events are stored inside a custom rack session variable
91
+ instead.
92
+
data/Gemfile CHANGED
@@ -7,5 +7,5 @@ gemspec
7
7
 
8
8
  gem 'pry'
9
9
  gem 'rake'
10
- gem 'rspec', '~> 3.1.0'
10
+ gem 'rspec', '~> 3.12.0'
11
11
  gem 'rubocop', '~> 0.79.0', require: false
data/README.md CHANGED
@@ -7,13 +7,13 @@ app.
7
7
  A rack middleware is automatically inserted into the stack. It transports
8
8
  the event data to the client. Normal requests get a DIV injected, Ajax requests
9
9
  get a data-pounded custom HTTP header appended. In case of redirects the data
10
- survives inside Rails' flash.
10
+ survives inside of rack a rack session.
11
11
  The asset pipeline-ready CoffeeScript extracts this data on the client-side and
12
- pushes it to Google Analytics via ga.js or Google Tag Manager.
12
+ pushes it to Google Analytics via gtag.js or Google Tag Manager.
13
13
 
14
14
  ## Dependencies
15
15
 
16
- * Ruby >= 2.3
16
+ * Ruby >= 3.2
17
17
  * Rails 4.2 onwards
18
18
  * jQuery
19
19
 
@@ -35,42 +35,11 @@ Add to the top of your `application.js` (but after requiring jQuery):
35
35
 
36
36
  After requiring `ga_events.js`, you have to choose an adapter.
37
37
 
38
- ### Google Analytics (ga.js)
38
+ ### Google Analytics 4 (gtag.js)
39
39
 
40
40
  ```javascript
41
41
  GaEvents.Event.adapter = function() {
42
- return new GaEvents.GoogleAnalyticsAdapter();
43
- }
44
- ```
45
-
46
- ### Google Universal Analytics
47
-
48
- #### analytics.js
49
-
50
- ```javascript
51
- GaEvents.Event.adapter = function() {
52
- return new GaEvents.GoogleUniversalAnalyticsAdapter();
53
- }
54
- ```
55
-
56
- Optionally you can specify a custom send method to call and a custom tracker
57
- name:
58
-
59
- ```javascript
60
- GaEvents.Event.adapter = function() {
61
- return new GaEvents.GoogleUniversalAnalyticsAdapter(
62
- {send_method_name: "sendNow", tracker_name: "customTracker"}
63
- );
64
- }
65
- ```
66
-
67
- #### gtag.js
68
-
69
- ```javascript
70
- GaEvents.Event.adapter = function() {
71
- return new GaEvents.GoogleUniversalAnalyticsAdapter(
72
- {use_gtag_variant: true}
73
- );
42
+ return new GaEvents.GTagAdapter();
74
43
  }
75
44
  ```
76
45
 
@@ -79,21 +48,20 @@ your events to be sent to:
79
48
 
80
49
  ```javascript
81
50
  GaEvents.Event.adapter = function() {
82
- return new GaEvents.GoogleUniversalAnalyticsAdapter(
83
- {use_gtag_variant: true, tracker_name: "GA_MEASUREMENT_ID"}
51
+ return new GaEvents.GTagAdapter(
52
+ {tracker_name: "GA_MEASUREMENT_ID"}
84
53
  );
85
54
  }
86
55
  ```
87
56
 
88
57
  #### Optional custom object name
89
58
 
90
- The default names of the analytics object are `window.ga()` for `analytics.js`
91
- and `window.gtag()` for `gtag.js`. If you have renamed your analytics object,
92
- you can specify the name:
59
+ The default names of the analytics object for `gtag.js` is `window.gtag()`. If
60
+ you have renamed your analytics object, you can specify the name:
93
61
 
94
62
  ```javascript
95
63
  GaEvents.Event.adapter = function() {
96
- return new GaEvents.GoogleUniversalAnalyticsAdapter(
64
+ return new GaEvents.GTagAdapter(
97
65
  {analytics_object_name: "analytics"} // calls window.analytics()
98
66
  );
99
67
  }
@@ -138,24 +106,18 @@ HTTP header is added to the response.
138
106
  You can create a new event like this:
139
107
 
140
108
  ```ruby
141
- GaEvents::Event.new(category, action, label, value)
109
+ GaEvents::Event.new('example_event', { extra: 'dimension' })
142
110
  ```
143
111
 
144
112
  On the client-side there is a similar interface to GaEvents:
145
113
 
146
114
  ```javascript
147
- new GaEvents.Event(category, action, label, value)
115
+ new GaEvents.Event('example_event', { extra: 'dimension' })
148
116
  ```
149
117
 
150
118
  We have taken special care of tracking events while the DOM is loading.
151
119
  Events get collected until the DOM is ready and flushed afterwards.
152
120
 
153
- ### Default values
154
-
155
- While collecting hundreds of thousands of events on a daily basis in
156
- Google Analytics we found corrupted aggregated events when the event label or
157
- value is omitted. We now enforce a default label ("-") and value (1).
158
-
159
121
  ### Too many events
160
122
 
161
123
  Use something like this snippet to get informed of bloating HTTP headers with
@@ -201,7 +163,6 @@ Yes please! Use pull requests.
201
163
  ## More docs and tools
202
164
 
203
165
  * [Google Analytics: Event Tracking](https://developers.google.com/analytics/devguides/collection/gajs/eventTrackerGuide)
204
- * [Google Universal Analytics: Event Tracking (analytics.js)](https://developers.google.com/analytics/devguides/collection/analyticsjs/events)
205
166
  * [Google Universal Analytics: Event Tracking (gtag.js)](https://developers.google.com/analytics/devguides/collection/gtagjs/events)
206
167
  * [Google Tag Manager: Custom Events](http://support.google.com/tagmanager/answer/2574372#GoogleAnalytics)
207
168
  * [Chrome Web Store: Tag Assistant](https://chrome.google.com/webstore/detail/tag-assistant-legacy-by-g/kejbdjndbnbjgmefkgdddjlbokphdefk)
@@ -7,21 +7,25 @@ class GaEvents.Event
7
7
  adapter: null
8
8
  @list: []
9
9
  @may_flush: false
10
- @header_key: "X-GA-Events"
10
+ @header_key: "x-ga-events"
11
11
  @html_key: "ga-events"
12
12
  @require_user_consent: false
13
13
  @user_consent_given: false
14
14
  klass: @
15
15
 
16
16
  # Decompose an event-string (ruby side) into an event object.
17
- @from_string: (string) ->
18
- $.map string.split("$"), (part) =>
19
- [category, action, label, value] = part.split "|"
20
- new @(category, action, label, value)
17
+ @from_json: (string) ->
18
+ events = JSON.parse(string)
19
+
20
+ $.map events, (event) =>
21
+ if event_name = event.__event__
22
+ delete event.__event__
23
+ new @(event_name, event)
21
24
 
22
25
  @from_dom: ->
23
- dom_events = $("div[data-#{@html_key}]").data @html_key
24
- @from_string dom_events if dom_events?
26
+ data_attribute = "data-#{@html_key}"
27
+ dom_events = $("div[#{data_attribute}]").attr data_attribute
28
+ @from_json dom_events if dom_events?
25
29
 
26
30
  # Events should not be sent to an adapter unless the DOM has finished loading.
27
31
  @flush: ->
@@ -32,32 +36,18 @@ class GaEvents.Event
32
36
  @list = []
33
37
 
34
38
  # Add all events to a queue to flush them later
35
- constructor: (@category = "-", @action = "-", @label = "-", @value = 1) ->
39
+ constructor: (@event_name, @options = {}) ->
36
40
  @klass.list.push @
37
41
  @klass.flush()
38
42
 
39
- escape: (str) ->
40
- return unless str
41
- "#{str}".replace(/ä/g, "ae")
42
- .replace(/ö/g, "oe")
43
- .replace(/ü/g, "ue")
44
- .replace(/Ä/g, "Ae")
45
- .replace(/Ö/g, "Oe")
46
- .replace(/Ü/g, "Ue")
47
- .replace(/ß/g, "ss")
48
-
49
- to_hash: ->
50
- # Category, action and label must be escaped and of type string.
51
- action: @escape(@action)
52
- category: @escape(@category)
53
- label: @escape(@label)
54
- # Value has to be a positive integer or defaults to 1
55
- value: @to_positive_integer(@value)
56
-
57
- to_positive_integer: (n) ->
58
- if isFinite(n) and parseInt(n) >= 0 then parseInt n else 1
59
-
60
- push_to_adapter: -> @klass.adapter().push @to_hash()
43
+ push_to_adapter: ->
44
+ if @is_valid_event_name()
45
+ @klass.adapter().push(@event_name, @options)
46
+ else
47
+ console.warn("GA4 event name \"#{@event_name}\" is invalid.") if console
48
+
49
+ # https://support.google.com/analytics/answer/13316687?hl=en#zippy=%2Cweb
50
+ is_valid_event_name: -> /^[a-z]+[a-z0-9_]*$/i.test(@event_name)
61
51
 
62
52
  jQuery =>
63
53
  @may_flush = true
@@ -65,7 +55,7 @@ class GaEvents.Event
65
55
 
66
56
  process_xhr = (xhr) =>
67
57
  xhr_events = xhr.getResponseHeader @header_key
68
- @from_string xhr_events if xhr_events?
58
+ @from_json decodeURIComponent(xhr_events) if xhr_events?
69
59
 
70
60
  $(document).ajaxComplete((_, xhr) -> process_xhr(xhr))
71
61
  $(document).on "turbolinks:request-end", (event) ->
@@ -75,59 +65,31 @@ class GaEvents.Event
75
65
  @from_dom()
76
66
 
77
67
 
78
- class GaEvents.GoogleTagManagerAdapter
79
- constructor: (@event = "ga_event") ->
80
- push: (data) ->
81
- data.event = @event
82
- data.non_interaction = true
83
- window.dataLayer.push data
84
-
85
- class GaEvents.GoogleUniversalAnalyticsAdapter
68
+ class GaEvents.GTagAdapter
86
69
  constructor: (options) ->
87
- @use_gtag_variant = options?.use_gtag_variant || false
88
- @analytics_object_name =
89
- options?.analytics_object_name ||
90
- (if @use_gtag_variant then "gtag" else "ga")
91
-
92
- # Only relevant for analytics.js
93
- @send_method_name = options?.send_method_name || "send"
70
+ @analytics_object_name = options?.analytics_object_name || 'gtag'
94
71
 
95
72
  # https://developers.google.com/analytics/devguides/migration/ua/analyticsjs-to-gtagjs#measure_pageviews_with_specified_trackers
96
73
  @tracker_name = options?.tracker_name || false
97
- push: (data) ->
98
- if @use_gtag_variant
99
- options = {
100
- "event_category": data.category,
101
- "event_label": data.label,
102
- "value": data.value,
103
- "non_interaction": true
104
- }
105
- options["send_to"] = @tracker_name if @tracker_name
106
- window[@analytics_object_name]("event", data.action, options)
107
- else
108
- method_call_name =
109
- if @tracker_name
110
- "#{@tracker_name}.#{@send_method_name}"
111
- else
112
- @send_method_name
113
- window[@analytics_object_name](
114
- method_call_name, "event",
115
- data.category, data.action, data.label, data.value,
116
- {"nonInteraction": true}
117
- )
118
-
119
- class GaEvents.GoogleAnalyticsAdapter
120
- # https://developers.google.com/analytics/devguides/collection/gajs/eventTrackerGuide#SettingUpEventTracking
121
- # Send events non_interactive => no influence on bounce rates
122
- push: (data) ->
123
- window._gaq.push(
124
- ["_trackEvent", data.category, data.action, data.label, data.value, true]
125
- )
74
+
75
+ push: (event_name, data) ->
76
+ data.send_to = @tracker_name if @tracker_name
77
+ window[@analytics_object_name]("event", event_name, data)
126
78
 
127
79
  class GaEvents.NullAdapter
128
- push: (obj) -> console.log obj if console?
80
+ push: (event_name, data) -> console.log(event_name, data) if console?
81
+
82
+ class GaEvents.GoogleTagManagerAdapter
83
+ constructor: (@event = "ga_event") ->
84
+
85
+ push: (event_name, data) ->
86
+ data.event = @event
87
+ data.event_name = event_name
88
+ data.non_interaction = true
89
+ window.dataLayer.push data
129
90
 
130
91
  class GaEvents.TestAdapter
131
- push: (obj) ->
92
+ push: (event_name, data) ->
93
+ loggedEvent = Object.assign({ event_name: event_name }, data)
132
94
  window.events = [] unless window.events?
133
- window.events.push obj
95
+ window.events.push(loggedEvent)
data/ga_events.gemspec CHANGED
@@ -27,6 +27,6 @@ Gem::Specification.new do |gem|
27
27
  gem.version = GaEvents::VERSION
28
28
  gem.licenses = ['MIT']
29
29
 
30
- gem.required_ruby_version = '>= 2.3'
30
+ gem.required_ruby_version = '>= 3.2'
31
31
  gem.add_dependency 'rails', '>= 4.2'
32
32
  end
@@ -1,19 +1,37 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GaEvents
4
- Event = Struct.new(:category, :action, :label, :value) do
4
+ class Event
5
+ attr_reader :event_name, :event_params
6
+
5
7
  # Default values are set here, see README.md for details.
6
- def initialize(category = '-', action = '-', label = '-', value = 1)
7
- super
8
+ def initialize(event_name, event_params = {})
9
+ @event_name = event_name
10
+ @event_params = event_params
8
11
  GaEvents::List << self
9
12
  end
10
13
 
11
14
  def to_s
12
- [category, action, label, value].join('|')
15
+ JSON.generate({ __event__: event_name, **event_params })
16
+ end
17
+
18
+ def to_h
19
+ { event_name:, event_params: event_params.symbolize_keys }
20
+ end
21
+
22
+ def deconstruct_keys(keys)
23
+ keys ? to_h.slice(*keys) : to_h
24
+ end
25
+
26
+ def self.from_hash(event_hash)
27
+ if event_name = event_hash.delete('__event__')
28
+ new(event_name, event_hash)
29
+ end
13
30
  end
14
31
 
15
- def self.from_string(str)
16
- new(*str.split('|'))
32
+ def ==(other)
33
+ self.class == other.class && event_name == other.event_name &&
34
+ event_params == other.event_params
17
35
  end
18
36
  end
19
37
  end
@@ -12,13 +12,18 @@ module GaEvents
12
12
  def_delegators :data, :<<, :present?
13
13
 
14
14
  def to_s
15
- data.collect(&:to_s).join('$')
15
+ "[#{data.collect(&:to_s).join(',')}]"
16
16
  end
17
17
 
18
18
  # Init list, optionally with a string of serialized events
19
19
  def init(str = nil)
20
20
  Thread.current[:ga_events] = []
21
- (str || '').split('$').each { |s| GaEvents::Event.from_string(s) }
21
+ if str.present?
22
+ raw_events = JSON.parse(str)
23
+ raw_events.each { |raw_event| GaEvents::Event.from_hash(raw_event) }
24
+ end
25
+ rescue JSON::ParserError
26
+ nil
22
27
  end
23
28
 
24
29
  private
@@ -4,6 +4,8 @@ require 'rack/utils'
4
4
 
5
5
  module GaEvents
6
6
  class Middleware
7
+ SESSION_GA_EVENTS_KEY = 'ga_events.events'
8
+
7
9
  def initialize(app)
8
10
  @app = app
9
11
  end
@@ -20,12 +22,11 @@ module GaEvents
20
22
  serialized = GaEvents::List.to_s
21
23
  if xhr_or_turbolinks?(request)
22
24
  # AJAX request
23
- headers['X-GA-Events'] = serialized
24
-
25
+ headers['x-ga-events'] = CGI.escapeURIComponent(serialized)
25
26
  elsif redirect?(status)
26
- # 30x/redirect? Then add event list to flash to survive the redirect.
27
- add_events_to_flash(env, serialized)
28
-
27
+ # 30x/redirect? Then add event list to rack session to survive the
28
+ # redirect.
29
+ add_events_to_session(env, serialized)
29
30
  elsif html?(status, headers)
30
31
  response = inject_div(response, serialized)
31
32
  end
@@ -37,23 +38,14 @@ module GaEvents
37
38
  private
38
39
 
39
40
  def init_event_list(env)
40
- flash = env['rack.session'] && env['rack.session']['flash'] &&
41
- env['rack.session']['flash']['flashes']
42
-
43
- # The key has to be removed from the flash here to ensure it does not
44
- # remain after the finished redirect. This copies the behaviour of the
45
- # "#use" and "#sweep" methods of the rails flash middleware:
46
- # https://github.com/rails/rails/blob/v3.2.14/actionpack/lib/action_dispatch/middleware/flash.rb#L220
47
- GaEvents::List.init(flash&.delete('ga_events'))
41
+ events = env['rack.session']&.delete(SESSION_GA_EVENTS_KEY)
42
+ GaEvents::List.init(events)
48
43
  end
49
44
 
50
- def add_events_to_flash env, serialized_data
51
- flash = env['rack.session'] && env['rack.session']['flash'] &&
52
- env['rack.session']['flash']['flashes']
53
-
54
- return unless flash
55
-
56
- flash['ga_events'] = serialized_data
45
+ def add_events_to_session env, serialized_data
46
+ if session = env.dig('rack.session')
47
+ session[SESSION_GA_EVENTS_KEY] = serialized_data
48
+ end
57
49
  end
58
50
 
59
51
  def normalize_response(response)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GaEvents
4
- VERSION = '3.0.0'
4
+ VERSION = '4.0.0'
5
5
  end
@@ -0,0 +1,68 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe GaEvents::Event do
4
+ it 'has a custom #to_s implementation ' do
5
+ expect(
6
+ described_class.new('test', { p1: 'my-action', p2: 'my-label' }).to_s
7
+ ).to eq('{"__event__":"test","p1":"my-action","p2":"my-label"}')
8
+ end
9
+
10
+ it 'can be restored from hash' do
11
+ initialized_event =
12
+ described_class.new(
13
+ 'test',
14
+ {
15
+ 'category' => 'my-category',
16
+ 'label' => 'my-label',
17
+ 'value' => 'my-value'
18
+ }
19
+ )
20
+ from_hash_event =
21
+ described_class.from_hash(
22
+ {
23
+ 'category' => 'my-category',
24
+ '__event__' => 'test',
25
+ 'label' => 'my-label',
26
+ 'value' => 'my-value'
27
+ }
28
+ )
29
+ expect(from_hash_event).to eq initialized_event
30
+ end
31
+
32
+ it 'adds itself to GaEvents::List' do
33
+ described_class.from_hash(
34
+ {
35
+ '__event__' => 'test',
36
+ 'category' => 'my-category',
37
+ 'label' => 'my-label',
38
+ 'value' => 'first-value'
39
+ }
40
+ )
41
+ described_class.new('clicked', { some: 'thing' })
42
+
43
+ expect(GaEvents::List.to_s).to eq(<<~EVENTS.tr("\n", ''))
44
+ [{"__event__":"test","category":"my-category","label":"my-label","value":"first-value"},
45
+ {"__event__":"clicked","some":"thing"}]
46
+ EVENTS
47
+ end
48
+
49
+ it 'can be initialized with a hash' do
50
+ expect(
51
+ described_class.new('one_value', { stars: 5 }).to_s
52
+ ).to eq '{"__event__":"one_value","stars":5}'
53
+ expect(
54
+ described_class.new('two_values', { stars: 5, mode: 'main' }).to_s
55
+ ).to eq '{"__event__":"two_values","stars":5,"mode":"main"}'
56
+ expect(
57
+ described_class.new('with_array', { list: [5, 'stars'] }).to_s
58
+ ).to eq '{"__event__":"with_array","list":[5,"stars"]}'
59
+ end
60
+
61
+ it 'can be pattern matched against' do
62
+ event = described_class.new('test', { stars: 5 })
63
+ event => {
64
+ event_name: 'test', event_params: { stars: Integer => five_stars }
65
+ }
66
+ expect(five_stars).to eq 5
67
+ end
68
+ end
data/spec/list_spec.rb ADDED
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe 'GaEvents::List' do
4
+ describe '#to_s' do
5
+ it 'generates valid json' do
6
+ GaEvents::Event.new('clicked', { a: 'a' })
7
+ GaEvents::Event.new('clicked', { b: 'b' })
8
+ expect(JSON.parse(GaEvents::List.to_s)).to eq(
9
+ [
10
+ { '__event__' => 'clicked', 'a' => 'a' },
11
+ { '__event__' => 'clicked', 'b' => 'b' }
12
+ ]
13
+ )
14
+ end
15
+ end
16
+
17
+ it 'can be initialized with a json string' do
18
+ GaEvents::List.init(<<~JSON.squish)
19
+ [
20
+ { "__event__": "clicked", "a": "a" }
21
+ ]
22
+ JSON
23
+
24
+ expect(
25
+ GaEvents::List.send(:data).to_h { [_1.event_name, _1.event_params] }
26
+ ).to eq({ 'clicked' => { 'a' => 'a' } })
27
+ end
28
+
29
+ it 'can be initialized with a broken json string' do
30
+ GaEvents::List.init(<<~JSON.squish)
31
+ [
32
+ { "__event__": "clicked", "trailing": "comma triggers ParserError", }
33
+ ]
34
+ JSON
35
+
36
+ expect(
37
+ GaEvents::List.send(:data).to_h { [_1.event_name, _1.event_params] }
38
+ ).to be_empty
39
+ end
40
+ end
@@ -33,26 +33,26 @@ describe GaEvents::Middleware do
33
33
  context 'events present in GaEvents::List' do
34
34
  let(:app) do
35
35
  proc do |_|
36
- GaEvents::Event.new('category', 'action', 'label', 'value')
36
+ GaEvents::Event.new('test', { 'cool' => 'stuff' })
37
37
  [200, { 'Content-Type' => 'text/html' }, response_body]
38
38
  end
39
39
  end
40
40
 
41
- context 'there is no body closing tag' do
41
+ context 'when no body closing tag exists' do
42
42
  let(:response) { request.get('/') }
43
43
  it 'leaves everything as it was' do
44
44
  expect(response.body).to eq response_body
45
45
  end
46
46
  end
47
47
 
48
- context 'there exists body closing tag' do
48
+ context 'when a body closing tag exists' do
49
49
  let(:response) { request.get('/') }
50
50
  let(:response_body) { 'something awesome!</body>' }
51
51
 
52
52
  it 'injects data-ga-events' do
53
53
  expect(response.body).to eq(
54
54
  'something awesome!' \
55
- "<div data-ga-events='category|action|label|value'></div></body>"
55
+ "<div data-ga-events='[{\"__event__\":\"test\",\"cool\":\"stuff\"}]'></div></body>"
56
56
  )
57
57
  end
58
58
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ga_events
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0
4
+ version: 4.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Florian Dütsch
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2022-01-10 00:00:00.000000000 Z
12
+ date: 2023-08-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -49,6 +49,8 @@ files:
49
49
  - lib/ga_events/list.rb
50
50
  - lib/ga_events/middleware.rb
51
51
  - lib/ga_events/version.rb
52
+ - spec/event_spec.rb
53
+ - spec/list_spec.rb
52
54
  - spec/middleware_spec.rb
53
55
  - spec/spec_helper.rb
54
56
  homepage: https://github.com/Nix-wie-weg/ga_events
@@ -63,15 +65,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
63
65
  requirements:
64
66
  - - ">="
65
67
  - !ruby/object:Gem::Version
66
- version: '2.3'
68
+ version: '3.2'
67
69
  required_rubygems_version: !ruby/object:Gem::Requirement
68
70
  requirements:
69
71
  - - ">="
70
72
  - !ruby/object:Gem::Version
71
73
  version: '0'
72
74
  requirements: []
73
- rubyforge_project:
74
- rubygems_version: 2.7.6.2
75
+ rubygems_version: 3.4.6
75
76
  signing_key:
76
77
  specification_version: 4
77
78
  summary: This gem allows you to annotate events everywhere in the code of your Rails
@@ -81,5 +82,7 @@ summary: This gem allows you to annotate events everywhere in the code of your R
81
82
  extracts this data on the client side and pushes it to Google Analytics via ga.js
82
83
  or Google Tag Manager.
83
84
  test_files:
85
+ - spec/event_spec.rb
86
+ - spec/list_spec.rb
84
87
  - spec/middleware_spec.rb
85
88
  - spec/spec_helper.rb