@@ -57,7 +57,7 @@ def initialize(datafile, event_dispatcher = nil, logger = nil, error_handler = n
57
57
@event_dispatcher = event_dispatcher || EventDispatcher . new
58
58
59
59
begin
60
- validate_inputs ( datafile , skip_json_validation )
60
+ validate_instantiation_options ( datafile , skip_json_validation )
61
61
rescue InvalidInputError => e
62
62
@is_valid = false
63
63
logger = SimpleLogger . new
@@ -82,7 +82,7 @@ def initialize(datafile, event_dispatcher = nil, logger = nil, error_handler = n
82
82
end
83
83
84
84
@bucketer = Bucketer . new ( @config )
85
- @event_builder = EVENT_BUILDERS_BY_VERSION [ @config . version ] . new ( @config , @bucketer )
85
+ @event_builder = EVENT_BUILDERS_BY_VERSION [ @config . version ] . new ( @config )
86
86
end
87
87
88
88
def activate ( experiment_key , user_id , attributes = nil )
@@ -101,24 +101,15 @@ def activate(experiment_key, user_id, attributes = nil)
101
101
return nil
102
102
end
103
103
104
- if attributes && !attributes_valid? ( attributes )
105
- @logger . log ( Logger ::INFO , "Not activating user '#{ user_id } '." )
106
- return nil
107
- end
108
-
109
- unless preconditions_valid? ( experiment_key , user_id , attributes )
110
- @logger . log ( Logger ::INFO , "Not activating user '#{ user_id } '." )
111
- return nil
112
- end
113
-
114
- variation_id = @bucketer . bucket ( experiment_key , user_id )
104
+ variation_key = get_variation ( experiment_key , user_id , attributes )
115
105
116
- if not variation_id
106
+ if variation_key . nil?
117
107
@logger . log ( Logger ::INFO , "Not activating user '#{ user_id } '." )
118
108
return nil
119
109
end
120
110
121
111
# Create and dispatch impression event
112
+ variation_id = @config . get_variation_id_from_key ( experiment_key , variation_key )
122
113
impression_event = @event_builder . create_impression_event ( experiment_key , variation_id , user_id , attributes )
123
114
@logger . log ( Logger ::INFO ,
124
115
'Dispatching impression event to URL %s with params %s.' % [ impression_event . url ,
@@ -129,7 +120,7 @@ def activate(experiment_key, user_id, attributes = nil)
129
120
@logger . log ( Logger ::ERROR , "Unable to dispatch impression event. Error: #{ e } " )
130
121
end
131
122
132
- @config . get_variation_key_from_id ( experiment_key , variation_id )
123
+ variation_key
133
124
end
134
125
135
126
def get_variation ( experiment_key , user_id , attributes = nil )
@@ -148,24 +139,34 @@ def get_variation(experiment_key, user_id, attributes = nil)
148
139
return nil
149
140
end
150
141
151
- if attributes && ! attributes_valid? ( attributes )
142
+ unless preconditions_valid? ( experiment_key , attributes )
152
143
@logger . log ( Logger ::INFO , "Not activating user '#{ user_id } ." )
153
144
return nil
154
145
end
155
146
156
- unless preconditions_valid? ( experiment_key , user_id , attributes )
157
- @logger . log ( Logger ::INFO , "Not activating user '#{ user_id } ." )
147
+ variation_id = @bucketer . get_forced_variation_id ( experiment_key , user_id )
148
+
149
+ unless variation_id . nil?
150
+ return @config . get_variation_key_from_id ( experiment_key , variation_id )
151
+ end
152
+
153
+ unless Audience . user_in_experiment? ( @config , experiment_key , attributes )
154
+ @logger . log ( Logger ::INFO ,
155
+ "User '#{ user_id } ' does not meet the conditions to be in experiment '#{ experiment_key } '." )
158
156
return nil
159
157
end
160
158
161
159
variation_id = @bucketer . bucket ( experiment_key , user_id )
162
- @config . get_variation_key_from_id ( experiment_key , variation_id )
160
+ unless variation_id . nil?
161
+ return @config . get_variation_key_from_id ( experiment_key , variation_id )
162
+ end
163
+ nil
163
164
end
164
165
165
166
def track ( event_key , user_id , attributes = nil , event_tags = nil )
166
167
# Send conversion event to Optimizely.
167
168
#
168
- # event_key - Goal key representing the event which needs to be recorded.
169
+ # event_key - Event key representing the event which needs to be recorded.
169
170
# user_id - String ID for user.
170
171
# attributes - Hash representing visitor attributes and values which need to be recorded.
171
172
# event_tags - Hash representing metadata associated with the event.
@@ -183,34 +184,26 @@ def track(event_key, user_id, attributes = nil, event_tags = nil)
183
184
@logger . log ( Logger ::WARN , 'Event value is deprecated in track call. Use event tags to pass in revenue value instead.' )
184
185
end
185
186
186
- return nil if attributes && !attributes_valid? ( attributes )
187
- return nil if event_tags && !event_tags_valid? ( event_tags )
187
+ return nil unless user_inputs_valid? ( attributes , event_tags )
188
188
189
- experiment_ids = @config . get_experiment_ids_for_goal ( event_key )
189
+ experiment_ids = @config . get_experiment_ids_for_event ( event_key )
190
190
if experiment_ids . empty?
191
191
@config . logger . log ( Logger ::INFO , "Not tracking user '#{ user_id } '." )
192
192
return nil
193
193
end
194
194
195
195
# Filter out experiments that are not running or that do not include the user in audience conditions
196
- valid_experiment_keys = [ ]
197
- experiment_ids . each do |experiment_id |
198
- experiment_key = @config . experiment_id_map [ experiment_id ] [ 'key' ]
199
- unless preconditions_valid? ( experiment_key , user_id , attributes )
200
- @config . logger . log ( Logger ::INFO , "Not tracking user '#{ user_id } ' for experiment '#{ experiment_key } '." )
201
- next
202
- end
203
- valid_experiment_keys . push ( experiment_key )
204
- end
196
+
197
+ experiment_variation_map = get_valid_experiments_for_event ( event_key , user_id , attributes )
205
198
206
199
# Don't track events without valid experiments attached
207
- if valid_experiment_keys . empty?
200
+ if experiment_variation_map . empty?
208
201
@logger . log ( Logger ::INFO , "There are no valid experiments for event '#{ event_key } ' to track." )
209
202
return nil
210
203
end
211
204
212
205
conversion_event = @event_builder . create_conversion_event ( event_key , user_id , attributes ,
213
- event_tags , valid_experiment_keys )
206
+ event_tags , experiment_variation_map )
214
207
@logger . log ( Logger ::INFO ,
215
208
'Dispatching conversion event to URL %s with params %s.' % [ conversion_event . url ,
216
209
conversion_event . params ] )
@@ -223,7 +216,35 @@ def track(event_key, user_id, attributes = nil, event_tags = nil)
223
216
224
217
private
225
218
226
- def preconditions_valid? ( experiment_key , user_id , attributes )
219
+ def get_valid_experiments_for_event ( event_key , user_id , attributes )
220
+ # Get the experiments that we should be tracking for the given event.
221
+ #
222
+ # event_key - Event key representing the event which needs to be recorded.
223
+ # user_id - String ID for user.
224
+ # attributes - Map of attributes of the user.
225
+ #
226
+ # Returns Map where each object contains the ID of the experiment to track and the ID of the variation the user
227
+ # is bucketed into.
228
+
229
+ valid_experiments = { }
230
+ experiment_ids = @config . get_experiment_ids_for_event ( event_key )
231
+ experiment_ids . each do |experiment_id |
232
+ experiment_key = @config . get_experiment_key ( experiment_id )
233
+ variation_key = get_variation ( experiment_key , user_id , attributes )
234
+
235
+ if variation_key . nil?
236
+ @logger . log ( Logger ::INFO , "Not tracking user '#{ user_id } ' for experiment '#{ experiment_key } '." )
237
+ next
238
+ end
239
+
240
+ variation_id = @config . get_variation_id_from_key ( experiment_key , variation_key )
241
+ valid_experiments [ experiment_id ] = variation_id
242
+ end
243
+
244
+ valid_experiments
245
+ end
246
+
247
+ def preconditions_valid? ( experiment_key , attributes = nil , event_tags = nil )
227
248
# Validates preconditions for bucketing a user.
228
249
#
229
250
# experiment_key - String key for an experiment.
@@ -232,18 +253,29 @@ def preconditions_valid?(experiment_key, user_id, attributes)
232
253
#
233
254
# Returns boolean representing whether all preconditions are valid.
234
255
256
+ return false unless user_inputs_valid? ( attributes , event_tags )
257
+
235
258
unless @config . experiment_running? ( experiment_key )
236
259
@logger . log ( Logger ::INFO , "Experiment '#{ experiment_key } ' is not running." )
237
260
return false
238
261
end
239
262
240
- if @config . user_in_forced_variation? ( experiment_key , user_id )
241
- return true
263
+ true
264
+ end
265
+
266
+ def user_inputs_valid? ( attributes = nil , event_tags = nil )
267
+ # Helper method to validate user inputs.
268
+ #
269
+ # attributes - Dict representing user attributes.
270
+ # event_tags - Dict representing metadata associated with an event.
271
+ #
272
+ # Returns boolean True if inputs are valid. False otherwise.
273
+
274
+ if !attributes . nil? && !attributes_valid? ( attributes )
275
+ return false
242
276
end
243
277
244
- unless Audience . user_in_experiment? ( @config , experiment_key , attributes )
245
- @logger . log ( Logger ::INFO ,
246
- "User '#{ user_id } ' does not meet the conditions to be in experiment '#{ experiment_key } '." )
278
+ if !event_tags . nil? && !event_tags_valid? ( event_tags )
247
279
return false
248
280
end
249
281
@@ -268,7 +300,7 @@ def event_tags_valid?(event_tags)
268
300
true
269
301
end
270
302
271
- def validate_inputs ( datafile , skip_json_validation )
303
+ def validate_instantiation_options ( datafile , skip_json_validation )
272
304
unless skip_json_validation
273
305
raise InvalidInputError . new ( 'datafile' ) unless Helpers ::Validator . datafile_valid? ( datafile )
274
306
end
0 commit comments