kameleoon-client-ruby 3.10.0 → 3.12.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1831531ee6a40f0fbd32f110f9a9c9c1a33f71569c8b8de842bc01c06250d6d5
4
- data.tar.gz: 6e6f8f9d0ee511c2a27fc63ff040e6155b90df66925989d1d08bd473f86c071b
3
+ metadata.gz: 40923e6f42531b0686515b2ed716e62c1fb99aaeb8a739014bb60b75d661b06d
4
+ data.tar.gz: 7bcc9f40e5ffce5701d0046250e852ec7330638d2d3ee48ea838b7842054f280
5
5
  SHA512:
6
- metadata.gz: 6f575eb2b6e12302ffa5cdb067582d994ab890edcab12f174732d396adc4248fc96a9e27935c008db52f59a93b5e0c713530356acab47711727651d2a4d48e3a
7
- data.tar.gz: '058e6a5284550663cf20223eca099728a9ca0985aacfcfa829e585070228a83b38b4facda77d38a7f3ae17ae8fad37cc7898e47e2519826364a46b3205b33452'
6
+ metadata.gz: 760b08574a3dc5d79f6e8f241ec14bae4e31447ec8b39fe047d089edf5d64de2c95de43ed14dc995f32a68a806fb08ff8417f212e570ba5ac905b67908451a5b
7
+ data.tar.gz: 6d906512cc30caa25506b0b2a26faaaa9c7ad545663b05c155c2a040098448c9e7e3f67a8226feea905e1d70c6d0bbe15bc013341bcdbac0b99cba12bb316606
@@ -1,26 +1,31 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'json'
4
+ require 'kameleoon/data/custom_data'
4
5
  require 'kameleoon/network/uri_helper'
6
+ require 'kameleoon/utils'
5
7
  require_relative 'data'
6
8
 
7
9
  module Kameleoon
8
10
  # Conversion class uses for tracking conversion
9
11
  class Conversion < DuplicationSafeData
10
- attr_reader :goal_id, :revenue, :negative
12
+ attr_reader :goal_id, :revenue, :negative, :metadata
11
13
 
12
14
  def to_s
13
- "Conversion{goal_id:#{@goal_id},revenue:#{@revenue},negative:#{@negative}}"
15
+ "Conversion{goal_id:#{@goal_id},revenue:#{@revenue},negative:#{@negative}," \
16
+ "metadata:#{Utils::Strval.obj_to_s(@metadata)}}"
14
17
  end
15
18
 
16
19
  # @param [Integer] goal_id Id of the goal associated to the conversion
17
20
  # @param [Float] revenue Optional field - Revenue associated to the conversion.
18
21
  # @param [Boolean] negative Optional field - If the revenue is negative. By default it's positive.
19
- def initialize(goal_id, revenue = 0.0, negative = false)
22
+ # @param [Array] metadata Optional field - Metadata of the conversion. Array of CustomData objects.
23
+ def initialize(goal_id, revenue = 0.0, negative = false, metadata: nil)
20
24
  super(DataType::CONVERSION)
21
25
  @goal_id = goal_id
22
26
  @revenue = revenue || 0.0
23
27
  @negative = negative || false
28
+ @metadata = metadata
24
29
  end
25
30
 
26
31
  def obtain_full_post_text_line
@@ -31,7 +36,22 @@ module Kameleoon
31
36
  negative: @negative,
32
37
  nonce: nonce
33
38
  }
39
+ params[:metadata] = encode_metadata if @metadata&.length&.positive?
34
40
  Kameleoon::Network::UriHelper.encode_query(params)
35
41
  end
42
+
43
+ private
44
+
45
+ def encode_metadata
46
+ metadata = {}
47
+ added_indices = Set[]
48
+ @metadata&.each do |mcd|
49
+ next if !mcd.is_a?(CustomData) || added_indices.include?(mcd.id)
50
+
51
+ metadata[mcd.id] = mcd.values
52
+ added_indices.add(mcd.id)
53
+ end
54
+ JSON.generate(metadata)
55
+ end
36
56
  end
37
57
  end
@@ -38,10 +38,6 @@ module Kameleoon
38
38
  @values = args
39
39
  end
40
40
 
41
- if @values.empty?
42
- Logging::KameleoonLogger.error('Created a custom data %s with no values. It will not be tracked.', @id)
43
- end
44
-
45
41
  return if @id.is_a?(Integer)
46
42
 
47
43
  Logging::KameleoonLogger.warning("CustomData field 'id' must be of 'Integer' type")
@@ -50,8 +46,6 @@ module Kameleoon
50
46
  # rubocop:enable Metrics/MethodLength
51
47
 
52
48
  def obtain_full_post_text_line
53
- return '' if @values.empty?
54
-
55
49
  str_values = JSON.generate(Hash[@values.collect { |k| [k, 1] }])
56
50
  params = {
57
51
  eventType: 'customData',
@@ -8,6 +8,7 @@ require 'kameleoon/data/custom_data'
8
8
  require 'kameleoon/data/device'
9
9
  require 'kameleoon/data/kcs_heat'
10
10
  require 'kameleoon/data/page_view'
11
+ require 'kameleoon/data/personalization'
11
12
  require 'kameleoon/data/unique_identifier'
12
13
  require 'kameleoon/data/user_agent'
13
14
  require 'kameleoon/data/manager/assigned_variation'
@@ -172,6 +173,14 @@ module Kameleoon
172
173
  variations
173
174
  end
174
175
 
176
+ def personalizations
177
+ personalizations = @data.personalizations
178
+ Logging::KameleoonLogger.debug(
179
+ 'CALL/RETURN: Visitor.personalizations -> (personalizations: %s)', personalizations
180
+ )
181
+ personalizations
182
+ end
183
+
175
184
  def get_forced_feature_variation(feature_key)
176
185
  Logging::KameleoonLogger.debug("CALL: Visitor.get_forced_feature_variation(feature_key: '%s')", feature_key)
177
186
  variation = @data.get_from_map(@data.simulated_variations, feature_key)
@@ -225,6 +234,8 @@ module Kameleoon
225
234
  @data.user_agent = data.value
226
235
  when AssignedVariation
227
236
  @data.add_variation(data, overwrite)
237
+ when Personalization
238
+ @data.add_personalization(data, overwrite)
228
239
  when ForcedFeatureVariation
229
240
  @data.add_forced_feature_variation(data)
230
241
  when ForcedExperimentVariation
@@ -348,6 +359,10 @@ module Kameleoon
348
359
  DataMapStorage.new(@mutex, @variations)
349
360
  end
350
361
 
362
+ def personalizations
363
+ DataMapStorage.new(@mutex, @personalizations)
364
+ end
365
+
351
366
  def set_device(device, overwrite)
352
367
  @device = device if overwrite || @device.nil?
353
368
  end
@@ -359,6 +374,13 @@ module Kameleoon
359
374
  end
360
375
  end
361
376
 
377
+ def add_personalization(personalization, overwrite)
378
+ @personalizations ||= {}
379
+ if overwrite || !@personalizations.include?(personalization.id)
380
+ @personalizations[personalization.id] = personalization
381
+ end
382
+ end
383
+
362
384
  def set_browser(browser, overwrite)
363
385
  @browser = browser if overwrite || @browser.nil?
364
386
  end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kameleoon
4
+ class Personalization
5
+ attr_reader :id, :variation_id
6
+
7
+ def initialize(id, variation_id)
8
+ @id = id
9
+ @variation_id = variation_id
10
+ end
11
+
12
+ def to_s
13
+ "Personalization{id:#{@id},variation_id:#{@variation_id}}"
14
+ end
15
+ end
16
+ end
@@ -186,21 +186,29 @@ module Kameleoon
186
186
  # @param [Float] revenue Optional - Revenue of the conversion.
187
187
  # @param [Bool] is_unique_identifier(DEPRECATED) Parameter that specifies whether the visitorCode is a unique
188
188
  # identifier. This field is optional.
189
+ # @param [Bool] negative Defines if the revenue is positive or negative.
190
+ # This field is optional (`false` by default).
191
+ # @param [Array] metadata Metadata of the conversion. This field is optional.
189
192
  #
190
193
  # @raise [Kameleoon::Exception::VisitorCodeInvalid] If the visitor code is empty or longer than 255 chars
191
194
  #
192
- def track_conversion(visitor_code, goal_id, revenue = 0.0, is_unique_identifier: nil)
195
+ def track_conversion(
196
+ visitor_code, goal_id, revenue = 0.0,
197
+ is_unique_identifier: nil, negative: false, metadata: nil
198
+ )
193
199
  Logging::KameleoonLogger.info(
194
- "CALL: KameleoonClient.track_conversion(visitor_code: '%s', goal_id: %s, revenue: %s, is_unique_identifier: %s)",
195
- visitor_code, goal_id, revenue, is_unique_identifier
200
+ "CALL: KameleoonClient.track_conversion(visitor_code: '%s', goal_id: %s, revenue: %s, " \
201
+ 'is_unique_identifier: %s, negative: %s, metadata: %s)',
202
+ visitor_code, goal_id, revenue, is_unique_identifier, negative, metadata
196
203
  )
197
204
  Utils::VisitorCode.validate(visitor_code)
198
205
  set_unique_identifier(visitor_code, is_unique_identifier) unless is_unique_identifier.nil?
199
- add_data(visitor_code, Conversion.new(goal_id, revenue))
206
+ add_data(visitor_code, Conversion.new(goal_id, revenue, negative, metadata: metadata))
200
207
  @tracking_manager.add_visitor_code(visitor_code)
201
208
  Logging::KameleoonLogger.info(
202
- "RETURN: KameleoonClient.track_conversion(visitor_code: '%s', goal_id: %s, revenue: %s, is_unique_identifier: %s)",
203
- visitor_code, goal_id, revenue, is_unique_identifier
209
+ "RETURN: KameleoonClient.track_conversion(visitor_code: '%s', goal_id: %s, revenue: %s, " \
210
+ 'is_unique_identifier: %s, negative: %s, metadata: %s)',
211
+ visitor_code, goal_id, revenue, is_unique_identifier, negative, metadata
204
212
  )
205
213
  end
206
214
 
@@ -8,6 +8,7 @@ require 'kameleoon/data/device'
8
8
  require 'kameleoon/data/geolocation'
9
9
  require 'kameleoon/data/kcs_heat'
10
10
  require 'kameleoon/data/page_view'
11
+ require 'kameleoon/data/personalization'
11
12
  require 'kameleoon/data/visitor_visits'
12
13
  require 'kameleoon/data/manager/page_view_visit'
13
14
  require 'kameleoon/data/manager/assigned_variation'
@@ -16,8 +17,8 @@ module Kameleoon
16
17
  module Managers
17
18
  module RemoteData
18
19
  class RemoteVisitorData
19
- attr_reader :custom_data_dict, :page_view_visits, :conversions, :experiments, :device, :browser,
20
- :operating_system, :geolocation, :previous_visitor_visits, :kcs_heat, :cbs, :visitor_code
20
+ attr_reader :custom_data_dict, :page_view_visits, :conversions, :experiments, :personalizations, :device,
21
+ :browser, :operating_system, :geolocation, :previous_visitor_visits, :kcs_heat, :cbs, :visitor_code
21
22
 
22
23
  def initialize(hash)
23
24
  current_visit = hash['currentVisit']
@@ -45,6 +46,7 @@ module Kameleoon
45
46
  data_to_add.push(@cbs) unless @cbs.nil?
46
47
  data_to_add.concat(@page_view_visits.values) unless @page_view_visits.nil?
47
48
  data_to_add.concat(@experiments.values) unless @experiments.nil?
49
+ data_to_add.concat(@personalizations.values) unless @personalizations.nil?
48
50
  data_to_add.concat(conversions_single_objects)
49
51
  end
50
52
 
@@ -85,6 +87,8 @@ module Kameleoon
85
87
  geolocation_events.size.positive?
86
88
  static_data_events = hash['staticDataEvent']
87
89
  parse_static_data(static_data_events) unless static_data_events.nil?
90
+ personalization_events = hash['personalizationEvents']
91
+ parse_personalizations(personalization_events) unless personalization_events.nil?
88
92
  end
89
93
 
90
94
  def parse_custom_data(custom_data_events)
@@ -93,7 +97,9 @@ module Kameleoon
93
97
  data = custom_data_event['data']
94
98
  id = data['index']
95
99
  id = -1 if id.nil?
96
- @custom_data_dict[id] = CustomData.new(id, *data['valuesCountMap'].keys) unless @custom_data_dict.include?(id)
100
+ next if @custom_data_dict.include?(id)
101
+
102
+ @custom_data_dict[id] = CustomData.new(id, *data['valuesCountMap'].keys)
97
103
  end
98
104
  end
99
105
 
@@ -115,14 +121,12 @@ module Kameleoon
115
121
  @experiments = {} if @experiments.nil?
116
122
  experiment_events.reverse_each do |experiment_event|
117
123
  id = experiment_event['data']['id']
118
- variation = @experiments[id]
119
- if variation.nil?
120
- variation = DataManager::AssignedVariation.new(
121
- id, experiment_event['data']['variationId'],
122
- Configuration::RuleType::UNKNOWN, assignment_time: experiment_event['time']
123
- )
124
- @experiments[id] = variation
125
- end
124
+ next if @experiments.include?(id)
125
+
126
+ @experiments[id] = DataManager::AssignedVariation.new(
127
+ id, experiment_event['data']['variationId'],
128
+ Configuration::RuleType::UNKNOWN, assignment_time: experiment_event['time']
129
+ )
126
130
  end
127
131
  end
128
132
 
@@ -141,8 +145,6 @@ module Kameleoon
141
145
  end
142
146
 
143
147
  def parse_static_data(static_data_event)
144
- return if @device != nil && @browser != nil && @operating_system != nil
145
-
146
148
  data = static_data_event['data']
147
149
  if @device.nil?
148
150
  device_type = data['deviceType']
@@ -158,6 +160,16 @@ module Kameleoon
158
160
  end
159
161
  end
160
162
 
163
+ def parse_personalizations(personalization_events)
164
+ @personalizations = {} if @personalizations.nil?
165
+ personalization_events.reverse_each do |personalization_event|
166
+ id = personalization_event['data']['id']
167
+ next if @personalizations.include?(id)
168
+
169
+ @personalizations[id] = Personalization.new(id, personalization_event['data']['variationId'])
170
+ end
171
+ end
172
+
161
173
  def conversions_single_objects
162
174
  objects = []
163
175
  objects += @conversions unless @conversions.nil?
@@ -76,6 +76,7 @@ module Kameleoon
76
76
  params[:experiment] = true if filter.experiments
77
77
  params[:page] = true if filter.page_views
78
78
  params[:staticData] = true if filter.device || filter.browser || filter.operating_system
79
+ params[:personalization] = true if filter.personalization
79
80
  params[:cbs] = true if filter.cbs
80
81
  format(DATA_API_URL_FORMAT, @data_api_domain, VISITOR_DATA_PATH, UriHelper.encode_query(params))
81
82
  end
@@ -9,7 +9,10 @@ module Kameleoon
9
9
  module ConditionType
10
10
  CUSTOM_DATUM = 'CUSTOM_DATUM'
11
11
  TARGET_FEATURE_FLAG = 'TARGET_FEATURE_FLAG'
12
+ TARGET_EXPERIMENT = 'TARGET_EXPERIMENT'
13
+ TARGET_PERSONALIZATION = 'TARGET_PERSONALIZATION'
12
14
  EXCLUSIVE_FEATURE_FLAG = 'EXCLUSIVE_FEATURE_FLAG'
15
+ EXCLUSIVE_EXPERIMENT = 'EXCLUSIVE_EXPERIMENT'
13
16
  PAGE_URL = 'PAGE_URL'
14
17
  PAGE_VIEWS = 'PAGE_VIEWS'
15
18
  PREVIOUS_PAGE = 'PREVIOUS_PAGE'
@@ -1,5 +1,8 @@
1
1
  require_relative 'conditions/custom_datum'
2
+ require_relative 'conditions/target_experiment_condition'
2
3
  require_relative 'conditions/target_feature_flag_condition'
4
+ require_relative 'conditions/target_personalization_condition'
5
+ require_relative 'conditions/exclusive_experiment_condition'
3
6
  require_relative 'conditions/exclusive_feature_flag_condition'
4
7
  require_relative 'conditions/page_title_condition'
5
8
  require_relative 'conditions/page_url_condition'
@@ -32,8 +35,14 @@ module Kameleoon
32
35
  CustomDatum.new(condition_json)
33
36
  when ConditionType::TARGET_FEATURE_FLAG
34
37
  TargetFeatureFlagCondition.new(condition_json)
38
+ when ConditionType::TARGET_EXPERIMENT
39
+ TargetExperimentCondition.new(condition_json)
40
+ when ConditionType::TARGET_PERSONALIZATION
41
+ TargetPersonalizationCondition.new(condition_json)
35
42
  when ConditionType::EXCLUSIVE_FEATURE_FLAG
36
43
  ExclusiveFeatureFlagCondition.new(condition_json)
44
+ when ConditionType::EXCLUSIVE_EXPERIMENT
45
+ ExclusiveExperimentCondition.new(condition_json)
37
46
  when ConditionType::PAGE_URL
38
47
  PageUrlCondition.new(condition_json)
39
48
  when ConditionType::PAGE_VIEWS
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'kameleoon/logging/kameleoon_logger'
4
+ require 'kameleoon/targeting/condition'
5
+
6
+ module Kameleoon
7
+ # @api private
8
+ module Targeting
9
+ # ExclusiveExperiment represents an instance of Exclusive Experiment condition in user account
10
+ class ExclusiveExperimentCondition < Condition
11
+ module CampaignType
12
+ EXPERIMENT = 'EXPERIMENT'
13
+ PERSONALIZATION = 'PERSONALIZATION'
14
+ ANY = 'ANY'
15
+ end
16
+
17
+ def initialize(json_condition)
18
+ super(json_condition)
19
+
20
+ @campaign_type = json_condition['campaignType']
21
+ end
22
+
23
+ def check(data)
24
+ return false unless data.is_a?(ExclusiveExperimentInfo)
25
+
26
+ case @campaign_type
27
+ when CampaignType::EXPERIMENT
28
+ return check_experiment(data)
29
+ when CampaignType::PERSONALIZATION
30
+ return check_personalization(data)
31
+ when CampaignType::ANY
32
+ return check_personalization(data) && check_experiment(data)
33
+ end
34
+ Logging::KameleoonLogger.error("Unexpected campaign type for '#{type}' condition: '#{@campaign_type}'")
35
+ false
36
+ end
37
+
38
+ private
39
+
40
+ def check_experiment(data)
41
+ size = data.variations_storage&.size || 0
42
+ size.zero? || (size == 1 && !data.variations_storage.get(data.current_experiment_id).nil?)
43
+ end
44
+
45
+ def check_personalization(data)
46
+ (data.personalizations_storage&.size || 0).zero?
47
+ end
48
+ end
49
+
50
+ class ExclusiveExperimentInfo
51
+ attr_reader :current_experiment_id, :variations_storage, :personalizations_storage
52
+
53
+ def initialize(current_experiment_id, variations_storage, personalizations_storage)
54
+ @current_experiment_id = current_experiment_id
55
+ @variations_storage = variations_storage
56
+ @personalizations_storage = personalizations_storage
57
+ end
58
+ end
59
+ end
60
+ end
@@ -5,7 +5,7 @@ require 'kameleoon/targeting/condition'
5
5
  module Kameleoon
6
6
  # @api private
7
7
  module Targeting
8
- # ExclusiveExperiment represents an instance of Exclusive Experiment condition in user account
8
+ # ExclusiveFeatureFlag represents an instance of Exclusive FeatureFlag condition in user account
9
9
  class ExclusiveFeatureFlagCondition < Condition
10
10
  def check(data)
11
11
  return false unless data.is_a?(ExclusiveFeatureFlagInfo)
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'kameleoon/logging/kameleoon_logger'
4
+ require 'kameleoon/targeting/condition'
5
+
6
+ module Kameleoon
7
+ # @api private
8
+ module Targeting
9
+ # TargetExperiment represents an instance of Experiment condition in user account
10
+ class TargetExperimentCondition < Condition
11
+ include Kameleoon::Exception
12
+
13
+ def initialize(json_condition)
14
+ super(json_condition)
15
+
16
+ @variation_id = json_condition['variationId'] || -1
17
+ @experiment_id = json_condition['experimentId'] || -1
18
+ @variation_match_type = json_condition['variationMatchType'] || Operator::UNKNOWN
19
+ end
20
+
21
+ def check(data)
22
+ return false unless data.is_a?(TargetExperimentInfo)
23
+
24
+ variation = data.variations_storage&.get(@experiment_id)
25
+ case @variation_match_type
26
+ when Operator::ANY
27
+ return !variation.nil?
28
+ when Operator::EXACT
29
+ return !variation.nil? && (variation.variation_id == @variation_id)
30
+ end
31
+ Logging::KameleoonLogger.error(
32
+ "Unexpected variation match type for '#{type}' condition: '#{@variation_match_type}'"
33
+ )
34
+ false
35
+ end
36
+ end
37
+
38
+ class TargetExperimentInfo
39
+ attr_reader :variations_storage
40
+
41
+ def initialize(variations_storage)
42
+ @variations_storage = variations_storage
43
+ end
44
+ end
45
+ end
46
+ end
@@ -6,7 +6,7 @@ require 'kameleoon/exceptions'
6
6
  module Kameleoon
7
7
  # @api private
8
8
  module Targeting
9
- # TargetExperiment represents an instance of Experiment condition in user account
9
+ # TargetFeatureFlag represents an instance of FeatureFlag condition in user account
10
10
  class TargetFeatureFlagCondition < Condition
11
11
  include Kameleoon::Exception
12
12
 
@@ -19,13 +19,15 @@ module Kameleoon
19
19
  end
20
20
 
21
21
  def check(data)
22
- return false unless data.is_a?(Kameleoon::Targeting::TargetFeatureFlagInfo) && data.variations_storage.size != 0
22
+ return false unless data.is_a?(TargetFeatureFlagInfo) && data.variations_storage.size.positive?
23
23
 
24
24
  get_rules(data).any? { |rule| check_rule(data, rule) }
25
25
  end
26
26
 
27
- private def check_rule(data, rule)
28
- return false unless rule.is_a?(Kameleoon::Configuration::Rule)
27
+ private
28
+
29
+ def check_rule(data, rule)
30
+ return false unless rule.is_a?(Configuration::Rule)
29
31
  return false if !@condition_rule_id.nil? && (@condition_rule_id != rule.id)
30
32
 
31
33
  variation = data.variations_storage.get(rule.experiment.id)
@@ -35,7 +37,7 @@ module Kameleoon
35
37
 
36
38
  variation = data.data_file.variation_by_id[variation.variation_id]
37
39
 
38
- return false unless variation.is_a?(Kameleoon::Configuration::VariationByExposition)
40
+ return false unless variation.is_a?(Configuration::VariationByExposition)
39
41
 
40
42
  variation.variation_key == @condition_variation_key
41
43
  end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'kameleoon/targeting/condition'
4
+
5
+ module Kameleoon
6
+ # @api private
7
+ module Targeting
8
+ # TargetPersonalization represents an instance of Personalization condition in user account
9
+ class TargetPersonalizationCondition < Condition
10
+ include Kameleoon::Exception
11
+
12
+ def initialize(json_condition)
13
+ super(json_condition)
14
+
15
+ @personalization_id = json_condition['personalizationId'] || -1
16
+ end
17
+
18
+ def check(data)
19
+ return false unless data.is_a?(TargetPersonalizationInfo)
20
+
21
+ !data.personalizations_storage&.get(@personalization_id).nil?
22
+ end
23
+ end
24
+
25
+ class TargetPersonalizationInfo
26
+ attr_reader :personalizations_storage
27
+
28
+ def initialize(personalizations_storage)
29
+ @personalizations_storage = personalizations_storage
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,7 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'kameleoon/logging/kameleoon_logger'
4
+ require 'kameleoon/targeting/condition'
5
+ require 'kameleoon/targeting/conditions/exclusive_experiment_condition'
6
+ require 'kameleoon/targeting/conditions/exclusive_feature_flag_condition'
7
+ require 'kameleoon/targeting/conditions/sdk_language_condition'
4
8
  require 'kameleoon/targeting/conditions/segment_condition'
9
+ require 'kameleoon/targeting/conditions/target_experiment_condition'
10
+ require 'kameleoon/targeting/conditions/target_feature_flag_condition'
11
+ require 'kameleoon/targeting/conditions/target_personalization_condition'
5
12
 
6
13
  module Kameleoon
7
14
  # @api private
@@ -42,47 +49,53 @@ module Kameleoon
42
49
  )
43
50
  condition_data = nil
44
51
  case type
45
- when Kameleoon::Targeting::ConditionType::CUSTOM_DATUM
52
+ when ConditionType::CUSTOM_DATUM
46
53
  condition_data = visitor.custom_data unless visitor.nil?
47
- when Kameleoon::Targeting::ConditionType::PAGE_VIEWS,
48
- Kameleoon::Targeting::ConditionType::PREVIOUS_PAGE,
49
- Kameleoon::Targeting::ConditionType::PAGE_TITLE,
50
- Kameleoon::Targeting::ConditionType::PAGE_URL
54
+ when ConditionType::PAGE_VIEWS,
55
+ ConditionType::PREVIOUS_PAGE,
56
+ ConditionType::PAGE_TITLE,
57
+ ConditionType::PAGE_URL
51
58
  condition_data = visitor.page_view_visits unless visitor.nil?
52
- when Kameleoon::Targeting::ConditionType::DEVICE_TYPE
59
+ when ConditionType::DEVICE_TYPE
53
60
  condition_data = visitor.device unless visitor.nil?
54
- when Kameleoon::Targeting::ConditionType::BROWSER
61
+ when ConditionType::BROWSER
55
62
  condition_data = visitor.browser unless visitor.nil?
56
- when Kameleoon::Targeting::ConditionType::COOKIE
63
+ when ConditionType::COOKIE
57
64
  condition_data = visitor.cookie unless visitor.nil?
58
- when Kameleoon::Targeting::ConditionType::GEOLOCATION
65
+ when ConditionType::GEOLOCATION
59
66
  condition_data = visitor.geolocation unless visitor.nil?
60
- when Kameleoon::Targeting::ConditionType::OPERATING_SYSTEM
67
+ when ConditionType::OPERATING_SYSTEM
61
68
  condition_data = visitor.operating_system unless visitor.nil?
62
- when Kameleoon::Targeting::ConditionType::SEGMENT
69
+ when ConditionType::SEGMENT
63
70
  condition_data = SegmentInfo.new(
64
71
  @data_manager.data_file,
65
72
  lambda { |type|
66
73
  get_condition_data(type, visitor, visitor_code, campaign_id)
67
74
  }
68
75
  )
69
- when Kameleoon::Targeting::ConditionType::CONVERSIONS
76
+ when ConditionType::CONVERSIONS
70
77
  condition_data = visitor.conversions unless visitor.nil?
71
- when Kameleoon::Targeting::ConditionType::SDK_LANGUAGE
72
- condition_data = Kameleoon::Targeting::SdkInfo.new(Kameleoon::SDK_NAME, Kameleoon::SDK_VERSION)
73
- when Kameleoon::Targeting::ConditionType::VISITOR_CODE
78
+ when ConditionType::SDK_LANGUAGE
79
+ condition_data = SdkInfo.new(Kameleoon::SDK_NAME, Kameleoon::SDK_VERSION)
80
+ when ConditionType::VISITOR_CODE
74
81
  condition_data = visitor_code
75
- when Kameleoon::Targeting::ConditionType::TARGET_FEATURE_FLAG
82
+ when ConditionType::TARGET_FEATURE_FLAG
76
83
  condition_data = TargetFeatureFlagInfo.new(@data_manager.data_file, visitor.variations) unless visitor.nil?
77
- when Kameleoon::Targeting::ConditionType::EXCLUSIVE_FEATURE_FLAG
84
+ when ConditionType::TARGET_EXPERIMENT
85
+ condition_data = TargetExperimentInfo.new(visitor&.variations)
86
+ when ConditionType::TARGET_PERSONALIZATION
87
+ condition_data = TargetPersonalizationInfo.new(visitor&.personalizations)
88
+ when ConditionType::EXCLUSIVE_FEATURE_FLAG
78
89
  condition_data = ExclusiveFeatureFlagInfo.new(campaign_id, visitor&.variations)
90
+ when ConditionType::EXCLUSIVE_EXPERIMENT
91
+ condition_data = ExclusiveExperimentInfo.new(campaign_id, visitor&.variations, visitor&.personalizations)
79
92
  when ConditionType::FIRST_VISIT,
80
93
  ConditionType::LAST_VISIT,
81
94
  ConditionType::VISITS,
82
95
  ConditionType::SAME_DAY_VISITS,
83
96
  ConditionType::NEW_VISITORS
84
97
  condition_data = visitor.visitor_visits unless visitor.nil?
85
- when Kameleoon::Targeting::ConditionType::HEAT_SLICE
98
+ when ConditionType::HEAT_SLICE
86
99
  condition_data = visitor&.kcs_heat
87
100
  end
88
101
  Logging::KameleoonLogger.debug(
@@ -5,7 +5,7 @@ module Kameleoon
5
5
  module Types
6
6
  class RemoteVisitorDataFilter
7
7
  attr_reader :previous_visit_amount, :current_visit, :custom_data, :page_views, :geolocation, :device, :browser,
8
- :operating_system, :conversions, :experiments, :kcs, :visitor_code, :cbs
8
+ :operating_system, :conversions, :experiments, :kcs, :visitor_code, :personalization, :cbs
9
9
 
10
10
  def to_s
11
11
  "RemoteVisitorDataFilter{previous_visit_amount:#{@previous_visit_amount}," \
@@ -20,13 +20,14 @@ module Kameleoon
20
20
  "experiments:#{@experiments}," \
21
21
  "kcs:#{@kcs}," \
22
22
  "visitor_code:#{@visitor_code}}" \
23
+ "personalization:#{@personalization}}" \
23
24
  "cbs:#{@cbs}}"
24
25
  end
25
26
 
26
27
  def initialize(
27
28
  previous_visit_amount: 1, current_visit: true, custom_data: true, page_views: false,
28
29
  geolocation: false, device: false, browser: false, operating_system: false, conversions: false,
29
- experiments: false, kcs: false, visitor_code: true, cbs: false
30
+ experiments: false, kcs: false, visitor_code: true, personalization: false, cbs: false
30
31
  )
31
32
  @previous_visit_amount = previous_visit_amount
32
33
  @current_visit = current_visit
@@ -40,6 +41,7 @@ module Kameleoon
40
41
  @experiments = experiments
41
42
  @kcs = kcs
42
43
  @visitor_code = visitor_code
44
+ @personalization = personalization
43
45
  @cbs = cbs
44
46
  end
45
47
  end
@@ -50,6 +50,22 @@ module Kameleoon
50
50
  end
51
51
 
52
52
  module Strval
53
+ def self.obj_to_s(obj)
54
+ case obj
55
+ when nil
56
+ 'nil'
57
+ when String
58
+ "'#{obj}'"
59
+ when Array
60
+ "[#{obj.map { |v| obj_to_s(v) }.join(',')}]"
61
+ when Hash
62
+ sb = []
63
+ obj.each { |k, v| sb.push("#{obj_to_s(k)}:#{obj_to_s(v)}") }
64
+ "{#{sb.join(',')}}"
65
+ else
66
+ obj.to_s
67
+ end
68
+ end
53
69
 
54
70
  def self.secret(secret)
55
71
  hid_ch = '*'
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kameleoon
4
- SDK_VERSION = '3.10.0'
4
+ SDK_VERSION = '3.12.0'
5
5
  SDK_NAME = 'RUBY'
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kameleoon-client-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.10.0
4
+ version: 3.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kameleoon
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-03-18 00:00:00.000000000 Z
11
+ date: 2025-04-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: em-http-request
@@ -107,6 +107,7 @@ files:
107
107
  - lib/kameleoon/data/mapping_identifier.rb
108
108
  - lib/kameleoon/data/operating_system.rb
109
109
  - lib/kameleoon/data/page_view.rb
110
+ - lib/kameleoon/data/personalization.rb
110
111
  - lib/kameleoon/data/unique_identifier.rb
111
112
  - lib/kameleoon/data/user_agent.rb
112
113
  - lib/kameleoon/data/visitor_visits.rb
@@ -151,6 +152,7 @@ files:
151
152
  - lib/kameleoon/targeting/conditions/cookie_condition.rb
152
153
  - lib/kameleoon/targeting/conditions/custom_datum.rb
153
154
  - lib/kameleoon/targeting/conditions/device_condition.rb
155
+ - lib/kameleoon/targeting/conditions/exclusive_experiment_condition.rb
154
156
  - lib/kameleoon/targeting/conditions/exclusive_feature_flag_condition.rb
155
157
  - lib/kameleoon/targeting/conditions/geolocation_condition.rb
156
158
  - lib/kameleoon/targeting/conditions/kcs_heat_range_condition.rb
@@ -163,7 +165,9 @@ files:
163
165
  - lib/kameleoon/targeting/conditions/sdk_language_condition.rb
164
166
  - lib/kameleoon/targeting/conditions/segment_condition.rb
165
167
  - lib/kameleoon/targeting/conditions/string_value_condition.rb
168
+ - lib/kameleoon/targeting/conditions/target_experiment_condition.rb
166
169
  - lib/kameleoon/targeting/conditions/target_feature_flag_condition.rb
170
+ - lib/kameleoon/targeting/conditions/target_personalization_condition.rb
167
171
  - lib/kameleoon/targeting/conditions/time_elapsed_since_visit_condition.rb
168
172
  - lib/kameleoon/targeting/conditions/unknown_condition.rb
169
173
  - lib/kameleoon/targeting/conditions/visit_number_today_condition.rb