Skip to content

feat: add google sheets notification provider#6777

Merged
CommanderStorm merged 7 commits intolouislam:masterfrom
dharunashokkumar:feat/google-sheets-notification
Jan 22, 2026
Merged

feat: add google sheets notification provider#6777
CommanderStorm merged 7 commits intolouislam:masterfrom
dharunashokkumar:feat/google-sheets-notification

Conversation

@dharunashokkumar
Copy link
Copy Markdown
Contributor

Description

fixes #1951

adds google sheets notification provider that logs monitor events to a spreadsheet using google apps script webhook.

Implementation

  • uses apps script webhook approach (simpler than oauth2)
  • logs timestamp, status, monitor name, url, message, response time, and status code
  • includes setup guide in the ui with copy-paste script code
  • automatically creates header row on first use

Setup for users

  1. open google spreadsheet
  2. go to extensions → apps script
  3. paste the provided script code
  4. deploy as web app with "anyone" access
  5. copy webhook url to uptime kuma

Testing

  • tested with manual notifications
  • verified data logs correctly to spreadsheet
  • tested with real monitor up/down events

logs monitor events to google spreadsheet via apps script webhook
Copilot AI review requested due to automatic review settings January 20, 2026 04:24
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a Google Sheets notification provider that logs monitor events to a spreadsheet using Google Apps Script webhooks. This provides users with a simple way to maintain a spreadsheet log of their monitor status changes without requiring OAuth2 setup.

Changes:

  • Added Google Sheets notification provider with Apps Script webhook integration
  • Included in-UI setup guide with copy-paste script code for user convenience
  • Logs timestamp, status, monitor name, URL, message, response time, and status code to spreadsheet

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/components/notifications/index.js Registers GoogleSheets component in the notification form list
src/components/notifications/GoogleSheets.vue Vue component providing UI for webhook URL input and setup instructions with Apps Script code
src/components/NotificationDialog.vue Adds Google Sheets to the "Other Integrations" category in the notification dialog
server/notification.js Registers GoogleSheets provider in the server-side notification system
server/notification-providers/google-sheets.js Backend provider implementation that sends monitor event data to Google Apps Script webhook

if (heartbeatJSON) {
status = heartbeatJSON.status === DOWN ? "DOWN" : heartbeatJSON.status === UP ? "UP" : "UNKNOWN";
responseTime = heartbeatJSON.ping || "N/A";
statusCode = heartbeatJSON.status || "N/A";
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The statusCode field is incorrectly using heartbeatJSON.status instead of the HTTP status code. The status field represents UP/DOWN state (already used on line 29), not the HTTP status code. Use heartbeatJSON.statusCode or similar property that contains the actual HTTP response code.

Suggested change
statusCode = heartbeatJSON.status || "N/A";
statusCode = heartbeatJSON.statusCode || "N/A";

Copilot uses AI. Check for mistakes.
Comment on lines +100 to +101
navigator.clipboard.writeText(scriptCode);
alert(this.$t("Copied to clipboard!"));
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The clipboard write operation can fail (e.g., due to browser permissions), but the success message is shown unconditionally. Wrap the clipboard operation in a try-catch and only show success message if the write succeeds, otherwise show an appropriate error message to the user.

Copilot uses AI. Check for mistakes.
Comment on lines +44 to +50
timestamp: timestamp,
status: status,
monitorName: monitorName,
monitorUrl: monitorUrl,
message: msg,
responseTime: responseTime,
statusCode: statusCode,
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Object property shorthand can be used here since the property names match the variable names. This would make the code more concise and easier to read.

Suggested change
timestamp: timestamp,
status: status,
monitorName: monitorName,
monitorUrl: monitorUrl,
message: msg,
responseTime: responseTime,
statusCode: statusCode,
timestamp,
status,
monitorName,
monitorUrl,
message: msg,
responseTime,
statusCode,

Copilot uses AI. Check for mistakes.
use proper statusCode field and add error handling for clipboard
@dharunashokkumar dharunashokkumar force-pushed the feat/google-sheets-notification branch from e4f3e7d to 44923b0 Compare January 20, 2026 04:32
Copy link
Copy Markdown
Collaborator

@CommanderStorm CommanderStorm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code mostly lgtm.

My airplane is lifting off soon, so review is a bit more rushed.

Please make sure to post a screenshot

}

// Send data to Google Apps Script webhook
const webhookUrl = notification.googleSheetsWebhookUrl;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Please inline

// Other Integrations
let other = {};
let other = {
GoogleSheets: "Google Sheets",
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did not think we would need this section this quickly.. 🤣

<template>
<div class="mb-3">
<label for="google-sheets-webhook-url" class="form-label">{{ $t("Google Apps Script Webhook URL") }}</label>
<input
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use an HiddenInput for all secrets.
This seems like one.

Comment on lines +37 to +64
<textarea readonly class="form-control" rows="15" style="font-family: monospace; font-size: 12px">
function doPost(e) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var data = JSON.parse(e.postData.contents);

// Add header row if sheet is empty
if (sheet.getLastRow() === 0) {
sheet.appendRow(['Timestamp', 'Status', 'Monitor Name', 'URL', 'Message', 'Response Time', 'Status Code']);
}

// Add data row
sheet.appendRow([
data.timestamp,
data.status,
data.monitorName,
data.monitorUrl,
data.message,
data.responseTime,
data.statusCode
]);

return ContentService.createTextOutput(JSON.stringify({result: 'success'}))
.setMimeType(ContentService.MimeType.JSON);
}</textarea
>
<button type="button" class="btn btn-outline-secondary btn-sm mt-2" @click="copyScript">
{{ $t("Copy to Clipboard") }}
</button>
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really not have a component for this?

Comment on lines +30 to +32
<button type="button" class="btn btn-secondary btn-sm" @click="showScript = !showScript">
{{ showScript ? $t("Hide Script Code") : $t("Show Script Code") }}
</button>
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a bootstrap acordeon might be more fitting? Not sure what we want here exactly, but this seems a bit odd

methods: {
copyScript() {
const scriptCode = `function doPost(e) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't want this script twice in case we have to duplicate this in the future.

I think this living on the js side makes things easier?
I am fine with this living on the html side.
I just want to prevent footguns

Use HiddenInput for webhook URL, replace button with ToggleSection, inline webhook variable, and move script to constant to avoid duplication
@dharunashokkumar dharunashokkumar force-pushed the feat/google-sheets-notification branch from 50d29c6 to bcaf554 Compare January 20, 2026 15:49
@dharunashokkumar dharunashokkumar force-pushed the feat/google-sheets-notification branch from f259e2b to 484ab97 Compare January 20, 2026 15:53
Add English translations for Google Sheets notification setup instructions
@dharunashokkumar dharunashokkumar force-pushed the feat/google-sheets-notification branch from 2568503 to 32c2b91 Compare January 20, 2026 16:03
@dharunashokkumar
Copy link
Copy Markdown
Contributor Author

Screenshot 2026-01-20 215149 Screenshot 2026-01-20 215832 Screenshot 2026-01-20 215936

Comment on lines +16 to +18
<div class="alert alert-info" style="border-radius: 8px">
<h6 style="margin-bottom: 12px; font-weight: 600">{{ $t("Quick Setup Guide") }}:</h6>
<ol style="margin-bottom: 0; padding-left: 20px; line-height: 1.8">
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this being an alert with the custom fromat looks a bit strange on the screenshots

Suggested change
<div class="alert alert-info" style="border-radius: 8px">
<h6 style="margin-bottom: 12px; font-weight: 600">{{ $t("Quick Setup Guide") }}:</h6>
<ol style="margin-bottom: 0; padding-left: 20px; line-height: 1.8">
<div class="mt-3 form-text">
<h6>{{ $t("Quick Setup Guide") }}:</h6>
<ol>

Copy link
Copy Markdown
Collaborator

@CommanderStorm CommanderStorm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@CommanderStorm CommanderStorm enabled auto-merge (squash) January 22, 2026 10:43
@CommanderStorm CommanderStorm added this to the 2.1.0 milestone Jan 22, 2026
@CommanderStorm CommanderStorm merged commit a38c6de into louislam:master Jan 22, 2026
24 checks passed
@dharunashokkumar dharunashokkumar deleted the feat/google-sheets-notification branch February 28, 2026 16:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Log notifications with Google Sheets

3 participants