vwo-sdk 1.5.0 → 1.15.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/vwo/constants.rb +26 -3
- data/lib/vwo/core/bucketer.rb +4 -6
- data/lib/vwo/core/variation_decider.rb +337 -45
- data/lib/vwo/enums.rb +49 -9
- data/lib/vwo/logger.rb +1 -1
- data/lib/vwo/schemas/settings_file.rb +1 -1
- data/lib/vwo/services/batch_events_dispatcher.rb +110 -0
- data/lib/vwo/services/batch_events_queue.rb +175 -0
- data/lib/vwo/services/event_dispatcher.rb +1 -13
- data/lib/vwo/services/hooks_manager.rb +36 -0
- data/lib/vwo/services/operand_evaluator.rb +10 -2
- data/lib/vwo/services/segment_evaluator.rb +5 -26
- data/lib/vwo/services/settings_file_manager.rb +8 -4
- data/lib/vwo/services/settings_file_processor.rb +6 -1
- data/lib/vwo/services/usage_stats.rb +29 -0
- data/lib/vwo/user_storage.rb +1 -1
- data/lib/vwo/utils/campaign.rb +108 -1
- data/lib/vwo/utils/custom_dimensions.rb +26 -3
- data/lib/vwo/utils/feature.rb +1 -1
- data/lib/vwo/utils/function.rb +1 -1
- data/lib/vwo/utils/impression.rb +58 -7
- data/lib/vwo/utils/request.rb +15 -1
- data/lib/vwo/utils/segment.rb +1 -1
- data/lib/vwo/utils/uuid.rb +1 -1
- data/lib/vwo/utils/validations.rb +85 -1
- data/lib/vwo.rb +586 -203
- metadata +36 -13
data/lib/vwo/utils/request.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2019-
|
1
|
+
# Copyright 2019-2021 Wingify Software Pvt. Ltd.
|
2
2
|
#
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
4
|
# you may not use this file except in compliance with the License.
|
@@ -24,6 +24,20 @@ class VWO
|
|
24
24
|
uri.query = URI.encode_www_form(params)
|
25
25
|
Net::HTTP.get_response(uri)
|
26
26
|
end
|
27
|
+
|
28
|
+
def self.post(url, params, post_data)
|
29
|
+
uri = URI.parse(url)
|
30
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
31
|
+
http.use_ssl = true
|
32
|
+
uri.query = URI.encode_www_form(params)
|
33
|
+
headers = {
|
34
|
+
'Authorization'=>params[:env],
|
35
|
+
'Content-Type' =>'application/json',
|
36
|
+
'Accept'=>'application/json'
|
37
|
+
}
|
38
|
+
response = http.post(uri, post_data.to_json, headers)
|
39
|
+
response
|
40
|
+
end
|
27
41
|
end
|
28
42
|
end
|
29
43
|
end
|
data/lib/vwo/utils/segment.rb
CHANGED
data/lib/vwo/utils/uuid.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2019-
|
1
|
+
# Copyright 2019-2021 Wingify Software Pvt. Ltd.
|
2
2
|
#
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
4
|
# you may not use this file except in compliance with the License.
|
@@ -15,6 +15,9 @@
|
|
15
15
|
require 'json'
|
16
16
|
require 'json-schema'
|
17
17
|
require_relative '../schemas/settings_file'
|
18
|
+
require_relative '../logger'
|
19
|
+
require_relative '../enums'
|
20
|
+
require_relative '../constants'
|
18
21
|
|
19
22
|
class VWO
|
20
23
|
module Utils
|
@@ -59,6 +62,87 @@ class VWO
|
|
59
62
|
def valid_basic_data_type?(val)
|
60
63
|
valid_number?(val) || valid_string?(val) || valid_boolean?(val)
|
61
64
|
end
|
65
|
+
|
66
|
+
# Validates if the value passed batch_events has correct data type and values or not.
|
67
|
+
#
|
68
|
+
# Args: batch_events [Hash]: value to be tested
|
69
|
+
#
|
70
|
+
# @return: [Boolean]: True if all conditions are passed else False
|
71
|
+
def is_valid_batch_event_settings(batch_events)
|
72
|
+
logger = VWO::Logger.get_instance
|
73
|
+
events_per_request = batch_events[:events_per_request]
|
74
|
+
request_time_interval = batch_events[:request_time_interval]
|
75
|
+
|
76
|
+
unless events_per_request || request_time_interval
|
77
|
+
logger.log(
|
78
|
+
VWO::LogLevelEnum::ERROR,
|
79
|
+
format(
|
80
|
+
VWO::LogMessageEnum::ErrorMessages::EVENT_BATCHING_INSUFFICIENT,
|
81
|
+
file: VWO::FileNameEnum::ValidateUtil
|
82
|
+
)
|
83
|
+
)
|
84
|
+
return false
|
85
|
+
end
|
86
|
+
|
87
|
+
if (request_time_interval && !valid_number?(request_time_interval))
|
88
|
+
logger.log(
|
89
|
+
VWO::LogLevelEnum::ERROR,
|
90
|
+
format(
|
91
|
+
VWO::LogMessageEnum::ErrorMessages::REQUEST_TIME_INTERVAL_INVALID,
|
92
|
+
file: VWO::FileNameEnum::ValidateUtil
|
93
|
+
)
|
94
|
+
)
|
95
|
+
return false
|
96
|
+
end
|
97
|
+
|
98
|
+
if (events_per_request && !valid_number?(events_per_request))
|
99
|
+
logger.log(
|
100
|
+
VWO::LogLevelEnum::ERROR,
|
101
|
+
format(
|
102
|
+
VWO::LogMessageEnum::ErrorMessages::EVENTS_PER_REQUEST_INVALID,
|
103
|
+
file: VWO::FileNameEnum::ValidateUtil
|
104
|
+
)
|
105
|
+
)
|
106
|
+
return false
|
107
|
+
end
|
108
|
+
|
109
|
+
if events_per_request && (events_per_request < VWO::MIN_EVENTS_PER_REQUEST || events_per_request > VWO::MAX_EVENTS_PER_REQUEST)
|
110
|
+
logger.log(
|
111
|
+
VWO::LogLevelEnum::ERROR,
|
112
|
+
format(
|
113
|
+
VWO::LogMessageEnum::ErrorMessages::EVENTS_PER_REQUEST_OUT_OF_BOUNDS,
|
114
|
+
file: VWO::FileNameEnum::ValidateUtil,
|
115
|
+
min_value: VWO::MIN_EVENTS_PER_REQUEST,
|
116
|
+
max_value: VWO::MAX_EVENTS_PER_REQUEST
|
117
|
+
)
|
118
|
+
)
|
119
|
+
return false
|
120
|
+
end
|
121
|
+
|
122
|
+
if request_time_interval && request_time_interval < VWO::MIN_REQUEST_TIME_INTERVAL
|
123
|
+
logger.log(
|
124
|
+
VWO::LogLevelEnum::ERROR,
|
125
|
+
format(
|
126
|
+
VWO::LogMessageEnum::ErrorMessages::REQUEST_TIME_INTERVAL_OUT_OF_BOUNDS,
|
127
|
+
file: VWO::FileNameEnum::ValidateUtil,
|
128
|
+
min_value: VWO::MIN_REQUEST_TIME_INTERVAL
|
129
|
+
)
|
130
|
+
)
|
131
|
+
return false
|
132
|
+
end
|
133
|
+
|
134
|
+
if batch_events.key?(:flushCallback) && !batch_events[:flushCallback].is_a?(Method)
|
135
|
+
logger.log(
|
136
|
+
VWO::LogLevelEnum::ERROR,
|
137
|
+
format(
|
138
|
+
VWO::LogMessageEnum::ErrorMessages::FLUSH_CALLBACK_INVALID,
|
139
|
+
file: VWO::FileNameEnum::ValidateUtil
|
140
|
+
)
|
141
|
+
)
|
142
|
+
return false
|
143
|
+
end
|
144
|
+
true
|
145
|
+
end
|
62
146
|
end
|
63
147
|
end
|
64
148
|
end
|
data/lib/vwo.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2019-
|
1
|
+
# Copyright 2019-2021 Wingify Software Pvt. Ltd.
|
2
2
|
#
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
4
|
# you may not use this file except in compliance with the License.
|
@@ -25,11 +25,14 @@ require_relative 'vwo/utils/feature'
|
|
25
25
|
require_relative 'vwo/utils/custom_dimensions'
|
26
26
|
require_relative 'vwo/constants'
|
27
27
|
require_relative 'vwo/core/variation_decider'
|
28
|
+
require_relative 'vwo/services/batch_events_dispatcher'
|
29
|
+
require_relative 'vwo/services/batch_events_queue'
|
30
|
+
require_relative 'vwo/services/usage_stats'
|
28
31
|
|
29
32
|
# VWO main file
|
30
33
|
class VWO
|
31
|
-
attr_accessor :is_instance_valid, :logger
|
32
|
-
|
34
|
+
attr_accessor :is_instance_valid, :logger, :settings_file_manager, :variation_decider
|
35
|
+
attr_reader :usage_stats
|
33
36
|
include Enums
|
34
37
|
include Utils::Validations
|
35
38
|
include Utils::Feature
|
@@ -65,7 +68,15 @@ class VWO
|
|
65
68
|
@is_development_mode = is_development_mode
|
66
69
|
@logger = VWO::Logger.get_instance(logger)
|
67
70
|
@logger.instance.level = options[:log_level] if (0..5).include?(options[:log_level])
|
71
|
+
usage_stats = {}
|
72
|
+
|
73
|
+
usage_stats[:cl] = 1 if logger
|
74
|
+
usage_stats[:ll] = 1 if options[:log_level]
|
75
|
+
usage_stats[:ss] = 1 if @user_storage
|
76
|
+
usage_stats[:ig] = 1 if options.key?(:integrations)
|
77
|
+
usage_stats[:eb] = 1 if options.key?(:batch_events)
|
68
78
|
|
79
|
+
@settings_file_manager = VWO::Services::SettingsFileManager.new(@account_id, @sdk_key)
|
69
80
|
unless valid_settings_file?(get_settings(settings_file))
|
70
81
|
@logger.log(
|
71
82
|
LogLevelEnum::ERROR,
|
@@ -74,6 +85,45 @@ class VWO
|
|
74
85
|
@is_instance_valid = false
|
75
86
|
return
|
76
87
|
end
|
88
|
+
|
89
|
+
if options.key?(:should_track_returning_user)
|
90
|
+
if [true, false].include? options[:should_track_returning_user]
|
91
|
+
@should_track_returning_user = options[:should_track_returning_user]
|
92
|
+
usage_stats[:tr] = 1 if @should_track_returning_user
|
93
|
+
else
|
94
|
+
@logger.log(
|
95
|
+
LogLevelEnum::ERROR,
|
96
|
+
format(
|
97
|
+
LogMessageEnum::ErrorMessages::INVALID_TRACK_RETURNING_USER_VALUE,
|
98
|
+
file: FILE
|
99
|
+
)
|
100
|
+
)
|
101
|
+
@is_instance_valid = false
|
102
|
+
return
|
103
|
+
end
|
104
|
+
else
|
105
|
+
@should_track_returning_user = false
|
106
|
+
end
|
107
|
+
|
108
|
+
if options.key?(:goal_type_to_track)
|
109
|
+
if GOAL_TYPES.key? options[:goal_type_to_track]
|
110
|
+
@goal_type_to_track = options[:goal_type_to_track]
|
111
|
+
usage_stats[:gt] = 1
|
112
|
+
else
|
113
|
+
@logger.log(
|
114
|
+
LogLevelEnum::ERROR,
|
115
|
+
format(
|
116
|
+
LogMessageEnum::ErrorMessages::INVALID_GOAL_TYPE,
|
117
|
+
file: FILE
|
118
|
+
)
|
119
|
+
)
|
120
|
+
@is_instance_valid = false
|
121
|
+
return
|
122
|
+
end
|
123
|
+
else
|
124
|
+
@goal_type_to_track = 'ALL'
|
125
|
+
end
|
126
|
+
|
77
127
|
@is_instance_valid = true
|
78
128
|
@config = VWO::Services::SettingsFileProcessor.new(get_settings)
|
79
129
|
|
@@ -89,8 +139,54 @@ class VWO
|
|
89
139
|
@config.process_settings_file
|
90
140
|
@settings_file = @config.get_settings_file
|
91
141
|
|
142
|
+
@usage_stats = VWO::Services::UsageStats.new(usage_stats, @is_development_mode)
|
143
|
+
|
144
|
+
if options.key?(:batch_events)
|
145
|
+
if options[:batch_events].is_a?(Hash)
|
146
|
+
unless is_valid_batch_event_settings(options[:batch_events])
|
147
|
+
@is_instance_valid = false
|
148
|
+
return
|
149
|
+
end
|
150
|
+
@batch_event_dispatcher = VWO::Services::BatchEventsDispatcher.new
|
151
|
+
def dispatcher (events, callback)
|
152
|
+
@batch_event_dispatcher.dispatch(
|
153
|
+
{
|
154
|
+
ev: events
|
155
|
+
},
|
156
|
+
callback,
|
157
|
+
{
|
158
|
+
a: @account_id,
|
159
|
+
sd: SDK_NAME,
|
160
|
+
sv: SDK_VERSION,
|
161
|
+
env: @sdk_key
|
162
|
+
}.merge(@usage_stats.usage_stats)
|
163
|
+
)
|
164
|
+
end
|
165
|
+
@batch_events_queue = VWO::Services::BatchEventsQueue.new(
|
166
|
+
options[:batch_events].merge(
|
167
|
+
{
|
168
|
+
account_id: @account_id,
|
169
|
+
dispatcher: method(:dispatcher)
|
170
|
+
}
|
171
|
+
)
|
172
|
+
)
|
173
|
+
@batch_events_queue.flush(manual: true)
|
174
|
+
@batch_events = options[:batch_events]
|
175
|
+
else
|
176
|
+
@logger.log(
|
177
|
+
LogLevelEnum::ERROR,
|
178
|
+
format(
|
179
|
+
LogMessageEnum::ErrorMessages::EVENT_BATCHING_NOT_OBJECT,
|
180
|
+
file: FILE
|
181
|
+
)
|
182
|
+
)
|
183
|
+
@is_instance_valid = false
|
184
|
+
return
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
92
188
|
# Assign VariationDecider to VWO
|
93
|
-
@variation_decider = VWO::Core::VariationDecider.new(@settings_file, user_storage)
|
189
|
+
@variation_decider = VWO::Core::VariationDecider.new(@settings_file, user_storage, options)
|
94
190
|
|
95
191
|
if is_development_mode
|
96
192
|
@logger.log(
|
@@ -118,9 +214,55 @@ class VWO
|
|
118
214
|
|
119
215
|
# VWO get_settings method to get settings for a particular account_id
|
120
216
|
def get_settings(settings_file = nil)
|
121
|
-
@
|
122
|
-
settings_file ||
|
123
|
-
@
|
217
|
+
@settings_file ||=
|
218
|
+
settings_file || @settings_file_manager.get_settings_file
|
219
|
+
@settings_file
|
220
|
+
end
|
221
|
+
|
222
|
+
# This API method: fetch the latest settings file and update it
|
223
|
+
|
224
|
+
# VWO get_settings method to get settings for a particular account_id
|
225
|
+
def get_and_update_settings_file
|
226
|
+
|
227
|
+
unless @is_instance_valid
|
228
|
+
@logger.log(
|
229
|
+
LogLevelEnum::ERROR,
|
230
|
+
format(
|
231
|
+
LogMessageEnum::ErrorMessages::API_CONFIG_CORRUPTED,
|
232
|
+
file: FILE,
|
233
|
+
api_name: ApiMethods.GET_AND_UPDATE_SETTINGS_FILE
|
234
|
+
)
|
235
|
+
)
|
236
|
+
return
|
237
|
+
end
|
238
|
+
|
239
|
+
latest_settings = @settings_file_manager.get_settings_file(true)
|
240
|
+
latest_settings = JSON.parse(latest_settings)
|
241
|
+
if latest_settings == @settings_file
|
242
|
+
@logger.log(
|
243
|
+
LogLevelEnum::INFO,
|
244
|
+
format(
|
245
|
+
LogMessageEnum::InfoMessages::SETTINGS_NOT_UPDATED,
|
246
|
+
api_name: ApiMethods::GET_AND_UPDATE_SETTINGS_FILE,
|
247
|
+
file: FILE
|
248
|
+
)
|
249
|
+
)
|
250
|
+
end
|
251
|
+
|
252
|
+
@config.update_settings_file(latest_settings)
|
253
|
+
@settings_file = @config.get_settings_file
|
254
|
+
@settings_file
|
255
|
+
rescue StandardError => e
|
256
|
+
@logger.log(
|
257
|
+
LogLevelEnum::ERROR,
|
258
|
+
format(
|
259
|
+
LogMessageEnum::ErrorMessages::API_NOT_WORKING,
|
260
|
+
file: FILE,
|
261
|
+
api_name: ApiMethods::GET_AND_UPDATE_SETTINGS_FILE,
|
262
|
+
exception: e
|
263
|
+
)
|
264
|
+
)
|
265
|
+
nil
|
124
266
|
end
|
125
267
|
|
126
268
|
# This API method: Gets the variation assigned for the user
|
@@ -136,34 +278,37 @@ class VWO
|
|
136
278
|
#
|
137
279
|
# @param[String] :campaign_key Unique campaign key
|
138
280
|
# @param[String] :user_id ID assigned to a user
|
139
|
-
# @param[Hash]
|
281
|
+
# @param[Hash] :options Options for custom variables required for segmentation
|
140
282
|
# @return[String|None] If variation is assigned then variation-name
|
141
283
|
# otherwise null in case of user not becoming part
|
142
284
|
|
143
285
|
def activate(campaign_key, user_id, options = {})
|
144
|
-
|
145
|
-
custom_variables = options['custom_variables'] || options[:custom_variables]
|
146
|
-
|
147
|
-
# Validate input parameters
|
148
|
-
unless valid_string?(campaign_key) && valid_string?(user_id) && (custom_variables.nil? || valid_hash?(custom_variables))
|
286
|
+
unless @is_instance_valid
|
149
287
|
@logger.log(
|
150
288
|
LogLevelEnum::ERROR,
|
151
289
|
format(
|
152
|
-
LogMessageEnum::ErrorMessages::
|
153
|
-
|
154
|
-
|
290
|
+
LogMessageEnum::ErrorMessages::API_CONFIG_CORRUPTED,
|
291
|
+
file: FILE,
|
292
|
+
api_name: ApiMethods::ACTIVATE
|
155
293
|
)
|
156
294
|
)
|
157
295
|
return
|
158
296
|
end
|
159
297
|
|
160
|
-
|
298
|
+
# Retrieve custom variables
|
299
|
+
custom_variables = options['custom_variables'] || options[:custom_variables]
|
300
|
+
variation_targeting_variables = options['variation_targeting_variables'] || options[:variation_targeting_variables]
|
301
|
+
|
302
|
+
should_track_returning_user = get_should_track_returning_user(options)
|
303
|
+
# Validate input parameters
|
304
|
+
unless valid_string?(campaign_key) && valid_string?(user_id) && (custom_variables.nil? || valid_hash?(custom_variables)) &&
|
305
|
+
(variation_targeting_variables.nil? || valid_hash?(variation_targeting_variables)) && [true, false].include?(should_track_returning_user)
|
161
306
|
@logger.log(
|
162
307
|
LogLevelEnum::ERROR,
|
163
308
|
format(
|
164
|
-
LogMessageEnum::ErrorMessages::
|
165
|
-
|
166
|
-
|
309
|
+
LogMessageEnum::ErrorMessages::ACTIVATE_API_MISSING_PARAMS,
|
310
|
+
api_name: ApiMethods::ACTIVATE,
|
311
|
+
file: FILE
|
167
312
|
)
|
168
313
|
)
|
169
314
|
return
|
@@ -208,11 +353,14 @@ class VWO
|
|
208
353
|
|
209
354
|
# Once the matching RUNNING campaign is found, assign the
|
210
355
|
# deterministic variation to the user_id provided
|
356
|
+
|
211
357
|
variation = @variation_decider.get_variation(
|
212
358
|
user_id,
|
213
359
|
campaign,
|
360
|
+
ApiMethods::ACTIVATE,
|
214
361
|
campaign_key,
|
215
|
-
custom_variables
|
362
|
+
custom_variables,
|
363
|
+
variation_targeting_variables
|
216
364
|
)
|
217
365
|
|
218
366
|
# Check if variation_name has been assigned
|
@@ -229,15 +377,56 @@ class VWO
|
|
229
377
|
return
|
230
378
|
end
|
231
379
|
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
380
|
+
if is_eligible_to_send_impression(should_track_returning_user)
|
381
|
+
if defined?(@batch_events)
|
382
|
+
impression = create_bulk_event_impression(
|
383
|
+
@settings_file,
|
384
|
+
campaign['id'],
|
385
|
+
variation['id'],
|
386
|
+
user_id
|
387
|
+
)
|
388
|
+
@batch_events_queue.enqueue(impression)
|
389
|
+
else
|
390
|
+
# Variation found, dispatch it to server
|
391
|
+
impression = create_impression(
|
392
|
+
@settings_file,
|
393
|
+
campaign['id'],
|
394
|
+
variation['id'],
|
395
|
+
user_id,
|
396
|
+
@sdk_key,
|
397
|
+
nil, # goal_id
|
398
|
+
nil, # revenue
|
399
|
+
usage_stats: @usage_stats.usage_stats
|
400
|
+
)
|
401
|
+
if @event_dispatcher.dispatch(impression)
|
402
|
+
@logger.log(
|
403
|
+
LogLevelEnum::INFO,
|
404
|
+
format(
|
405
|
+
LogMessageEnum::InfoMessages::IMPRESSION_SUCCESS,
|
406
|
+
file: FILE,
|
407
|
+
sdk_key: @sdk_key,
|
408
|
+
account_id: @account_id,
|
409
|
+
campaign_id: campaign['id'],
|
410
|
+
variation_id: variation['id'],
|
411
|
+
end_point: EVENTS::TRACK_USER
|
412
|
+
)
|
413
|
+
)
|
414
|
+
end
|
415
|
+
end
|
416
|
+
variation['name']
|
417
|
+
else
|
418
|
+
@logger.log(
|
419
|
+
LogLevelEnum::INFO,
|
420
|
+
format(
|
421
|
+
LogMessageEnum::InfoMessages::USER_ALREADY_TRACKED,
|
422
|
+
file: FILE,
|
423
|
+
user_id: user_id,
|
424
|
+
campaign_key: campaign_key,
|
425
|
+
api_name: ApiMethods::ACTIVATE
|
426
|
+
)
|
427
|
+
)
|
428
|
+
nil
|
429
|
+
end
|
241
430
|
rescue StandardError => e
|
242
431
|
@logger.log(
|
243
432
|
LogLevelEnum::ERROR,
|
@@ -248,7 +437,7 @@ class VWO
|
|
248
437
|
exception: e
|
249
438
|
)
|
250
439
|
)
|
251
|
-
|
440
|
+
e
|
252
441
|
end
|
253
442
|
|
254
443
|
# This API method: Gets the variation name assigned for the
|
@@ -269,28 +458,30 @@ class VWO
|
|
269
458
|
# Otherwise null in case of user not becoming part
|
270
459
|
#
|
271
460
|
def get_variation_name(campaign_key, user_id, options = {})
|
272
|
-
|
273
|
-
custom_variables = options['custom_variables'] || options[:custom_variables]
|
274
|
-
|
275
|
-
# Validate input parameters
|
276
|
-
unless valid_string?(campaign_key) && valid_string?(user_id) && (custom_variables.nil? || valid_hash?(custom_variables))
|
461
|
+
unless @is_instance_valid
|
277
462
|
@logger.log(
|
278
463
|
LogLevelEnum::ERROR,
|
279
464
|
format(
|
280
|
-
LogMessageEnum::ErrorMessages::
|
281
|
-
|
282
|
-
|
465
|
+
LogMessageEnum::ErrorMessages::API_CONFIG_CORRUPTED,
|
466
|
+
file: FILE,
|
467
|
+
api_name: ApiMethods::GET_VARIATION_NAME
|
283
468
|
)
|
284
469
|
)
|
285
470
|
return
|
286
471
|
end
|
287
|
-
|
472
|
+
# Retrieve custom variables
|
473
|
+
custom_variables = options['custom_variables'] || options[:custom_variables]
|
474
|
+
variation_targeting_variables = options['variation_targeting_variables'] || options[:variation_targeting_variables]
|
475
|
+
|
476
|
+
# Validate input parameters
|
477
|
+
unless valid_string?(campaign_key) && valid_string?(user_id) && (custom_variables.nil? || valid_hash?(custom_variables)) &&
|
478
|
+
(variation_targeting_variables.nil? || valid_hash?(variation_targeting_variables))
|
288
479
|
@logger.log(
|
289
480
|
LogLevelEnum::ERROR,
|
290
481
|
format(
|
291
|
-
LogMessageEnum::ErrorMessages::
|
292
|
-
|
293
|
-
|
482
|
+
LogMessageEnum::ErrorMessages::GET_VARIATION_NAME_API_INVALID_PARAMS,
|
483
|
+
api_name: ApiMethods::GET_VARIATION_NAME,
|
484
|
+
file: FILE
|
294
485
|
)
|
295
486
|
)
|
296
487
|
return
|
@@ -330,7 +521,7 @@ class VWO
|
|
330
521
|
return
|
331
522
|
end
|
332
523
|
|
333
|
-
variation = @variation_decider.get_variation(user_id, campaign, campaign_key, custom_variables)
|
524
|
+
variation = @variation_decider.get_variation(user_id, campaign, ApiMethods::GET_VARIATION_NAME, campaign_key, custom_variables, variation_targeting_variables)
|
334
525
|
|
335
526
|
# Check if variation_name has been assigned
|
336
527
|
unless valid_value?(variation)
|
@@ -372,33 +563,11 @@ class VWO
|
|
372
563
|
# @param[String] :campaign_key Unique campaign key
|
373
564
|
# @param[String] :user_id ID assigned to a user
|
374
565
|
# @param[String] :goal_identifier Unique campaign's goal identifier
|
375
|
-
# @param[
|
566
|
+
# @param[Hash] :options Contains revenue value and custom variables
|
376
567
|
# @param[Numeric|String] :revenue_value It is the revenue generated on triggering the goal
|
377
568
|
#
|
378
|
-
def track(campaign_key, user_id, goal_identifier, *args)
|
379
|
-
if args[0].is_a?(Hash)
|
380
|
-
revenue_value = args[0]['revenue_value'] || args[0][:revenue_value]
|
381
|
-
custom_variables = args[0]['custom_variables'] || args[0][:custom_variables]
|
382
|
-
elsif args.is_a?(Array)
|
383
|
-
revenue_value = args[0]
|
384
|
-
custom_variables = nil
|
385
|
-
end
|
386
|
-
|
387
|
-
# Check for valid args
|
388
|
-
unless valid_string?(campaign_key) && valid_string?(user_id) && valid_string?(goal_identifier) &&
|
389
|
-
(custom_variables.nil? || valid_hash?(custom_variables)) || (revenue_value.nil? || valid_basic_data_type?(revenue_value))
|
390
|
-
# log invalid params
|
391
|
-
@logger.log(
|
392
|
-
LogLevelEnum::ERROR,
|
393
|
-
format(
|
394
|
-
LogMessageEnum::ErrorMessages::TRACK_API_INVALID_PARAMS,
|
395
|
-
file: FILE,
|
396
|
-
api_name: ApiMethods.TRACK
|
397
|
-
)
|
398
|
-
)
|
399
|
-
return false
|
400
|
-
end
|
401
569
|
|
570
|
+
def track(campaign_key, user_id, goal_identifier, options = {})
|
402
571
|
unless @is_instance_valid
|
403
572
|
@logger.log(
|
404
573
|
LogLevelEnum::ERROR,
|
@@ -411,98 +580,187 @@ class VWO
|
|
411
580
|
return false
|
412
581
|
end
|
413
582
|
|
414
|
-
|
415
|
-
|
583
|
+
revenue_value = options['revenue_value'] || options[:revenue_value]
|
584
|
+
custom_variables = options['custom_variables'] || options[:custom_variables]
|
585
|
+
variation_targeting_variables = options['variation_targeting_variables'] || options[:variation_targeting_variables]
|
586
|
+
should_track_returning_user = get_should_track_returning_user(options)
|
587
|
+
goal_type_to_track = get_goal_type_to_track(options)
|
416
588
|
|
417
|
-
#
|
418
|
-
|
419
|
-
|
589
|
+
# Check for valid args
|
590
|
+
unless (valid_string?(campaign_key) || campaign_key.is_a?(Array) || campaign_key.nil?) && valid_string?(user_id) && valid_string?(goal_identifier) && (custom_variables.nil? || valid_hash?(custom_variables)) &&
|
591
|
+
(variation_targeting_variables.nil? || valid_hash?(variation_targeting_variables)) && [true, false].include?(should_track_returning_user) && (GOAL_TYPES.key? (goal_type_to_track))
|
592
|
+
# log invalid params
|
420
593
|
@logger.log(
|
421
594
|
LogLevelEnum::ERROR,
|
422
595
|
format(
|
423
|
-
LogMessageEnum::ErrorMessages::
|
596
|
+
LogMessageEnum::ErrorMessages::TRACK_API_INVALID_PARAMS,
|
424
597
|
file: FILE,
|
425
|
-
campaign_key: campaign_key,
|
426
598
|
api_name: ApiMethods::TRACK
|
427
599
|
)
|
428
600
|
)
|
429
601
|
return false
|
430
602
|
end
|
431
603
|
|
432
|
-
|
604
|
+
# Get campaigns settings
|
605
|
+
campaigns = get_campaigns(@settings_file, campaign_key, goal_identifier, goal_type_to_track)
|
433
606
|
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
format(
|
438
|
-
LogMessageEnum::ErrorMessages::INVALID_API,
|
439
|
-
file: FILE,
|
440
|
-
api_name: ApiMethods::TRACK,
|
441
|
-
user_id: user_id,
|
442
|
-
campaign_key: campaign_key,
|
443
|
-
campaign_type: campaign_type
|
444
|
-
)
|
445
|
-
)
|
446
|
-
return false
|
607
|
+
# Validate campaign
|
608
|
+
if campaigns.nil?
|
609
|
+
return nil
|
447
610
|
end
|
448
611
|
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
612
|
+
result = {}
|
613
|
+
campaigns.each do |campaign|
|
614
|
+
begin
|
615
|
+
campaign_type = campaign['type']
|
616
|
+
|
617
|
+
if campaign_type == CampaignTypes::FEATURE_ROLLOUT
|
618
|
+
@logger.log(
|
619
|
+
LogLevelEnum::ERROR,
|
620
|
+
format(
|
621
|
+
LogMessageEnum::ErrorMessages::INVALID_API,
|
622
|
+
file: FILE,
|
623
|
+
api_name: ApiMethods::TRACK,
|
624
|
+
user_id: user_id,
|
625
|
+
campaign_key: campaign['key'],
|
626
|
+
campaign_type: campaign_type
|
627
|
+
)
|
463
628
|
)
|
464
|
-
|
465
|
-
|
466
|
-
|
629
|
+
result[campaign['key']] = false
|
630
|
+
next
|
631
|
+
end
|
632
|
+
|
633
|
+
variation = @variation_decider.get_variation(user_id, campaign, ApiMethods::TRACK, campaign['key'], custom_variables, variation_targeting_variables, goal_identifier)
|
634
|
+
|
635
|
+
if variation
|
636
|
+
goal = get_campaign_goal(campaign, goal_identifier)
|
637
|
+
if goal.nil? || !goal["id"]
|
638
|
+
@logger.log(
|
639
|
+
LogLevelEnum::ERROR,
|
640
|
+
format(
|
641
|
+
LogMessageEnum::ErrorMessages::TRACK_API_GOAL_NOT_FOUND,
|
642
|
+
file: FILE,
|
643
|
+
goal_identifier: goal_identifier,
|
644
|
+
user_id: user_id,
|
645
|
+
campaign_key: campaign['key'],
|
646
|
+
api_name: ApiMethods::TRACK
|
647
|
+
)
|
648
|
+
)
|
649
|
+
result[campaign['key']] = false
|
650
|
+
next
|
651
|
+
elsif goal['type'] == GoalTypes::REVENUE && !valid_value?(revenue_value)
|
652
|
+
@logger.log(
|
653
|
+
LogLevelEnum::ERROR,
|
654
|
+
format(
|
655
|
+
LogMessageEnum::ErrorMessages::TRACK_API_REVENUE_NOT_PASSED_FOR_REVENUE_GOAL,
|
656
|
+
file: FILE,
|
657
|
+
user_id: user_id,
|
658
|
+
goal_identifier: goal_identifier,
|
659
|
+
campaign_key: campaign['key'],
|
660
|
+
api_name: ApiMethods::TRACK
|
661
|
+
)
|
662
|
+
)
|
663
|
+
result[campaign['key']] = false
|
664
|
+
next
|
665
|
+
elsif goal['type'] == GoalTypes::CUSTOM
|
666
|
+
revenue_value = nil
|
667
|
+
end
|
668
|
+
|
669
|
+
if variation['goal_identifier']
|
670
|
+
identifiers = variation['goal_identifier'].split(VWO_DELIMITER)
|
671
|
+
else
|
672
|
+
variation['goal_identifier'] = ''
|
673
|
+
identifiers = []
|
674
|
+
end
|
675
|
+
|
676
|
+
if !identifiers.include? goal_identifier
|
677
|
+
updated_goal_identifier = variation['goal_identifier']
|
678
|
+
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']
|
680
|
+
# set variation at user storage
|
681
|
+
elsif !should_track_returning_user
|
682
|
+
@logger.log(
|
683
|
+
LogLevelEnum::INFO,
|
684
|
+
format(
|
685
|
+
LogMessageEnum::InfoMessages::GOAL_ALREADY_TRACKED,
|
686
|
+
file: FILE,
|
687
|
+
user_id: user_id,
|
688
|
+
campaign_key: campaign['key'],
|
689
|
+
goal_identifier: goal_identifier,
|
690
|
+
api_name: ApiMethods::TRACK
|
691
|
+
)
|
692
|
+
)
|
693
|
+
result[campaign['key']] = false
|
694
|
+
next
|
695
|
+
end
|
696
|
+
|
697
|
+
if defined?(@batch_events)
|
698
|
+
impression = create_bulk_event_impression(
|
699
|
+
@settings_file,
|
700
|
+
campaign['id'],
|
701
|
+
variation['id'],
|
702
|
+
user_id,
|
703
|
+
goal['id'],
|
704
|
+
revenue_value
|
705
|
+
)
|
706
|
+
@batch_events_queue.enqueue(impression)
|
707
|
+
else
|
708
|
+
impression = create_impression(
|
709
|
+
@settings_file,
|
710
|
+
campaign['id'],
|
711
|
+
variation['id'],
|
712
|
+
user_id,
|
713
|
+
@sdk_key,
|
714
|
+
goal['id'],
|
715
|
+
revenue_value
|
716
|
+
)
|
717
|
+
if @event_dispatcher.dispatch(impression)
|
718
|
+
@logger.log(
|
719
|
+
LogLevelEnum::INFO,
|
720
|
+
format(
|
721
|
+
LogMessageEnum::InfoMessages::IMPRESSION_SUCCESS,
|
722
|
+
file: FILE,
|
723
|
+
sdk_key: @sdk_key,
|
724
|
+
account_id: @account_id,
|
725
|
+
campaign_id: campaign['id'],
|
726
|
+
variation_id: variation['id'],
|
727
|
+
end_point: EVENTS::TRACK_GOAL
|
728
|
+
)
|
729
|
+
)
|
730
|
+
@logger.log(
|
731
|
+
LogLevelEnum::INFO,
|
732
|
+
format(
|
733
|
+
LogMessageEnum::InfoMessages::MAIN_KEYS_FOR_IMPRESSION,
|
734
|
+
file: FILE,
|
735
|
+
sdk_key: @sdk_key,
|
736
|
+
campaign_id: impression[:experiment_id],
|
737
|
+
account_id: impression[:account_id],
|
738
|
+
variation_id: impression[:combination]
|
739
|
+
)
|
740
|
+
)
|
741
|
+
end
|
742
|
+
end
|
743
|
+
result[campaign['key']] = true
|
744
|
+
next
|
745
|
+
end
|
746
|
+
result[campaign['key']] = false
|
747
|
+
rescue StandardError => e
|
467
748
|
@logger.log(
|
468
749
|
LogLevelEnum::ERROR,
|
469
750
|
format(
|
470
|
-
|
751
|
+
e.message,
|
471
752
|
file: FILE,
|
472
|
-
|
473
|
-
goal_identifier: goal_identifier,
|
474
|
-
campaign_key: campaign_key,
|
475
|
-
api_name: ApiMethods::TRACK
|
753
|
+
exception: e
|
476
754
|
)
|
477
755
|
)
|
478
|
-
return false
|
479
|
-
elsif goal['type'] == GoalTypes::CUSTOM
|
480
|
-
revenue_value = nil
|
481
756
|
end
|
482
|
-
|
483
|
-
@settings_file,
|
484
|
-
campaign['id'],
|
485
|
-
variation['id'],
|
486
|
-
user_id,
|
487
|
-
goal['id'],
|
488
|
-
revenue_value
|
489
|
-
)
|
490
|
-
@event_dispatcher.dispatch(impression)
|
757
|
+
end
|
491
758
|
|
492
|
-
|
493
|
-
|
494
|
-
format(
|
495
|
-
LogMessageEnum::InfoMessages::MAIN_KEYS_FOR_IMPRESSION,
|
496
|
-
file: FILE,
|
497
|
-
campaign_id: impression[:experiment_id],
|
498
|
-
user_id: impression[:uId],
|
499
|
-
account_id: impression[:account_id],
|
500
|
-
variation_id: impression[:combination]
|
501
|
-
)
|
502
|
-
)
|
503
|
-
return true
|
759
|
+
if result.length() == 0
|
760
|
+
return nil
|
504
761
|
end
|
505
|
-
|
762
|
+
|
763
|
+
result
|
506
764
|
rescue StandardError => e
|
507
765
|
@logger.log(
|
508
766
|
LogLevelEnum::ERROR,
|
@@ -530,28 +788,40 @@ class VWO
|
|
530
788
|
# @return[Boolean] true if user becomes part of feature test/rollout, otherwise false.
|
531
789
|
|
532
790
|
def feature_enabled?(campaign_key, user_id, options = {})
|
533
|
-
|
534
|
-
custom_variables = options['custom_variables'] || options[:custom_variables]
|
535
|
-
|
536
|
-
# Validate input parameters
|
537
|
-
unless valid_string?(campaign_key) && valid_string?(user_id) && (custom_variables.nil? || valid_hash?(custom_variables))
|
791
|
+
unless @is_instance_valid
|
538
792
|
@logger.log(
|
539
793
|
LogLevelEnum::ERROR,
|
540
794
|
format(
|
541
|
-
LogMessageEnum::ErrorMessages::
|
542
|
-
|
543
|
-
|
795
|
+
LogMessageEnum::ErrorMessages::API_CONFIG_CORRUPTED,
|
796
|
+
file: FILE,
|
797
|
+
api_name: ApiMethods::IS_FEATURE_ENABLED
|
544
798
|
)
|
545
799
|
)
|
546
800
|
return false
|
547
801
|
end
|
548
|
-
|
802
|
+
|
803
|
+
# Retrieve custom variables
|
804
|
+
custom_variables = options['custom_variables'] || options[:custom_variables]
|
805
|
+
variation_targeting_variables = options['variation_targeting_variables'] || options[:variation_targeting_variables]
|
806
|
+
should_track_returning_user = get_should_track_returning_user(options)
|
807
|
+
@logger.log(
|
808
|
+
LogLevelEnum::INFO,
|
809
|
+
format(
|
810
|
+
LogMessageEnum::InfoMessages::API_CALLED,
|
811
|
+
file: FILE,
|
812
|
+
api_name: ApiMethods::IS_FEATURE_ENABLED,
|
813
|
+
user_id: user_id
|
814
|
+
)
|
815
|
+
)
|
816
|
+
# Validate input parameters
|
817
|
+
unless valid_string?(campaign_key) && valid_string?(user_id) && (custom_variables.nil? || valid_hash?(custom_variables)) &&
|
818
|
+
(variation_targeting_variables.nil? || valid_hash?(variation_targeting_variables)) && [true, false].include?(should_track_returning_user)
|
549
819
|
@logger.log(
|
550
820
|
LogLevelEnum::ERROR,
|
551
821
|
format(
|
552
|
-
LogMessageEnum::ErrorMessages::
|
553
|
-
|
554
|
-
|
822
|
+
LogMessageEnum::ErrorMessages::IS_FEATURE_ENABLED_API_INVALID_PARAMS,
|
823
|
+
api_name: ApiMethods::IS_FEATURE_ENABLED,
|
824
|
+
file: FILE
|
555
825
|
)
|
556
826
|
)
|
557
827
|
return false
|
@@ -594,57 +864,84 @@ class VWO
|
|
594
864
|
end
|
595
865
|
|
596
866
|
# Get variation
|
597
|
-
variation = @variation_decider.get_variation(user_id, campaign, campaign_key, custom_variables)
|
867
|
+
variation = @variation_decider.get_variation(user_id, campaign, ApiMethods::IS_FEATURE_ENABLED, campaign_key, custom_variables, variation_targeting_variables)
|
598
868
|
|
599
869
|
# If no variation, did not become part of feature_test/rollout
|
600
870
|
return false unless variation
|
601
871
|
|
602
872
|
# if campaign type is feature_test Send track call to server
|
603
873
|
if campaign_type == CampaignTypes::FEATURE_TEST
|
604
|
-
|
605
|
-
@
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
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
|
+
)
|
610
894
|
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
)
|
623
|
-
result = variation['isFeatureEnabled']
|
624
|
-
if result
|
625
|
-
@logger.log(
|
626
|
-
LogLevelEnum::INFO,
|
627
|
-
format(
|
628
|
-
LogMessageEnum::InfoMessages::FEATURE_ENABLED_FOR_USER,
|
629
|
-
file: FILE,
|
630
|
-
user_id: user_id,
|
631
|
-
feature_key: campaign_key,
|
632
|
-
api_name: ApiMethods::IS_FEATURE_ENABLED
|
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
|
+
)
|
633
906
|
)
|
634
|
-
|
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
|
635
933
|
else
|
636
934
|
@logger.log(
|
637
935
|
LogLevelEnum::INFO,
|
638
936
|
format(
|
639
|
-
LogMessageEnum::InfoMessages::
|
937
|
+
LogMessageEnum::InfoMessages::USER_ALREADY_TRACKED,
|
640
938
|
file: FILE,
|
641
939
|
user_id: user_id,
|
642
|
-
|
940
|
+
campaign_key: campaign_key,
|
643
941
|
api_name: ApiMethods::IS_FEATURE_ENABLED
|
644
942
|
)
|
645
943
|
)
|
646
944
|
end
|
647
|
-
return result
|
648
945
|
end
|
649
946
|
true
|
650
947
|
rescue StandardError => e
|
@@ -680,29 +977,30 @@ class VWO
|
|
680
977
|
#
|
681
978
|
|
682
979
|
def get_feature_variable_value(campaign_key, variable_key, user_id, options = {})
|
683
|
-
|
684
|
-
custom_variables = options['custom_variables'] || options[:custom_variables]
|
685
|
-
|
686
|
-
unless valid_string?(campaign_key) && valid_string?(variable_key) && valid_string?(user_id) &&
|
687
|
-
(custom_variables.nil? || valid_hash?(custom_variables))
|
980
|
+
unless @is_instance_valid
|
688
981
|
@logger.log(
|
689
982
|
LogLevelEnum::ERROR,
|
690
983
|
format(
|
691
|
-
LogMessageEnum::ErrorMessages::
|
984
|
+
LogMessageEnum::ErrorMessages::API_CONFIG_CORRUPTED,
|
692
985
|
file: FILE,
|
693
|
-
api_name: ApiMethods
|
986
|
+
api_name: ApiMethods.GET_FEATURE_VARIABLE_VALUE
|
694
987
|
)
|
695
988
|
)
|
696
989
|
return
|
697
990
|
end
|
698
991
|
|
699
|
-
|
992
|
+
# Retrieve custom variables
|
993
|
+
custom_variables = options['custom_variables'] || options[:custom_variables]
|
994
|
+
variation_targeting_variables = options['variation_targeting_variables'] || options[:variation_targeting_variables]
|
995
|
+
|
996
|
+
unless valid_string?(campaign_key) && valid_string?(variable_key) && valid_string?(user_id) &&
|
997
|
+
(custom_variables.nil? || valid_hash?(custom_variables)) && (variation_targeting_variables.nil? || valid_hash?(variation_targeting_variables))
|
700
998
|
@logger.log(
|
701
999
|
LogLevelEnum::ERROR,
|
702
1000
|
format(
|
703
|
-
LogMessageEnum::ErrorMessages::
|
1001
|
+
LogMessageEnum::ErrorMessages::GET_FEATURE_VARIABLE_VALUE_API_INVALID_PARAMS,
|
704
1002
|
file: FILE,
|
705
|
-
api_name: ApiMethods
|
1003
|
+
api_name: ApiMethods::GET_FEATURE_VARIABLE_VALUE
|
706
1004
|
)
|
707
1005
|
)
|
708
1006
|
return
|
@@ -743,7 +1041,7 @@ class VWO
|
|
743
1041
|
return
|
744
1042
|
end
|
745
1043
|
|
746
|
-
variation = @variation_decider.get_variation(user_id, campaign, campaign_key, custom_variables)
|
1044
|
+
variation = @variation_decider.get_variation(user_id, campaign, ApiMethods::GET_FEATURE_VARIABLE_VALUE, campaign_key, custom_variables, variation_targeting_variables)
|
747
1045
|
|
748
1046
|
# Check if variation has been assigned to user
|
749
1047
|
return unless variation
|
@@ -832,6 +1130,18 @@ class VWO
|
|
832
1130
|
# @return true if call is made successfully, else false
|
833
1131
|
|
834
1132
|
def push(tag_key, tag_value, user_id)
|
1133
|
+
unless @is_instance_valid
|
1134
|
+
@logger.log(
|
1135
|
+
LogLevelEnum::ERROR,
|
1136
|
+
format(
|
1137
|
+
LogMessageEnum::ErrorMessages::API_CONFIG_CORRUPTED,
|
1138
|
+
file: FILE,
|
1139
|
+
api_name: ApiMethods.PUSH
|
1140
|
+
)
|
1141
|
+
)
|
1142
|
+
return
|
1143
|
+
end
|
1144
|
+
|
835
1145
|
unless valid_string?(tag_key) && valid_string?(tag_value) && valid_string?(user_id)
|
836
1146
|
@logger.log(
|
837
1147
|
LogLevelEnum::ERROR,
|
@@ -872,32 +1182,105 @@ class VWO
|
|
872
1182
|
return false
|
873
1183
|
end
|
874
1184
|
|
875
|
-
|
876
|
-
|
877
|
-
|
1185
|
+
if defined?(@batch_events)
|
1186
|
+
impression = get_batch_event_url_params(@settings_file, tag_key, tag_value, user_id)
|
1187
|
+
@batch_events_queue.enqueue(impression)
|
1188
|
+
else
|
1189
|
+
impression = get_url_params(@settings_file, tag_key, tag_value, user_id, @sdk_key)
|
1190
|
+
@event_dispatcher.dispatch(impression)
|
878
1191
|
|
1192
|
+
@logger.log(
|
1193
|
+
LogLevelEnum::INFO,
|
1194
|
+
format(
|
1195
|
+
LogMessageEnum::InfoMessages::MAIN_KEYS_FOR_PUSH_API,
|
1196
|
+
file: FILE,
|
1197
|
+
sdk_key: @sdk_key,
|
1198
|
+
u: impression['u'],
|
1199
|
+
account_id: impression['account_id'],
|
1200
|
+
tags: impression['tags']
|
1201
|
+
)
|
1202
|
+
)
|
1203
|
+
end
|
1204
|
+
true
|
1205
|
+
rescue StandardError => e
|
879
1206
|
@logger.log(
|
880
|
-
LogLevelEnum::
|
1207
|
+
LogLevelEnum::ERROR,
|
881
1208
|
format(
|
882
|
-
LogMessageEnum::
|
1209
|
+
LogMessageEnum::ErrorMessages::API_NOT_WORKING,
|
883
1210
|
file: FILE,
|
884
|
-
|
885
|
-
|
886
|
-
account_id: impression['account_id'],
|
887
|
-
tags: impression['tags']
|
1211
|
+
api_name: ApiMethods::PUSH,
|
1212
|
+
exception: e
|
888
1213
|
)
|
889
1214
|
)
|
890
|
-
|
1215
|
+
false
|
1216
|
+
end
|
1217
|
+
|
1218
|
+
def get_should_track_returning_user(options)
|
1219
|
+
if !options.key?(:should_track_returning_user)
|
1220
|
+
options[:should_track_returning_user] = @should_track_returning_user
|
1221
|
+
elsif ![true, false].include?(options[:should_track_returning_user])
|
1222
|
+
@logger.log(
|
1223
|
+
LogLevelEnum::ERROR,
|
1224
|
+
format(
|
1225
|
+
LogMessageEnum::ErrorMessages::INVALID_TRACK_RETURNING_USER_VALUE,
|
1226
|
+
file: FILE
|
1227
|
+
)
|
1228
|
+
)
|
1229
|
+
end
|
1230
|
+
options[:should_track_returning_user]
|
1231
|
+
end
|
1232
|
+
|
1233
|
+
def is_eligible_to_send_impression(should_track_returning_user = false)
|
1234
|
+
!@user_storage || !@variation_decider.has_stored_variation || should_track_returning_user
|
1235
|
+
end
|
1236
|
+
|
1237
|
+
def flush_events
|
1238
|
+
unless @is_instance_valid
|
1239
|
+
@logger.log(
|
1240
|
+
LogLevelEnum::ERROR,
|
1241
|
+
format(
|
1242
|
+
LogMessageEnum::ErrorMessages::API_CONFIG_CORRUPTED,
|
1243
|
+
file: FILE,
|
1244
|
+
api_name: ApiMethods::FLUSH_EVENTS
|
1245
|
+
)
|
1246
|
+
)
|
1247
|
+
return
|
1248
|
+
end
|
1249
|
+
result = @batch_events_queue.flush(manual: true)
|
1250
|
+
@batch_events_queue.kill_thread
|
1251
|
+
result
|
891
1252
|
rescue StandardError => e
|
892
1253
|
@logger.log(
|
893
1254
|
LogLevelEnum::ERROR,
|
894
1255
|
format(
|
895
1256
|
LogMessageEnum::ErrorMessages::API_NOT_WORKING,
|
896
1257
|
file: FILE,
|
897
|
-
api_name: ApiMethods::
|
1258
|
+
api_name: ApiMethods::FLUSH_EVENTS,
|
898
1259
|
exception: e
|
899
1260
|
)
|
900
1261
|
)
|
901
1262
|
false
|
902
1263
|
end
|
1264
|
+
|
1265
|
+
def get_goal_type_to_track(options)
|
1266
|
+
goal_type_to_track = nil
|
1267
|
+
if !options.key?(:goal_type_to_track)
|
1268
|
+
if @goal_type_to_track
|
1269
|
+
goal_type_to_track = @goal_type_to_track
|
1270
|
+
else
|
1271
|
+
goal_type_to_track = GOAL_TYPES['ALL']
|
1272
|
+
end
|
1273
|
+
elsif GOAL_TYPES.key? options[:goal_type_to_track]
|
1274
|
+
goal_type_to_track = options[:goal_type_to_track]
|
1275
|
+
else
|
1276
|
+
@logger.log(
|
1277
|
+
LogLevelEnum::ERROR,
|
1278
|
+
format(
|
1279
|
+
LogMessageEnum::ErrorMessages::INVALID_GOAL_TYPE,
|
1280
|
+
file: FILE
|
1281
|
+
)
|
1282
|
+
)
|
1283
|
+
end
|
1284
|
+
goal_type_to_track
|
1285
|
+
end
|
903
1286
|
end
|