Extending the compose UI with compose actions Stay organized with collections Save and categorize content based on your preferences.
Page Summary
Google Workspace add-ons can automate composing emails in Gmail by providing a UI when creating new messages or replies.
Add-ons use a compose trigger function defined in the manifest to build this UI, which is displayed when composing a draft.
Building a compose add-on involves adding a manifest field, implementing a compose trigger function, and creating callback functions for UI interactions.
The compose UI uses the Apps Script Card service to construct cards and widgets, similar to the message UI.
Add-ons can insert content into drafts using the Card service's extended classes for updating draft subject, body, and recipients.
In addition to providing a card-based interface when a user is reading a Gmailmessage, Google Workspace add-ons that extend Gmailcan provide another interface when the user is composing new messages orreplying to existing ones. This allows Google Workspace add-ons to automate the task of composing emails for the user.
Accessing the add-on compose UI
There are two ways to view an add-on's compose UI. The first way is to startcomposing a new draft or reply while the add-on is already open. The secondway is to start the add-on while composing a draft.
Either case causes the add-on to execute the correspondingcompose trigger function, defined in the add-onmanifest.The compose trigger function builds the compose UI for that composeaction, which Gmail then displays to the user.
Building a compose add-on
You can add compose functionality to an add-on by following these general steps:
- Add the
gmail.composeTriggerfield to the add-on script projectmanifestand update the manifestscopes to includethose required for compose actions. - Implement a compose trigger function that builds a compose UI when thetrigger fires. Compose trigger functions return either a single
Cardobject or an array ofCardobjects that comprisethe compose UI for the compose action. - Implement associated callback functions needed to react to the user'scompose UI interactions. These functions are not the compose action itself(which only causes the compose UI to appear); rather, these are theindividual functions that govern what happens when different elements of thecompose UI are selected. For example, a UI card containing a buttonusually has an associated callback function that executes when a user clicksthat button. The callback function for widgets that update the draft messagecontent should return a
UpdateDraftActionResponseobject.
Compose trigger function
An add-on's compose UI is built the same way as the add-on's messageUI—using the Apps ScriptCard service to constructcards and fill them withwidgets.
You must implement thegmail.composeTrigger.selectActions[].runFunctionthat you define in your manifest. The compose trigger function must returneither a singleCard object oran array ofCard objectsthat comprise the compose UI for that action. These functions are very similartocontextual trigger functionsand should build cards in the same way.
Compose trigger event objects
When a compose action is selected, it executes the corresponding compose triggerfunction and passes the function anevent objectas a parameter. The event object can carry information about the add-on contextand the draft being composed to the trigger function.
SeeEvent object structurefor details on how information is arranged in the event object. The informationcontained in the event object is partially controlled by the value of thegmail.composeTrigger.draftAccessmanifest field:
If the
gmail.composeTrigger.draftAccessmanifest field isNONEor isn't included, the event object has onlyminimal information.If
gmail.composeTrigger.draftAccessis set toMETADATA, the event object passed to the compose trigger functionis populated with lists of recipients of the email being composed.
METADATA draft access requires that the add-on manifest includethehttps://www.googleapis.com/auth/gmail.addons.current.message.metadataGmail scope.Inserting content into active drafts
Typically a Google Workspace add-on compose UI providesthe user options and control that help compose a message. For these use cases,once the user has made selections in the UI the add-on interprets the selectionsand updates the current working email draft accordingly.
To make it easier to update the current draft email, theCard servicehas been extended with the following classes:
ContentType—Anenum that defines whether to add mutable HTML, immutable HTML (which Gmailusers can't edit), or plain text content.UpdateDraftActionResponse—Representsa response to an action that updates the current draft email.UpdateDraftActionResponseBuilder—Abuilder forUpdateDraftActionResponseobjects.UpdateDraftBodyAction—Representsan action that updates the body of the current draft email.UpdateDraftBodyType—Anenum that defines how the body is changed.UpdateDraftSubjectAction—Representsan action that updates the subject field of the current draft email.UpdateDraftToRecipientsAction—Representsan action that updates the To recipients of the current draft email.UpdateDraftCcRecipientsAction—Representsan action that updates the Cc recipients of the current draft email.UpdateDraftBccRecipientsAction—Representsan action that updates the Bcc recipients of the current draft email.
Typically an add-on compose UI includes a 'Save' or 'Insert' widget that a usercan click to indicate they are done making selections in the UI and want theirchoices to be added to the email they are composing. To add thisinteractivity, the widget should havean associatedAction object thatinstructs the add-on to run a specific callback function when the widget isclicked. You must implement these callback functions. Each callback function shouldreturn a builtUpdateDraftActionResponseobject that details the changes to make to the current draft email.
Example 1
The following code snippet shows how to build a compose UI that updates the subject, and To, Cc, Bcc recipients of the current email draft.
/***ComposetriggerfunctionthatfireswhenthecomposeUIis*requested.BuildsandreturnsacomposeUIforinsertingimages.**@param{event}eThecomposetriggereventobject.Notusedin*thisexample.*@return{Card[]}*/functiongetComposeUI(e){return[buildComposeCard()];}/***Buildacardtodisplayinteractivebuttonstoallowtheuserto*updatethesubject,andTo,Cc,Bccrecipients.**@return{Card}*/functionbuildComposeCard(){varcard=CardService.newCardBuilder();varcardSection=CardService.newCardSection().setHeader('Update email');cardSection.addWidget(CardService.newTextButton().setText('Update subject').setOnClickAction(CardService.newAction().setFunctionName('applyUpdateSubjectAction')));cardSection.addWidget(CardService.newTextButton().setText('Update To recipients').setOnClickAction(CardService.newAction().setFunctionName('updateToRecipients')));cardSection.addWidget(CardService.newTextButton().setText('Update Cc recipients').setOnClickAction(CardService.newAction().setFunctionName('updateCcRecipients')));cardSection.addWidget(CardService.newTextButton().setText('Update Bcc recipients').setOnClickAction(CardService.newAction().setFunctionName('updateBccRecipients')));returncard.addSection(cardSection).build();}/***Updatesthesubjectfieldofthecurrentemailwhentheuserclicks*on"Update subject"inthecomposeUI.**Note:ThisisnotthecomposeactionthatbuildsacomposeUI,but*ratheranactiontakenwhentheuserinteractswiththecomposeUI.**@return{UpdateDraftActionResponse}*/functionapplyUpdateSubjectAction(){//Getthenewsubjectfieldoftheemail.//Thisfunctionisnotshowninthisexample.varsubject=getSubject();varresponse=CardService.newUpdateDraftActionResponseBuilder().setUpdateDraftSubjectAction(CardService.newUpdateDraftSubjectAction().addUpdateSubject(subject)).build();returnresponse;}/***UpdatestheTorecipientsofthecurrentemailwhentheuserclicks*on"Update To recipients"inthecomposeUI.**Note:ThisisnotthecomposeactionthatbuildsacomposeUI,but*ratheranactiontakenwhentheuserinteractswiththecomposeUI.**@return{UpdateDraftActionResponse}*/functionapplyUpdateToRecipientsAction(){//GetthenewTorecipientsoftheemail.//Thisfunctionisnotshowninthisexample.vartoRecipients=getToRecipients();varresponse=CardService.newUpdateDraftActionResponseBuilder().setUpdateDraftToRecipientsAction(CardService.newUpdateDraftToRecipientsAction().addUpdateToRecipients(toRecipients)).build();returnresponse;}/***UpdatestheCcrecipientsofthecurrentemailwhentheuserclicks*on"Update Cc recipients"inthecomposeUI.**Note:ThisisnotthecomposeactionthatbuildsacomposeUI,but*ratheranactiontakenwhentheuserinteractswiththecomposeUI.**@return{UpdateDraftActionResponse}*/functionapplyUpdateCcRecipientsAction(){//GetthenewCcrecipientsoftheemail.//Thisfunctionisnotshowninthisexample.varccRecipients=getCcRecipients();varresponse=CardService.newUpdateDraftActionResponseBuilder().setUpdateDraftCcRecipientsAction(CardService.newUpdateDraftCcRecipientsAction().addUpdateToRecipients(ccRecipients)).build();returnresponse;}/***UpdatestheBccrecipientsofthecurrentemailwhentheuserclicks*on"Update Bcc recipients"inthecomposeUI.**Note:ThisisnotthecomposeactionthatbuildsacomposeUI,but*ratheranactiontakenwhentheuserinteractswiththecomposeUI.**@return{UpdateDraftActionResponse}*/functionapplyUpdateBccRecipientsAction(){//GetthenewBccrecipientsoftheemail.//Thisfunctionisnotshowninthisexample.varbccRecipients=getBccRecipients();varresponse=CardService.newUpdateDraftActionResponseBuilder().setUpdateDraftBccRecipientsAction(CardService.newUpdateDraftBccRecipientsAction().addUpdateToRecipients(bccRecipients)).build();returnresponse;}Example 2
The following code snippet shows how to build a compose UI that inserts imagesinto the current draft email.
/** * Compose trigger function that fires when the compose UI is * requested. Builds and returns a compose UI for inserting images. * * @param {event} e The compose trigger event object. Not used in * this example. * @return {Card[]} */functiongetInsertImageComposeUI(e){return[buildImageComposeCard()];}/** * Build a card to display images from a third-party source. * * @return {Card} */functionbuildImageComposeCard(){//GetashortlistofimageURLstodisplayintheUI.//Thisfunctionisnotshowninthisexample.varimageUrls=getImageUrls();varcard=CardService.newCardBuilder();varcardSection=CardService.newCardSection().setHeader('My Images');for(vari=0;i <imageUrls.length;i++){varimageUrl=imageUrls[i];cardSection.addWidget(CardService.newImage().setImageUrl(imageUrl).setOnClickAction(CardService.newAction().setFunctionName('applyInsertImageAction').setParameters({'url':imageUrl})));}returncard.addSection(cardSection).build();}/** * Adds an image to the current draft email when the image is clicked * in the compose UI. The image is inserted at the current cursor * location. If any content of the email draft is currently selected, * it is deleted and replaced with the image. * * Note: This is not the compose action that builds a compose UI, but * rather an action taken when the user interacts with the compose UI. * * @param {event} e The incoming event object. * @return {UpdateDraftActionResponse} */functionapplyInsertImageAction(e){varimageUrl=e.parameters.url;varimageHtmlContent='<img style=\"display: block\" src=\"'+imageUrl+'\"/>';varresponse=CardService.newUpdateDraftActionResponseBuilder().setUpdateDraftBodyAction(CardService.newUpdateDraftBodyAction().addUpdateContent(imageHtmlContent,CardService.ContentType.MUTABLE_HTML).setUpdateType(CardService.UpdateDraftBodyType.IN_PLACE_INSERT)).build();returnresponse;}Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.
Last updated 2025-12-11 UTC.