Google Sheets – Team Hub Maintenance Webhook

Team Hub ~5 minutes

What this does

When your team logs a machine in the Team Hub Maintenance screen, each entry is sent to your Google Sheet and stored in a dated tab, one row per log.

Each club only needs to do this once to connect their own Google Sheet.

Step 1 — Make or open your Google Sheet

1
Create a new Google Sheet (or pick an existing “Maintenance Log” sheet for your club).
2
You don’t need the Sheet ID for this one — the script uses the sheet you attach it to.

Step 2 — Add the Apps Script

1
In the sheet, go to Extensions → Apps Script.
2
Delete anything in the editor, then paste this script:
const TZ = 'Europe/London'; 

// Entry point
function doPost(e) {
  try {
    const body = JSON.parse(e.postData.contents || '{}');

    if (body.action === 'maintenance') {
      return handleMaintenance(body);
    }

    return ContentService
      .createTextOutput('ignored')
      .setMimeType(ContentService.MimeType.TEXT);

  } catch (err) {
    console.error(err);
    return ContentService
      .createTextOutput('error')
      .setMimeType(ContentService.MimeType.TEXT);
  }
}

function handleMaintenance(p) {
  const ss = SpreadsheetApp.getActive();

  // Convert timestamp
  const when = p.timestamp ? new Date(p.timestamp) : new Date();
  const sheetName = 'Maintenance ' + Utilities.formatDate(when, TZ, 'dd-MM-yyyy');
  const timeOnly  = Utilities.formatDate(when, TZ, 'HH:mm');

  // Normalise status to uppercase for neat display
  const status = (p.status || '').toString().toUpperCase();

  // Get or create sheet
  let sh = ss.getSheetByName(sheetName);
  if (!sh) {
    sh = ss.insertSheet(sheetName);

    // Header row
    sh.appendRow([
      'Time',
      'Log Date',
      'Machine',
      'Hours',
      'Initials',
      'Status',
      'Note',
      'Site'
    ]);

    sh.setFrozenRows(1);
    sh.getRange('A1:H1').setFontWeight('bold');

    // Set column widths (adjust if desired)
    const widths = [
      70,   // Time
      90,   // Log Date
      180,  // Machine
      60,   // Hours
      80,   // Initials
      90,   // Status
      260,  // Note
      120   // Site
    ];
    widths.forEach((w, i) => sh.setColumnWidth(i + 1, w));

    // Conditional formatting for Status (column F)
    const statusRange = sh.getRange('F2:F');
    const rules = [];

    rules.push(
      SpreadsheetApp.newConditionalFormatRule()
        .whenTextEqualTo('GREEN')
        .setBackground('#A9D18E')
        .setRanges([statusRange])
        .build()
    );
    rules.push(
      SpreadsheetApp.newConditionalFormatRule()
        .whenTextEqualTo('AMBER')
        .setBackground('#FFD966')
        .setRanges([statusRange])
        .build()
    );
    rules.push(
      SpreadsheetApp.newConditionalFormatRule()
        .whenTextEqualTo('RED')
        .setBackground('#F4B084')
        .setRanges([statusRange])
        .build()
    );

    sh.setConditionalFormatRules(rules);
  }

  // Append maintenance row
  sh.appendRow([
    timeOnly,
    p.date || '',
    p.machine || '',
    p.hours || '',
    p.initials || '',
    status,
    p.note || '',
    p.site || ''
  ]);

  return ContentService
    .createTextOutput('ok')
    .setMimeType(ContentService.MimeType.TEXT);
}
3
Click the floppy disk icon or press Ctrl + S / ⌘ + S to save.

Step 3 — Deploy the Web App (Webhook)

  1. Click Deploy → New deployment.
  2. For Select type, choose Web app.
  3. Execute as: Me.
  4. Who has access: Anyone with the link (or Anyone depending on your Google UI).
  5. Click Deploy and approve the permissions if prompted.
  6. Copy the Web App URL (it should end with /exec).
Paste into the app:
Team Hub App → Settings → Links & Sheets → Maintenance Webhook
Paste your Web App URL and tap Save.

Step 4 — Test it

  1. Open the Team Hub Maintenance screen and log a test machine (any status).
  2. Check your Google Sheet — you should see a new tab called Maintenance dd-MM-yyyy with your log row.
  3. Change another machine to Amber/Red and confirm a second row appears.

If nothing arrives, double-check:
• The deployment URL you pasted ends with /exec.
Who has access is set to Anyone with the link.