ユニバーサル アクションは、ユーザーが選択したときに新しいウェブページを開いたり、新しい 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 つのユニバーサル アクションは、次の処理を行います。
- Open google.com は、新しいタブで https://www.google.com を開きます。
- Open contact URL は、開く URL を決定する関数を実行し、
OpenLinkオブジェクトを使用して新しいタブで開きます。このコードは、送信者のメールアドレスを使用して URL を作成します。 - [Open settings] は、アドオン スクリプト プロジェクトで定義されている
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.
}