kameleoon-client-ruby 3.16.2 → 3.17.1
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 +5 -1
- data/lib/kameleoon/configuration/settings.rb +27 -1
- data/lib/kameleoon/configuration/variation.rb +2 -1
- data/lib/kameleoon/data/manager/legal_consent.rb +11 -0
- data/lib/kameleoon/data/manager/visitor.rb +2 -1
- data/lib/kameleoon/exceptions.rb +0 -4
- data/lib/kameleoon/kameleoon_client.rb +105 -8
- data/lib/kameleoon/managers/remote_data/remote_visitor_data.rb +9 -8
- data/lib/kameleoon/managers/tracking/tracking_builder.rb +3 -1
- data/lib/kameleoon/network/cookie/cookie_manager.rb +8 -18
- data/lib/kameleoon/network/net_provider.rb +16 -0
- data/lib/kameleoon/network/request.rb +4 -0
- data/lib/kameleoon/targeting/condition_factory.rb +3 -1
- data/lib/kameleoon/types/data_file.rb +19 -0
- data/lib/kameleoon/types/feature_flag.rb +26 -0
- data/lib/kameleoon/types/remote_visitor_data_filter.rb +0 -1
- data/lib/kameleoon/types/rule.rb +19 -0
- data/lib/kameleoon/types/variable.rb +1 -1
- data/lib/kameleoon/types/variation.rb +5 -4
- 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: 7fc2b3610def24ae9ceb3a3e11f8a1e6e360c12359631c47c1af18e7bdd67a2b
|
|
4
|
+
data.tar.gz: ebe8a7cd7920d0522c8cde5f09e02db0050b3ccbd81fe47ffde2452c1c40c136
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2f4ec5f9d42e0260ad0646a837654c412b15e42583763992ab7df04167357e4d670874cfad5abfb017212cbcce224cef5828e4f7df10ae94305ee7efa1eb36ec
|
|
7
|
+
data.tar.gz: 2c562cccbdf690902f653fc13b961a3197ef493be9886253842e369943c2935d90fc50bac9e5aba98a4c1bff0171db1a6a663bf14c1b169a19bd418936d59f80
|
|
@@ -46,8 +46,12 @@ module Kameleoon
|
|
|
46
46
|
def get_feature_flag(feature_key)
|
|
47
47
|
ff = @feature_flags[feature_key]
|
|
48
48
|
raise Exception::FeatureNotFound, feature_key if ff.nil?
|
|
49
|
-
raise Exception::FeatureEnvironmentDisabled.new(feature_key, @environment) unless ff.environment_enabled
|
|
50
49
|
|
|
50
|
+
unless ff.environment_enabled
|
|
51
|
+
env = @environment.nil? ? 'default' : "'#{@environment}'"
|
|
52
|
+
msg = "Feature '#{feature_key}' is disabled for #{env} environment'"
|
|
53
|
+
raise Exception::FeatureEnvironmentDisabled, msg
|
|
54
|
+
end
|
|
51
55
|
ff
|
|
52
56
|
end
|
|
53
57
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'kameleoon/logging/kameleoon_logger'
|
|
4
|
+
|
|
3
5
|
module Kameleoon
|
|
4
6
|
# Module which contains all internal data of SDK
|
|
5
7
|
module Configuration
|
|
@@ -7,7 +9,7 @@ module Kameleoon
|
|
|
7
9
|
# state of real time update for site code and etc
|
|
8
10
|
class Settings
|
|
9
11
|
attr_accessor :real_time_update
|
|
10
|
-
attr_reader :is_consent_required, :data_api_domain
|
|
12
|
+
attr_reader :is_consent_required, :blocking_behaviour_if_consent_not_given, :data_api_domain
|
|
11
13
|
|
|
12
14
|
def to_s
|
|
13
15
|
"Settings{real_time_update:#{@real_time_update},is_consent_required:#{@is_consent_required}," \
|
|
@@ -18,13 +20,37 @@ module Kameleoon
|
|
|
18
20
|
if configuration.nil?
|
|
19
21
|
@real_time_update = false
|
|
20
22
|
@is_consent_required = false
|
|
23
|
+
@blocking_behaviour_if_consent_not_given = ConsentBlockingBehaviour::PARTIALLY_BLOCKED
|
|
21
24
|
@data_api_domain = nil
|
|
22
25
|
else
|
|
23
26
|
@real_time_update = configuration['realTimeUpdate'] || false
|
|
24
27
|
@is_consent_required = configuration['consentType'] == 'REQUIRED'
|
|
28
|
+
@blocking_behaviour_if_consent_not_given =
|
|
29
|
+
ConsentBlockingBehaviour.from_str(configuration['consentOptOutBehavior'])
|
|
25
30
|
@data_api_domain = configuration['dataApiDomain']
|
|
26
31
|
end
|
|
27
32
|
end
|
|
28
33
|
end
|
|
34
|
+
|
|
35
|
+
# ConsentBlockingBehaviour
|
|
36
|
+
module ConsentBlockingBehaviour
|
|
37
|
+
PARTIALLY_BLOCKED = 0
|
|
38
|
+
COMPLETELY_BLOCKED = 1
|
|
39
|
+
|
|
40
|
+
PARTIALLY_BLOCKED_STR = 'PARTIALLY_BLOCK'
|
|
41
|
+
COMPLETELY_BLOCKED_STR = 'FULLY_BLOCK'
|
|
42
|
+
|
|
43
|
+
def self.from_str(str)
|
|
44
|
+
case str
|
|
45
|
+
when PARTIALLY_BLOCKED_STR
|
|
46
|
+
PARTIALLY_BLOCKED
|
|
47
|
+
when COMPLETELY_BLOCKED_STR
|
|
48
|
+
COMPLETELY_BLOCKED
|
|
49
|
+
else
|
|
50
|
+
Logging::KameleoonLogger.warning("Unexpected consent blocking type '%s'", str)
|
|
51
|
+
PARTIALLY_BLOCKED
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
29
55
|
end
|
|
30
56
|
end
|
|
@@ -12,7 +12,7 @@ module Kameleoon
|
|
|
12
12
|
|
|
13
13
|
# Variation of feature flag
|
|
14
14
|
class Variation
|
|
15
|
-
|
|
15
|
+
attr_reader :key, :variables, :name
|
|
16
16
|
|
|
17
17
|
def self.create_from_array(array)
|
|
18
18
|
array&.map { |it| Variation.new(it) }
|
|
@@ -21,6 +21,7 @@ module Kameleoon
|
|
|
21
21
|
def initialize(hash)
|
|
22
22
|
@key = hash['key']
|
|
23
23
|
@variables = Variable.create_from_array(hash['variables'])
|
|
24
|
+
@name = hash['name'] || ''
|
|
24
25
|
end
|
|
25
26
|
|
|
26
27
|
def get_variable_by_key(key)
|
|
@@ -18,6 +18,7 @@ require 'kameleoon/data/manager/data_array_storage'
|
|
|
18
18
|
require 'kameleoon/data/manager/data_map_storage'
|
|
19
19
|
require 'kameleoon/data/manager/forced_experiment_variation'
|
|
20
20
|
require 'kameleoon/data/manager/forced_feature_variation'
|
|
21
|
+
require 'kameleoon/data/manager/legal_consent'
|
|
21
22
|
require 'kameleoon/data/manager/page_view_visit'
|
|
22
23
|
require 'kameleoon/logging/kameleoon_logger'
|
|
23
24
|
|
|
@@ -312,7 +313,7 @@ module Kameleoon
|
|
|
312
313
|
Logging::KameleoonLogger.debug('CALL: VisitorData.new')
|
|
313
314
|
@time_started = (Time.now.to_f * 1000).to_i
|
|
314
315
|
@mutex = Concurrent::ReadWriteLock.new
|
|
315
|
-
@legal_consent =
|
|
316
|
+
@legal_consent = LegalConsent::UNKNOWN
|
|
316
317
|
Logging::KameleoonLogger.debug('RETURN: VisitorData.new')
|
|
317
318
|
end
|
|
318
319
|
|
data/lib/kameleoon/exceptions.rb
CHANGED
|
@@ -53,10 +53,6 @@ module Kameleoon
|
|
|
53
53
|
|
|
54
54
|
# Feature Environment Disabled
|
|
55
55
|
class FeatureEnvironmentDisabled < FeatureError
|
|
56
|
-
def initialize(feature_key, environment = nil)
|
|
57
|
-
environment = environment.nil? ? 'default' : "'#{environment}'"
|
|
58
|
-
super("Feature '#{feature_key}' is disabled for #{environment} environment'")
|
|
59
|
-
end
|
|
60
56
|
end
|
|
61
57
|
|
|
62
58
|
# Config Error
|
|
@@ -8,6 +8,7 @@ require 'kameleoon/data/custom_data'
|
|
|
8
8
|
require 'kameleoon/data/user_agent'
|
|
9
9
|
require 'kameleoon/data/manager/assigned_variation'
|
|
10
10
|
require 'kameleoon/data/manager/forced_experiment_variation'
|
|
11
|
+
require 'kameleoon/data/manager/legal_consent'
|
|
11
12
|
require 'kameleoon/data/manager/visitor_manager'
|
|
12
13
|
require 'kameleoon/exceptions'
|
|
13
14
|
require 'kameleoon/hybrid/manager'
|
|
@@ -27,6 +28,9 @@ require 'kameleoon/targeting/models'
|
|
|
27
28
|
require 'kameleoon/targeting/targeting_manager'
|
|
28
29
|
require 'kameleoon/types/variable'
|
|
29
30
|
require 'kameleoon/types/variation'
|
|
31
|
+
require 'kameleoon/types/rule'
|
|
32
|
+
require 'kameleoon/types/feature_flag'
|
|
33
|
+
require 'kameleoon/types/data_file'
|
|
30
34
|
require 'rufus/scheduler'
|
|
31
35
|
require 'yaml'
|
|
32
36
|
require 'json'
|
|
@@ -123,8 +127,9 @@ module Kameleoon
|
|
|
123
127
|
# visitor_code = get_visitor_code(cookies, 'my-domaine.com')
|
|
124
128
|
#
|
|
125
129
|
def get_visitor_code(cookies, default_visitor_code = nil)
|
|
126
|
-
Logging::KameleoonLogger.info(
|
|
127
|
-
|
|
130
|
+
Logging::KameleoonLogger.info(
|
|
131
|
+
"CALL: KameleoonClient.get_visitor_code(cookies: %s, default_visitor_code: '%s')", cookies, default_visitor_code
|
|
132
|
+
)
|
|
128
133
|
visitor_code = @cookie_manager.get_or_add(cookies, default_visitor_code)
|
|
129
134
|
Logging::KameleoonLogger.info(
|
|
130
135
|
"RETURN: KameleoonClient.get_visitor_code(cookies: %s, default_visitor_code: '%s') -> (visitor_code: '%s')",
|
|
@@ -140,7 +145,7 @@ module Kameleoon
|
|
|
140
145
|
)
|
|
141
146
|
Utils::VisitorCode.validate(visitor_code)
|
|
142
147
|
visitor = @visitor_manager.get_or_create_visitor(visitor_code)
|
|
143
|
-
visitor.legal_consent = consent
|
|
148
|
+
visitor.legal_consent = consent ? DataManager::LegalConsent::GIVEN : DataManager::LegalConsent::NOT_GIVEN
|
|
144
149
|
@cookie_manager.update(visitor_code, consent, cookies)
|
|
145
150
|
Logging::KameleoonLogger.info(
|
|
146
151
|
"RETURN: KameleoonClient.set_legal_consent(visitor_code: '%s', consent: %s, cookies: %s)",
|
|
@@ -366,7 +371,11 @@ module Kameleoon
|
|
|
366
371
|
@data_manager.data_file.feature_flags.each_value do |feature_flag|
|
|
367
372
|
next unless feature_flag.environment_enabled
|
|
368
373
|
|
|
369
|
-
|
|
374
|
+
begin
|
|
375
|
+
variation_key, eval_exp = get_variation_info(visitor_code, feature_flag, track)
|
|
376
|
+
rescue Exception::FeatureEnvironmentDisabled
|
|
377
|
+
next
|
|
378
|
+
end
|
|
370
379
|
next if only_active && (variation_key == Configuration::VariationType::VARIATION_OFF)
|
|
371
380
|
|
|
372
381
|
variation = feature_flag.get_variation_by_key(variation_key)
|
|
@@ -631,7 +640,11 @@ module Kameleoon
|
|
|
631
640
|
@data_manager.data_file.feature_flags.each do |feature_key, feature_flag|
|
|
632
641
|
next unless feature_flag.environment_enabled
|
|
633
642
|
|
|
634
|
-
|
|
643
|
+
begin
|
|
644
|
+
eval_exp = evaluate(visitor, visitor_code, feature_flag, false, false)
|
|
645
|
+
rescue Exception::FeatureEnvironmentDisabled
|
|
646
|
+
next
|
|
647
|
+
end
|
|
635
648
|
variation_key = calculate_variation_key(eval_exp, feature_flag.default_variation_key)
|
|
636
649
|
list_keys.push(feature_key) if variation_key != Kameleoon::Configuration::VariationType::VARIATION_OFF
|
|
637
650
|
end
|
|
@@ -666,7 +679,11 @@ module Kameleoon
|
|
|
666
679
|
@data_manager.data_file.feature_flags.each_value do |feature_flag|
|
|
667
680
|
next unless feature_flag.environment_enabled
|
|
668
681
|
|
|
669
|
-
|
|
682
|
+
begin
|
|
683
|
+
eval_exp = evaluate(visitor, visitor_code, feature_flag, false, false)
|
|
684
|
+
rescue Exception::FeatureEnvironmentDisabled
|
|
685
|
+
next
|
|
686
|
+
end
|
|
670
687
|
variation_key = calculate_variation_key(eval_exp, feature_flag.default_variation_key)
|
|
671
688
|
|
|
672
689
|
next if variation_key == Configuration::VariationType::VARIATION_OFF
|
|
@@ -779,6 +796,52 @@ module Kameleoon
|
|
|
779
796
|
Logging::KameleoonLogger.info("RETURN: KameleoonClient.evaluate_audiences(visitor_code: '%s')", visitor_code)
|
|
780
797
|
end
|
|
781
798
|
|
|
799
|
+
##
|
|
800
|
+
# Retrieves the current SDK configuration (also known as the data file),
|
|
801
|
+
# containing all feature flags and their variations.
|
|
802
|
+
#
|
|
803
|
+
# @return [Kameleoon::Types::DataFile] The current DataFile instance.
|
|
804
|
+
def get_data_file
|
|
805
|
+
Logging::KameleoonLogger.info('CALL: KameleoonClient.get_data_file')
|
|
806
|
+
|
|
807
|
+
feature_flags_map = @data_manager.data_file.feature_flags.transform_values do |source_feature_flag|
|
|
808
|
+
# Collect variations
|
|
809
|
+
variations_map = source_feature_flag.variations.each_with_object({}) do |variation, variations_map|
|
|
810
|
+
variables_map = variation.variables.each_with_object({}) do |var, variables_map|
|
|
811
|
+
variables_map[var.key] = Types::Variable.new(var.key, var.type, _parse_feature_variable(var))
|
|
812
|
+
end
|
|
813
|
+
variations_map[variation.key] = Types::Variation.new(variation.key, nil, nil, variables_map, variation.name)
|
|
814
|
+
end
|
|
815
|
+
|
|
816
|
+
# Collect rules
|
|
817
|
+
rules = source_feature_flag.rules.map do |rule|
|
|
818
|
+
rule_variations = rule.experiment.variations_by_exposition.each_with_object({}) do |var_by_exp, rule_variations|
|
|
819
|
+
base_variation = variations_map[var_by_exp.variation_key]
|
|
820
|
+
next unless base_variation
|
|
821
|
+
rule_variations[base_variation.key] = Types::Variation.new(
|
|
822
|
+
base_variation.key,
|
|
823
|
+
var_by_exp.variation_id,
|
|
824
|
+
rule.experiment.id,
|
|
825
|
+
base_variation.variables,
|
|
826
|
+
base_variation.name
|
|
827
|
+
)
|
|
828
|
+
end
|
|
829
|
+
Types::Rule.new(rule_variations)
|
|
830
|
+
end
|
|
831
|
+
|
|
832
|
+
Types::FeatureFlag.new(
|
|
833
|
+
variations_map,
|
|
834
|
+
source_feature_flag.environment_enabled,
|
|
835
|
+
rules,
|
|
836
|
+
source_feature_flag.default_variation_key
|
|
837
|
+
)
|
|
838
|
+
end
|
|
839
|
+
|
|
840
|
+
data_file = Types::DataFile.new(feature_flags_map)
|
|
841
|
+
Logging::KameleoonLogger.info('RETURN: KameleoonClient.get_data_file -> (data_file: %s)', data_file)
|
|
842
|
+
data_file
|
|
843
|
+
end
|
|
844
|
+
|
|
782
845
|
private
|
|
783
846
|
|
|
784
847
|
HYBRID_EXPIRATION_TIME = 5
|
|
@@ -995,11 +1058,19 @@ module Kameleoon
|
|
|
995
1058
|
holdout = @data_manager.data_file.holdout
|
|
996
1059
|
return true if holdout.nil?
|
|
997
1060
|
|
|
998
|
-
in_holdout_variation_key = 'in-holdout'
|
|
999
1061
|
Logging::KameleoonLogger.debug(
|
|
1000
1062
|
"CALL: KameleoonClient.visitor_not_in_holdout?(visitor, visitor_code: '%s', track: %s, save: %s, " \
|
|
1001
1063
|
'bucketing_custom_data_index: %s)', visitor_code, track, save, bucketing_custom_data_index
|
|
1002
1064
|
)
|
|
1065
|
+
|
|
1066
|
+
consent, blocking_behaviour = _get_consent_and_blocking_behaviour(visitor)
|
|
1067
|
+
if consent == DataManager::LegalConsent::NOT_GIVEN &&
|
|
1068
|
+
blocking_behaviour == Configuration::ConsentBlockingBehaviour::COMPLETELY_BLOCKED
|
|
1069
|
+
raise FeatureEnvironmentDisabled,
|
|
1070
|
+
"Evaluation for a holdout is blocked because visitor's consent was not provided."
|
|
1071
|
+
end
|
|
1072
|
+
|
|
1073
|
+
in_holdout_variation_key = 'in-holdout'
|
|
1003
1074
|
is_not_in_holdout = true
|
|
1004
1075
|
code_for_hash = get_code_for_hash(visitor, visitor_code, bucketing_custom_data_index)
|
|
1005
1076
|
variation_hash = Utils::Hasher.obtain(code_for_hash, holdout.id)
|
|
@@ -1116,6 +1187,7 @@ module Kameleoon
|
|
|
1116
1187
|
visitor_code, feature_flag
|
|
1117
1188
|
)
|
|
1118
1189
|
visitor = @visitor_manager.get_visitor(visitor_code)
|
|
1190
|
+
consent, blocking_behaviour = _get_consent_and_blocking_behaviour(visitor)
|
|
1119
1191
|
code_for_hash = get_code_for_hash(visitor, visitor_code, feature_flag.bucketing_custom_data_index)
|
|
1120
1192
|
# no rules -> return default_variation_key
|
|
1121
1193
|
eval_exp = nil
|
|
@@ -1139,6 +1211,15 @@ module Kameleoon
|
|
|
1139
1211
|
Logging::KameleoonLogger.debug("Calculated rule hash %s for code '%s'", hash_rule, code_for_hash)
|
|
1140
1212
|
# check main expostion for rule with hashRule
|
|
1141
1213
|
if hash_rule <= rule.exposition
|
|
1214
|
+
# Checking if the evaluation is blocked due to the consent policy
|
|
1215
|
+
if (consent == DataManager::LegalConsent::NOT_GIVEN) && rule.experimentation_type?
|
|
1216
|
+
break if blocking_behaviour == Configuration::ConsentBlockingBehaviour::PARTIALLY_BLOCKED
|
|
1217
|
+
|
|
1218
|
+
# TODO: In the next major, create a new error type for the Completely Blocked by Consent error
|
|
1219
|
+
msg = "Evaluation of #{rule} is blocked because consent is not provided for visitor '#{visitor_code}'"
|
|
1220
|
+
raise Exception::FeatureEnvironmentDisabled, msg
|
|
1221
|
+
end
|
|
1222
|
+
# Checking CBS
|
|
1142
1223
|
eval_exp = evaluate_cbscores(visitor, visitor_code, rule, feature_flag.bucketing_custom_data_index)
|
|
1143
1224
|
break unless eval_exp.nil?
|
|
1144
1225
|
|
|
@@ -1167,6 +1248,18 @@ module Kameleoon
|
|
|
1167
1248
|
eval_exp
|
|
1168
1249
|
end
|
|
1169
1250
|
|
|
1251
|
+
def _get_consent_and_blocking_behaviour(visitor)
|
|
1252
|
+
datafile = @data_manager.data_file
|
|
1253
|
+
behaviour = datafile.settings.blocking_behaviour_if_consent_not_given
|
|
1254
|
+
|
|
1255
|
+
consent = DataManager::LegalConsent::GIVEN
|
|
1256
|
+
if datafile.settings.is_consent_required
|
|
1257
|
+
consent = visitor&.legal_consent || DataManager::LegalConsent::UNKNOWN
|
|
1258
|
+
end
|
|
1259
|
+
|
|
1260
|
+
[consent, behaviour]
|
|
1261
|
+
end
|
|
1262
|
+
|
|
1170
1263
|
def calculate_variation_key(eval_exp, default_value)
|
|
1171
1264
|
Logging::KameleoonLogger.debug(
|
|
1172
1265
|
"CALL: KameleoonClient.calculate_variation_key(eval_exp: %s, default_value: '%s') ", eval_exp, default_value
|
|
@@ -1193,7 +1286,11 @@ module Kameleoon
|
|
|
1193
1286
|
end
|
|
1194
1287
|
ext_variables.freeze
|
|
1195
1288
|
ext_variation = Types::Variation.new(
|
|
1196
|
-
variation&.key
|
|
1289
|
+
variation&.key || '',
|
|
1290
|
+
eval_exp&.var_by_exp&.variation_id,
|
|
1291
|
+
eval_exp&.experiment&.id,
|
|
1292
|
+
ext_variables,
|
|
1293
|
+
variation&.name || ''
|
|
1197
1294
|
)
|
|
1198
1295
|
Logging::KameleoonLogger.debug(
|
|
1199
1296
|
'RETURN: KameleoonClient.create_external_variation(variation: %s, eval_exp: %s) -> (ext_variation: %s)',
|
|
@@ -24,15 +24,16 @@ module Kameleoon
|
|
|
24
24
|
@filter = filter
|
|
25
25
|
@visit_number = 0
|
|
26
26
|
current_visit = hash['currentVisit']
|
|
27
|
-
parse_visit(current_visit,
|
|
27
|
+
parse_visit(current_visit, 0) unless current_visit.nil?
|
|
28
28
|
previous_visits = hash['previousVisits']
|
|
29
29
|
previous_visits = [] if previous_visits.nil?
|
|
30
30
|
|
|
31
31
|
if previous_visits.size.positive?
|
|
32
32
|
prev_visits = []
|
|
33
|
-
previous_visits.
|
|
33
|
+
previous_visits.each_index do |i|
|
|
34
|
+
visit = previous_visits[i]
|
|
34
35
|
prev_visits.push(VisitorVisits::Visit.new(visit['timeStarted'] || 0, visit['timeLastEvent']))
|
|
35
|
-
parse_visit(visit,
|
|
36
|
+
parse_visit(visit, i + 1)
|
|
36
37
|
end
|
|
37
38
|
@visitor_visits = VisitorVisits.new(prev_visits, @visit_number)
|
|
38
39
|
end
|
|
@@ -74,7 +75,7 @@ module Kameleoon
|
|
|
74
75
|
|
|
75
76
|
private
|
|
76
77
|
|
|
77
|
-
def parse_visit(hash,
|
|
78
|
+
def parse_visit(hash, visit_offset)
|
|
78
79
|
@visitor_code = hash['visitorCode'] if @visitor_code.nil?
|
|
79
80
|
custom_data_events = hash['customDataEvents']
|
|
80
81
|
parse_custom_data(custom_data_events) if !custom_data_events.nil? && custom_data_events.size.positive?
|
|
@@ -88,7 +89,7 @@ module Kameleoon
|
|
|
88
89
|
@geolocation = parse_geolocation(geolocation_events) if @geolocation.nil? && !geolocation_events.nil? && \
|
|
89
90
|
geolocation_events.size.positive?
|
|
90
91
|
static_data_events = hash['staticDataEvent']
|
|
91
|
-
parse_static_data(static_data_events,
|
|
92
|
+
parse_static_data(static_data_events, visit_offset) unless static_data_events.nil?
|
|
92
93
|
personalization_events = hash['personalizationEvents']
|
|
93
94
|
parse_personalizations(personalization_events) unless personalization_events.nil?
|
|
94
95
|
end
|
|
@@ -146,11 +147,11 @@ module Kameleoon
|
|
|
146
147
|
Geolocation.new(data['country'], data['region'], data['city'])
|
|
147
148
|
end
|
|
148
149
|
|
|
149
|
-
def parse_static_data(static_data_event,
|
|
150
|
+
def parse_static_data(static_data_event, visit_offset)
|
|
150
151
|
data = static_data_event['data']
|
|
151
152
|
if @visit_number.zero?
|
|
152
|
-
|
|
153
|
-
@visit_number
|
|
153
|
+
remote_visit_number = data['visitNumber']
|
|
154
|
+
@visit_number = remote_visit_number + visit_offset unless remote_visit_number.nil?
|
|
154
155
|
end
|
|
155
156
|
if @filter.device && @device.nil?
|
|
156
157
|
device_type = data['deviceType']
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'kameleoon/data/custom_data'
|
|
4
|
+
require 'kameleoon/data/manager/legal_consent'
|
|
4
5
|
require 'kameleoon/logging/kameleoon_logger'
|
|
5
6
|
require 'kameleoon/network/activity_event'
|
|
6
7
|
require 'kameleoon/network/uri_helper'
|
|
@@ -65,7 +66,8 @@ module Kameleoon
|
|
|
65
66
|
end
|
|
66
67
|
|
|
67
68
|
def consent_given?(visitor)
|
|
68
|
-
!@data_file.settings.is_consent_required ||
|
|
69
|
+
!@data_file.settings.is_consent_required ||
|
|
70
|
+
((visitor&.legal_consent || DataManager::LegalConsent::UNKNOWN) == DataManager::LegalConsent::GIVEN)
|
|
69
71
|
end
|
|
70
72
|
|
|
71
73
|
def collect_tracking_data(visitor_code, visitor, is_consent_given)
|
|
@@ -45,16 +45,13 @@ module Kameleoon
|
|
|
45
45
|
def update(visitor_code, consent, cookies)
|
|
46
46
|
return if cookies.nil?
|
|
47
47
|
|
|
48
|
-
Logging::KameleoonLogger.debug(
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if consent
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
end
|
|
56
|
-
Logging::KameleoonLogger.debug("RETURN: CookieManager.update(visitor_code: '%s', consent: %s, cookies: %s)",
|
|
57
|
-
visitor_code, consent, cookies)
|
|
48
|
+
Logging::KameleoonLogger.debug(
|
|
49
|
+
"CALL: CookieManager.update(visitor_code: '%s', consent: %s, cookies: %s)", visitor_code, consent, cookies
|
|
50
|
+
)
|
|
51
|
+
add(visitor_code, cookies) if consent
|
|
52
|
+
Logging::KameleoonLogger.debug(
|
|
53
|
+
"RETURN: CookieManager.update(visitor_code: '%s', consent: %s, cookies: %s)", visitor_code, consent, cookies
|
|
54
|
+
)
|
|
58
55
|
end
|
|
59
56
|
|
|
60
57
|
private
|
|
@@ -79,7 +76,7 @@ module Kameleoon
|
|
|
79
76
|
visitor_code = default_visitor_code
|
|
80
77
|
Utils::VisitorCode.validate(visitor_code)
|
|
81
78
|
Logging::KameleoonLogger.debug("Used default visitor code '{%s}'", default_visitor_code)
|
|
82
|
-
add(visitor_code, cookies)
|
|
79
|
+
add(visitor_code, cookies) unless @data_manager.visitor_code_managed?
|
|
83
80
|
visitor_code
|
|
84
81
|
end
|
|
85
82
|
|
|
@@ -100,13 +97,6 @@ module Kameleoon
|
|
|
100
97
|
cookies
|
|
101
98
|
end
|
|
102
99
|
|
|
103
|
-
def remove(cookies)
|
|
104
|
-
Logging::KameleoonLogger.debug('CALL: CookieManager.remove(cookies: %s)', cookies)
|
|
105
|
-
cookies[VISITOR_CODE_COOKIE] = nil if @data_manager.visitor_code_managed?
|
|
106
|
-
Logging::KameleoonLogger.debug('RETURN: CookieManager.remove(cookies: %s)', cookies)
|
|
107
|
-
cookies
|
|
108
|
-
end
|
|
109
|
-
|
|
110
100
|
def process_simulated_variations(cookies, visitor_code)
|
|
111
101
|
raw = get_value_from_cookies(cookies, KAMELEOON_SIMULATION_FF_DATA)
|
|
112
102
|
return if raw.nil?
|
|
@@ -28,6 +28,22 @@ module Kameleoon
|
|
|
28
28
|
|
|
29
29
|
class SyncNetProvider < NetProvider
|
|
30
30
|
def make_request(request)
|
|
31
|
+
for _ in 0..8 do
|
|
32
|
+
response = make_single_request(request)
|
|
33
|
+
break if (response.code != 307) && (response.code != 308)
|
|
34
|
+
|
|
35
|
+
# supports only absolute urls
|
|
36
|
+
new_loc = response.headers['location'][0]
|
|
37
|
+
break unless new_loc
|
|
38
|
+
|
|
39
|
+
request.redirect(new_loc)
|
|
40
|
+
end
|
|
41
|
+
response
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
def make_single_request(request)
|
|
31
47
|
resp = nil
|
|
32
48
|
case request.method
|
|
33
49
|
when Method::GET
|
|
@@ -29,7 +29,8 @@ module Kameleoon
|
|
|
29
29
|
# Module for create different targeting conditions
|
|
30
30
|
module ConditionFactory
|
|
31
31
|
def get_condition(condition_json)
|
|
32
|
-
|
|
32
|
+
cond_type = condition_json['targetingType']
|
|
33
|
+
case cond_type
|
|
33
34
|
when ConditionType::CUSTOM_DATUM
|
|
34
35
|
CustomDatum.new(condition_json)
|
|
35
36
|
when ConditionType::TARGET_FEATURE_FLAG
|
|
@@ -77,6 +78,7 @@ module Kameleoon
|
|
|
77
78
|
when ConditionType::HEAT_SLICE
|
|
78
79
|
KcsHeatRangeCondition.new(condition_json)
|
|
79
80
|
else
|
|
81
|
+
Logging::KameleoonLogger.info("Unexpected TargetingConditionType: '%s'", cond_type)
|
|
80
82
|
UnknownCondition.new(condition_json)
|
|
81
83
|
end
|
|
82
84
|
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Kameleoon
|
|
4
|
+
module Types
|
|
5
|
+
# DataFile
|
|
6
|
+
class DataFile
|
|
7
|
+
attr_reader :feature_flags
|
|
8
|
+
|
|
9
|
+
# @api private
|
|
10
|
+
def initialize(feature_flags)
|
|
11
|
+
@feature_flags = feature_flags
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def to_s
|
|
15
|
+
"DataFile{feature_flags:#{@feature_flags}}"
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Kameleoon
|
|
4
|
+
module Types
|
|
5
|
+
# FeatureFlag
|
|
6
|
+
class FeatureFlag
|
|
7
|
+
attr_reader :variations, :environment_enabled, :rules, :default_variation_key
|
|
8
|
+
|
|
9
|
+
# @api private
|
|
10
|
+
def initialize(variations, environment_enabled, rules, default_variation_key)
|
|
11
|
+
@variations = variations
|
|
12
|
+
@environment_enabled = environment_enabled
|
|
13
|
+
@rules = rules
|
|
14
|
+
@default_variation_key = default_variation_key
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def default_variation
|
|
18
|
+
@variations[@default_variation_key]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def to_s
|
|
22
|
+
"FeatureFlag{variations:#{@variations},environment_enabled:#{@environment_enabled},rules:#{@rules},default_variation_key:#{@default_variation_key}}"
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Kameleoon
|
|
4
|
+
module Types
|
|
5
|
+
# Rule
|
|
6
|
+
class Rule
|
|
7
|
+
attr_reader :variations
|
|
8
|
+
|
|
9
|
+
# @api private
|
|
10
|
+
def initialize(variations)
|
|
11
|
+
@variations = variations
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def to_s
|
|
15
|
+
"Rule{variations:#{@variations}}"
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Kameleoon
|
|
4
|
-
# Module which contains all internal data of SDK
|
|
5
4
|
module Types
|
|
6
5
|
# Variable
|
|
7
6
|
class Variable
|
|
@@ -11,6 +10,7 @@ module Kameleoon
|
|
|
11
10
|
"Variable{key:'#{@key}',type:'#{@type}',value:#{@value}}"
|
|
12
11
|
end
|
|
13
12
|
|
|
13
|
+
# @api private
|
|
14
14
|
def initialize(key, type, value)
|
|
15
15
|
@key = key
|
|
16
16
|
@type = type
|
|
@@ -3,21 +3,22 @@
|
|
|
3
3
|
require 'kameleoon/configuration/variation'
|
|
4
4
|
|
|
5
5
|
module Kameleoon
|
|
6
|
-
# Module which contains all internal data of SDK
|
|
7
6
|
module Types
|
|
8
7
|
# Variation
|
|
9
8
|
class Variation
|
|
10
|
-
attr_reader :key, :id, :experiment_id, :variables
|
|
9
|
+
attr_reader :name, :key, :id, :experiment_id, :variables
|
|
11
10
|
|
|
12
11
|
def to_s
|
|
13
|
-
"Variation{key:'#{@key}',id:#{@id},experiment_id:#{@experiment_id},variables:#{@variables}}"
|
|
12
|
+
"Variation{name:'#{@name}',key:'#{@key}',id:#{@id},experiment_id:#{@experiment_id},variables:#{@variables}}"
|
|
14
13
|
end
|
|
15
14
|
|
|
16
|
-
|
|
15
|
+
# @api private
|
|
16
|
+
def initialize(key, id, experiment_id, variables, name = '')
|
|
17
17
|
@key = key
|
|
18
18
|
@id = id
|
|
19
19
|
@experiment_id = experiment_id
|
|
20
20
|
@variables = variables
|
|
21
|
+
@name = name
|
|
21
22
|
end
|
|
22
23
|
|
|
23
24
|
def active?
|
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.17.1
|
|
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-12-24 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: em-http-request
|
|
@@ -101,6 +101,7 @@ files:
|
|
|
101
101
|
- lib/kameleoon/data/manager/forced_experiment_variation.rb
|
|
102
102
|
- lib/kameleoon/data/manager/forced_feature_variation.rb
|
|
103
103
|
- lib/kameleoon/data/manager/forced_variation.rb
|
|
104
|
+
- lib/kameleoon/data/manager/legal_consent.rb
|
|
104
105
|
- lib/kameleoon/data/manager/page_view_visit.rb
|
|
105
106
|
- lib/kameleoon/data/manager/visitor.rb
|
|
106
107
|
- lib/kameleoon/data/manager/visitor_manager.rb
|
|
@@ -178,7 +179,10 @@ files:
|
|
|
178
179
|
- lib/kameleoon/targeting/models.rb
|
|
179
180
|
- lib/kameleoon/targeting/targeting_manager.rb
|
|
180
181
|
- lib/kameleoon/targeting/tree_builder.rb
|
|
182
|
+
- lib/kameleoon/types/data_file.rb
|
|
183
|
+
- lib/kameleoon/types/feature_flag.rb
|
|
181
184
|
- lib/kameleoon/types/remote_visitor_data_filter.rb
|
|
185
|
+
- lib/kameleoon/types/rule.rb
|
|
182
186
|
- lib/kameleoon/types/variable.rb
|
|
183
187
|
- lib/kameleoon/types/variation.rb
|
|
184
188
|
- lib/kameleoon/utils.rb
|