クイックスタート: Cats Google Workspace アドオン

 l10n-placeholder13=

このページの残りの部分で説明する手順を完了すると、 Google Workspace アドオンを約 10 分で作成できます。この例のアドオンでは、Google Workspace アドオンのいくつかの機能(ホームページ、コンテキスト トリガー、サードパーティ API への接続など)のデモを行います。

このアドオンは、Gmail、カレンダー、ドライブにコンテキストに基づくサイドバーとコンテキストのないサイドバーを作成します。サイドバーには、絵が描かれた猫の画像がテキストで表示されます。テキストは、静的です(ホームページの場合)。または、ホスト アプリケーションのコンテキスト(コンテキスト トリガーの場合)から取得されます。

このアドオンを作成する手順は以下のとおりです。




ステップ 1: スクリプト プロジェクトを作成する

まず、新しいスクリプト プロジェクトを作成し、アドオンコードを入力します。

新しいエディタ

  1. 新しいスタンドアロン Apps Script プロジェクトを作成します
  2. 左上にある [無題のプロジェクト] をクリックします。
  3. Apps Script プロジェクト Cats の名前を変更し、[Rename] をクリックします。
  4. 左側の &qt;Code.gs&quot の横にあるその他アイコン をクリックします。 > Rename
  5. ファイル名を「Common」に変更し、Enter キーを押します。
  6. 上部の [ファイル] の横にある「ファイルを追加」アイコン [スクリプト] をクリックします。
  7. 新しいファイル名として「Gmail」と入力し、Enter キーを押します。
  8. 上記の手順を繰り返して、Calendar という名前の別のスクリプト ファイルを作成し、もう一度 Drive という名前のスクリプト ファイルを作成します。完了すると、4 つのスクリプト ファイルが作成されます。
  9. これらのファイルの各内容を、それぞれ次のコンテンツに置き換えます。

Common.gs

/**
 * This simple Google Workspace Add-on shows a random image of a cat in the
 * sidebar. When opened manually (the homepage card), some static text is
 * overlayed on the image, but when contextual cards are opened a new cat image
 * is shown with the text taken from that context (such as a message's subject
 * line) overlaying the image. There is also a button that updates the card with
 * a new random cat image.
 *
 * Click "File > Make a copy..." to copy the script, and "Publish > Deploy from
 * manifest > Install add-on" to install it.
 */

/**
 * The maximum number of characters that can fit in the cat image.
 */
var MAX_MESSAGE_LENGTH = 40;

/**
 * Callback for rendering the homepage card.
 * @return {CardService.Card} The card to show to the user.
 */
function onHomepage(e) {
  console.log(e);
  var hour = Number(Utilities.formatDate(new Date(), e.userTimezone.id, 'H'));
  var message;
  if (hour >= 6 && hour < 12) {
    message = 'Good morning';
  } else if (hour >= 12 && hour < 18) {
    message = 'Good afternoon';
  } else {
    message = 'Good night';
  }
  message += ' ' + e.hostApp;
  return createCatCard(message, true);
}

/**
 * Creates a card with an image of a cat, overlayed with the text.
 * @param {String} text The text to overlay on the image.
 * @param {Boolean} isHomepage True if the card created here is a homepage;
 *      false otherwise. Defaults to false.
 * @return {CardService.Card} The assembled card.
 */
function createCatCard(text, isHomepage) {
  // Explicitly set the value of isHomepage as false if null or undefined.
  if (!isHomepage) {
    isHomepage = false;
  }

  // Use the "Cat as a service" API to get the cat image. Add a "time" URL
  // parameter to act as a cache buster.
  var now = new Date();
  // Replace formward slashes in the text, as they break the CataaS API.
  var caption = text.replace(/\//g, ' ');
  var imageUrl =
      Utilities.formatString('https://cataas.com/cat/says/%s?time=%s',
          encodeURIComponent(caption), now.getTime());
  var image = CardService.newImage()
      .setImageUrl(imageUrl)
      .setAltText('Meow')

  // Create a button that changes the cat image when pressed.
  // Note: Action parameter keys and values must be strings.
  var action = CardService.newAction()
      .setFunctionName('onChangeCat')
      .setParameters({text: text, isHomepage: isHomepage.toString()});
  var button = CardService.newTextButton()
      .setText('Change cat')
      .setOnClickAction(action)
      .setTextButtonStyle(CardService.TextButtonStyle.FILLED);
  var buttonSet = CardService.newButtonSet()
      .addButton(button);

  // Create a footer to be shown at the bottom.
  var footer = CardService.newFixedFooter()
      .setPrimaryButton(CardService.newTextButton()
          .setText('Powered by cataas.com')
          .setOpenLink(CardService.newOpenLink()
              .setUrl('https://cataas.com')));

  // Assemble the widgets and return the card.
  var section = CardService.newCardSection()
      .addWidget(image)
      .addWidget(buttonSet);
  var card = CardService.newCardBuilder()
      .addSection(section)
      .setFixedFooter(footer);

  if (!isHomepage) {
    // Create the header shown when the card is minimized,
    // but only when this card is a contextual card. Peek headers
    // are never used by non-contexual cards like homepages.
    var peekHeader = CardService.newCardHeader()
      .setTitle('Contextual Cat')
      .setImageUrl('https://www.gstatic.com/images/icons/material/system/1x/pets_black_48dp.png')
      .setSubtitle(text);
    card.setPeekCardHeader(peekHeader)
  }

  return card.build();
}

/**
 * Callback for the "Change cat" button.
 * @param {Object} e The event object, documented {@link
 *     https://developers.google.com/gmail/add-ons/concepts/actions#action_event_objects
 *     here}.
 * @return {CardService.ActionResponse} The action response to apply.
 */
function onChangeCat(e) {
  console.log(e);
  // Get the text that was shown in the current cat image. This was passed as a
  // parameter on the Action set for the button.
  var text = e.parameters.text;

  // The isHomepage parameter is passed as a string, so convert to a Boolean.
  var isHomepage = e.parameters.isHomepage === 'true';

  // Create a new card with the same text.
  var card = createCatCard(text, isHomepage);

  // Create an action response that instructs the add-on to replace
  // the current card with the new one.
  var navigation = CardService.newNavigation()
      .updateCard(card);
  var actionResponse = CardService.newActionResponseBuilder()
      .setNavigation(navigation);
  return actionResponse.build();
}

/**
 * Truncate a message to fit in the cat image.
 * @param {string} message The message to truncate.
 * @return {string} The truncated message.
 */
function truncate(message) {
  if (message.length > MAX_MESSAGE_LENGTH) {
    message = message.slice(0, MAX_MESSAGE_LENGTH);
    message = message.slice(0, message.lastIndexOf(' ')) + '...';
  }
  return message;
}

Gmail.gs

/**
 * Callback for rendering the card for a specific Gmail message.
 * @param {Object} e The event object.
 * @return {CardService.Card} The card to show to the user.
 */
function onGmailMessage(e) {
  console.log(e);
  // Get the ID of the message the user has open.
  var messageId = e.gmail.messageId;

  // Get an access token scoped to the current message and use it for GmailApp
  // calls.
  var accessToken = e.gmail.accessToken;
  GmailApp.setCurrentMessageAccessToken(accessToken);

  // Get the subject of the email.
  var message = GmailApp.getMessageById(messageId);
  var subject = message.getThread().getFirstMessageSubject();

  // Remove labels and prefixes.
  subject = subject
      .replace(/^([rR][eE]|[fF][wW][dD])\:\s*/, '')
      .replace(/^\[.*?\]\s*/, '');

  // If neccessary, truncate the subject to fit in the image.
  subject = truncate(subject);

  return createCatCard(subject);
}

/**
 * Callback for rendering the card for the compose action dialog.
 * @param {Object} e The event object.
 * @return {CardService.Card} The card to show to the user.
 */
function onGmailCompose(e) {
  console.log(e);
  var header = CardService.newCardHeader()
      .setTitle('Insert cat')
      .setSubtitle('Add a custom cat image to your email message.');
  // Create text input for entering the cat's message.
  var input = CardService.newTextInput()
      .setFieldName('text')
      .setTitle('Caption')
      .setHint('What do you want the cat to say?');
  // Create a button that inserts the cat image when pressed.
  var action = CardService.newAction()
      .setFunctionName('onGmailInsertCat');
  var button = CardService.newTextButton()
      .setText('Insert cat')
      .setOnClickAction(action)
      .setTextButtonStyle(CardService.TextButtonStyle.FILLED);
  var buttonSet = CardService.newButtonSet()
      .addButton(button);
  // Assemble the widgets and return the card.
  var section = CardService.newCardSection()
      .addWidget(input)
      .addWidget(buttonSet);
  var card = CardService.newCardBuilder()
      .setHeader(header)
      .addSection(section);
  return card.build();
}

/**
 * Callback for inserting a cat into the Gmail draft.
 * @param {Object} e The event object.
 * @return {CardService.UpdateDraftActionResponse} The draft update response.
 */
function onGmailInsertCat(e) {
  console.log(e);
  // Get the text that was entered by the user.
  var text = e.formInput.text;
  // Use the "Cat as a service" API to get the cat image. Add a "time" URL
  // parameter to act as a cache buster.
  var now = new Date();
  var imageUrl = 'https://cataas.com/cat';
  if (text) {
    // Replace formward slashes in the text, as they break the CataaS API.
    var caption = text.replace(/\//g, ' ');
    imageUrl += Utilities.formatString('/says/%s?time=%s',
        encodeURIComponent(caption), now.getTime());
  }
  var imageHtmlContent = '<img style="display: block; max-height: 300px;" src="'
      + imageUrl + '"/>';
  var response = CardService.newUpdateDraftActionResponseBuilder()
      .setUpdateDraftBodyAction(CardService.newUpdateDraftBodyAction()
          .addUpdateContent(imageHtmlContent,CardService.ContentType.MUTABLE_HTML)
          .setUpdateType(CardService.UpdateDraftBodyType.IN_PLACE_INSERT))
      .build();
  return response;
}

Calendar.gs

/**
 * Callback for rendering the card for a specific Calendar event.
 * @param {Object} e The event object.
 * @return {CardService.Card} The card to show to the user.
 */
function onCalendarEventOpen(e) {
  console.log(e);
  var calendar = CalendarApp.getCalendarById(e.calendar.calendarId);
  // The event metadata doesn't include the event's title, so using the
  // calendar.readonly scope and fetching the event by it's ID.
  var event = calendar.getEventById(e.calendar.id);
  if (!event) {
    // This is a new event still being created.
    return createCatCard('A new event! Am I invited?');
  }
  var title = event.getTitle();
  // If neccessary, truncate the title to fit in the image.
  title = truncate(title);
  return createCatCard(title);
}

Drive.gs

/**
 * Callback for rendering the card for specific Drive items.
 * @param {Object} e The event object.
 * @return {CardService.Card} The card to show to the user.
 */
function onDriveItemsSelected(e) {
  console.log(e);
  var items = e.drive.selectedItems;
  // Include at most 5 items in the text.
  items = items.slice(0, 5);
  var text = items.map(function(item) {
    var title = item.title;
    // If neccessary, truncate the title to fit in the image.
    title = truncate(title);
    return title;
  }).join('\n');
  return createCatCard(text);
}

  1. 上部の [プロジェクトを保存] をクリックします。

以前のエディタ

  1. 新しいスタンドアロン Apps Script プロジェクトを作成します
  2. 左側のナビゲーションで、Code.gs エントリの横にある アイコンをクリックし、[Rename] を選択します。
  3. 次のダイアログで、スクリプト プロジェクト名を Cats に変更し、[OK] をクリックします。
  4. スクリプト プロジェクトの名前の変更が完了すると、[Rename File] ダイアログが開きます。Code ファイルの名前を Common に変更し、[OK] をクリックします。
  5. [ファイル > 新しい > スクリプト ファイル] をクリックします。新しいファイル名として Gmail を入力し、[OK] をクリックします。これにより、Gmail.gs という名前のスクリプト プロジェクトに 2 つ目のコードファイルが作成されます。左側のナビゲーションの [Common.gs] で確認できます。
  6. 上記の手順を繰り返して、Calendar という名前の別のスクリプト ファイルを作成し、もう一度 Drive という名前のファイルを作成します。完了すると、左側のナビゲーションに 4 つのスクリプト ファイルが表示されます。
  7. これらのファイルの各内容を、それぞれ次のコンテンツに置き換えます。

Common.gs

/**
 * This simple Google Workspace Add-on shows a random image of a cat in the
 * sidebar. When opened manually (the homepage card), some static text is
 * overlayed on the image, but when contextual cards are opened a new cat image
 * is shown with the text taken from that context (such as a message's subject
 * line) overlaying the image. There is also a button that updates the card with
 * a new random cat image.
 *
 * Click "File > Make a copy..." to copy the script, and "Publish > Deploy from
 * manifest > Install add-on" to install it.
 */

/**
 * The maximum number of characters that can fit in the cat image.
 */
var MAX_MESSAGE_LENGTH = 40;

/**
 * Callback for rendering the homepage card.
 * @return {CardService.Card} The card to show to the user.
 */
function onHomepage(e) {
  console.log(e);
  var hour = Number(Utilities.formatDate(new Date(), e.userTimezone.id, 'H'));
  var message;
  if (hour >= 6 && hour < 12) {
    message = 'Good morning';
  } else if (hour >= 12 && hour < 18) {
    message = 'Good afternoon';
  } else {
    message = 'Good night';
  }
  message += ' ' + e.hostApp;
  return createCatCard(message, true);
}

/**
 * Creates a card with an image of a cat, overlayed with the text.
 * @param {String} text The text to overlay on the image.
 * @param {Boolean} isHomepage True if the card created here is a homepage;
 *      false otherwise. Defaults to false.
 * @return {CardService.Card} The assembled card.
 */
function createCatCard(text, isHomepage) {
  // Explicitly set the value of isHomepage as false if null or undefined.
  if (!isHomepage) {
    isHomepage = false;
  }

  // Use the "Cat as a service" API to get the cat image. Add a "time" URL
  // parameter to act as a cache buster.
  var now = new Date();
  // Replace formward slashes in the text, as they break the CataaS API.
  var caption = text.replace(/\//g, ' ');
  var imageUrl =
      Utilities.formatString('https://cataas.com/cat/says/%s?time=%s',
          encodeURIComponent(caption), now.getTime());
  var image = CardService.newImage()
      .setImageUrl(imageUrl)
      .setAltText('Meow')

  // Create a button that changes the cat image when pressed.
  // Note: Action parameter keys and values must be strings.
  var action = CardService.newAction()
      .setFunctionName('onChangeCat')
      .setParameters({text: text, isHomepage: isHomepage.toString()});
  var button = CardService.newTextButton()
      .setText('Change cat')
      .setOnClickAction(action)
      .setTextButtonStyle(CardService.TextButtonStyle.FILLED);
  var buttonSet = CardService.newButtonSet()
      .addButton(button);

  // Create a footer to be shown at the bottom.
  var footer = CardService.newFixedFooter()
      .setPrimaryButton(CardService.newTextButton()
          .setText('Powered by cataas.com')
          .setOpenLink(CardService.newOpenLink()
              .setUrl('https://cataas.com')));

  // Assemble the widgets and return the card.
  var section = CardService.newCardSection()
      .addWidget(image)
      .addWidget(buttonSet);
  var card = CardService.newCardBuilder()
      .addSection(section)
      .setFixedFooter(footer);

  if (!isHomepage) {
    // Create the header shown when the card is minimized,
    // but only when this card is a contextual card. Peek headers
    // are never used by non-contexual cards like homepages.
    var peekHeader = CardService.newCardHeader()
      .setTitle('Contextual Cat')
      .setImageUrl('https://www.gstatic.com/images/icons/material/system/1x/pets_black_48dp.png')
      .setSubtitle(text);
    card.setPeekCardHeader(peekHeader)
  }

  return card.build();
}

/**
 * Callback for the "Change cat" button.
 * @param {Object} e The event object, documented {@link
 *     https://developers.google.com/gmail/add-ons/concepts/actions#action_event_objects
 *     here}.
 * @return {CardService.ActionResponse} The action response to apply.
 */
function onChangeCat(e) {
  console.log(e);
  // Get the text that was shown in the current cat image. This was passed as a
  // parameter on the Action set for the button.
  var text = e.parameters.text;

  // The isHomepage parameter is passed as a string, so convert to a Boolean.
  var isHomepage = e.parameters.isHomepage === 'true';

  // Create a new card with the same text.
  var card = createCatCard(text, isHomepage);

  // Create an action response that instructs the add-on to replace
  // the current card with the new one.
  var navigation = CardService.newNavigation()
      .updateCard(card);
  var actionResponse = CardService.newActionResponseBuilder()
      .setNavigation(navigation);
  return actionResponse.build();
}

/**
 * Truncate a message to fit in the cat image.
 * @param {string} message The message to truncate.
 * @return {string} The truncated message.
 */
function truncate(message) {
  if (message.length > MAX_MESSAGE_LENGTH) {
    message = message.slice(0, MAX_MESSAGE_LENGTH);
    message = message.slice(0, message.lastIndexOf(' ')) + '...';
  }
  return message;
}

Gmail.gs

/**
 * Callback for rendering the card for a specific Gmail message.
 * @param {Object} e The event object.
 * @return {CardService.Card} The card to show to the user.
 */
function onGmailMessage(e) {
  console.log(e);
  // Get the ID of the message the user has open.
  var messageId = e.gmail.messageId;

  // Get an access token scoped to the current message and use it for GmailApp
  // calls.
  var accessToken = e.gmail.accessToken;
  GmailApp.setCurrentMessageAccessToken(accessToken);

  // Get the subject of the email.
  var message = GmailApp.getMessageById(messageId);
  var subject = message.getThread().getFirstMessageSubject();

  // Remove labels and prefixes.
  subject = subject
      .replace(/^([rR][eE]|[fF][wW][dD])\:\s*/, '')
      .replace(/^\[.*?\]\s*/, '');

  // If neccessary, truncate the subject to fit in the image.
  subject = truncate(subject);

  return createCatCard(subject);
}

/**
 * Callback for rendering the card for the compose action dialog.
 * @param {Object} e The event object.
 * @return {CardService.Card} The card to show to the user.
 */
function onGmailCompose(e) {
  console.log(e);
  var header = CardService.newCardHeader()
      .setTitle('Insert cat')
      .setSubtitle('Add a custom cat image to your email message.');
  // Create text input for entering the cat's message.
  var input = CardService.newTextInput()
      .setFieldName('text')
      .setTitle('Caption')
      .setHint('What do you want the cat to say?');
  // Create a button that inserts the cat image when pressed.
  var action = CardService.newAction()
      .setFunctionName('onGmailInsertCat');
  var button = CardService.newTextButton()
      .setText('Insert cat')
      .setOnClickAction(action)
      .setTextButtonStyle(CardService.TextButtonStyle.FILLED);
  var buttonSet = CardService.newButtonSet()
      .addButton(button);
  // Assemble the widgets and return the card.
  var section = CardService.newCardSection()
      .addWidget(input)
      .addWidget(buttonSet);
  var card = CardService.newCardBuilder()
      .setHeader(header)
      .addSection(section);
  return card.build();
}

/**
 * Callback for inserting a cat into the Gmail draft.
 * @param {Object} e The event object.
 * @return {CardService.UpdateDraftActionResponse} The draft update response.
 */
function onGmailInsertCat(e) {
  console.log(e);
  // Get the text that was entered by the user.
  var text = e.formInput.text;
  // Use the "Cat as a service" API to get the cat image. Add a "time" URL
  // parameter to act as a cache buster.
  var now = new Date();
  var imageUrl = 'https://cataas.com/cat';
  if (text) {
    // Replace formward slashes in the text, as they break the CataaS API.
    var caption = text.replace(/\//g, ' ');
    imageUrl += Utilities.formatString('/says/%s?time=%s',
        encodeURIComponent(caption), now.getTime());
  }
  var imageHtmlContent = '<img style="display: block; max-height: 300px;" src="'
      + imageUrl + '"/>';
  var response = CardService.newUpdateDraftActionResponseBuilder()
      .setUpdateDraftBodyAction(CardService.newUpdateDraftBodyAction()
          .addUpdateContent(imageHtmlContent,CardService.ContentType.MUTABLE_HTML)
          .setUpdateType(CardService.UpdateDraftBodyType.IN_PLACE_INSERT))
      .build();
  return response;
}

Calendar.gs

/**
 * Callback for rendering the card for a specific Calendar event.
 * @param {Object} e The event object.
 * @return {CardService.Card} The card to show to the user.
 */
function onCalendarEventOpen(e) {
  console.log(e);
  var calendar = CalendarApp.getCalendarById(e.calendar.calendarId);
  // The event metadata doesn't include the event's title, so using the
  // calendar.readonly scope and fetching the event by it's ID.
  var event = calendar.getEventById(e.calendar.id);
  if (!event) {
    // This is a new event still being created.
    return createCatCard('A new event! Am I invited?');
  }
  var title = event.getTitle();
  // If neccessary, truncate the title to fit in the image.
  title = truncate(title);
  return createCatCard(title);
}

Drive.gs

/**
 * Callback for rendering the card for specific Drive items.
 * @param {Object} e The event object.
 * @return {CardService.Card} The card to show to the user.
 */
function onDriveItemsSelected(e) {
  console.log(e);
  var items = e.drive.selectedItems;
  // Include at most 5 items in the text.
  items = items.slice(0, 5);
  var text = items.map(function(item) {
    var title = item.title;
    // If neccessary, truncate the title to fit in the image.
    title = truncate(title);
    return title;
  }).join('\n');
  return createCatCard(text);
}

  1. [File] > [Save] をクリックし、[OK] をクリックしてプロジェクトの変更を保存します。

アドオン コードを 4 つのスクリプト ファイルに分割し、アドオンの機能に基づいて論理組織部門を作成しました。これは、長期的なアドオンのメンテナンスに役立ちます。

ステップ 2: スクリプト マニフェストを更新する

次に、マニフェスト ファイルを更新してアドオンを構成します。この手順では、アドオンのホームページとコンテキスト トリガーを構成し、アドオンの名前やスコープなどの情報を設定します。

新しいエディタ

  1. 左側にある [プロジェクト設定] をクリックします。
  2. [マニフェストでファイルを表示する] チェックボックスを選択します。
  3. マニフェストの内容を削除して、次のように置き換えます。

    {
      "timeZone": "America/New_York",
      "dependencies": {
      },
      "exceptionLogging": "STACKDRIVER",
      "oauthScopes": [
        "https://www.googleapis.com/auth/calendar.addons.execute",
        "https://www.googleapis.com/auth/calendar.readonly",
        "https://www.googleapis.com/auth/drive.addons.metadata.readonly",
        "https://www.googleapis.com/auth/gmail.addons.current.action.compose",
        "https://www.googleapis.com/auth/gmail.addons.current.message.readonly",
        "https://www.googleapis.com/auth/gmail.addons.execute",
        "https://www.googleapis.com/auth/script.locale"],
      "runtimeVersion": "V8",
      "addOns": {
        "common": {
          "name": "Cats",
          "logoUrl": "https://www.gstatic.com/images/icons/material/system/1x/pets_black_48dp.png",
          "useLocaleFromApp": true,
          "homepageTrigger": {
            "runFunction": "onHomepage",
            "enabled": true
          },
          "universalActions": [{
            "label": "Learn more about Cataas",
            "openLink": "https://cataas.com"
          }]
        },
        "gmail": {
          "contextualTriggers": [{
            "unconditional": {
            },
            "onTriggerFunction": "onGmailMessage"
          }],
          "composeTrigger": {
            "selectActions": [{
              "text": "Insert cat",
              "runFunction": "onGmailCompose"
            }],
            "draftAccess": "NONE"
          }
        },
        "drive": {
          "onItemsSelectedTrigger": {
            "runFunction": "onDriveItemsSelected"
          }
        },
        "calendar": {
          "eventOpenTrigger": {
            "runFunction": "onCalendarEventOpen"
          }
        }
      }
    }
    
    
  4. 上部の [プロジェクトを保存] をクリックします。

以前のエディタ

  1. スクリプト エディタで、[View > Show manifest file] メニュー項目を選択します。 マニフェスト ファイル(appsscript.json)がエディタで開きます。
  2. マニフェストの内容を削除して、次のように置き換えます。

    {
      "timeZone": "America/New_York",
      "dependencies": {
      },
      "exceptionLogging": "STACKDRIVER",
      "oauthScopes": [
        "https://www.googleapis.com/auth/calendar.addons.execute",
        "https://www.googleapis.com/auth/calendar.readonly",
        "https://www.googleapis.com/auth/drive.addons.metadata.readonly",
        "https://www.googleapis.com/auth/gmail.addons.current.action.compose",
        "https://www.googleapis.com/auth/gmail.addons.current.message.readonly",
        "https://www.googleapis.com/auth/gmail.addons.execute",
        "https://www.googleapis.com/auth/script.locale"],
      "runtimeVersion": "V8",
      "addOns": {
        "common": {
          "name": "Cats",
          "logoUrl": "https://www.gstatic.com/images/icons/material/system/1x/pets_black_48dp.png",
          "useLocaleFromApp": true,
          "homepageTrigger": {
            "runFunction": "onHomepage",
            "enabled": true
          },
          "universalActions": [{
            "label": "Learn more about Cataas",
            "openLink": "https://cataas.com"
          }]
        },
        "gmail": {
          "contextualTriggers": [{
            "unconditional": {
            },
            "onTriggerFunction": "onGmailMessage"
          }],
          "composeTrigger": {
            "selectActions": [{
              "text": "Insert cat",
              "runFunction": "onGmailCompose"
            }],
            "draftAccess": "NONE"
          }
        },
        "drive": {
          "onItemsSelectedTrigger": {
            "runFunction": "onDriveItemsSelected"
          }
        },
        "calendar": {
          "eventOpenTrigger": {
            "runFunction": "onCalendarEventOpen"
          }
        }
      }
    }
    
    
  3. [File > Save] を選択して、これらの変更をマニフェストに保存します。

手順 3: 非公開アドオンをインストールする

これで、アドオンをテストできるようになりました。次の手順でテスト用にインストールします。

新しいエディタ

  1. 右上の [Deploy > Test Deployment] をクリックします。
  2. [Test Deployment] ダイアログで、[Install > Done] をクリックします。

以前のエディタ

  1. [Publish > Deploy from manifest...] を選択して、[Deployments] ダイアログを開きます。
  2. [最新バージョン(Head)] 行で、[アドオンをインストール] をクリックして、現在保存されているバージョンのアドオンを開発モードでインストールします。アドオンの最新バージョン(Head)をインストールすると、そのアドオンのコードに加えた変更はすべてすぐに適用されるため、再インストールする必要はありません。
  3. [閉じる] をクリックします。

ステップ 4: 試してみる

これで、アドオンを使用できるようになります。

  1. Gmail を開くか、Gmail タブを開いている場合は更新します。Gmail の受信トレイの右側のパネルに、Cats アドオン が表示されます。
  2. アドオンを開くには、右側のパネルで Cats アイコン をクリックします。
  3. 承認されていないことがアドオンで通知された場合は、[アクセスを承認] をクリックし、画面の指示に従います。
  4. 承認されると、アドオンは再読み込みされ、使用できるようになります。

このアドオンは猫の画像とテキストを表示します。画像を変更するには、[猫を変更] をクリックします。ページを更新して、猫の画像を提供するサードパーティ API Cataas の詳細を確認するには、その他の操作アイコン をクリックします。

アドオンを開いた状態で Gmail のメッセージを開くと、画像が更新され、メッセージの件名がテキストに変わります(長すぎる場合は切り捨てられます)。Gmail の受信トレイに戻ると、アドオンのホームページに戻ります。

カレンダーとドライブでも、ホームページとコンテキスト コンテンツのどちらに関しても同様の操作を確認できます。これらのホストでアドオンを使用するために、アドオンを再承認する必要はありません。

公開

これはアドオンの一例であるため、このチュートリアルはここで終了します。実際のアドオンを開発している場合、最後の手順では、他のユーザーがそのアドオンを見つけてインストールできるように公開します。

詳細

Apps Script でGoogle Workspace を拡張する方法の詳細については、次のリソースをご覧ください。