ga_events 2.1.0 → 4.0.0
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.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/CHANGELOG.md +43 -1
- data/Gemfile +1 -1
- data/README.md +21 -18
- data/Rakefile +5 -0
- data/app/assets/javascripts/ga_events.js.coffee +43 -55
- data/ga_events.gemspec +2 -0
- data/lib/ga_events/event.rb +24 -6
- data/lib/ga_events/list.rb +7 -2
- data/lib/ga_events/middleware.rb +12 -20
- data/lib/ga_events/version.rb +1 -1
- data/spec/event_spec.rb +68 -0
- data/spec/list_spec.rb +40 -0
- data/spec/middleware_spec.rb +4 -4
- metadata +10 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: af13dc202f2b24f7fa7ba45345d90fea5158e4b50c5e55fbb6bbc68752c6083b
|
4
|
+
data.tar.gz: bbd3f2173bba05a2ce2d1dc4315a288b83b469810327dd2cbccd30799f6e595a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cb529a2794580ae3c52a2a226c620b94ba79b278dc1171fcda5a27bdc511901b95f2d9243028285484a2a8d66af2feeb6a40539e82e5def320ed0974bf62e74e
|
7
|
+
data.tar.gz: 9b9adf95d667f066198b222cb45e233b83b03420e84a6743cd93cfba70b90bbaed7982b070d552f37e69c148a21800159a18223af176d6dac955049fe8f02971
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -40,7 +40,7 @@ The format suggested at http://keepachangelog.com/ is used.
|
|
40
40
|
- Ensure category, action and label do not include any umlauts or ß chars
|
41
41
|
- Fixed an error where events are remaining after a redirect
|
42
42
|
|
43
|
-
## 2.0.0 -
|
43
|
+
## 2.0.0 - 2020-11-20
|
44
44
|
|
45
45
|
### Removed
|
46
46
|
- Support for rubies < 2.3
|
@@ -48,3 +48,45 @@ The format suggested at http://keepachangelog.com/ is used.
|
|
48
48
|
|
49
49
|
### Added
|
50
50
|
- Compatibility for Rails 5
|
51
|
+
|
52
|
+
## 2.1.0 - 2021-09-07
|
53
|
+
|
54
|
+
### Added
|
55
|
+
- Optional user consent flag to prevent event flushing until consent was given
|
56
|
+
|
57
|
+
## 3.0.0 - 2022-01-10
|
58
|
+
|
59
|
+
### Added
|
60
|
+
- Universal Analytics Adapter can be configured to use `gtag.js` instead of
|
61
|
+
`analytics.js` event syntax
|
62
|
+
- [Breaking] The constructor interface has changed due to more configuration
|
63
|
+
options that differ between `analytics.js` and `gtag.js`.
|
64
|
+
- Universal Analytics Adapter can be configured to use a custom name for the
|
65
|
+
analytics object (defaults to `window.ga()` for `analytics.js` and
|
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
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
|
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
|
12
|
+
pushes it to Google Analytics via gtag.js or Google Tag Manager.
|
13
13
|
|
14
14
|
## Dependencies
|
15
15
|
|
16
|
-
* Ruby >= 2
|
16
|
+
* Ruby >= 3.2
|
17
17
|
* Rails 4.2 onwards
|
18
18
|
* jQuery
|
19
19
|
|
@@ -35,27 +35,35 @@ 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 (
|
38
|
+
### Google Analytics 4 (gtag.js)
|
39
39
|
|
40
40
|
```javascript
|
41
41
|
GaEvents.Event.adapter = function() {
|
42
|
-
return new GaEvents.
|
42
|
+
return new GaEvents.GTagAdapter();
|
43
43
|
}
|
44
44
|
```
|
45
45
|
|
46
|
-
|
46
|
+
Optionally you can specify a custom tracker GA_MEASUREMENT_ID where you want
|
47
|
+
your events to be sent to:
|
47
48
|
|
48
49
|
```javascript
|
49
50
|
GaEvents.Event.adapter = function() {
|
50
|
-
return new GaEvents.
|
51
|
+
return new GaEvents.GTagAdapter(
|
52
|
+
{tracker_name: "GA_MEASUREMENT_ID"}
|
53
|
+
);
|
51
54
|
}
|
52
55
|
```
|
53
56
|
|
54
|
-
|
57
|
+
#### Optional custom object name
|
58
|
+
|
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:
|
55
61
|
|
56
62
|
```javascript
|
57
63
|
GaEvents.Event.adapter = function() {
|
58
|
-
return new GaEvents.
|
64
|
+
return new GaEvents.GTagAdapter(
|
65
|
+
{analytics_object_name: "analytics"} // calls window.analytics()
|
66
|
+
);
|
59
67
|
}
|
60
68
|
```
|
61
69
|
|
@@ -98,24 +106,18 @@ HTTP header is added to the response.
|
|
98
106
|
You can create a new event like this:
|
99
107
|
|
100
108
|
```ruby
|
101
|
-
GaEvents::Event.new(
|
109
|
+
GaEvents::Event.new('example_event', { extra: 'dimension' })
|
102
110
|
```
|
103
111
|
|
104
112
|
On the client-side there is a similar interface to GaEvents:
|
105
113
|
|
106
114
|
```javascript
|
107
|
-
new GaEvents.Event(
|
115
|
+
new GaEvents.Event('example_event', { extra: 'dimension' })
|
108
116
|
```
|
109
117
|
|
110
118
|
We have taken special care of tracking events while the DOM is loading.
|
111
119
|
Events get collected until the DOM is ready and flushed afterwards.
|
112
120
|
|
113
|
-
### Default values
|
114
|
-
|
115
|
-
While collecting hundreds of thousands of events on a daily basis in
|
116
|
-
Google Analytics we found corrupted aggregated events when the event label or
|
117
|
-
value is omitted. We now enforce a default label ("-") and value (1).
|
118
|
-
|
119
121
|
### Too many events
|
120
122
|
|
121
123
|
Use something like this snippet to get informed of bloating HTTP headers with
|
@@ -161,5 +163,6 @@ Yes please! Use pull requests.
|
|
161
163
|
## More docs and tools
|
162
164
|
|
163
165
|
* [Google Analytics: Event Tracking](https://developers.google.com/analytics/devguides/collection/gajs/eventTrackerGuide)
|
166
|
+
* [Google Universal Analytics: Event Tracking (gtag.js)](https://developers.google.com/analytics/devguides/collection/gtagjs/events)
|
164
167
|
* [Google Tag Manager: Custom Events](http://support.google.com/tagmanager/answer/2574372#GoogleAnalytics)
|
165
|
-
* [Chrome Web Store:
|
168
|
+
* [Chrome Web Store: Tag Assistant](https://chrome.google.com/webstore/detail/tag-assistant-legacy-by-g/kejbdjndbnbjgmefkgdddjlbokphdefk)
|
data/Rakefile
CHANGED
@@ -7,23 +7,27 @@ class GaEvents.Event
|
|
7
7
|
adapter: null
|
8
8
|
@list: []
|
9
9
|
@may_flush: false
|
10
|
-
@header_key: "
|
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
|
-
# Decompose
|
17
|
-
@
|
18
|
-
|
19
|
-
|
20
|
-
|
16
|
+
# Decompose an event-string (ruby side) into an event object.
|
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
|
-
|
24
|
-
|
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
|
-
# Events should not be
|
30
|
+
# Events should not be sent to an adapter unless the DOM has finished loading.
|
27
31
|
@flush: ->
|
28
32
|
return if @require_user_consent && !@user_consent_given
|
29
33
|
|
@@ -32,33 +36,18 @@ class GaEvents.Event
|
|
32
36
|
@list = []
|
33
37
|
|
34
38
|
# Add all events to a queue to flush them later
|
35
|
-
constructor: (@
|
39
|
+
constructor: (@event_name, @options = {}) ->
|
36
40
|
@klass.list.push @
|
37
41
|
@klass.flush()
|
38
42
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
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
|
-
# https://developers.google.com/analytics/devguides/collection/gajs/eventTrackerGuide#SettingUpEventTracking
|
61
|
-
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)
|
62
51
|
|
63
52
|
jQuery =>
|
64
53
|
@may_flush = true
|
@@ -66,7 +55,7 @@ class GaEvents.Event
|
|
66
55
|
|
67
56
|
process_xhr = (xhr) =>
|
68
57
|
xhr_events = xhr.getResponseHeader @header_key
|
69
|
-
@
|
58
|
+
@from_json decodeURIComponent(xhr_events) if xhr_events?
|
70
59
|
|
71
60
|
$(document).ajaxComplete((_, xhr) -> process_xhr(xhr))
|
72
61
|
$(document).on "turbolinks:request-end", (event) ->
|
@@ -76,32 +65,31 @@ class GaEvents.Event
|
|
76
65
|
@from_dom()
|
77
66
|
|
78
67
|
|
68
|
+
class GaEvents.GTagAdapter
|
69
|
+
constructor: (options) ->
|
70
|
+
@analytics_object_name = options?.analytics_object_name || 'gtag'
|
71
|
+
|
72
|
+
# https://developers.google.com/analytics/devguides/migration/ua/analyticsjs-to-gtagjs#measure_pageviews_with_specified_trackers
|
73
|
+
@tracker_name = options?.tracker_name || false
|
74
|
+
|
75
|
+
push: (event_name, data) ->
|
76
|
+
data.send_to = @tracker_name if @tracker_name
|
77
|
+
window[@analytics_object_name]("event", event_name, data)
|
78
|
+
|
79
|
+
class GaEvents.NullAdapter
|
80
|
+
push: (event_name, data) -> console.log(event_name, data) if console?
|
81
|
+
|
79
82
|
class GaEvents.GoogleTagManagerAdapter
|
80
83
|
constructor: (@event = "ga_event") ->
|
81
|
-
|
84
|
+
|
85
|
+
push: (event_name, data) ->
|
82
86
|
data.event = @event
|
87
|
+
data.event_name = event_name
|
83
88
|
data.non_interaction = true
|
84
89
|
window.dataLayer.push data
|
85
90
|
|
86
|
-
class GaEvents.GoogleUniversalAnalyticsAdapter
|
87
|
-
constructor: (@method_call_name = "send", tracker_name) ->
|
88
|
-
@method_call_name = "#{tracker_name}.#{@method_call_name}" if tracker_name
|
89
|
-
|
90
|
-
push: (h) ->
|
91
|
-
window.ga @method_call_name, "event", h.category, h.action, h.label,
|
92
|
-
h.value, {"nonInteraction": true}
|
93
|
-
|
94
|
-
class GaEvents.GoogleAnalyticsAdapter
|
95
|
-
# Send events non_interactive => no influence on bounce rates
|
96
|
-
push: (h) ->
|
97
|
-
window._gaq.push(
|
98
|
-
["_trackEvent", h.category, h.action, h.label, h.value, true]
|
99
|
-
)
|
100
|
-
|
101
|
-
class GaEvents.NullAdapter
|
102
|
-
push: (obj) -> console.log obj if console?
|
103
|
-
|
104
91
|
class GaEvents.TestAdapter
|
105
|
-
push: (
|
92
|
+
push: (event_name, data) ->
|
93
|
+
loggedEvent = Object.assign({ event_name: event_name }, data)
|
106
94
|
window.events = [] unless window.events?
|
107
|
-
window.events.push
|
95
|
+
window.events.push(loggedEvent)
|
data/ga_events.gemspec
CHANGED
data/lib/ga_events/event.rb
CHANGED
@@ -1,19 +1,37 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module GaEvents
|
4
|
-
Event
|
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(
|
7
|
-
|
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
|
-
|
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
|
16
|
-
|
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
|
data/lib/ga_events/list.rb
CHANGED
@@ -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
|
-
|
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
|
data/lib/ga_events/middleware.rb
CHANGED
@@ -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['
|
24
|
-
|
25
|
+
headers['x-ga-events'] = CGI.escapeURIComponent(serialized)
|
25
26
|
elsif redirect?(status)
|
26
|
-
# 30x/redirect? Then add event list to
|
27
|
-
|
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
|
-
|
41
|
-
|
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
|
51
|
-
|
52
|
-
|
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)
|
data/lib/ga_events/version.rb
CHANGED
data/spec/event_spec.rb
ADDED
@@ -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
|
data/spec/middleware_spec.rb
CHANGED
@@ -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('
|
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 '
|
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 '
|
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='
|
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:
|
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:
|
12
|
+
date: 2023-08-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -49,10 +49,13 @@ 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
|
55
|
-
licenses:
|
57
|
+
licenses:
|
58
|
+
- MIT
|
56
59
|
metadata: {}
|
57
60
|
post_install_message:
|
58
61
|
rdoc_options: []
|
@@ -62,14 +65,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
62
65
|
requirements:
|
63
66
|
- - ">="
|
64
67
|
- !ruby/object:Gem::Version
|
65
|
-
version: '
|
68
|
+
version: '3.2'
|
66
69
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
70
|
requirements:
|
68
71
|
- - ">="
|
69
72
|
- !ruby/object:Gem::Version
|
70
73
|
version: '0'
|
71
74
|
requirements: []
|
72
|
-
rubygems_version: 3.
|
75
|
+
rubygems_version: 3.4.6
|
73
76
|
signing_key:
|
74
77
|
specification_version: 4
|
75
78
|
summary: This gem allows you to annotate events everywhere in the code of your Rails
|
@@ -79,5 +82,7 @@ summary: This gem allows you to annotate events everywhere in the code of your R
|
|
79
82
|
extracts this data on the client side and pushes it to Google Analytics via ga.js
|
80
83
|
or Google Tag Manager.
|
81
84
|
test_files:
|
85
|
+
- spec/event_spec.rb
|
86
|
+
- spec/list_spec.rb
|
82
87
|
- spec/middleware_spec.rb
|
83
88
|
- spec/spec_helper.rb
|