How to build a Google Chat App with Apps Script

Chanel Greco
Google Cloud - Community
10 min readFeb 8, 2024

✅ Block out calendar for the day
✅ Cancel all meetings
✅ Set an out of office auto reply

Do you find yourself having to perform the above mentioned tasks when you take a day off from work?

In this blog post you will learn how you can build a Google Chat app that takes care of those tasks for you. Once you have created and installed the Chat app, you’ll only have to invoke the slash commands and the associated task will be completed for you.

To follow along with this post you will need a Google Workspace account or a Google account and access to the Google Cloud Console.

The creation process can be broken down in nine separate steps. For every step of the Chat app creation you can find a subheading in this post.

Creation process of a Google Chat app with Apps Script

Want to follow along as I build this Chat app? Then check out the video for this tutorial.

1. Create the script & update script manifest

Since we are creating our Chat app with Apps Script we are going to create a new standalone script. The easiest way to do so is to type script.new in your browser’s address bar. Replace the default code in Code.gs with the code in Code.gs, which is hosted on GitHub, and save the file.

To make it easier to find this Apps Script project in the future, I suggest you rename it. You do so by clicking the default name “Untitled project” and naming the project something like “OOO Chat app”.

Rename your project in the IDE

Let’s have a look at the code you just copied to understand how the Chat app logic works. We won’t be following the flow of the code but instead will be grouping connected functions to get a better picture of what the script is doing.

The onAddToSpace function handles the event where a Chat app is either added to a 1-on-1 conversation with the user or to a Chat space.

function onAddToSpace(event) {
let message = 'Thank you for adding me to ';
if (event.space.type === 'DM') {
message += 'a DM, ' + event.user.displayName + '!';
} else {
message += event.space.displayName;
}
return { text: message };
}

The function onRemoveFromSpace takes care of the event where a user removes the Chat app from a Chat space.

  function onRemoveFromSpace(event) {
console.log('App removed from ', event.space.name);
}

The onMessage function is where we handle the user messaging the app. As you can see, we are using a switch statement to handle slash commands. We will add these four slash commands to our app configuration in GCP later in this tutorial.

function onMessage(event) {
const message = event.message;

if (message.slashCommand) {
switch (message.slashCommand.commandId) {
case 1: // Help command
return createHelpCard();
case 2: // Block out day command
return blockDayOut();
case 3: // Cancel all meetings command
return cancelAllMeetings();
case 4: // Set auto reply command
return setAutoReply();
}
}
}

All of the functions so far make use of the event object that gets passed in as a parameter. This object contains contextual information that we can use to do things like identify the Chat app user, know which slash command was invoked, and so on.

When the user invokes the help slash command, our app will display a card with some information about how to use the Chat app. To achieve this we add the createHelpCard function to our script which returns the JSON representation of our card message.

function createHelpCard() {
return {
"cardsV2": [
{
"cardId": "2",
"card": {
"sections": [
{
"header": "",
"widgets": [
{
"decoratedText": {
"topLabel": "",
"text": "Hi! 👋 I'm here to help you with your out of office tasks.<br><br>Here's a list of commands I understand.",
"wrapText": true
}
}
]
},
{
"widgets": [
{
"decoratedText": {
"topLabel": "",
"text": "<b>/blockDayOut</b>: I will block out your calendar for you.",
"wrapText": true
}
},
{
"decoratedText": {
"topLabel": "",
"text": "<b>/cancelAllMeetings</b>: I will cancel all your meetings for the day.",
"wrapText": true
}
},
{
"decoratedText": {
"topLabel": "",
"text": "<b>/setAutoReply</b>: Set an out of office auto reply in Gmail.",
"wrapText": true
}
}
]
}
],
"header": {
"title": "OOO app",
"subtitle": "Helping you manage your OOO",
"imageUrl": "https://goo.gle/3SfMkjb",
"imageType": "SQUARE"
}
}
}
]
}
}

To handle the slash command blockDayOut we add the corresponding function to our script. This function calls the blockOutCalendar function which creates an out of office event in the Chat app user’s Google Calendar.

function blockDayOut() {
blockOutCalendar();
return createResponseCard('Your calendar has been blocked out for you.')
}


function blockOutCalendar() {
function getDateAndHours(hour, minutes) {
const date = new Date();
date.setHours(hour);
date.setMinutes(minutes);
date.setSeconds(0);
date.setMilliseconds(0);
return date.toISOString();
}

const event = {
start: {dateTime: getDateAndHours(9,00)},
end: {dateTime: getDateAndHours(17,00)},
eventType: 'outOfOffice',
summary: 'Out of office',
outOfOfficeProperties: {
autoDeclineMode: 'declineOnlyNewConflictingInvitations',
declineMessage: 'Declined because I am taking a day of.',
}
}
Calendar.Events.insert(event, 'primary');
}

The blockDayOut function finally returns the createResponseCard function. This function contains the JSON representation of the card message used to inform the Chat app user about the completion of the task they requested. To not have to create three separate card messages for each of our three tasks, we simply pass in the text as a parameter when we call the createResponseCard function.

function createResponseCard(responseText) {
return {
"cardsV2": [
{
"cardId": "1",
"card": {
"sections": [
{
"widgets": [
{
"decoratedText": {
"topLabel": "",
"text": responseText,
"startIcon": {
"knownIcon": "NONE",
"altText": "Task done",
"iconUrl": "https://fonts.gstatic.com/s/i/short-term/web/system/1x/task_alt_gm_grey_48dp.png"
},
"wrapText": true
}
}
]
}
],
"header": {
"title": "OOO app",
"subtitle": "Helping you manage your OOO",
"imageUrl": "https://goo.gle/3SfMkjb",
"imageType": "CIRCLE"
}
}
}
]
}
}

To handle the slash command cancelAllMeetings we add the function of that same name to our script which calls the cancelMeetings function. This function gets all of the day’s meetings the Chat app user has, and then sets the status to “NO”.

 function cancelAllMeetings() {
cancelMeetings();
return createResponseCard('All your meetings have been canceled.')
}


function cancelMeetings() {
const events = CalendarApp.getEventsForDay(new Date());

events.forEach(function(event) {
if (event.getGuestList().length > 0) {
event.setMyStatus(CalendarApp.GuestStatus.NO);
}
});
}

To handle the fourth and final slash command, we add the setAutoReply function which calls the turnOnAutoResponder function. This function turns on the out of office responder in the Chat app user’s Gmail.

  function setAutoReply() {
turnOnAutoResponder();
return createResponseCard('The out of office auto reply has been turned on.')
}

function turnOnAutoResponder() {
const ONE_DAY_MILLIS = 24 * 60 * 60 * 1000;
const currentTime = (new Date()).getTime();
Gmail.Users.Settings.updateVacation({
enableAutoReply: true,
responseSubject: 'I am out of the office today',
responseBodyHtml: 'I am out of the office today; will be back on the next business day.<br><br><i>Created by OOO Chat app!</i>',
restrictToContacts: true,
restrictToDomain: true,
startTime: currentTime,
endTime: currentTime + ONE_DAY_MILLIS
}, 'me');
}

We have to update the manifest file to be able to publish our app to Google Chat. To do so we first need to make the file visible in the script editor. We do it by hovering over the side panel on the left to expand the menu and selecting Project Settings > Show “appsscript.json” manifest file in editor.

Once the file appscript.json is visible, add “chat” as property and an empty object as the key. Note that you should not change the value of the “timeZone” in the file as this is dependent on your actual time zone/location you are in. Keep in mind to save the project after every change you make to any of the files in the IDE.

{
"timeZone": "Europe/Madrid",
"dependencies": {
},
"exceptionLogging": "STACKDRIVER",
"runtimeVersion": "V8",
"chat": {}
}

2. Enable Gmail and Calendar Advanced service

Two of our functions require advanced services to be turned on: Gmail API and Calendar API. We proceed as follows to enable these advanced services:

  • At the left, we click Editor <>.
  • At the left, next to Services, we click Add a service +.
  • We select the Gmail advanced Google service and click Add.
  • We select the Calendar advanced Google service and click Add.
Enable Gmail and Calendar advanced services

3. Create a Google Cloud project

When you create an Apps Script project, Apps Script creates a default Google Cloud project that operates in the background. For most scripts this is the best option.

But when you create a Google Chat app, we need to be able to manually configure the Cloud project. Check out this guide if you would like a step-by-step tutorial on how to create a new Google Cloud project.

4. Create OAuth consent screen

For every Google Chat app we create, we have to configure an OAuth consent screen which is found in the Google Cloud Console under APIs & Services > OAuth consent screen. This screen will be displayed to the user whenever they install the Chat app and it requests the user’s permission to run on their behalf.

Since we plan to use this Chat app only within our Google Workspace domain, we choose User type: Internal. Whatever we add under App information will be visible for the Chat app users on the consent screen. For the app logo, you can use this sample.

Add app information in the Google Cloud Console

We can provide additional information under the App domain section like the link to our Chat apps privacy policy, and so on.

We make sure to provide an up to date email address so Google can notify us about any changes to our Cloud console project. We proceed to the next screen by clicking on Save and Continue.

Since the app is only for internal use, there is no need to manually add any scopes for review.

Next we add our newly created Cloud Console project’s number to our Apps Script project settings. For this we copy the project number which we find in the settings of the Cloud Console project: More > Project settings.

In the script editor access the Project Settings and under the section Google Cloud Platform (GCP) Project we click Change project. We paste the project number we copied and click Set Project.

In the Project settings you will find the project number

5. Publish Chat app

At this point we are ready to publish our app to Google Chat which we do in the script editor by clicking Deploy > New deployment.

Deploy the Chat app in the IDE
UI for the deployment of the app

We publish our Chat app as an Add-on, give it a description and copy the deployment ID. We are going to need this ID in the next step when we configure the Google Chat API to establish a link between our app and the API which we will enable in the Google Cloud project we previously created.

Copy the deployment ID to add it to the Google Chat API config

6. Enable Google Chat API

In the Google Cloud project we have to enable the Google Chat API and configure our Chat app. We can use the search field at the top of the console to find the API we’re looking for.

Search for the Google Chat API in the Google Cloud Console
Enable the API

We select the API from the search results and click Enable. Once enabled, we can click on Manage to access the configuration user interface.

7. Setup functionality, connections & permissions

On the Configuration tab we add the necessary information about our app. In this tutorial we are configuring our Chat app to receive direct messages from users and that it can be added to a group conversation or space. The deployment ID we copied in the script editor has to be added in conjunction with choosing Apps Script project as connection setting.

Configure your Chat app in the Google Cloud Console

8. Add slash commands

We’ve designed our script to respond to four different slash commands. In the Google Chat API settings is where we can define these slash commands.

For each slash command we need to provide a name, which the user types in Google Chat, a command Id and a short description.

We make sure that the command Ids we define on this screen correspond to the ones the code will respond to which we defined in step 1 in our Code.js file.

Add the slash commands to the Chat app config

Under Visibility add your email address and that of anyone else if they too should test your Chat app. Tick the box next to Log errors to Logging and save your configuration.

9. Enable the Gmail and Calendar API

Remember that we enabled the Gmail and the Calendar API advanced services in our Apps Script project? Since we exchanged the default Cloud project with our newly created project, we have to additionally enable the Gmail API and the Calendar API in the Google Cloud Console.

Just as with the Google Chat API, we can use the search field at the top of the console to search for the APIs, and enable them.

Search for and enable the Gmail and Calendar APIs

Start using the Chat app

Now that our Chat app is published we can start using it! In Google Chat, we click New Chat > Find apps. We can search for the Chat app by the name we gave it, select it and click Install.

Once installed, we can interact with the Chat app by typing the slash commands we defined.

Since this is the first time we are using the Chat app it asks us for permission to access our Gmail and Google Calendar and we grant the request.

From now on we can use our OOO App, to manage our out of office days.

OOO Chat app in action!

Conclusion

Want to learn more about Google Chat apps? Then check out the Google Chat for Developers documentation. There you will find easy to follow along samples to get you started building your own Google Chat apps.

--

--

Chanel Greco
Google Cloud - Community

I'm a Developer Advocate for Google Workspace working for Google. I like writing about technology.