How the add-on works
The add-on is a Google Apps Script project deployed as a Workspace Add-on from theclients/google-meet-addon/ directory. When a calendar event is opened, onCalendarEventOpen fires; when attendees or times change, onCalendarEventUpdate fires. Each trigger calls buildEventCard, which reads the open event’s attendees, filters out rooms and declined guests, resolves the RRULE cadence, and POSTs to /api/v1/estimate on your MeetCost backend.
The add-on requests
currentEventAccess: READ and nothing wider. It cannot see any calendar the user has not explicitly opened, and it has no write scope of any kind.OAuth scopes
Prerequisites
Before you begin, confirm:- You have a deployed MeetCost backend reachable over HTTPS.
- A Google Workspace admin account is available to grant domain-wide delegation and publish the add-on to the domain.
- A Google Cloud service account exists (or can be created) with the Admin SDK API enabled, for directory sync and attendance polling.
Installation
1
Create the Apps Script project
Go to script.google.com and create a New project. Copy
Code.gs, Config.gs, and Ui.gs from clients/google-meet-addon/ into the project.2
Apply the manifest
In Project Settings, enable Show “appsscript.json” manifest file, then replace the contents with the Replace
appsscript.json from clients/google-meet-addon/:https://meetcost.your-company.example/ with your actual MeetCost address. Apps Script will refuse to reach any other host.3
Set the backend URL script property
In Project Settings → Script Properties, add:
If this property is unset, the add-on displays a configuration message and does nothing. There is no default and no fallback — by design.
4
Test on your own account
Go to Deploy → Test deployments, install the add-on on your own account, open a calendar event, and confirm the MeetCost card appears in the side panel.
5
Publish to your Workspace domain
Go to Deploy → New deployment → Add-on, then publish through the Google Workspace Marketplace SDK. Choose Private (domain-only) distribution — this requires no Google review and is available to everyone in your Workspace organisation immediately.
Authentication
The add-on identifies the calling user withScriptApp.getIdentityToken(), which returns a Google-issued OpenID Connect token. The backend verifies this token against the OIDC issuer https://accounts.google.com. MeetCost has no accounts and no passwords: the identity assertion is Google’s own, travelling to your organisation’s own infrastructure.
Directory sync
MeetCost looks up pay figures by email address, so it needs a copy of your Workspace user directory. The Google adapter authenticates with a service account using a JWT grant (domain-wide delegation), then pages through the Admin SDK Directory API.Required environment variables on the server
Service account permissions
Grant the service account domain-wide delegation in your Workspace Admin console, with these OAuth scopes:
The service account must have the Admin SDK API enabled in your Google Cloud project (
admin.googleapis.com).
Attendance collection
Google Meet has no end-of-meeting webhook. Attendance is polled from the Reports APImeet application, call_ended events. Because the Reports API is eventually consistent — events can lag a meeting’s end by minutes to hours — MeetCost uses a poller with an overlapping window rather than a one-shot read.
Run the collector on a schedule (for example, every 15 minutes via cron):
--hours flag sets how far back the window reaches. Use a value larger than the typical lag you observe in your domain; 3 is a reasonable starting point.
Authenticated trigger endpoint
For operator-initiated sweeps, the backend also exposes an authenticated admin endpoint:hours query parameter is optional and defaults to 24. It is useful for triggering a collect after a known meeting ends without waiting for the cron.
The poll trigger does not replace the cron. Reports API events can still be delayed after the trigger fires. Run both for reliable coverage.
Cadence and the annualised figure
The add-on maps Google Calendar’sRRULE values to MeetCost cadences automatically:
When the cadence is
one_off or cannot be determined, the annualised figure is suppressed rather than guessed. The organiser can always set the cadence manually in the card. Showing no annual figure is better than showing a wrong one.
Security model
No pay data to Google
The add-on never sends a salary, rate, or cost figure to Google. It sends attendee email addresses and duration — data the user already has on screen.
No default backend
The
urlFetchWhitelist in appsscript.json and the MEETCOST_BACKEND_URL script property together enforce that the add-on contacts only the URL your administrator set. There is no fallback address.HTTPS enforced
getBackendUrl() rejects plaintext URLs to any host other than localhost. Identity tokens are never sent over unencrypted connections to production addresses.Read-only event access
currentEventAccess: READ is the narrowest scope Calendar add-ons can request. The add-on cannot modify any event or see any calendar the user has not opened.