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 +4 -4
- data/lib/kameleoon/data/conversion.rb +23 -3
- data/lib/kameleoon/data/custom_data.rb +0 -6
- data/lib/kameleoon/data/manager/visitor.rb +22 -0
- data/lib/kameleoon/data/personalization.rb +16 -0
- data/lib/kameleoon/kameleoon_client.rb +14 -6
- data/lib/kameleoon/managers/remote_data/remote_visitor_data.rb +25 -13
- data/lib/kameleoon/network/url_provider.rb +1 -0
- data/lib/kameleoon/targeting/condition.rb +3 -0
- data/lib/kameleoon/targeting/condition_factory.rb +9 -0
- data/lib/kameleoon/targeting/conditions/exclusive_experiment_condition.rb +60 -0
- data/lib/kameleoon/targeting/conditions/exclusive_feature_flag_condition.rb +1 -1
- data/lib/kameleoon/targeting/conditions/target_experiment_condition.rb +46 -0
- data/lib/kameleoon/targeting/conditions/target_feature_flag_condition.rb +7 -5
- data/lib/kameleoon/targeting/conditions/target_personalization_condition.rb +33 -0
- data/lib/kameleoon/targeting/targeting_manager.rb +31 -18
- data/lib/kameleoon/types/remote_visitor_data_filter.rb +4 -2
- data/lib/kameleoon/utils.rb +16 -0
- data/lib/kameleoon/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 40923e6f42531b0686515b2ed716e62c1fb99aaeb8a739014bb60b75d661b06d
|
4
|
+
data.tar.gz: 7bcc9f40e5ffce5701d0046250e852ec7330638d2d3ee48ea838b7842054f280
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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(
|
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,
|
195
|
-
|
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,
|
203
|
-
|
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, :
|
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
|
-
|
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
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
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
|
-
#
|
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
|
-
#
|
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?(
|
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
|
28
|
-
|
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?(
|
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
|
52
|
+
when ConditionType::CUSTOM_DATUM
|
46
53
|
condition_data = visitor.custom_data unless visitor.nil?
|
47
|
-
when
|
48
|
-
|
49
|
-
|
50
|
-
|
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
|
59
|
+
when ConditionType::DEVICE_TYPE
|
53
60
|
condition_data = visitor.device unless visitor.nil?
|
54
|
-
when
|
61
|
+
when ConditionType::BROWSER
|
55
62
|
condition_data = visitor.browser unless visitor.nil?
|
56
|
-
when
|
63
|
+
when ConditionType::COOKIE
|
57
64
|
condition_data = visitor.cookie unless visitor.nil?
|
58
|
-
when
|
65
|
+
when ConditionType::GEOLOCATION
|
59
66
|
condition_data = visitor.geolocation unless visitor.nil?
|
60
|
-
when
|
67
|
+
when ConditionType::OPERATING_SYSTEM
|
61
68
|
condition_data = visitor.operating_system unless visitor.nil?
|
62
|
-
when
|
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
|
76
|
+
when ConditionType::CONVERSIONS
|
70
77
|
condition_data = visitor.conversions unless visitor.nil?
|
71
|
-
when
|
72
|
-
condition_data =
|
73
|
-
when
|
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
|
82
|
+
when ConditionType::TARGET_FEATURE_FLAG
|
76
83
|
condition_data = TargetFeatureFlagInfo.new(@data_manager.data_file, visitor.variations) unless visitor.nil?
|
77
|
-
when
|
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
|
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
|
data/lib/kameleoon/utils.rb
CHANGED
@@ -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 = '*'
|
data/lib/kameleoon/version.rb
CHANGED
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.
|
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-
|
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
|