omnitrack-rb 0.1.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 +7 -0
- data/.env.example +43 -0
- data/AI_GEM_SETUP.md +164 -0
- data/CHANGELOG.md +38 -0
- data/LICENSE.txt +21 -0
- data/README.md +364 -0
- data/USAGE.md +276 -0
- data/lib/generators/omnitrack/install/install_generator.rb +47 -0
- data/lib/generators/omnitrack/install/templates/README +19 -0
- data/lib/generators/omnitrack/install/templates/env.example +43 -0
- data/lib/generators/omnitrack/install/templates/initializer.rb +112 -0
- data/lib/omnitrack/adapters/base.rb +197 -0
- data/lib/omnitrack/adapters/google_ads.rb +172 -0
- data/lib/omnitrack/adapters/google_analytics.rb +97 -0
- data/lib/omnitrack/adapters/meta.rb +151 -0
- data/lib/omnitrack/adapters/snapchat.rb +100 -0
- data/lib/omnitrack/adapters/tiktok.rb +114 -0
- data/lib/omnitrack/concerns/controller.rb +66 -0
- data/lib/omnitrack/configuration.rb +109 -0
- data/lib/omnitrack/context.rb +119 -0
- data/lib/omnitrack/errors.rb +26 -0
- data/lib/omnitrack/helpers/view_helpers.rb +148 -0
- data/lib/omnitrack/jobs/tracking_job.rb +27 -0
- data/lib/omnitrack/logger.rb +122 -0
- data/lib/omnitrack/middleware/request_tracker.rb +40 -0
- data/lib/omnitrack/pipeline/dispatcher.rb +56 -0
- data/lib/omnitrack/railtie.rb +53 -0
- data/lib/omnitrack/registry.rb +59 -0
- data/lib/omnitrack/result.rb +113 -0
- data/lib/omnitrack/tasks/omnitrack.rake +39 -0
- data/lib/omnitrack/version.rb +5 -0
- data/lib/omnitrack.rb +166 -0
- metadata +207 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnitrack
|
|
4
|
+
# Railtie hooks OmniTrack into Rails automatically.
|
|
5
|
+
# No user action required — simply add the gem and run the installer.
|
|
6
|
+
class Railtie < Rails::Railtie
|
|
7
|
+
# Allow Rails config namespace: config.omnitrack.mode = :backend
|
|
8
|
+
config.omnitrack = ActiveSupport::OrderedOptions.new
|
|
9
|
+
|
|
10
|
+
initializer "omnitrack.tracking_job" do
|
|
11
|
+
if defined?(ActiveJob::Base)
|
|
12
|
+
require_relative "jobs/tracking_job"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
initializer "omnitrack.configure" do |app|
|
|
17
|
+
# Map any rails config keys into Omnitrack config
|
|
18
|
+
rails_cfg = app.config.omnitrack
|
|
19
|
+
if rails_cfg.any?
|
|
20
|
+
Omnitrack.configure do |c|
|
|
21
|
+
c.mode = rails_cfg[:mode] if rails_cfg[:mode]
|
|
22
|
+
c.log_level = rails_cfg[:log_level] if rails_cfg[:log_level]
|
|
23
|
+
c.async = rails_cfg[:async] if rails_cfg.key?(:async)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
initializer "omnitrack.middleware" do |app|
|
|
29
|
+
app.middleware.use Omnitrack::Middleware::RequestTracker
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
initializer "omnitrack.view_helpers" do
|
|
33
|
+
ActiveSupport.on_load(:action_view) do
|
|
34
|
+
include Omnitrack::Helpers::ViewHelpers
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
initializer "omnitrack.controller_helpers" do
|
|
39
|
+
ActiveSupport.on_load(:action_controller) do
|
|
40
|
+
include Omnitrack::Controller
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
initializer "omnitrack.logger_setup" do
|
|
45
|
+
Omnitrack.send(:reset_logger!)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Expose rake tasks
|
|
49
|
+
rake_tasks do
|
|
50
|
+
load File.join(__dir__, "tasks/omnitrack.rake")
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnitrack
|
|
4
|
+
# Thread-safe registry mapping adapter names (symbols) → adapter classes.
|
|
5
|
+
# Adapters are auto-registered via Base.inherited and can also be registered
|
|
6
|
+
# manually with Registry.register.
|
|
7
|
+
module Registry
|
|
8
|
+
MUTEX = Mutex.new
|
|
9
|
+
private_constant :MUTEX
|
|
10
|
+
|
|
11
|
+
@adapters = {}
|
|
12
|
+
|
|
13
|
+
class << self
|
|
14
|
+
# Register an adapter class.
|
|
15
|
+
# @param klass [Class] must inherit from Omnitrack::Adapters::Base
|
|
16
|
+
def register(klass)
|
|
17
|
+
MUTEX.synchronize do
|
|
18
|
+
@adapters[klass.adapter_name] = klass
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Look up an adapter class by name.
|
|
23
|
+
# @param name [Symbol, String]
|
|
24
|
+
# @return [Class]
|
|
25
|
+
# @raise [Omnitrack::UnknownAdapterError]
|
|
26
|
+
def lookup(name)
|
|
27
|
+
klass = MUTEX.synchronize { @adapters[name.to_sym] }
|
|
28
|
+
raise Omnitrack::UnknownAdapterError, "Unknown adapter: #{name}" unless klass
|
|
29
|
+
|
|
30
|
+
klass
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# All registered adapter names
|
|
34
|
+
def registered
|
|
35
|
+
MUTEX.synchronize { @adapters.keys }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Instantiate all *enabled* adapters based on current configuration.
|
|
39
|
+
# @return [Array<Omnitrack::Adapters::Base>]
|
|
40
|
+
def enabled_adapters
|
|
41
|
+
MUTEX.synchronize { @adapters.dup }.filter_map do |adapter_name, klass|
|
|
42
|
+
cfg = Omnitrack.config.adapter_config(adapter_name)
|
|
43
|
+
next unless cfg.fetch(:enabled, false)
|
|
44
|
+
|
|
45
|
+
klass.new(config: cfg, logger: Omnitrack.logger)
|
|
46
|
+
rescue Omnitrack::ConfigurationError => e
|
|
47
|
+
Omnitrack.logger.error("registry.init_error",
|
|
48
|
+
adapter: adapter_name, message: e.message)
|
|
49
|
+
nil
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Clear all registrations (useful in tests)
|
|
54
|
+
def reset!
|
|
55
|
+
MUTEX.synchronize { @adapters = {} }
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnitrack
|
|
4
|
+
# Immutable value object returned by every adapter call.
|
|
5
|
+
# Provides a consistent interface regardless of platform.
|
|
6
|
+
class Result
|
|
7
|
+
attr_reader :status, :adapter, :data, :error, :metadata
|
|
8
|
+
|
|
9
|
+
def initialize(status:, adapter: nil, data: nil, error: nil, metadata: {})
|
|
10
|
+
@status = status.to_sym # :success | :failure | :skipped
|
|
11
|
+
@adapter = adapter
|
|
12
|
+
@data = data
|
|
13
|
+
@error = error
|
|
14
|
+
@metadata = metadata || {}
|
|
15
|
+
freeze
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# -------------------------------------------------------------------
|
|
19
|
+
# Factory methods
|
|
20
|
+
# -------------------------------------------------------------------
|
|
21
|
+
|
|
22
|
+
def self.success(adapter: nil, data: nil, metadata: {})
|
|
23
|
+
new(status: :success, adapter: adapter, data: data, metadata: metadata)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def self.failure(error: nil, adapter: nil, metadata: {})
|
|
27
|
+
new(status: :failure, adapter: adapter, error: error, metadata: metadata)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def self.skipped(reason: nil, adapter: nil)
|
|
31
|
+
new(status: :skipped, adapter: adapter,
|
|
32
|
+
metadata: { reason: reason })
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# -------------------------------------------------------------------
|
|
36
|
+
# Predicate helpers
|
|
37
|
+
# -------------------------------------------------------------------
|
|
38
|
+
|
|
39
|
+
def success?
|
|
40
|
+
@status == :success
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def failure?
|
|
44
|
+
@status == :failure
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def skipped?
|
|
48
|
+
@status == :skipped
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# -------------------------------------------------------------------
|
|
52
|
+
# Serialisation
|
|
53
|
+
# -------------------------------------------------------------------
|
|
54
|
+
|
|
55
|
+
def to_h
|
|
56
|
+
{
|
|
57
|
+
status: @status,
|
|
58
|
+
adapter: @adapter,
|
|
59
|
+
data: @data,
|
|
60
|
+
error: @error&.message,
|
|
61
|
+
metadata: @metadata
|
|
62
|
+
}
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def to_json(*args)
|
|
66
|
+
require "json"
|
|
67
|
+
JSON.generate(to_h, *args)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def inspect
|
|
71
|
+
"#<Omnitrack::Result status=#{@status} adapter=#{@adapter} " \
|
|
72
|
+
"error=#{@error&.message.inspect}>"
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Aggregated result for pipeline dispatches (one result per adapter)
|
|
77
|
+
class MultiResult
|
|
78
|
+
include Enumerable
|
|
79
|
+
|
|
80
|
+
attr_reader :results
|
|
81
|
+
|
|
82
|
+
def initialize(results = [])
|
|
83
|
+
@results = results.freeze
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def each(&block)
|
|
87
|
+
@results.each(&block)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def success?
|
|
91
|
+
@results.all?(&:success?)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def any_failure?
|
|
95
|
+
@results.any?(&:failure?)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def failures
|
|
99
|
+
@results.select(&:failure?)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def successes
|
|
103
|
+
@results.select(&:success?)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def to_h
|
|
107
|
+
{
|
|
108
|
+
success: success?,
|
|
109
|
+
results: @results.map(&:to_h)
|
|
110
|
+
}
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
namespace :omnitrack do
|
|
4
|
+
desc "Show OmniTrack configuration and registered adapters"
|
|
5
|
+
task status: :environment do
|
|
6
|
+
puts "\n=== OmniTrack v#{Omnitrack::VERSION} ===\n"
|
|
7
|
+
puts "Mode: #{Omnitrack.config.effective_mode}"
|
|
8
|
+
puts "Log file: #{Omnitrack.config.resolved_log_file}"
|
|
9
|
+
puts "Log level: #{Omnitrack.config.log_level}"
|
|
10
|
+
puts "Async: #{Omnitrack.config.async}"
|
|
11
|
+
puts "Queue: #{Omnitrack.config.queue_name}"
|
|
12
|
+
puts "\nRegistered adapters:"
|
|
13
|
+
Omnitrack::Registry.registered.each do |adapter_name|
|
|
14
|
+
enabled = Omnitrack.config.adapter_enabled?(adapter_name)
|
|
15
|
+
status = enabled ? "✓ enabled" : "✗ disabled"
|
|
16
|
+
puts " #{adapter_name.to_s.ljust(20)} #{status}"
|
|
17
|
+
end
|
|
18
|
+
puts ""
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
desc "Send a test event through all enabled adapters"
|
|
22
|
+
task :test_event, [:event_name] => :environment do |_, args|
|
|
23
|
+
event = args[:event_name] || "test_event"
|
|
24
|
+
puts "Sending test event '#{event}' through all enabled adapters..."
|
|
25
|
+
result = Omnitrack.track(event, value: 1.0, currency: "USD", test: true)
|
|
26
|
+
result.each do |r|
|
|
27
|
+
icon = r.success? ? "✓" : (r.skipped? ? "–" : "✗")
|
|
28
|
+
puts " #{icon} #{r.adapter}: #{r.status}"
|
|
29
|
+
puts " error: #{r.error&.message}" if r.failure?
|
|
30
|
+
end
|
|
31
|
+
puts ""
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
desc "Rotate OmniTrack log file"
|
|
35
|
+
task rotate_log: :environment do
|
|
36
|
+
Omnitrack.logger.reopen
|
|
37
|
+
puts "OmniTrack log rotated: #{Omnitrack.config.resolved_log_file}"
|
|
38
|
+
end
|
|
39
|
+
end
|
data/lib/omnitrack.rb
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_support/concern"
|
|
4
|
+
require "active_support/core_ext/object/blank"
|
|
5
|
+
require "active_support/core_ext/string/inflections"
|
|
6
|
+
require "fileutils"
|
|
7
|
+
require "securerandom"
|
|
8
|
+
|
|
9
|
+
require_relative "omnitrack/version"
|
|
10
|
+
require_relative "omnitrack/errors"
|
|
11
|
+
require_relative "omnitrack/result"
|
|
12
|
+
require_relative "omnitrack/configuration"
|
|
13
|
+
require_relative "omnitrack/logger"
|
|
14
|
+
require_relative "omnitrack/context"
|
|
15
|
+
require_relative "omnitrack/registry"
|
|
16
|
+
require_relative "omnitrack/pipeline/dispatcher"
|
|
17
|
+
require_relative "omnitrack/adapters/base"
|
|
18
|
+
require_relative "omnitrack/adapters/google_ads"
|
|
19
|
+
require_relative "omnitrack/adapters/google_analytics"
|
|
20
|
+
require_relative "omnitrack/adapters/meta"
|
|
21
|
+
require_relative "omnitrack/adapters/tiktok"
|
|
22
|
+
require_relative "omnitrack/adapters/snapchat"
|
|
23
|
+
require_relative "omnitrack/middleware/request_tracker"
|
|
24
|
+
require_relative "omnitrack/helpers/view_helpers"
|
|
25
|
+
require_relative "omnitrack/concerns/controller"
|
|
26
|
+
|
|
27
|
+
# Lazy-load Rails integrations only when Rails is present
|
|
28
|
+
if defined?(Rails)
|
|
29
|
+
require_relative "omnitrack/railtie"
|
|
30
|
+
require_relative "generators/omnitrack/install/install_generator"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# ==============================================================================
|
|
34
|
+
# Omnitrack
|
|
35
|
+
# ==============================================================================
|
|
36
|
+
# Top-level module providing the primary public API.
|
|
37
|
+
#
|
|
38
|
+
# Usage:
|
|
39
|
+
# Omnitrack.configure { |c| c.adapters = { ... } }
|
|
40
|
+
# Omnitrack.track("purchase", value: 99.00, currency: "USD")
|
|
41
|
+
# Omnitrack.track_conversion(value: 99.00, order_id: "ORD-001")
|
|
42
|
+
# Omnitrack.identify(email: "user@example.com")
|
|
43
|
+
#
|
|
44
|
+
module Omnitrack
|
|
45
|
+
class << self
|
|
46
|
+
# -------------------------------------------------------------------
|
|
47
|
+
# Configuration
|
|
48
|
+
# -------------------------------------------------------------------
|
|
49
|
+
|
|
50
|
+
# Access the global configuration object.
|
|
51
|
+
# @return [Omnitrack::Configuration]
|
|
52
|
+
def config
|
|
53
|
+
@config ||= Configuration.new
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Configure OmniTrack via block.
|
|
57
|
+
#
|
|
58
|
+
# Omnitrack.configure do |c|
|
|
59
|
+
# c.mode = :hybrid
|
|
60
|
+
# c.adapters = { meta: { enabled: true, pixel_id: "..." } }
|
|
61
|
+
# end
|
|
62
|
+
#
|
|
63
|
+
def configure
|
|
64
|
+
yield config
|
|
65
|
+
config.validate!
|
|
66
|
+
reset_logger!
|
|
67
|
+
self
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Reset configuration and logger (useful in tests)
|
|
71
|
+
def reset!
|
|
72
|
+
@config = nil
|
|
73
|
+
@logger = nil
|
|
74
|
+
Omnitrack::Registry.reset!
|
|
75
|
+
# Re-bind built-in adapters without reloading (avoids duplicate constant/method warnings)
|
|
76
|
+
[
|
|
77
|
+
Omnitrack::Adapters::GoogleAds,
|
|
78
|
+
Omnitrack::Adapters::GoogleAnalytics,
|
|
79
|
+
Omnitrack::Adapters::Meta,
|
|
80
|
+
Omnitrack::Adapters::TikTok,
|
|
81
|
+
Omnitrack::Adapters::Snapchat
|
|
82
|
+
].each { |adapter_class| Omnitrack::Registry.register(adapter_class) }
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# -------------------------------------------------------------------
|
|
86
|
+
# Logger
|
|
87
|
+
# -------------------------------------------------------------------
|
|
88
|
+
|
|
89
|
+
# @return [Omnitrack::Logger]
|
|
90
|
+
def logger
|
|
91
|
+
@logger ||= build_logger
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# -------------------------------------------------------------------
|
|
95
|
+
# Public tracking API
|
|
96
|
+
# -------------------------------------------------------------------
|
|
97
|
+
|
|
98
|
+
# Track a named event across all enabled adapters.
|
|
99
|
+
#
|
|
100
|
+
# @param event_name [String, Symbol]
|
|
101
|
+
# @param payload [Hash]
|
|
102
|
+
# @return [Omnitrack::MultiResult]
|
|
103
|
+
def track(event_name, payload = {})
|
|
104
|
+
dispatch(:track_event, event_name.to_s, payload.to_h)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Track a conversion across all enabled adapters.
|
|
108
|
+
#
|
|
109
|
+
# @param data [Hash]
|
|
110
|
+
# @return [Omnitrack::MultiResult]
|
|
111
|
+
def track_conversion(data = {})
|
|
112
|
+
dispatch(:track_conversion, data.to_h)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Identify a user across all enabled adapters.
|
|
116
|
+
#
|
|
117
|
+
# @param user_data [Hash] keys: :email, :phone, :external_id, :first_name, :last_name, etc.
|
|
118
|
+
# @return [Omnitrack::MultiResult]
|
|
119
|
+
def identify(user_data = {})
|
|
120
|
+
dispatch(:identify_user, user_data.to_h)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# -------------------------------------------------------------------
|
|
124
|
+
# Mode helpers
|
|
125
|
+
# -------------------------------------------------------------------
|
|
126
|
+
|
|
127
|
+
def frontend_mode?
|
|
128
|
+
%i[frontend hybrid].include?(config.effective_mode)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def backend_mode?
|
|
132
|
+
%i[backend hybrid].include?(config.effective_mode)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
private
|
|
136
|
+
|
|
137
|
+
def dispatch(operation, *args)
|
|
138
|
+
if config.async && defined?(Omnitrack::Jobs::TrackingJob)
|
|
139
|
+
Omnitrack::Jobs::TrackingJob.perform_later(operation.to_s, *args)
|
|
140
|
+
return Omnitrack::MultiResult.new([
|
|
141
|
+
Omnitrack::Result.success(metadata: { queued: true, operation: operation })
|
|
142
|
+
])
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
Omnitrack::Pipeline::Dispatcher.dispatch(operation, *args)
|
|
146
|
+
rescue StandardError => e
|
|
147
|
+
# Top-level safety net — never raise into the host application
|
|
148
|
+
logger.error("omnitrack.dispatch_error",
|
|
149
|
+
operation: operation, error: e.class.name, message: e.message)
|
|
150
|
+
Omnitrack::MultiResult.new([
|
|
151
|
+
Omnitrack::Result.failure(error: e)
|
|
152
|
+
])
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def build_logger
|
|
156
|
+
Omnitrack::Logger.new(
|
|
157
|
+
log_file: config.resolved_log_file,
|
|
158
|
+
log_level: config.log_level
|
|
159
|
+
)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def reset_logger!
|
|
163
|
+
@logger = nil
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: omnitrack-rb
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Your Name
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-04-26 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: activesupport
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '6.0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '6.0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: railties
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '6.0'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '6.0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: net-http
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ">="
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0'
|
|
48
|
+
type: :runtime
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ">="
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: bundler
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '2.0'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '2.0'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: rake
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - "~>"
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '13.0'
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - "~>"
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '13.0'
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: rspec
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - "~>"
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '3.12'
|
|
90
|
+
type: :development
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - "~>"
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: '3.12'
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: rails
|
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - ">="
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '6.0'
|
|
104
|
+
type: :development
|
|
105
|
+
prerelease: false
|
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - ">="
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: '6.0'
|
|
111
|
+
- !ruby/object:Gem::Dependency
|
|
112
|
+
name: webmock
|
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
|
114
|
+
requirements:
|
|
115
|
+
- - "~>"
|
|
116
|
+
- !ruby/object:Gem::Version
|
|
117
|
+
version: '3.0'
|
|
118
|
+
type: :development
|
|
119
|
+
prerelease: false
|
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
121
|
+
requirements:
|
|
122
|
+
- - "~>"
|
|
123
|
+
- !ruby/object:Gem::Version
|
|
124
|
+
version: '3.0'
|
|
125
|
+
- !ruby/object:Gem::Dependency
|
|
126
|
+
name: rubocop
|
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
|
128
|
+
requirements:
|
|
129
|
+
- - "~>"
|
|
130
|
+
- !ruby/object:Gem::Version
|
|
131
|
+
version: '1.50'
|
|
132
|
+
type: :development
|
|
133
|
+
prerelease: false
|
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
135
|
+
requirements:
|
|
136
|
+
- - "~>"
|
|
137
|
+
- !ruby/object:Gem::Version
|
|
138
|
+
version: '1.50'
|
|
139
|
+
description: |
|
|
140
|
+
OmniTrack is a production-grade tracking and conversion gem for Ruby on Rails.
|
|
141
|
+
It supports multiple ad/analytics platforms (Google Ads, GA4, Meta, TikTok, Snapchat)
|
|
142
|
+
via a clean adapter pattern, works in both full-stack and API-only Rails apps,
|
|
143
|
+
and provides structured logging, background job support, and an extensible pipeline.
|
|
144
|
+
email:
|
|
145
|
+
- you@example.com
|
|
146
|
+
executables: []
|
|
147
|
+
extensions: []
|
|
148
|
+
extra_rdoc_files: []
|
|
149
|
+
files:
|
|
150
|
+
- ".env.example"
|
|
151
|
+
- AI_GEM_SETUP.md
|
|
152
|
+
- CHANGELOG.md
|
|
153
|
+
- LICENSE.txt
|
|
154
|
+
- README.md
|
|
155
|
+
- USAGE.md
|
|
156
|
+
- lib/generators/omnitrack/install/install_generator.rb
|
|
157
|
+
- lib/generators/omnitrack/install/templates/README
|
|
158
|
+
- lib/generators/omnitrack/install/templates/env.example
|
|
159
|
+
- lib/generators/omnitrack/install/templates/initializer.rb
|
|
160
|
+
- lib/omnitrack.rb
|
|
161
|
+
- lib/omnitrack/adapters/base.rb
|
|
162
|
+
- lib/omnitrack/adapters/google_ads.rb
|
|
163
|
+
- lib/omnitrack/adapters/google_analytics.rb
|
|
164
|
+
- lib/omnitrack/adapters/meta.rb
|
|
165
|
+
- lib/omnitrack/adapters/snapchat.rb
|
|
166
|
+
- lib/omnitrack/adapters/tiktok.rb
|
|
167
|
+
- lib/omnitrack/concerns/controller.rb
|
|
168
|
+
- lib/omnitrack/configuration.rb
|
|
169
|
+
- lib/omnitrack/context.rb
|
|
170
|
+
- lib/omnitrack/errors.rb
|
|
171
|
+
- lib/omnitrack/helpers/view_helpers.rb
|
|
172
|
+
- lib/omnitrack/jobs/tracking_job.rb
|
|
173
|
+
- lib/omnitrack/logger.rb
|
|
174
|
+
- lib/omnitrack/middleware/request_tracker.rb
|
|
175
|
+
- lib/omnitrack/pipeline/dispatcher.rb
|
|
176
|
+
- lib/omnitrack/railtie.rb
|
|
177
|
+
- lib/omnitrack/registry.rb
|
|
178
|
+
- lib/omnitrack/result.rb
|
|
179
|
+
- lib/omnitrack/tasks/omnitrack.rake
|
|
180
|
+
- lib/omnitrack/version.rb
|
|
181
|
+
homepage: https://github.com/yourorg/omnitrack-rb
|
|
182
|
+
licenses:
|
|
183
|
+
- MIT
|
|
184
|
+
metadata:
|
|
185
|
+
homepage_uri: https://github.com/yourorg/omnitrack-rb
|
|
186
|
+
source_code_uri: https://github.com/yourorg/omnitrack-rb
|
|
187
|
+
changelog_uri: https://github.com/yourorg/omnitrack-rb/blob/main/CHANGELOG.md
|
|
188
|
+
post_install_message:
|
|
189
|
+
rdoc_options: []
|
|
190
|
+
require_paths:
|
|
191
|
+
- lib
|
|
192
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
193
|
+
requirements:
|
|
194
|
+
- - ">="
|
|
195
|
+
- !ruby/object:Gem::Version
|
|
196
|
+
version: 2.7.0
|
|
197
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
198
|
+
requirements:
|
|
199
|
+
- - ">="
|
|
200
|
+
- !ruby/object:Gem::Version
|
|
201
|
+
version: '0'
|
|
202
|
+
requirements: []
|
|
203
|
+
rubygems_version: 3.4.10
|
|
204
|
+
signing_key:
|
|
205
|
+
specification_version: 4
|
|
206
|
+
summary: Flexible, modular tracking and conversion system for Rails
|
|
207
|
+
test_files: []
|