kameleoon-client-ruby 3.14.0 → 3.16.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 +12 -3
- data/lib/kameleoon/configuration/data_file.rb +13 -11
- data/lib/kameleoon/data/custom_data.rb +51 -13
- data/lib/kameleoon/data/data.rb +1 -0
- data/lib/kameleoon/data/manager/visitor.rb +27 -3
- data/lib/kameleoon/data/manager/visitor_manager.rb +26 -15
- data/lib/kameleoon/data/mapping_identifier.rb +9 -2
- data/lib/kameleoon/data/targeted_segment.rb +30 -0
- data/lib/kameleoon/kameleoon_client.rb +24 -3
- data/lib/kameleoon/targeting/conditions/segment_condition.rb +3 -3
- data/lib/kameleoon/targeting/models.rb +3 -2
- data/lib/kameleoon/targeting/targeting_manager.rb +12 -16
- data/lib/kameleoon/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3df9ec4718c2a87cff0c2ad6344d43ca3ad095531badca20a6ac1bc0c1db9126
|
4
|
+
data.tar.gz: ba946333858defdeedccfdd3468aab44eeae80a8e9f4f407b68db4b4701a47bb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d01c49dabf864637880c54117b74580d8b9f08567fe3755dbdaf3483e8da91e44c46041bfc537de1efb9bbcc969fdf106a273a235e4b933ccf85da74cafa00f2
|
7
|
+
data.tar.gz: 287fc1558d2f377db0cbe20b31069fa216bdffa5cc640286897895bb7a18903f2b1f706c1697c37ac1f1af0fe1e9b88a7beded87aaa056ec810ef571f77793d9
|
@@ -14,13 +14,18 @@ module Kameleoon
|
|
14
14
|
@local_only = Set[]
|
15
15
|
@visitor_scope = Set[]
|
16
16
|
@custom_data_index_by_id = {}
|
17
|
+
@custom_data_index_by_name = {}
|
17
18
|
unless hashes.nil?
|
18
19
|
for hash in hashes
|
19
20
|
index = hash['index']
|
20
21
|
@local_only.add(index) if hash['localOnly']
|
21
22
|
@visitor_scope.add(index) if hash['scope'] == SCOPE_VISITOR
|
22
|
-
|
23
|
-
|
23
|
+
if index
|
24
|
+
id = hash['id']
|
25
|
+
name = hash['name']
|
26
|
+
@custom_data_index_by_id[id] = index if id
|
27
|
+
@custom_data_index_by_name[name] = index if name
|
28
|
+
end
|
24
29
|
if hash['isMappingIdentifier']
|
25
30
|
unless @mapping_identifier_index.nil?
|
26
31
|
Logging::KameleoonLogger.warning('More than one mapping identifier is set. Undefined behavior ' \
|
@@ -48,8 +53,12 @@ module Kameleoon
|
|
48
53
|
@custom_data_index_by_id[custom_data_id]
|
49
54
|
end
|
50
55
|
|
56
|
+
def get_custom_data_index_by_name(custom_data_name)
|
57
|
+
@custom_data_index_by_name[custom_data_name]
|
58
|
+
end
|
59
|
+
|
51
60
|
def self.mapping_identifier?(custom_data_info, custom_data)
|
52
|
-
!custom_data_info.nil? && (custom_data.
|
61
|
+
!custom_data_info.nil? && (custom_data.index == custom_data_info.mapping_identifier_index) && \
|
53
62
|
!(custom_data.values.empty? || custom_data.values[0].empty?)
|
54
63
|
end
|
55
64
|
end
|
@@ -11,9 +11,9 @@ require 'kameleoon/targeting/models'
|
|
11
11
|
module Kameleoon
|
12
12
|
module Configuration
|
13
13
|
class DataFile
|
14
|
-
attr_reader :last_modified, :settings, :
|
15
|
-
:
|
16
|
-
:experiment_ids_with_js_css_variable, :holdout
|
14
|
+
attr_reader :last_modified, :settings, :segments, :audience_tracking_segments, :feature_flags, :me_groups,
|
15
|
+
:has_any_targeted_delivery_rule, :feature_flag_by_id, :rule_info_by_exp_id, :variation_by_id,
|
16
|
+
:custom_data_info, :experiment_ids_with_js_css_variable, :holdout
|
17
17
|
|
18
18
|
def to_s
|
19
19
|
'DataFile{' \
|
@@ -70,9 +70,9 @@ module Kameleoon
|
|
70
70
|
def init(configuration)
|
71
71
|
Logging::KameleoonLogger.debug('CALL: DataFile.init(configuration: %s)', configuration)
|
72
72
|
@settings = Settings.new(configuration['configuration'])
|
73
|
-
segments = parse_segments(configuration)
|
73
|
+
@segments, @audience_tracking_segments = parse_segments(configuration)
|
74
74
|
@custom_data_info = CustomDataInfo.new(configuration['customData'])
|
75
|
-
@feature_flags = parse_feature_flags(configuration,
|
75
|
+
@feature_flags = parse_feature_flags(configuration, @custom_data_info)
|
76
76
|
@me_groups = make_me_groups(@feature_flags)
|
77
77
|
@has_any_targeted_delivery_rule = any_targeted_delivery_rule?
|
78
78
|
@holdout = Experiment.from_json(configuration['holdout']) if configuration.include?('holdout')
|
@@ -80,15 +80,20 @@ module Kameleoon
|
|
80
80
|
end
|
81
81
|
|
82
82
|
def parse_segments(configuration)
|
83
|
-
|
83
|
+
audience_tracking_segments = []
|
84
|
+
segments = configuration['segments'].to_h do |raw_seg|
|
84
85
|
seg = Targeting::Segment.new(raw_seg)
|
86
|
+
audience_tracking_segments.push(seg) if seg.audience_tracking
|
85
87
|
[seg.id, seg]
|
86
88
|
end
|
89
|
+
segments.freeze
|
90
|
+
audience_tracking_segments.freeze
|
91
|
+
[segments, audience_tracking_segments]
|
87
92
|
end
|
88
93
|
|
89
|
-
def parse_feature_flags(configuration,
|
94
|
+
def parse_feature_flags(configuration, cdi)
|
90
95
|
configuration['featureFlags'].to_h do |raw_ff|
|
91
|
-
ff = FeatureFlag.new(raw_ff, segments, cdi)
|
96
|
+
ff = FeatureFlag.new(raw_ff, @segments, cdi)
|
92
97
|
[ff.feature_key, ff]
|
93
98
|
end
|
94
99
|
end
|
@@ -99,7 +104,6 @@ module Kameleoon
|
|
99
104
|
|
100
105
|
def collect_indices
|
101
106
|
@feature_flag_by_id = {}
|
102
|
-
@rule_by_segment_id = {}
|
103
107
|
@rule_info_by_exp_id = {}
|
104
108
|
@variation_by_id = {}
|
105
109
|
@experiment_ids_with_js_css_variable = Set.new
|
@@ -110,7 +114,6 @@ module Kameleoon
|
|
110
114
|
|
111
115
|
has_feature_flag_variable_js_css = feature_flag_variable_js_css?(feature_flag)
|
112
116
|
feature_flag.rules.each do |rule|
|
113
|
-
@rule_by_segment_id[rule.segment_id] = rule
|
114
117
|
@rule_info_by_exp_id[rule.experiment.id] = RuleInfo.new(feature_flag, rule)
|
115
118
|
rule.experiment.variations_by_exposition.each do |variation|
|
116
119
|
@variation_by_id[variation.variation_id] = variation
|
@@ -119,7 +122,6 @@ module Kameleoon
|
|
119
122
|
end
|
120
123
|
end
|
121
124
|
@feature_flag_by_id.freeze
|
122
|
-
@rule_by_segment_id.freeze
|
123
125
|
@variation_by_id.freeze
|
124
126
|
@experiment_ids_with_js_css_variable.freeze
|
125
127
|
end
|
@@ -8,50 +8,88 @@ require_relative 'data'
|
|
8
8
|
module Kameleoon
|
9
9
|
# Represents any custom data for targeting conditions
|
10
10
|
class CustomData < DuplicationUnsafeData
|
11
|
-
attr_reader :
|
11
|
+
attr_reader :index, :name, :values, :overwrite
|
12
12
|
|
13
13
|
def to_s
|
14
|
-
"CustomData{
|
14
|
+
"CustomData{index:#{@index},name:'#{@name}',values:#{@values},overwrite:#{@overwrite}}"
|
15
15
|
end
|
16
16
|
|
17
|
-
# @param [Integer]
|
17
|
+
# @param [Integer] index Index of the custom data
|
18
18
|
# @param [String] value Value of the custom data
|
19
19
|
# @param [Array] values Array of values of the custom data
|
20
|
+
# @param [Boolean] overwrite Flag to explicitly control how the values are stored and how they appear in reports
|
21
|
+
#
|
22
|
+
# @overload
|
23
|
+
# @param [String] name Custom Data name, can be used instead of Custom Data index
|
24
|
+
# @param [String] value Value of the custom data
|
25
|
+
# @param [Array] values Array of values of the custom data
|
26
|
+
# @param [Boolean] overwrite Flag to explicitly control how the values are stored and how they appear in reports
|
20
27
|
#
|
21
28
|
# @overload
|
22
29
|
# @param [Hash] hash Json value encoded in a hash.
|
23
30
|
# rubocop:disable Metrics/MethodLength
|
24
|
-
def initialize(arg0, *args)
|
31
|
+
def initialize(arg0, *args, overwrite: true)
|
25
32
|
super(DataType::CUSTOM)
|
26
33
|
if arg0.is_a?(Hash)
|
27
34
|
hash = arg0
|
28
|
-
|
29
|
-
|
35
|
+
index = hash['index'] || hash['id']
|
36
|
+
name = hash['name']
|
37
|
+
if index.nil? && name.nil?
|
38
|
+
raise Kameleoon::Exception::NotFound.new('index/id/name'), '"index/id/name" is mandatory'
|
39
|
+
end
|
30
40
|
|
31
|
-
@
|
41
|
+
@index = index || -1
|
42
|
+
@name = name
|
32
43
|
values = hash['values']
|
33
44
|
raise Kameleoon::Exception::NotFound.new('values'), '"values" is mandatory' if values.nil?
|
34
45
|
|
35
46
|
@values = values.is_a?(Array) ? values.dup : [values]
|
47
|
+
@overwrite = hash.fetch('overwrite', true)
|
36
48
|
else
|
37
|
-
|
49
|
+
case arg0
|
50
|
+
when Integer
|
51
|
+
@index = arg0
|
52
|
+
when String
|
53
|
+
@index = -1
|
54
|
+
@name = arg0
|
55
|
+
else
|
56
|
+
raise Kameleoon::Exception.new('Unexpected arg0 type'), 'Unexpected arg0 type'
|
57
|
+
end
|
38
58
|
@values = args
|
59
|
+
@overwrite = overwrite
|
39
60
|
end
|
40
61
|
|
41
|
-
return if @
|
62
|
+
return if @index.is_a?(Integer)
|
42
63
|
|
43
|
-
Logging::KameleoonLogger.warning("CustomData field '
|
44
|
-
@
|
64
|
+
Logging::KameleoonLogger.warning("CustomData field 'index' must be of 'Integer' type")
|
65
|
+
@index = @index.is_a?(String) ? @index.to_i : -1
|
45
66
|
end
|
46
67
|
# rubocop:enable Metrics/MethodLength
|
47
68
|
|
69
|
+
def named_to_indexed(index)
|
70
|
+
CustomData.new(
|
71
|
+
{
|
72
|
+
'index' => index,
|
73
|
+
'name' => @name,
|
74
|
+
'values' => @values,
|
75
|
+
'overwrite' => @overwrite
|
76
|
+
}
|
77
|
+
)
|
78
|
+
end
|
79
|
+
|
80
|
+
##
|
81
|
+
# DEPRECATED. Please use `index` instead.
|
82
|
+
def id
|
83
|
+
@index
|
84
|
+
end
|
85
|
+
|
48
86
|
def obtain_full_post_text_line
|
49
87
|
str_values = JSON.generate(Hash[@values.collect { |k| [k, 1] }])
|
50
88
|
params = {
|
51
89
|
eventType: 'customData',
|
52
|
-
index: @
|
90
|
+
index: @index,
|
53
91
|
valuesCountMap: str_values,
|
54
|
-
overwrite:
|
92
|
+
overwrite: @overwrite,
|
55
93
|
nonce: nonce
|
56
94
|
}
|
57
95
|
Kameleoon::Network::UriHelper.encode_query(params)
|
data/lib/kameleoon/data/data.rb
CHANGED
@@ -10,6 +10,7 @@ require 'kameleoon/data/device'
|
|
10
10
|
require 'kameleoon/data/kcs_heat'
|
11
11
|
require 'kameleoon/data/page_view'
|
12
12
|
require 'kameleoon/data/personalization'
|
13
|
+
require 'kameleoon/data/targeted_segment'
|
13
14
|
require 'kameleoon/data/unique_identifier'
|
14
15
|
require 'kameleoon/data/user_agent'
|
15
16
|
require 'kameleoon/data/manager/assigned_variation'
|
@@ -186,6 +187,14 @@ module Kameleoon
|
|
186
187
|
personalizations
|
187
188
|
end
|
188
189
|
|
190
|
+
def targeted_segments
|
191
|
+
targeted_segments = @data.targeted_segments
|
192
|
+
Logging::KameleoonLogger.debug(
|
193
|
+
'CALL/RETURN: Visitor.targeted_segments -> (targeted_segments: %s)', targeted_segments
|
194
|
+
)
|
195
|
+
targeted_segments
|
196
|
+
end
|
197
|
+
|
189
198
|
def get_forced_feature_variation(feature_key)
|
190
199
|
Logging::KameleoonLogger.debug("CALL: Visitor.get_forced_feature_variation(feature_key: '%s')", feature_key)
|
191
200
|
variation = @data.get_from_map(@data.simulated_variations, feature_key)
|
@@ -234,6 +243,8 @@ module Kameleoon
|
|
234
243
|
Logging::KameleoonLogger.debug('CALL: Visitor.add_data(args: %s, overwrite: %s)', args, overwrite)
|
235
244
|
@data.mutex.with_write_lock do
|
236
245
|
args.each do |data|
|
246
|
+
next if data.nil?
|
247
|
+
|
237
248
|
case data
|
238
249
|
when UserAgent
|
239
250
|
@data.user_agent = data.value
|
@@ -241,6 +252,8 @@ module Kameleoon
|
|
241
252
|
@data.add_variation(data, overwrite)
|
242
253
|
when Personalization
|
243
254
|
@data.add_personalization(data, overwrite)
|
255
|
+
when TargetedSegment
|
256
|
+
@data.add_targeted_segment(data)
|
244
257
|
when ForcedFeatureVariation
|
245
258
|
@data.add_forced_feature_variation(data)
|
246
259
|
when ForcedExperimentVariation
|
@@ -329,6 +342,7 @@ module Kameleoon
|
|
329
342
|
@custom_data_map&.each { |_, cd| blk.call(cd) }
|
330
343
|
@page_view_visits&.each { |_, pvv| blk.call(pvv.page_view) }
|
331
344
|
@variations&.each { |_, av| blk.call(av) }
|
345
|
+
@targeted_segments&.each { |_, ts| blk.call(ts) }
|
332
346
|
@conversions&.each { |c| blk.call(c) }
|
333
347
|
end
|
334
348
|
end
|
@@ -344,8 +358,9 @@ module Kameleoon
|
|
344
358
|
count += 1 unless @visitor_visits.nil?
|
345
359
|
count += @custom_data_map.size unless @custom_data_map.nil?
|
346
360
|
count += @page_view_visits.size unless @page_view_visits.nil?
|
347
|
-
count += @conversions.size unless @conversions.nil?
|
348
361
|
count += @variations.size unless @variations.nil?
|
362
|
+
count += @targeted_segments.size unless @targeted_segments.nil?
|
363
|
+
count += @conversions.size unless @conversions.nil?
|
349
364
|
end
|
350
365
|
Logging::KameleoonLogger.debug('RETURN: VisitorData.count_sendable_data -> (count: %s)', count)
|
351
366
|
count
|
@@ -371,6 +386,10 @@ module Kameleoon
|
|
371
386
|
DataMapStorage.new(@mutex, @personalizations)
|
372
387
|
end
|
373
388
|
|
389
|
+
def targeted_segments
|
390
|
+
DataMapStorage.new(@mutex, @targeted_segments)
|
391
|
+
end
|
392
|
+
|
374
393
|
def set_device(device, overwrite)
|
375
394
|
@device = device if overwrite || @device.nil?
|
376
395
|
end
|
@@ -389,14 +408,19 @@ module Kameleoon
|
|
389
408
|
end
|
390
409
|
end
|
391
410
|
|
411
|
+
def add_targeted_segment(targeted_segment)
|
412
|
+
@targeted_segments ||= {}
|
413
|
+
@targeted_segments[targeted_segment.id] = targeted_segment
|
414
|
+
end
|
415
|
+
|
392
416
|
def set_browser(browser, overwrite)
|
393
417
|
@browser = browser if overwrite || @browser.nil?
|
394
418
|
end
|
395
419
|
|
396
420
|
def add_custom_data(custom_data, overwrite)
|
397
421
|
@custom_data_map ||= {}
|
398
|
-
if overwrite || !@custom_data_map.include?(custom_data.
|
399
|
-
@custom_data_map[custom_data.
|
422
|
+
if overwrite || !@custom_data_map.include?(custom_data.index)
|
423
|
+
@custom_data_map[custom_data.index] = custom_data
|
400
424
|
end
|
401
425
|
end
|
402
426
|
|
@@ -77,21 +77,8 @@ module Kameleoon
|
|
77
77
|
cdi = @data_manager.data_file.custom_data_info
|
78
78
|
args.size.times do |i|
|
79
79
|
custom_data = args[i]
|
80
|
-
|
81
|
-
|
82
|
-
# We shouldn't send custom data with local only type
|
83
|
-
custom_data.mark_as_sent if cdi.local_only?(custom_data.id)
|
84
|
-
# If mappingIdentifier is passed, we should link anonymous visitor with real unique userId.
|
85
|
-
# After authorization, customer must be able to continue work with userId, but hash for variation
|
86
|
-
# should be calculated based on anonymous visitor code, that's why set MappingIdentifier to visitor.
|
87
|
-
if Configuration::CustomDataInfo.mapping_identifier?(cdi, custom_data)
|
88
|
-
visitor.mapping_identifier = visitor_code
|
89
|
-
user_id = custom_data.values[0]
|
90
|
-
args[i] = MappingIdentifier.new(custom_data)
|
91
|
-
if visitor_code != user_id
|
92
|
-
@visitors[user_id] = visitor.clone
|
93
|
-
Logging::KameleoonLogger.info(-> { "Linked anonymous visitor '#{visitor_code}' with user '#{user_id}'" })
|
94
|
-
end
|
80
|
+
if custom_data.is_a?(Kameleoon::CustomData)
|
81
|
+
args[i] = process_custom_data(cdi, visitor_code, visitor, custom_data)
|
95
82
|
end
|
96
83
|
end
|
97
84
|
visitor.add_data(*args, overwrite: overwrite)
|
@@ -104,6 +91,30 @@ module Kameleoon
|
|
104
91
|
|
105
92
|
private
|
106
93
|
|
94
|
+
def process_custom_data(cdi, visitor_code, visitor, custom_data)
|
95
|
+
unless custom_data.name.nil?
|
96
|
+
cd_index = cdi.get_custom_data_index_by_name(custom_data.name)
|
97
|
+
return nil if cd_index.nil?
|
98
|
+
|
99
|
+
custom_data = custom_data.named_to_indexed(cd_index)
|
100
|
+
end
|
101
|
+
# We shouldn't send custom data with local only type
|
102
|
+
custom_data.mark_as_sent if cdi.local_only?(custom_data.index)
|
103
|
+
# If mappingIdentifier is passed, we should link anonymous visitor with real unique userId.
|
104
|
+
# After authorization, customer must be able to continue work with userId, but hash for variation
|
105
|
+
# should be calculated based on anonymous visitor code, that's why set MappingIdentifier to visitor.
|
106
|
+
if Configuration::CustomDataInfo.mapping_identifier?(cdi, custom_data)
|
107
|
+
visitor.mapping_identifier = visitor_code
|
108
|
+
user_id = custom_data.values[0]
|
109
|
+
custom_data = MappingIdentifier.new(custom_data)
|
110
|
+
if visitor_code != user_id
|
111
|
+
@visitors[user_id] = visitor.clone
|
112
|
+
Logging::KameleoonLogger.info(-> { "Linked anonymous visitor '#{visitor_code}' with user '#{user_id}'" })
|
113
|
+
end
|
114
|
+
end
|
115
|
+
custom_data
|
116
|
+
end
|
117
|
+
|
107
118
|
def purge
|
108
119
|
Logging::KameleoonLogger.debug('CALL: VisitorManager.purge')
|
109
120
|
expired_time = Time.new.to_i - @expiration_period
|
@@ -6,7 +6,14 @@ require 'kameleoon/network/uri_helper'
|
|
6
6
|
module Kameleoon
|
7
7
|
class MappingIdentifier < CustomData
|
8
8
|
def initialize(custom_data)
|
9
|
-
super(
|
9
|
+
super(
|
10
|
+
{
|
11
|
+
'index' => custom_data.index,
|
12
|
+
'name' => custom_data.name,
|
13
|
+
'values' => custom_data.values,
|
14
|
+
'overwrite' => custom_data.overwrite
|
15
|
+
}
|
16
|
+
)
|
10
17
|
end
|
11
18
|
|
12
19
|
def unsent
|
@@ -27,7 +34,7 @@ module Kameleoon
|
|
27
34
|
end
|
28
35
|
|
29
36
|
def to_s
|
30
|
-
"MappingIdentifier{
|
37
|
+
"MappingIdentifier{index:#{@index},name:'#{@name}',values:#{@values},overwrite:#{@overwrite}}"
|
31
38
|
end
|
32
39
|
end
|
33
40
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'kameleoon/data/data'
|
4
|
+
require 'kameleoon/network/uri_helper'
|
5
|
+
|
6
|
+
module Kameleoon
|
7
|
+
class TargetedSegment < DuplicationUnsafeData
|
8
|
+
EVENT_TYPE = 'targetingSegment'
|
9
|
+
|
10
|
+
attr_reader :id
|
11
|
+
|
12
|
+
def initialize(id)
|
13
|
+
super(DataType::TARGETED_SEGMENT)
|
14
|
+
@id = id
|
15
|
+
end
|
16
|
+
|
17
|
+
def obtain_full_post_text_line
|
18
|
+
params = {
|
19
|
+
eventType: EVENT_TYPE,
|
20
|
+
id: @id,
|
21
|
+
nonce: nonce
|
22
|
+
}
|
23
|
+
Network::UriHelper.encode_query(params)
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_s
|
27
|
+
"TargetedSegment{id:#{@id}}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -758,6 +758,27 @@ module Kameleoon
|
|
758
758
|
)
|
759
759
|
end
|
760
760
|
|
761
|
+
##
|
762
|
+
# Evaluates the visitor against all available Audiences Explorer segments and tracks those that match.
|
763
|
+
# A detailed analysis of segment performance can then be performed directly in Audiences Explorer.
|
764
|
+
#
|
765
|
+
# @param [String] visitor_code The unique visitor code identifying the visitor.
|
766
|
+
#
|
767
|
+
# @raise [Kameleoon::Exception::VisitorCodeInvalid] The provided **visitor code** is invalid.
|
768
|
+
def evaluate_audiences(visitor_code)
|
769
|
+
Logging::KameleoonLogger.info("CALL: KameleoonClient.evaluate_audiences(visitor_code: '%s')", visitor_code)
|
770
|
+
Utils::VisitorCode.validate(visitor_code)
|
771
|
+
segments = @data_manager.data_file.audience_tracking_segments.select do |seg|
|
772
|
+
check_targeting(visitor_code, nil, seg)
|
773
|
+
end
|
774
|
+
unless segments.empty?
|
775
|
+
segments.map! { |seg| TargetedSegment.new(seg.id) }
|
776
|
+
@visitor_manager.add_data(visitor_code, *segments)
|
777
|
+
end
|
778
|
+
@tracking_manager.add_visitor_code(visitor_code)
|
779
|
+
Logging::KameleoonLogger.info("RETURN: KameleoonClient.evaluate_audiences(visitor_code: '%s')", visitor_code)
|
780
|
+
end
|
781
|
+
|
761
782
|
private
|
762
783
|
|
763
784
|
HYBRID_EXPIRATION_TIME = 5
|
@@ -904,8 +925,8 @@ module Kameleoon
|
|
904
925
|
# nil
|
905
926
|
# end
|
906
927
|
|
907
|
-
def check_targeting(visitor_code, campaign_id,
|
908
|
-
@targeting_manager.check_targeting(visitor_code, campaign_id,
|
928
|
+
def check_targeting(visitor_code, campaign_id, segment)
|
929
|
+
@targeting_manager.check_targeting(visitor_code, campaign_id, segment)
|
909
930
|
end
|
910
931
|
|
911
932
|
def get_variation_info(visitor_code, feature_flag, track)
|
@@ -1106,7 +1127,7 @@ module Kameleoon
|
|
1106
1127
|
break
|
1107
1128
|
end
|
1108
1129
|
# check if visitor is targeted for rule, else next rule
|
1109
|
-
next unless check_targeting(visitor_code, rule.experiment.id, rule)
|
1130
|
+
next unless check_targeting(visitor_code, rule.experiment.id, rule.targeting_segment)
|
1110
1131
|
|
1111
1132
|
unless forced_variation.nil?
|
1112
1133
|
# Forcing experiment variation in targeting-only mode
|
@@ -19,10 +19,10 @@ module Kameleoon
|
|
19
19
|
private
|
20
20
|
|
21
21
|
def check_targeting(segment_info)
|
22
|
-
|
23
|
-
return false
|
22
|
+
segment = segment_info.data_file.segments[@segment_id]
|
23
|
+
return false if segment.nil?
|
24
24
|
|
25
|
-
|
25
|
+
segment.check_tree(->(type) { segment_info.condition_data(type) })
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
@@ -8,10 +8,10 @@ module Kameleoon
|
|
8
8
|
module Targeting
|
9
9
|
class Segment
|
10
10
|
include TreeBuilder
|
11
|
-
attr_accessor :id, :tree
|
11
|
+
attr_accessor :id, :tree, :audience_tracking
|
12
12
|
|
13
13
|
def to_s
|
14
|
-
@
|
14
|
+
"Segment{id:#{@id},audience_tracking:#{@audience_tracking}}"
|
15
15
|
end
|
16
16
|
|
17
17
|
def initialize(*args)
|
@@ -28,6 +28,7 @@ module Kameleoon
|
|
28
28
|
if hash['conditionsData'].nil?
|
29
29
|
raise Kameleoon::Exception::NotFound.new(hash['conditionsData']), 'hash[\'conditionsData\']'
|
30
30
|
end
|
31
|
+
@audience_tracking = hash['audienceTracking'] || false
|
31
32
|
@tree = create_tree(hash['conditionsData'])
|
32
33
|
elsif args.length == 2
|
33
34
|
@id = args[0]
|
@@ -19,25 +19,19 @@ module Kameleoon
|
|
19
19
|
@visitor_manager = visitor_manager
|
20
20
|
end
|
21
21
|
|
22
|
-
def check_targeting(visitor_code, campaign_id,
|
22
|
+
def check_targeting(visitor_code, campaign_id, segment)
|
23
23
|
Logging::KameleoonLogger.debug(
|
24
|
-
"CALL: TargetingManager.check_targeting(visitor_code: '%s', campaign_id: %s,
|
25
|
-
visitor_code, campaign_id,
|
24
|
+
"CALL: TargetingManager.check_targeting(visitor_code: '%s', campaign_id: %s, segment: %s)",
|
25
|
+
visitor_code, campaign_id, segment
|
26
26
|
)
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
'(targeting: true)', visitor_code, campaign_id, exp_ff_rule
|
32
|
-
)
|
33
|
-
return true
|
27
|
+
targeting = true
|
28
|
+
unless segment.nil?
|
29
|
+
visitor = @visitor_manager.get_visitor(visitor_code)
|
30
|
+
targeting = segment.check_tree(->(type) { get_condition_data(type, visitor, visitor_code, campaign_id) })
|
34
31
|
end
|
35
|
-
|
36
|
-
visitor = @visitor_manager.get_visitor(visitor_code)
|
37
|
-
targeting = segment.check_tree(->(type) { get_condition_data(type, visitor, visitor_code, campaign_id) })
|
38
32
|
Logging::KameleoonLogger.debug(
|
39
|
-
"RETURN: TargetingManager.check_targeting(visitor_code: '%s', campaign_id: %s,
|
40
|
-
'(targeting: %s)', visitor_code, campaign_id,
|
33
|
+
"RETURN: TargetingManager.check_targeting(visitor_code: '%s', campaign_id: %s, segment: %s) -> " \
|
34
|
+
'(targeting: %s)', visitor_code, campaign_id, segment, targeting
|
41
35
|
)
|
42
36
|
targeting
|
43
37
|
end
|
@@ -86,7 +80,9 @@ module Kameleoon
|
|
86
80
|
when ConditionType::TARGET_PERSONALIZATION
|
87
81
|
condition_data = TargetPersonalizationInfo.new(visitor&.personalizations)
|
88
82
|
when ConditionType::EXCLUSIVE_EXPERIMENT
|
89
|
-
|
83
|
+
unless campaign_id.nil?
|
84
|
+
condition_data = ExclusiveExperimentInfo.new(campaign_id, visitor&.variations, visitor&.personalizations)
|
85
|
+
end
|
90
86
|
when ConditionType::FIRST_VISIT,
|
91
87
|
ConditionType::LAST_VISIT,
|
92
88
|
ConditionType::VISITS,
|
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.16.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-08-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: em-http-request
|
@@ -108,6 +108,7 @@ files:
|
|
108
108
|
- lib/kameleoon/data/operating_system.rb
|
109
109
|
- lib/kameleoon/data/page_view.rb
|
110
110
|
- lib/kameleoon/data/personalization.rb
|
111
|
+
- lib/kameleoon/data/targeted_segment.rb
|
111
112
|
- lib/kameleoon/data/unique_identifier.rb
|
112
113
|
- lib/kameleoon/data/user_agent.rb
|
113
114
|
- lib/kameleoon/data/visitor_visits.rb
|