Google Chat アプリのホームページを作成する

このページでは、Google Chat 用アプリでダイレクト メッセージのホームページを作成する方法について説明します。ホームページ(Google Chat API では「アプリホーム」と呼ばれます)は、ユーザーと Chat 用アプリ間の 1 対 1 のダイレクト メッセージ スペースの [ホーム] タブに表示される、カスタマイズ可能なカード インターフェースです。

2 つのウィジェットを含むアプリのホームカード。
図 1: Chat 用アプリとのダイレクト メッセージに表示されるホームページの例。

他の Google Workspace ホスト アプリケーションとは異なり、Chat を拡張するアドオンは、右側のクイック アクセス パネルにホームページを表示せず、マニフェストで addOns.common.homepageTrigger を使用しません。代わりに、Chat アプリとの 1 対 1 のダイレクト メッセージの [ホーム] タブにカードとしてホームページが表示されます。このホームページは Google Cloud コンソールで構成されます。

アプリホームを使用すると、Chat 用アプリの操作に関するヒントを共有したり、ユーザーのパーソナライズされたダッシュボードを表示したり、ユーザーが Chat から外部のサービスやツールにアクセスして構成したりできます。


カード作成ツールを使用して、Chat 用アプリのメッセージとユーザー インターフェースを設計してプレビューします。

カードビルダーを開く

前提条件

HTTP

ユーザー インタラクションを受け取って応答する Google Chat 用アプリ。作成するには、HTTP クイックスタートを完了します。

Apps Script

ユーザー インタラクションを受け取って応答する Google Chat 用アプリ。作成するには、Apps Script クイックスタートを完了します。

Chat 用アプリの [アプリのホーム] を構成する

アプリのホームをサポートするには、Google Cloud コンソールで [アプリのホームをサポート] を有効にして、[アプリのホーム] トリガーを構成します。ユーザーが Chat アプリとの 1 対 1 のダイレクト メッセージで [ホーム] タブを開くと、Chat 用アプリは アプリホーム トリガー イベントを受け取ります。

Google Cloud コンソールでアプリのホームを構成するには:

  1. Google Cloud コンソールで、メニュー > [API とサービス] > [有効な API とサービス] > [Google Chat API] > [構成] に移動します。

    Chat API の構成に移動

  2. [インタラクティブ機能] で、[インタラクティブ機能を有効にする] がオンになっていることを確認し、[機能] で [アプリのホームをサポートする] チェックボックスをオンにします。

  3. [接続設定] > [トリガー] で、Chat 用アプリのアーキテクチャに基づいて、[アプリのホーム] フィールドにアプリのホーム ハンドラを指定します。

    • HTTP: アプリのホーム リクエストを処理する HTTPS エンドポイント URL を入力します(または、すべてのトリガーに共通の HTTP エンドポイント URL を使用する を選択して、共通の HTTP エンドポイント URL がすべてのイベントを受信するようにします)。
    • Google Apps Script: ホームページ カードを作成して返す Google Apps Script コールバック関数の名前を入力します(デフォルトは onAppHome)。
  4. [保存] をクリックします。

App Home イベント オブジェクトを処理する

ユーザーが Chat アプリとの 1 対 1 のダイレクト メッセージの [ホーム] タブを開くと、Chat はアプリホームのエンドポイントまたはコールバック関数にイベント オブジェクトを送信します。

スペースやメッセージのインタラクション イベントとは異なり、最初の App Home イベント オブジェクトにはユニオン インタラクション ペイロード(messagePayload など)は含まれません。次のフィールドが含まれます。

  • commonEventObject: clientPlatform、hostApp("CHAT")、userLocale、userTimezone を含みます。
  • chat.user: [ホーム] タブを開いた Chat ユーザー。
  • chat.eventTime: ユーザーが [ホーム] タブを開いたときのタイムスタンプ。

アプリのホームカードを作成する

ユーザーが [ホーム] タブを開いたときに、アプリのホーム トリガー イベントを処理するには、pushCard ナビゲーション アクションと Card を含む RenderActions オブジェクトを返します。インタラクティブなエクスペリエンスを作成するために、カードにはボタンやテキスト入力などのインタラクティブなウィジェットを含めることができます。

HTTP

{
  "action": {
    "navigations": [
      {
        "pushCard": {
          "header": {
            "title": "Welcome to App Home"
          },
          "sections": [
            {
              "widgets": [
                {
                  "textParagraph": {
                    "text": "Manage your settings and view your dashboard here."
                  }
                },
                {
                  "buttonList": {
                    "buttons": [
                      {
                        "text": "Refresh",
                        "onClick": {
                          "action": {
                            "function": "https://example.com/updateAppHome"
                          }
                        }
                      }
                    ]
                  }
                }
              ]
            }
          ]
        }
      }
    ]
  }
}

Apps Script

/**
 * Builds and returns the App Home card when a user opens the Home tab.
 *
 * @param {Object} event The event object from Google Chat.
 * @return {ActionResponse} The RenderActions response pushing the homepage card.
 */
function onAppHome(event) {
  const card = CardService.newCardBuilder()
      .setHeader(
          CardService.newCardHeader().setTitle('Welcome to App Home'))
      .addSection(
          CardService.newCardSection()
              .addWidget(
                  CardService.newTextParagraph().setText(
                      'Manage your settings and view your dashboard here.'))
              .addWidget(
                  CardService.newButtonSet().addButton(
                      CardService.newTextButton()
                          .setText('Refresh')
                          .setOnClickAction(
                              CardService.newAction().setFunctionName(
                                  'updateAppHome')))))
      .build();

  return CardService.newActionResponseBuilder()
      .setNavigation(CardService.newNavigation().pushCard(card))
      .build();
}

アプリのホームの操作に応答する

アプリのホームカードにボタンやフォーム入力などのインタラクティブなウィジェットが含まれている場合、ボタンをクリックすると、chat.buttonClickedPayload(commonEventObject.parameters と commonEventObject.formInputs も含む)を含むイベント オブジェクトが、ボタンの構成済みアクション関数またはエンドポイントに送信されます。

ユーザー操作に応じてアプリのホームカードを更新するには、updateCard ナビゲーション アクションを含む RenderActions オブジェクトを返します。インタラクティブ ウィジェットからフォーム入力を読み取る方法については、カードでユーザーが入力したフォームデータを読み取るをご覧ください。

HTTP

{
  "action": {
    "navigations": [
      {
        "updateCard": {
          "header": {
            "title": "Welcome to App Home"
          },
          "sections": [
            {
              "widgets": [
                {
                  "textParagraph": {
                    "text": "Last updated: 2026-10-02T23:00:00Z"
                  }
                }
              ]
            }
          ]
        }
      }
    ]
  }
}

Apps Script

/**
 * Updates the App Home card when a user clicks the Refresh button.
 *
 * @param {Object} event The event object from Google Chat.
 * @return {ActionResponse} The RenderActions response updating the homepage card.
 */
function updateAppHome(event) {
  const updatedCard = CardService.newCardBuilder()
      .setHeader(
          CardService.newCardHeader().setTitle('Welcome to App Home'))
      .addSection(
          CardService.newCardSection().addWidget(
              CardService.newTextParagraph().setText(
                  'Last updated: ' + new Date().toTimeString())))
      .build();

  return CardService.newActionResponseBuilder()
      .setNavigation(CardService.newNavigation().updateCard(updatedCard))
      .build();
}

アプリのホームからダイアログを開く

Chat 用アプリは、ダイアログを開いて App Home での操作に応答することもできます。

さまざまなウィジェットが表示されたダイアログ。
図 2: ユーザーに連絡先の追加を求めるダイアログ。

RenderActions(pushCard、updateCard、endNavigation: "CLOSE_DIALOG")を使用してダイアログを開き、更新し、閉じる方法については、インタラクティブ ダイアログを開くをご覧ください。

アドオンではない Chat 用アプリ: Chat 用アプリのホームページを作成する

Google Workspace アドオンではない Chat 用アプリを管理している場合、ユーザーが [ホーム] タブを開くと、Chat は APP_HOME インタラクション イベントを送信します。また、ユーザーがアプリホーム カードのウィジェットを操作すると、CARD_CLICKED または SUBMIT_FORM インタラクション イベントを送信します。

アドオンではない Chat 用アプリを Google Workspace アドオン フレームワークにアップグレードするには、Google Chat 用アプリを Google Workspace アドオンに変換するをご覧ください。

アドオンではない Chat 用アプリでアプリのホームカードをビルドする

アドオンではない Chat 用アプリでは、最上位の renderActions フィールドに pushCard ナビゲーションを含むレスポンスを返すことで、APP_HOME インタラクション イベントを処理します。

Node.js

node/app-home/index.js
app.post('/', async (req, res) => {
  let event = req.body.chat;

  let body = {};
  if (event.type === 'APP_HOME') {
    // App home is requested
    body = { action: { navigations: [{
      pushCard: getHomeCard()
    }]}}
  } else if (event.type === 'SUBMIT_FORM') {
    // The update button from app home is clicked
    commonEvent = req.body.commonEventObject;
    if (commonEvent && commonEvent.invokedFunction === 'updateAppHome') {
      body = updateAppHome()
    }
  }

  return res.json(body);
});

// Create the app home card
function getHomeCard() {
  return { sections: [{ widgets: [
    { textParagraph: {
      text: "Here is the app home 🏠 It's " + new Date().toTimeString()
    }},
    { buttonList: { buttons: [{
      text: "Update app home",
      onClick: { action: {
        function: "updateAppHome"
      }}
    }]}}
  ]}]};
}

Python

python/app-home/main.py
@app.route('/', methods=['POST'])
def post() -> Mapping[str, Any]:
  """Handle requests from Google Chat

  Returns:
      Mapping[str, Any]: the response
  """
  event = request.get_json()
  match event['chat'].get('type'):

    case 'APP_HOME':
      # App home is requested
      body = { "action": { "navigations": [{
        "pushCard": get_home_card()
      }]}}

    case 'SUBMIT_FORM':
      # The update button from app home is clicked
      event_object = event.get('commonEventObject')
      if event_object is not None:
        if 'update_app_home' == event_object.get('invokedFunction'):
          body = update_app_home()

    case _:
      # Other response types are not supported
      body = {}

  return json.jsonify(body)


def get_home_card() -> Mapping[str, Any]:
  """Create the app home card

  Returns:
      Mapping[str, Any]: the card
  """
  return { "sections": [{ "widgets": [
    { "textParagraph": {
      "text": "Here is the app home 🏠 It's " +
        datetime.datetime.now().isoformat()
    }},
    { "buttonList": { "buttons": [{
      "text": "Update app home",
      "onClick": { "action": {
        "function": "update_app_home"
      }}
    }]}}
  ]}]}

Java

java/app-home/src/main/java/com/google/chat/app/home/App.java
// Process Google Chat events
@PostMapping("/")
@ResponseBody
public GenericJson onEvent(@RequestBody JsonNode event) throws Exception {
  switch (event.at("/chat/type").asText()) {
    case "APP_HOME":
      // App home is requested
      GenericJson navigation = new GenericJson();
      navigation.set("pushCard", getHomeCard());

      GenericJson action = new GenericJson();
      action.set("navigations", List.of(navigation));

      GenericJson response = new GenericJson();
      response.set("action", action);
      return response;
    case "SUBMIT_FORM":
      // The update button from app home is clicked
      if (event.at("/commonEventObject/invokedFunction").asText().equals("updateAppHome")) {
        return updateAppHome();
      }
  }

  return new GenericJson();
}

// Create the app home card
GoogleAppsCardV1Card getHomeCard() {
  return new GoogleAppsCardV1Card()
    .setSections(List.of(new GoogleAppsCardV1Section()
      .setWidgets(List.of(
        new GoogleAppsCardV1Widget()
          .setTextParagraph(new GoogleAppsCardV1TextParagraph()
            .setText("Here is the app home 🏠 It's " + new Date())),
        new GoogleAppsCardV1Widget()
          .setButtonList(new GoogleAppsCardV1ButtonList().setButtons(List.of(new GoogleAppsCardV1Button()
            .setText("Update app home")
            .setOnClick(new GoogleAppsCardV1OnClick()
              .setAction(new GoogleAppsCardV1Action()
                .setFunction("updateAppHome"))))))))));
}

Apps Script

この例では、カード JSON を返すことでカード メッセージを送信します。Apps Script カードサービスを使用することもできます。

apps-script/app-home/app-home.gs
/**
 * Responds to a APP_HOME event in Google Chat.
 */
function onAppHome() {
  return { action: { navigations: [{
    pushCard: getHomeCard()
  }]}};
}

/**
 * Returns the app home card.
 */
function getHomeCard() {
  return { sections: [{ widgets: [
    { textParagraph: {
      text: "Here is the app home 🏠 It's " + new Date().toTimeString()
    }},
    { buttonList: { buttons: [{
      text: "Update app home",
      onClick: { action: {
        function: "updateAppHome"
      }}
    }]}}
  ]}]};
}

アドオンではない Chat 用アプリでアプリのホームのインタラクションに応答する

アドオンではない Chat 用アプリでは、最上位の renderActions フィールドに updateCard ナビゲーションを含むレスポンスを返すことで、アプリのホームカードからの CARD_CLICKED または SUBMIT_FORM インタラクション イベントを処理します。

Node.js

node/app-home/index.js
// Update the app home
function updateAppHome() {
  return { renderActions: { action: { navigations: [{
    updateCard: getHomeCard()
  }]}}}
};

Python

python/app-home/main.py
def update_app_home() -> Mapping[str, Any]:
  """Update the app home

  Returns:
      Mapping[str, Any]: the update card render action
  """
  return { "renderActions": { "action": { "navigations": [{
    "updateCard": get_home_card()
  }]}}}

Java

java/app-home/src/main/java/com/google/chat/app/home/App.java
// Update the app home
GenericJson updateAppHome() {
  GenericJson navigation = new GenericJson();
  navigation.set("updateCard", getHomeCard());

  GenericJson action = new GenericJson();
  action.set("navigations", List.of(navigation));

  GenericJson renderActions = new GenericJson();
  renderActions.set("action", action);

  GenericJson response = new GenericJson();
  response.set("renderActions", renderActions);
  return response;
}

Apps Script

この例では、カード JSON を返すことでカード メッセージを送信します。Apps Script カードサービスを使用することもできます。

apps-script/app-home/app-home.gs
/**
 * Updates the home app.
 */
function updateAppHome() {
  return { renderActions: { action: { navigations: [{
    updateCard: getHomeCard()
  }]}}};
}