kameleoon-client-ruby 3.4.0 → 3.6.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/data_file.rb +15 -1
- data/lib/kameleoon/configuration/feature_flag.rb +1 -1
- data/lib/kameleoon/data/manager/assigned_variation.rb +3 -1
- data/lib/kameleoon/data/manager/page_view_visit.rb +3 -2
- data/lib/kameleoon/data/manager/visitor.rb +17 -4
- data/lib/kameleoon/hybrid/manager.rb +7 -4
- data/lib/kameleoon/kameleoon_client.rb +187 -42
- data/lib/kameleoon/kameleoon_client_config.rb +1 -1
- data/lib/kameleoon/managers/data/data_manager.rb +4 -4
- data/lib/kameleoon/managers/remote_data/remote_data_manager.rb +10 -4
- data/lib/kameleoon/managers/remote_data/remote_visitor_data.rb +9 -7
- data/lib/kameleoon/managers/tracking/tracking_manager.rb +5 -4
- data/lib/kameleoon/network/cookie/cookie_manager.rb +7 -6
- data/lib/kameleoon/network/network_manager.rb +6 -5
- data/lib/kameleoon/network/url_provider.rb +1 -1
- data/lib/kameleoon/targeting/conditions/page_title_condition.rb +9 -7
- data/lib/kameleoon/targeting/conditions/page_url_condition.rb +9 -14
- data/lib/kameleoon/types/remote_visitor_data_filter.rb +6 -3
- data/lib/kameleoon/types/variation.rb +4 -0
- data/lib/kameleoon/utils.rb +31 -0
- data/lib/kameleoon/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 92e73ac3d81e29ddfc093e8da1a47f42b9970ea6e8717e0752be511b759db17a
|
4
|
+
data.tar.gz: 710361f25b6338e35bb668bb30f116c931efddd21fdb272fa5367add4d82db22
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 24db6ec9d63c160690506060d703661f77c5b60160fc585117b91460e74185a095f0b52156b268ba18d445797a584c9bd92e824c2bbecf8533d08e09cf89dab6
|
7
|
+
data.tar.gz: ab2f4e530b33235f7105158414ff77ce52f5b824632e4cae53ed06425f32be6f22719dcae86d7d5660cbd09ea4c090672ee5a237828a6db0e0772e80d65032c5
|
@@ -9,7 +9,7 @@ module Kameleoon
|
|
9
9
|
module Configuration
|
10
10
|
class DataFile
|
11
11
|
attr_reader :settings, :feature_flags, :has_any_targeted_delivery_rule, :feature_flag_by_id, :rule_by_segment_id,
|
12
|
-
:variation_by_id, :custom_data_info
|
12
|
+
:variation_by_id, :custom_data_info, :experiment_ids_with_js_css_variable
|
13
13
|
|
14
14
|
def to_s
|
15
15
|
'DataFile{' \
|
@@ -39,6 +39,10 @@ module Kameleoon
|
|
39
39
|
ff
|
40
40
|
end
|
41
41
|
|
42
|
+
def experiment_js_css_variable?(experiment_id)
|
43
|
+
@experiment_ids_with_js_css_variable.include?(experiment_id)
|
44
|
+
end
|
45
|
+
|
42
46
|
private
|
43
47
|
|
44
48
|
def init_default
|
@@ -71,21 +75,31 @@ module Kameleoon
|
|
71
75
|
@feature_flag_by_id = {}
|
72
76
|
@rule_by_segment_id = {}
|
73
77
|
@variation_by_id = {}
|
78
|
+
@experiment_ids_with_js_css_variable = Set.new
|
74
79
|
|
75
80
|
@feature_flags.each_value do |feature_flag|
|
76
81
|
@feature_flag_by_id[feature_flag.id] = feature_flag
|
77
82
|
next if feature_flag.rules.nil?
|
78
83
|
|
84
|
+
has_feature_flag_variable_js_css = feature_flag_variable_js_css?(feature_flag)
|
79
85
|
feature_flag.rules.each do |rule|
|
80
86
|
@rule_by_segment_id[rule.segment_id] = rule
|
81
87
|
rule.variation_by_exposition.each do |variation|
|
82
88
|
@variation_by_id[variation.variation_id] = variation
|
83
89
|
end
|
90
|
+
@experiment_ids_with_js_css_variable.add(rule.experiment_id) if has_feature_flag_variable_js_css
|
84
91
|
end
|
85
92
|
end
|
86
93
|
@feature_flag_by_id.freeze
|
87
94
|
@rule_by_segment_id.freeze
|
88
95
|
@variation_by_id.freeze
|
96
|
+
@experiment_ids_with_js_css_variable.freeze
|
97
|
+
end
|
98
|
+
|
99
|
+
def feature_flag_variable_js_css?(feature_flag)
|
100
|
+
feature_flag.variations.first&.variables&.any? do |variable|
|
101
|
+
%w[JS CSS].include?(variable.type)
|
102
|
+
end
|
89
103
|
end
|
90
104
|
end
|
91
105
|
end
|
@@ -18,7 +18,9 @@ module Kameleoon
|
|
18
18
|
"assignment_time:#{@assignment_time},rule_type:#{@rule_type}}"
|
19
19
|
end
|
20
20
|
|
21
|
-
def initialize(
|
21
|
+
def initialize(
|
22
|
+
experiment_id, variation_id, rule_type = Kameleoon::Configuration::RuleType::UNKNOWN, assignment_time: nil
|
23
|
+
)
|
22
24
|
super(DataType::ASSIGNED_VARIATION)
|
23
25
|
@experiment_id = experiment_id
|
24
26
|
@variation_id = variation_id
|
@@ -12,7 +12,7 @@ module Kameleoon
|
|
12
12
|
def initialize(page_view, count = 1, timestamp = nil)
|
13
13
|
@page_view = page_view
|
14
14
|
@count = count
|
15
|
-
@last_timestamp = timestamp
|
15
|
+
@last_timestamp = timestamp.nil? ? Time.new.to_i : timestamp
|
16
16
|
end
|
17
17
|
|
18
18
|
# Not thread-save method, should be called in synchronized code
|
@@ -20,10 +20,11 @@ module Kameleoon
|
|
20
20
|
def overwrite(page_view)
|
21
21
|
@page_view = page_view
|
22
22
|
@count += 1
|
23
|
+
@last_timestamp = Time.new.to_i
|
23
24
|
end
|
24
25
|
|
25
26
|
# Not thread-save method, should be called in synchronized code
|
26
|
-
def merge
|
27
|
+
def merge(page_view_visit)
|
27
28
|
@count += page_view_visit.count
|
28
29
|
@last_timestamp = [@last_timestamp, page_view_visit.last_timestamp].max
|
29
30
|
end
|
@@ -24,7 +24,7 @@ module Kameleoon
|
|
24
24
|
attr_reader :data, :is_unique_identifier
|
25
25
|
|
26
26
|
def to_s
|
27
|
-
|
27
|
+
'Visitor{}'
|
28
28
|
end
|
29
29
|
|
30
30
|
def initialize(source = nil)
|
@@ -52,7 +52,10 @@ module Kameleoon
|
|
52
52
|
|
53
53
|
def count_sendable_data
|
54
54
|
count_sendable_data = @data.count_sendable_data
|
55
|
-
Logging::KameleoonLogger.debug(
|
55
|
+
Logging::KameleoonLogger.debug(
|
56
|
+
'CALL/RETURN: Visitor.count_sendable_data -> (count_sendable_data: %s)',
|
57
|
+
count_sendable_data
|
58
|
+
)
|
56
59
|
count_sendable_data
|
57
60
|
end
|
58
61
|
|
@@ -82,7 +85,10 @@ module Kameleoon
|
|
82
85
|
|
83
86
|
def operating_system
|
84
87
|
operating_system = @data.operating_system
|
85
|
-
Logging::KameleoonLogger.debug(
|
88
|
+
Logging::KameleoonLogger.debug(
|
89
|
+
'CALL/RETURN: Visitor.operating_system -> (operating_system: %s)',
|
90
|
+
operating_system
|
91
|
+
)
|
86
92
|
operating_system
|
87
93
|
end
|
88
94
|
|
@@ -122,7 +128,14 @@ module Kameleoon
|
|
122
128
|
end
|
123
129
|
|
124
130
|
def mapping_identifier=(value)
|
125
|
-
@data.mapping_identifier
|
131
|
+
return unless @data.mapping_identifier.nil?
|
132
|
+
|
133
|
+
@data.mutex.with_write_lock do
|
134
|
+
if @data.mapping_identifier.nil?
|
135
|
+
@data.mapping_identifier = value
|
136
|
+
Logging::KameleoonLogger.debug('CALL/RETURN: Visitor.mapping_identifier = %s', value)
|
137
|
+
end
|
138
|
+
end
|
126
139
|
end
|
127
140
|
|
128
141
|
def custom_data
|
@@ -5,8 +5,8 @@ require 'kameleoon/logging/kameleoon_logger'
|
|
5
5
|
module Kameleoon
|
6
6
|
module Hybrid
|
7
7
|
TC_INIT = 'window.kameleoonQueue=window.kameleoonQueue||[];'
|
8
|
-
TC_ASSIGN_VARIATION_FORMAT = "window.kameleoonQueue.push(['Experiments.assignVariation',%d,%d]);"
|
9
|
-
TC_TRIGGER_FORMAT = "window.kameleoonQueue.push(['Experiments.trigger',%d
|
8
|
+
TC_ASSIGN_VARIATION_FORMAT = "window.kameleoonQueue.push(['Experiments.assignVariation',%d,%d,true]);"
|
9
|
+
TC_TRIGGER_FORMAT = "window.kameleoonQueue.push(['Experiments.trigger',%d,%s]);"
|
10
10
|
TC_ASSIGN_VARIATION_TRIGGER_FORMAT = TC_ASSIGN_VARIATION_FORMAT + TC_TRIGGER_FORMAT
|
11
11
|
|
12
12
|
# Will be useful for Ruby 3.0
|
@@ -19,10 +19,11 @@ module Kameleoon
|
|
19
19
|
|
20
20
|
# Implementation of Cache with auto cleaning feature
|
21
21
|
class ManagerImpl < Manager
|
22
|
-
def initialize(expiration_time)
|
22
|
+
def initialize(expiration_time, data_manager)
|
23
23
|
super()
|
24
24
|
Logging::KameleoonLogger.debug('CALL: HybridManager.new(expiration_time: %s)', expiration_time)
|
25
25
|
@expiration_time = expiration_time
|
26
|
+
@data_manager = data_manager
|
26
27
|
Logging::KameleoonLogger.debug('RETURN: HybridManager.new(expiration_time: %s)', expiration_time)
|
27
28
|
end
|
28
29
|
|
@@ -34,7 +35,9 @@ module Kameleoon
|
|
34
35
|
expired_time = (Time.now - @expiration_time).to_i
|
35
36
|
visitor_variations.enumerate do |v|
|
36
37
|
if v.assignment_time > expired_time
|
37
|
-
|
38
|
+
tracking_only = !@data_manager.data_file.experiment_js_css_variable?(v.experiment_id)
|
39
|
+
v_code = format(TC_ASSIGN_VARIATION_TRIGGER_FORMAT, v.experiment_id, v.variation_id, v.experiment_id,
|
40
|
+
tracking_only)
|
38
41
|
tracking_code.push(v_code)
|
39
42
|
end
|
40
43
|
end
|
@@ -24,6 +24,8 @@ require 'kameleoon/real_time/real_time_configuration_service'
|
|
24
24
|
require 'kameleoon/storage/cache_factory'
|
25
25
|
require 'kameleoon/targeting/models'
|
26
26
|
require 'kameleoon/targeting/targeting_manager'
|
27
|
+
require 'kameleoon/types/variable'
|
28
|
+
require 'kameleoon/types/variation'
|
27
29
|
require 'rufus/scheduler'
|
28
30
|
require 'yaml'
|
29
31
|
require 'json'
|
@@ -59,7 +61,7 @@ module Kameleoon
|
|
59
61
|
@visitor_manager = Kameleoon::DataManager::VisitorManager.new(
|
60
62
|
@data_manager, config.session_duration_second, @scheduler
|
61
63
|
)
|
62
|
-
@hybrid_manager = Hybrid::ManagerImpl.new(HYBRID_EXPIRATION_TIME)
|
64
|
+
@hybrid_manager = Hybrid::ManagerImpl.new(HYBRID_EXPIRATION_TIME, @data_manager)
|
63
65
|
@network_manager = Network::NetworkManager.new(
|
64
66
|
config.environment,
|
65
67
|
config.default_timeout_millisecond,
|
@@ -81,6 +83,7 @@ module Kameleoon
|
|
81
83
|
Logging::KameleoonLogger.log_level = Logging::LogLevel::INFO
|
82
84
|
end
|
83
85
|
|
86
|
+
ObjectSpace.define_finalizer(self, method(:dispose))
|
84
87
|
Logging::KameleoonLogger.info("RETURN: KameleoonClient.new(site_code: '%s', config: %s)",
|
85
88
|
site_code, config)
|
86
89
|
end
|
@@ -263,22 +266,31 @@ module Kameleoon
|
|
263
266
|
# @param [String] feature_key Key of the feature flag you want to expose to a user. This field is mandatory.
|
264
267
|
# @param [Bool] is_unique_identifier(DEPRECATED) Parameter that specifies whether the visitorCode is a unique
|
265
268
|
# identifier. This field is optional.
|
269
|
+
# @param [Bool] track Optional flag indicating whether tracking of the feature evaluation is enabled
|
270
|
+
# (`true`) or disabled (`false`); the default value is `true`.
|
271
|
+
#
|
272
|
+
# @return [Bool] If the user has not been associated with your feature flag before, the SDK returns
|
273
|
+
# a random boolean value (`true` if the user should have this feature or `false` if not).
|
266
274
|
#
|
267
275
|
# @raise [Kameleoon::Exception::FeatureNotFound] Feature Flag isn't found in this configuration
|
268
276
|
# @raise [Kameleoon::Exception::VisitorCodeInvalid] If the visitor code is empty or longer than 255 chars
|
269
277
|
#
|
270
|
-
def feature_active?(visitor_code, feature_key, is_unique_identifier: nil)
|
278
|
+
def feature_active?(visitor_code, feature_key, is_unique_identifier: nil, track: true)
|
271
279
|
Logging::KameleoonLogger.info(
|
272
|
-
"CALL: KameleoonClient.feature_active?(visitor_code: '%s', feature_key: '%s',
|
273
|
-
|
280
|
+
"CALL: KameleoonClient.feature_active?(visitor_code: '%s', feature_key: '%s', " \
|
281
|
+
'is_unique_identifier: %s, track: %s)',
|
282
|
+
visitor_code, feature_key, is_unique_identifier, track
|
274
283
|
)
|
275
284
|
Utils::VisitorCode.validate(visitor_code)
|
276
285
|
set_unique_identifier(visitor_code, is_unique_identifier) unless is_unique_identifier.nil?
|
277
|
-
|
286
|
+
feature_flag = @data_manager.data_file.get_feature_flag(feature_key)
|
287
|
+
variation_key, = get_variation_info(visitor_code, feature_flag, track)
|
278
288
|
feature_active = variation_key != Kameleoon::Configuration::VariationType::VARIATION_OFF
|
289
|
+
@tracking_manager.add_visitor_code(visitor_code) if track
|
279
290
|
Logging::KameleoonLogger.info(
|
280
|
-
"RETURN: KameleoonClient.feature_active?(visitor_code: '%s', feature_key: '%s',
|
281
|
-
|
291
|
+
"RETURN: KameleoonClient.feature_active?(visitor_code: '%s', feature_key: '%s', " \
|
292
|
+
'is_unique_identifier: %s, track: %s) -> (feature_active: %s)',
|
293
|
+
visitor_code, feature_key, is_unique_identifier, track, feature_active
|
282
294
|
)
|
283
295
|
feature_active
|
284
296
|
rescue Exception::FeatureEnvironmentDisabled
|
@@ -286,6 +298,82 @@ module Kameleoon
|
|
286
298
|
false
|
287
299
|
end
|
288
300
|
|
301
|
+
##
|
302
|
+
# Retrieves the variation assigned to the given visitor for a specific feature flag.
|
303
|
+
#
|
304
|
+
# @param [String] visitor_code The unique identifier of the visitor.
|
305
|
+
# @param [String] feature_key The unique identifier of the feature flag.
|
306
|
+
# @param [Bool] track Optional flag indicating whether tracking of the feature evaluation is enabled
|
307
|
+
# (`true`) or disabled (`false`); the default value is `true`.
|
308
|
+
#
|
309
|
+
# @return [Kameleoon::Types::Variation] The variation assigned to the visitor if the visitor is associated with some
|
310
|
+
# rule of the feature flag, otherwise the method returns the default variation of the feature flag.
|
311
|
+
#
|
312
|
+
# @raise [Kameleoon::Exception::VisitorCodeInvalid] If the visitor code is empty or longer than 255 chars.
|
313
|
+
# @raise [Kameleoon::Exception::FeatureNotFound] Feature Flag isn't found in this configuration.
|
314
|
+
# @raise [Kameleoon::Exception::FeatureEnvironmentDisabled] If the requested feature flag is disabled for
|
315
|
+
# the current environment.
|
316
|
+
def get_variation(visitor_code, feature_key, track: true)
|
317
|
+
Logging::KameleoonLogger.info(
|
318
|
+
"CALL: KameleoonClient.get_variation(visitor_code: '%s', feature_key: '%s', track: %s)",
|
319
|
+
visitor_code, feature_key, track
|
320
|
+
)
|
321
|
+
Utils::VisitorCode.validate(visitor_code)
|
322
|
+
feature_flag = @data_manager.data_file.get_feature_flag(feature_key)
|
323
|
+
variation_key, var_by_exp, rule = get_variation_info(visitor_code, feature_flag, track)
|
324
|
+
variation = feature_flag.get_variation_by_key(variation_key)
|
325
|
+
external_variation = make_external_variation(variation, var_by_exp&.variation_id, rule&.experiment_id)
|
326
|
+
@tracking_manager.add_visitor_code(visitor_code) if track
|
327
|
+
Logging::KameleoonLogger.info(
|
328
|
+
"RETURN: KameleoonClient.get_variation(visitor_code: '%s', feature_key: '%s', track: %s)" \
|
329
|
+
' -> (variation: %s)',
|
330
|
+
visitor_code, feature_key, track, external_variation
|
331
|
+
)
|
332
|
+
external_variation
|
333
|
+
end
|
334
|
+
|
335
|
+
##
|
336
|
+
# Forms a dictionary of variations assigned to a given visitor across all feature flags.
|
337
|
+
# This method iterates over all available feature flags and returns the assigned variation for each flag
|
338
|
+
# associated with the specified visitor.
|
339
|
+
#
|
340
|
+
# @param [String] visitor_code The unique identifier of the visitor.
|
341
|
+
# @param [Bool] only_active Optional flag indicating whether to return only variations for active feature
|
342
|
+
# flags (`true`) or for any feature flags (`false`); the default value is `false`.
|
343
|
+
# @param [Bool] track Optional flag indicating whether tracking of the feature evaluation is enabled
|
344
|
+
# (`true`) or disabled (`false`); the default value is `true`.
|
345
|
+
#
|
346
|
+
# @return [Hash] A hash consisting of feature flag keys as keys (`String`) and their corresponding
|
347
|
+
# variations (or the default variation of that feature flag) as values (`Kameleoon::Types::Variation`).
|
348
|
+
#
|
349
|
+
# @raise [Kameleoon::Exception::VisitorCodeInvalid] If the visitor code is empty or longer than 255 chars.
|
350
|
+
def get_variations(visitor_code, only_active: false, track: true)
|
351
|
+
Logging::KameleoonLogger.info(
|
352
|
+
"CALL: KameleoonClient.get_variations(visitor_code: '%s', only_active: %s, track: %s)",
|
353
|
+
visitor_code, only_active, track
|
354
|
+
)
|
355
|
+
Utils::VisitorCode.validate(visitor_code)
|
356
|
+
variations = {}
|
357
|
+
@data_manager.data_file.feature_flags.each_value do |feature_flag|
|
358
|
+
next unless feature_flag.environment_enabled
|
359
|
+
|
360
|
+
variation_key, var_by_exp, rule = get_variation_info(visitor_code, feature_flag, track)
|
361
|
+
next if only_active && (variation_key == Configuration::VariationType::VARIATION_OFF)
|
362
|
+
|
363
|
+
variation = feature_flag.get_variation_by_key(variation_key)
|
364
|
+
variations[feature_flag.feature_key] =
|
365
|
+
make_external_variation(variation, var_by_exp&.variation_id, rule&.experiment_id)
|
366
|
+
end
|
367
|
+
variations.freeze
|
368
|
+
@tracking_manager.add_visitor_code(visitor_code) if track
|
369
|
+
Logging::KameleoonLogger.info(
|
370
|
+
"RETURN: KameleoonClient.get_variations(visitor_code: '%s', only_active: %s, track: %s)" \
|
371
|
+
' -> (variations: %s)',
|
372
|
+
visitor_code, only_active, track, variations
|
373
|
+
)
|
374
|
+
variations
|
375
|
+
end
|
376
|
+
|
289
377
|
##
|
290
378
|
# get_feature_variation_key returns a variation key for visitor code
|
291
379
|
#
|
@@ -305,7 +393,12 @@ module Kameleoon
|
|
305
393
|
# @raise [Kameleoon::Exception::FeatureEnvironmentDisabled] If the requested feature flag is disabled for
|
306
394
|
# the current environment
|
307
395
|
#
|
396
|
+
# DEPRECATED. Please use `get_variation(visitor_code, feature_key, track: true)` instead.
|
308
397
|
def get_feature_variation_key(visitor_code, feature_key, is_unique_identifier: nil)
|
398
|
+
Logging::KameleoonLogger.info(
|
399
|
+
'[DEPRECATION] `get_feature_variation_key` is deprecated. ' \
|
400
|
+
'Please use `get_variation(visitor_code, feature_key, track: true)` instead.'
|
401
|
+
)
|
309
402
|
Logging::KameleoonLogger.info(
|
310
403
|
"CALL: KameleoonClient.get_feature_variation_key(visitor_code: '%s', feature_key: '%s', " \
|
311
404
|
'is_unique_identifier: %s)',
|
@@ -339,7 +432,12 @@ module Kameleoon
|
|
339
432
|
# @raise [Kameleoon::Exception::FeatureEnvironmentDisabled] If the requested feature flag is disabled for
|
340
433
|
# the current environment
|
341
434
|
#
|
435
|
+
# DEPRECATED. Please use `get_variation(visitor_code, feature_key, track: true)` instead.
|
342
436
|
def get_feature_variable(visitor_code, feature_key, variable_name, is_unique_identifier: nil)
|
437
|
+
Logging::KameleoonLogger.info(
|
438
|
+
'[DEPRECATION] `get_feature_variable` is deprecated. ' \
|
439
|
+
'Please use `get_variation(visitor_code, feature_key, track: true)` instead.'
|
440
|
+
)
|
343
441
|
Logging::KameleoonLogger.info(
|
344
442
|
"CALL: KameleoonClient.get_feature_variable(visitor_code: '%s', feature_key: '%s', variable_name: '%s', " \
|
345
443
|
'is_unique_identifier: %s)', visitor_code, feature_key, variable_name, is_unique_identifier
|
@@ -347,7 +445,7 @@ module Kameleoon
|
|
347
445
|
Utils::VisitorCode.validate(visitor_code)
|
348
446
|
set_unique_identifier(visitor_code, is_unique_identifier) unless is_unique_identifier.nil?
|
349
447
|
feature_flag, variation_key = _get_feature_variation_key(visitor_code, feature_key)
|
350
|
-
variation = feature_flag.
|
448
|
+
variation = feature_flag.get_variation_by_key(variation_key)
|
351
449
|
variable = variation&.get_variable_by_key(variable_name)
|
352
450
|
if variable.nil?
|
353
451
|
raise Exception::FeatureVariableNotFound.new(variable_name),
|
@@ -376,13 +474,18 @@ module Kameleoon
|
|
376
474
|
# @raise [Kameleoon::Exception::FeatureVariationNotFound]
|
377
475
|
# @raise [Kameleoon::Exception::FeatureEnvironmentDisabled]
|
378
476
|
#
|
477
|
+
# DEPRECATED. Please use `get_variation(visitor_code, feature_key, track: false)` instead.
|
379
478
|
def get_feature_variation_variables(feature_key, variation_key)
|
479
|
+
Logging::KameleoonLogger.info(
|
480
|
+
'[DEPRECATION] `get_feature_variation_variables` is deprecated. ' \
|
481
|
+
'Please use `get_variation(visitor_code, feature_key, track: false)` instead.'
|
482
|
+
)
|
380
483
|
Logging::KameleoonLogger.info(
|
381
484
|
"CALL: KameleoonClient.get_feature_variation_variables(feature_key: '%s', variation_key: '%s')",
|
382
485
|
feature_key, variation_key
|
383
486
|
)
|
384
487
|
feature_flag = @data_manager.data_file.get_feature_flag(feature_key)
|
385
|
-
variation = feature_flag.
|
488
|
+
variation = feature_flag.get_variation_by_key(variation_key)
|
386
489
|
if variation.nil?
|
387
490
|
raise Exception::FeatureVariationNotFound.new(variation_key),
|
388
491
|
"Variation key #{variation_key} not found"
|
@@ -508,7 +611,7 @@ module Kameleoon
|
|
508
611
|
#
|
509
612
|
# DEPRECATED. Please use `get_active_features` instead.
|
510
613
|
def get_active_feature_list_for_visitor(visitor_code)
|
511
|
-
Logging::KameleoonLogger.
|
614
|
+
Logging::KameleoonLogger.info('[DEPRECATION] `get_active_feature_list_for_visitor` is deprecated.' \
|
512
615
|
' Please use `get_active_features` instead.')
|
513
616
|
Logging::KameleoonLogger.info("CALL: KameleoonClient.get_active_feature_list_for_visitor(visitor_code: '%s')",
|
514
617
|
visitor_code)
|
@@ -537,7 +640,13 @@ module Kameleoon
|
|
537
640
|
# @raise [Kameleoon::Exception::VisitorCodeInvalid] If the visitor code is empty or longer than 255 chars or is nil
|
538
641
|
#
|
539
642
|
# @return [Hash] Hash of active features for a visitor
|
643
|
+
#
|
644
|
+
# DEPRECATED. Please use `get_variations(visitor_code, only_active: true, track: false)` instead.
|
540
645
|
def get_active_features(visitor_code)
|
646
|
+
Logging::KameleoonLogger.info(
|
647
|
+
'[DEPRECATION] `get_active_features` is deprecated. ' \
|
648
|
+
'Please use `get_variations(visitor_code, only_active: true, track: false)` instead.'
|
649
|
+
)
|
541
650
|
Logging::KameleoonLogger.info("CALL: KameleoonClient.get_active_features(visitor_code: '%s')", visitor_code)
|
542
651
|
Utils::VisitorCode.validate(visitor_code)
|
543
652
|
map_active_features = {}
|
@@ -550,24 +659,9 @@ module Kameleoon
|
|
550
659
|
|
551
660
|
next if variation_key == Configuration::VariationType::VARIATION_OFF
|
552
661
|
|
553
|
-
variation = feature_flag.
|
554
|
-
|
555
|
-
|
556
|
-
variation&.variables&.each do |variable|
|
557
|
-
variables[variable.key] = Kameleoon::Types::Variable.new(
|
558
|
-
variable.key,
|
559
|
-
variable.type,
|
560
|
-
_parse_feature_variable(variable)
|
561
|
-
)
|
562
|
-
end
|
563
|
-
|
564
|
-
variables.freeze
|
565
|
-
map_active_features[feature_flag.feature_key] = Kameleoon::Types::Variation.new(
|
566
|
-
variation_key,
|
567
|
-
var_by_exp ? var_by_exp.variation_id : nil,
|
568
|
-
rule ? rule.experiment_id : nil,
|
569
|
-
variables
|
570
|
-
)
|
662
|
+
variation = feature_flag.get_variation_by_key(variation_key)
|
663
|
+
map_active_features[feature_flag.feature_key] =
|
664
|
+
make_external_variation(variation, var_by_exp&.variation_id, rule&.experiment_id)
|
571
665
|
end
|
572
666
|
|
573
667
|
map_active_features.freeze
|
@@ -754,6 +848,22 @@ module Kameleoon
|
|
754
848
|
@targeting_manager.check_targeting(visitor_code, campaign_id, exp_ff_rule)
|
755
849
|
end
|
756
850
|
|
851
|
+
def get_variation_info(visitor_code, feature_flag, track)
|
852
|
+
Logging::KameleoonLogger.debug(
|
853
|
+
"CALL: KameleoonClient.get_variation_info(visitor_code: '%s', feature_flag: %s, track: %s)",
|
854
|
+
visitor_code, feature_flag, track
|
855
|
+
)
|
856
|
+
var_by_exp, rule = _calculate_variation_key_for_feature(visitor_code, feature_flag)
|
857
|
+
variation_key = _get_variation_key(var_by_exp, rule, feature_flag)
|
858
|
+
save_variation(visitor_code, rule, var_by_exp, track: track)
|
859
|
+
Logging::KameleoonLogger.debug(
|
860
|
+
"RETURN: KameleoonClient.get_variation_info(visitor_code: '%s', feature_flag: %s, track: %s)" \
|
861
|
+
' -> (variation_key: %s, variation_by_exposition: %s, rule: %s)',
|
862
|
+
visitor_code, feature_flag, track, variation_key, var_by_exp, rule
|
863
|
+
)
|
864
|
+
[variation_key, var_by_exp, rule]
|
865
|
+
end
|
866
|
+
|
757
867
|
##
|
758
868
|
# helper method for getting variation key for feature flag
|
759
869
|
def _get_feature_variation_key(visitor_code, feature_key)
|
@@ -764,16 +874,7 @@ module Kameleoon
|
|
764
874
|
feature_flag = @data_manager.data_file.get_feature_flag(feature_key)
|
765
875
|
variation, rule = _calculate_variation_key_for_feature(visitor_code, feature_flag)
|
766
876
|
variation_key = _get_variation_key(variation, rule, feature_flag)
|
767
|
-
|
768
|
-
unless rule.nil?
|
769
|
-
experiment_id = rule.experiment_id
|
770
|
-
variation_id = variation.variation_id unless variation.nil?
|
771
|
-
visitor = @visitor_manager.get_or_create_visitor(visitor_code)
|
772
|
-
unless experiment_id.nil? || variation_id.nil?
|
773
|
-
as_variation = Kameleoon::DataManager::AssignedVariation.new(experiment_id, variation_id, rule.type)
|
774
|
-
visitor.assign_variation(as_variation)
|
775
|
-
end
|
776
|
-
end
|
877
|
+
save_variation(visitor_code, rule, variation)
|
777
878
|
@tracking_manager.add_visitor_code(visitor_code)
|
778
879
|
Logging::KameleoonLogger.debug(
|
779
880
|
"RETURN: KameleoonClient._get_feature_variation_key(visitor_code: '%s', feature_key: '%s')" \
|
@@ -783,6 +884,25 @@ module Kameleoon
|
|
783
884
|
[feature_flag, variation_key]
|
784
885
|
end
|
785
886
|
|
887
|
+
def save_variation(visitor_code, rule, var_by_exp, track: true)
|
888
|
+
experiment_id = rule&.experiment_id
|
889
|
+
variation_id = var_by_exp&.variation_id
|
890
|
+
return if experiment_id.nil? || variation_id.nil?
|
891
|
+
|
892
|
+
Logging::KameleoonLogger.debug(
|
893
|
+
"CALL: KameleoonClient.save_variation(visitor_code: '%s', rule: %s, var_by_exp: %s, track: %s)",
|
894
|
+
visitor_code, rule, var_by_exp, track
|
895
|
+
)
|
896
|
+
visitor = @visitor_manager.get_or_create_visitor(visitor_code)
|
897
|
+
as_variation = Kameleoon::DataManager::AssignedVariation.new(experiment_id, variation_id, rule.type)
|
898
|
+
as_variation.mark_as_sent unless track
|
899
|
+
visitor.assign_variation(as_variation)
|
900
|
+
Logging::KameleoonLogger.debug(
|
901
|
+
"RETURN: KameleoonClient.save_variation(visitor_code: '%s', rule: %s, var_by_exp: %s, track: %s)",
|
902
|
+
visitor_code, rule, var_by_exp, track
|
903
|
+
)
|
904
|
+
end
|
905
|
+
|
786
906
|
##
|
787
907
|
# helper method for calculate variation key for feature flag
|
788
908
|
def _calculate_variation_key_for_feature(visitor_code, feature_flag)
|
@@ -845,22 +965,47 @@ module Kameleoon
|
|
845
965
|
feature_flag.default_variation_key
|
846
966
|
end
|
847
967
|
|
968
|
+
def make_external_variation(internal_variation, variation_id, experiment_id)
|
969
|
+
Logging::KameleoonLogger.debug(
|
970
|
+
'CALL: KameleoonClient.make_external_variation(internal_variation: %s, variation_id: %s, experiment_id: %s)',
|
971
|
+
internal_variation, variation_id, experiment_id
|
972
|
+
)
|
973
|
+
variables = {}
|
974
|
+
internal_variation&.variables&.each do |variable|
|
975
|
+
variables[variable.key] = Types::Variable.new(
|
976
|
+
variable.key,
|
977
|
+
variable.type,
|
978
|
+
_parse_feature_variable(variable)
|
979
|
+
)
|
980
|
+
end
|
981
|
+
variables.freeze
|
982
|
+
variation = Types::Variation.new(internal_variation&.key, variation_id, experiment_id, variables)
|
983
|
+
Logging::KameleoonLogger.debug(
|
984
|
+
'RETURN: KameleoonClient.make_external_variation(internal_variation: %s, variation_id: %s, experiment_id: %s)' \
|
985
|
+
' -> (variation: %s)',
|
986
|
+
internal_variation, variation_id, experiment_id, variation
|
987
|
+
)
|
988
|
+
variation
|
989
|
+
end
|
990
|
+
|
848
991
|
##
|
849
992
|
# helper method for fetching values from a Variable
|
850
993
|
def _parse_feature_variable(variable)
|
851
994
|
case variable.type
|
852
|
-
when 'BOOLEAN', 'STRING', 'NUMBER'
|
995
|
+
when 'BOOLEAN', 'STRING', 'NUMBER', 'JS', 'CSS'
|
853
996
|
variable.value
|
854
997
|
when 'JSON'
|
855
998
|
JSON.parse(variable.value)
|
856
999
|
else
|
857
|
-
|
858
|
-
|
1000
|
+
Logging::KameleoonLogger.error("Unknown type '#{variable.type}' for feature variable")
|
1001
|
+
variable.value
|
859
1002
|
end
|
860
1003
|
end
|
861
1004
|
|
862
1005
|
def set_unique_identifier(visitor_code, is_unique_identifier)
|
863
|
-
Logging::KameleoonLogger.
|
1006
|
+
Logging::KameleoonLogger.info(
|
1007
|
+
"The 'isUniqueIdentifier' parameter is deprecated. Please, add 'UniqueIdentifier' to a visitor instead."
|
1008
|
+
)
|
864
1009
|
@visitor_manager.add_data(visitor_code, UniqueIdentifier.new(is_unique_identifier))
|
865
1010
|
end
|
866
1011
|
end
|
@@ -113,7 +113,7 @@ module Kameleoon
|
|
113
113
|
'Setting top level domain is strictly recommended, otherwise you may have problems when using subdomains.'
|
114
114
|
)
|
115
115
|
end
|
116
|
-
@top_level_domain = top_level_domain
|
116
|
+
@top_level_domain = Utils::Domain.validate_top_level_domain(top_level_domain)
|
117
117
|
end
|
118
118
|
|
119
119
|
def self.read_from_yaml(path)
|
@@ -16,18 +16,18 @@ module Kameleoon
|
|
16
16
|
@container = Container.new(value)
|
17
17
|
end
|
18
18
|
|
19
|
-
def
|
20
|
-
@container.
|
19
|
+
def visitor_code_managed?
|
20
|
+
@container.visitor_code_managed
|
21
21
|
end
|
22
22
|
|
23
23
|
class Container
|
24
|
-
attr_reader :data_file, :
|
24
|
+
attr_reader :data_file, :visitor_code_managed
|
25
25
|
|
26
26
|
def initialize(data_file)
|
27
27
|
@data_file = data_file
|
28
28
|
# Regarding GDPR policy we should set visitorCode if legal consent isn't required or we have at
|
29
29
|
# least one Targeted Delivery rule in datafile
|
30
|
-
@
|
30
|
+
@visitor_code_managed = data_file.settings.is_consent_required && !data_file.has_any_targeted_delivery_rule
|
31
31
|
end
|
32
32
|
end
|
33
33
|
end
|
@@ -42,12 +42,20 @@ module Kameleoon
|
|
42
42
|
filter = Types::RemoteVisitorDataFilter.new unless filter.is_a?(Types::RemoteVisitorDataFilter)
|
43
43
|
is_unique_identifier = @visitor_manger.get_visitor(visitor_code)&.is_unique_identifier || false
|
44
44
|
response = @network_manager.get_remote_visitor_data(visitor_code, filter, is_unique_identifier, timeout)
|
45
|
-
|
45
|
+
remote_visitor_data = parse_custom_data_array(visitor_code, response)
|
46
|
+
remote_visitor_data.mark_data_as_sent(@data_manager.data_file.custom_data_info)
|
47
|
+
data_to_add = remote_visitor_data.collect_data_to_add
|
46
48
|
if add_data && !data_to_add.empty?
|
47
49
|
# Cannot use `VisitorManager.add_data` because it could use remote visitor data for mapping.
|
48
50
|
visitor = @visitor_manger.get_or_create_visitor(visitor_code)
|
49
51
|
visitor.add_data(*data_to_add, overwrite: false)
|
50
52
|
end
|
53
|
+
if filter.visitor_code && !remote_visitor_data.visitor_code.nil?
|
54
|
+
# We apply visitor code from the latest visit fetched from Data API
|
55
|
+
visitor = @visitor_manger.get_or_create_visitor(visitor_code)
|
56
|
+
visitor.mapping_identifier = remote_visitor_data.visitor_code
|
57
|
+
end
|
58
|
+
data_to_return = remote_visitor_data.collect_data_to_return
|
51
59
|
Logging::KameleoonLogger.debug(
|
52
60
|
"RETURN: RemoteDataManager.get_visitor_data(visitor_code: '%s', add_data: %s, filter: %s," \
|
53
61
|
' timeout: %s) -> (visitor_data: %s)',
|
@@ -59,9 +67,7 @@ module Kameleoon
|
|
59
67
|
##
|
60
68
|
# helper method used by `get_remote_visitor_data`
|
61
69
|
def parse_custom_data_array(visitor_code, response)
|
62
|
-
|
63
|
-
remote_visitor_data.mark_data_as_sent(@data_manager.data_file.custom_data_info)
|
64
|
-
[remote_visitor_data.collect_data_to_add, remote_visitor_data.collect_data_to_return]
|
70
|
+
RemoteVisitorData.new(JSON.parse(response))
|
65
71
|
rescue StandardError => e
|
66
72
|
Logging::KameleoonLogger.error("Parsing of remote visitor data of '#{visitor_code}' failed: #{e}")
|
67
73
|
raise
|
@@ -16,7 +16,7 @@ module Kameleoon
|
|
16
16
|
module RemoteData
|
17
17
|
class RemoteVisitorData
|
18
18
|
attr_reader :custom_data_dict, :page_view_visits, :conversions, :experiments, :device, :browser,
|
19
|
-
:operating_system, :geolocation, :previous_visitor_visits, :kcs_heat
|
19
|
+
:operating_system, :geolocation, :previous_visitor_visits, :kcs_heat, :visitor_code
|
20
20
|
|
21
21
|
def initialize(hash)
|
22
22
|
current_visit = hash['currentVisit']
|
@@ -68,18 +68,20 @@ module Kameleoon
|
|
68
68
|
private
|
69
69
|
|
70
70
|
def parse_visit(hash)
|
71
|
+
@visitor_code = hash['visitorCode'] if @visitor_code.nil?
|
71
72
|
custom_data_events = hash['customDataEvents']
|
72
|
-
parse_custom_data(custom_data_events) if custom_data_events
|
73
|
+
parse_custom_data(custom_data_events) if !custom_data_events.nil? && custom_data_events.size.positive?
|
73
74
|
page_events = hash['pageEvents']
|
74
|
-
parse_pages(page_events) if page_events
|
75
|
+
parse_pages(page_events) if !page_events.nil? && page_events.size.positive?
|
75
76
|
experiment_events = hash['experimentEvents']
|
76
|
-
parse_experiments(experiment_events) if experiment_events
|
77
|
+
parse_experiments(experiment_events) if !experiment_events.nil? && experiment_events.size.positive?
|
77
78
|
conversion_events = hash['conversionEvents']
|
78
|
-
parse_conversions(conversion_events) if conversion_events
|
79
|
+
parse_conversions(conversion_events) if !conversion_events.nil? && conversion_events.size.positive?
|
79
80
|
geolocation_events = hash['geolocationEvents']
|
80
|
-
@geolocation = parse_geolocation(geolocation_events) if @geolocation.nil? && geolocation_events
|
81
|
+
@geolocation = parse_geolocation(geolocation_events) if @geolocation.nil? && !geolocation_events.nil? && \
|
82
|
+
geolocation_events.size.positive?
|
81
83
|
static_data_events = hash['staticDataEvent']
|
82
|
-
parse_static_data(static_data_events)
|
84
|
+
parse_static_data(static_data_events) unless static_data_events.nil?
|
83
85
|
end
|
84
86
|
|
85
87
|
def parse_custom_data(custom_data_events)
|
@@ -80,12 +80,13 @@ module Kameleoon
|
|
80
80
|
Thread.new do
|
81
81
|
result = @network_manager.send_tracking_data(lines)
|
82
82
|
if result != false
|
83
|
-
Logging::KameleoonLogger.
|
84
|
-
|
83
|
+
Logging::KameleoonLogger.info('Successful request for tracking visitors: %s, data: %s',
|
84
|
+
visitor_codes, visitor_data)
|
85
85
|
visitor_data.each { |d| d.mark_as_sent if d.is_a?(Kameleoon::Data) }
|
86
86
|
else
|
87
|
-
Logging::KameleoonLogger.
|
88
|
-
|
87
|
+
Logging::KameleoonLogger.error('Tracking request failed')
|
88
|
+
Logging::KameleoonLogger.info('Failed request for tracking visitors: %s, data: %s',
|
89
|
+
visitor_codes, visitor_data)
|
89
90
|
visitor_data.each { |d| d.mark_as_unsent if d.is_a?(Kameleoon::Data) }
|
90
91
|
@tracking_visitors.add_all(visitor_codes)
|
91
92
|
end
|
@@ -31,7 +31,7 @@ module Kameleoon
|
|
31
31
|
Utils::VisitorCode.validate(visitor_code)
|
32
32
|
Logging::KameleoonLogger.debug("Read visitor code '%s' from cookies %s", visitor_code, cookies)
|
33
33
|
# Remove adding cookies when we will be sure that it doesn't break anything
|
34
|
-
add(visitor_code, cookies) unless @data_manager.
|
34
|
+
add(visitor_code, cookies) unless @data_manager.visitor_code_managed?
|
35
35
|
Logging::KameleoonLogger.debug(
|
36
36
|
"RETURN: CookieManager.get_or_add(cookies: %s, default_visitor_code: '%s') -> (visitor_code: '%s')",
|
37
37
|
cookies, default_visitor_code, visitor_code
|
@@ -42,7 +42,7 @@ module Kameleoon
|
|
42
42
|
if default_visitor_code.nil?
|
43
43
|
visitor_code = Utils::VisitorCode.generate
|
44
44
|
Logging::KameleoonLogger.debug("Generated new visitor code '%s'", visitor_code)
|
45
|
-
add(visitor_code, cookies) unless @data_manager.
|
45
|
+
add(visitor_code, cookies) unless @data_manager.visitor_code_managed?
|
46
46
|
Logging::KameleoonLogger.debug(
|
47
47
|
"RETURN: CookieManager.get_or_add(cookies: %s, default_visitor_code: '%s') -> (visitor_code: '%s')",
|
48
48
|
cookies, default_visitor_code, visitor_code
|
@@ -56,7 +56,8 @@ module Kameleoon
|
|
56
56
|
add(visitor_code, cookies)
|
57
57
|
Logging::KameleoonLogger.debug(
|
58
58
|
"RETURN: CookieManager.get_or_add(cookies: %s, default_visitor_code: '%s') -> (visitor_code: '%s')",
|
59
|
-
cookies, default_visitor_code, visitor_code
|
59
|
+
cookies, default_visitor_code, visitor_code
|
60
|
+
)
|
60
61
|
visitor_code
|
61
62
|
end
|
62
63
|
|
@@ -72,7 +73,7 @@ module Kameleoon
|
|
72
73
|
remove(cookies)
|
73
74
|
end
|
74
75
|
Logging::KameleoonLogger.debug("RETURN: CookieManager.update(visitor_code: '%s', consent: %s, cookies: %s)",
|
75
|
-
|
76
|
+
visitor_code, consent, cookies)
|
76
77
|
end
|
77
78
|
|
78
79
|
private
|
@@ -88,13 +89,13 @@ module Kameleoon
|
|
88
89
|
}
|
89
90
|
cookies[VISITOR_CODE_COOKIE] = cookie
|
90
91
|
Logging::KameleoonLogger.debug("RETURN: CookieManager.add(visitor_code: '%s', cookies: %s)",
|
91
|
-
|
92
|
+
visitor_code, cookies)
|
92
93
|
cookies
|
93
94
|
end
|
94
95
|
|
95
96
|
def remove(cookies)
|
96
97
|
Logging::KameleoonLogger.debug('CALL: CookieManager.remove(cookies: %s)', cookies)
|
97
|
-
cookies[VISITOR_CODE_COOKIE] = nil if @data_manager.
|
98
|
+
cookies[VISITOR_CODE_COOKIE] = nil if @data_manager.visitor_code_managed?
|
98
99
|
Logging::KameleoonLogger.debug('RETURN: CookieManager.remove(cookies: %s)', cookies)
|
99
100
|
cookies
|
100
101
|
end
|
@@ -88,11 +88,13 @@ module Kameleoon
|
|
88
88
|
if response.success?
|
89
89
|
success = true
|
90
90
|
elsif !response.error.nil?
|
91
|
-
|
92
|
-
|
91
|
+
log_level = attempt < retry_limit ? Logging::LogLevel::WARNING : Logging::LogLevel::ERROR
|
92
|
+
Logging::KameleoonLogger.log(log_level, "%s call '%s' failed: Error occurred during request: %s",
|
93
|
+
request.method, request.url, response.error)
|
93
94
|
else
|
94
|
-
|
95
|
-
|
95
|
+
log_level = attempt < retry_limit ? Logging::LogLevel::WARNING : Logging::LogLevel::ERROR
|
96
|
+
Logging::KameleoonLogger.log(log_level, "%s call '%s' failed: Received unexpected status code '%s'",
|
97
|
+
request.method, request.url, response.code)
|
96
98
|
if response.code == 401 && request.access_token
|
97
99
|
Logging::KameleoonLogger.warning("Unexpected rejection of access token '#{request.access_token}'")
|
98
100
|
@access_token_source.discard_token(request.access_token)
|
@@ -108,7 +110,6 @@ module Kameleoon
|
|
108
110
|
attempt += 1
|
109
111
|
end
|
110
112
|
Logging::KameleoonLogger.debug('Fetched response %s for request %s', response, request)
|
111
|
-
Logging::KameleoonLogger.error("Failed %s request '%s'", request.method, request.url) unless success
|
112
113
|
success ? response.body : false
|
113
114
|
end
|
114
115
|
|
@@ -19,7 +19,7 @@ module Kameleoon
|
|
19
19
|
DEFAULT_DATA_API_DOMAIN = 'data.kameleoon.io'
|
20
20
|
TEST_DATA_API_DOMAIN = 'data.kameleoon.net'
|
21
21
|
DEFAULT_AUTOMATION_API_DOMAIN = 'api.kameleoon.com'
|
22
|
-
TEST_AUTOMATION_API_DOMAIN = 'api.
|
22
|
+
TEST_AUTOMATION_API_DOMAIN = 'api.kameleoon.net'
|
23
23
|
|
24
24
|
attr_reader :site_code, :data_api_domain, :automation_api_domain
|
25
25
|
|
@@ -13,15 +13,17 @@ module Kameleoon
|
|
13
13
|
super(json_condition, json_condition['title'])
|
14
14
|
end
|
15
15
|
|
16
|
-
def check(
|
17
|
-
return false unless
|
16
|
+
def check(page_view_visits)
|
17
|
+
return false unless page_view_visits.is_a?(Kameleoon::DataManager::DataMapStorage)
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
latest = nil
|
20
|
+
page_view_visits.enumerate do |visit|
|
21
|
+
if visit.is_a?(Kameleoon::DataManager::PageViewVisit) \
|
22
|
+
&& (latest.nil? || visit.last_timestamp > latest.last_timestamp)
|
23
|
+
latest = visit
|
24
|
+
end
|
23
25
|
end
|
24
|
-
|
26
|
+
!latest.nil? && latest.is_a?(Kameleoon::DataManager::PageViewVisit) && check_targeting(latest.page_view.title)
|
25
27
|
end
|
26
28
|
end
|
27
29
|
end
|
@@ -13,22 +13,17 @@ module Kameleoon
|
|
13
13
|
super(json_condition, json_condition['url'])
|
14
14
|
end
|
15
15
|
|
16
|
-
def check(
|
17
|
-
return false unless
|
18
|
-
return !page_view_visit_storage.get(condition_value).nil? if operator == Operator::EXACT
|
16
|
+
def check(page_view_visits)
|
17
|
+
return false unless page_view_visits.is_a?(Kameleoon::DataManager::DataMapStorage)
|
19
18
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
19
|
+
latest = nil
|
20
|
+
page_view_visits.enumerate do |visit|
|
21
|
+
if visit.is_a?(Kameleoon::DataManager::PageViewVisit) \
|
22
|
+
&& (latest.nil? || visit.last_timestamp > latest.last_timestamp)
|
23
|
+
latest = visit
|
24
|
+
end
|
24
25
|
end
|
25
|
-
|
26
|
-
end
|
27
|
-
|
28
|
-
private
|
29
|
-
|
30
|
-
def check_page_view_visit(visit)
|
31
|
-
visit.is_a?(Kameleoon::DataManager::PageViewVisit) && check_targeting(visit.page_view.url)
|
26
|
+
!latest.nil? && latest.is_a?(Kameleoon::DataManager::PageViewVisit) && check_targeting(latest.page_view.url)
|
32
27
|
end
|
33
28
|
end
|
34
29
|
end
|
@@ -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
|
8
|
+
:operating_system, :conversions, :experiments, :kcs, :visitor_code
|
9
9
|
|
10
10
|
def to_s
|
11
11
|
"RemoteVisitorDataFilter{previous_visit_amount:#{@previous_visit_amount}," \
|
@@ -17,13 +17,15 @@ module Kameleoon
|
|
17
17
|
"browser:#{@browser}," \
|
18
18
|
"operating_system:#{@operating_system}," \
|
19
19
|
"conversions:#{@conversions}," \
|
20
|
-
"experiments:#{@experiments},
|
20
|
+
"experiments:#{@experiments}," \
|
21
|
+
"kcs:#{@kcs}," \
|
22
|
+
"visitor_code:#{@visitor_code}}"
|
21
23
|
end
|
22
24
|
|
23
25
|
def initialize(
|
24
26
|
previous_visit_amount: 1, current_visit: true, custom_data: true, page_views: false,
|
25
27
|
geolocation: false, device: false, browser: false, operating_system: false, conversions: false,
|
26
|
-
experiments: false, kcs: false
|
28
|
+
experiments: false, kcs: false, visitor_code: true
|
27
29
|
)
|
28
30
|
@previous_visit_amount = previous_visit_amount
|
29
31
|
@current_visit = current_visit
|
@@ -36,6 +38,7 @@ module Kameleoon
|
|
36
38
|
@conversions = conversions
|
37
39
|
@experiments = experiments
|
38
40
|
@kcs = kcs
|
41
|
+
@visitor_code = visitor_code
|
39
42
|
end
|
40
43
|
end
|
41
44
|
end
|
data/lib/kameleoon/utils.rb
CHANGED
@@ -4,6 +4,7 @@ require 'fiber'
|
|
4
4
|
require 'bigdecimal'
|
5
5
|
require 'kameleoon/utils'
|
6
6
|
require 'kameleoon/exceptions'
|
7
|
+
require 'kameleoon/logging/kameleoon_logger'
|
7
8
|
|
8
9
|
module Kameleoon
|
9
10
|
# Utils is a helper module for project
|
@@ -68,5 +69,35 @@ module Kameleoon
|
|
68
69
|
secret[0, length - hidden_length] + hid_ch * hidden_length
|
69
70
|
end
|
70
71
|
end
|
72
|
+
|
73
|
+
module Domain
|
74
|
+
HTTP = 'http://'
|
75
|
+
HTTPS = 'https://'
|
76
|
+
REGEX_DOMAIN = /^(\.?(([a-zA-Z\d][a-zA-Z\d-]*[a-zA-Z\d])|[a-zA-Z\d]))
|
77
|
+
(\.(([a-zA-Z\d][a-zA-Z\d-]*[a-zA-Z\d])|[a-zA-Z\d])){1,126}$/x.freeze
|
78
|
+
|
79
|
+
def self.validate_top_level_domain(top_level_domain)
|
80
|
+
return nil if top_level_domain.nil? || top_level_domain.empty?
|
81
|
+
|
82
|
+
top_level_domain = top_level_domain.downcase
|
83
|
+
|
84
|
+
[HTTP, HTTPS].each do |protocol|
|
85
|
+
next unless top_level_domain.start_with?(protocol)
|
86
|
+
|
87
|
+
top_level_domain = top_level_domain[protocol.length..]
|
88
|
+
Logging::KameleoonLogger.warning(
|
89
|
+
"The top-level domain contains '%s'. Domain after protocol trimming: '%s'", protocol, top_level_domain
|
90
|
+
)
|
91
|
+
break
|
92
|
+
end
|
93
|
+
|
94
|
+
unless REGEX_DOMAIN.match?(top_level_domain)
|
95
|
+
Logging::KameleoonLogger.error("The top-level domain '%s' is invalid.", top_level_domain)
|
96
|
+
return nil
|
97
|
+
end
|
98
|
+
|
99
|
+
top_level_domain
|
100
|
+
end
|
101
|
+
end
|
71
102
|
end
|
72
103
|
end
|
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.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kameleoon
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-11-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: em-http-request
|