ユニバーサル アクション

コレクションでコンテンツを整理 必要に応じて、コンテンツの保存と分類を行います。

ユニバーサル アクションは、ユーザーが新しいウェブページを開いたり、新しい UI カードを表示したり、特定の Apps Script 関数を選択したときに実行したりできるメニュー項目要素です。操作の仕組みは、カード アクションとほぼ同じですが、現在のアドオンのコンテキストに関係なく、ユニバーサル アクションは常にアドオンのすべてのカードに配置されます。

ユニバーサル アクションを使用すると、アドオンのどの部分を操作するかにかかわらず、ユーザーが常に特定の機能にアクセスできるようになります。ユニバーサル アクションのユースケースの例を次に示します。

  • 設定ウェブページを開く(または設定カードを表示する)
  • ユーザーにヘルプ情報を表示します。
  • 「新規顧客の追加」などの新しいワークフローを開始します。
  • アドオンについてユーザーがフィードバックを送信できるカードを表示する。

現在のコンテキストに依存しないアクションが存在する場合は、それをユニバーサル アクションにすることを検討してください。

ユニバーサル アクションの使用

ユニバーサル アクションは、アドオンのプロジェクトのマニフェストで構成します。設定したユニバーサル アクションは、アドオンのユーザーが常に利用できます。ユーザーがカードを表示している場合、ユーザーが定義したすべてのユニバーサル アクションのカードは常に、そのカードに定義されたカード アクションの後にカードメニューに表示されます。ユニバーサル アクションは、アドオンのマニフェストで定義されているのと同じ順序でカードメニューに表示されます。

ユニバーサル アクションの構成

ユニバーサル アクションは、アドオンのマニフェストで構成します。詳しくは、マニフェストをご覧ください。

アクションごとに、そのアクションのメニューに表示されるテキストを指定します。次に、アクションのウェブページを新しいタブで直接開くことを示す openLink フィールドを指定できます。また、ユニバーサル アクションが選択されたときに実行する Apps Script コールバック関数を指定する runFunction フィールドを指定することもできます。

runFunction が使用される場合、指定されたコールバック関数は通常、次のいずれかを行います。

  • ビルドされた UniversalActionResponse オブジェクトを返すことで、すぐに表示する UI カードを作成します。
  • ビルドされた UniversalActionResponse オブジェクトを返すことで、他のタスクの実行後に URL を開きます。
  • バックグラウンド タスクを実行します。新しいカードに切り替えたり、URL を開いたりすることはありません。 この場合、コールバック関数は何も返しません。

このコールバック関数が呼び出されると、開いているカードとアドオンのコンテキストに関する情報を含むイベント オブジェクトがコールバック関数に渡されます。

次のコード スニペットは、Gmail の拡張中にユニバーサル アクションを使用するGoogle Workspace アドオンの抜粋したマニフェスト例を示しています。このコードでは、アドオンがメッセージの送信者を判断できるように、メタデータ スコープが明示的に設定されます。

  "oauthScopes": [
    "https://www.googleapis.com/auth/gmail.addons.current.message.metadata"
  ],
  "addOns": {
    "common": {
      "name": "Universal Actions Only Addon",
      "logoUrl": "https://www.example.com/hosted/images/2x/my-icon.png",
      "openLinkUrlPrefixes": [
        "https://www.google.com",
        "https://www.example.com/urlbase"
      ],
      "universalActions": [{
          "label": "Open google.com",
          "openLink": "https://www.google.com"
        }, {
          "label": "Open contact URL",
          "runFunction": "openContactURL"
        }, {
          "label": "Open settings",
          "runFunction": "createSettingsResponse"
        }, {
          "label": "Run background sync",
          "runFunction": "runBackgroundSync"
      }],
      ...
    },
    "gmail": {
      "contextualTriggers": [
        {
          "unconditional": {},
          "onTriggerFunction": "getContextualAddOn"
        }
      ]
    },
    ...
  },
  ...

上記の例で定義されている 3 つのユニバーサル アクションでは、次のような処理が行われます。

  • google.com を新しいタブで開く(https://www.google.com
  • 連絡先 URL を開くは、開く URL を決定する関数を実行し、OpenLink オブジェクトを使用して新しいタブで開きます。このコードにより、送信者のメールアドレスを使用して URL が作成されます。
  • 設定を開くと、アドオン スクリプト プロジェクトで定義された createSettingsCards() 関数が実行されます。この関数は、アドオンの設定やその他の情報を含むカードセットを含む有効な UniversalActionResponse オブジェクトを返します。関数によるこのオブジェクトの作成が完了すると、UI にカードのリストが表示されます(複数のカードを返すをご覧ください)。
  • [バックグラウンド同期を実行] は、アドオン スクリプト プロジェクトで定義された runBackgroundSync() 関数を実行します。この関数はカードをビルドせず、UI を変更しない他のバックグラウンド タスクを実行します。この関数は UniversalActionResponse を返さないため、関数が終了したときに UI で新しいカードは表示されません。代わりに、関数の実行中に UI に読み込みインジケーター スピナーが表示されます。

openContactURL()createSettingsResponse()runBackgroundSync() 関数を作成する例を次に示します。

/**
 * Open a contact URL.
 * @param {Object} e an event object
 * @return {UniversalActionResponse}
 */
function openContactURL(e) {
  // Activate temporary Gmail scopes, in this case so that the
  // open message metadata can be read.
  var accessToken = e.gmail.accessToken;
  GmailApp.setCurrentMessageAccessToken(accessToken);

  // Build URL to open based on a base URL and the sender's email.
  // This URL must be included in the openLinkUrlPrefixes whitelist.
  var messageId = e.gmail.messageId;
  var message = GmailApp.getMessageById(messageId);
  var sender = message.getFrom();
  var url = "https://www.example.com/urlbase/" + sender;
  return CardService.newUniversalActionResponseBuilder()
      .setOpenLink(CardService.newOpenLink()
          .setUrl(url))
      .build();
}

/**
 * Create a collection of cards to control the add-on settings and
 * present other information. These cards are displayed in a list when
 * the user selects the associated "Open settings" universal action.
 *
 * @param {Object} e an event object
 * @return {UniversalActionResponse}
 */
function createSettingsResponse(e) {
  return CardService.newUniversalActionResponseBuilder()
      .displayAddOnCards(
          [createSettingCard(), createAboutCard()])
      .build();
}

/**
 * Create and return a built settings card.
 * @return {Card}
 */
function createSettingCard() {
  return CardService.newCardBuilder()
      .setHeader(CardService.newCardHeader().setTitle('Settings'))
      .addSection(CardService.newCardSection()
          .addWidget(CardService.newSelectionInput()
              .setType(CardService.SelectionInputType.CHECK_BOX)
              .addItem("Ask before deleting contact", "contact", false)
              .addItem("Ask before deleting cache", "cache", false)
              .addItem("Preserve contact ID after deletion", "contactId", false))
          // ... continue adding widgets or other sections here ...
      ).build();   // Don't forget to build the card!
}

/**
 * Create and return a built 'About' informational card.
 * @return {Card}
 */
function createAboutCard() {
  return CardService.newCardBuilder()
      .setHeader(CardService.newCardHeader().setTitle('About'))
      .addSection(CardService.newCardSection()
          .addWidget(CardService.newTextParagraph()
              .setText('This add-on manages contact information. For more '
                  + 'details see the <a href="https://www.example.com/help">'
                  + 'help page</a>.'))
      // ... add other information widgets or sections here ...
      ).build();  // Don't forget to build the card!
}

/**
 * Run background tasks, none of which should alter the UI.
 * Also records the time of sync in the script properties.
 *
 * @param {Object} e an event object
 */
function runBackgroundSync(e) {
  var props = PropertiesService.getUserProperties();
  props.setProperty("syncTime", new Date().toString());

  syncWithContacts();  // Not shown.
  updateCache();       // Not shown.
  validate();          // Not shown.

  // no return value tells the UI to keep showing the current card.
}