vwo-sdk 1.16.0 → 1.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '084660e0c3fcb3c07826944ba8d83988711b59165ea54a54b1e47042a889bbf5'
4
- data.tar.gz: 62c4ae889870a381d2973967412f0916baa0d25ce377604aa096c5f4dd0a8e79
3
+ metadata.gz: 84d01560f605a69e8ed011a19ba4e3aae0f67341fd653a562d817801d6a55073
4
+ data.tar.gz: b1355bef1b2b095774c702a6757c1a7141e2cf9758d0a1b8a0510111a8ee597a
5
5
  SHA512:
6
- metadata.gz: 67fd788b416ac54e9d27999ca757662eb88a123a804ccf3c93538e58787a3fd1181686543a7abdbb94dbd7d66f5d1c63421ae21d1b3e794b93cff6951355fdd2
7
- data.tar.gz: 7950a38da6e5993575ff46e1c1ba2f901d98fa4112e54070297c78846e2b29eacdae4042c51d03f1e9e8b05d55aa4e60b698fa70af43c7d1ae2167953aaaec6c
6
+ metadata.gz: cc2c8a411e3c0a674ab2bc00e540b3e49a8dd943ec50aa04fba04839ef6f3e255fc275529f872aa5ca73dfe893cb43e8853a0875cc3dda9330554b6491590947
7
+ data.tar.gz: 5482e79564a365ec8fe4012b25997096352129e915daca28774c790c416a528302ea1f0bb685ef559b9ee0846b0229957a8f6ab77008f4e48222a7cae5892699
data/lib/abc.txt ADDED
@@ -0,0 +1,28 @@
1
+ {"user_id"=>"Ashley", "variation_name"=>"Control", "campaign_key"=>"DEV_TEST_162"}
2
+ GOT_ELIGIBLE_CAMPAIGNS
3
+ {"user_id"=>"Ashley", "variation_name"=>"Control", "campaign_key"=>"DEV_TEST_162"}
4
+ GOT_ELIGIBLE_CAMPAIGNS
5
+ {"user_id"=>"Ashley", "variation_name"=>"Control", "campaign_key"=>"DEV_TEST_162"}
6
+ GOT_ELIGIBLE_CAMPAIGNS
7
+ {"user_id"=>"Ashley", "variation_name"=>"Control", "campaign_key"=>"DEV_TEST_162"}
8
+ GOT_ELIGIBLE_CAMPAIGNS
9
+ {"user_id"=>"Ashley", "variation_name"=>"Control", "campaign_key"=>"DEV_TEST_162"}
10
+ GOT_ELIGIBLE_CAMPAIGNS
11
+ {"user_id"=>"Ashley", "variation_name"=>"Control", "campaign_key"=>"DEV_TEST_162"}
12
+ GOT_ELIGIBLE_CAMPAIGNS
13
+ {"user_id"=>"Ashley", "variation_name"=>"Control", "campaign_key"=>"DEV_TEST_162"}
14
+ GOT_ELIGIBLE_CAMPAIGNS
15
+ {"user_id"=>"Ashley", "variation_name"=>"Control", "campaign_key"=>"DEV_TEST_162"}
16
+ GOT_ELIGIBLE_CAMPAIGNS
17
+ {"user_id"=>"Ashley", "variation_name"=>"Control", "campaign_key"=>"DEV_TEST_162"}
18
+ GOT_ELIGIBLE_CAMPAIGNS
19
+ {"user_id"=>"Ashley", "variation_name"=>"Control", "campaign_key"=>"DEV_TEST_162"}
20
+ GOT_ELIGIBLE_CAMPAIGNS
21
+ {"user_id"=>"Ashley", "variation_name"=>"Control", "campaign_key"=>"DEV_TEST_162"}
22
+ GOT_ELIGIBLE_CAMPAIGNS
23
+ {"user_id"=>"Ashley", "variation_name"=>"Control", "campaign_key"=>"DEV_TEST_162"}
24
+ GOT_ELIGIBLE_CAMPAIGNS
25
+ {"user_id"=>"Ashley", "variation_name"=>"Control", "campaign_key"=>"DEV_TEST_162"}
26
+ GOT_ELIGIBLE_CAMPAIGNS
27
+ {"user_id"=>"Ashley", "variation_name"=>"Control", "campaign_key"=>"DEV_TEST_162"}
28
+ GOT_ELIGIBLE_CAMPAIGNS
data/lib/vwo/constants.rb CHANGED
@@ -19,6 +19,7 @@ class VWO
19
19
  SEED_VALUE = 1
20
20
  MAX_TRAFFIC_PERCENT = 100
21
21
  MAX_TRAFFIC_VALUE = 10_000
22
+ MAX_RANGE = 10000
22
23
  STATUS_RUNNING = 'RUNNING'
23
24
  # rubocop:disable Style/ExpandPathArguments
24
25
  LIBRARY_PATH = File.expand_path('../..', __FILE__)
@@ -26,7 +27,7 @@ class VWO
26
27
  HTTP_PROTOCOL = 'http://'
27
28
  HTTPS_PROTOCOL = 'https://'
28
29
  URL_NAMESPACE = '6ba7b811-9dad-11d1-80b4-00c04fd430c8'
29
- SDK_VERSION = '1.16.0'
30
+ SDK_VERSION = '1.22.0'
30
31
  SDK_NAME = 'ruby'
31
32
  VWO_DELIMITER = '_vwo_'
32
33
  MAX_EVENTS_PER_REQUEST = 5000
@@ -60,7 +60,7 @@ class VWO
60
60
  end
61
61
 
62
62
  traffic_allocation = campaign['percentTraffic']
63
- value_assigned_to_user = get_bucket_value_for_user(user_id)
63
+ value_assigned_to_user = get_bucket_value_for_user(user_id, campaign)
64
64
  is_user_part = (value_assigned_to_user != 0) && value_assigned_to_user <= traffic_allocation
65
65
  @logger.log(
66
66
  LogLevelEnum::INFO,
@@ -94,7 +94,11 @@ class VWO
94
94
  return
95
95
  end
96
96
 
97
- hash_value = MurmurHash3::V32.str_hash(user_id, SEED_VALUE) & U_MAX_32_BIT
97
+ user_id_for_hash_value = user_id
98
+ if campaign[:isBucketingSeedEnabled]
99
+ user_id_for_hash_value = campaign[:id].to_s + "_" + user_id
100
+ end
101
+ hash_value = MurmurHash3::V32.str_hash(user_id_for_hash_value, SEED_VALUE) & U_MAX_32_BIT
98
102
  normalize = MAX_TRAFFIC_VALUE.to_f / campaign['percentTraffic']
99
103
  multiplier = normalize / 100
100
104
  bucket_value = get_bucket_value(
@@ -136,10 +140,17 @@ class VWO
136
140
  # User by hashing the userId by murmurHash and scaling it down.
137
141
  #
138
142
  # @param[String] :user_id The unique ID assigned to User
143
+ # @param[String] :campaign Campaign data
139
144
  # @return[Integer] The bucket Value allotted to User
140
145
  # (between 1 to $this->$MAX_TRAFFIC_PERCENT)
141
- def get_bucket_value_for_user(user_id)
142
- hash_value = MurmurHash3::V32.str_hash(user_id, SEED_VALUE) & U_MAX_32_BIT
146
+ def get_bucket_value_for_user(user_id, campaign = {}, group_id = nil, disable_logs = false)
147
+ user_id_for_hash_value = user_id
148
+ if group_id
149
+ user_id_for_hash_value = group_id.to_s + "_" + user_id
150
+ elsif campaign[:isBucketingSeedEnabled]
151
+ user_id_for_hash_value = campaign[:id].to_s + "_" + user_id
152
+ end
153
+ hash_value = MurmurHash3::V32.str_hash(user_id_for_hash_value, SEED_VALUE) & U_MAX_32_BIT
143
154
  bucket_value = get_bucket_value(hash_value, MAX_TRAFFIC_PERCENT)
144
155
 
145
156
  @logger.log(
@@ -150,7 +161,8 @@ class VWO
150
161
  hash_value: hash_value,
151
162
  bucket_value: bucket_value,
152
163
  user_id: user_id
153
- )
164
+ ),
165
+ disable_logs
154
166
  )
155
167
  bucket_value
156
168
  end
@@ -168,6 +180,22 @@ class VWO
168
180
  multiplied_value = (max_value * ratio + 1) * multiplier
169
181
  multiplied_value.to_i
170
182
  end
183
+
184
+ # Returns a campaign by checking the Start and End Bucket Allocations of each campaign.
185
+ #
186
+ # @param[Integer] :range_for_campaigns the bucket value of the user
187
+ # @param[Hash] :campaigns The bucket Value of the user
188
+ # @return[Hash|nil]
189
+ #
190
+ def get_campaign_using_range(range_for_campaigns, campaigns)
191
+ range_for_campaigns = range_for_campaigns * 100
192
+ campaigns.each do |campaign|
193
+ if campaign["max_range"] && campaign["max_range"] >= range_for_campaigns && campaign["min_range"] <= range_for_campaigns
194
+ return campaign
195
+ end
196
+ end
197
+ nil
198
+ end
171
199
  end
172
200
  end
173
201
  end
@@ -66,6 +66,8 @@ class VWO
66
66
 
67
67
  return unless campaign
68
68
 
69
+ is_campaign_part_of_group = @settings_file && is_part_of_group(@settings_file, campaign["id"])
70
+
69
71
  @has_stored_variation = false
70
72
  decision = {
71
73
  :campaign_id => campaign['id'],
@@ -93,62 +95,17 @@ class VWO
93
95
  :vwo_user_id => generator_for(user_id, @settings_file['accountId'])
94
96
  }
95
97
 
96
- if campaign['isForcedVariationEnabled']
97
- variation = evaluate_whitelisting(
98
- user_id,
99
- campaign,
100
- api_name,
101
- campaign_key,
102
- variation_targeting_variables
103
- )
104
- status = if variation
105
- StatusEnum::PASSED
106
- else
107
- StatusEnum::FAILED
108
- end
109
-
110
- @logger.log(
111
- LogLevelEnum::INFO,
112
- format(
113
- LogMessageEnum::InfoMessages::SEGMENTATION_STATUS,
114
- file: FILE,
115
- campaign_key: campaign_key,
116
- user_id: user_id,
117
- status: status,
118
- custom_variables: variation_targeting_variables,
119
- variation_name: status == StatusEnum::PASSED ? "and #{variation['name']} is Assigned" : ' ',
120
- segmentation_type: SegmentationTypeEnum::WHITELISTING,
121
- api_name: api_name
122
- )
123
- )
124
-
125
- if variation
126
- if campaign['type'] == CampaignTypes::VISUAL_AB || campaign['type'] == CampaignTypes::FEATURE_TEST
127
- decision[:variation_name] = variation['name']
128
- decision[:variation_id] = variation['id']
129
- if campaign['type'] == CampaignTypes::FEATURE_TEST
130
- decision[:is_feature_enabled] = variation['isFeatureEnabled']
131
- elsif campaign['type'] == CampaignTypes::VISUAL_AB
132
- decision[:is_user_whitelisted] = !!variation['name']
133
- end
134
- end
135
- @hooks_manager.execute(decision)
136
- end
137
-
138
- return variation if variation && variation['name']
139
- else
140
- @logger.log(
141
- LogLevelEnum::INFO,
142
- format(
143
- LogMessageEnum::InfoMessages::WHITELISTING_SKIPPED,
144
- file: FILE,
145
- campaign_key: campaign_key,
146
- user_id: user_id,
147
- api_name: api_name
148
- )
149
- )
98
+ if is_campaign_part_of_group
99
+ group_id = @settings_file["campaignGroups"][campaign["id"].to_s]
100
+ decision[:group_id] = group_id
101
+ group_name = @settings_file["groups"][group_id.to_s]["name"]
102
+ decision[:group_name] = group_name
150
103
  end
151
104
 
105
+ # evaluate whitelisting
106
+ variation = get_variation_if_whitelisting_passed(user_id, campaign, variation_targeting_variables, api_name, decision, true)
107
+ return variation if variation && variation['name']
108
+
152
109
  user_campaign_map = get_user_storage(user_id, campaign_key)
153
110
  variation = get_stored_variation(user_id, campaign_key, user_campaign_map) if valid_hash?(user_campaign_map)
154
111
 
@@ -194,8 +151,7 @@ class VWO
194
151
  )
195
152
  )
196
153
 
197
- if ([ApiMethods::TRACK, ApiMethods::GET_VARIATION_NAME, ApiMethods::GET_FEATURE_VARIABLE_VALUE].include? api_name) &&
198
- @user_storage_service && campaign['type'] != CampaignTypes::FEATURE_ROLLOUT
154
+ if ([ApiMethods::TRACK, ApiMethods::GET_VARIATION_NAME, ApiMethods::GET_FEATURE_VARIABLE_VALUE].include? api_name) && @user_storage_service
199
155
  @logger.log(
200
156
  LogLevelEnum::DEBUG,
201
157
  format(
@@ -223,82 +179,106 @@ class VWO
223
179
  end
224
180
 
225
181
  # Pre-segmentation
182
+ is_presegmentation = check_presegmentation(campaign, user_id, custom_variables, api_name)
183
+ is_presegmentation_and_traffic_passed = is_presegmentation && @bucketer.user_part_of_campaign?(user_id, campaign)
184
+ unless is_presegmentation_and_traffic_passed
185
+ return nil
186
+ end
226
187
 
227
- segments = get_segments(campaign)
228
- is_valid_segments = valid_value?(segments)
188
+ if is_presegmentation_and_traffic_passed && is_campaign_part_of_group
189
+ group_campaigns = get_group_campaigns(@settings_file, group_id)
190
+
191
+ if group_campaigns
192
+ is_any_campaign_whitelisted_or_stored = check_whitelisting_or_storage_for_grouped_campaigns(user_id, campaign, group_campaigns, group_name, variation_targeting_variables, true)
193
+
194
+ if is_any_campaign_whitelisted_or_stored
195
+ @logger.log(
196
+ LogLevelEnum::INFO,
197
+ format(
198
+ LogMessageEnum::InfoMessages::CALLED_CAMPAIGN_NOT_WINNER,
199
+ file: FILE,
200
+ campaign_key: campaign_key,
201
+ user_id: user_id,
202
+ group_name: group_name
203
+ )
204
+ )
205
+ return nil
206
+ end
207
+
208
+ eligible_campaigns = get_eligible_campaigns(user_id, group_campaigns, campaign, custom_variables)
209
+ non_eligible_campaigns_key = get_non_eligible_campaigns_key(eligible_campaigns, group_campaigns)
210
+
211
+ @logger.log(
212
+ LogLevelEnum::DEBUG,
213
+ format(
214
+ LogMessageEnum::DebugMessages::GOT_ELIGIBLE_CAMPAIGNS,
215
+ file: FILE,
216
+ user_id: user_id,
217
+ eligible_campaigns_key: get_eligible_campaigns_key(eligible_campaigns).join(","),
218
+ ineligible_campaigns_log_text: non_eligible_campaigns_key ? ("campaigns:" + non_eligible_campaigns_key.join("'")) : "no campaigns",
219
+ group_name: group_name
220
+ )
221
+ )
229
222
 
230
- if is_valid_segments
231
- unless custom_variables
232
223
  @logger.log(
233
224
  LogLevelEnum::INFO,
234
225
  format(
235
- LogMessageEnum::InfoMessages::NO_CUSTOM_VARIABLES,
226
+ LogMessageEnum::InfoMessages::GOT_ELIGIBLE_CAMPAIGNS,
236
227
  file: FILE,
237
- campaign_key: campaign_key,
238
228
  user_id: user_id,
239
- api_name: api_name
229
+ no_of_eligible_campaigns: eligible_campaigns.length,
230
+ no_of_group_campaigns: group_campaigns.length,
231
+ group_name: group_name
240
232
  )
241
233
  )
242
- custom_variables = {}
243
- end
244
- unless @segment_evaluator.evaluate(campaign_key, user_id, segments, custom_variables)
234
+
235
+ winner_campaign = get_winner_campaign(user_id, eligible_campaigns, group_id)
245
236
  @logger.log(
246
237
  LogLevelEnum::INFO,
247
238
  format(
248
- LogMessageEnum::InfoMessages::USER_FAILED_SEGMENTATION,
249
- file: FileNameEnum::SegmentEvaluator,
239
+ LogMessageEnum::InfoMessages::GOT_WINNER_CAMPAIGN,
240
+ file: FILE,
250
241
  user_id: user_id,
251
- campaign_key: campaign_key,
252
- custom_variables: custom_variables
242
+ campaign_key: winner_campaign["key"],
243
+ group_name: group_name
253
244
  )
254
245
  )
255
- return
246
+
247
+ if winner_campaign && winner_campaign["id"] == campaign["id"]
248
+ variation = get_variation_allotted(user_id, campaign, true)
249
+ if variation && variation['name']
250
+ save_user_storage(user_id, campaign_key, campaign['type'], variation['name'], goal_identifier, true) if variation['name']
251
+ else
252
+ return nil
253
+ end
254
+ else
255
+ @logger.log(
256
+ LogLevelEnum::INFO,
257
+ format(
258
+ LogMessageEnum::InfoMessages::CALLED_CAMPAIGN_NOT_WINNER,
259
+ file: FILE,
260
+ campaign_key: campaign_key,
261
+ user_id: user_id,
262
+ group_name: group_name
263
+ )
264
+ )
265
+ return nil
266
+ end
256
267
  end
257
- @logger.log(
258
- LogLevelEnum::INFO,
259
- format(
260
- LogMessageEnum::InfoMessages::USER_PASSED_SEGMENTATION,
261
- file: FileNameEnum::SegmentEvaluator,
262
- user_id: user_id,
263
- campaign_key: campaign_key,
264
- custom_variables: custom_variables
265
- )
266
- )
267
- else
268
- @logger.log(
269
- LogLevelEnum::INFO,
270
- format(
271
- LogMessageEnum::InfoMessages::SKIPPING_SEGMENTATION,
272
- file: FILE,
273
- campaign_key: campaign_key,
274
- user_id: user_id,
275
- api_name: api_name,
276
- variation: ''
277
- )
278
- )
279
268
  end
280
269
 
281
- variation = get_variation_allotted(user_id, campaign)
282
-
283
- if variation && variation['name']
284
- save_user_storage(user_id, campaign_key, variation['name'], goal_identifier) if variation['name']
270
+ if variation.nil?
271
+ variation = get_variation_allotted(user_id, campaign)
285
272
 
286
- @logger.log(
287
- LogLevelEnum::INFO,
288
- format(
289
- LogMessageEnum::InfoMessages::VARIATION_ALLOCATED,
290
- file: FILE,
291
- campaign_key: campaign_key,
292
- user_id: user_id,
293
- variation_name: variation['name'],
294
- campaign_type: campaign['type']
273
+ if variation && variation['name']
274
+ save_user_storage(user_id, campaign_key, campaign['type'], variation['name'], goal_identifier) if variation['name']
275
+ else
276
+ @logger.log(
277
+ LogLevelEnum::INFO,
278
+ format(LogMessageEnum::InfoMessages::NO_VARIATION_ALLOCATED, file: FILE, campaign_key: campaign_key, user_id: user_id)
295
279
  )
296
- )
297
- else
298
- @logger.log(
299
- LogLevelEnum::INFO,
300
- format(LogMessageEnum::InfoMessages::NO_VARIATION_ALLOCATED, file: FILE, campaign_key: campaign_key, user_id: user_id)
301
- )
280
+ end
281
+
302
282
  end
303
283
 
304
284
  if variation
@@ -321,7 +301,7 @@ class VWO
321
301
  #
322
302
  # @return[Hash]
323
303
 
324
- def get_variation_allotted(user_id, campaign)
304
+ def get_variation_allotted(user_id, campaign, disable_logs = false)
325
305
  unless valid_value?(user_id)
326
306
  @logger.log(
327
307
  LogLevelEnum::ERROR,
@@ -341,7 +321,8 @@ class VWO
341
321
  user_id: user_id,
342
322
  campaign_key: campaign['key'],
343
323
  method: 'get_variation_allotted'
344
- )
324
+ ),
325
+ disable_logs
345
326
  )
346
327
  variation
347
328
  else
@@ -354,7 +335,8 @@ class VWO
354
335
  user_id: user_id,
355
336
  campaign_key: nil,
356
337
  method: 'get_variation_allotted'
357
- )
338
+ ),
339
+ disable_logs
358
340
  )
359
341
  nil
360
342
  end
@@ -413,13 +395,15 @@ class VWO
413
395
  # @param[String] :campaign_key Unique campaign identifier
414
396
  # @param[String] :variation_name Variation identifier
415
397
  # @param[String] :goal_identifier The unique campaign's goal identifier
398
+ # @param[Boolean] :disable_logs optional: disable logs if True
416
399
  # @return[Boolean] true if found otherwise false
417
400
 
418
- def save_user_storage(user_id, campaign_key, variation_name, goal_identifier)
401
+ def save_user_storage(user_id, campaign_key, campaign_type, variation_name, goal_identifier, disable_logs = false)
419
402
  unless @user_storage_service
420
403
  @logger.log(
421
404
  LogLevelEnum::DEBUG,
422
- format(LogMessageEnum::DebugMessages::NO_USER_STORAGE_SERVICE_SAVE, file: FILE)
405
+ format(LogMessageEnum::DebugMessages::NO_USER_STORAGE_SERVICE_SAVE, file: FILE),
406
+ disable_logs
423
407
  )
424
408
  return false
425
409
  end
@@ -435,13 +419,28 @@ class VWO
435
419
 
436
420
  @logger.log(
437
421
  LogLevelEnum::INFO,
438
- format(LogMessageEnum::InfoMessages::SAVING_DATA_USER_STORAGE_SERVICE, file: FILE, user_id: user_id)
422
+ format(LogMessageEnum::InfoMessages::SAVING_DATA_USER_STORAGE_SERVICE, file: FILE, user_id: user_id),
423
+ disable_logs
424
+ )
425
+
426
+ @logger.log(
427
+ LogLevelEnum::INFO,
428
+ format(
429
+ LogMessageEnum::InfoMessages::VARIATION_ALLOCATED,
430
+ file: FILE,
431
+ campaign_key: campaign_key,
432
+ user_id: user_id,
433
+ variation_name: variation_name,
434
+ campaign_type: campaign_type
435
+ ),
436
+ disable_logs
439
437
  )
440
438
  true
441
439
  rescue StandardError
442
440
  @logger.log(
443
441
  LogLevelEnum::ERROR,
444
- format(LogMessageEnum::ErrorMessages::SAVE_USER_STORAGE_SERVICE_FAILED, file: FILE, user_id: user_id)
442
+ format(LogMessageEnum::ErrorMessages::SAVE_USER_STORAGE_SERVICE_FAILED, file: FILE, user_id: user_id),
443
+ disable_logs
445
444
  )
446
445
  false
447
446
  end
@@ -455,10 +454,11 @@ class VWO
455
454
  # @param[String] :api_name The key Passed to identify the calling API
456
455
  # @param[String] :campaign_key Unique campaign key
457
456
  # @param[Hash] :variation_targeting_variables Key/value pair of Whitelisting Custom Attributes
457
+ # @param[Boolean] :disable_logs optional: disable logs if True
458
458
  #
459
459
  # @return[Hash]
460
460
 
461
- def evaluate_whitelisting(user_id, campaign, api_name, campaign_key, variation_targeting_variables = {})
461
+ def evaluate_whitelisting(user_id, campaign, api_name, campaign_key, variation_targeting_variables = {}, disable_logs = false)
462
462
  if variation_targeting_variables.nil?
463
463
  variation_targeting_variables = { '_vwo_user_id' => user_id }
464
464
  else
@@ -470,7 +470,7 @@ class VWO
470
470
  segments = get_segments(variation)
471
471
  is_valid_segments = valid_value?(segments)
472
472
  if is_valid_segments
473
- if @segment_evaluator.evaluate(campaign_key, user_id, segments, variation_targeting_variables)
473
+ if @segment_evaluator.evaluate(campaign_key, user_id, segments, variation_targeting_variables, disable_logs)
474
474
  targeted_variations.push(variation)
475
475
  status = StatusEnum::PASSED
476
476
  else
@@ -488,7 +488,8 @@ class VWO
488
488
  variation_name: variation['name'],
489
489
  segmentation_type: SegmentationTypeEnum::WHITELISTING,
490
490
  api_name: api_name
491
- )
491
+ ),
492
+ disable_logs
492
493
  )
493
494
  else
494
495
  @logger.log(
@@ -500,7 +501,8 @@ class VWO
500
501
  user_id: user_id,
501
502
  api_name: api_name,
502
503
  variation: variation['name']
503
- )
504
+ ),
505
+ disable_logs
504
506
  )
505
507
  end
506
508
  end
@@ -525,7 +527,8 @@ class VWO
525
527
  whitelisted_variation = @bucketer.get_variation(
526
528
  targeted_variations_deep_clone,
527
529
  @bucketer.get_bucket_value_for_user(
528
- user_id
530
+ user_id,
531
+ campaign
529
532
  )
530
533
  )
531
534
  else
@@ -553,18 +556,26 @@ class VWO
553
556
  end
554
557
  end
555
558
 
559
+ def scale_campaigns_weight(campaigns)
560
+ normalize_weight = 100/campaigns.length
561
+ campaigns.each do |campaign|
562
+ campaign['weight'] = normalize_weight
563
+ end
564
+ end
556
565
  # Get the UserStorageData after looking up into get method
557
566
  # Being provided via UserStorageService
558
567
  #
559
568
  # @param[String]: Unique user identifier
560
569
  # @param[String]: Unique campaign key
570
+ # @param[Boolean] :disable_logs if True
561
571
  # @return[Hash|Boolean]: user_storage data
562
572
 
563
- def get_user_storage(user_id, campaign_key)
573
+ def get_user_storage(user_id, campaign_key, disable_logs = false)
564
574
  unless @user_storage_service
565
575
  @logger.log(
566
576
  LogLevelEnum::DEBUG,
567
- format(LogMessageEnum::DebugMessages::NO_USER_STORAGE_SERVICE_LOOKUP, file: FILE)
577
+ format(LogMessageEnum::DebugMessages::NO_USER_STORAGE_SERVICE_LOOKUP, file: FILE),
578
+ disable_logs
568
579
  )
569
580
  return false
570
581
  end
@@ -577,13 +588,15 @@ class VWO
577
588
  file: FILE,
578
589
  user_id: user_id,
579
590
  status: data.nil? ? 'Not Found' : 'Found'
580
- )
591
+ ),
592
+ disable_logs
581
593
  )
582
594
  data
583
595
  rescue StandardError
584
596
  @logger.log(
585
597
  LogLevelEnum::ERROR,
586
- format(LogMessageEnum::ErrorMessages::LOOK_UP_USER_STORAGE_SERVICE_FAILED, file: FILE, user_id: user_id)
598
+ format(LogMessageEnum::ErrorMessages::LOOK_UP_USER_STORAGE_SERVICE_FAILED, file: FILE, user_id: user_id),
599
+ disable_logs
587
600
  )
588
601
  false
589
602
  end
@@ -593,10 +606,11 @@ class VWO
593
606
  # @param[String] :user_id
594
607
  # @param[String] :campaign_key campaign identified
595
608
  # @param[Hash] :user_campaign_map BucketMap consisting of stored user variation
609
+ # @param[Boolean] :disable_logs if True
596
610
  #
597
611
  # @return[Object, nil] if found then variation settings object otherwise None
598
612
 
599
- def get_stored_variation(user_id, campaign_key, user_campaign_map)
613
+ def get_stored_variation(user_id, campaign_key, user_campaign_map, disable_logs = false)
600
614
  return unless user_campaign_map['campaign_key'] == campaign_key
601
615
 
602
616
  variation_name = user_campaign_map['variation_name']
@@ -608,7 +622,8 @@ class VWO
608
622
  campaign_key: campaign_key,
609
623
  user_id: user_id,
610
624
  variation_name: variation_name
611
- )
625
+ ),
626
+ disable_logs
612
627
  )
613
628
 
614
629
  get_campaign_variation(
@@ -617,6 +632,277 @@ class VWO
617
632
  variation_name
618
633
  )
619
634
  end
635
+
636
+ # this function check whether pre-segmentation is passed or not
637
+ #
638
+ # @param[String] :user_id The unique key assigned to User
639
+ # @param[Hash] :campaign Campaign hash for Unique campaign key
640
+ # @param[Hash] :custom_variables Key/value pair for segmentation
641
+ # @param[String] :api_name The key Passed to identify the calling API
642
+ # @param[Boolean] :disable_logs optional: disable logs if True
643
+ #
644
+ # @return[Boolean]
645
+ def check_presegmentation(campaign, user_id, custom_variables, api_name, disable_logs = false)
646
+ campaign_key = campaign['key']
647
+ segments = get_segments(campaign)
648
+ is_valid_segments = valid_value?(segments)
649
+
650
+ if is_valid_segments
651
+ unless custom_variables
652
+ @logger.log(
653
+ LogLevelEnum::INFO,
654
+ format(
655
+ LogMessageEnum::InfoMessages::NO_CUSTOM_VARIABLES,
656
+ file: FILE,
657
+ campaign_key: campaign_key,
658
+ user_id: user_id,
659
+ api_name: api_name
660
+ ),
661
+ disable_logs
662
+ )
663
+ custom_variables = {}
664
+ end
665
+ unless @segment_evaluator.evaluate(campaign_key, user_id, segments, custom_variables, disable_logs)
666
+ @logger.log(
667
+ LogLevelEnum::INFO,
668
+ format(
669
+ LogMessageEnum::InfoMessages::USER_FAILED_SEGMENTATION,
670
+ file: FileNameEnum::SegmentEvaluator,
671
+ user_id: user_id,
672
+ campaign_key: campaign_key,
673
+ custom_variables: custom_variables
674
+ ),
675
+ disable_logs
676
+ )
677
+ return false
678
+ end
679
+ @logger.log(
680
+ LogLevelEnum::INFO,
681
+ format(
682
+ LogMessageEnum::InfoMessages::USER_PASSED_SEGMENTATION,
683
+ file: FileNameEnum::SegmentEvaluator,
684
+ user_id: user_id,
685
+ campaign_key: campaign_key,
686
+ custom_variables: custom_variables
687
+ ),
688
+ disable_logs
689
+ )
690
+ else
691
+ @logger.log(
692
+ LogLevelEnum::INFO,
693
+ format(
694
+ LogMessageEnum::InfoMessages::SKIPPING_SEGMENTATION,
695
+ file: FILE,
696
+ campaign_key: campaign_key,
697
+ user_id: user_id,
698
+ api_name: api_name,
699
+ variation: ''
700
+ ),
701
+ disable_logs
702
+ )
703
+ end
704
+ true
705
+ end
706
+
707
+ # Finds and returns eligible campaigns from group_campaigns.
708
+ #
709
+ # @param[String] :user_id The unique key assigned to User
710
+ # @param[Hash] :called_campaign campaign for which api is called
711
+ # @param[Array] :group_campaigns campaigns part of group
712
+ # @param[String] :custom_variables Key/value pair for segmentation
713
+ #
714
+ # @return[Array]
715
+ def get_eligible_campaigns(user_id, group_campaigns, called_campaign, custom_variables)
716
+ eligible_campaigns = []
717
+
718
+ group_campaigns.each do |campaign|
719
+ if called_campaign["id"] == campaign["id"] || check_presegmentation(campaign, user_id, custom_variables, '', true) && @bucketer.user_part_of_campaign?(user_id, campaign)
720
+ eligible_campaigns.append(campaign)
721
+ end
722
+ end
723
+ return eligible_campaigns
724
+ end
725
+
726
+ # Finds and returns the winner campaign from eligible_campaigns list.
727
+ #
728
+ # @param[String] :user_id The unique key assigned to User
729
+ # @param[Array] :eligible_campaigns campaigns part of group which were eligible to be winner
730
+ #
731
+ # @return[Hash]
732
+ def get_winner_campaign(user_id, eligible_campaigns, group_id)
733
+ if eligible_campaigns.length == 1
734
+ return eligible_campaigns[0]
735
+ end
736
+
737
+ eligible_campaigns = scale_campaigns_weight(eligible_campaigns)
738
+ eligible_campaigns = set_campaign_allocation(eligible_campaigns)
739
+ bucket_value = @bucketer.get_bucket_value_for_user(user_id, {}, group_id, true)
740
+ return @bucketer.get_campaign_using_range(bucket_value, eligible_campaigns)
741
+ end
742
+
743
+ # Get campaign keys of all eligible Campaigns.
744
+ #
745
+ # @param[Array] :eligible_campaigns campaigns part of group which were eligible to be winner
746
+ #
747
+ # @return[Array]
748
+ def get_eligible_campaigns_key(eligible_campaigns)
749
+ eligible_campaigns_key = []
750
+ eligible_campaigns.each do |campaign|
751
+ eligible_campaigns_key.append(campaign["key"])
752
+ end
753
+ eligible_campaigns_key
754
+ end
755
+
756
+ # Get campaign keys of all non eligible Campaigns.
757
+ #
758
+ # @param[Array] :eligible_campaigns campaigns part of group which were eligible to be winner
759
+ # @param[Array] :group_campaigns campaigns part of group
760
+ #
761
+ # @return[Array]
762
+ def get_non_eligible_campaigns_key(eligible_campaigns, group_campaigns)
763
+ non_eligible_campaigns_key = []
764
+ group_campaigns.each do |campaign|
765
+ unless eligible_campaigns.include? campaign
766
+ non_eligible_campaigns_key.append(campaign["key"])
767
+ end
768
+ end
769
+ non_eligible_campaigns_key
770
+ end
771
+
772
+ # Checks if any other campaign in groupCampaigns satisfies whitelisting or is in user storage.
773
+ #
774
+ # @param[String] :user_id the unique ID assigned to User
775
+ # @param[Hash] :called_campaign campaign for which api is called
776
+ # @param[Array] :group_campaigns campaigns part of group
777
+ # @param[String] :group_name group name
778
+ # @param[Hash] :variation_targeting_variables Key/value pair of Whitelisting Custom Attributes
779
+ # @param[Boolean] :disable_logs optional: disable logs if True
780
+ # @return[Boolean]
781
+
782
+ def check_whitelisting_or_storage_for_grouped_campaigns(user_id, called_campaign, group_campaigns, group_name, variation_targeting_variables, disable_logs = false)
783
+ group_campaigns.each do |campaign|
784
+ if called_campaign["id"] != campaign["id"]
785
+ targeted_variation = evaluate_whitelisting(
786
+ user_id,
787
+ campaign,
788
+ '',
789
+ campaign["key"],
790
+ variation_targeting_variables,
791
+ true
792
+ )
793
+ if targeted_variation
794
+ @logger.log(
795
+ LogLevelEnum::INFO,
796
+ format(
797
+ LogMessageEnum::InfoMessages::OTHER_CAMPAIGN_SATISFIES_WHITELISTING_OR_STORAGE,
798
+ file: FILE,
799
+ campaign_key: campaign["key"],
800
+ user_id: user_id,
801
+ group_name: group_name,
802
+ type: "whitelisting"
803
+ ),
804
+ disable_logs
805
+ )
806
+ return true
807
+ end
808
+ end
809
+ end
810
+
811
+ group_campaigns.each do |campaign|
812
+ if called_campaign["id"] != campaign["id"]
813
+ user_storage_data = get_user_storage(user_id, campaign["key"], true)
814
+ if user_storage_data
815
+ @logger.log(
816
+ LogLevelEnum::INFO,
817
+ format(
818
+ LogMessageEnum::InfoMessages::OTHER_CAMPAIGN_SATISFIES_WHITELISTING_OR_STORAGE,
819
+ file: FILE,
820
+ campaign_key: campaign["key"],
821
+ user_id: user_id,
822
+ group_name: group_name,
823
+ type: "user storage"
824
+ ),
825
+ disable_logs
826
+ )
827
+ return true
828
+ end
829
+ end
830
+ end
831
+ false
832
+ end
833
+
834
+ # Get variation if whitelisting passes
835
+ #
836
+ # @param[String] :user_id the unique ID assigned to User
837
+ # @param[Hash] :campaign campaign for which checking whitelisting
838
+ # @param[Hash] :variation_targeting_variables Key/value pair of Whitelisting Custom Attributes
839
+ # @param[String] :api_name The key Passed to identify the calling API
840
+ # @param[Hash] :decision data containing campaign info passed to hooks manager
841
+ # @param[Boolean] :disable_logs optional: disable logs if True
842
+ # @return[Hash]
843
+ def get_variation_if_whitelisting_passed(user_id, campaign, variation_targeting_variables, api_name, decision, disable_logs = false)
844
+ campaign_key = campaign['key']
845
+ if campaign['isForcedVariationEnabled']
846
+ variation = evaluate_whitelisting(
847
+ user_id,
848
+ campaign,
849
+ api_name,
850
+ campaign_key,
851
+ variation_targeting_variables,
852
+ disable_logs
853
+ )
854
+ status = if variation
855
+ StatusEnum::PASSED
856
+ else
857
+ StatusEnum::FAILED
858
+ end
859
+
860
+ @logger.log(
861
+ LogLevelEnum::INFO,
862
+ format(
863
+ LogMessageEnum::InfoMessages::SEGMENTATION_STATUS,
864
+ file: FILE,
865
+ campaign_key: campaign_key,
866
+ user_id: user_id,
867
+ status: status,
868
+ custom_variables: variation_targeting_variables,
869
+ variation_name: status == StatusEnum::PASSED ? "and #{variation['name']} is Assigned" : ' ',
870
+ segmentation_type: SegmentationTypeEnum::WHITELISTING,
871
+ api_name: api_name
872
+ ),
873
+ disable_logs
874
+ )
875
+
876
+ if variation
877
+ if campaign['type'] == CampaignTypes::VISUAL_AB || campaign['type'] == CampaignTypes::FEATURE_TEST
878
+ decision[:variation_name] = variation['name']
879
+ decision[:variation_id] = variation['id']
880
+ if campaign['type'] == CampaignTypes::FEATURE_TEST
881
+ decision[:is_feature_enabled] = variation['isFeatureEnabled']
882
+ elsif campaign['type'] == CampaignTypes::VISUAL_AB
883
+ decision[:is_user_whitelisted] = !!variation['name']
884
+ end
885
+ end
886
+ @hooks_manager.execute(decision)
887
+ end
888
+
889
+ return variation if variation && variation['name']
890
+ else
891
+ @logger.log(
892
+ LogLevelEnum::INFO,
893
+ format(
894
+ LogMessageEnum::InfoMessages::WHITELISTING_SKIPPED,
895
+ file: FILE,
896
+ campaign_key: campaign_key,
897
+ user_id: user_id,
898
+ api_name: api_name
899
+ ),
900
+ disable_logs
901
+ )
902
+ end
903
+ nil
904
+ end
905
+
620
906
  end
621
907
  end
622
908
  end
data/lib/vwo/enums.rb CHANGED
@@ -113,6 +113,7 @@ class VWO
113
113
  BULK_NOT_PROCESSED = "(%<file>s): Batch events couldn't be received by VWO. Calling Flush Callback with error and data."
114
114
  BEFORE_FLUSHING = '(%<file>s): Flushing events queue %<manually>s having %<length>s events %<timer>s queue summary: %<queue_metadata>s'
115
115
  EVENT_BATCHING_INSUFFICIENT = '(%<file>s): %<key>s not provided, assigning default value'
116
+ GOT_ELIGIBLE_CAMPAIGNS = "(%<file>s): Campaigns:%<eligible_campaigns_key>s are eligible, %<ineligible_campaigns_log_text>s are ineligible from the Group:%<group_name>s for the User ID:%<user_id>s"
116
117
  end
117
118
 
118
119
  # Info Messages
@@ -152,9 +153,13 @@ class VWO
152
153
  CAMPAIGN_NOT_ACTIVATED = '(%<file>s): Activate the campaign:%<campaign_key>s for User ID:%<user_id>s to %<reason>s.'
153
154
  GOAL_ALREADY_TRACKED = '(%<file>s): Goal:%<goal_identifier>s of Campaign:%<campaign_key>s for User ID:%<user_id>s has already been tracked earlier. Skipping now'
154
155
  USER_ALREADY_TRACKED = '(%<file>s): User ID:%<user_id>s for Campaign:%<campaign_key>s has already been tracked earlier for "%<api_name>s" API. Skipping now'
155
- API_CALLED = '(%<file>s): API: {api_name} called for UserId:%<user_id>s'
156
+ API_CALLED = '(%<file>s): API: %<api_name>s called for UserId:%<user_id>s'
156
157
  BULK_IMPRESSION_SUCCESS = '(%<file>s): Impression event - %<end_point>s was successfully received by VWO having accountId:%<a>s'
157
158
  AFTER_FLUSHING = '(%<file>s): Events queue having %<length>s events has been flushed %<manually>s queue summary: %<queue_metadata>s'
159
+ GOT_WINNER_CAMPAIGN = "(%<file>s): Campaign:%<campaign_key>s is selected from the mutually exclusive group:%<group_name>s for the User ID:%<user_id>s"
160
+ GOT_ELIGIBLE_CAMPAIGNS = "(%<file>s): Got %<no_of_eligible_campaigns>s eligible winners out of %<no_of_group_campaigns>s from the Group:%<group_name>s and for User ID:%<user_id>s"
161
+ CALLED_CAMPAIGN_NOT_WINNER = "(%<file>s): Campaign:%<campaign_key>s does not qualify from the mutually exclusive group:%<group_name>s for User ID:%<user_id>s"
162
+ OTHER_CAMPAIGN_SATISFIES_WHITELISTING_OR_STORAGE = "(%<file>s): Campaign:%<campaign_key>s of Group:%<group_name>s satisfies %<type>s for User ID:%<user_id>s"
158
163
  end
159
164
 
160
165
  # Warning Messages
data/lib/vwo/logger.rb CHANGED
@@ -28,8 +28,10 @@ class VWO
28
28
  end
29
29
 
30
30
  # Override this method to handle logs in a custom manner
31
- def log(level, message)
32
- @@logger_instance.log(level, message)
31
+ def log(level, message, disable_logs = false)
32
+ unless disable_logs
33
+ @@logger_instance.log(level, message)
34
+ end
33
35
  end
34
36
 
35
37
  def instance
@@ -91,6 +91,7 @@ class VWO
91
91
  '$ref' => '#/definitions/variables_schema'
92
92
  }
93
93
  },
94
+ isBucketingSeedEnabled: ['boolean'],
94
95
  minItems: 2
95
96
  }
96
97
  },
@@ -63,10 +63,11 @@ class VWO
63
63
  # @param[String] :user_id Unique user identifier
64
64
  # @param[Hash] :dsl Segments provided in the settings_file
65
65
  # @param[Hash] :custom_variables Custom variables provided in the apis
66
+ # @param[Boolean] :disable_logs disable logs if True
66
67
  #
67
68
  # @return[Boolean] true if user passed pre-segmentation, else false
68
69
  #
69
- def evaluate(campaign_key, user_id, dsl, custom_variables)
70
+ def evaluate(campaign_key, user_id, dsl, custom_variables, disable_logs = false)
70
71
  result = evaluate_util(dsl, custom_variables) if valid_value?(dsl)
71
72
  result
72
73
  rescue StandardError => e
@@ -79,7 +80,8 @@ class VWO
79
80
  campaign_key: campaign_key,
80
81
  custom_variables: custom_variables,
81
82
  error_message: e
82
- )
83
+ ),
84
+ disable_logs
83
85
  )
84
86
  false
85
87
  end
@@ -57,6 +57,26 @@ class VWO
57
57
  end
58
58
  end
59
59
 
60
+ # Sets campaign allocation range in the provided campaigns list
61
+ #
62
+ # @param [Array]: Array of Campaigns
63
+ def set_campaign_allocation(campaigns)
64
+ current_allocation = 0
65
+ campaigns.each do |campaign|
66
+ step_factor = get_variation_bucketing_range(campaign['weight'])
67
+ if step_factor > 0
68
+ start_range = current_allocation + 1
69
+ end_range = current_allocation + step_factor
70
+ campaign['min_range'] = start_range
71
+ campaign['max_range'] = end_range
72
+ current_allocation += step_factor
73
+ else
74
+ campaign['min_range'] = -1
75
+ campaign['max_range'] = -1
76
+ end
77
+ end
78
+ end
79
+
60
80
  # Returns goal from given campaign_key and gaol_identifier.
61
81
  # @param[String] :campaign Campaign object
62
82
  # @param[String] :goal_identifier Goal identifier
@@ -249,6 +269,44 @@ class VWO
249
269
  return campaign
250
270
  end
251
271
 
272
+ # Checks whether a campaign is part of a group.
273
+ #
274
+ # @param[Hash] :settings_file Settings file for the project
275
+ # @param[Integer] :campaign_id Id of campaign which is to be checked
276
+ # @return[Boolean]
277
+ def is_part_of_group(settings_file, campaign_id)
278
+ if settings_file["campaignGroups"] && (settings_file["campaignGroups"].has_key?(campaign_id.to_s))
279
+ return true
280
+ end
281
+ false
282
+ end
283
+
284
+ # Returns campaigns which are part of given group using group_id.
285
+ #
286
+ # @param[Hash] :settings_file Settings file for the project
287
+ # @param[Integer] :group_id id of group whose campaigns are to be return
288
+ # @return[Array]
289
+ def get_group_campaigns(settings_file, group_id)
290
+ group_campaign_ids = []
291
+ group_campaigns = []
292
+ groups = settings_file["groups"]
293
+
294
+ if groups && groups.has_key?(group_id.to_s)
295
+ group_campaign_ids = groups[group_id.to_s]["campaigns"]
296
+ end
297
+
298
+ if group_campaign_ids
299
+ group_campaign_ids.each do |campaign_id|
300
+ settings_file["campaigns"].each do |campaign|
301
+ if campaign["id"] == campaign_id && campaign["status"] == STATUS_RUNNING
302
+ group_campaigns.append(campaign)
303
+ end
304
+ end
305
+ end
306
+ end
307
+ group_campaigns
308
+ end
309
+
252
310
  end
253
311
  end
254
312
  end
data/lib/vwo.rb CHANGED
@@ -413,7 +413,6 @@ class VWO
413
413
  )
414
414
  end
415
415
  end
416
- variation['name']
417
416
  else
418
417
  @logger.log(
419
418
  LogLevelEnum::INFO,
@@ -425,8 +424,8 @@ class VWO
425
424
  api_name: ApiMethods::ACTIVATE
426
425
  )
427
426
  )
428
- nil
429
427
  end
428
+ variation['name']
430
429
  rescue StandardError => e
431
430
  @logger.log(
432
431
  LogLevelEnum::ERROR,
@@ -676,7 +675,7 @@ class VWO
676
675
  if !identifiers.include? goal_identifier
677
676
  updated_goal_identifier = variation['goal_identifier']
678
677
  updated_goal_identifier += VWO_DELIMITER + goal_identifier
679
- @variation_decider.save_user_storage(user_id, campaign['key'], variation['name'], updated_goal_identifier) if variation['name']
678
+ @variation_decider.save_user_storage(user_id, campaign['key'], campaign['name'], variation['name'], updated_goal_identifier) if variation['name']
680
679
  # set variation at user storage
681
680
  elsif !should_track_returning_user
682
681
  @logger.log(
@@ -870,80 +869,85 @@ class VWO
870
869
  return false unless variation
871
870
 
872
871
  # if campaign type is feature_test Send track call to server
873
- if campaign_type == CampaignTypes::FEATURE_TEST
874
- if is_eligible_to_send_impression(should_track_returning_user)
875
- if defined?(@batch_events)
876
- impression = create_bulk_event_impression(
877
- @settings_file,
878
- campaign['id'],
879
- variation['id'],
880
- user_id
881
- )
882
- @batch_events_queue.enqueue(impression)
883
- else
884
- impression = create_impression(
885
- @settings_file,
886
- campaign['id'],
887
- variation['id'],
888
- user_id,
889
- @sdk_key,
890
- goal_id: nil,
891
- revenue: nil,
892
- usage_stats: @usage_stats.usage_stats
893
- )
894
872
 
895
- @event_dispatcher.dispatch(impression)
896
- @logger.log(
897
- LogLevelEnum::INFO,
898
- format(
899
- LogMessageEnum::InfoMessages::MAIN_KEYS_FOR_IMPRESSION,
900
- file: FILE,
901
- campaign_id: impression[:experiment_id],
902
- sdk_key: @sdk_key,
903
- account_id: impression[:account_id],
904
- variation_id: impression[:combination]
905
- )
906
- )
907
- end
908
- result = variation['isFeatureEnabled']
909
- if result
910
- @logger.log(
911
- LogLevelEnum::INFO,
912
- format(
913
- LogMessageEnum::InfoMessages::FEATURE_ENABLED_FOR_USER,
914
- file: FILE,
915
- user_id: user_id,
916
- feature_key: campaign_key,
917
- api_name: ApiMethods::IS_FEATURE_ENABLED
918
- )
919
- )
920
- else
921
- @logger.log(
922
- LogLevelEnum::INFO,
923
- format(
924
- LogMessageEnum::InfoMessages::FEATURE_NOT_ENABLED_FOR_USER,
925
- file: FILE,
926
- user_id: user_id,
927
- feature_key: campaign_key,
928
- api_name: ApiMethods::IS_FEATURE_ENABLED
929
- )
930
- )
931
- end
932
- return result
873
+ if is_eligible_to_send_impression(should_track_returning_user)
874
+ if defined?(@batch_events)
875
+ impression = create_bulk_event_impression(
876
+ @settings_file,
877
+ campaign['id'],
878
+ variation['id'],
879
+ user_id
880
+ )
881
+ @batch_events_queue.enqueue(impression)
933
882
  else
883
+ impression = create_impression(
884
+ @settings_file,
885
+ campaign['id'],
886
+ variation['id'],
887
+ user_id,
888
+ @sdk_key,
889
+ nil,
890
+ nil,
891
+ usage_stats: @usage_stats.usage_stats
892
+ )
893
+
894
+ @event_dispatcher.dispatch(impression)
934
895
  @logger.log(
935
896
  LogLevelEnum::INFO,
936
897
  format(
937
- LogMessageEnum::InfoMessages::USER_ALREADY_TRACKED,
898
+ LogMessageEnum::InfoMessages::MAIN_KEYS_FOR_IMPRESSION,
938
899
  file: FILE,
939
- user_id: user_id,
940
- campaign_key: campaign_key,
941
- api_name: ApiMethods::IS_FEATURE_ENABLED
900
+ campaign_id: impression[:experiment_id],
901
+ sdk_key: @sdk_key,
902
+ account_id: impression[:account_id],
903
+ variation_id: impression[:combination]
942
904
  )
943
905
  )
944
906
  end
907
+
908
+ else
909
+ @logger.log(
910
+ LogLevelEnum::INFO,
911
+ format(
912
+ LogMessageEnum::InfoMessages::USER_ALREADY_TRACKED,
913
+ file: FILE,
914
+ user_id: user_id,
915
+ campaign_key: campaign_key,
916
+ api_name: ApiMethods::IS_FEATURE_ENABLED
917
+ )
918
+ )
945
919
  end
946
- true
920
+ if campaign_type == CampaignTypes::FEATURE_ROLLOUT
921
+ result = true
922
+ else
923
+ result = variation['isFeatureEnabled']
924
+ end
925
+
926
+ if result
927
+ @logger.log(
928
+ LogLevelEnum::INFO,
929
+ format(
930
+ LogMessageEnum::InfoMessages::FEATURE_ENABLED_FOR_USER,
931
+ file: FILE,
932
+ user_id: user_id,
933
+ feature_key: campaign_key,
934
+ api_name: ApiMethods::IS_FEATURE_ENABLED
935
+ )
936
+ )
937
+ else
938
+ @logger.log(
939
+ LogLevelEnum::INFO,
940
+ format(
941
+ LogMessageEnum::InfoMessages::FEATURE_NOT_ENABLED_FOR_USER,
942
+ file: FILE,
943
+ user_id: user_id,
944
+ feature_key: campaign_key,
945
+ api_name: ApiMethods::IS_FEATURE_ENABLED
946
+ )
947
+ )
948
+ end
949
+
950
+ result
947
951
  rescue StandardError => e
948
952
  @logger.log(
949
953
  LogLevelEnum::ERROR,
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vwo-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.16.0
4
+ version: 1.22.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - VWO
@@ -87,6 +87,7 @@ executables: []
87
87
  extensions: []
88
88
  extra_rdoc_files: []
89
89
  files:
90
+ - lib/abc.txt
90
91
  - lib/vwo.rb
91
92
  - lib/vwo/constants.rb
92
93
  - lib/vwo/core/bucketer.rb