Guide · 10 min read

How to manage contracts in Google Drive

Google Drive can run contract management perfectly well, up to a specific point: the moment you need to answer “what renews next quarter, and who owns it?” without opening files. Storage is not the hard part of contract management — recall is. A folder holds a signed PDF indefinitely; it will not tell you that the notice window on your largest vendor closed last Tuesday.

This guide builds the Drive setup properly: a folder structure, a naming convention that puts the dates in the filename, a companion Sheet with the one column most trackers miss, and a working script that emails you before a deadline instead of after it. Then it covers, honestly, where the approach stops holding — and how to tell which side of that line you are on.

Step 1: A folder structure that survives other people

Contracts/                              ← a shared drive, not My Drive
├── 01_Active/
│   ├── Software/
│   ├── Services/
│   ├── Facilities/
│   └── People/
├── 02_Expired/
├── 03_Templates/
└── Contract-Register            ← the tracking Sheet, pinned to the top

The structure below is deliberately shallow. Deep hierarchies fail because filing a contract becomes a judgment call, and anything that requires judgment gets skipped when someone is in a hurry. Two levels is enough: status first, then category.

Put this in a shared drive rather than someone's My Drive. Files in a personal My Drive belong to that account, and when the account is closed the files can go with it — the single most common way a contract archive quietly loses its contents. A shared drive is owned by the organization, so a departure changes nothing.

Keep expired contracts. An agreement that ended still governs what happened while it was live, which matters in a dispute, an audit, or a data-subject request. Move them, do not delete them.

Screenshot placeholder — not for publication

The Contracts shared drive, expanded to show 01_Active and its four subfolders

TODO(verify): real screenshot required — Rasmus to capture from an actual Drive account. Do not generate or mock this image.

Step 2: Put the dates in the filename

Drive search is fast and it searches filenames reliably. That makes the filename the cheapest index you will ever build — if it carries the facts you actually search for. The convention below front-loads the signing date so files sort chronologically, then names the counterparty, then encodes the two dates that decide whether you keep paying.

{signed}_{Counterparty}_{Type}_renewal-{date}_notice-{days}d.pdf
  • 2026-03-15_Acme_MSA_renewal-2027-03-15_notice-60d.pdf
  • 2026-01-08_Ravelin_SaaS_renewal-2027-01-08_notice-30d.pdf
  • 2025-11-30_Northgate_Lease_renewal-2028-11-30_notice-180d.pdf
  • 2026-02-02_Beacon_NDA_expires-2029-02-02_notice-none.pdf

The point of the notice suffix is that it makes an invisible obligation visible in a file listing. Someone scanning the folder sees “notice-60d” and knows the decision date is two months before the renewal, without opening anything or trusting their memory of clause 12.

Apply it going forward and rename in bulk when you have an afternoon; a partially converted folder is still better than none, because the converted files become searchable immediately.

What columns should a contract tracking sheet have?

Twelve columns cover it: counterparty, contract type, owner, start date, renewal date, notice period in days, the calculated notice deadline, whether it auto-renews, annual value, department, a link to the signed file, and status. The notice deadline is the one that must be a formula rather than typed.

The folder holds documents; the Sheet holds answers. One row per active contract, one tab, no macros. The column that separates a working tracker from a decorative one is the notice deadline — the last day you can act — and it should be calculated, never typed, because typed dates drift the moment a renewal date is corrected.

Store the notice period in days rather than describing it in prose, so the deadline can be derived. Then let the sheet do the arithmetic with a formula, and let conditional formatting turn the row amber inside sixty days and red once the window has closed. A tracker that looks the same on the day a deadline passes is not telling you anything.

ColHeaderWhat goes in it
ACounterpartyWho you signed with. Matches the filename.
BTypeSoftware, Services, Facilities, People.
COwnerOne named person. Not a team, not a mailbox.
DRenewal dateReal date value, not text.
ENotice daysA number: 30, 60, 90. Zero if none.
FNotice deadlineCalculated, never typed. Formula below.
GAnnual valueFor sorting by what actually matters.
HAuto-renewsYes or No. Drives how hard F is.
IStatusActive, Renewed, Cancelled, Done.
JLinkPaste the Drive link to the signed PDF.
KNotesWhy the last decision went the way it did.

F2, filled down:

=IF(OR(ISBLANK(D2),ISBLANK(E2)),"",D2-E2)

The notice deadline: renewal date minus the notice period. Sheets stores dates as day numbers, so subtracting a count of days is ordinary date arithmetic.

L2, filled down:

=IF(ISBLANK(F2),"",F2-TODAY())

Days remaining. Negative once the window has closed, which is exactly the number you want to see turn red.

Worked example: a contract renewing on 15 March 2027 with a 60-day notice period has a notice deadline of 14 January 2027. Column F returns exactly that. A reminder set for the renewal date would reach you two months after the decision was already made for you.

Screenshot placeholder — not for publication

The tracking Sheet with column F calculated and conditional formatting applied

TODO(verify): real screenshot required — Rasmus to capture from an actual Sheet with sample rows. Do not generate or mock this image.

How do you get Google Drive to remind you about a renewal?

Drive itself has no reminder feature, so the reminder has to come from the tracking Sheet. Google Apps Script can read the sheet on a daily schedule and email whoever owns a contract before its notice deadline, at no cost and with no third-party tool. The script below does exactly that.

This is the step most Drive setups skip, and it is the one that decides whether the system works. A tracker nobody opens is a document, not a control. Google Sheets can send mail on a schedule through Apps Script, which means Drive can email you thirty days before a notice deadline without any third-party tool or subscription.

The script below reads the tracking Sheet every morning, finds rows whose notice deadline falls inside the reminder window, and sends one digest email listing them with their owners. It also reports deadlines that have already passed without the row being marked done, because a missed window you know about is recoverable far more often than one you do not.

/**
 * Contract renewal reminders from a Google Sheet.
 *
 * Paste into Extensions → Apps Script on the tracking Sheet, set the four
 * CONFIG values, then run setUpDailyTrigger() once. It emails you when a
 * notice deadline is REMINDER_DAYS away or closer, and again the day a
 * deadline passes without the row being marked done.
 *
 * Published on https://lumipact.com/alternatives/google-drive — this file is
 * the source of truth the page renders, so the script on the page and the
 * script in the repo cannot drift apart.
 */

var CONFIG = {
  // Exact name of the tab holding the contracts.
  sheetName: "Contracts",
  // Where to send reminders. A shared alias survives someone leaving.
  notifyEmail: "contracts@example.com",
  // Send a reminder when the notice deadline is this many days away or less.
  reminderDays: 30,
  // First row of data, i.e. the row after the header.
  firstDataRow: 2,
};

// Column positions, 1-indexed, matching the column order in the guide.
var COLUMN = {
  counterparty: 1,
  type: 2,
  owner: 3,
  renewalDate: 4,
  noticeDays: 5,
  noticeDeadline: 6,
  annualValue: 7,
  autoRenews: 8,
  status: 9,
};

/**
 * Run once, by hand, from the Apps Script editor. Creates a trigger that
 * runs checkNoticeDeadlines() every morning. Running it twice would create a
 * second trigger and send every email twice, so it clears its own first.
 */
function setUpDailyTrigger() {
  var existing = ScriptApp.getProjectTriggers();
  for (var i = 0; i < existing.length; i++) {
    if (existing[i].getHandlerFunction() === "checkNoticeDeadlines") {
      ScriptApp.deleteTrigger(existing[i]);
    }
  }
  ScriptApp.newTrigger("checkNoticeDeadlines").timeBased().atHour(7).everyDays(1).create();
}

/** Midnight UTC for a Date or a date-like cell value, so comparisons are whole days. */
function toUtcMidnight(value) {
  var date = value instanceof Date ? value : new Date(value);
  if (isNaN(date.getTime())) return null;
  return Date.UTC(date.getFullYear(), date.getMonth(), date.getDate());
}

/** Whole days from today until the given date. Negative once it has passed. */
function daysUntil(value) {
  var target = toUtcMidnight(value);
  if (target === null) return null;
  var now = new Date();
  var today = Date.UTC(now.getFullYear(), now.getMonth(), now.getDate());
  return Math.round((target - today) / 86400000);
}

/**
 * The notice deadline for a row.
 *
 * Prefers the deadline column when it is filled in, and falls back to
 * computing renewal date minus notice days — the same arithmetic as the
 * sheet formula, so a row with an empty deadline column is still covered.
 */
function noticeDeadlineFor(row) {
  var explicit = row[COLUMN.noticeDeadline - 1];
  if (explicit instanceof Date) return explicit;

  var renewal = row[COLUMN.renewalDate - 1];
  var noticeDays = Number(row[COLUMN.noticeDays - 1]);
  if (!(renewal instanceof Date) || isNaN(noticeDays)) return null;

  var deadline = new Date(renewal.getTime());
  deadline.setDate(deadline.getDate() - noticeDays);
  return deadline;
}

function formatDate(date) {
  return Utilities.formatDate(date, Session.getScriptTimeZone(), "d MMMM yyyy");
}

/** Runs daily. Emails one digest covering every row that needs attention. */
function checkNoticeDeadlines() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(CONFIG.sheetName);
  if (!sheet) {
    throw new Error('No sheet named "' + CONFIG.sheetName + '" in this spreadsheet.');
  }

  var lastRow = sheet.getLastRow();
  if (lastRow < CONFIG.firstDataRow) return;

  var values = sheet
    .getRange(CONFIG.firstDataRow, 1, lastRow - CONFIG.firstDataRow + 1, COLUMN.status)
    .getValues();

  var approaching = [];
  var missed = [];

  for (var i = 0; i < values.length; i++) {
    var row = values[i];
    var status = String(row[COLUMN.status - 1] || "").toLowerCase();
    // Rows already dealt with are not reminders any more.
    if (status === "cancelled" || status === "renewed" || status === "done") continue;

    var deadline = noticeDeadlineFor(row);
    if (!deadline) continue;

    var days = daysUntil(deadline);
    if (days === null) continue;

    var line =
      row[COLUMN.counterparty - 1] +
      " — notice deadline " +
      formatDate(deadline) +
      " (" +
      (days < 0 ? Math.abs(days) + " days ago" : "in " + days + " days") +
      "), owner: " +
      (row[COLUMN.owner - 1] || "unassigned");

    if (days < 0) {
      missed.push(line);
    } else if (days <= CONFIG.reminderDays) {
      approaching.push(line);
    }
  }

  if (approaching.length === 0 && missed.length === 0) return;

  var body = "";
  if (missed.length > 0) {
    body += "NOTICE WINDOW CLOSED\n" + missed.join("\n") + "\n\n";
  }
  if (approaching.length > 0) {
    body +=
      "Notice deadline within " +
      CONFIG.reminderDays +
      " days\n" +
      approaching.join("\n") +
      "\n\n";
  }
  body += SpreadsheetApp.getActiveSpreadsheet().getUrl();

  MailApp.sendEmail({
    to: CONFIG.notifyEmail,
    subject:
      "Contract notice deadlines: " +
      approaching.length +
      " approaching, " +
      missed.length +
      " passed",
    body: body,
  });
}

Paste it into Extensions → Apps Script on the Sheet, set the four values at the top, and run setUpDailyTrigger once from the editor. Google will ask for permission to send mail as you the first time; that is the script requesting the scope it needs, and you can revoke it in your account settings at any time.

Two things to know before relying on it. Apps Script quotas limit how many emails an account can send per day, which is not a constraint at contract volumes but is worth knowing if you point it at something larger. And the script is code someone has to own: when it breaks — a renamed tab, a revoked authorization, a changed column order — it fails silently, so test it by setting a deadline a few days out and confirming the email arrives.

The script is also available as a file if you would rather not copy it out of a web page.

Step 5: Decide who can open what, deliberately

A folder of executed contracts is one of the more sensitive collections in a company. Employment agreements carry salaries. Vendor agreements carry pricing you are usually contractually obliged to keep confidential. Data processing agreements carry the names of subprocessors and, sometimes, personal data.

Give edit access to the two or three people who maintain the register, and view access to everyone who needs to read a contract. The distinction matters more than it sounds: edit access includes the ability to delete, and Drive's trash is emptied on a schedule.

Avoid “anyone with the link” on this folder entirely. Link sharing is convenient precisely because it removes the check on who is looking, and links leak the way any URL leaks — forwarded in email, pasted into a ticket, copied into a chat with a contractor. Share with named people or groups instead, and audit the list when someone changes role.

What this setup genuinely gives you

  • It is free, and you already pay for it. No new vendor, no procurement conversation, no security review.
  • Everyone already knows how to use it. Adoption is the thing that kills most contract tooling, and there is nothing to adopt here.
  • There is no migration. The contracts are already in Drive, or one drag away from being there.
  • Search genuinely works on filenames and on text Drive can extract, which is why the naming convention earns its keep.
  • Version history is automatic, so an overwritten Sheet is recoverable for the retention period on your plan.

Where the Drive setup stops holding

Five specific failure modes, in the order they usually show up. None of them is a reason to abandon Drive on its own; together they describe the ceiling.

Search stops at whatever Drive could read

Drive indexes the text it can extract from a file. A born-digital PDF is generally searchable; a contract that was printed, signed, scanned, and emailed back may not be, and a photograph of a signature page usually is not. That is precisely the population of documents most likely to hold a handwritten date or an amended term.

Test it rather than assuming either way: open a scanned contract, pick a distinctive phrase from the middle of it, and search Drive for that phrase. If the file does not come back, you have found the boundary of your search, and the filename convention is now doing all the work.

The Sheet is only as current as its least busy week

Nothing in this setup forces the tracker and reality to agree. A contract gets renegotiated, the renewal date moves, and the row still says what it said in March. The failure is invisible: the Sheet looks authoritative either way, and decisions get made from it.

The counter is ownership and cadence — one named person, one recurring thirty-minute review, and a rule that a contract is not filed until its row exists. Both are process, not tooling, which means both depend on someone caring about them next quarter as much as they do today.

Nothing warns you unless someone keeps the script alive

The script above closes the biggest gap, but it inherits a maintainer. Rename the tab, reorder the columns, let the authorization lapse, or have the person who set it up leave, and it stops sending — quietly, with no error anyone sees, because a script that does not run does not complain.

If you rely on it, put a canary row in the Sheet with a deadline that stays inside the reminder window, so a morning without an email is itself the signal that something broke.

Should you calendar the renewal date or the notice deadline?

Always the notice deadline. The renewal date is when the contract rolls over; the notice deadline is the last day you can stop it, and the two can be months apart. A reminder set for the renewal date arrives after the decision has already been made for you by default.

This is the specific mistake that costs the most money, and it is entirely arithmetic. A contract renewing on 15 March with a sixty-day notice period has a real deadline of 14 January. A calendar reminder set for the renewal date arrives two months after your leverage expired — you are not negotiating at that point, you are asking a favor.

Every date you track has to be the notice deadline, not the renewal date, and it has to be derived from the notice period rather than estimated. That is the whole reason the Sheet computes it and the filename carries it.

What happens when the person who owned the contract leaves

Most of what makes a Drive setup work is not in Drive. It is in one person's head: which vendor is being replaced anyway, which renewal is genuinely negotiable, why that agreement was filed under Services rather than Software. When they leave, the folder survives and the judgment does not.

Three things reduce the damage, and all three are worth doing before anyone hands in notice. Keep the files in a shared drive so ownership never sat with an individual account. Put a named owner in a column on every row, and reassign it as part of offboarding rather than discovering the gap at the next renewal. And write the decision, not just the date — one sentence in a notes column about why a contract was renewed is the difference between inheriting a register and inheriting a list.

How to tell whether it is still working

None of the above is an argument for buying software. It is an argument for being deliberate, and plenty of teams are deliberate in a spreadsheet for years. The useful question is not how many contracts you have but whether the setup is still holding, and three signals answer it better than a count does.

First: has anyone missed a notice deadline in the past year? Once is a bad week; twice is a system telling you something. Second: how many people need an answer from the register in a normal month? A tracker maintained by one person and read by one person is stable; the same tracker read by finance, operations, and whoever is covering a departure is a coordination problem. Third: how long does it take to answer “what are we committed to next quarter, and what can we still get out of?” If that takes an afternoon, the cost is already being paid — just in hours rather than in a subscription.

There is no contract count that answers this, and treating one as the trigger gets the risk backwards: a single lease with a six-month notice period carries more exposure than a long tail of small subscriptions nobody has to act on. So add a fourth question, and make it the first one you ask — what is your largest single commitment, and what would it cost to miss its notice window? If that number is uncomfortable, the size of the portfolio is beside the point.

Where Lumipact fits

Lumipact does the parts of the setup above that depend on somebody remembering. It reads the contract on upload and extracts the counterparty, dates, value, and notice period, with each field linked to the passage it came from, so the register fills itself instead of being typed. Alerts fire against the notice deadline rather than the renewal date, to a named owner, and escalate if nobody acknowledges them.

What it does not do: there is no e-signature, and no drafting or redlining. It picks up after the signature. There is also no Google Drive sync — contracts come in by bulk upload, CSV, or email forwarding, so a Drive-based archive is a folder you drag in rather than a connection you configure.

It costs money and a spreadsheet does not. If the Drive setup on this page is working for you, keep it.

Start free — no credit card

Frequently asked questions

Can you manage contracts in Google Drive?

You can store them, and for a small set of rarely-changing agreements that may be enough. What Drive cannot do is tell you what is inside the files: renewal dates, notice deadlines, and owners live in the documents, so every question means opening PDFs one by one and reading.

How do you get renewal reminders from Google Drive?

Google Drive has no reminder feature, so teams bolt one on: a shared spreadsheet of dates plus calendar events, maintained by hand. That works until the person maintaining it is on holiday, leaves, or simply misses one row. The reminder is only as reliable as the manual step that created it.

At what point does a shared drive stop being enough for contracts?

When missing a date starts costing money. The warning signs are concrete: an auto-renewal that surprised you on an invoice, a notice deadline discovered after it passed, or nobody being able to say who owns a vendor relationship. Folder structure does not fix those — they are visibility problems, not storage problems.

Does Lumipact import contracts from Google Drive?

Not with a direct integration — a Drive sync does not exist today. Getting contracts in means bulk-uploading files from any folder, importing a CSV, or forwarding documents to your workspace's email ingest address, and the AI extracts key terms on arrival. Download from Drive, drop the folder in, and the extraction does the rest.

Should you keep using Google Drive alongside Lumipact?

Yes. Drive remains a good home for everything that is not a contract: proposals, working drafts, project files. Lumipact replaces the tracking layer, not the storage habit — the signed agreement lives in Lumipact where its dates and owner are visible, while day-to-day collaboration stays wherever your team already works.

    We use privacy-friendly analytics to understand which pages are useful. No ads, no cross-site tracking. Read our cookie policy.