エンドポイントベースのA/Bテストをセットアップする

エンドポイントベースのA/Bテストは、公開中スキルのコードに条件文を追加することによって制御します。これらの文によりスキルは、コントロールバージョン(C)、トリートメントバージョン(T1)の2つのバージョンに分岐します。

このロジックをセットアップしてテストを有効にしたあとに、スキルユーザーがスキルを起動すると、2つのバージョンのいずれかがランダムに提供されます。テストが終了したら、収集したメトリクスを分析し、どのスキルバージョンを使い続けるかを判断します。

このチュートリアルについて

このチュートリアルでは、ASKコマンドラインインターフェース(CLI)を使って、エンドポイントベースのA/Bテストをセットアップする手順を最初から最後まで紹介します。

以下のステップでは、2つのISP Upsell文の効果を、テストメトリクスを追跡することで測定するテストを作成します。 使用するメトリクスは、CPDR、ISP_SALES_QUANTITY、およびNEXT_DAY_RETENTIONです。

このタスクを実行するには、1つのUpsell文をスキルのCバージョンに、もう1つのUpsell文をスキルのT1バージョンに、それぞれ割り当てます。

チュートリアルの条件

このチュートリアルをそのまま使うには、次の前提条件を満たす必要があります。

  • スキルにスキル内課金(ISP)を実装しており、ISPステータスが公開中であること。
  • スキルでISP Upsellメッセージを設定していること。

スキルでISPを使っていない場合

スキルがISPを使っていない場合でも、このチュートリアルを利用できます。その際は、ISPのコード例ではなく、汎用コード例を使いますステップ2: スキルコードを更新するを参照)。テストするスキルコードロジックに合わせて汎用コード例を設定します。

エンドポイントベースのA/Bテスト利用資格条件

エンドポイントベースのA/Bテストを実施するには、次の利用資格条件を満たす必要があります。

手順の概要

以下のタスクリストは、このチュートリアルの各ステップをまとめたものです。

ステップ1: A/Bテストを作成する

ASK CLIを使ってテストメトリクスを使用するA/Bテストを作成します。

A/Bテストを作成する

  1. 次のコマンドを使ってA/Bテストを作成します。

    ISP Upsellメッセージのテストを行わない場合、次のcreate-experimentパラメーターを変更します。

    ask smapi create-experiment --skill-id <skill-id> --experiment-name "my_experiment" --experiment-description "My first A/B test" --experiment-type ENDPOINT_BASED --experiment-planned-duration "P3W" --experiment-exposure percentage 10 --experiment-metric-configurations "[{\"name\":\"CPDR\",\"metricTypes\":[\"KEY\"],\"expectedChange\":\"DECREASE\"},{\"name\":\"ISP_SALES_QUANTITY\",\"metricTypes\":[\"KEY\"],\"expectedChange\":\"INCREASE\"},{\"name\":\"NEXT_DAY_RETENTION\",\"metricTypes\":[\"GUARDRAIL\"],\"expectedChange\":\"INCREASE\"}]" --debug                          
    
  2. テストIDを探します。

    テストを作成すると、赤字で示したようにテストIDを含む内容が出力されます。この値は次のステップで必要です。

     {
       "key": "location",
       "value": "/v0/skills/amzn1.ask.skill.66424560-4gh4-4358-94b1-741ff424e423/experiments/a556651f-f432-406c-a6a6-c5e74fd654fd"
     },

ステップ2: スキルコードを更新する

A/Bテストを作成したら、CとT1のステージを処理する条件文にスキルコードを分岐させます。

スキルコードを分岐させる

  1. スキルコードに以下のコード例を追加します。
    • ISPのアップセルメッセージをテストしている場合、ISPのコード例を選択します。
    • カスタムテストを実施している場合、汎用コード例を選択します。
    ISPの例

    NodeJSの例

     const UpsellRequestHandler = {
       canHandle(handlerInput) {
           return handlerInput.requestEnvelope.request.type === 'UpsellRequest';
       },
       handle(handlerInput) {
    
         const experimentId = "<<experiment_id>>"; // ASK CLI/開発者コンソールでテストIDを自分のIDに置き換えます
         const experiment = handlerInput.requestEnvelope.context.Experimentation
                               .activeExperiments.find(exp => exp.id == experimentId);
    
         if (experiment) {
           const treatment = experiment.assignedVariant.name;
    
           if (treatment == interfaces.alexa.experimentation.VariantName.TREATMENT_1) {
             return handlerInput.responseBuilder.addDirective({
                 type: "Connections.SendRequest",
                 name: "Upsell",
                 payload: {
                     InSkillProduct: {
                         productId: "myISP_productId_1"                       
                     },
                 upsellMessage: requestAttributes.t("TREATMENT_UPSELL_MSG")                        
                 }})
               .addExperimentTrigger(experimentId)
               .shouldEndSession(false)
               .getResponse();
           } else {
             return handlerInput.responseBuilder.addDirective({
                 type: "Connections.SendRequest",
                 name: "Upsell",
                 payload: {
                     InSkillProduct: {
                         productId: "myISP_productId_2"                       
                     },
                 upsellMessage: requestAttributes.t("CONTROL_UPSELL_MSG")                        
                 }})
               .addExperimentTrigger(experimentId)
               .shouldEndSession(false)
               .getResponse();
           }
         } else { // ユーザーにはテストが表示されません。デフォルトのコントロールの動作です。
           return handlerInput.responseBuilder.addDirective({
             type: "Connections.SendRequest",
             name: "Upsell",
             payload: {
                 InSkillProduct: {
                     productId: "myISP_productId_1"                       
                 },
             upsellMessage: requestAttributes.t("CONTROL_UPSELL_MSG")                        
             }})
           .shouldEndSession(false)
           .getResponse();
         }                    
       }
      };
    
    汎用例

    NodeJSの例

     const experimentId = "<<experiment_id>>"; // ASK CLI/開発者コンソールでテストIDを自分のIDに置き換えます
           const experiment = handlerInput.requestEnvelope.context.Experimentation
                               .activeExperiments.find(exp => exp.id == experimentId);
           if (experiment) {
    
             const treatment = experiment.assignedVariant.name;
    
             if (treatment == interfaces.alexa.experimentation.VariantName.TREATMENT_1) {
               return handlerInput.responseBuilder.speak("トリートメントの応答")
                     .addExperimentTrigger(experimentId)
                     .getResponse();
             } else {
               return handlerInput.responseBuilder.speak("control response")
                     .addExperimentTrigger(experimentId)
                     .getResponse();
             }
           } else  {
             return handlerInput.responseBuilder.speak("トリートメントには表示されません")
                   .getResponse();
           }
    
    リクエストの例

    リクエストのペイロードには、A/Bテスト作成時に生成されたテストIDのactiveExperimentsオブジェクトが含まれます。assignedVariantオブジェクトには、リクエストのバリエーション名が含まれます。この値は、CONTROLTREATMENT_1のいずれかです。

     {
     "version": "1.0",
     "session": {},
     "context": {
       "experimentation": {
         "activeExperiments": [
           {
             "id": "テストID",
             "assignedVariant": {
               "name": "TREATMENT_1"
             }
           }
         ]
       }
     },
     "request": {}
    }
    
    応答の例

    応答には、スキルがA/BテストをトリガーしたかどうかをAlexaが判断するのに使用するexperimentationオブジェクトと、triggeredExperimentsパラメーターが含まれます。両方ともテストメトリクスの算出に必要です。応答のテストIDは、テスト作成時に受け取ったテストIDと一致している必要があります。

     {
       "response": {
         "outputSpeech": {},
         "card": {},
         "directives": [],
         "experimentation": {
           "triggeredExperiments": ["<<リクエストペイロードから取得したテストID>>"]
         }
       }
     }
    
  2. コピーしたコードの以下のセクションを変更します。

    ISPの例
    • テストID<<experiment_id>>のすべてのインスタンスを検索し、生成済みのテストIDで置き換えます。
    • アップセルメッセージTREATMENT_UPSELL_MSGCONTROL_UPSELL_MSGの両方に、異なるUpsellメッセージを割り当てます。
    • ISP商品ID – 有効なISP商品IDをCおよびT1のInSkillProductオブジェクトに指定します。商品IDが公開中、つまり商品が認定済みで公開されていることを確認します。ISP商品IDの詳細については、スキルコードにISPのサポートを追加するを参照してください。
    汎用例
    • テストID<<experiment_id>>のすべてのインスタンスを検索し、ステップ1で生成済みのテストIDで置き換えます。
    • カスタムコード – 必要に応じてカスタムコードを変更します。
  3. スキルコードを保存します。

ステップ3: (任意)A/Bテストを評価する

A/Bテストを実際のユーザーに公開する前に、意図したとおりに機能することを確認します。このためには、開発者アカウントのユーザートリートメントオーバーライド値をT1に設定します。この値を設定すると、スキルの起動時にトリートメントエクスペリエンスが提供されます。

A/Bテストを評価する

  1. 次のコマンドで、ユーザートリートメントオーバーライド値をT1に変更します。

    ask smapi set-customer-treatment-override --skill-id <skill-id> --experiment-id <experiment-id> --treatment-id T1

  2. 以下のコマンドでテストを開始します。

    テストが開始されるまでに、最大10分かかる場合があります。

    ask smapi manage-experiment-state --skill-id <skill-id> --experiment-id <experiment-id> --target-state RUNNING

  3. ASKシミュレーターでスキルを開き、テストが機能することを確認します。

    スキルを実行すると、テストのT1エクスペリエンスが提供されます。たとえば、このチュートリアルの場合では、TREATMENT_UPSELL_MSGではなく、CONTROL_UPSELL_MSGがスキルに表示されます。

ステップ4: A/Bテストを開始する

A/Bテストを開始すると、T1エクスペリエンスがユーザーに公開されます。

テスト評価後にA/Bテストを開始する

テストを評価した場合は、以下の手順に従います(詳細は、「ステップ3: (任意)A/Bテストを評価する」を参照)。それ以外の場合、その他のタブに記載されている手順に従います。

以下のコマンドで、露出度を上げます。

ask smapi update-exposure --skill-id <skill-id> --experiment-id <experiment-id> --exposure-percentage 10

既にステップ3でテストを開始しているため、このコマンドで新しいテストエクスペリエンスをユーザーに公開します。

テストを評価せずにA/Bテストを開始する

テストの評価を省略した場合は、以下の手順に従います(詳細は、「ステップ3: (任意)A/Bテストを評価する」を参照)。それ以外の場合、その他のタブに記載されている手順に従います。

以下のコマンドでA/Bテストを開始します。

ask smapi manage-experiment-state --skill-id <skill-id> --experiment-id <experiment-id> --target-state RUNNING

テストが開始されるまでに、最大10分かかる場合があります。テストのステータスを確認するにはget-experiment-stateコマンドを使用します。

ステップ5: A/Bテスト結果を分析する

A/Bテストの結果は、テストの実行中でも終了後でも分析できます。ただし、一部のメトリクスは、確認できる状態になるまで2~5日かかる場合があります。

A/Bテスト結果を分析する

  1. 以下のコマンドを使って、メトリクスが利用できるかどうかを確認します。

    ask smapi list-experiment-metric-snapshots --skill-id <skill-id> --experiment-id <experiment-id>

    このコマンドを実行すると、テストIDと関連するmetricSnapshotIdを含む応答が返されます。

  2. 返されたmetricSnapshotIdを使って、以下のコマンドで詳細な分析レポートを取得します。

    ask smapi get-experiment-metric-snapshot --skill-id <skill-id> --experiment-id <experiment-id> --metric-snapshot-id <metric-snapshot-id>

ステップ6: (任意)露出度を上げる

データを分析したあとに、結論が出せないとわかる場合があります。より多くのデータを収集したい場合、T1グループの露出度を上げてT1グループにより多くのユーザーを含めることができます。この設定をしたあとも、A/Bテストを継続できます。

露出度を上げる

以下のコマンドで、露出度を上げます。

ask smapi update-exposure --skill-id <skill-id> --experiment-id <experiment-id> --exposure-percentage 20

ステップ7: A/Bテストを停止する

A/Bテストの結果に満足できたら、テスト状態をSTOPPEDに変更します。途中で問題に気付いた場合も、テストを停止することができます。

テストを停止したら、メトリクスは収集されなくなります。

A/Bテストを停止する

以下のコマンドを使って、テストの状態をSTOPPEDに変更します。

ask smapi manage-experiment-state --skill-id <skill-id> --experiment-id <experiment-id> --target-state STOPPED

テストを再度行うには、新規のテストをステップ1から作成する必要があります。