track_relay 1.2.0 → 1.3.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/CHANGELOG.md +20 -0
- data/lib/track_relay/page_view_tracking.rb +102 -0
- data/lib/track_relay/version.rb +1 -1
- data/lib/track_relay.rb +1 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4d71fbb5a7101c3f407ba9fc7c05bf032a5718447a7cacd341647b9b794c47b2
|
|
4
|
+
data.tar.gz: b36598739beda0519f71b98cf906159b3857234dd9510d7aff35d1f33ecd9808
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f71946bad98b203c57850991846de8e3fb95828bc825f5d9ccb2d6b5a205d6531253087a65e77c0e4eb4981f5e95129439ecf081fc719939618daeb93b611ca0
|
|
7
|
+
data.tar.gz: 1b05f9d685e43a6c97e37f306aa6f0a970f1b7fe6ccb774a037a4a26043295d7464a22ec2d821425aad6eb9ac6e1e07461420f7fc8ce6875f3bec1919e3d95e1
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [1.3.0] - 2026-07-31
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- `TrackRelay::PageViewTracking` — opt-in automatic server-side
|
|
14
|
+
`page_view` emission for hosts delivering GA4 purely via the
|
|
15
|
+
Measurement Protocol (no client gtag). `include
|
|
16
|
+
TrackRelay::PageViewTracking` + `track_page_views` emits exactly one
|
|
17
|
+
`page_view` per full HTML page render — never for JSON/non-HTML,
|
|
18
|
+
turbo-frame fetches, turbo-stream responses, redirects, non-GETs, or
|
|
19
|
+
unsuccessful responses. A host suppression hook (`track_page_views
|
|
20
|
+
if: :method_name` or a proc, instance-exec'd per request) is where
|
|
21
|
+
tracking policy (opt-out, geo, bot checks) plugs in. Events ride the
|
|
22
|
+
normal `TrackRelay.track` path, so `track_gate`, subscribers, and
|
|
23
|
+
GA4 page-context enrichment apply unchanged.
|
|
24
|
+
- The builtin `page_view` event is registered directly with the
|
|
25
|
+
catalog (and therefore the manifest), deliberately bypassing the
|
|
26
|
+
DSL's GA4 reserved-name validation: that guard protects *custom*
|
|
27
|
+
events from shadowing gtag auto-collection, but the MP-standard
|
|
28
|
+
`page_view` is exactly what a server-side host must send.
|
|
29
|
+
|
|
10
30
|
## [1.2.0] - 2026-07-31
|
|
11
31
|
|
|
12
32
|
### Added
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_support/concern"
|
|
4
|
+
|
|
5
|
+
module TrackRelay
|
|
6
|
+
# Opt-in automatic server-side `page_view` emission.
|
|
7
|
+
#
|
|
8
|
+
# Hosts that deliver GA4 purely via the Measurement Protocol (no
|
|
9
|
+
# client-side gtag) still need standard `page_view` events for GA4's
|
|
10
|
+
# page and engagement reports. Include this concern and call the
|
|
11
|
+
# macro:
|
|
12
|
+
#
|
|
13
|
+
# class ApplicationController < ActionController::Base
|
|
14
|
+
# include TrackRelay::PageViewTracking
|
|
15
|
+
# track_page_views
|
|
16
|
+
# end
|
|
17
|
+
#
|
|
18
|
+
# Events go through the normal {TrackRelay.track} path, so the host's
|
|
19
|
+
# `track_gate`, subscribers, and GA4 page-context enrichment apply
|
|
20
|
+
# unchanged.
|
|
21
|
+
#
|
|
22
|
+
# ## The builtin `page_view` catalog entry
|
|
23
|
+
#
|
|
24
|
+
# `page_view` sits in {TrackRelay::GA4_RESERVED_NAMES}, which guards
|
|
25
|
+
# *custom* catalog events from shadowing gtag's auto-collected ones.
|
|
26
|
+
# A server-side host has no auto-collection — the MP-standard
|
|
27
|
+
# `page_view` is exactly what it must send — so the concern registers
|
|
28
|
+
# the definition directly with the catalog, bypassing the DSL's
|
|
29
|
+
# reserved-name validation on purpose.
|
|
30
|
+
module PageViewTracking
|
|
31
|
+
extend ActiveSupport::Concern
|
|
32
|
+
|
|
33
|
+
include ControllerTracking
|
|
34
|
+
|
|
35
|
+
# Register the builtin `page_view` {EventDefinition} (no params —
|
|
36
|
+
# page context is attached by GA4 enrichment at delivery time).
|
|
37
|
+
# Idempotent so it can be re-run after test-suite `Catalog.clear!`.
|
|
38
|
+
#
|
|
39
|
+
# @return [void]
|
|
40
|
+
def self.register_builtin_event!
|
|
41
|
+
return if Catalog.defined?(:page_view)
|
|
42
|
+
|
|
43
|
+
Catalog.register(EventDefinition.new(name: :page_view))
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
included do
|
|
47
|
+
class_attribute :_track_relay_page_view_condition,
|
|
48
|
+
instance_accessor: false, instance_predicate: false, default: nil
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
class_methods do
|
|
52
|
+
# Enable automatic page_view emission for this controller (and
|
|
53
|
+
# subclasses).
|
|
54
|
+
#
|
|
55
|
+
# @param if [Symbol, Proc, nil] host-side suppression hook —
|
|
56
|
+
# a method name or proc evaluated in the controller instance
|
|
57
|
+
# per request; a falsy result suppresses the page_view.
|
|
58
|
+
# Tracking *policy* (opt-out, geo, bot checks) belongs to the
|
|
59
|
+
# host; this is where it plugs in.
|
|
60
|
+
# @return [void]
|
|
61
|
+
def track_page_views(if: nil)
|
|
62
|
+
self._track_relay_page_view_condition = binding.local_variable_get(:if)
|
|
63
|
+
PageViewTracking.register_builtin_event!
|
|
64
|
+
after_action :_track_relay_emit_page_view
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
private
|
|
69
|
+
|
|
70
|
+
def _track_relay_emit_page_view
|
|
71
|
+
return unless _track_relay_page_view_response?
|
|
72
|
+
return unless _track_relay_page_view_allowed?
|
|
73
|
+
|
|
74
|
+
PageViewTracking.register_builtin_event!
|
|
75
|
+
track(:page_view)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def _track_relay_page_view_allowed?
|
|
79
|
+
condition = self.class._track_relay_page_view_condition
|
|
80
|
+
case condition
|
|
81
|
+
when nil then true
|
|
82
|
+
when Symbol then !!send(condition)
|
|
83
|
+
else !!instance_exec(&condition)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Exactly one page_view per full HTML page render:
|
|
88
|
+
#
|
|
89
|
+
# - GET only (a POST that re-renders a form is not a page view)
|
|
90
|
+
# - successful (2xx) only — redirects land on a page that fires its
|
|
91
|
+
# own page_view; error pages are noise
|
|
92
|
+
# - `text/html` only (excludes JSON and turbo-stream's
|
|
93
|
+
# `text/vnd.turbo-stream.html`)
|
|
94
|
+
# - not a turbo-frame fetch (partial navigation within a page)
|
|
95
|
+
def _track_relay_page_view_response?
|
|
96
|
+
request.get? &&
|
|
97
|
+
response.successful? &&
|
|
98
|
+
response.media_type == "text/html" &&
|
|
99
|
+
request.headers["Turbo-Frame"].nil?
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
data/lib/track_relay/version.rb
CHANGED
data/lib/track_relay.rb
CHANGED
|
@@ -24,6 +24,7 @@ require "track_relay/subscribers/ahoy"
|
|
|
24
24
|
require "track_relay/delivery_job"
|
|
25
25
|
require "track_relay/dispatcher"
|
|
26
26
|
require "track_relay/controller_tracking"
|
|
27
|
+
require "track_relay/page_view_tracking"
|
|
27
28
|
require "track_relay/job_tracking"
|
|
28
29
|
require "track_relay/linter"
|
|
29
30
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: track_relay
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- dchuk
|
|
@@ -209,6 +209,7 @@ files:
|
|
|
209
209
|
- lib/track_relay/job_tracking.rb
|
|
210
210
|
- lib/track_relay/linter.rb
|
|
211
211
|
- lib/track_relay/manifest.rb
|
|
212
|
+
- lib/track_relay/page_view_tracking.rb
|
|
212
213
|
- lib/track_relay/railtie.rb
|
|
213
214
|
- lib/track_relay/subscribers/ahoy.rb
|
|
214
215
|
- lib/track_relay/subscribers/base.rb
|