A/B テストを導入する

A/B テストを設定する に引き続き、以下のサンプルシナリオを例に取りつつ、アプリに A/B テストを導入する方法を説明していきます。

サンプルシナリオ
アプリのあるボタンを押すと新たな機能が有効化されます。現在このボタンのラベルは "Get Started Now!" であり、背景色は "green" になっています。

ユーザーによるボタンの CTR(click through rate)を上げるために、このボタンのラベルを "GET STARTED NOW!" に、背景色を "red" に変更することを検討しています。

この変更が本当に CTR の上昇に貢献するか、A/B テストを使って測定してみましょう。

A/B テスト設定の読み込み

まずは Kii Cloud より A/B テスト設定(Experiment)を読み込みます。A/B テスト設定を読み込むことで、A/B テストの最新ステータス(e.g テストが実行中なのか、完了しているのか)も読み込まれます。

Android 用のサンプルコードを以下に挙げます。

// Get the experiment synchronously.
KiiExperiment experiment = null;
try {
  experiment = KiiExperiment.getByID("7a9d430f-fef6-424d-a521-7e07318650fa");
} catch (AppException e) {
  // Handle the error.
} catch (IOException e) {
  // Handle the error.
}

次に iOS 用のサンプルコードを以下に挙げます。

Swift 3:

// Get the experiment synchronously.
let experiment : KiiExperiment

do{
  experiment = try KiiExperiment.getSynchronous("7a9d430f-fef6-424d-a521-7e07318650fa")
}catch let error as NSError {
  // Handle the error.
  return
}

Objective-C:

// Get the experiment synchronously.
KiiExperiment* experiment = nil;
NSError* error = nil;
experiment = [KiiExperiment getExperimentSynchronous:@"7a9d430f-fef6-424d-a521-7e07318650fa"
                                           withError:&error];
if(error != nil){
  // Handle the error.
}

いずれのケースについても、対象テスト の ID を指定して getByName/getExperimentSynchronous/GetByID メソッドを実行し、A/B テスト設定を読み込んでいます。A/B テストを設定する で説明したように、この ID は開発者ポータルで確認できます。

A/B テスト設定の読み込みが何らかの理由で失敗した場合(たとえば端末がオフラインであった場合など)は例外が発生します。詳細については Javadocappledoc、または Monodoc を参照してください。

バリエーションの適用

A/B テスト設定の読み込みが完了すると、バリエーションの取得および変数値が取得できるようになります。

Android 用のサンプルコードを以下に挙げます。

// Assume these are the variables for variation 'A'.
String buttonColor = "green";
String buttonLabel = "Get Started Now!";

// Initialize a variation. This sample code fallbacks to variation 'A'.
Variation va = experiment.getVariationByName("A");
try {
  va = experiment.getAppliedVariation();
} catch (ExperimentNotAppliedException e) {
  // Failed to apply a variation.
  // Execute the getReason() method for the cause of this error.
  // This sample code fallbacks to variation 'A' if it fails to randomly apply a variation.
}

JSONObject test = va.getVariableSet();
try {
  buttonColor = test.getString("buttonColor");
  buttonLabel = test.getString("buttonLabel");
  // Apply the color and label to the button.
} catch (JSONException e) {
  // This error occurs when the configuration in the developer portal and the code differ.
  // Apply the variables for variation 'A' that are declared above.
}

次に iOS 用のサンプルコードを以下に挙げます。

Swift 3:

let variation : KiiVariation
do{
  variation = try experiment.appliedVariation()

}catch{
  // Failed to apply a variation.
  // Get the error.code property for the cause of this error.
  // This sample code fallbacks to variation 'A' if it fails to randomly apply a variation.
  variation = experiment.variation(byName: "A")!
}

let variableSet = variation.variableDictionary!

// Get the variables for variation 'A'.
let buttonColor = variableSet["buttonColor"] as! String
let buttonLabel = variableSet["buttonLabel"] as! String
// Apply the color and label to the button.

Objective-C:

NSError *error;
KiiVariation *variation = [experiment appliedVariationWithError:&error];
if (error != nil) {
  // Failed to apply a variation.
  // Get the error.code property for the cause of this error.
  // This sample code fallbacks to variation 'A' if it fails to randomly apply a variation.
  variation = [experiment variationByName:@"A"];
}

NSDictionary *variableSet = variation.variableDictionary;

// Get the variables for variation 'A'.
NSString *buttonColor = variableSet[@"buttonColor"];
NSString *buttonLabel = variableSet[@"buttonLabel"];
// Apply the color and label to the button.

サンプルコードでは、以下の処理が行われています。

  1. getAppliedVariation/appliedVariationWithError/GetAppliedVariation メソッドを実行してバリエーションを取得。

  2. getVariableSet/variableDictionary/VariableSet メソッドを実行して変数値を取得。

ここでバリエーションの取得が失敗することがあります。取得失敗する例をいくつか挙げます。

アプリでは、たとえば今回のサンプルコードのようにデフォルト値にフォールバックさせる等、これらのケースにおける処理を実装する必要があります(必要に応じて、Android であれば getReason メソッドを実行、iOS であればエラーコードを確認することも可能です。詳細については Javadoc または appledoc を参照してください)。

ユーザーログインを行わずにバリエーションを取得する

通常のバリエーション取得は、バリエーション決定時に使用する乱数のシードとしてログイン中ユーザーの KiiUser を使用しています。このため、必ずユーザーがログインしている必要があります。

ユーザーがログインしていない状態でバリエーションを取得するには、以下のサンプルコードのようにタイムベースに動作するバリエーションサンプラーを利用します。

Android 用のサンプルコード:

// Assume these are the variables for variation 'A'.
String buttonColor = "green";
String buttonLabel = "Get Started Now!";

// Define a sampler based on the execution timestamp.
VariationSampler randomSampler = new RandomVariationSampler();

// Initialize a variation. This sample code fallbacks to variation 'A'.
Variation fallback = experiment.getVariationByName("A");
Variation va = experiment.getAppliedVariation(fallback, randomSampler);

JSONObject test = va.getVariableSet();
try {
  buttonColor = test.getString("buttonColor");
  buttonLabel = test.getString("buttonLabel");
  // Apply the color and label to the button.
} catch (JSONException e) {
  // This error occurs when the configuration in the developer portal and the code differ.
  // Apply the variables for variation 'A' that are declared above.
}

iOS 用のサンプルコード:

Swift 3:

// Assume these are the variables for variation 'A'.
var buttonColor = "green";
var buttonLabel = "Get Started Now!";

// Define a sampler based on the execution timestamp.
let randomSampler =  KiiRandomVariationSampler()

let fallback = experiment.variation(byName: "A")
let variation = experiment.appliedVariation(with: randomSampler, fallback: fallback)!

let variableSet = variation.variableDictionary!

// Get the variables for variation 'A'.
buttonColor = variableSet["buttonColor"] as! String
buttonLabel = variableSet["buttonLabel"] as! String
// Apply the color and label to the button.

Objective-C:

NSError *error;
// Define a sampler based on the execution timestamp.
id<KiiVariationSampler> *randomSampler =  [[KiiRandomVariationSampler alloc] init];
// Initialize a variation. This sample code fallbacks to variation 'A'.
KiiVariation *fallback = [experiment variationByName:@"A"];
KiiVariation *variation = [experiment appliedVariationWithSampler:randomSampler
                                                         fallback:fallback];

NSDictionary *variableSet = variation.variableDictionary;

// Get the variables for variation 'A'.
NSString *buttonColor = variableSet[@"buttonColor"];
NSString *buttonLabel = variableSet[@"buttonLabel"];
// Apply the color and label to the button.

イベントの送信

最後に View/Conversion イベントを送信する方法を説明します。今回のサンプルシナリオでは、以下の 2 つのイベントを送信することになります(開発者ポータルにおけるイベント設定方法は A/B テストを設定する を参照してください)。

  • アプリが対象ボタンを表示したタイミングで eventViewed イベントを送信。
  • ユーザーが対象ボタンをクリックしたタイミングで eventClicked イベントを送信。

Android 用のサンプルコードを以下に挙げます。

// The button is displayed and the "eventViewed" event is triggered.
KiiEvent viewEvent = va.eventForConversion(getApplicationContext(),
                                           "eventViewed");

// The button is clicked and the "eventClicked" event is triggered.
KiiEvent clickedEvent = va.eventForConversion(getApplicationContext(),
                                              "eventClicked");
try {
  // This sample code does not consider the user operation context.
  // In a real app, send it to the handler of the Activity and View classes.
  viewEvent.push();
  clickedEvent.push();
} catch (IOException e) {
  // This error occurs when the app storage is not accessible.
  // This is generally a rare exception and handling it is out of the scope of this sample code.
}

次に iOS 用のサンプルコードを以下に挙げます。

Swift 3:

// The button is displayed and the "eventViewed" event is triggered.
let viewEvent = variation.eventDictionaryForConversion(withName: "eventViewed")

// The button is clicked and the "eventClicked" event is triggered.
let clickEvent = variation.eventDictionaryForConversion(withName: "eventClicked")

// This sample code does not consider the user operation context.
// In a real app, send it to the handler of the controller class.
KiiAnalytics.trackEvent(experiment.experimentID, withExtras: viewEvent)
KiiAnalytics.trackEvent(experiment.experimentID, withExtras: clickEvent)

Objective-C:

// The button is displayed and the "eventViewed" event is triggered.
NSDictionary *viewEvent = [variation eventDictionaryForConversionWithName:@"eventViewed"];

// The button is clicked and the "eventClicked" event is triggered.
NSDictionary *clickEvent = [variation eventDictionaryForConversionWithName:@"eventClicked"];

// This sample code does not consider the user operation context.
// In a real app, send it to the handler of the controller class.
[KiiAnalytics trackEvent:experiment.experimentID
              withExtras:viewEvent];
[KiiAnalytics trackEvent:experiment.experimentID
              withExtras:clickEvent];

サンプルコードでは、以下の処理が行われています。

  1. イベント名を指定して eventForConversion/eventDictionaryForConversionWithName/EventForConversion メソッドを実行し、イベントを記録。
  2. push/trackEvent/Upload メソッドを実行して、記録したイベントを Kii Cloud に送信。

push/trackEvent/Upload メソッドを実行するとイベントがキャッシュされます。キャッシュされたイベントは、適切なタイミングで自動的に Kii Cloud に送信されます。


これでアプリの設定は終了です。早速 A/B テストを開始してみましょう: A/B テストを実施する