kameleoon-client-ruby 3.1.1 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/lib/kameleoon/configuration/custom_data_info.rb +43 -0
  3. data/lib/kameleoon/configuration/data_file.rb +31 -2
  4. data/lib/kameleoon/configuration/rule.rb +4 -1
  5. data/lib/kameleoon/configuration/variation_exposition.rb +1 -1
  6. data/lib/kameleoon/data/browser.rb +19 -0
  7. data/lib/kameleoon/data/cookie.rb +14 -0
  8. data/lib/kameleoon/data/custom_data.rb +2 -0
  9. data/lib/kameleoon/data/data.rb +2 -0
  10. data/lib/kameleoon/data/geolocation.rb +45 -0
  11. data/lib/kameleoon/data/kcs_heat.rb +12 -0
  12. data/lib/kameleoon/data/manager/assigned_variation.rb +2 -1
  13. data/lib/kameleoon/data/manager/page_view_visit.rb +16 -2
  14. data/lib/kameleoon/data/manager/visitor.rb +71 -14
  15. data/lib/kameleoon/data/manager/visitor_manager.rb +23 -1
  16. data/lib/kameleoon/data/operating_system.rb +72 -0
  17. data/lib/kameleoon/data/page_view.rb +2 -2
  18. data/lib/kameleoon/data/visitor_visits.rb +20 -0
  19. data/lib/kameleoon/kameleoon_client.rb +122 -94
  20. data/lib/kameleoon/managers/remote_data/remote_data_manager.rb +55 -0
  21. data/lib/kameleoon/managers/remote_data/remote_visitor_data.rb +188 -0
  22. data/lib/kameleoon/managers/warehouse/warehouse_manager.rb +3 -1
  23. data/lib/kameleoon/network/access_token_source.rb +22 -5
  24. data/lib/kameleoon/network/network_manager.rb +10 -10
  25. data/lib/kameleoon/network/response.rb +1 -1
  26. data/lib/kameleoon/network/url_provider.rb +16 -12
  27. data/lib/kameleoon/targeting/condition.rb +24 -2
  28. data/lib/kameleoon/targeting/condition_factory.rb +39 -6
  29. data/lib/kameleoon/targeting/conditions/cookie_condition.rb +55 -0
  30. data/lib/kameleoon/targeting/conditions/exclusive_feature_flag_condition.rb +27 -0
  31. data/lib/kameleoon/targeting/conditions/geolocation_condition.rb +33 -0
  32. data/lib/kameleoon/targeting/conditions/kcs_heat_range_condition.rb +37 -0
  33. data/lib/kameleoon/targeting/conditions/number_condition.rb +38 -0
  34. data/lib/kameleoon/targeting/conditions/operating_system_condition.rb +27 -0
  35. data/lib/kameleoon/targeting/conditions/page_view_number_condition.rb +28 -0
  36. data/lib/kameleoon/targeting/conditions/previous_page_condition.rb +35 -0
  37. data/lib/kameleoon/targeting/conditions/segment_condition.rb +42 -0
  38. data/lib/kameleoon/targeting/conditions/target_feature_flag_condition.rb +59 -0
  39. data/lib/kameleoon/targeting/conditions/time_elapsed_since_visit_condition.rb +29 -0
  40. data/lib/kameleoon/targeting/conditions/visit_number_today_condition.rb +28 -0
  41. data/lib/kameleoon/targeting/conditions/visit_number_total_condition.rb +23 -0
  42. data/lib/kameleoon/targeting/conditions/visitor_new_return_condition.rb +34 -0
  43. data/lib/kameleoon/targeting/targeting_manager.rb +68 -0
  44. data/lib/kameleoon/types/remote_visitor_data_filter.rb +29 -0
  45. data/lib/kameleoon/types/variable.rb +17 -0
  46. data/lib/kameleoon/types/variation.rb +18 -0
  47. data/lib/kameleoon/utils.rb +1 -0
  48. data/lib/kameleoon/version.rb +1 -1
  49. metadata +28 -4
  50. data/lib/kameleoon/targeting/conditions/exclusive_experiment.rb +0 -18
  51. 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: 3a2ae21c547d82441a35f311ca195d4d0b15be760535eb2d2cd33763cdaa5d3f
4
- data.tar.gz: ae9e41be3beda39be11c259d115d0543179e5b4a0549aa73b05c253d99cbd950
3
+ metadata.gz: '019ae7a1fe145f50f68beea1eb05bcae993d4061a2b1bdb2fe4324fc4215aa39'
4
+ data.tar.gz: fe9637047ba81b006c1b19a4c85e82fa5641a4d3f666fe14cb28ee243076b6ac
5
5
  SHA512:
6
- metadata.gz: 8e99dc556e6f39202765a6ac8da2f0c0ccf3d6f7ebccee7996f9741d5608eb485d6802b1920aaa78f881b0f66d05c63d89102df75ed20853aae562fc87787cf5
7
- data.tar.gz: 161950ca9c72591a7ffa59e82d231c01b478d504449557852b79570b97cb94cacf686033343275915653cc9f66cb9395563a542dc6955ed9b93354d4fa43c525
6
+ metadata.gz: 5455718dd4a68c584c280e4004ff1c96e28b35d7bfcd9bd8299c68b9d0f3930bd064e16057ce71bbfc386911f106839f54a6398165e6966cad5ce5a4388ccbe9
7
+ data.tar.gz: 7a2e231a4625c642a56354615999543c26d7e882d8fc7a2c743f7f4f045d01bc88d5dafd227757fd88f308053610f22f21bfa6cbadd79eafe2b7f2bc3a5e03b7
@@ -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,22 @@
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,
11
+ :variation_by_id, :custom_data_info
9
12
 
10
- def initialize(environment)
13
+ def initialize(environment, log_func = nil)
11
14
  @settings = Settings.new
12
15
  @feature_flags = {}
13
16
  @environment = environment
17
+ @log_func = log_func
18
+ collect_indices
19
+ @custom_data_info = Kameleoon::Configuration::CustomDataInfo.new(nil, @log_func)
14
20
  end
15
21
 
16
22
  def init(configuration)
@@ -20,6 +26,8 @@ module Kameleoon
20
26
  @feature_flags[ff.feature_key] = ff
21
27
  end
22
28
  @has_any_targeted_delivery_rule = any_targeted_delivery_rule?
29
+ collect_indices
30
+ @custom_data_info = CustomDataInfo.new(configuration['customData'], @log_func)
23
31
  self
24
32
  end
25
33
 
@@ -36,6 +44,27 @@ module Kameleoon
36
44
  def any_targeted_delivery_rule?
37
45
  @feature_flags.any? { |_, ff| ff.environment_enabled && ff.rules.any?(&:targeted_delivery_type?) }
38
46
  end
47
+
48
+ def collect_indices
49
+ @feature_flag_by_id = {}
50
+ @rule_by_segment_id = {}
51
+ @variation_by_id = {}
52
+
53
+ @feature_flags.each_value do |feature_flag|
54
+ @feature_flag_by_id[feature_flag.id] = feature_flag
55
+ next if feature_flag.rules.nil?
56
+
57
+ feature_flag.rules.each do |rule|
58
+ @rule_by_segment_id[rule.segment_id] = rule
59
+ rule.variation_by_exposition.each do |variation|
60
+ @variation_by_id[variation.variation_id] = variation
61
+ end
62
+ end
63
+ end
64
+ @feature_flag_by_id.freeze
65
+ @rule_by_segment_id.freeze
66
+ @variation_by_id.freeze
67
+ end
39
68
  end
40
69
  end
41
70
  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
- attr_accessor :variation_key, :variation_id, :exposition
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
@@ -14,6 +14,8 @@ module Kameleoon
14
14
  DEVICE = 'DEVICE'
15
15
  PAGE_VIEW = 'PAGE_VIEW'
16
16
  ASSIGNED_VARIATION = 'ASSIGNED_VARIATION'
17
+ OPERATING_SYSTEM = 'OPERATING_SYSTEM'
18
+ GEOLOCATION = 'GEOLOCATION'
17
19
  end
18
20
 
19
21
  # Represents base class for any Kameleoon data
@@ -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
+
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kameleoon
4
+ class KcsHeat
5
+ attr_reader :values
6
+
7
+ def initialize(values)
8
+ @values = values
9
+ @values.freeze
10
+ end
11
+ end
12
+ end
@@ -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,9 @@ 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,
22
+ :kcs_heat, :visitor_visits
23
+ attr_accessor :legal_consent, :mapping_identifier
23
24
 
24
25
  def initialize
25
26
  @mutex = Concurrent::ReadWriteLock.new
@@ -34,6 +35,8 @@ module Kameleoon
34
35
  def enumerate_sendable_data(&blk)
35
36
  blk.call(@device) unless @device.nil?
36
37
  blk.call(@browser) unless @browser.nil?
38
+ blk.call(@operating_system) unless @operating_system.nil?
39
+ blk.call(@geolocation) unless @geolocation.nil?
37
40
  @mutex.with_read_lock do
38
41
  @custom_data_map&.each { |_, cd| blk.call(cd) }
39
42
  @page_view_visits&.each { |_, pvv| blk.call(pvv.page_view) }
@@ -47,6 +50,8 @@ module Kameleoon
47
50
  @mutex.with_read_lock do
48
51
  count += 1 unless @device.nil?
49
52
  count += 1 unless @browser.nil?
53
+ count += 1 unless @geolocation.nil?
54
+ count += 1 unless @operating_system.nil?
50
55
  count += @custom_data_map.size unless @custom_data_map.nil?
51
56
  count += @page_view_visits.size unless @page_view_visits.nil?
52
57
  count += @conversions.size unless @conversions.nil?
@@ -71,22 +76,36 @@ module Kameleoon
71
76
  DataMapStorage.new(@mutex, @variations)
72
77
  end
73
78
 
74
- def add_data(log_func, *args)
79
+ def add_data(log_func, *args, overwrite: true)
75
80
  @mutex.with_write_lock do
76
81
  args.each do |data|
77
82
  case data
78
83
  when Kameleoon::UserAgent
79
- add_user_agent(data)
84
+ set_user_agent(data)
85
+ when Kameleoon::DataManager::AssignedVariation
86
+ add_variation(data, overwrite)
80
87
  when Kameleoon::Device
81
- add_device(data)
88
+ set_device(data, overwrite)
82
89
  when Kameleoon::Browser
83
- add_browser(data)
90
+ set_browser(data, overwrite)
84
91
  when Kameleoon::CustomData
85
- add_custom_data(data)
92
+ add_custom_data(data, overwrite)
86
93
  when Kameleoon::PageView
87
94
  add_page_view(data)
95
+ when Kameleoon::DataManager::PageViewVisit
96
+ add_page_view_visit(data)
88
97
  when Kameleoon::Conversion
89
98
  add_conversion(data)
99
+ when Kameleoon::Cookie
100
+ set_cookie(data)
101
+ when Kameleoon::OperatingSystem
102
+ set_operating_system(data, overwrite)
103
+ when Kameleoon::Geolocation
104
+ set_geolocation(data, overwrite)
105
+ when Kameleoon::KcsHeat
106
+ set_kcs_heat(data)
107
+ when Kameleoon::VisitorVisits
108
+ set_visitor_visits(data)
90
109
  else
91
110
  log_func&.call("Data has unsupported type '#{data.class}'")
92
111
  end
@@ -103,21 +122,28 @@ module Kameleoon
103
122
 
104
123
  private
105
124
 
106
- def add_user_agent(user_agent)
125
+ def set_user_agent(user_agent)
107
126
  @user_agent = user_agent.value
108
127
  end
109
128
 
110
- def add_device(device)
111
- @device = device
129
+ def set_device(device, overwrite)
130
+ @device = device if overwrite || @device == nil
112
131
  end
113
132
 
114
- def add_browser(browser)
115
- @browser = browser
133
+ def add_variation(variation, overwrite)
134
+ @variations = {} if @variations == nil
135
+ if overwrite || !@variations.include?(variation.experiment_id)
136
+ @variations[variation.experiment_id] = variation
137
+ end
116
138
  end
117
139
 
118
- def add_custom_data(custom_data)
140
+ def set_browser(browser, overwrite)
141
+ @browser = browser if overwrite || @browser == nil
142
+ end
143
+
144
+ def add_custom_data(custom_data, overwrite)
119
145
  @custom_data_map = {} if @custom_data_map.nil?
120
- @custom_data_map[custom_data.id] = custom_data
146
+ @custom_data_map[custom_data.id] = custom_data if overwrite || !@custom_data_map.include?(custom_data.id)
121
147
  end
122
148
 
123
149
  def add_page_view(page_view)
@@ -133,10 +159,41 @@ module Kameleoon
133
159
  @page_view_visits[page_view.url] = visit
134
160
  end
135
161
 
162
+ def add_page_view_visit(page_view_visit)
163
+ @page_view_visits = {} if @page_view_visits.nil?
164
+ visit = @page_view_visits[page_view_visit.page_view.url]
165
+ if visit.nil?
166
+ visit = page_view_visit
167
+ @page_view_visits[page_view_visit.page_view.url] = visit
168
+ else
169
+ visit.merge(page_view_visit)
170
+ end
171
+ end
172
+
136
173
  def add_conversion(conversion)
137
174
  @conversions = [] if @conversions.nil?
138
175
  @conversions.push(conversion)
139
176
  end
177
+
178
+ def set_geolocation(geolocation, overwrite)
179
+ @geolocation = geolocation if overwrite || @geolocation == nil
180
+ end
181
+
182
+ def set_cookie(cookie)
183
+ @cookie = cookie
184
+ end
185
+
186
+ def set_operating_system(operating_system, overwrite)
187
+ @operating_system = operating_system if overwrite || @operating_system == nil
188
+ end
189
+
190
+ def set_kcs_heat(kcs_heat)
191
+ @kcs_heat = kcs_heat
192
+ end
193
+
194
+ def set_visitor_visits(visitor_visits)
195
+ @visitor_visits = visitor_visits
196
+ end
140
197
  end
141
198
  end
142
199
  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 Title of the page
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,20 @@
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
+
12
+ def self.get_previous_visit_timestamps(visitor_visits)
13
+ visitor_visits.is_a?(VisitorVisits) ? visitor_visits.previous_visit_timestamps : []
14
+ end
15
+
16
+ def self.visitor_visits?(obj)
17
+ obj.nil? || obj.is_a?(VisitorVisits)
18
+ end
19
+ end
20
+ end