プログラムで Remote Config を変更する

このドキュメントでは、Remote Config テンプレートと呼ばれる、JSON 形式のパラメータと条件のセットをプログラムで読み取り、変更する方法について説明します。Remote Config テンプレートを使用すると、バックエンドで加えたテンプレートの変更を、クライアント アプリがクライアント ライブラリを使用してフェッチできます。

このガイドで説明する Remote Config REST API または Admin SDK を使用すると、Firebase コンソールでテンプレートを管理しなくても、Remote Config の変更を独自のプロセスに直接統合できます。たとえば、Remote Config バックエンド API を使用すると、次のことができます。

  • Remote Config 更新のスケジュール。cron ジョブと一緒に API 呼び出しを使用して、Remote Config の値を定期的に変更できます。
  • 独自のシステムから Firebase Remote Config に効率的に移行するための構成値の一括インポート
  • サーバー側で発生したイベントに基づいてアプリ内の値を変更する Cloud Functions for Firebase と Remote Config の使用。たとえば、Remote Config を使用してアプリ内の新しい機能をプロモートした後、十分な人数の担当者が新しい機能を使用していることを検出した段階で、そのプロモーションを自動的にオフにできます。

    Remote Config バックエンドとカスタムツールやサーバーとの連携を表す図

このガイドの以降のセクションで、Remote Config のバックエンド API で実行できるオペレーションについて説明します。こうしたタスクを REST API を使用して実行するコードを確認するには、次のサンプルアプリのいずれかをご覧ください。

Firebase Admin SDK を使用して Remote Config に変更を加える

Admin SDK は、特権環境から Firebase を操作するために使用するサーバー ライブラリのセットです。Admin SDK では、Remote Config の更新に加えて、Firebase 認証トークンの生成と検証、Realtime Database に対する読み取りと書き込みなどを行うことができます。Admin SDK の前提条件と設定について詳しくは、サーバーに Firebase Admin SDK を追加するをご覧ください。

標準的な Remote Config フローでは、現在のテンプレートを取得してパラメータまたはパラメータ グループと条件の一部を変更し、更新後のテンプレートを検証してから公開します。こうした API 呼び出しを行う前に、SDK からのリクエストを認可する必要があります。

SDK を初期化して API リクエストを認可する

パラメータを指定せずに Admin SDK を初期化すると、SDK は Google アプリケーションのデフォルト認証情報を使用し、FIREBASE_CONFIG 環境変数からオプションを読み取ります。FIREBASE_CONFIG 変数は、そこに格納されている値が { で始まる場合、JSON オブジェクトとして解析されます。それ以外の場合、SDK は文字列がオプションを含む JSON ファイルの名前であるとみなします。

例:

Node.js

const admin = require('firebase-admin');
admin.initializeApp();

Java

FileInputStream serviceAccount = new FileInputStream("service-account.json");
FirebaseOptions options = FirebaseOptions.builder()
        .setCredentials(GoogleCredentials.fromStream(serviceAccount))
        .build();
FirebaseApp.initializeApp(options);

現在の Remote Config テンプレートを取得する

Remote Config テンプレートを操作するときは、テンプレートがバージョニングされているという点と、各バージョンが作成されてからアップデートで置き換えられるまでの存続期間は限られていて(90 日間)、保存できるバージョンの最大数は合計 300 であるという点にご注意ください。詳しくは、テンプレートとバージョニングをご覧ください。

バックエンド API を使用すると、Remote Config テンプレートの現在のアクティブ バージョンを JSON 形式で取得できます。

A/B Testing のテストでバリアントとして作成されたパラメータとパラメータ値は、エクスポートされるテンプレートには含まれません。

テンプレートを取得するには次のようにします。

Node.js

function getTemplate() {
  var config = admin.remoteConfig();
  config.getTemplate()
      .then(function (template) {
        console.log('ETag from server: ' + template.etag);
        var templateStr = JSON.stringify(template);
        fs.writeFileSync('config.json', templateStr);
      })
      .catch(function (err) {
        console.error('Unable to get template');
        console.error(err);
      });
}

Java

Template template = FirebaseRemoteConfig.getInstance().getTemplateAsync().get();
// See the ETag of the fetched template.
System.out.println("ETag from server: " + template.getETag());

Remote Config のパラメータを変更する

Remote Config のパラメータとパラメータ グループをプログラムによって変更、追加できます。たとえば、「new_menu」という名前の既存のパラメータ グループに季節情報の表示を制御するパラメータを追加するには、次のようにします。

Node.js

function addParameterToGroup(template) {
  template.parameterGroups['new_menu'].parameters['spring_season'] = {
    defaultValue: {
      useInAppDefault: true
    },
    description: 'spring season menu visibility.',
  };
}

Java

template.getParameterGroups().get("new_menu").getParameters()
        .put("spring_season", new Parameter()
                .setDefaultValue(ParameterValue.inAppDefault())
                .setDescription("spring season menu visibility.")
        );

API を使用すると、新しいパラメータやパラメータ グループの作成や、デフォルト値、条件値、説明の変更を行えます。いずれの場合も、変更後にテンプレートを明示的に公開する必要があります。

Remote Config の条件を変更する

Remote Config の条件と条件値をプログラムによって変更、追加できます。たとえば、新しい条件を追加するには次のようにします。

Node.js

function addNewCondition(template) {
  template.conditions.push({
    name: 'android_en',
    expression: 'device.os == \'android\' && device.country in [\'us\', \'uk\']',
    tagColor: 'BLUE',
  });
}

Java

template.getConditions().add(new Condition("android_en",
        "device.os == 'android' && device.country in ['us', 'uk']", TagColor.BLUE));

いずれの場合も、変更後にテンプレートを明示的に公開する必要があります。

Remote Config バックエンド API では、さまざまな条件と比較演算子を使用してアプリの動作や外観を変更できます。条件と、これらの条件でサポートされる演算子について詳しくは、条件式リファレンスをご覧ください。

Remote Config テンプレートを検証する

必要に応じて、次のように公開前に更新を検証できます。

Node.js

function validateTemplate(template) {
  admin.remoteConfig().validateTemplate(template)
      .then(function (validatedTemplate) {
        // The template is valid and safe to use.
        console.log('Template was valid and safe to use');
      })
      .catch(function (err) {
        console.error('Template is invalid and cannot be published');
        console.error(err);
      });
}

Java

try {
  Template validatedTemplate = FirebaseRemoteConfig.getInstance()
          .validateTemplateAsync(template).get();
  System.out.println("Template was valid and safe to use");
} catch (ExecutionException e) {
  if (e.getCause() instanceof FirebaseRemoteConfigException) {
    FirebaseRemoteConfigException rcError = (FirebaseRemoteConfigException) e.getCause();
    System.out.println("Template is invalid and cannot be published");
    System.out.println(rcError.getMessage());
  }
}

この検証プロセスでは、パラメータや条件で重複しているキー、無効な条件名、存在しない条件、ETag の形式の誤りなどのエラーがチェックされます。たとえば、リクエストに最大許容数(2,000 個)を超えるキーが含まれる場合は、エラー メッセージ Param count too large が返されます。

Remote Config テンプレートを公開する

テンプレートを取得し、必要な更新を加えて改訂したら、テンプレートを公開できます。このセクションに記載する方法でテンプレートを公開すると、既存の構成テンプレート全体が更新後のファイルに置き換えられます。新しいアクティブなテンプレートには、置き換え前のテンプレートよりも 1 つ大きいバージョン番号が割り当てられます。

必要に応じて、REST API を使用して前のバージョンにロールバックできます。更新でエラーが発生するリスクを軽減するために、公開前に検証できます。

ダウンロードされるテンプレートには Remote Config のパーソナライズと条件が含まれています。そのため、別のプロジェクトに公開する場合は、次の制限事項に注意する必要があります。

  • あるプロジェクトから別のプロジェクトにパーソナライズをインポートすることはできません。

    たとえば、あるプロジェクトでパーソナライズを有効にしていて、テンプレートをダウンロードして編集した場合、そのテンプレートを同じプロジェクトに公開することは可能ですが、テンプレートからパーソナライズを削除しない限り別のプロジェクトに公開することはできません。

  • 条件はプロジェクト間でインポートできますが、公開する前に、特定の条件値(アプリ ID やオーディエンスなど)がターゲット プロジェクトに存在している必要があります。

    たとえば、プラットフォーム値として iOS が指定される条件を使用する Remote Config パラメータがある場合、プラットフォーム値はすべてのプロジェクトで同じであるため、そのテンプレートを別のプロジェクトに公開できます。一方で、ターゲット プロジェクトに存在しない特定のアプリ ID やユーザー オーディエンスに依存する条件が含まれている場合は、検証に失敗します。

  • 公開するテンプレートに Google アナリティクスに依存する条件が含まれている場合は、ターゲット プロジェクトでアナリティクスを有効にする必要があります。

Node.js

function publishTemplate() {
  var config = admin.remoteConfig();
  var template = config.createTemplateFromJSON(
      fs.readFileSync('config.json', 'UTF8'));
  config.publishTemplate(template)
      .then(function (updatedTemplate) {
        console.log('Template has been published');
        console.log('ETag from server: ' + updatedTemplate.etag);
      })
      .catch(function (err) {
        console.error('Unable to publish template.');
        console.error(err);
      });
}

Java

try {
  Template publishedTemplate = FirebaseRemoteConfig.getInstance()
          .publishTemplateAsync(template).get();
  System.out.println("Template has been published");
  // See the ETag of the published template.
  System.out.println("ETag from server: " + publishedTemplate.getETag());
} catch (ExecutionException e) {
  if (e.getCause() instanceof FirebaseRemoteConfigException) {
    FirebaseRemoteConfigException rcError = (FirebaseRemoteConfigException) e.getCause();
    System.out.println("Unable to publish template.");
    System.out.println(rcError.getMessage());
  }
}

REST API を使用して Remote Config を変更する

このセクションでは、https://firebaseremoteconfig.googleapis.com にある Remote Config REST API の主な機能について説明します。詳細については、API リファレンスをご覧ください。

API リクエストを認証して認可するためのアクセス トークンを取得する

Firebase プロジェクトでは Google サービス アカウントがサポートされています。これを使用して、アプリサーバーまたは信頼できる環境から Firebase サーバー API を呼び出せます。コードをローカルで開発している、または アプリケーションをオンプレミスでデプロイしている場合、このサービス アカウントで取得した認証情報を使用してサーバー リクエストを認可することができます。

サービス アカウントを認証して Firebase サービスへのアクセスを認可するには、秘密鍵ファイルを JSON 形式で生成する必要があります。

サービス アカウント用の秘密鍵ファイルを生成するには:

  1. Firebase コンソールで、[設定] > [サービス アカウント] を開きます。

  2. [新しい秘密鍵の生成] をクリックし、[キーを生成] をクリックして確定します。

  3. キーを含む JSON ファイルを安全に保管します。

サービス アカウントを介して認可する場合、アプリケーションの認証情報を指定するには 2 つの選択肢があります。GOOGLE_APPLICATION_CREDENTIALS 環境変数を設定することも、サービス アカウント キーへのパスをコード内で明示的に示すこともできます。 1 つ目の選択肢のほうが安全であるため、そちらを強くおすすめします。

環境変数を設定するには:

環境変数 GOOGLE_APPLICATION_CREDENTIALS を、サービス アカウント キーが含まれる JSON ファイルのファイルパスに設定します。 この変数は現在のシェル セッションにのみ適用されるので、新しいセッションを開く場合は、変数を再度設定してください。

Linux または macOS

export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/service-account-file.json"

Windows

PowerShell を使用する場合:

$env:GOOGLE_APPLICATION_CREDENTIALS="C:\Users\username\Downloads\service-account-file.json"

上述の手順を完了すると、アプリケーションのデフォルト認証情報(ADC)は認証情報を暗黙的に判別し、Google 以外の環境でテストまたは実行する際にサービス アカウントの認証情報を使用できるようになります。

次に示すように、有効期間の短い OAuth 2.0 アクセス トークンを取得するために、適切な言語の Google 認証ライブラリと一緒に Firebase 認証情報を使用します。

node.js

 function getAccessToken() {
  return admin.credential.applicationDefault().getAccessToken()
      .then(accessToken => {
        return accessToken.access_token;
      })
      .catch(err => {
        console.error('Unable to get access token');
        console.error(err);
      });
}

この例では、Google API クライアント ライブラリはリクエストを JSON Web Token(JWT)で認証します。詳細については、JSON Web Token をご覧ください。

Python

def _get_access_token():
  """Retrieve a valid access token that can be used to authorize requests.

  :return: Access token.
  """
  credentials = ServiceAccountCredentials.from_json_keyfile_name(
      'service-account.json', SCOPES)
  access_token_info = credentials.get_access_token()
  return access_token_info.access_token

Java

public static String getAccessToken() throws IOException {
  GoogleCredentials googleCredentials = GoogleCredentials
          .fromStream(new FileInputStream("service-account.json"))
          .createScoped(Arrays.asList(SCOPES));
  googleCredentials.refreshAccessToken();
  return googleCredentials.getAccessToken().getTokenValue();
}

アクセス トークンが期限切れになると、更新されたアクセス トークンを取得するために、トークンの更新メソッドが自動的に呼び出されます。

Remote Config へのアクセスを認可するには、スコープ https://www.googleapis.com/auth/firebase.remoteconfig をリクエストします。

Remote Config テンプレートを変更する

Remote Config テンプレートを操作するときは、テンプレートがバージョニングされているという点と、各バージョンが作成されてからアップデートで置き換えられるまでの存続期間は限られていて(90 日間)、保存できるバージョンの最大数は合計 300 であるという点にご注意ください。詳しくは、テンプレートとバージョニングをご覧ください。

現在の Remote Config テンプレートを取得する

バックエンド API を使用すると、Remote Config テンプレートの現在のアクティブ バージョンを JSON 形式で取得できます。

A/B Testing のテストでバリアントとして作成されたパラメータとパラメータ値は、エクスポートされるテンプレートには含まれません。

以下のコマンドを使用します。

cURL

curl --compressed -D headers -H "Authorization: Bearer token" -X GET https://firebaseremoteconfig.googleapis.com/v1/projects/my-project-id/remoteConfig -o filename

このコマンドは、JSON ペイロードを 1 つのファイルに出力し、ヘッダー(ETag を含む)を別のファイルに出力します。

未加工の HTTP リクエスト

Host: firebaseremoteconfig.googleapis.com

GET /v1/projects/my-project-id/remoteConfig HTTP/1.1
Authorization: Bearer token
Accept-Encoding: gzip

この API 呼び出しは、後続のリクエストで使用する ETag が組み込まれた個別のヘッダーとともに、次の JSON を返します。

Remote Config テンプレートを検証する

必要に応じて、公開前に更新を検証できます。テンプレートの更新を検証するには、公開リクエストの末尾に URL パラメータ ?validate_only=true を追加します。レスポンスでステータス コード 200 が返され、ETag の接尾辞が -0 に更新されている場合は、更新の検証が成功したことを意味します。200 以外のレスポンスは、JSON データに、公開前に訂正が必要なエラーが含まれていることを意味します。

Remote Config テンプレートを更新する

テンプレートを取得し、必要な更新を加えて JSON の内容を改訂したら、テンプレートを公開できます。このセクションに記載する方法でテンプレートを公開すると、既存の構成テンプレート全体が更新後のファイルに置き換えられます。新しいアクティブなテンプレートには、置き換え前のテンプレートよりも 1 つ大きいバージョン番号が割り当てられます。

必要に応じて、REST API を使用して前のバージョンにロールバックできます。更新でエラーが発生するリスクを軽減するために、公開前に検証できます。

ダウンロードされるテンプレートには Remote Config のパーソナライズと条件が含まれています。そのため、別のプロジェクトに公開する場合は、次の制限事項に注意する必要があります。

  • あるプロジェクトから別のプロジェクトにパーソナライズをインポートすることはできません。

    たとえば、あるプロジェクトでパーソナライズを有効にしていて、テンプレートをダウンロードして編集した場合、そのテンプレートを同じプロジェクトに公開することは可能ですが、テンプレートからパーソナライズを削除しない限り別のプロジェクトに公開することはできません。

  • 条件はプロジェクト間でインポートできますが、公開する前に、特定の条件値(アプリ ID やオーディエンスなど)がターゲット プロジェクトに存在している必要があります。

    たとえば、プラットフォーム値として iOS が指定される条件を使用する Remote Config パラメータがある場合、プラットフォーム値はすべてのプロジェクトで同じであるため、そのテンプレートを別のプロジェクトに公開できます。一方で、ターゲット プロジェクトに存在しない特定のアプリ ID やユーザー オーディエンスに依存する条件が含まれている場合は、検証に失敗します。

  • 公開するテンプレートに Google アナリティクスに依存する条件が含まれている場合は、ターゲット プロジェクトでアナリティクスを有効にする必要があります。

cURL

curl --compressed -H "Content-Type: application/json; UTF8" -H "If-Match: last-returned-etag" -H "Authorization: Bearer token" -X PUT https://firebaseremoteconfig.googleapis.com/v1/projects/my-project-id/remoteConfig -d @filename

この curl コマンドでは、コンテンツを指定するために「@」文字を使用し、その後にファイル名を続けます。

未加工の HTTP リクエスト

Host: firebaseremoteconfig.googleapis.com
PUT /v1/projects/my-project-id/remoteConfig HTTP/1.1
Content-Length: size
Content-Type: application/json; UTF8
Authorization: Bearer token
If-Match: expected ETag
Accept-Encoding: gzip
JSON_HERE

これは書き込みリクエストなので、このコマンドによって ETag が変更されます。更新された ETag は、次の PUT コマンドのレスポンス ヘッダーに入力されます。

Remote Config の条件を変更する

プログラムによって Remote Config の条件と条件値を変更できます。REST API を使用する場合、テンプレートを公開する前に、テンプレートを直接編集して条件を変更する必要があります。

{
  "conditions": [{
    "name": "android_english",
    "expression": "device.os == 'android' && device.country in ['us', 'uk']",
    "tagColor": "BLUE"
  }, {
    "name": "tenPercent",
    "expression": "percent <= 10",
    "tagColor": "BROWN"
  }],
  "parameters": {
    "welcome_message": {
      "defaultValue": {
        "value": "Welcome to this sample app"
      },
      "conditionalValues": {
        "tenPercent": {
          "value": "Welcome to this new sample app"
        }
      },
      "description": "The sample app's welcome message"
    },
    "welcome_message_caps": {
      "defaultValue": {
        "value": "false"
      },
      "conditionalValues": {
        "android_english": {
          "value": "true"
        }
      },
      "description": "Whether the welcome message should be displayed in all capital letters."
    }
  }
}

上記の変更では、まず一連の条件を定義してから、各パラメータのデフォルト値と条件に基づくパラメータ値(条件値)を定義します。さらに、要素ごとにオプションの説明を追加します。コードコメントと同様に、この説明はデベロッパーのためのもので、アプリには表示されません。また、バージョン管理の目的で ETag も提供されます。

Remote Config バックエンド API では、さまざまな条件と比較演算子を使用してアプリの動作や外観を変更できます。条件と、これらの条件でサポートされる演算子について詳しくは、条件式リファレンスをご覧ください。

HTTP エラーコード

ステータス コード 意味
200 正常に更新されました。
400 検証エラーが発生しました。たとえば、リクエストに最大許容数(2,000 個)を超えるキーが含まれる場合は、ステータス コード 400(Bad Request)とエラー メッセージ「Param count too large」が返されます。またこの HTTPS ステータス コードは、次の 2 つの状況で発生します。
  • 最後に ETag 値を取得した後に値と条件のセットが更新されているため、バージョンの不一致エラーが発生した。このエラーを解決するには、GET コマンドを使用して新しいテンプレートと ETag 値を取得し、テンプレートを更新してから、そのテンプレートと新しい ETag 値を使用して送信する必要があります。
  • If-Match ヘッダーを指定せずに PUT コマンド(Remote Config テンプレートの更新リクエスト)が行われた。
401 認可エラーが発生しました(アクセス トークンが指定されていないか、Firebase Remote Config REST API が Cloud デベロッパー コンソール内のプロジェクトにまだ追加されていません)。
403 認証エラーが発生しました(誤ったアクセス トークンが提供された)。
500 内部エラーが発生しました。このエラーが発生した場合は、Firebase サポート チケットを申請してください

ステータス コード 200 の場合、Remote Config テンプレート(プロジェクトのパラメータ、値、および条件)がすでに更新され、このプロジェクトを使用するアプリで利用できる状態になっています。その他のステータス コードの場合は、これまでの Remote Config テンプレートが引き続き使用されます。

テンプレートに更新を送信した後、Firebase コンソールに移動して、意図したとおりに変更が表示されることを確認します。条件の順序は条件の評価内容に影響するため、ここで確認しておくことが重要です(最初に true と評価された条件が適用されます)。

ETag の使用と強制的な更新

Remote Config REST API では、エンティティ タグ(ETag)を使用して、競合状態やリソースの更新の重複を防ぎます。ETag の詳細については、ETag-HTTP をご覧ください。

REST API では、最新の GET コマンドで提供された ETag をキャッシュに保存し、PUT コマンドを発行するときに If-Match リクエスト ヘッダーでその ETag 値を使用することをおすすめします。PUT コマンドの結果が HTTPS ステータス コード 409 の場合、新しい GET コマンドを発行して、次の PUT コマンドで使用する新しい ETag とテンプレートを取得する必要があります。

ETag および ETag が提供する保護を回避するには、If-Match: * という方法で Remote Config テンプレートを強制的に更新できます。ただし、複数のクライアントが Remote Config テンプレートを更新する場合は、Remote Config テンプレートの更新が失われる危険性があるため、この方法はおすすめしません。こうした競合は、API を使用する複数のクライアント、または API クライアントおよび Firebase コンソール ユーザーからの更新の競合によって発生する可能性があります。

Remote Config テンプレートのバージョン管理の指針については、Remote Config テンプレートとバージョニングをご覧ください。