Checks every site listed in a spreadsheet on a schedule and alerts you in Slack or by email when one goes down or recovers.

UsesGmailGoogle SheetsSlack

Watch your websites for downtime

ScheduleRun every 15 minutes.Run every 15 minutes.
ValuesSet sitesSheetUrl to blank.Set sitesSheetUrl to blank.
ValuesSet sitesTabName to Sites.Set sitesTabName to Sites.
ValuesSet statusTabName to Status log.Set statusTabName to Status log.
ValuesSet alertSlackChannelId to blank.Set alertSlackChannelId to blank.
ValuesSet alertEmailAddress to blank.Set alertEmailAddress to blank.
ValuesSet maxSites to 25.Set maxSites to 25.
Dates & TimesGet the current date and time and save it as checkedAt.Get the current date and time and save it as checkedAt.
ValuesSet siteRows to an empty list.Set siteRows to an empty list.
Decisions & LoopsIf a step below fails, save the error as siteListErrorIf a step below fails, save the error as siteListError
Try
Google SheetsGoogle SheetsRead the rows of sitesSheetUrl. Save it as siteList.Read the rows of sitesSheetUrl. Save it as siteList.
ValuesChange siteRows to siteList.rows.Change siteRows to siteList.rows.
On error
Decisions & LoopsStop and report a problem: Could not read the site list, so nothing was checked. Check that the spreadsheet in 'sitesSheetUrl' has a tab named as in 'sitesTabName'. (siteListError.message).Stop and report a problem: Could not read the site list, so nothing was checked. Check that the spreadsheet in 'sitesSheetUrl' has a tab named as in 'sitesTabName'. (siteListError.message).
ValuesSet logRows to an empty list.Set logRows to an empty list.
ValuesSet logHasHeader to false.Set logHasHeader to false.
Decisions & LoopsIf a step below fails, save the error as logReadErrorIf a step below fails, save the error as logReadError
Try
Google SheetsGoogle SheetsRead the rows of sitesSheetUrl. Save it as storedLog.Read the rows of sitesSheetUrl. Save it as storedLog.
ValuesChange logRows to storedLog.rows.Change logRows to storedLog.rows.
ValuesChange logHasHeader to the length of storedLog.headers is greater than 0.Change logHasHeader to the length of storedLog.headers is greater than 0.
On error
ValuesShow in the output: There is no status log yet, so this run creates it and records what it finds as the starting point. (logReadError.message).Show in the output: There is no status log yet, so this run creates it and records what it finds as the starting point. (logReadError.message).
Decisions & LoopsIf a step below fails, save the error as createTabErrorIf a step below fails, save the error as createTabError
Try
Google SheetsGoogle SheetsCreate the tab statusTabName in sitesSheetUrl.Create the tab statusTabName in sitesSheetUrl.
On error
ValuesShow in the output: Could not create the status log tab; carrying on in case it already exists. (createTabError.message).Show in the output: Could not create the status log tab; carrying on in case it already exists. (createTabError.message).
Decisions & LoopsIf logHasHeader is noIf logHasHeader is no
Yes
Decisions & LoopsIf a step below fails, save the error as headerErrorIf a step below fails, save the error as headerError
Try
Google SheetsGoogle SheetsAdd a row to statusTabName in sitesSheetUrl.Add a row to statusTabName in sitesSheetUrl.
On error
ValuesShow in the output: Could not write the status log header row. (headerError.message).Show in the output: Could not write the status log header row. (headerError.message).
No
No steps
ValuesSet sitesChecked to 0.Set sitesChecked to 0.
ValuesSet sitesDown to 0.Set sitesDown to 0.
Decisions & LoopsFor each site in siteRows:For each site in siteRows:
ValuesSet siteUrl to blank.Set siteUrl to blank.
Decisions & LoopsIf a step below fails, save the error as urlErrorIf a step below fails, save the error as urlError
Try
TextTrim site.URL and save it as siteUrl.Trim site.URL and save it as siteUrl.
On error
ValuesShow in the output: A row in the site list has no 'URL' column, so it was skipped. Check that the first row of the sites tab has a column headed URL..Show in the output: A row in the site list has no 'URL' column, so it was skipped. Check that the first row of the sites tab has a column headed URL..
Decisions & LoopsIf siteUrl is emptyIf siteUrl is empty
Yes
Decisions & LoopsSkip to the next item.Skip to the next item.
No
No steps
ValuesAdd 1 to sitesChecked.Add 1 to sitesChecked.
ValuesSet isUp to false.Set isUp to false.
ValuesSet detail to blank.Set detail to blank.
Decisions & LoopsIf a step below fails, save the error as checkErrorIf a step below fails, save the error as checkError
Try
HTTPFetch siteUrl and save it as response.Fetch siteUrl and save it as response.
ValuesChange isUp to response.ok.Change isUp to response.ok.
ValuesChange detail to Answered with HTTP response.status as text.Change detail to Answered with HTTP response.status as text.
On error
ValuesChange isUp to false.Change isUp to false.
ValuesChange detail to Could not be reached. checkError.message.Change detail to Could not be reached. checkError.message.
ValuesSet currentStatus to Down.Set currentStatus to Down.
Decisions & LoopsIf isUp is yesIf isUp is yes
Yes
ValuesChange currentStatus to Up.Change currentStatus to Up.
No
ValuesAdd 1 to sitesDown.Add 1 to sitesDown.
ValuesSet lastStatus to blank.Set lastStatus to blank.
ValuesSet lastChangedAt to blank.Set lastChangedAt to blank.
Decisions & LoopsFor each entry in logRows:For each entry in logRows:
Decisions & LoopsIf a step below fails, save the error as logRowErrorIf a step below fails, save the error as logRowError
Try
TextTrim entry.URL and save it as entryUrl.Trim entry.URL and save it as entryUrl.
TextTrim entry.Status and save it as entryStatus.Trim entry.Status and save it as entryStatus.
TextTrim entry.Time and save it as entryTime.Trim entry.Time and save it as entryTime.
Decisions & LoopsIf entryUrl is siteUrlIf entryUrl is siteUrl
Yes
ValuesChange lastStatus to entryStatus.Change lastStatus to entryStatus.
ValuesChange lastChangedAt to entryTime.Change lastChangedAt to entryTime.
No
No steps
On error
ValuesShow in the output: Ignored a status log row that is missing a column. (logRowError.message).Show in the output: Ignored a status log row that is missing a column. (logRowError.message).
Decisions & LoopsIf currentStatus is not lastStatusIf currentStatus is not lastStatus
Yes
Decisions & LoopsIf a step below fails, save the error as logWriteErrorIf a step below fails, save the error as logWriteError
Try
Google SheetsGoogle SheetsAdd a row to statusTabName in sitesSheetUrl.Add a row to statusTabName in sitesSheetUrl.
On error
ValuesShow in the output: Could not record the change for siteUrl in the status log. (logWriteError.message).Show in the output: Could not record the change for siteUrl in the status log. (logWriteError.message).
ValuesSet alertSubject to blank.Set alertSubject to blank.
ValuesSet alertBody to blank.Set alertBody to blank.
Decisions & LoopsIf currentStatus is DownIf currentStatus is Down
Yes
ValuesChange alertSubject to Site down: siteUrl.Change alertSubject to Site down: siteUrl.
ValuesChange alertBody to siteUrl did not answer as expected.Change alertBody to siteUrl did not answer as expected. detail First seen at checkedAt.
Else if @lastStatus isn't empty
ValuesChange alertSubject to Site back up: siteUrl.Change alertSubject to Site back up: siteUrl.
ValuesChange alertBody to siteUrl is answering again.Change alertBody to siteUrl is answering again. detail It had been down since lastChangedAt.
Otherwise
No steps
Decisions & LoopsIf alertSubject isn't emptyIf alertSubject isn't empty
Yes
Decisions & LoopsIf alertSlackChannelId isn't emptyIf alertSlackChannelId isn't empty
Yes
Decisions & LoopsIf a step below fails, save the error as slackErrorIf a step below fails, save the error as slackError
Try
SlackSlackSend a message to alertSlackChannelId.Send a message to alertSlackChannelId.alertSubject alertBody
On error
ValuesShow in the output: Could not post the alert for siteUrl to Slack. (slackError.message).Show in the output: Could not post the alert for siteUrl to Slack. (slackError.message).
No
No steps
Decisions & LoopsIf alertEmailAddress isn't emptyIf alertEmailAddress isn't empty
Yes
Decisions & LoopsIf a step below fails, save the error as emailErrorIf a step below fails, save the error as emailError
Try
GmailGmailSend an email to alertEmailAddress.Send an email to alertEmailAddress. Subject: alertSubjectalertBody
On error
ValuesShow in the output: Could not email the alert for siteUrl. (emailError.message).Show in the output: Could not email the alert for siteUrl. (emailError.message).
No
No steps
No
No steps
No
No steps
ValuesShow in the output: Checked sitesChecked as text site(s); sitesDown as text not answering.Show in the output: Checked sitesChecked as text site(s); sitesDown as text not answering.