kameleoon-client-ruby 3.1.1 → 3.2.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/lib/kameleoon/configuration/custom_data_info.rb +43 -0
- data/lib/kameleoon/configuration/data_file.rb +30 -2
- data/lib/kameleoon/configuration/rule.rb +4 -1
- data/lib/kameleoon/configuration/variation_exposition.rb +1 -1
- data/lib/kameleoon/data/browser.rb +19 -0
- data/lib/kameleoon/data/cookie.rb +14 -0
- data/lib/kameleoon/data/custom_data.rb +2 -0
- data/lib/kameleoon/data/data.rb +2 -0
- data/lib/kameleoon/data/geolocation.rb +45 -0
- data/lib/kameleoon/data/manager/assigned_variation.rb +2 -1
- data/lib/kameleoon/data/manager/page_view_visit.rb +16 -2
- data/lib/kameleoon/data/manager/visitor.rb +64 -14
- data/lib/kameleoon/data/manager/visitor_manager.rb +23 -1
- data/lib/kameleoon/data/operating_system.rb +72 -0
- data/lib/kameleoon/data/page_view.rb +2 -2
- data/lib/kameleoon/data/visitor_visits.rb +13 -0
- data/lib/kameleoon/kameleoon_client.rb +75 -94
- data/lib/kameleoon/managers/remote_data/remote_data_manager.rb +57 -0
- data/lib/kameleoon/managers/remote_data/remote_visitor_data.rb +162 -0
- data/lib/kameleoon/managers/warehouse/warehouse_manager.rb +3 -1
- data/lib/kameleoon/network/access_token_source.rb +22 -5
- data/lib/kameleoon/network/network_manager.rb +10 -10
- data/lib/kameleoon/network/response.rb +1 -1
- data/lib/kameleoon/network/url_provider.rb +15 -12
- data/lib/kameleoon/targeting/condition.rb +22 -2
- data/lib/kameleoon/targeting/condition_factory.rb +36 -6
- data/lib/kameleoon/targeting/conditions/cookie_condition.rb +55 -0
- data/lib/kameleoon/targeting/conditions/exclusive_feature_flag_condition.rb +27 -0
- data/lib/kameleoon/targeting/conditions/geolocation_condition.rb +33 -0
- data/lib/kameleoon/targeting/conditions/number_condition.rb +38 -0
- data/lib/kameleoon/targeting/conditions/operating_system_condition.rb +27 -0
- data/lib/kameleoon/targeting/conditions/page_view_number_condition.rb +28 -0
- data/lib/kameleoon/targeting/conditions/previous_page_condition.rb +35 -0
- data/lib/kameleoon/targeting/conditions/segment_condition.rb +42 -0
- data/lib/kameleoon/targeting/conditions/target_feature_flag_condition.rb +63 -0
- data/lib/kameleoon/targeting/conditions/time_elapsed_since_visit_condition.rb +30 -0
- data/lib/kameleoon/targeting/conditions/visit_number_today_condition.rb +28 -0
- data/lib/kameleoon/targeting/conditions/visit_number_total_condition.rb +21 -0
- data/lib/kameleoon/targeting/conditions/visitor_new_return_condition.rb +33 -0
- data/lib/kameleoon/targeting/targeting_manager.rb +66 -0
- data/lib/kameleoon/types/remote_visitor_data_filter.rb +24 -0
- data/lib/kameleoon/utils.rb +1 -0
- data/lib/kameleoon/version.rb +1 -1
- metadata +24 -4
- data/lib/kameleoon/targeting/conditions/exclusive_experiment.rb +0 -18
- data/lib/kameleoon/targeting/conditions/target_experiment.rb +0 -45
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b8dea61e52fdfa38f0fc3d2161711fe169940de6053d9d372fef06b30e70975f
|
4
|
+
data.tar.gz: 201acbdb7b3597d4637207c6f599c04dc9bbf0984de60fb93904569193152230
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d3ecf83261db7d1ed52d231c141521df16ea5f2d0e42240c80db684537dd5ab32f5047430446fe1779f40485357b37ea455416369d5dce0f748c76ed7b132103
|
7
|
+
data.tar.gz: f5e1641dd1311bac6620c6db63f396fbe7d46f96eecab69713eef49e9e81f67a24c5644f68b7fdff4dd99455a5c480be57ab26e7372947b02eefec3033d310fc
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kameleoon
|
4
|
+
# Module which contains all internal data of SDK
|
5
|
+
module Configuration
|
6
|
+
|
7
|
+
class CustomDataInfo
|
8
|
+
attr_reader :local_only, :visitor_scope, :mapping_identifier_index
|
9
|
+
SCOPE_VISITOR = 'VISITOR'
|
10
|
+
|
11
|
+
def initialize(hashes, log_func = nil)
|
12
|
+
@local_only = Set[]
|
13
|
+
@visitor_scope = Set[]
|
14
|
+
@log_func = log_func
|
15
|
+
unless hashes.nil?
|
16
|
+
for hash in hashes
|
17
|
+
index = hash['index']
|
18
|
+
@local_only.add(index) if hash['localOnly']
|
19
|
+
@visitor_scope.add(index) if hash['scope'] == SCOPE_VISITOR
|
20
|
+
if hash['isMappingIdentifier']
|
21
|
+
if @mapping_identifier_index != nil
|
22
|
+
@log_func&.call('More than one mapping identifier is set. Undefined behavior may occur on cross-device reconciliation.')
|
23
|
+
end
|
24
|
+
@mapping_identifier_index = index
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def local_only? (index)
|
31
|
+
@local_only.include?(index)
|
32
|
+
end
|
33
|
+
|
34
|
+
def mapping_identifier? (index)
|
35
|
+
index == @mapping_identifier_index
|
36
|
+
end
|
37
|
+
|
38
|
+
def visitor_scope? (index)
|
39
|
+
@visitor_scope.include?(index)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -1,16 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'kameleoon/configuration/settings'
|
4
|
+
require 'kameleoon/configuration/feature_flag'
|
5
|
+
require 'kameleoon/configuration/custom_data_info'
|
4
6
|
|
5
7
|
module Kameleoon
|
6
8
|
module Configuration
|
7
9
|
class DataFile
|
8
|
-
attr_reader :settings, :feature_flags, :has_any_targeted_delivery_rule
|
10
|
+
attr_reader :settings, :feature_flags, :has_any_targeted_delivery_rule, :feature_flag_by_id, :rule_by_segment_id, :variation_by_id, :custom_data_info
|
9
11
|
|
10
|
-
def initialize(environment)
|
12
|
+
def initialize(environment, log_func = nil)
|
11
13
|
@settings = Settings.new
|
12
14
|
@feature_flags = {}
|
13
15
|
@environment = environment
|
16
|
+
@log_func = log_func
|
17
|
+
collect_indices
|
18
|
+
@custom_data_info = Kameleoon::Configuration::CustomDataInfo.new(nil, @log_func)
|
14
19
|
end
|
15
20
|
|
16
21
|
def init(configuration)
|
@@ -20,6 +25,8 @@ module Kameleoon
|
|
20
25
|
@feature_flags[ff.feature_key] = ff
|
21
26
|
end
|
22
27
|
@has_any_targeted_delivery_rule = any_targeted_delivery_rule?
|
28
|
+
collect_indices
|
29
|
+
@custom_data_info = CustomDataInfo.new(configuration['customData'], @log_func)
|
23
30
|
self
|
24
31
|
end
|
25
32
|
|
@@ -36,6 +43,27 @@ module Kameleoon
|
|
36
43
|
def any_targeted_delivery_rule?
|
37
44
|
@feature_flags.any? { |_, ff| ff.environment_enabled && ff.rules.any?(&:targeted_delivery_type?) }
|
38
45
|
end
|
46
|
+
|
47
|
+
def collect_indices
|
48
|
+
@feature_flag_by_id = {}
|
49
|
+
@rule_by_segment_id = {}
|
50
|
+
@variation_by_id = {}
|
51
|
+
|
52
|
+
@feature_flags.each_value do |feature_flag|
|
53
|
+
next if feature_flag.rules.nil?
|
54
|
+
|
55
|
+
feature_flag.rules.each do |rule|
|
56
|
+
@feature_flag_by_id[feature_flag.id] = feature_flag
|
57
|
+
@rule_by_segment_id[rule.segment_id] = rule
|
58
|
+
rule.variation_by_exposition.each do |variation|
|
59
|
+
@variation_by_id[variation.variation_id] = variation
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
@feature_flag_by_id.freeze
|
64
|
+
@rule_by_segment_id.freeze
|
65
|
+
@variation_by_id.freeze
|
66
|
+
end
|
39
67
|
end
|
40
68
|
end
|
41
69
|
end
|
@@ -29,7 +29,7 @@ module Kameleoon
|
|
29
29
|
|
30
30
|
# Rule is a class for new rules of feature flags
|
31
31
|
class Rule
|
32
|
-
attr_reader :id, :order, :type, :exposition, :experiment_id, :variation_by_exposition, :respool_time
|
32
|
+
attr_reader :id, :order, :type, :exposition, :experiment_id, :variation_by_exposition, :respool_time, :segment_id, :first_variation
|
33
33
|
attr_accessor :targeting_segment
|
34
34
|
|
35
35
|
def self.create_from_array(array)
|
@@ -44,7 +44,10 @@ module Kameleoon
|
|
44
44
|
@experiment_id = hash['experimentId']
|
45
45
|
@respool_time = hash['respoolTime']
|
46
46
|
@variation_by_exposition = VariationByExposition.create_from_array(hash['variationByExposition'])
|
47
|
+
@variation_by_exposition.freeze
|
48
|
+
@first_variation = @variation_by_exposition.first
|
47
49
|
@targeting_segment = Kameleoon::Targeting::Segment.new((hash['segment'])) if hash['segment']
|
50
|
+
@segment_id = @targeting_segment != nil ? targeting_segment.id : -1
|
48
51
|
end
|
49
52
|
|
50
53
|
def get_variation(hash_double)
|
@@ -5,7 +5,7 @@ module Kameleoon
|
|
5
5
|
module Configuration
|
6
6
|
# VariationByExposition represents a variation with exposition rate for rule
|
7
7
|
class VariationByExposition
|
8
|
-
|
8
|
+
attr_reader :variation_key, :variation_id, :exposition
|
9
9
|
|
10
10
|
def self.create_from_array(array)
|
11
11
|
array&.map { |it| VariationByExposition.new(it) }
|
@@ -12,6 +12,25 @@ module Kameleoon
|
|
12
12
|
SAFARI = 3
|
13
13
|
OPERA = 4
|
14
14
|
OTHER = 5
|
15
|
+
|
16
|
+
def self.from_name(name)
|
17
|
+
case name
|
18
|
+
when 'CHROME'
|
19
|
+
BrowserType::CHROME
|
20
|
+
when 'INTERNET_EXPLORER'
|
21
|
+
BrowserType::INTERNET_EXPLORER
|
22
|
+
when 'FIREFOX'
|
23
|
+
BrowserType::FIREFOX
|
24
|
+
when 'SAFARI'
|
25
|
+
BrowserType::SAFARI
|
26
|
+
when 'OPERA'
|
27
|
+
BrowserType::OPERA
|
28
|
+
when 'OTHER'
|
29
|
+
BrowserType::OTHER
|
30
|
+
else
|
31
|
+
nil
|
32
|
+
end
|
33
|
+
end
|
15
34
|
end
|
16
35
|
|
17
36
|
# Represents browser data for tracking calls
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kameleoon
|
4
|
+
# Cookie contains information about the cookie stored on the visitor's device
|
5
|
+
class Cookie
|
6
|
+
attr_reader :cookies
|
7
|
+
|
8
|
+
# @param [Hash] cookies
|
9
|
+
def initialize(cookies)
|
10
|
+
@cookies = cookies
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
@@ -8,6 +8,7 @@ module Kameleoon
|
|
8
8
|
# Represents any custom data for targeting conditions
|
9
9
|
class CustomData < DuplicationUnsafeData
|
10
10
|
attr_reader :id, :values
|
11
|
+
attr_accessor :is_mapping_identifier
|
11
12
|
|
12
13
|
# @param [Integer] id Id of the custom data
|
13
14
|
# @param [String] value Value of the custom data
|
@@ -50,6 +51,7 @@ module Kameleoon
|
|
50
51
|
overwrite: 'true',
|
51
52
|
nonce: nonce
|
52
53
|
}
|
54
|
+
params[:mappingIdentifier] = is_mapping_identifier if is_mapping_identifier
|
53
55
|
Kameleoon::Network::UriHelper.encode_query(params)
|
54
56
|
end
|
55
57
|
end
|
data/lib/kameleoon/data/data.rb
CHANGED
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kameleoon
|
4
|
+
# Geolocation contains the visitor's geolocation details
|
5
|
+
class Geolocation < DuplicationUnsafeData
|
6
|
+
attr_reader :country, :region, :city, :postal_code, :latitude, :longitude
|
7
|
+
|
8
|
+
# @param [String] country Country of visitor's geolocation. Required
|
9
|
+
# @param [String] region Region of visitor's geolocation. Optional
|
10
|
+
# @param [String] city City of visitor's geolocation. Optional
|
11
|
+
# @param [String] postal_code Postal code of visitor's geolocation. Optional
|
12
|
+
# @param [Float] latitude Latitude of visitor's geolocation. Optional
|
13
|
+
# @param [Float] longitude Longitude of visitor's geolocation. Optional
|
14
|
+
def initialize(country, region = nil, city = nil, postal_code = nil, latitude = Float::NAN, longitude = Float::NAN)
|
15
|
+
super(DataType::GEOLOCATION)
|
16
|
+
@country = country
|
17
|
+
@region = region
|
18
|
+
@city = city
|
19
|
+
@postal_code = postal_code
|
20
|
+
@latitude = latitude
|
21
|
+
@longitude = longitude
|
22
|
+
end
|
23
|
+
|
24
|
+
def obtain_full_post_text_line
|
25
|
+
params = {
|
26
|
+
eventType: 'staticData',
|
27
|
+
nonce: nonce
|
28
|
+
}
|
29
|
+
params[:country] = @country if @country.is_a?(String)
|
30
|
+
params[:region] = @region if @region.is_a?(String)
|
31
|
+
params[:city] = @city if @city.is_a?(String)
|
32
|
+
params[:postalCode] = @postal_code if @postal_code.is_a?(String)
|
33
|
+
params[:latitude] = @latitude if valid_number?(@latitude)
|
34
|
+
params[:longitude] = @longitude if valid_number?(@longitude)
|
35
|
+
Kameleoon::Network::UriHelper.encode_query(params)
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def valid_number?(value)
|
41
|
+
value.is_a?(Integer) || (value.is_a?(Float) && !value.nan?)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'kameleoon/data/data'
|
4
4
|
require 'kameleoon/network/uri_helper'
|
5
|
+
require 'kameleoon/configuration/rule'
|
5
6
|
|
6
7
|
module Kameleoon
|
7
8
|
module DataManager
|
@@ -12,7 +13,7 @@ module Kameleoon
|
|
12
13
|
|
13
14
|
attr_reader :experiment_id, :variation_id, :rule_type, :assignment_time
|
14
15
|
|
15
|
-
def initialize(experiment_id, variation_id, rule_type, assignment_time: nil)
|
16
|
+
def initialize(experiment_id, variation_id, rule_type = Kameleoon::Configuration::RuleType::UNKNOWN, assignment_time: nil)
|
16
17
|
super(DataType::ASSIGNED_VARIATION)
|
17
18
|
@experiment_id = experiment_id
|
18
19
|
@variation_id = variation_id
|
@@ -3,17 +3,31 @@
|
|
3
3
|
module Kameleoon
|
4
4
|
module DataManager
|
5
5
|
class PageViewVisit
|
6
|
-
attr_reader :page_view, :count
|
6
|
+
attr_reader :page_view, :count, :last_timestamp
|
7
7
|
|
8
|
-
def initialize(page_view, count = 1)
|
8
|
+
def initialize(page_view, count = 1, timestamp = nil)
|
9
9
|
@page_view = page_view
|
10
10
|
@count = count
|
11
|
+
@last_timestamp = timestamp != nil ? timestamp : Time.new.to_i
|
11
12
|
end
|
12
13
|
|
14
|
+
# Not thread-save method, should be called in synchronized code
|
15
|
+
# We need to return a new PageViewVisit for case if PageView was already sent and it's new visit
|
13
16
|
def overwrite(page_view)
|
14
17
|
@page_view = page_view
|
15
18
|
@count += 1
|
16
19
|
end
|
20
|
+
|
21
|
+
# Not thread-save method, should be called in synchronized code
|
22
|
+
def merge (page_view_visit)
|
23
|
+
@count += page_view_visit.count
|
24
|
+
@last_timestamp = [@last_timestamp, page_view_visit.last_timestamp].max
|
25
|
+
end
|
26
|
+
|
27
|
+
# Not thread-save method, should be called in synchronized code
|
28
|
+
def increase_page_visits
|
29
|
+
@count += 1
|
30
|
+
end
|
17
31
|
end
|
18
32
|
end
|
19
33
|
end
|
@@ -18,8 +18,8 @@ module Kameleoon
|
|
18
18
|
# Visitor is a container of all data assigned to a visitor.
|
19
19
|
# It is thread-safe
|
20
20
|
class Visitor
|
21
|
-
attr_reader :last_activity_time, :user_agent, :device, :browser
|
22
|
-
attr_accessor :legal_consent
|
21
|
+
attr_reader :last_activity_time, :user_agent, :device, :browser, :geolocation, :operating_system, :cookie, :visitor_visits
|
22
|
+
attr_accessor :legal_consent, :mapping_identifier
|
23
23
|
|
24
24
|
def initialize
|
25
25
|
@mutex = Concurrent::ReadWriteLock.new
|
@@ -34,6 +34,8 @@ module Kameleoon
|
|
34
34
|
def enumerate_sendable_data(&blk)
|
35
35
|
blk.call(@device) unless @device.nil?
|
36
36
|
blk.call(@browser) unless @browser.nil?
|
37
|
+
blk.call(@operating_system) unless @operating_system.nil?
|
38
|
+
blk.call(@geolocation) unless @geolocation.nil?
|
37
39
|
@mutex.with_read_lock do
|
38
40
|
@custom_data_map&.each { |_, cd| blk.call(cd) }
|
39
41
|
@page_view_visits&.each { |_, pvv| blk.call(pvv.page_view) }
|
@@ -47,6 +49,8 @@ module Kameleoon
|
|
47
49
|
@mutex.with_read_lock do
|
48
50
|
count += 1 unless @device.nil?
|
49
51
|
count += 1 unless @browser.nil?
|
52
|
+
count += 1 unless @geolocation.nil?
|
53
|
+
count += 1 unless @operating_system.nil?
|
50
54
|
count += @custom_data_map.size unless @custom_data_map.nil?
|
51
55
|
count += @page_view_visits.size unless @page_view_visits.nil?
|
52
56
|
count += @conversions.size unless @conversions.nil?
|
@@ -71,22 +75,34 @@ module Kameleoon
|
|
71
75
|
DataMapStorage.new(@mutex, @variations)
|
72
76
|
end
|
73
77
|
|
74
|
-
def add_data(log_func, *args)
|
78
|
+
def add_data(log_func, *args, overwrite: true)
|
75
79
|
@mutex.with_write_lock do
|
76
80
|
args.each do |data|
|
77
81
|
case data
|
78
82
|
when Kameleoon::UserAgent
|
79
|
-
|
83
|
+
set_user_agent(data)
|
84
|
+
when Kameleoon::DataManager::AssignedVariation
|
85
|
+
add_variation(data, overwrite)
|
80
86
|
when Kameleoon::Device
|
81
|
-
|
87
|
+
set_device(data, overwrite)
|
82
88
|
when Kameleoon::Browser
|
83
|
-
|
89
|
+
set_browser(data, overwrite)
|
84
90
|
when Kameleoon::CustomData
|
85
|
-
add_custom_data(data)
|
91
|
+
add_custom_data(data, overwrite)
|
86
92
|
when Kameleoon::PageView
|
87
93
|
add_page_view(data)
|
94
|
+
when Kameleoon::DataManager::PageViewVisit
|
95
|
+
add_page_view_visit(data)
|
88
96
|
when Kameleoon::Conversion
|
89
97
|
add_conversion(data)
|
98
|
+
when Kameleoon::Cookie
|
99
|
+
set_cookie(data)
|
100
|
+
when Kameleoon::OperatingSystem
|
101
|
+
set_operating_system(data, overwrite)
|
102
|
+
when Kameleoon::Geolocation
|
103
|
+
set_geolocation(data, overwrite)
|
104
|
+
when Kameleoon::VisitorVisits
|
105
|
+
set_visitor_visits(data)
|
90
106
|
else
|
91
107
|
log_func&.call("Data has unsupported type '#{data.class}'")
|
92
108
|
end
|
@@ -103,21 +119,28 @@ module Kameleoon
|
|
103
119
|
|
104
120
|
private
|
105
121
|
|
106
|
-
def
|
122
|
+
def set_user_agent(user_agent)
|
107
123
|
@user_agent = user_agent.value
|
108
124
|
end
|
109
125
|
|
110
|
-
def
|
111
|
-
@device = device
|
126
|
+
def set_device(device, overwrite)
|
127
|
+
@device = device if overwrite || @device == nil
|
112
128
|
end
|
113
129
|
|
114
|
-
def
|
115
|
-
@
|
130
|
+
def add_variation(variation, overwrite)
|
131
|
+
@variations = {} if @variations == nil
|
132
|
+
if overwrite || !@variations.include?(variation.experiment_id)
|
133
|
+
@variations[variation.experiment_id] = variation
|
134
|
+
end
|
116
135
|
end
|
117
136
|
|
118
|
-
def
|
137
|
+
def set_browser(browser, overwrite)
|
138
|
+
@browser = browser if overwrite || @browser == nil
|
139
|
+
end
|
140
|
+
|
141
|
+
def add_custom_data(custom_data, overwrite)
|
119
142
|
@custom_data_map = {} if @custom_data_map.nil?
|
120
|
-
@custom_data_map[custom_data.id] = custom_data
|
143
|
+
@custom_data_map[custom_data.id] = custom_data if overwrite || !@custom_data_map.include?(custom_data.id)
|
121
144
|
end
|
122
145
|
|
123
146
|
def add_page_view(page_view)
|
@@ -133,10 +156,37 @@ module Kameleoon
|
|
133
156
|
@page_view_visits[page_view.url] = visit
|
134
157
|
end
|
135
158
|
|
159
|
+
def add_page_view_visit(page_view_visit)
|
160
|
+
@page_view_visits = {} if @page_view_visits.nil?
|
161
|
+
visit = @page_view_visits[page_view_visit.page_view.url]
|
162
|
+
if visit.nil?
|
163
|
+
visit = page_view_visit
|
164
|
+
@page_view_visits[page_view_visit.page_view.url] = visit
|
165
|
+
else
|
166
|
+
visit.merge(page_view_visit)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
136
170
|
def add_conversion(conversion)
|
137
171
|
@conversions = [] if @conversions.nil?
|
138
172
|
@conversions.push(conversion)
|
139
173
|
end
|
174
|
+
|
175
|
+
def set_geolocation(geolocation, overwrite)
|
176
|
+
@geolocation = geolocation if overwrite || @geolocation == nil
|
177
|
+
end
|
178
|
+
|
179
|
+
def set_cookie(cookie)
|
180
|
+
@cookie = cookie
|
181
|
+
end
|
182
|
+
|
183
|
+
def set_operating_system(operating_system, overwrite)
|
184
|
+
@operating_system = operating_system if overwrite || @operating_system == nil
|
185
|
+
end
|
186
|
+
|
187
|
+
def set_visitor_visits(visitor_visits)
|
188
|
+
@visitor_visits = visitor_visits
|
189
|
+
end
|
140
190
|
end
|
141
191
|
end
|
142
192
|
end
|
@@ -11,10 +11,12 @@ module Kameleoon
|
|
11
11
|
# It is thread-safe except `stop` method
|
12
12
|
class VisitorManager
|
13
13
|
attr_reader :expiration_period
|
14
|
+
attr_accessor :custom_data_info
|
14
15
|
|
15
|
-
def initialize(expiration_period)
|
16
|
+
def initialize(expiration_period, log_func = nil)
|
16
17
|
@expiration_period = expiration_period
|
17
18
|
@visitors = Concurrent::Map.new
|
19
|
+
@log_func = log_func
|
18
20
|
start
|
19
21
|
end
|
20
22
|
|
@@ -49,6 +51,26 @@ module Kameleoon
|
|
49
51
|
@visitors.size
|
50
52
|
end
|
51
53
|
|
54
|
+
def add_data(visitor_code, *args)
|
55
|
+
visitor = get_or_create_visitor(visitor_code)
|
56
|
+
for custom_data in args
|
57
|
+
next unless custom_data.is_a?(Kameleoon::CustomData)
|
58
|
+
# We shouldn't send custom data with local only type
|
59
|
+
custom_data.mark_as_sent if @custom_data_info.local_only?(custom_data.id)
|
60
|
+
# If mappingIdentifier is passed, we should link anonymous visitor with real unique userId.
|
61
|
+
# After authorization, customer must be able to continue work with userId, but hash for variation
|
62
|
+
# should be calculated based on anonymous visitor code, that's why set MappingIdentifier to visitor.
|
63
|
+
if @custom_data_info.mapping_identifier?(custom_data.id) && custom_data.values.size > 0 && custom_data.values[0].size > 0
|
64
|
+
custom_data.is_mapping_identifier = true
|
65
|
+
visitor.mapping_identifier = visitor_code
|
66
|
+
target_visitor_code = custom_data.values[0]
|
67
|
+
@visitors[target_visitor_code] = visitor if visitor_code != target_visitor_code
|
68
|
+
end
|
69
|
+
end
|
70
|
+
visitor.add_data(@log_func, *args)
|
71
|
+
visitor
|
72
|
+
end
|
73
|
+
|
52
74
|
private
|
53
75
|
|
54
76
|
def purge
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kameleoon
|
4
|
+
module OperatingSystemType
|
5
|
+
WINDOWS = 0
|
6
|
+
MAC = 1
|
7
|
+
IOS = 2
|
8
|
+
LINUX = 3
|
9
|
+
ANDROID = 4
|
10
|
+
WINDOWS_PHONE = 5
|
11
|
+
|
12
|
+
def self.from_name(name)
|
13
|
+
case name
|
14
|
+
when 'WINDOWS'
|
15
|
+
WINDOWS
|
16
|
+
when 'MAC'
|
17
|
+
MAC
|
18
|
+
when 'IOS'
|
19
|
+
IOS
|
20
|
+
when 'LINUX'
|
21
|
+
LINUX
|
22
|
+
when 'ANDROID'
|
23
|
+
ANDROID
|
24
|
+
when 'WINDOWS_PHONE'
|
25
|
+
WINDOWS_PHONE
|
26
|
+
else
|
27
|
+
nil
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.name_from_type(operating_system_type)
|
32
|
+
case operating_system_type
|
33
|
+
when OperatingSystemType::WINDOWS
|
34
|
+
'WINDOWS'
|
35
|
+
when OperatingSystemType::MAC
|
36
|
+
'MAC'
|
37
|
+
when OperatingSystemType::IOS
|
38
|
+
'IOS'
|
39
|
+
when OperatingSystemType::LINUX
|
40
|
+
'LINUX'
|
41
|
+
when OperatingSystemType::ANDROID
|
42
|
+
'ANDROID'
|
43
|
+
when OperatingSystemType::WINDOWS_PHONE
|
44
|
+
'WINDOWS_PHONE'
|
45
|
+
else
|
46
|
+
nil
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# OperatingSystem contains information about the operating system on the visitor's device
|
52
|
+
class OperatingSystem < DuplicationUnsafeData
|
53
|
+
attr_reader :os_type
|
54
|
+
|
55
|
+
# @param [OperatingSystemType] os_type Operating system type, can be: WINDOWS, MAC, IOS, LINUX, ANDROID, WINDOWS_PHONE
|
56
|
+
def initialize(os_type)
|
57
|
+
super(DataType::OPERATING_SYSTEM)
|
58
|
+
@os_type = os_type
|
59
|
+
end
|
60
|
+
|
61
|
+
def obtain_full_post_text_line
|
62
|
+
params = {
|
63
|
+
eventType: 'staticData',
|
64
|
+
os: OperatingSystemType.name_from_type(@os_type),
|
65
|
+
osIndex: @os_type,
|
66
|
+
nonce: nonce
|
67
|
+
}
|
68
|
+
Kameleoon::Network::UriHelper.encode_query(params)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
@@ -10,9 +10,9 @@ module Kameleoon
|
|
10
10
|
attr_reader :url, :title, :referrer
|
11
11
|
|
12
12
|
# @param [String] url Url of the page
|
13
|
-
# @param [String] title
|
13
|
+
# @param [String] title Optional field - title of the page
|
14
14
|
# @param [Array] referrers Optional field - Referrer ids
|
15
|
-
def initialize(url, title, referrers = nil)
|
15
|
+
def initialize(url, title = nil, referrers = nil)
|
16
16
|
super(DataType::PAGE_VIEW)
|
17
17
|
@url = url || ''
|
18
18
|
print('Kameleoon SDK: Url for PageView is required parameter, the data will be ignored.') if url == ''
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kameleoon
|
4
|
+
class VisitorVisits
|
5
|
+
attr_reader :previous_visit_timestamps
|
6
|
+
|
7
|
+
def initialize(previous_visit_timestamps = [])
|
8
|
+
@previous_visit_timestamps = previous_visit_timestamps
|
9
|
+
@previous_visit_timestamps.freeze
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|