สร้างส่วนเสริม Google Workspace ในภาษาการเข้ารหัสภาษาใดก็ได้

คุณจะสร้างส่วนเสริมในภาษาการเขียนโค้ดใดก็ได้ที่ต้องการเป็นอีกทางเลือกหนึ่งแทนการใช้ Google Apps Script ตราบใดที่คุณส่งคืน JSON ที่จัดรูปแบบอย่างถูกต้องเพื่อให้อินเทอร์เฟซแสดงผลเป็นการ์ดได้

ตั้งค่ารันไทม์

เลือกโครงสร้างพื้นฐานของโฮสติ้งและตั้งค่าปลายทาง HTTPS หากต้องการสร้างและโฮสต์ส่วนเสริมบน Google Cloud เราขอแนะนำให้คุณใช้ Cloud Run

สร้างแหล่งข้อมูลการทำให้ใช้งานได้

เมื่อสร้างส่วนเสริมในภาษาอื่น คุณต้องกำหนดค่าทรัพยากรการทำให้ใช้งานได้ของส่วนเสริมใน Google Cloud ทรัพยากรการทำให้ใช้งานได้ทำงานเหมือนกับไฟล์ Manifest ของโครงการ Apps Script

ทำตามขั้นตอนด้านล่างเพื่อกำหนดค่าทรัพยากรการติดตั้งใช้งานของส่วนเสริม

  1. หากยังไม่ได้สร้าง ให้สร้างโปรเจ็กต์ Google Cloud สำหรับส่วนเสริม
  2. ในโปรเจ็กต์ Cloud ให้พิมพ์ Google Workspace Marketplace SDK ในแถบค้นหาที่ด้านบน แล้วกด Enter
  3. ในผลการค้นหา ให้คลิก SDK ของ Google Workspace Marketplace
  4. หากยังไม่ได้เปิดใช้ SDK ของ Google Workspace Marketplace ให้คลิกเปิดใช้ หากเปิดใช้ไว้ ให้คลิกจัดการ
  5. คลิกรันไทม์อื่นทางด้านซ้าย
  6. คลิกเปิดใช้ในส่วน Google Workspace Add-ons API
  7. คลิกสร้างการทำให้ใช้งานได้ใหม่ที่ด้านบน
  8. ตั้งชื่อทรัพยากรการทำให้ใช้งานได้แล้วคลิก Next
  9. เพิ่มข้อมูลส่วนเสริมในรูปแบบ JSON แล้วคลิกส่ง

ตัวอย่าง: ทรัพยากรการติดตั้งใช้งาน

ด้านล่างนี้เป็นตัวอย่างแหล่งข้อมูลการทำให้ใช้งานได้ที่ทริกเกอร์หน้าแรกที่ไม่ซ้ำกันใน Gmail โดยใช้ปลายทาง HTTPS

{
  "oauthScopes": ["https://www.googleapis.com/auth/gmail.addons.execute", "https://www.googleapis.com/auth/gmail.metadata"],
  "addOns": {
    "common": {
      "name": "My HTTP Add-on",
      "logoUrl": "https://fonts.gstatic.com/s/i/googlematerialicons/markunread_mailbox/v6/black-24dp/1x/gm_markunread_mailbox_black_24dp.png",
      "homepageTrigger": {
        "runFunction": "https://us-central1-test-http-runtime.cloudfunctions.net/HttpAddOn/exampleWidgets"
      }
    },
    "gmail": {
          "contextualTriggers": [
            {
              "unconditional": {},
              "onTriggerFunction": "https://us-central1-test-http-runtime.cloudfunctions.net/GmailExample/simpleMessageInfo"
            }
          ]
     },
    "calendar": {},
    "drive": {}
  }
}

สร้างการ์ด JSON

ออกแบบอินเทอร์เฟซส่วนเสริมด้วย เฟรมเวิร์กการ์ด ใช้ JSON แทน Google Apps Script Card Service เพื่อสร้างการ์ด สำหรับข้อมูลโดยละเอียดเกี่ยวกับออบเจ็กต์ JSON สำหรับการ์ด โปรดดูเอกสารอ้างอิง

ดูตัวอย่างการ์ด JSON ได้ที่อินเทอร์เฟซของการ์ด JSON

สร้างออบเจ็กต์การตอบสนองของ JSON

จุดแรกเข้าที่ไม่ซ้ำกันแต่ละจุดซึ่งระบุไว้ในไฟล์ Manifest ของส่วนเสริมต้องมีออบเจ็กต์การตอบสนอง JSON ที่ไม่ซ้ำกัน

ด้านล่างนี้คือจุดแรกเข้าซึ่งเป็นส่วนเสริมของ Google Workspace ยอดนิยม พร้อมตัวอย่างสคีมาการตอบสนอง JSON

จุดแรกเข้าทั่วไปสำหรับ Gmail, Google ปฏิทิน, Google ไดรฟ์ และเครื่องมือแก้ไข

จุดแรกเข้าคำอธิบายการตอบสนองของ JSON
homepageTrigger.runFunctionผู้ใช้เปิดหน้าแรกของส่วนเสริมrenderActions
OnClick.action.functionผู้ใช้คลิกการดำเนินการภายในส่วนเสริมonClick
TextInput.autoCompleteAction.function ผู้ใช้ป้อนข้อความและส่วนเสริมจะมีคำแนะนำอัตโนมัติgetAutocompletionResponse

จุดแรกเข้าสำหรับ Gmail

จุดแรกเข้าคำอธิบายการตอบสนองของ JSON
contextualTrigger.onTriggerFunction ผู้ใช้เปิดอีเมล renderActions
composeTrigger การคลิกของผู้ใช้จะเปิดมุมมองcompose renderActions

จุดแรกเข้าสำหรับปฏิทิน

จุดแรกเข้าคำอธิบายการตอบสนองของ JSON
eventOpenTrigger ผู้ใช้เปิดกิจกรรมrenderActions
eventUpdateTrigger ผู้ใช้อัปเดตกิจกรรมcalendarClientActionMarkup

จุดแรกเข้าสำหรับไดรฟ์

จุดแรกเข้าคำอธิบายการตอบสนองของ JSON
onItemsSelectedTrigger ผู้ใช้เลือกไฟล์renderActions

จุดแรกเข้าสำหรับเอดิเตอร์

จุดแรกเข้าคำอธิบายการตอบสนองของ JSON
linkPreviewTriggers ผู้ใช้โต้ตอบกับ URL ที่ตรงกับรูปแบบที่ระบุไว้ใน LinkPreviewTriggers linkPreview
onFileScopeGrantedTrigger ผู้ใช้ให้สิทธิ์เข้าถึงไฟล์เพื่อตอบสนองต่อการดำเนินการ requestFileScopeForActiveDocument เรียบร้อยแล้วrenderActions

ตรวจสอบคำขอ JSON

คำขอที่ส่งไปยังปลายทางเป็นคำขอ POST ที่มีออบเจ็กต์เหตุการณ์ JSON ในเนื้อหาคำขอ

ปกป้องปลายทาง HTTPS อย่างเหมาะสมเพื่อให้มั่นใจว่าคำขอที่ส่งไปยังส่วนเสริมจะได้รับการตอบสนองตามคำขอที่มาจาก Google เท่านั้น ซึ่งเป็นเรื่องที่สำคัญโดยเฉพาะอย่างยิ่งหากปลายทาง HTTPS แสดงข้อมูลผู้ใช้จากบริการของคุณ

ใช้โทเค็นรหัส authorizationEventObject เพื่อเข้าถึงบริการของ Google และตรวจสอบผู้ใช้และบัญชีบริการ

โทเค็น ID

ช่องโทเค็นTypeคำอธิบาย
authorizationEventObject.userOAuthToken สตริงโทเค็นเพื่อการเข้าถึง OAuth ของผู้ใช้ปลายทางตามขอบเขตที่ขอ

ดูตัวอย่างนี้

authorizationEventObject.userIdToken สตริงโทเค็นรหัสผู้ใช้ปลายทาง ระบบจะเข้ารหัสอีเมลของผู้ใช้ในโทเค็นรหัสผู้ใช้ปลายทางในรูปแบบโทเค็นเว็บ JSON

หากต้องการรับออบเจ็กต์เหตุการณ์นี้ในคำขอ คุณต้องระบุขอบเขต https://www.googleapis.com/auth/userinfo.email ในทรัพยากรการทำให้ใช้งานได้ของส่วนเสริม

ดูตัวอย่างนี้

authorizationEventObject.systemIdTokenสตริงโทเค็นรหัสสำหรับบัญชีบริการของส่วนเสริม Google Workspace สำหรับการทำให้ใช้งานได้ที่เฉพาะเจาะจง สามารถใช้เพื่อยืนยันว่าคำขอมาจาก Google

ดูตัวอย่างนี้

ตัวอย่าง: รับข้อมูล Gmail ของผู้ใช้

หากต้องการเข้าถึงข้อมูล Google ของผู้ใช้ โปรดส่งคำขอขอบเขตที่เกี่ยวข้องในทรัพยากรการทำให้ใช้งานได้ของส่วนเสริม จากนั้นใช้ authorizationEventObject.userOAuthToken เพื่อส่งต่อการเรียก API

ในตัวอย่างต่อไปนี้ ส่วนเสริมจะใช้ทริกเกอร์ตามบริบทเพื่ออ้างอิงผู้รับอีเมลขณะที่ผู้ใช้อ่านอีเมล ดูข้อมูลเพิ่มเติมเกี่ยวกับทริกเกอร์ตามบริบทใน Gmail ได้ที่การขยาย UI ของข้อความ

เพิ่มทริกเกอร์และขอบเขต

ก่อนอื่นให้อัปเดตทรัพยากรการทำให้ใช้งานได้ให้รวมทริกเกอร์ตามบริบทของ Gmail และขอบเขต OAuth เพื่ออนุญาตการเข้าถึงข้อความปัจจุบัน

{
  "oauthScopes": [
    "https://www.googleapis.com/auth/gmail.addons.execute",
    "https://www.googleapis.com/auth/gmail.addons.current.message.metadata"
  ],
  "addOns": {
    "common": {...},
    "gmail": {
      "contextualTriggers": [
        {
          "unconditional": {},
          "onTriggerFunction": "https://us-central1-test-http-runtime.cloudfunctions.net/GmailExample/simpleMessageInfo"
        }
      ],
    }
  }
}

ระบุปลายทาง HTTPS สำหรับส่วนเสริมที่จะใช้เมื่อผู้ใช้ดูข้อความอีเมล

หากไม่ต้องการใช้เส้นทาง URL เพื่อแยกระหว่างจุดแรกเข้าต่างๆ คุณอาจใช้พารามิเตอร์การค้นหา เช่น https://us-central1-test-http-runtime.cloudfunctions.net/HttpAddOn/exampleWidgets?trigger=onEmailOpen

เมื่อทริกเกอร์ ซึ่งในกรณีนี้เมื่อผู้ใช้เปิดอีเมล ระบบจะส่งออบเจ็กต์เหตุการณ์ต่อไปนี้ไปยังส่วนเสริมเป็น JSON Blob ในเนื้อหา HTTP

{
  "commonEventObject": {
     "hostApp": "GMAIL",
     "platform": "WEB"
  },
  "authorizationEventObject": {
    "userOAuthToken": "ya29...",
    "systemIdToken": "eyJhbGc...",
    "userIdToken": "jaaa45...",
  },
  "gmail": {
     "messageId": "msg-f:1234567",
     "threadId": "thread-f:2345678",
     "accessToken": "xedf241...",
  },
}

ดึงข้อมูล

ออบเจ็กต์เหตุการณ์ไม่มีอีเมลของผู้ใช้หรือเนื้อหาของอีเมล หากต้องการดูข้อมูลนี้ ให้ใช้ Gmail API เพื่อรับเนื้อหาของอีเมลที่มี messageId

หากต้องการตรวจสอบสิทธิ์กับ Gmail API ให้ส่งโทเค็น OAuth2 ในส่วนหัว Authorization เป็นโทเค็นสำหรับผู้ถือ ส่งโทเค็นเพื่อการเข้าถึง OAuth2 จาก authorizationEventObject.userOauthToken

เมื่อใช้ขอบเขตต่อข้อความรายการใดรายการหนึ่ง ให้ใส่โทเค็นข้อความจาก gmail.accessToken ในส่วนหัว X-Goog-Gmail-Access-Token เพิ่มเติมด้วย

โค้ดตัวอย่างด้านล่างแสดงวิธีรับเนื้อหาในอีเมลโดยใช้ Gmail API

Java

import com.fasterxml.jackson.databind.JsonNode;
import com.google.api.client.auth.oauth2.BearerToken;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.http.HttpHeaders;
import com.google.api.services.gmail.Gmail;
import com.google.api.services.gmail.model.Message;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class GmailMessageDemoController {

   @PostMapping("/message")
   public JsonNode onViewMessage(@RequestBody JsonNode event)
           throws Exception {
       String messageId = event.at("/gmail/messageId").asText();
       String messageToken = event.at("//gmail/accessToken").asText();
       String accessToken = event.at("//authorizationEventObject/userOauthToken")
               .asText();
       Credential credential = new Credential(BearerToken.authorizationHeaderAccessMethod());
       credential.setAccessToken(accessToken);

       Gmail gmailClient = new Gmail.Builder(
               GoogleNetHttpTransport.newTrustedTransport(),
               JacksonFactory.getDefaultInstance(),
               credential)
               .setApplicationName("GSAO Demo")
               .build();
       HttpHeaders headers = new HttpHeaders()
               .set("X-Goog-Gmail-Access-Token", messageToken);
       Message message = gmailClient.users().messages().get("me", messageId)
               .setFormat("metadata")
               .setRequestHeaders(headers)
               .execute();
     // Build and return response...
   }
}

Node.JS

import express from "express";
import { Request, Response } from "express";
import { google } from "googleapis";
import asyncHandler from "express-async-handler";
import { OAuth2Client } from "google-auth-library";

const gmail = google.gmail({version: "v1"});

const app = express();

app.post("/", asyncHandler(async (req, res) => {
   const currentMessageId = req.body.gmail.messageId;
   const event = req.body;
   const accessToken = event.authorizationEventObject.userOAuthToken;
   const messageToken = event.gmail.accessToken;
   const auth = new OAuth2Client();
   auth.setCredentials({access_token: accessToken});

   const gmailResponse = await gmail.users.messages.get({
       id: currentMessageId,
       userId: "me",
       format: "metadata",
       auth,
       headers: { "X-Goog-Gmail-Access-Token": messageToken }
   });

   const message = gmailResponse.data;
   const response = ...; // Build and return response
   res.json(response);
}));

ตัวอย่าง: ดูอีเมลของผู้ใช้

วิธีเข้าถึงอีเมลของผู้ใช้

  1. เพิ่มขอบเขตที่เกี่ยวข้องลงในทรัพยากรการทำให้ใช้งานได้ของส่วนเสริม
  2. รับรหัสไคลเอ็นต์ที่สร้างขึ้นเพื่อตรวจสอบความถูกต้องของโทเค็นเว็บ JSON
  3. ใช้ authorizationEventObject.userIdToken เพื่อดึงข้อมูลรหัสผู้ใช้และอีเมล

เพิ่มขอบเขต

หากต้องการเข้าถึงอีเมลของผู้ใช้ ให้เพิ่มขอบเขต OAuth https://www.googleapis.com/auth/userinfo.email ลงในทรัพยากรการทำให้ใช้งานได้ของส่วนเสริม ดังนี้

{
  "oauthScopes": [
    "https://www.googleapis.com/auth/userinfo.email",
  ],
  "addOns": {
    "common": {...},
  }
}

ดูรหัสไคลเอ็นต์

หากต้องการยืนยันโทเค็นรหัสผู้ใช้และดึงข้อมูลรหัสผู้ใช้และอีเมล คุณต้องใช้รหัสไคลเอ็นต์ที่สร้างขึ้นเพื่อตรวจสอบโทเค็นเว็บ JSON

หากต้องการรับรหัสไคลเอ็นต์ ให้ไปที่ SDK ของ Google Workspace Marketplace ใน Google Cloud Console:

  1. เปิด Google Cloud Console แล้วเลือกโปรเจ็กต์ Google Cloud ของส่วนเสริม
  2. ไปที่หน้ารันไทม์อื่นของ Google Workspace Marketplace SDK
  3. ในส่วนทรัพยากรการให้สิทธิ์ ให้ไปที่ช่องรหัสไคลเอ็นต์ OAuth และคัดลอกรหัส

หรือหากคุณติดตั้ง Google Cloud CLI ไว้แล้ว ให้รับรหัสไคลเอ็นต์โดยเรียกใช้คำสั่ง get-authorization ต่อไปนี้

gcloud workspace-add-ons get-authorization

ดึงข้อมูลรหัสผู้ใช้และอีเมล

ตัวอย่างโค้ดต่อไปนี้จะได้รับรหัสผู้ใช้และอีเมล CLIENT_ID_FOR_ADDON เป็นตัวยึดตำแหน่งสำหรับรหัสไคลเอ็นต์:

Java

import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier;
import com.google.api.client.googleapis.auth.oauth2.GoogleTokenResponse;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;

final static String CLIENT_ID = "CLIENT_ID_FOR_ADDON";

//...

GoogleIdToken.Payload decodeIdToken(JsonNode event) throws Exception {
    String idToken = event.at("/authorizationEventObject/userIdToken").asText();
    GoogleIdTokenVerifier.Builder builder = new GoogleIdTokenVerifier.Builder(
                GoogleNetHttpTransport.newTrustedTransport(),
                JacksonFactory.getDefaultInstance());
    builder.setAudience(Collections.singletonList(CLIENT_ID);
    GoogleIdTokenVerifier verifier = builder.build();
    GoogleIdToken decodedToken = verifier.verify(idToken);
    GoogleIdToken.Payload payload = decodedToken.getPayload();
    return payload;
    // E.g. payload.getEmail() for email,  payload.getSubject() for user ID
}

Node.JS

const { OAuth2Client } = require('google-auth-library');
const CLIENT_ID = 'CLIENT_ID_FOR_ADDON';

// ...

async decodeIdToken(event) {
   const oAuth2Client = new OAuth2Client();
   const decodedToken = await oAuth2Client.verifyIdToken({
        idToken: event.authorizationEventObject.userIdToken,
        audience: CLIENT_ID
    });
    const payload = decodedToken.getPayload();
    // E.g. payload.email for email,  payload.sub for user ID
    return payload;
}

ตัวอย่าง: ตรวจสอบคำขอจาก Google

คุณต้องมีอีเมลบัญชีบริการเพื่อยืนยัน authorizationEventObject.systemIdToken

หากต้องการรับอีเมลบัญชีบริการ ให้ไปที่ SDK ของ Google Workspace Marketplace ใน Google Cloud Console:

  1. เปิด Google Cloud Console แล้วเลือกโปรเจ็กต์ Google Cloud ของส่วนเสริม
  2. ไปที่หน้ารันไทม์อื่นของ Google Workspace Marketplace SDK
  3. ในส่วนทรัพยากรการให้สิทธิ์ ให้ไปที่ช่องอีเมลบัญชีบริการและคัดลอกอีเมล

ตัวอย่างโค้ดต่อไปนี้จะตรวจสอบสิทธิ์คำขอจาก Google ด้วยบัญชีบริการของระบบของส่วนเสริม SERVICE_ACCOUNT_EMAIL เป็นตัวยึดตำแหน่งสำหรับอีเมลบัญชีบริการ

Java


import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Collections;
import java.util.List;

class Auth {
    static final String SERVICE_ACCOUNT_EMAIL;

   public static void authenticateRequest(HttpServletRequest httpRequest) throws Exception {
        String authHeader = httpRequest.getHeader("Authorization");

        if (authHeader == null || !authHeader.startsWith("Bearer ")) {
            throw new IllegalArgumentException("Missing authorization header");
        }
        String idToken = authHeader.substring(7);
        String currentUrl = httpRequest.getRequestURL().toString();
        // Verify the ID token -- issued by Google & matches our current URL
        List audience = Collections.singletonList(currentUrl);
        GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(
                GoogleNetHttpTransport.newTrustedTransport(),
                JacksonFactory.getDefaultInstance())
                .setAudience(audience)
                .build();
        GoogleIdToken decodedToken = verifier.verify(idToken);
        if (decodedToken == null) {
            throw new IllegalStateException("Decoded token is null");
        }
        GoogleIdToken.Payload payload = decodedToken.getPayload();

        // Email should also match the service account issued for this add-on
        if (SERVICE_ACCOUNT_EMAIL != null && !serviceAccountEmail.equals(payload.getEmail())) {
            throw new IllegalArgumentException("Invalid email in system idToken");
        }
    }
}

Node.JS

const {OAuth2Client} = require('google-auth-library');
const SERVICE_ACCOUNT_EMAIL = process.env.SERVICE_ACCOUNT_EMAIL;

async function authenticateRequest(req) {
  let idToken = req.token; // Using express-bearer-token middleware
  if (!idToken) throw 'Missing bearer token';
  const audience = `${req.protocol}://${req.hostname}${req.originalUrl}`;
  const authClient = new OAuth2Client();
  const ticket = await authClient.verifyIdToken({idToken, audience});
  if (SERVICE_ACCOUNT_EMAIL && ticket.getPayload().email !== SERVICE_ACCOUNT_EMAIL) {
    throw 'Invalid email';
  }
}

ทดสอบส่วนเสริม

หากต้องการติดตั้งและทดสอบส่วนเสริมจาก Google Cloud Console โปรดดูที่ส่วนติดตั้งส่วนเสริมที่ยังไม่ได้เผยแพร่

หากต้องการดำเนินการโดยใช้โปรแกรม โปรดดูเอกสารอ้างอิงเกี่ยวกับ API ส่วนเสริมของ Google Workspace นอกจากนี้คุณยังใช้คำสั่ง gcloud ได้อีกด้วย

ติดตั้งส่วนเสริมที่ยังไม่ได้เผยแพร่

หากต้องการติดตั้งส่วนเสริมสำหรับการทดสอบหรือการใช้งานส่วนบุคคล ให้ทำตามขั้นตอนต่อไปนี้

  1. ในโปรเจ็กต์ Cloud ของส่วนเสริม ให้ไปที่หน้ารันไทม์สำรองใน SDK ของ Google Workspace Marketplace
  2. คลิกติดตั้งถัดจากการทำให้ใช้งานได้ที่ต้องการทดสอบ

ถอนการติดตั้งส่วนเสริมที่ยังไม่ได้เผยแพร่

หากต้องการถอนการติดตั้งส่วนเสริมที่ยังไม่ได้เผยแพร่ ให้ทำตามขั้นตอนต่อไปนี้

  1. ในโปรเจ็กต์ Cloud ของส่วนเสริม ให้ไปที่หน้ารันไทม์สำรองใน SDK ของ Google Workspace Marketplace
  2. คลิกถอนการติดตั้งถัดจากการทำให้ใช้งานได้ที่ต้องการถอนการติดตั้ง

ตัวอย่างสคีมา JSON

คุณรวมตัวอย่างสคีมาต่อไปนี้ลงในสภาพแวดล้อมการพัฒนาได้ ตัวอย่างเช่น ดูการรองรับโค้ด Visual Studio สำหรับ JSON

อินเทอร์เฟซการ์ด JSON

การ์ดทั่วไป

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "description": "The card object used to build UIs for Google Workspace add-ons.",
  "definitions": {
    "textParagraph": {
      "$id": "/properties/textParagraph",
      "type": "object",
      "description": "Text paragraph widget.",
      "required": [
        "text"
      ],
      "properties": {
        "text": {
          "type": "string",
          "description": "The text of the paragraph. Can contain formatted text."
        }
      }
    },
    "image": {
      "$id": "/properties/image",
      "type": "object",
      "description": "Image widget.",
      "required": [
        "imageUrl"
      ],
      "properties": {
        "imageUrl": {
          "type": "string",
          "description": "Sets the image to use by providing its URL or data string."
        },
        "altText": {
          "type": "string",
          "description": "Sets the alternative text of the image for accessibility."
        },
        "onClick": {
          "type": "object",
          "description": "Sets an action that executes when the object is clicked.",
          "$ref": "#/definitions/onClick"
        }
      }
    },
    "icon": {
      "$id": "/properties/icon",
      "type": "object",
      "description": "The icon, can be specified by KnownIcon string or a URL.",
      "oneOf": [
        {
          "properties": {
            "knownIcon": {
              "type": "string",
              "description": "The icon specified by the string name of a list of known icons"
            },
            "iconUrl": {
              "type": "string",
              "description": "The icon specified by a URL."
            }
          }
        }
      ],
      "properties": {
        "altText": {
          "type": "string",
          "description": "The description of icon which is used for accessibility."
        }
      }
    },
    "divider": {
      "$id": "/properties/divider",
      "type": "object",
      "description": "A horizontal divider."
    },
    "button": {
      "$id": "/properties/button",
      "type": "object",
      "description": "A button. Can be a text button or an image button.",
      "required": ["onClick", "text"],
      "properties": {
        "text": {
          "type": "string",
          "description": "The text of the button."
        },
        "icon": {
          "type": "object",
          "description": "The icon image",
          "$ref": "#/definitions/icon"
        },
        "color": {
          "type": "object",
          "description": "If set, the button is filled with solid background.",
          "$ref": "#/definitions/color"
        },
        "onClick": {
          "type": "object",
          "description": "The onClick action of the button.",
          "$ref": "#/definitions/onClick"
        },
        "disabled": {
          "type": "boolean",
          "description": "If true, the button is displayed in a disabled state and doesn't respond to user actions"
        }
      }
    },
    "buttonList": {
      "$id": "/properties/buttonList",
      "type": "object",
      "properties": {
        "buttons": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/button"
          },
          "description": "A list of buttons laid out horizontally"
        }
      }
    },
    "decoratedText": {
      "$id": "/properties/decoratedText",
      "type": "object",
      "required": [
        "text"
      ],
      "properties": {
        "button" : {
          "type": "object",
          "description": "A button that can be clicked to trigger an action",
          "$ref": "#/definitions/button"
        },
        "switchControl": {
          "type": "object",
          "description": "A switch widget can be clicked to change its state or trigger an action.",
          "$ref": "#/definitions/switchControl"
        },
        "icon": {
          "type": "object",
          "description": "The icon displayed in front of the text.",
          "$ref": "#/definitions/icon"
        },
        "imageType": {
          "type": "string",
          "enum": [
            "SQUARE",
            "CIRCLE"
          ],
          "description": "Define the cropping of the image."
        },
        "topLabel": {
          "type": "string",
          "description": "The formatted text label that shows above the main text."
        },
        "text": {
          "type": "string",
          "description": "The main widget formatted text."
        },
        "wrapText": {
          "type": "boolean",
          "description": "The wrap text setting. If true, the text is wrapped and displayed in multiline.\nOtherwise the text is truncated."
        },
        "bottomLabel": {
          "type": "string",
          "description": "The formatted text label that shows below the main text."
        },
        "onClick": {
          "type": "object",
          "description": "Only the top/bottom label + content region is clickable.",
          "$ref": "#/definitions/onClick"
        }
      }
    },
    "switchControl": {
      "$id": "/properties/switchControl",
      "type": "object",
      "properties": {
        "name": {
          "type": "string",
          "description": "The name of the switch widget which is used in formInput."
        },
        "value": {
          "type": "string",
          "description": "The value is what is passed back in the Apps Script callback."
        },
        "selected": {
          "type": "boolean",
          "description": "If the switch is selected."
        },
        "onChangeAction": {
          "type": "object",
          "description": "The action when the switch state is changed.",
          "$ref": "#/definitions/action"
        },
        "controlType": {
          "type": "string",
          "description": "The control type, it could be either Switch or Checkbox.",
          "enum": [
            "SWITCH",
            "CHECKBOX"
          ]
        }
      }
    },
    "onClick": {
      "$id": "/properties/onClick",
      "type": "object",
      "properties": {
        "action": {
          "type": "object",
          "$ref": "#/definitions/action",
          "description": "An action is triggered by this onClick, if specified."
        },
        "openLink": {
          "type": "object",
          "$ref": "#/definitions/openLink",
          "description": "This onClick triggers an open link action if specified."
        },
        "openDynamicLinkAction": {
          "type": "object",
          "$ref": "#/definitions/action",
          "description": "An add-on triggers this action when the action needs to open a link.\nThis differs from the openLink above in that this needs to talk to server to get the link.\nThus some preparation work is required for web client to do before the open link action response comes back."
        },
        "card": {
          "type": "object",
          "$ref": "#/definitions/card",
          "description": "A new card is pushed to the card stack after clicking if specified."
        }
      }
    },
    "openLink": {
      "$id": "/properties/openLink",
      "description": "Opens a URL",
      "required": ["url"],
      "properties": {
        "url": {
          "type": "string",
          "description": "The URL to open."
        },
        "openAs": {
          "type": "string",
          "description": "When an onClick opens a link, then the client can either open it as a \n full size (window if that is the frame used by the client), or an \n overlay (such as a pop-up). The implementation depends on the client\nplatform capabilities, and the value selected may be ignored if the\nclient does not support it. FULL_SIZE is supported by all clients.",
          "enum": [
            "FULL_SIZE",
            "OVERLAY"
          ]
        },
        "onClose": {
          "type": "string",
          "enum": [
            "NOTHING",
            "RELOAD"
          ]
        }
      }
    },
    "textInput": {
      "$id": "/properties/textInput",
      "type": "object",
      "description": "A text input is a UI item where the users can input text.",
      "required": ["name"],
      "properties": {
        "name": {
          "type": "string",
          "description": "The name of the text input which is used in formInput."
        },
        "label": {
          "type": "string",
          "description": "At least one of label and hintText is required to be specified."
        },
        "hintText": {
          "type": "string",
          "description": "The hint text."
        },
        "value": {
          "type": "string",
          "description": "The default value when no input from user."
        },
        "type": {
          "type": "string",
          "enum": [
            "SINGLE_LINE",
            "MULTIPLE_LINE"
          ],
          "description": "The style of the text (for example, single line or multiple line)."
        },
        "onChangeAction": {
          "type": "object",
          "description": "The onChange action (for example, invoke an Apps Script)",
          "$ref": "#/definitions/action"
        },
        "initialSuggestions": {
          "type": "object",
          "description": "The initial suggestions made before any user input",
          "$ref": "#/definitions/suggestions"
        },
        "autoCompleteAction": {
          "type": "object",
          "$ref": "#/definitions/action",
          "description": "The refresh function which returns suggestions based on the user's input text."
        },
        "multipleSuggestions": {
          "type": "boolean",
          "description": "When set to true, a user can input multiple suggestions items."
        }
      }
    },
    "suggestions": {
      "$id": "/properties/suggestions",
      "description": "A container wrapping elements necessary for showing suggestion items used in text input autocomplete.",
      "properties": {
        "items": {
          "type": "array",
          "description": "A list of suggestion items which will be used in are used in autocomplete.",
          "items": {
            "$ref": "#/definitions/suggestionItem"
          }
        }
      }
    },
    "suggestionItem": {
      "$id": "/properties/suggestionItem",
      "type": "object",
      "description": "A Suggestion Item. Only supports text for now.",
      "properties": {
        "text": {
          "type": "string",
          "description": "Text."
        }
      }
    },
    "selectionInput": {
      "$id": "/properties/selectionInput",
      "description": "A widget which creates a UI item (for example, a drop-down list) with options for users to select.",
      "required": ["name"],
      "properties": {
        "name": {
          "type": "string",
          "description": ""
        },
        "label": {
          "type": "string",
          "description": "The label displayed ahead of the switch control."
        },
        "type": {
          "type": "string",
          "description": "The type of the selection.",
          "enum": [
            "CHECK_BOX",
            "RADIO_BUTTON",
            "SWITCH",
            "DROPDOWN"
          ]
        },
        "items": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/selectionItem"
          },
          "description": "The item/items in the switch control."
        },
        "onChangeAction": {
          "type": "object",
          "description": "If specified, form is submitted when selection changes",
          "$ref": "#/definitions/action"
        }
      }
    },
    "selectionItem": {
      "type":"object",
      "$id": "/properties/selectionItem",
      "description": "The item in the switch control.",
      "properties": {
        "text": {
          "type": "string",
          "description": "The text to be displayed"
        },
        "value": {
          "type": "string",
          "description": "The value associated with this item which is sent back to Apps Script.\nThe client should use this as a form input value."
        },
        "selected": {
          "type": "boolean",
          "description": "If more than one items are selected for RADIO_BUTTON or DROPDOWN,\nthe first selected item is treated as selected and the after ones are all ignored."
        }
      }
    },
    "dateTimePicker": {
      "$id": "/properties/dateTimePicker",
      "description": "The widget to allow users to specify date and time",
      "properties": {
        "name": {
          "type": "string",
          "description": "The name of the text input which is used in formInput, and uniquely identifies this input."
        },
        "label": {
          "type": "string",
          "description": "The label for the field, which is displayed to the user."
        },
        "type": {
          "type": "string",
          "description": "The type of the date time picker.",
          "enum": [
            "DATE_AND_TIME",
            "DATE_ONLY",
            "TIME_ONLY"
          ]
        },
        "valueMsEpoch": {
          "type": "number",
          "description": "The value to display which can be the default value before user input or previous user input.\nIt is represented in milliseconds (Epoch time)"
        },
        "timezoneOffsetDate": {
          "type": "number",
          "description": "The number representing the time-zone offset from UTC, in minutes."
        },
        "onChangeAction": {
          "type": "object",
          "description": "Triggered when the user clicks on the Save, or Clear button from the date time picker dialog.",
          "$ref": "#/definitions/action"
        }
      }
    },
    "borderStyle": {
      "$id": "/properties/borderStyle",
      "type": "object",
      "description": "A border style.",
      "required": ["type"],
      "properties": {
        "type": {
          "type": "string",
          "description": "The border type.",
          "enum": [
            "NO_BORDER",
            "STROKE"
          ]
        },
        "strokeColor": {
          "description": "The border color.",
          "$ref": "#/definitions/color"
        },
        "cornerRadius": {
          "type": "number",
          "description": "The border corner radius."
        }
      }
    },
    "imageCropStyle": {
      "$id": "/properties/imageCropStyle",
      "type": "object",
      "description": "A crop style that can be applied to images.",
      "required": ["type"],
      "properties": {
        "type": {
          "type": "string",
          "description": "The crop type.",
          "enum": [
            "SQUARE",
            "CIRCLE",
            "RECTANGLE_CUSTOM",
            "RECTANGLE_4_3"
          ]
        },
        "aspectRatio": {
          "type": "number",
          "description": "The aspect ratio for a custom rectangular crop."
        }
      }
    },
    "imageComponent": {
      "$id": "/properties/imageComponent",
      "type": "object",
      "description": "An image and its properties.",
      "required": ["imageUri"],
      "properties": {
        "imageUri": {
          "type": "string",
          "description": "The URL for the image resource."
        },
        "altText": {
          "type": "string",
          "description": "The accessibility label for the image."
        },
        "cropStyle": {
          "$ref": "#/definitions/imageCropStyle",
          "description": "The crop style to apply to the image."
        },
        "borderStyle": {
          "$ref": "#/definitions/borderStyle",
          "description": "The border style to apply to the image."
        }
      }
    },
    "grid": {
      "$id": "/properties/grid",
      "type": "object",
      "description": "A grid that displays a collection of grid items.",
      "required": [],
      "properties": {
        "title": {
          "type": "string",
          "description": "The title of the grid."
        },
        "items": {
          "description": "List of grid items.",
          "type": "array",
          "items": {
            "$ref": "#/definitions/griditem"
          }
        },
        "borderStyle": {
          "description": "The border style for the grid items.",
          "$ref": "#/definitions/borderStyle"
        },
        "columnCount": {
          "type": "number",
          "description": "The number of columns in the grid."
        },
        "onClick": {
          "description": "The action that executes when a grid item is clicked.",
          "$ref": "#/definitions/onClick"
        }
      }
    },
    "griditem": {
      "$id": "/properties/griditem",
      "type": "object",
      "description": "An item that can be displayed in a grid widget.",
      "required": [],
      "properties": {
        "id": {
          "type": "string",
          "description": "An identifier for the grid item."
        },
        "image": {
          "description": "The image to display in the grid item.",
          "$ref": "#/definitions/imageComponent"
        },
        "title": {
          "type": "string",
          "description": "The title of the grid item."
        },
        "subtitle": {
          "type": "string",
          "description": "The subtitle of the grid item."
        },
        "textAlignment": {
          "description": "The text alignment for the grid item's text.",
          "$ref": "#/definitions/horizontalAlignment"
        },
        "layout": {
          "type": "string",
          "description": "The grid item layout.",
          "enum": [
            "TEXT_BELOW",
            "TEXT_ABOVE"
          ]
        }
      }
    },
    "horizontalAlignment": {
      "$id": "/properties/horizontalAlignment",
      "type": "string",
      "description": "Horizontal alignment options.",
      "enum": [
        "START",
        "CENTER",
        "END"
      ]
    },
    "widget": {
      "$id": "/properties/widget",
      "type": "object",
      "properties": {
        "textParagraph": {
          "type": "object",
          "description": "Display a text paragraph in this widget",
          "$ref": "#/definitions/textParagraph"
        },
        "image": {
          "type": "object",
          "description": "Display an image in this widget",
          "$ref": "#/definitions/image"
        },
        "decoratedText": {
          "type": "object",
          "description": "Display a decorated text item in this widget",
          "$ref": "#/definitions/decoratedText"
        },
        "buttonList": {
          "type": "object",
          "description": "A List of buttons",
          "$ref": "#/definitions/buttonList"
        },
        "textInput": {
          "type": "object",
          "description": "Display a text input in this widget",
          "$ref": "#/definitions/textInput"
        },
        "selectionInput": {
          "type": "object",
          "description": "Display a switch control in this widget",
          "$ref": "#/definitions/selectionInput"
        },
        "dateTimePicker": {
          "type": "object",
          "description": "Display a date/time picker in this widget",
          "$ref": "#/definitions/dateTimePicker"
        },
        "horizontalAlignment": {
          "description": "The horizontal alignment of this widget.",
          "$ref": "#/definitions/horizontalAlignment"
        },
        "divider": {
          "description": "Inserts a divider.",
          "$ref": "#/definitions/divider"
        },
        "grid": {
          "description": "Display a grid control in this widget.",
          "$ref": "#/definitions/grid"
        }
      }
    },
    "section": {
      "$id": "/properties/section",
      "type": "object",
      "required": [
        "widgets"
      ],
      "properties": {
        "header": {
          "type": "string",
          "description": "The text header of a section"
        },
        "collapsible": {
          "type": "boolean",
          "description": "Whether section can be collapsed or not."
        },
        "widgets": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/widget"
          },
          "description": "The widgets within a section. Example of a widget is TextParagraph or Image."
        },
        "uncollapsibleWidgetsCount": {
          "type": "number",
          "description": "The number of uncollapsable widgets"
        }
      }
    },
    "color": {
      "$id": "/properties/color",
      "type": "object",
      "description": "Represents a color in the RGBA color space.",
      "required": [
        "red",
        "green",
        "blue"
      ],
      "properties": {
        "red": {
          "type": "number",
          "minimum": 0,
          "maximum": 1,
          "description": "The amount of red in the color as a value in the interval [0, 1]"
        },
        "green": {
          "type": "number",
          "minimum": 0,
          "maximum": 1,
          "description": "The amount of green in the color as a value in the interval [0, 1]"
        },
        "blue": {
          "type": "number",
          "minimum": 0,
          "maximum": 1,
          "description": "The amount of blue in the color as a value in the interval [0, 1]"
        },
        "alpha": {
          "type": "number",
          "minimum": 0,
          "maximum": 1,
          "description": "The alpha value of the color as a value in the interval [0, 1]. 1 is sloid color and 0 is transparent"
        }
      }
    },
    "cardHeader": {
      "$id": "/properties/cardHeader",
      "type": "object",
      "description": "Optional header in the card.",
      "required": [
        "title"
      ],
      "properties": {
        "title": {
          "type": "string",
          "description": "Required title in the header."
        },
        "subtitle": {
          "type": "string",
          "description": "Optional - renders beneath the title. If not specified, title will take up both lines."
        },
        "imageUrl": {
          "type": "string",
          "description": "Optional - renders an image on the right of the title."
        },
        "imageType": {
          "type": "string",
          "enum": [
            "SQUARE",
            "CIRCLE"
          ],
          "description": "Define the cropping of the image in the header."
        },
        "imageAltText": {
          "type": "string",
          "description": "The Alternative text of this image"
        }
      }
    },
    "cardAction": {
      "$id": "/properties/cardAction",
      "description": "A Card action is the action associated with the card.",
      "properties": {
        "actionLabel": {
          "type": "string",
          "description": "The label used to be displayed in the action menu item."
        },
        "onClick": {
          "type": "object",
          "description": "The onClick action for this action item.",
          "$ref": "#/definitions/onClick"
        }
      }
    },
    "cardFixedFooter": {
      "$id": "/properties/cardFixedFooter",
      "description": "A persistent (sticky) footer that is added to the bottom of the card.",
      "properties": {
        "primaryButton": {
          "type": "object",
          "description": "The Primary button of the fixed footer.",
          "$ref": "#/definitions/button"
        },
        "secondaryButton": {
          "type": "object",
          "description": "The Secondary button of the fixed footer.",
          "$ref": "#/definitions/button"
        }
      }
    },
    "card": {
      "$id": "/properties/card",
      "type": "object",
      "required": [
        "sections"
      ],
      "properties": {
        "header": {
          "type": "object",
          "description": "The Header of the card.",
          "$ref": "#/definitions/cardHeader"
        },
        "sections": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/section"
          },
          "description": "A card consist of 1 or more sections. Widgets are defined within a section."
        },
        "cardActions": {
          "type": "object",
          "description": "The actions of this card.",
          "$ref": "#/definitions/cardAction"
        },
        "name": {
          "type": "string",
          "description": "Name of the card which is used as an identifier for the card in the card navigation."
        },
        "fixedFooter": {
          "type": "object",
          "description": "The fixed footer that is shown at the bottom of this card.",
          "$ref": "#/definitions/cardFixedFooter"
        },
        "displayStyle": {
          "type": "string",
          "description": "The Display Style for the peekCardHeader.",
          "enum": [
            "DISPLAY_STYLE_UNSPECIFIED",
            "PEEK",
            "REPLACE"
          ]
        },
        "peekCardHeader": {
          "type": "object",
          "description": "When displaying contextual content, the peek card header acts as a placeholder so that the user can\nnavigate forward between the homepage cards and the contextual cards.",
          "$ref": "#/definitions/cardHeader"
        }
      }
    },
    "action": {
      "$id": "/properties/action",
      "type": "object",
      "description": "An action that describes the behavior when a form is submitted - triggered from an onclick event on an input widget (e.g. button).",
      "required": [
        "function"
      ],
      "properties": {
        "function": {
          "description": "The apps script callback function or the https endpoint if using alternate runtimes.",
          "type": "string"
        }
      }
    }
  },
  "type": "object",
  "$ref": "#/definitions/card"
}

แอปค่าใช้จ่าย

{
  "action": {
    "navigations": [
      {
        "pushCard": {
          "sections": [
            {
              "header": "Budget Performance",
              "widgets": [
                {
                  "decoratedText": {
                    "text": "Current Quarter
Budget $18,000 (Ends in 5 days)
Spent: $410.75
", "wrapText": true } }, { "decoratedText": { "text": "Top Expense Category" } }, { "decoratedText": { "text": "Flights · 30%", "icon": { "iconUrl" : "http://ssl.gstatic.com/travel-trips-fe/icon_flight_grey_64.png" } } }, { "decoratedText": { "text": "Hotels · 50%", "icon": { "iconUrl" : "http://ssl.gstatic.com/travel-trips-fe/icon_hotel_grey_64.png" } } } ] }, { "header": "Expense Awaiting Your Approval", "widgets": [ { "decoratedText": { "text": "Submitted by Pam Bee", "icon": { "iconUrl" : "https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcQDQGRxqHJ2XZenPL496tC1EkP2b8wtvENQ4QIClnde2Hq1C7u3" } } }, { "decoratedText": { "text": "Team Lunch (Internal)
Cost: $85.00 USD
Date: 10/16/2019
Expense no. #7453" } }, { "buttonList": { "buttons": [ { "text": "Approve", "color": { "red": 0, "green": 0.4784, "blue": 0.353 }, "onClick": { "openLink": { "url": "https://www.domain.com/approve" } } }, { "text": "Decline", "color": { "red": 1, "green": 0.07843, "blue": 0.07843 }, "onClick": { "openLink": { "url": "https://www.domain.com/decline" } } }, { "text": "View Details", "color": { "red": 0.650, "green": 0.650, "blue": 0.650 }, "onClick": { "openLink": { "url": "https://www.domain.com/view" } } } ] } } ] }, { "widgets": [ { "decoratedText": { "text": "Submitted by Dwight Smith", "icon": { "iconUrl" : "https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcQDQGRxqHJ2XZenPL496tC1EkP2b8wtvENQ4QIClnde2Hq1C7u3" } } }, { "decoratedText": { "text": "Flight to New York
Cost: 530.00 USD
Date: 11/21/2019
Expense no. #9866" } }, { "buttonList": { "buttons": [ { "text": "Approve", "color": { "red": 0, "green": 0.4784, "blue": 0.353 }, "onClick": { "openLink": { "url": "https://www.domain.com/approve" } } }, { "text": "Decline", "color": { "red": 1, "green": 0.07843, "blue": 0.07843 }, "onClick": { "openLink": { "url": "https://www.domain.com/decline" } } }, { "text": "View Details", "color": { "red": 0.650, "green": 0.650, "blue": 0.650 }, "onClick": { "openLink": { "url": "https://www.domain.com/view" } } } ] } } ] } ] } } ] } }

ส่งแบบฟอร์ม

/**
 * A sample Google Workspace Add-on with a form submit with a happy/sad button.
 */
exports.homepage = (req, res) => {
  console.log("event: ", req.body);
  console.log("headers: ",JSON.stringify(req.headers));
  let parameters = req.body.commonEventObject.parameters;
  if (parameters) {
    let happy = parameters.happy;
    if (happy == '1') {
      res.status(200).send(createHappyCard());
    } else {
      res.status(200).send(createSadCard());
    }
  } else {
    res.status(200).send(createQuestionCard());
  }
};

function createSadCard() {
  return {
    "renderActions": {
      "action": {
        "navigations": [
          {
            "pushCard": {
              "sections": [
                {
                  "widgets": [
                    {
                      "image": {
                        "imageUrl": "https://cdn.pixabay.com/photo/2017/08/15/12/58/emoticon-2643814_960_720.jpg"
                      }
                    }
                  ]
                }
              ]
            }
          }
        ]
      }
    }
  };
}

function createHappyCard() {
  return {
    "renderActions": {
      "action": {
        "navigations": [
          {
            "pushCard": {
              "sections": [
                {
                  "widgets": [
                    {
                      "image": {
                        "imageUrl": "https://dg.imgix.net/do-you-think-you-re-happy-jgdbfiey-en/landscape/do-you-think-you-re-happy-jgdbfiey-9bb0198eeccd0a3c3c13aed064e2e2b3.jpg"
                      }
                    }
                  ]
                }
              ]
            }
          }
        ]
      }
    }
  };
}

function createQuestionCard() {
  return {
    "action": {
      "navigations": [
        {
          "pushCard": {
            "sections": [
              {
                "widgets": [
                  {
                    "textParagraph": {
                      "text": "Are you having a good day today?"
                    }
                  },
                  {
                    "buttonList": {
                      "buttons": [
                        {
                          "text": "Happy",
                          "color": {
                            "red": 0,
                            "green": 0.4784,
                            "blue": 0.353
                          },
                          "onClick": {
                            "action": {
                              "function": "https://us-central1-elevated-surge-267316.cloudfunctions.net/HttpGSAO",
                              "parameters": [
                                {
                                  "key": "happy",
                                  "value": "1"
                                }
                              ]
                            }
                          }
                        },
                        {
                          "text": "Sad",
                          "color": {
                            "red": 1,
                            "green": 0.07843,
                            "blue": 0.07843
                          },
                          "onClick": {
                            "action": {
                              "function": "https://us-central1-elevated-surge-267316.cloudfunctions.net/HttpGSAO",
                              "parameters": [
                                {
                                  "key": "happy",
                                  "value": "0"
                                }
                              ]
                            }
                          }
                        }
                      ]
                    }
                  }
                ]
              }
            ]
          }
        }
      ]
    }
  };
}

การอนุมัติ

{
  "action": {
    "navigations": [
      {
        "pushCard": {
          "sections": [
            {
              "widgets": [
                {
                  "textParagraph": {
                    "text": "You have a new request:"
                  }
                },
                {
                  "textParagraph": {
                    "text":
                      "John Dolittle - New Device Request"
                  }
                },
                {
                  "decoratedText": {
                    "topLabel": "Type:",
                    "text": "Computer (laptop)"
                  }
                },
                {
                  "decoratedText": {
                    "topLabel": "When:",
                    "text": "Submitted Aug 10"
                  }
                },
                {
                  "decoratedText": {
                    "topLabel": "Reason:",
                    "text": "Keyboard is not working"
                  }
                },
                {
                  "decoratedText": {
                    "topLabel": "Specs:",
                    "text": "Cheetah Pro 15"
                  }
                },
                {
                  "buttonList": {
                    "buttons": [
                      {
                        "text": "Approve",
                        "color": {
                          "red": 0,
                          "green": 0.4784,
                          "blue": 0.353
                        },
                        "onClick": {
                          "openLink": {
                            "url": "https://www.domain.com/approve"
                          }
                        }
                      },
                      {
                        "text": "Deny",
                        "color": {
                          "red": 1,
                          "green": 0.07843,
                          "blue": 0.07843
                        },
                        "onClick": {
                          "openLink": {
                            "url": "https://www.domain.com/deny"
                          }
                        }
                      }
                    ]
                  }
                }
              ]
            }
          ]
        }
      }
    ]
  }
}

ข้อมูลรายชื่อติดต่อ

/**
 * A sample Google Workspace Add-on that creates a top level card with a list of
 * contacts. Clicking on a contact will navigate (client side) to a full contact
 * card.
 */
exports.homepage = (req, res) => {
  res.status(200).send(createListCard());
};

function createContactCard(name, title, email, phone, location) {
  return {
    "header": {
      "imageType": "CIRCLE",
      "imageUrl": "https://ssl.gstatic.com/images/branding/product/1x/avatar_square_blue_512dp.png",
      "title": name,
      "subtitle": title
    },
    "sections": [
      {
        "widgets": [
          {
            "decoratedText": {
              "topLabel": "Email:",
              "text": email
            }
          },
          {
            "decoratedText": {
              "topLabel": "Phone Number:",
              "text": phone
            }
          },
          {
            "decoratedText": {
              "topLabel": "Location:",
              "text": location
            }
          }
        ]
      }
    ]
  };
}

function createContactListEntry(name, title, email, phone, location) {
  return {
    "decoratedText": {
      "topLabel": title,
      "text": name,
      "onClick": {
        "card": createContactCard(name, title, email, phone, location)
      },
      "icon": {
        "iconUrl": "https://ssl.gstatic.com/images/branding/product/1x/avatar_square_blue_512dp.png"
      }
    }
  };
}

function createListCard() {
  var LIST1 = createContactListEntry("John Dolittle", "President", "john@gmail.com", "800-555-0100", "Markham, ON");
  var LIST2 = createContactListEntry("Huckleberry Finn", "CFO", "huck@gmail.com", "800-555-0111", "Kingston, ON");
  var LIST3 = createContactListEntry("Grace Harlowe", "Senior Director", "grace@gmail.com", "800-555-0122", "Toronto, ON");
  return {
    "action": {
      "navigations": [
        {
          "pushCard": {
            "sections": [
              {
                "widgets": [
                  LIST1,
                  LIST2,
                  LIST3
                ]
              }
            ]
          }
        }
      ]
    }
  };
}

การให้สิทธิ์บุคคลที่สาม

โปรดดูข้อมูลเกี่ยวกับการให้สิทธิ์บุคคลที่สามที่หัวข้อเชื่อมต่อส่วนเสริม Google Workspace กับบริการของบุคคลที่สาม

{
  "custom_authorization_prompt": {
    "action": {
      "navigations": [
        {
          "pushCard": {
            "sections": [
              {
                "widgets": [
                  {
                    "image": {
                      "imageUrl": "https://www.example.com/images/logo",
                      "altText": "Example organization logo"
                    }
                  },
                  {
                    "divider": {}
                  },
                  {
                    "textParagraph": {
                      "text": "Sign in to get started."
                    }
                  },
                  {
                    "buttonList": {
                      "buttons": [
                        {
                          "text": "Sign in",
                          "onClick": {
                            "openLink": {
                              "url": "https://www.example.com/auth",
                              "onClose": "RELOAD",
                              "openAs": "OVERLAY"
                            }
                          },
                          "color": {
                            "red": 0,
                            "green": 0,
                            "blue": 1,
                            "alpha": 1,
                          }
                        }
                      ]
                    }
                  },
                  {
                    "textParagraph": {
                      "text": "If you don't have an account, <a href=\"https://www.example.com/signup\">sign up</a> here."
                    }
                  }
                ]
              }
            ]
          }
        }
      ]
    }
  }
}

วิดเจ็ต JSON

วิดเจ็ตทั่วไป

{
  "$schema": "/Users/dummy_user/Documents/JSON_schema/renderActionSchema.json",
  "action": {
    "navigations": [
      {
        "pushCard": {
          "header": {
            "title": "Main Card"
          },
          "name": "Main Card",
          "peekCardHeader": {
            "title": "This is a peek card",
            "imageType": "SQUARE",
            "imageUrl": "http://ssl.gstatic.com/travel-trips-fe/icon_hotel_grey_64.png",
            "imageAltText": "Image of Cards",
            "subtitle": "No Subtitle"
          },
          "cardActions": [
            {
              "actionLabel": "This is Card action - 1",
              "onClick": {
                "openDynamicLinkAction": {
                  "function": "https://dummy-function-from-resources.net/openLinkCallback"
                }
              }
            },
            {
              "actionLabel": "This is Card action - 2",
              "onClick": {
                "action": {
                  "function": "https://dummy-function-from-resources.net/generic_submit_form_response"
                }
              }
            },
            {
              "actionLabel": "This is Card action - 3",
              "onClick": {
                "openLink": {
                  "onClose": "RELOAD",
                  "openAs": "OVERLAY",
                  "url": "https://dummy-function-from-resources.net/open_link_sample"
                }
              }
            },
            {
              "actionLabel": "This is Card action - 4",
              "onClick": {
                "card": {
                  "header": {
                    "title": "This card is shown after card action 4 is clicked"
                  },
                  "sections": [
                    {
                      "widgets": [
                        {
                          "textParagraph": {
                            "text": "This is a sample text for the card that's shown after action 4 of the card is clicked"
                          }
                        }
                      ]
                    }
                  ]
                }
              }
            }
          ],
          "fixedFooter": {
            "primaryButton": {
              "text": "Primary Button",
              "color": {
                "red": 0,
                "blue": 0,
                "green": 0
              },
              "onClick": {
                "openLink": {
                  "url": "www.google.ca",
                  "onClose": "NOTHING",
                  "openAs": "FULL_SIZE"
                }
              }
            },
            "secondaryButton": {
              "text": "Secondary Button - Disabled",
              "disabled": true,
              "color": {
                "red": 0.32421,
                "blue": 0.23421,
                "green": 0.2353614
              },
              "onClick": {
                "openLink": {
                  "url": "www.google.com",
                  "onClose": "NOTHING",
                  "openAs": "FULL_SIZE"
                }
              }
            }
          },
          "sections": [
            {
              "header": "Section 1 - Date Time",
              "collapsible": true,
              "widgets": [
                {
                  "dateTimePicker": {
                    "name": "Date Time Picker - EST",
                    "label": "Date Time Picker - EST",
                    "valueMsEpoch": 1585166673000,
                    "onChangeAction": {
                      "function": "https://dummy-function-from-resources.net/sample_notification"
                    },
                    "timezoneOffsetDate": -240,
                    "type": "DATE_AND_TIME"
                  }
                },
                {
                  "dateTimePicker": {
                    "name": "Date Picker - CST",
                    "label": "Date Time Picker - CST",
                    "valueMsEpoch": 1585166673000,
                    "onChangeAction": {
                      "function": "https://dummy-function-from-resources.net/sample_notification"
                    },
                    "timezoneOffsetDate": -300,
                    "type": "DATE_AND_TIME"
                  }
                },
                {
                  "dateTimePicker": {
                    "name": "Date Time Picker - PST",
                    "label": "Date Time Picker - PST",
                    "valueMsEpoch": 1585166673000,
                    "onChangeAction": {
                      "function": "https://dummy-function-from-resources.net/sample_notification"
                    },
                    "timezoneOffsetDate": -420,
                    "type": "DATE_AND_TIME"
                  }
                }
              ]
            },
            {
              "header": "Section 2 - Decorated Text",
              "collapsible": true,
              "uncollapsibleWidgetsCount": 2,
              "widgets": [
                {
                  "decoratedText": {
                    "topLabel": "Top Label - Decorated Text CHECKBOX",
                    "switchControl": {
                      "controlType": "CHECKBOX",
                      "name": "Name - Check Box Sample",
                      "value": "Value - Check Box Sample"
                    },
                    "text": "Text - Decorated Text",
                    "bottomLabel": "Bottom Label - Decorated Text CHECKBOX",
                    "wrapText": false,
                    "onClick": {
                      "card": {
                        "header": {
                          "title": "Decorated Text - On Click Action Card"
                        },
                        "sections": [
                          {
                            "widgets": [
                              {
                                "image": {
                                  "imageUrl": "https://cataas.com/cat/says/hello%20world!",
                                  "altText": "Hello World - Cat Image"
                                }
                              }
                            ]
                          }
                        ]
                      }
                    }
                  }
                },
                {
                  "decoratedText": {
                    "topLabel": "Top Label - Decorated Text SWITCH",
                    "switchControl": {
                      "controlType": "SWITCH",
                      "name": "Name - SWITCH Sample",
                      "value": "Value - SWITCH Sample"
                    },
                    "text": "Text - Decorated Text",
                    "bottomLabel": "Bottom Label - Decorated Text SWITCH",
                    "wrapText": false,
                    "onClick": {
                      "card": {
                        "header": {
                          "title": "Decorated Text - On Click Action Card"
                        },
                        "sections": [
                          {
                            "widgets": [
                              {
                                "image": {
                                  "imageUrl": "https://cataas.com/cat/says/hello%20world!",
                                  "altText": "Hello World - Cat Image",
                                  "onClick": {
                                    "action": {
                                      "function": "https://dummy-function-from-resources.net/pop_to_root"
                                    }
                                  }
                                }
                              }
                            ]
                          }
                        ]
                      }
                    }
                  }
                },
                {
                  "decoratedText": {
                    "topLabel": "Top Label - Decorated Text Button",
                    "bottomLabel": "Bottom Label - Decorated Text Button",
                    "text": "Text - Decorated Text Button",
                    "button": {
                      "icon": {
                        "altText": "Assessment Blue",
                        "icon_url": "http://ssl.gstatic.com/travel-trips-fe/icon_hotel_grey_64.png"
                      },
                      "text": "Assessment Blue",
                      "onClick": {
                        "openLink": {
                          "url": "http://ssl.gstatic.com/travel-trips-fe/icon_hotel_grey_64.png",
                          "openAs": "OVERLAY",
                          "onClose": "RELOAD"
                        }
                      }
                    }
                  }
                },
                {
                  "decoratedText": {
                    "topLabel": "Top Label - Decorated Text CHECKBOX",
                    "switchControl": {
                      "controlType": "CHECKBOX",
                      "name": "Name - Check Box Sample",
                      "value": "Value - Check Box Sample"
                    },
                    "text": "Text - Decorated Text",
                    "bottomLabel": "Bottom Label - Decorated Text CHECKBOX",
                    "wrapText": false,
                    "onClick": {
                      "card": {
                        "header": {
                          "title": "Decorated Text - On Click Action Card"
                        },
                        "sections": [
                          {
                            "widgets": [
                              {
                                "image": {
                                  "imageUrl": "https://cataas.com/cat/says/hello%20world!",
                                  "altText": "Hello World - Cat Image"
                                }
                              }
                            ]
                          }
                        ]
                      }
                    }
                  }
                },
                {
                  "decoratedText": {
                    "topLabel": "Top Label - Decorated Text Icon",
                    "bottomLabel": "Bottom Label - Decorated Text Icon",
                    "text": "Text - Decorated Text Icon",
                    "icon": {
                      "iconUrl": "http://ssl.gstatic.com/travel-trips-fe/icon_hotel_grey_64.png",
                      "altText": "Arrow Right Blue"
                    }
                  }
                },
                {
                  "decoratedText": {
                    "topLabel": "Top Label - Decorated Text Wrap",
                    "bottomLabel": "Bottom Label - Decorated Text Wrap",
                    "text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam fringilla facilisis ne.",
                    "wrapText": true
                  }
                },
                {
                  "decoratedText": {
                    "topLabel": "Top Label - Decorated Text Non-Wrap",
                    "bottomLabel": "Bottom Label - Decorated Text Non-Wrap",
                    "text": "Nunc ultrices massa ut nisl porttitor, ut euismod nisl tincidunt. Vivamus pharetra, est sed sagittis consequat, arcu nisi.",
                    "wrapText": false
                  }
                }
              ]
            },
            {
              "header": "Section 3 - Button List",
              "collapsible": true,
              "widgets": [
                {
                  "buttonList": {
                    "buttons": [
                      {
                        "icon": {
                          "iconUrl": "http://ssl.gstatic.com/travel-trips-fe/icon_hotel_grey_64.png",
                          "altText": "G - Button"
                        },
                        "color": {
                          "red": 0,
                          "blue": 0,
                          "green": 1
                        },
                        "disabled": false,
                        "onClick": {
                          "openLink": {
                            "url": "www.google.ca/"
                          }
                        },
                        "text": "Green - Google.ca"
                      },
                      {
                        "color": {
                          "red": 1,
                          "blue": 0,
                          "green": 0
                        },
                        "disabled": false,
                        "onClick": {
                          "action": {
                            "function": "https://dummy-function-from-resources.net/pop_to_card_2"
                          }
                        },
                        "text": "Pop to Card 2"
                      },
                      {
                        "color": {
                          "red": 0,
                          "blue": 1,
                          "green": 0
                        },
                        "disabled": false,
                        "onClick": {
                          "openLink": {
                            "url": "www.google.ca/"
                          }
                        },
                        "text": "Blue - Google"
                      },
                      {
                        "color": {
                          "red": 1,
                          "blue": 1,
                          "green": 1
                        },
                        "disabled": true,
                        "onClick": {
                          "openLink": {
                            "url": "www.google.ca/"
                          }

                        },
                        "text": "Disabled Button"
                      }
                    ]
                  }
                }
              ]
            },
            {
              "header": "Section 4 - Images",
              "collapsible": true,
              "widgets": [
                {
                  "image": {
                    "imageUrl": "http://ssl.gstatic.com/travel-trips-fe/icon_hotel_grey_64.png",
                    "onClick": {
                      "openLink": {
                        "url": "http://ssl.gstatic.com/travel-trips-fe/icon_hotel_grey_64.png",
                        "openAs": "FULL_SIZE",
                        "onClose": "NOTHING"
                      }
                    }
                  }
                },
                {
                  "image": {
                    "imageUrl": "http://ssl.gstatic.com/travel-trips-fe/icon_hotel_grey_64.png",
                    "altText": "Commute - Black",
                    "onClick": {
                      "openLink": {
                        "url": "http://ssl.gstatic.com/travel-trips-fe/icon_hotel_grey_64.png",
                        "openAs": "FULL_SIZE",
                        "onClose": "RELOAD"
                      }
                    }
                  }
                }
              ]
            },
            {
              "header": "Section 5 - Text Paragraph",
              "collapsible": true,
              "widgets": [
                {
                  "textParagraph": {
                    "text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam fringilla facilisis neque, condimentum egestas dolor dapibus id."
                  }
                }
              ]
            },
            {
              "header": "Section 6 - Selection Input",
              "collapsible": true,
              "widgets": [
                {
                  "selectionInput": {
                    "name": "Selection Input Check box",
                    "label": "Selection Input Check box",
                    "type": "CHECK_BOX",
                    "items": [
                      {
                        "text": "Selection Input item 1 Text",
                        "value": "Selection Input item 1 Value"
                      },
                      {
                        "text": "Selection Input item 2 Text",
                        "value": "Selection Input item 2 Value"
                      }
                    ]
                  }
                },
                {
                  "selectionInput": {
                    "name": "Selection Input Dropdown",
                    "label": "Selection Input Dropdown",
                    "type": "DROPDOWN",
                    "items": [
                      {
                        "text": "Selection Input item 1 Text",
                        "value": "Selection Input item 1 Value"
                      },
                      {
                        "text": "Selection Input item 2 Text",
                        "value": "Selection Input item 2 Value"
                      }
                    ]
                  }
                },
                {
                  "selectionInput": {
                    "name": "Selection Input Radio",
                    "label": "Selection Input Radio",
                    "type": "RADIO_BUTTON",
                    "items": [
                      {
                        "text": "Selection Input item 1 Text",
                        "value": "Selection Input item 1 Value"
                      },
                      {
                        "text": "Selection Input item 2 Text",
                        "value": "Selection Input item 2 Value"
                      }
                    ]
                  }
                },
                {
                  "selectionInput": {
                    "name": "Selection Input Switch",
                    "label": "Selection Input Switch",
                    "type": "SWITCH",
                    "items": [
                      {
                        "text": "Selection Input item 1 Text",
                        "value": "Selection Input item 1 Value"
                      },
                      {
                        "text": "Selection Input item 2 Text",
                        "value": "Selection Input item 2 Value"
                      }
                    ]
                  }
                }
              ]
            }
          ]
        }
      }
    ]
  }
}

แสดงการแจ้งเตือน

{
  "$schema": "/Users/dummy_user/Documents/JSON_schema/submit_form_response_schema.json",
  "renderActions": {
    "action": {
      "notification": {
        "text": "This is a sample notification"
      }
    }
  }
}

เลื่อนไปที่การ์ดรูท

{
  "$schema": "/Users/dummy_user/Documents/JSON_schema/submit_form_response_schema.json",
  "renderActions": {
    "action": {
      "navigations": [
        {
          "popToRoot": true
        }
      ]
    }
  }
}

ไปยังบัตรที่ต้องการ

{
  "$schema": "/Users/dummy_user/Documents/JSON_schema/submit_form_response_schema.json",
  "render_actions": {
    "action": {
      "navigations": [
        {
          "popToCard": "card_2"
        }
      ]
    }
  }
}
{
  "$schema": "/Users/dummy_user/Documents/JSON_schema/render_action_schema.json",
  "action": {
    "navigations": [
      {
        "pushCard": {
          "header": {
            "title": "Open Link Test Case - HTTP"
          },
          "sections": [
            {
              "widgets": [
                {
                  "textParagraph": {
                    "text": "Verify a link is opened in a new tab. When returned to Gmail, the bolded text should say AFTER.

\nText BEFORE opening the link." } }, { "buttonList": { "buttons": [ { "text": "Open tab, close, refresh", "onClick": { "openLink": { "url": "https://www.google.ca/", "onClose": "RELOAD", "openAs": "OVERLAY" } } } ] } } ] } ] } } ] } }

การตอบกลับการส่งแบบฟอร์ม

{
  "$schema": "/Users/dummy_user/Documents/JSON_schema/submit_form_response_schema.json",
  "stateChanged": true,
  "renderActions": {
    "action": {
      "navigations": [
        {
          "pushCard": {
            "peekCardHeader": {
              "title": "Peek Card"
            },
            "header": {
              "title": "Generic Submit Form Response Card"
            },
            "sections": [
              {
                "widgets": [
                  {
                    "image": {
                      "imageUrl": "https://cataas.com/cat"
                    }
                  }
                ]
              }
            ]
          }
        }
      ]
    }
  }
}

GRid

{
  "$schema": "/Users/dummy_user/Documents/JSON_schema/render_action_schema.json",
  "action": {
    "navigations": [
      {
        "pushCard": {
          "header": {
            "title": "Main Card"
          },
          "sections": [
            {
              "header": "Grid Widget",
              "widgets": [
                {
                  "grid": {
                    "title": "A fine collection of cats",
                    "borderStyle": {
                      "type": "STROKE",
                      "cornerRadius": 5.0
                    },
                    "columnCount": 2,
                    "items": [
                      {
                        "id": "itemA",
                        "image": {
                          "imageUri": "https://cataas.com/cat?0.001",
                          "cropStyle": {
                            "type": "CIRCLE"
                          }
                        },
                        "title": "First cat"
                      },
                      {
                        "id": "itemB",
                        "image": {
                          "imageUri": "https://cataas.com/cat?0.002",
                          "cropStyle": {
                            "type": "CIRCLE"
                          }
                        },
                        "title": "Second cat",
                        "subtitle": "Top rated"
                      },
                      {
                        "id": "itemC",
                        "image": {
                          "imageUri": "https://cataas.com/cat?0.003",
                          "cropStyle": {
                            "type": "CIRCLE"
                          }
                        },
                        "title": "Third cat"
                      },
                      {
                        "id": "itemD",
                        "image": {
                          "imageUri": "https://cataas.com/cat?0.004",
                          "cropStyle": {
                            "type": "CIRCLE"
                          }
                        },
                        "title": "Fourth cat",
                      },
                      {
                        "id": "itemE",
                        "image": {
                          "imageUri": "https://cataas.com/cat?0.005",
                          "cropStyle": {
                            "type": "CIRCLE"
                          }
                        },
                        "title": "Fifth cat",
                        "subtitle": "Top rated"
                      },
                      {
                        "id": "itemF",
                        "image": {
                          "imageUri": "https://cataas.com/cat?0.006",
                          "cropStyle": {
                            "type": "CIRCLE"
                          }
                        },
                        "title": "Sixth cat"
                      }
                    ],
                    "onClick": {
                      "action": {
                        "function": "https://dummy-function-from-resources.net/grid_item_clicked",
                        "parameters": [
                          {
                            "key": "datasource",
                            "value": "Favorite cat pics"
                          }
                        ]
                      }
                    }
                  }
                }
              ]
            }
          ]
        }
      }
    ]
  }
}

ออบเจ็กต์เหตุการณ์ JSON

ทั่วไป (Gmail, ปฏิทิน, ไดรฟ์ และเครื่องมือแก้ไข)

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type":"object",
  "definitions": {
    "eventObject": {
      "$id": "/properties/eventObject",
      "type":"object",
      "description": "Event objects are JSON structures that are automatically constructed and passed as parameters to trigger or callback functions when a user interacts with an add-on (https://developers.google.com/workspace/add-ons/concepts/event-objects)",
      "properties": {
        "commonEventObject": {
          "$ref": "#/definitions/commonEventObject"
        },
        "authorizationEventObject": {
          "$ref": "#/definitions/authorizationEventObject",
          "description": "Set for requests to HTTP endpoints"
        },
        "gmail": {
          "$ref": "./gmail_event_object_schema.json#/definitions/gmailEventObject",
          "description": "An object containing Gmail information."
        },
        "drive": {
          "$ref": "./drive_event_object_schema.json#/definitions/driveEventObject",
          "description": "An object containing Drive information."
        },
        "docs": {
          "$ref": "./docs_event_object_schema.json#/definitions/docsEventObject",
          "description": "An object containing Docs information."
        },
        "sheets": {
          "$ref": "./sheets_event_object_schema.json#/definitions/sheetsEventObject",
          "description": "An object containing Sheets information."
        },
        "slides": {
          "$ref": "./slides_event_object_schema.json#/definitions/slidesEventObject",
          "description": "An object containing Slides information."
        },
        "calendar": {
          "$ref": "./calendar_event_object_schema.json#/definitions/calendarEventObject",
          "description": "An object containing calendar and event information."
        }
      }
    },
    "commonEventObject": {
      "$id": "/properties/commonEventObject",
      "type":"object",
      "description": "An object containing information common to all event objects, regardless of the host application.",
      "properties": {
        "userLocale": {
          "type": "string",
          "description": "The user's language and country/region identifier in the format of ISO 639 language code-ISO 3166 country/region code. For example, en-US."
        },
        "hostApp": {
          "type": "string",
          "description": "Indicates the host app the add-on is active in when the event object is generated. Possible values include the following:\nGMAIL\nCALENDAR\nDRIVE",
          "enum": ["GMAIL", "DRIVE", "CALENDAR"]
        },
        "platform": {
          "type": "string",
          "description": "Indicates where the event originates (`WEB`, `IOS`, or `ANDROID`)",
          "enum": ["WEB", "ANDRIOD", "IOS"]
        },
        "timeZone": {
          "type": "object",
          "$ref": "#/definitions/timeZone",
          "description": "The timezone ID and offset. To enable this field, you must set `addOns.common.useLocaleFromApp` to `true` in your add-on's manifest. Your add-on's scope list must also include `https://www.googleapis.com/auth/script.locale`\n See https://developers.google.com/workspace/add-ons/how-tos/access-user-locale for more details"
        },
        "formInputs": {
          "type": "object",
          "description": "A map containing the current values of the widgets in the displayed card. The map keys are the string IDs assigned with each widget, and each value is another wrapper object with a single \"\" key.",
          "additionalProperties": {
            "type":"object",
            "properties": {
              "stringInputs": {
                "$ref": "#/definitions/stringInputs"
              },
              "dateTimeInput": {
                "$ref": "#/definitions/dateTimeInput"
              },
              "dateInput": {
                "$ref": "#/definitions/dateInput"
              },
              "timeInput": {
                "$ref": "#/definitions/timeInput"
              }
            }
          }
        },
        "parameters": {
          "type": "object",
          "description": "Any additional parameters.",
          "additionalProperties": {
            "type": "string"
          }
        }
      }
    },
    "authorizationEventObject": {
      "type": "object",
      "properties": {
        "userOAuthToken": {
          "description": "The end user OAuth access token, authorized with the requested scopes",
          "type": "string"
        },
        "userIdToken": {
          "type": "string",
          "description": "An end-user ID token, if appropriate ID scopes are requested"
        },
        "systemIdToken": {
          "type": "string",
          "description": "An ID token for the Google Workspace Add-ons service account for this deployment"
        }
      }
    },
    "timeZone": {
      "$id": "/properties/timeZone",
      "type":"object",
      "properties": {
        "id": {
          "type":"string",
          "description": "The timezone identifier of the user's timezone. Examples include: America/New_York, Europe/Vienna, and Asia/Seoul. To enable this field, you must set `addOns.common.useLocaleFromApp` to `true` in your add-on's manifest. Your add-on's scope list must also include `https://www.googleapis.com/auth/script.locale`. See https://developers.google.com/workspace/add-ons/how-tos/access-user-locale for more details"
        },
        "offset": {
          "type": "integer",
          "description": "The time offset from Coordinated Universal Time (UTC) of the user's timezone, measured in milliseconds. See https://developers.google.com/workspace/add-ons/how-tos/access-user-locale for more details",
          "minimum": -2147483648,
          "maximum": 2147483647
        }
      }
    },
    "stringInputs": {
      "$id": "/properties/stringInputs",
      "type":"object",
      "description": "Input parameter for regular widgets.\nFor single-valued widgets, it will be a single value list; for\nmulti-valued widgets, such as checkbox, all the values are presented.",
      "properties": {
        "value": {
          "type":"array",
          "items": {
            "type":"string"
          }
        }
      }
    },
    "dateTimeInput": {
      "$id": "/properties/dateTimeInput",
      "type": "object",
      "description": "Input Parameter for Date and Time Picker widget.",
      "properties": {
        "msSinceEpoch": {
          "type": "integer",
          "description": "The time selected by the user, in milliseconds since epoch (00:00:00 UTC on 1 January 1970).",
          "minimum": -9223372036854775808,
          "maximum": 9223372036854775807
        },
        "hasDate": {
          "type": "boolean",
          "description": "true if the input date time includes a date; if false only a time is included."
        },
        "hasTime": {
          "type": "boolean",
          "description": "true if the input date time includes a time; if false only a date is included."
        }
      }
    },
    "dateInput": {
      "$id": "/properties/dateInput",
      "type": "object",
      "description": "Input Parameter for Date Picker widget.",
      "properties": {
        "msSinceEpoch": {
          "type": "integer",
          "description": "The time selected by the user, in milliseconds since epoch (00:00:00 UTC on 1 January 1970).",
          "minimum": -9223372036854775808,
          "maximum": 9223372036854775807
        }
      }
    },
    "timeInput": {
      "description": "Input Parameter for Time Picker widget.",
      "$id": "/properties/timeInput",
      "type": "object",
      "properties": {
        "hours": {
          "type": "integer",
          "description": "The hour number selected by the user.",
          "minimum": 0,
          "maximum": 23
        },
        "minutes": {
          "type": "integer",
          "description": "The minute number selected by the user.",
          "minimum": 0,
          "maximum": 59
        }
      }
    }
  },
  "$ref": "#/definitions/eventObject"
}
  

Gmail

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "definitions": {
    "gmailEventObject": {
      "$id": "/properties/gmailEventObject",
      "type": "object",
      "description": "The Gmail event object is the portion of the overall event object that carries information about a user's Gmail messages. It's only present in an event object if the host application is Gmail.",
      "properties": {
        "messageId": {
          "type": "string",
          "description": "The ID of the currently open Gmail message."
        },
        "threadId": {
          "type": "string",
          "description": "The currently open Gmail thread ID."
        },
        "accessToken": {
          "description": "The Gmail-specific access token. You can use this token with the \"X-Goog-Gmail-Access-Token\" HTTP header to grant your add-on temporary access to a user's currently open Gmail message or let your add-on compose new drafts.",
          "type": "string"
        },
        "toRecipients": {
          "type":"array",
          "description": "The list of \"To:\" recipient email addresses currently included in a draft the add-on is composing",
          "items": {
            "type":"string"
          }
        },
        "ccRecipients": {
          "type":"array",
          "description": "The list of \"CC:\" recipient email addresses currently included in a draft the add-on is composing",
          "items": {
            "type":"string"
          }
        },
        "bccRecipients": {
          "type":"array",
          "description": "The list of \"BCC:\" recipient email addresses currently included in a draft the add-on is composing",
          "items": {
            "type":"string"
          }
        }
      }
    }
  },
  "$ref": "#/definitions/gmailEventObject"
}

ปฏิทิน

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "definitions": {
    "calendarEventObject": {
      "$id": "/properties/calendarEventObject",
      "description": "The Calendar event object is the portion of the overall event object that carries information about a user's calendar and calendar events. It's only present in an event object if the host application is Google Calendar.",
      "type":"object",
      "properties": {
        "id": {
          "type": "string",
          "description": "The event ID."
        },
        "recurringEventId": {
          "type": "string",
          "description": "The ID of a recurring event."
        },
        "calendarId": {
          "type": "string",
          "description": "The calendar ID."
        },
        "organizer": {
          "type": "object",
          "description": "An object representing the organizer of the event.",
          "properties": {
            "email": {
              "description": "The event organizer's email address.",
              "type": "string"
            }
          }
        },
        "attendees": {
          "type": "array",
          "description": "A list of the attendees of the calendar event.",
          "items": {
            "$ref": "#definitions/attendee"
          }
        },
        "conferenceData": {
          "type": "object",
          "description": "An object representing any conference data associated with this event, such as Google Meet conference details.",
          "$ref": "#definitions/conferenceData"
        },
        "capabilities": {
          "type": "object",
          "description": "An object describing the capabilities of the add-on to view or update event information.",
          "properties": {
            "canSeeAttendees": {
              "type": "boolean",
              "description": "true if the add-on can read the event attendee list; false otherwise."
            },
            "canAddAttendees": {
              "type": "boolean",
              "description": "true if the add-on can add new attendees to the event attendee list; false otherwise."
            },
            "canSeeConferenceData": {
              "type": "boolean",
              "description": "true if the add-on can read the event conference data; false otherwise."
            },
            "canSetConferenceData": {
              "type": "boolean",
              "description": "true if the add-on can update the event conference data; false otherwise."
            }
          }
        }
      }
    },
    "attendee": {
      "type": "object",
      "$id": "/properties/attendee",
      "properties": {
        "email": {
          "type": "string",
          "description": "The attendee email address."
        },
        "optional": {
          "type": "boolean",
          "description": "true if the attendance for this attendee is marked as optional; false otherwise."
        },
        "displayName": {
          "type": "string",
          "description": "The attendee displayed name."
        },
        "organizer": {
          "type": "boolean",
          "description": "true if the attendee is an organizer for this event."
        },
        "self": {
          "type": "boolean",
          "description": "true if this attendee represents the calendar in which this event appears; false otherwise."
        },
        "resource": {
          "type": "boolean",
          "description": "true if the attendee represents a resource, such as room or piece of equipment; false otherwise."
        },
        "responseStatus": {
          "type": "string",
          "description": "The attendee's response status. Possible values include the following:\naccepted: The attendee has accepted the event invitation.\ndeclined: The attendee has declined the event invitation.\nneedsAction: The attendee has not responded to the event invitation.\ntentative: The attendee has tentatively accepted the event invitation."
        },
        "comment": {
          "type": "string",
          "description": "The attendee's response comment, if any."
        },
        "additionalGuests": {
          "type": "integer",
          "description": "The number of additional guests the attendee had indicated they are bringing. Defaults to zero.",
          "default": 0,
          "minimum": 0,
          "maximum": 2147483647
        }
      }
    },
    "conferenceData": {
      "$id": "/properties/conferenceData",
      "type": "object",
      "properties": {
        "conferenceId": {
          "type": "string",
          "description": "The ID of the conference. This ID is meant to allow applications to keep track of conferences; you shouldn't display this ID to users."
        },
        "conferenceSolution": {
          "type": "object",
          "description": "An object representing the conference solution, such as Hangouts or Google Meet.",
          "$ref": "#/definitions/conferenceSolution"
        },
        "entryPoints": {
          "type": "array",
          "description": "The list of conference entry points, such as URLs or phone numbers.",
          "items": {
            "$ref": "#/definitions/entryPoint"
          }
        },
        "notes": {
          "type": "string",
          "description": "Additional notes (such as instructions from the domain administrator or legal notices) about the conference to display to the user. Can contain HTML. The maximum length is 2048 characters."
        },
        "parameters": {
          "type": "object",
          "$ref": "#/definitions/parameters",
          "description": "An object containing a map of defined parameter data for use by the add-on."
        }
      }
    },
    "conferenceSolution": {
      "type": "object",
      "description": "An object representing the conference solution, such as Hangouts or Google Meet.",
      "$id": "/properties/conferenceSolution",
      "properties": {
        "iconUri": {
          "type": "string",
          "description": "The URI for the user-visible icon representing this conference solution."
        },
        "key": {
          "type": "object",
          "description": "The key which uniquely identifies the conference solution for this event.",
          "properties": {
            "type": {
              "type": "string",
              "description": "The conference solution type. Possible values include the following:\neventHangout for Hangouts for consumers (http://hangouts.google.com).\neventNamedHangout for classic Hangouts for Google Workspace users (http://hangouts.google.com).\nhangoutsMeet for Google Meet (http://meet.google.com)."
            }
          }
        },
        "name": {
          "type":"string",
          "description": "The user-visible name of this conference solution (not localized)."
        }
      }
    },
    "entryPoint": {
      "$id": "/properties/entryPoint",
      "description": "Entry point objects carry information about the established means of accessing a given conference, such as by phone or video. This information is present in the event object if and only if the data is present in the Calendar event and the add-on sets its addOns.calendar.currentEventAccess manifest (https://developers.google.com/workspace/add-ons/concepts/manifests#calendar_fields) field to READ or READ_WRITE.",
      "properties": {
        "accessCode": {
          "type":"string",
          "description": "The access code used to access the conference. The maximum length is 128 characters. Conference providers typically only use a subset of {accessCode, meetingCode, passcode, password, pin} to provide access to conferences. Match and only ever display the fields the conference provider uses."
        },
        "entryPointFeatures": {
          "type":"array",
          "description": "Features of the entry point. Currently these features only apply to phone entry points:\ntoll: The entry point is a toll phone call.\ntoll_free: The entry point is a toll-free phone call.",
          "items": {
            "type": "string"
          }
        },
        "entryPointType": {
          "type":"string",
          "description": "The type of entry point. Possible values are the following:\nmore: Additional conference joining instructions, such as alternate phone numbers. A conference can only have one more entry point; if present at least one other type of entry point is also required.\nphone: Join the conference via a phone number. A conference can have zero or more phone entry points. Google Calendar only displays the first two phone entry points, after formatting and sorting alphabetically.\nsip: Join the conference over SIP. A conference can have at most one sip entry point.\nvideo: Join the conference over HTTP. A conference can have at most one video entry point."
        },
        "label": {
          "type":"string",
          "description": "The user-visible label for the entry point URI (not localized)."
        },
        "meetingCode": {
          "type":"string",
          "description": "The meeting code used to access the conference. The maximum length is 128 characters. Conference providers typically only use a subset of {accessCode, meetingCode, passcode, password, pin} to provide access to conferences. Match and only ever display the fields the conference provider uses."
        },
        "passcode": {
          "type":"string",
          "description": "The passcode used to access the conference. The maximum length is 128 characters. Conference providers typically only use a subset of {accessCode, meetingCode, passcode, password, pin} to provide access to conferences. Match and only ever display the fields the conference provider uses."
        },
        "password": {
          "type":"string",
          "description": "The password used to access the conference. The maximum length is 128 characters. Conference providers typically only use a subset of {accessCode, meetingCode, passcode, password, pin} to provide access to conferences. Match and only ever display the fields the conference provider uses."
        },
        "pin": {
          "type":"string",
          "description": "The PIN used to access the conference. The maximum length is 128 characters. Conference providers typically only use a subset of {accessCode, meetingCode, passcode, password, pin} to provide access to conferences. Match and only ever display the fields the conference provider uses."
        },
        "regionCode": {
          "type":"string",
          "description": "Region code of the phone number. Needed by users if the URI doesn't include a country code. Values are based on the public CLDR list of region codes (http://cldr.unicode.org/translation/country-names)."
        },
        "uri": {
          "type":"string",
          "description": "The URI of the entry point. The maximum length is 1300 characters. The formatting depends on the entry point type:\nmore: A http: or https: schema is required.\nphone: A tel: schema is required. The URI should include the entire dial sequence (for example, \"tel:+12345678900,,,12345678;1234\").\nsip: A sip: or sips: schema is required. For example \"sip:12345678@myprovider.com\".\nvideo: A http: or https: schema is required."
        }
      }
    },
    "parameters": {
      "$id": "/properties/parameters",
      "description": "An object containing a map of defined parameter data for use by the add-on.",
      "properties": {
        "addOnParameters": {
          "description": "A map of parameter string keys and values. These keys and values are defined by the add-on developer to attach information to a specific conference for the add-on's use.",
          "type": "object",
          "$ref": "#/definitions/addOnParameters"
        }
      }
    },
    "addOnParameters": {
      "$id": "/properties/addOnParameters",
      "description": "A map of parameter string keys and values. These keys and values are defined by the add-on developer to attach information to a specific conference for the add-on's use.",
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "additionalProperties": {
            "type": "string"
          }
        }
      }
    }
  },
  "$ref": "#/definitions/calendarEventObject"
}

ไดรฟ์

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "definitions": {
    "driveEventObject": {
      "$id": "/properties/driveEventObject",
      "type": "object",
      "description": "The Drive event object is the portion of the overall event object that carries information about a user's Google Drive and its contents. It's only present in an event object if the host application is Google Drive.",
      "properties": {
        "activeCursorItem": {
          "type": "object",
          "description": "The Drive item currently active.",
          "$ref": "#definitions/driveItemMetaData"
        },
        "selectedItems": {
          "type":"array",
          "description": "A list of items (files or folders) selected in Drive.",
          "items": {
            "$ref": "#definitions/driveItemMetaData"
          }
        }
      }
    },
    "driveItemMetaData": {
      "$id": "/properties/driveItemMetaData",
      "type":"object",
      "properties": {
        "id": {
          "type": "string",
          "description": "The ID of the selected item."
        },
        "iconUrl": {
          "type": "string",
          "description": "The URL of the icon that represents the selected item."
        },
        "mimeType": {
          "type": "string",
          "description": "The MIME type of the selected item."
        },
        "title": {
          "type": "string",
          "description": "The title of the selected item."
        },
        "addonHasFileScopePermission": {
          "type": "boolean",
          "description": "If true, the add-on has requested and received https://www.googleapis.com/auth/drive.file scope authorization for this item; otherwise this field is false."
        }
      }
    }
  },
  "$ref": "#/definitions/driveEventObject"
}

เอกสาร

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "definitions": {
    "docsEventObject": {
      "$id": "/properties/docsEventObject",
      "type": "object",
      "description": "The Docs event object is the portion of the overall event object that carries information about a user's Google Docs document. It's only present in an event object if the host application is Google Docs.",
      "properties": {
        "id": {
          "type": "string",
          "description": "The ID of the document open in the Docs UI"
        },
        "title": {
          "type": "string",
          "description": "The title of the document open in the Docs UI"
        },
        "matchedUrl": {
          "$id": "/properties/matchedUrlObject",
          "type": "object",
          "description": "Object that contains the URL that matches the pattern set in the link preview trigger."
          "properties": {
            "url": {
              "type": "string",
              "description": "URL that matches the pattern set in the link preview trigger."
            },
          }
        },
        "addonHasFileScopePermission": {
          "type":"boolean",
          "description": " Whether or not the add-on has drive.file scope permission for this document."
        }
      }
    },
  },
  "$ref": "#/definitions/docsEventObject"
}

Google ชีต

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "definitions": {
    "docsEventObject": {
      "$id": "/properties/docsEventObject",
      "type": "object",
      "description": "The Docs event object is the portion of the overall event object that carries information about a user's Google Sheet and its contents. It's only present in an event object if the host application is Google Sheets.",
      "properties": {
        "id": {
          "type": "string",
          "description": "The ID of the document open in the Sheets UI"
        },
        "title": {
          "type": "string",
          "description": "The title of the document open in the Sheets UI"
        },
        "addonHasFileScopePermission": {
          "type":"boolean",
          "description": " Whether or not the add-on has drive.file scope permission for this document."
        }
      }
    },
  },
  "$ref": "#/definitions/docsEventObject"
}

Google สไลด์

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "definitions": {
    "docsEventObject": {
      "$id": "/properties/docsEventObject",
      "type": "object",
      "description": "The Slides event object is the portion of the overall event object that carries information about a user's Google Slides document. It's only present in an event object if the host application is Google Slides.",
      "properties": {
        "id": {
          "type": "string",
          "description": "The ID of the document open in the Slides UI"
        },
        "title": {
          "type": "string",
          "description": "The title of the document open in the Slides UI"
        },
        "addonHasFileScopePermission": {
          "type":"boolean",
          "description": " Whether or not the add-on has drive.file scope permission for this document."
        }
      }
    },
  },
  "$ref": "#/definitions/docsEventObject"
}

ออบเจ็กต์การตอบสนองของ JSON

ส่งแบบฟอร์ม

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "description": "The response to a form submit from the add-on.  The most common response will contain a navigation of cards - e.g.  pushing a card to render content to reflected the modified content.",
  "definitions": {
    "submitFormResponse": {
      "$id": "/properties/submitFormResponse",
      "type": "object",
      "required": ["renderActions"],
      "properties": {
        "renderActions": {
          "type" : "object",
          "$ref": "./renderActionSchema.json#/definitions/renderAction"
        },
        "stateChanged": {
          "type" : "boolean",
          "description": "Whether the state of the cards has changed and data in existing cards is stale."
        }
      }
    }
  },
  "type": "object",
  "$ref": "#/definitions/submitFormResponse"
}

แสดงผลการทำงาน

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "description": "The response to the invocation of the add-on. The most common response will contain a navigation for cards - e.g. pushing a card to render content.",
  "definitions": {
    "notification": {
      "$id": "/properties/notification",
      "type": "object",
      "description": "Card action which displays a notification in the host app.",
      "properties":{
        "text": {
          "type": "string",
          "description": "Plain text to display for the notification, without html tags."
        }
      }
    },
    "navigation": {
      "$id": "/properties/navigation",
      "type": "object",
      "properties": {
        "popToRoot": {
          "type" : "boolean",
          "description": "Card stack pops all card off except the root card."
        },
        "pop": {
          "type" : "boolean",
          "description": "Card stack pops one card off."
        },
        "popToCard": {
          "type" : "string",
          "description": "Card stack pops all cards above the specified card with given card name."
        },
        "pushCard": {
          "type" : "object",
          "description": "A card to push on top of the stack, which will be shown to end users.",
          "$ref": "./cardSchema.json#/definitions/card"
        },
        "updateCard": {
          "type" : "object",
          "description": "Card stack updates the top card with a new card, preserving filled form\nfields values. For non-equivalent field, the value is dropped.",
          "$ref": "./cardSchema.json#/definitions/card"
        }
      }
    },
    "action": {
      "$id": "/properties/action",
      "type": "object",
      "description": "Google Workspace add-on response to interact with the end user. The most common interaction is to render a card with a navigation.",
      "properties": {
        "navigations": {
          "description": "Specify the navigation within the card stack.",
          "type": "array",
          "items": {
            "$ref": "#/definitions/navigation"
          }
        },
        "link": {
          "type": "object",
          "description": "Immediately open the target link in a new tab or a popup.",
          "$ref": "./cardSchema.json#/definitions/openLink"
        },
        "notification": {
          "type": "object",
          "description": "Display a notification to the end-user.",
          "$ref": "#/definitions/notification"
        }
      }
    },
    "renderAction": {
      "type": "object",
      "properties": {
        "action": {
          "type": "object",
          "$ref": "#/definitions/action",
          "description": "Google Workspace add-on response to interact with the end user. The most common interaction is to render a card with a navigation."
        },
        "hostAppAction": {
          "type":"object",
          "description": "Actions handled by individual host apps.",
          "$ref": "./hostAppActionSchema.json#/definitions/hostAppActionMarkup"
        },
        "schema": {
          "type": "string",
          "description": "This is a no-op schema field that may be present in the markup for syntax\n checking."
        }
      }
    }
  },
  "type": "object",
  "$ref": "#/definitions/renderAction"
}

มาร์กอัปการดําเนินการของแอปโฮสต์

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "definitions": {
    "hostAppActionMarkup": {
      "$id": "/properties/hostAppActionMarkup",
      "type": "object",
      "properties": {
        "gmailAction": {
          "$id": "/properties/gmailAction",
          "type": "object",
          "$ref": "./gmailSchema.json#/definitions/gmailClientActionMarkup"
        },
        "calendarAction": {
          "$id": "/properties/calendarAction",
          "type": "object",
          "$ref": "./calendarSchema.json#/definitions/calendarClientActionMarkup"
        },
        "driveAction": {
          "$id": "/properties/driveAction",
          "type": "object",
          "$ref": "./drive_schema.json#/definitions/drive_client_action_markup"
        },
        "editor_action": {
          "$id": "/properties/editor_action",
          "type": "object",
          "$ref": "./editor_schema.json#/definitions/editor_client_action_markup"
        }
      },
      "description": ""
    }
  },
  "type": "object",
  "$ref": "#/definitions/hostAppActionMarkup"
}

มาร์กอัปการดำเนินการของ Gmail

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "definitions": {
    "gmailClientActionMarkup": {
      "$id": "/properties/gmailClientActionMarkup",
      "type": "object",
      "properties": {
        "updateDraftActionMarkup": {
          "type": "object",
          "description": "Update Draft Action Markup",
          "$ref": "#definitions/updateDraftActionMarkup"
        },
        "openCreatedDraftActionMarkup": {
          "type": "object",
          "description": "Open Created Draft Action Markup",
          "$ref": "#definitions/openCreatedDraftActionMarkup"
        }
      }
    },
    "updateDraftActionMarkup": {
      "$id" : "/properties/updateDraftActionMarkup",
      "type": "object",
      "properties": {
        "updateBody": {
          "type": "object",
          "$ref": "#/definitions/updateBody"
        },
        "updateToRecipients": {
          "type": "object",
          "description": "Update To Recipients.",
          "$ref": "#/definitions/updateToRecipients"
        },
        "updateCcRecipients": {
          "type": "object",
          "description": "Update CC Recipients.",
          "$ref": "#/definitions/updateCcRecipients"
        },
        "updateBccRecipients": {
          "type": "object",
          "description": "Update BCC Recipients.",
          "$ref": "#/definitions/updateBccRecipients"
        },
        "updateSubject": {
          "type": "object",
          "description": "Update Subject",
          "$ref": "#definitions/updateSubject"
        }
      }
    },
    "updateBody": {
      "$id": "/prioperties/updateBody",
      "type": "object",
      "description": "A field which contains a series of updates action to perform on the draft\n body that user is currently editing.",
      "properties": {
        "insertContents": {
          "type": "array",
          "description": "A repeated field which contains a series of insert content to perform\n on the draft that user is currently editing. The content currently\n contains 1) HTML content or 2) plain text content.",
          "items": {
            "$ref": "#definitions/insertContent"
          }
        },
        "type": {
          "type": "string",
          "description": "",
          "enum": [
            "IN_PLACE_INSERT"
          ]
        }
      }
    },
    "insertContent": {
      "$id": "/prioperties/insertContent",
      "type": "object",
      "properties": {
        "content": {
          "type": "string",
          "description": "The content to be inserted"
        },
        "contentType": {
          "type": "string",
          "description": "The type of inserted content",
          "enum": [
            "TEXT",
            "MUTABLE_HTML",
            "IMMUTABLE_HTML"
          ]
        }
      }
    },
    "recipient": {
      "$id": "/properties/recipient",
      "type": "object",
      "description": "recipient",
      "properties": {
        "email": {
          "type": "string"
        }
      }
    },
    "updateToRecipients": {
      "$id": "/properties/updateToRecipients",
      "description": "If set, replaces the existing To recipients of the draft the user is currently editing.",
      "type": "object",
      "properties": {
        "toRecipients": {
          "type": "array",
          "description": "To Recipients",
          "items": {
            "$ref": "#/definitions/recipient"
          }
        }
      }
    },
    "updateCcRecipients": {
      "$id": "/properties/updateCcRecipients",
      "description": "If set, replaces the existing Cc recipients of the draft the user is currently editing.",
      "type": "object",
      "properties": {
        "CcRecipients": {
          "type": "array",
          "description": "CC Recipients",
          "items": {
            "$ref": "#/definitions/recipient"
          }
        }
      }
    },
    "updateBccRecipients": {
      "$id": "/properties/updateBccRecipients",
      "description": "If set, replaces the existing Bcc recipients of the draft the user is currently editing.",
      "type": "object",
      "properties": {
        "BccRecipients": {
          "type": "array",
          "description": "BCC Recipients",
          "items": {
            "$ref": "#/definitions/recipient"
          }
        }
      }
    },
    "updateSubject": {
      "$id": "/properties/updateSubject",
      "description": "If set, replaces the existing subject of the draft the user is currently editing.",
      "type": "object",
      "properties": {
        "subject": {
          "type": "string"
        }
      }
    },
    "openCreatedDraftActionMarkup": {
      "type": "object",
      "$id": "/properties/openCreatedDraftActionMarkup",
      "description": "",
      "properties": {
        "draftId": {
          "type": "string",
          "description": "The ID of the newly-created draft in the form \"r123\"."
        },
        "draftThreadId": {
          "type": "string",
          "description": "The ID of the thread containing the newly-created draft, e.g., \"15e9fa622ce1029d\"."
        }
      }
    }
  },
  "type": "object",
  "$ref": "#/definitions/gmailClientActionMarkup"
}

มาร์กอัปการดำเนินการในปฏิทิน

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "definitions": {
    "editAttendeesActionMarkup": {
      "$id": "/properties/editAttendeesActionMarkup",
      "type": "object",
      "properties": {
        "addAttendeeEmails": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "description": ""
    },
    "editConferenceDataActionMarkup": {
      "$id": "/properties/editConferenceDataActionMarkup",
      "type": "object",
      "properties": {
        "setConferenceData": {
          "type": "object",
          "$ref": "./conferenceDataMarkupSchema.json#/definitions/conferenceDataMarkup"
        }
      }
    },
    "calendarClientActionMarkup": {
      "$id": "/properties/calendarClientActionMarkup",
      "type": "object",
      "properties": {
        "editAttendeesActionMarkup": {
          "type": "object",
          "description": "",
          "$ref": "#/definitions/editAttendeesActionMarkup"
        },
        "editConferenceDataActionMarkup": {
          "type": "object",
          "description": "",
          "$ref": "#/definitions/editConferenceDataActionMarkup"
        }
      }
    }
  },
  "type": "object",
  "$ref": "#/definitions/calendarClientActionMarkup"
}

มาร์กอัปการดำเนินการกระตุ้นให้ดำเนินการ

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "definitions": {
    "driveClientActionMarkup": {
      "$id": "/properties/driveClientActionMarkup",
      "type": "object",
      "properties": {
        "requestFileScope": {
          "type": "object",
          "properties": {
            "itemId": {
              "type": "string"
            }
          }
        }
      }
    }
  },
  "type": "object",
  "$ref": "#/definitions/driveClientActionMarkup"
}

มาร์กอัปการดำเนินการของ Editor

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "definitions": {
    "editor_client_action_markup": {
      "$id": "/properties/editor_client_action_markup",
      "type": "object",
      "properties": {
        "request_file_scope_for_active_document": {
          "type": "object"
        }
      }
    }
  },
  "type": "object",
  "$ref": "#/definitions/editor_client_action_markup"
}

รับการเติมข้อความอัตโนมัติ

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "description": "A response for getting autocomplete container, which includes elements\n necessary for showing auto complete items for text field.",
  "definitions": {
    "getAutocompletionResponse": {
      "$id": "/properties/getAutocompletionResponse",
      "type": "object",
      "required": ["autoComplete"],
      "properties": {
        "autoComplete": {
          "type" : "object",
          "$ref": "./cardSchema.json#/definitions/suggestions"
        },
        "schema": {
          "type" : "string",
          "description": "This is a no-op schema field that may be present in the markup for syntax checking."
        }
      }
    }
  },
  "type": "object",
  "$ref": "#/definitions/getAutocompletionResponse"
}