Track contract expiry from Drive files
Read expiry dates out of Northwind contract Docs and warn before renewals.
Published Oct 28, 2025
Northwind signs contracts the way most studios do — a Google Doc per client, filed in a folder, then forgotten until something goes wrong. The expiry date is written into the document, but nobody re-reads every contract every month, so a renewal slips past and the studio is suddenly out of cover or auto-renewed on old terms.
This script reads the expiry date straight out of each contract Doc. It scans a folder, pulls the date out of the document text with a regular expression, and emails a digest of anything expiring within a warning window. It is a reminder system that needs no separate spreadsheet of dates to maintain — the contracts themselves are the source of truth.
What you’ll need
- A Drive folder of contract Google Docs — its ID goes in the config below.
- Each contract must contain an expiry line the regex can find, e.g.
Expiry: 2026-03-31orExpires 2026-03-31. The date must be inYYYY-MM-DDform. - The address the digest should go to — set it in the config.
The script
// The folder of contract Google Docs to scan.
const CONTRACTS_FOLDER_ID = '1abcContractsFolderId';
// Where the "expiring soon" digest is sent.
const NOTIFY_EMAIL = '[email protected]';
// How many days ahead counts as "expiring soon".
const WARN_DAYS = 30;
// One day in milliseconds — used to build the cutoff date.
const DAY_MS = 86400000;
// Matches "expiry", "expires", or "expire", then a YYYY-MM-DD date.
const EXPIRY_PATTERN = /expir(?:y|es?)[:\s]*(\d{4}-\d{2}-\d{2})/i;
/**
* Scans the contracts folder, reads the expiry date from each Doc,
* and emails a digest of contracts expiring within WARN_DAYS.
*/
function checkExpiringContracts() {
// 1. Get every Google Doc in the contracts folder.
const files = DriveApp.getFolderById(CONTRACTS_FOLDER_ID)
.getFilesByType(MimeType.GOOGLE_DOCS);
// 2. Work out the cutoff: anything dated past this is not "soon".
const now = Date.now();
const cutoff = now + WARN_DAYS * DAY_MS;
// 3. Walk each Doc and collect the ones expiring inside the window.
const expiring = [];
while (files.hasNext()) {
const file = files.next();
// Read the document body as plain text and search for an expiry date.
const text = DocumentApp.openById(file.getId()).getBody().getText();
const match = text.match(EXPIRY_PATTERN);
if (!match) continue;
// Skip contracts already expired or still beyond the warning window.
const expiry = new Date(match[1]).getTime();
if (expiry < now || expiry > cutoff) continue;
expiring.push(`• ${file.getName()} expires ${match[1]}\n ${file.getUrl()}`);
}
// 4. Send a digest only if something is actually expiring soon.
if (!expiring.length) {
Logger.log('No contracts expiring in the next ' + WARN_DAYS + ' days.');
return;
}
GmailApp.sendEmail(
NOTIFY_EMAIL,
`${expiring.length} contract(s) expiring soon`,
expiring.join('\n'),
);
Logger.log('Sent a digest of ' + expiring.length + ' contract(s).');
}
How it works
checkExpiringContractsopens the contracts folder and gets only its Google Docs —getFilesByTypeskips PDFs, images, and anything else.- It computes a
cutofftimestampWARN_DAYSinto the future. A contract counts as “expiring soon” only if its date falls between now and that cutoff. - For each Doc it reads the body as plain text and runs
EXPIRY_PATTERNagainst it. A Doc with no matching line is skipped silently. - It parses the captured
YYYY-MM-DDdate. Contracts already expired (before now) or still far off (past the cutoff) are dropped; the rest are formatted into a bullet line with the file name, date, and link. - If the
expiringlist is empty it logs and stops — no empty email. Otherwise it sends one digest toNOTIFY_EMAILlisting every contract due for renewal.
Example run
Say the contracts folder holds five Docs and today is 2025-10-28 with
WARN_DAYS at 30. Two contracts have expiry lines inside the window:
| Contract Doc | Expiry line found | In window? |
|---|---|---|
| Acme Retainer 2025 | Expires 2025-11-12 | yes |
| Globex Hosting | Expiry: 2026-06-01 | no — too far off |
| Initech Support | Expiry: 2025-09-30 | no — already expired |
| Umbrella Studio Lease | Expires 2025-11-20 | yes |
| Wayne Co Licence | (no expiry line) | skipped |
The run sends one email, subject “2 contract(s) expiring soon”, with:
• Acme Retainer 2025 expires 2025-11-12
https://docs.google.com/document/d/...
• Umbrella Studio Lease expires 2025-11-20
https://docs.google.com/document/d/...
Trigger it
The reminder is only useful if it runs without anyone asking:
- In the Apps Script editor open Triggers (the clock icon).
- Add a trigger for
checkExpiringContracts, time-driven, on a weekly timer.
Weekly means a 30-day window gives roughly four nudges before any renewal — enough warning without becoming noise.
Watch out for
- The regex needs a date in
YYYY-MM-DDform. A contract writtenexpires 31 March 2026will not match — standardise the expiry wording when contracts are drafted. - It reads only the first match per document. If a Doc mentions several dates,
put the contract’s own expiry line first, or tighten
EXPIRY_PATTERN. - It scans one folder, not subfolders. Contracts filed in client subfolders are missed unless you add a recursive walk.
- Already-expired contracts are skipped, not flagged. If you want to catch ones
that lapsed unnoticed, drop the
expiry < nowcheck and label them separately. - The digest goes to a single address. For a shared inbox, use a group address
in
NOTIFY_EMAILso the whole team sees the reminder.
Related
Detect and report broken file shortcuts
Find Drive shortcuts in Northwind folders pointing at deleted or inaccessible files.
Updated Dec 3, 2025
Build a Drive cleanup recommendation report
Suggest what Northwind can delete or archive — large, stale, duplicate, or untouched files.
Updated Nov 21, 2025
Generate a folder-level changelog
Track additions and deletions in a Northwind folder over time — a written history.
Updated Nov 5, 2025
Build a Drive quota early-warning system
Alert Northwind before storage runs out — email when usage crosses 80%.
Updated Oct 20, 2025
Enforce file naming and tagging governance
Flag Northwind files that don't match required naming or tagging conventions.
Updated Oct 16, 2025