Form Choice Limiter
Cap how many people can pick each option in a Google Form. When an option fills up, it closes itself.
The problem
Google Forms has no way to say “only four people may take Monday 9am”. You find out the slot was oversubscribed after everyone has already booked it.
The usual fix is a marketplace add-on, which means granting a third party access to your form and every response in it. For a school, a clinic or an HR team, that is often exactly why the answer is no.
How it works
Open your form's script editor
Your Form → ⋮ → Apps Script.
Paste one file in
Replace everything in Code.gs with FormChoiceLimiter.gs.
Set your limits and run setup
Edit the CONFIG block, run setup once, approve the prompt.
It runs entirely inside your own Google account. Nothing is installed, nothing is reviewed, and no third party, including me, can see your form or your responses.
Set the limits in plain English
limits: {
'Pick a time slot': {
'Monday 9:00': 4, // four seats
'Monday 10:00': 4,
'Tuesday 14:00': 2
},
'Equipment': { 'Camera': 1, 'Tripod': 2 }
}Anything you don’t list stays unlimited. A limit of 0 makes an option unavailable from the start.
The detail most versions get wrong
A Google Forms choice question cannot have zero options. When the last seat of the last option goes, the obvious implementation tries to write an empty list, the update fails, usually silently, and the form carries on taking bookings for slots that are already full.
This one detects that case and relabels every option instead of emptying the question, and can close the form with a message if you want it to. That behaviour is covered by a test that runs against the exact file you receive.
The four ways a hand-written version fails silently The empty choice list, the re-snapshot that loses an option permanently, the missing lock, and the question title that does not match.
Looking for a Choice Eliminator alternative?
If you landed here searching for Choice Eliminator, Choice Eliminator Lite or Choice Eliminator 2, this does the same job with two differences.
- It is not an add-on. Nothing is installed and no third party can read your form or its responses. The code runs in your own Apps Script project.
- It cannot stop working because someone else's service went down or changed its pricing. It is a file you own.
- The free version below handles one question. The $9 version handles as many as you like.
Free version: build it for your form, below
Fill in your question and options and it writes the script for you. The most common reason these break is a question title that does not match the form exactly, so this removes that step. It handles a single multiple-choice question and it genuinely works. No email, no signup, nothing to buy. The paid version adds multiple questions, dropdown and checkbox support, strike-through mode, auto-close, restore, and an install guide.
This has to match character for character, including capitals and punctuation. Pasting it is safer than typing it.
Your script
/**
* Form Choice Limiter: free single-question version.
* Generated for: Pick a time slot
*
* Setup: Form → ⋮ → Apps Script → paste this in → run `setupLimiter` once.
*/
var QUESTION = 'Pick a time slot';
var MODE = 'hide';
var LIMITS = {
// add at least one option above
};
function setupLimiter() {
var form = FormApp.getActiveForm();
var props = PropertiesService.getDocumentProperties();
// Snapshot ONCE. Re-running setup after an option has already closed would otherwise
// snapshot the trimmed list, and restoreAllChoices() could never bring it back.
// Use resetLimiter() if you deliberately want to re-read the current options.
if (!props.getProperty('FCL_ORIG')) {
props.setProperty('FCL_ORIG', JSON.stringify(item_(form).getChoices().map(function (c) {
return String(c.getValue()).replace(/ — FULL$/, '');
})));
}
ScriptApp.getProjectTriggers().forEach(function (t) {
if (t.getHandlerFunction() === 'applyLimit') ScriptApp.deleteTrigger(t);
});
ScriptApp.newTrigger('applyLimit').forForm(form).onFormSubmit().create();
applyLimit();
}
function applyLimit() {
var lock = LockService.getScriptLock();
try { lock.waitLock(30000); } catch (e) { return; }
try {
var form = FormApp.getActiveForm();
var original = JSON.parse(PropertiesService.getDocumentProperties().getProperty('FCL_ORIG'));
var counts = {};
form.getResponses().forEach(function (fr) {
fr.getItemResponses().forEach(function (ir) {
if (ir.getItem().getTitle() !== QUESTION) return;
var v = ir.getResponse();
(Array.isArray(v) ? v : [v]).forEach(function (c) { if (c) counts[c] = (counts[c] || 0) + 1; });
});
});
var full = original.filter(function (o) {
var l = LIMITS[o];
return typeof l === 'number' && (counts[o] || 0) >= l;
});
var next;
if (MODE === 'strike') {
next = original.map(function (o) { return full.indexOf(o) === -1 ? o : o + ' — FULL'; });
} else {
next = original.filter(function (o) { return full.indexOf(o) === -1; });
// a Forms question cannot have zero choices
if (!next.length) next = original.map(function (o) { return o + ' — FULL'; });
}
item_(form).setChoiceValues(next);
} finally { lock.releaseLock(); }
}
function restoreAllChoices() {
var form = FormApp.getActiveForm();
var original = JSON.parse(
PropertiesService.getDocumentProperties().getProperty('FCL_ORIG') || 'null');
if (original) item_(form).setChoiceValues(original);
ScriptApp.getProjectTriggers().forEach(function (t) {
if (t.getHandlerFunction() === 'applyLimit') ScriptApp.deleteTrigger(t);
});
}
/** Forget the snapshot so the next setupLimiter() re-reads the current option list. */
function resetLimiter() {
restoreAllChoices();
PropertiesService.getDocumentProperties().deleteProperty('FCL_ORIG');
}
function item_(form) {
var f = form.getItems(FormApp.ItemType.MULTIPLE_CHOICE)
.filter(function (i) { return i.getTitle() === QUESTION; })[0];
if (!f) throw new Error('No multiple-choice question titled "' + QUESTION + '"');
return f.asMultipleChoiceItem();
}
Free, and it runs entirely in your own Google account. Nothing is installed and no third party can read your form or its responses.
Need more than one question?
The script above limits a single multiple-choice question. The paid version handles as many questions as you like, plus dropdown and checkbox questions, strike-through mode, auto-closing the form when everything is taken, and a one-command restore. with an install guide and support if it misbehaves on your form.
Get the full version for $9Form → ⋮ → Apps Script → paste → edit QUESTION and LIMITS → run setupLimiter once.
What you get
- FormChoiceLimiter.gs, the complete commented script
- Multiple choice, dropdown and checkbox questions
- Any number of questions, each with its own per-option limits
- Hide a full option, or keep it visible marked “— FULL”
- Optionally close the form once everything is taken
- restoreAllChoices() to put every option back
- A 2-minute install guide, plus troubleshooting
Form Choice Limiter, $9
One-time. Works on personal Gmail and Google Workspace accounts.
Something not working on your form? Email me with the question title and what you expected, and I’ll fix it.