Skip to content

Commit 8e1be15

Browse files
Bug fix: Activate/Track method was sending variation to server only from the bucketer. (#22)
1 parent 74b7f79 commit 8e1be15

File tree

4 files changed

+55
-28
lines changed

4 files changed

+55
-28
lines changed

OptimizelySDK.Tests/EventTests/EventBuilderTest.cs

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -241,8 +241,12 @@ public void TestCreateConversionEventNoAttributesNoValue()
241241
{
242242
{ "Content-Type", "application/json"}
243243
});
244+
var experimentToVariationMap = new Dictionary<string, Variation>
245+
{
246+
{"7716830082", new Variation{Id="7722370027", Key="control"} }
247+
};
244248

245-
var logEvent = EventBuilder.CreateConversionEvent(Config, "purchase", new Experiment[] { Config.GetExperimentFromKey("test_experiment") }, TestUserId, null, null);
249+
var logEvent = EventBuilder.CreateConversionEvent(Config, "purchase", experimentToVariationMap, TestUserId, null, null);
246250

247251
TestData.ChangeGUIDAndTimeStamp(logEvent.Params, timeStamp, guid);
248252

@@ -326,8 +330,11 @@ public void TestCreateConversionEventWithAttributesNoValue()
326330
{ "device_type", "iPhone" },
327331
{"company", "Optimizely" }
328332
};
329-
330-
var logEvent = EventBuilder.CreateConversionEvent(Config, "purchase", new Experiment[] { Config.GetExperimentFromKey("test_experiment") }, TestUserId, userAttributes, null);
333+
var experimentToVariationMap = new Dictionary<string, Variation>
334+
{
335+
{"7716830082", new Variation{Id="7722370027", Key="control"} }
336+
};
337+
var logEvent = EventBuilder.CreateConversionEvent(Config, "purchase", experimentToVariationMap, TestUserId, userAttributes, null);
331338

332339
TestData.ChangeGUIDAndTimeStamp(logEvent.Params, timeStamp, guid);
333340

@@ -403,8 +410,13 @@ public void TestCreateConversionEventNoAttributesWithValue()
403410
{ "Content-Type", "application/json"}
404411
});
405412

413+
var experimentToVariationMap = new Dictionary<string, Variation>
414+
{
415+
{"7716830082", new Variation{Id="7722370027", Key="control"} }
416+
};
417+
406418

407-
var logEvent = EventBuilder.CreateConversionEvent(Config, "purchase", new Experiment[] { Config.GetExperimentFromKey("test_experiment") }, TestUserId, null,
419+
var logEvent = EventBuilder.CreateConversionEvent(Config, "purchase", experimentToVariationMap, TestUserId, null,
408420
new EventTags
409421
{
410422
{"revenue", 42 }
@@ -501,7 +513,12 @@ public void TestCreateConversionEventWithAttributesWithValue()
501513
{"company", "Optimizely" }
502514
};
503515

504-
var logEvent = EventBuilder.CreateConversionEvent(Config, "purchase", new Experiment[] { Config.GetExperimentFromKey("test_experiment") }, TestUserId, userAttributes,
516+
var experimentToVariationMap = new Dictionary<string, Variation>
517+
{
518+
{"7716830082", new Variation{Id="7722370027", Key="control"} }
519+
};
520+
521+
var logEvent = EventBuilder.CreateConversionEvent(Config, "purchase", experimentToVariationMap, TestUserId, userAttributes,
505522
new EventTags
506523
{
507524
{"revenue", 42 },
@@ -582,7 +599,12 @@ public void TestCreateConversionEventNoAttributesWithInvalidValue()
582599
{ "Content-Type", "application/json"}
583600
});
584601

585-
var logEvent = EventBuilder.CreateConversionEvent(Config, "purchase", new Experiment[] { Config.GetExperimentFromKey("test_experiment") }, TestUserId, null,
602+
var experimentToVariationMap = new Dictionary<string, Variation>
603+
{
604+
{"7716830082", new Variation{Id="7722370027", Key="control"} }
605+
};
606+
607+
var logEvent = EventBuilder.CreateConversionEvent(Config, "purchase", experimentToVariationMap, TestUserId, null,
586608
new EventTags
587609
{
588610
{"revenue", "42" },
@@ -665,8 +687,12 @@ public void TestConversionEventWithNumericTag()
665687
{ "Content-Type", "application/json"}
666688
});
667689

690+
var experimentToVariationMap = new Dictionary<string, Variation>
691+
{
692+
{"7716830082", new Variation{Id="7722370027", Key="control"} }
693+
};
668694

669-
var logEvent = EventBuilder.CreateConversionEvent(Config, "purchase", new Experiment[] { Config.GetExperimentFromKey("test_experiment") }, TestUserId, null,
695+
var logEvent = EventBuilder.CreateConversionEvent(Config, "purchase", experimentToVariationMap, TestUserId, null,
670696
new EventTags
671697
{
672698
{"revenue", 42 },

OptimizelySDK.Tests/OptimizelyTest.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public void Initialize()
5757
It.IsAny<string>(), It.IsAny<string>(), It.IsAny<UserAttributes>()));
5858

5959
EventBuilderMock.Setup(b => b.CreateConversionEvent(It.IsAny<ProjectConfig>(), It.IsAny<string>(),
60-
It.IsAny<IEnumerable<Experiment>>(), It.IsAny<string>(), It.IsAny<UserAttributes>(), It.IsAny<EventTags>()));
60+
It.IsAny<Dictionary<string, Variation>>(), It.IsAny<string>(), It.IsAny<UserAttributes>(), It.IsAny<EventTags>()));
6161

6262
Config = ProjectConfig.Create(
6363
content: TestData.Datafile,
@@ -499,7 +499,7 @@ public void TestTrackInvalidAttributes()
499499
public void TestTrackNoAttributesNoEventValue()
500500
{
501501
EventBuilderMock.Setup(b => b.CreateConversionEvent(It.IsAny<ProjectConfig>(), It.IsAny<string>(),
502-
It.IsAny<IEnumerable<Experiment>>(), It.IsAny<string>(), It.IsAny<UserAttributes>(), It.IsAny<EventTags>()))
502+
It.IsAny<Dictionary<string,Variation>>(), It.IsAny<string>(), It.IsAny<UserAttributes>(), It.IsAny<EventTags>()))
503503
.Returns(new LogEvent("logx.optimizely.com/track", OptimizelyHelper.SingleParameter,
504504
"POST", new Dictionary<string, string> { }));
505505

@@ -519,7 +519,7 @@ public void TestTrackNoAttributesNoEventValue()
519519
public void TestTrackWithAttributesNoEventValue()
520520
{
521521
EventBuilderMock.Setup(b => b.CreateConversionEvent(It.IsAny<ProjectConfig>(), It.IsAny<string>(),
522-
It.IsAny<IEnumerable<Experiment>>(), It.IsAny<string>(), It.IsAny<UserAttributes>(), It.IsAny<EventTags>()))
522+
It.IsAny<Dictionary<string, Variation>>(), It.IsAny<string>(), It.IsAny<UserAttributes>(), It.IsAny<EventTags>()))
523523
.Returns(new LogEvent("logx.optimizely.com/track", OptimizelyHelper.SingleParameter,
524524
"POST", new Dictionary<string, string> { }));
525525

@@ -537,7 +537,7 @@ public void TestTrackWithAttributesNoEventValue()
537537
public void TestTrackNoAttributesWithEventValue()
538538
{
539539
EventBuilderMock.Setup(b => b.CreateConversionEvent(It.IsAny<ProjectConfig>(), It.IsAny<string>(),
540-
It.IsAny<IEnumerable<Experiment>>(), It.IsAny<string>(), It.IsAny<UserAttributes>(), It.IsAny<EventTags>()))
540+
It.IsAny<Dictionary<string, Variation>>(), It.IsAny<string>(), It.IsAny<UserAttributes>(), It.IsAny<EventTags>()))
541541
.Returns(new LogEvent("logx.optimizely.com/track", OptimizelyHelper.SingleParameter,
542542
"POST", new Dictionary<string, string> { }));
543543

@@ -566,7 +566,7 @@ public void TestTrackWithAttributesWithEventValue()
566566
};
567567

568568
EventBuilderMock.Setup(b => b.CreateConversionEvent(It.IsAny<ProjectConfig>(), It.IsAny<string>(),
569-
It.IsAny<IEnumerable<Experiment>>(), It.IsAny<string>(), It.IsAny<UserAttributes>(), It.IsAny<EventTags>()))
569+
It.IsAny<Dictionary<string, Variation>>(), It.IsAny<string>(), It.IsAny<UserAttributes>(), It.IsAny<EventTags>()))
570570
.Returns(new LogEvent("logx.optimizely.com/track", OptimizelyHelper.SingleParameter,
571571
"POST", new Dictionary<string, string> { }));
572572

@@ -589,7 +589,7 @@ public void TestTrackWithAttributesWithEventValue()
589589
public void TestTrackWithNullAttributesWithNullEventValue()
590590
{
591591
EventBuilderMock.Setup(b => b.CreateConversionEvent(It.IsAny<ProjectConfig>(), It.IsAny<string>(),
592-
It.IsAny<IEnumerable<Experiment>>(), It.IsAny<string>(), It.IsAny<UserAttributes>(), It.IsAny<EventTags>()))
592+
It.IsAny<Dictionary<string, Variation>>(), It.IsAny<string>(), It.IsAny<UserAttributes>(), It.IsAny<EventTags>()))
593593
.Returns(new LogEvent("logx.optimizely.com/track", OptimizelyHelper.SingleParameter,
594594
"POST", new Dictionary<string, string> { }));
595595

@@ -652,7 +652,7 @@ public void TestInvalidDispatchImpressionEvent()
652652
public void TestInvalidDispatchConversionEvent()
653653
{
654654
EventBuilderMock.Setup(b => b.CreateConversionEvent(It.IsAny<ProjectConfig>(), It.IsAny<string>(),
655-
It.IsAny<IEnumerable<Experiment>>(), It.IsAny<string>(), It.IsAny<UserAttributes>(), It.IsAny<EventTags>()))
655+
It.IsAny<Dictionary<string, Variation>>(), It.IsAny<string>(), It.IsAny<UserAttributes>(), It.IsAny<EventTags>()))
656656
.Returns(new LogEvent("logx.optimizely.com/track", OptimizelyHelper.SingleParameter,
657657
"POST", new Dictionary<string, string> { }));
658658

@@ -676,7 +676,7 @@ public void TestInvalidDispatchConversionEvent()
676676
public void TestTrackNoAttributesWithInvalidEventValue()
677677
{
678678
EventBuilderMock.Setup(b => b.CreateConversionEvent(It.IsAny<ProjectConfig>(), It.IsAny<string>(),
679-
It.IsAny<IEnumerable<Experiment>>(), It.IsAny<string>(), It.IsAny<UserAttributes>(), It.IsAny<EventTags>()))
679+
It.IsAny<Dictionary<string, Variation>>(), It.IsAny<string>(), It.IsAny<UserAttributes>(), It.IsAny<EventTags>()))
680680
.Returns(new LogEvent("logx.optimizely.com/track", OptimizelyHelper.SingleParameter,
681681
"POST", new Dictionary<string, string> { }));
682682

@@ -697,7 +697,7 @@ public void TestTrackNoAttributesWithDeprecatedEventValue()
697697
* In this case, int value can't be casted implicitly into Dictionary */
698698

699699
EventBuilderMock.Setup(b => b.CreateConversionEvent(It.IsAny<ProjectConfig>(), It.IsAny<string>(),
700-
It.IsAny<IEnumerable<Experiment>>(), It.IsAny<string>(), It.IsAny<UserAttributes>(), It.IsAny<EventTags>()))
700+
It.IsAny<Dictionary<string, Variation>>(), It.IsAny<string>(), It.IsAny<UserAttributes>(), It.IsAny<EventTags>()))
701701
.Returns(new LogEvent("logx.optimizely.com/track", OptimizelyHelper.SingleParameter,
702702
"POST", new Dictionary<string, string> { }));
703703

@@ -1036,7 +1036,7 @@ public void TestTrackNoAttributesNoEventValueAfterSetForcedVariation()
10361036
};
10371037

10381038
EventBuilderMock.Setup(b => b.CreateConversionEvent(It.IsAny<ProjectConfig>(), It.IsAny<string>(),
1039-
It.IsAny<IEnumerable<Experiment>>(), It.IsAny<string>(), It.IsAny<UserAttributes>(), It.IsAny<EventTags>()))
1039+
It.IsAny<Dictionary<string, Variation>>(), It.IsAny<string>(), It.IsAny<UserAttributes>(), It.IsAny<EventTags>()))
10401040
.Returns(new LogEvent("logx.optimizely.com/track", parameters, "POST", new Dictionary<string, string> { }));
10411041

10421042
var optly = Helper.CreatePrivateOptimizely();

OptimizelySDK/Event/Builder/EventBuilder.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -152,13 +152,14 @@ private Dictionary<string, object> GetImpressionParams(Experiment experiment, st
152152
return impressionEvent;
153153
}
154154

155-
private List<object> GetConversionParams(ProjectConfig config, string eventKey, Experiment[] experiments, string userId, Dictionary<string, object> eventTags)
155+
private List<object> GetConversionParams(ProjectConfig config, string eventKey, Dictionary<string, Variation> experimentIdVariationMap, string userId, Dictionary<string, object> eventTags)
156156
{
157157

158158
var conversionEventParams = new List<object>();
159-
foreach (var experiment in experiments)
159+
foreach (var experimentId in experimentIdVariationMap.Keys)
160160
{
161-
var variation = Bucketer.Bucket(config, experiment, userId);
161+
var variation = experimentIdVariationMap[experimentId];
162+
var experiment = config.ExperimentIdMap[experimentId];
162163
var eventEntity = config.EventKeyMap[eventKey];
163164

164165
if (string.IsNullOrEmpty(variation.Key)) continue;
@@ -255,17 +256,16 @@ public virtual LogEvent CreateImpressionEvent(ProjectConfig config, Experiment e
255256
/// </summary>
256257
/// <param name="config">ProjectConfig Configuration for the project.</param>
257258
/// <param name="eventKey">Event Key representing the event</param>
258-
/// <param name="experiments">collection of Experiments for which conversion event needs to be recorded</param>
259+
/// <param name="ExperimentIdVariationMap">Map of experiment ID to the variation that the user is bucketed into.</param>
259260
/// <param name="userId">ID of user</param>
260261
/// <param name="userAttributes">associative array of Attributes for the user</param>
261262
/// <param name="eventValue">integer Value associated with the event</param>
262263
/// <returns>LogEvent object to be sent to dispatcher</returns>
263-
public virtual LogEvent CreateConversionEvent(ProjectConfig config, string eventKey, IEnumerable<Experiment> experiments,
264-
string userId, UserAttributes userAttributes, EventTags eventTags)
264+
public virtual LogEvent CreateConversionEvent(ProjectConfig config, string eventKey, Dictionary<string, Variation> experimentIdVariationMap, string userId, UserAttributes userAttributes, EventTags eventTags)
265265
{
266266
var commonParams = GetCommonParams(config, userId, userAttributes ?? new UserAttributes());
267267

268-
var conversionOnlyParams = GetConversionParams(config, eventKey, experiments.ToArray(), userId, eventTags).ToArray();
268+
var conversionOnlyParams = GetConversionParams(config, eventKey, experimentIdVariationMap, userId, eventTags).ToArray();
269269

270270
var conversionParams = GetImpressionOrConversionParamsWithCommonParams(commonParams, conversionOnlyParams);
271271

OptimizelySDK/Optimizely.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -206,24 +206,25 @@ public void Track(string eventKey, string userId, UserAttributes userAttributes
206206
}
207207

208208
// Filter out experiments that are not running or when user(s) do not meet conditions.
209-
var validExperiments = new List<Experiment>();
209+
var validExperimentIdToVariationMap = new Dictionary<string, Variation>();
210210
var experimentIds = eevent.ExperimentIds;
211211
foreach (string id in eevent.ExperimentIds)
212212
{
213213
var experiment = Config.GetExperimentFromId(id);
214214
//Validate experiment
215215
var variation = DecisionService.GetVariation(experiment, userId, userAttributes);
216+
216217
if (variation != null)
217218
{
218-
validExperiments.Add(experiment);
219+
validExperimentIdToVariationMap[experiment.Id] = variation;
219220
}
220221
else
221222
{
222223
Logger.Log(LogLevel.INFO, string.Format("Not tracking user \"{0}\" for experiment \"{1}\"", userId, experiment.Key));
223224
}
224225
}
225226

226-
if (validExperiments.Count > 0)
227+
if (validExperimentIdToVariationMap.Count > 0)
227228
{
228229

229230
if (userAttributes != null)
@@ -236,7 +237,7 @@ public void Track(string eventKey, string userId, UserAttributes userAttributes
236237
eventTags = eventTags.FilterNullValues(Logger);
237238
}
238239

239-
var conversionEvent = EventBuilder.CreateConversionEvent(Config, eventKey, validExperiments,
240+
var conversionEvent = EventBuilder.CreateConversionEvent(Config, eventKey, validExperimentIdToVariationMap,
240241
userId, userAttributes, eventTags);
241242
Logger.Log(LogLevel.INFO, string.Format("Tracking event {0} for user {1}.", eventKey, userId));
242243
Logger.Log(LogLevel.DEBUG, string.Format("Dispatching conversion event to URL {0} with params {1}.",

0 commit comments

Comments
 (0)