appscript.dev
Automation Beginner Docs

Build a fillable intake form inside a Doc

Create structured intake forms with placeholder fields readers can fill — for client briefs.

Published Jan 11, 2026

Every project starts with the same questions — what is the goal, who is the audience, what is the budget — and every time someone asks them in a slightly different order, a brief comes back missing the one detail that mattered. Northwind wants project intake to be the same shape every time: the same fields, in the same order, with a clear place for the client to write.

This script generates a fresh intake Doc for a named client. Each question is a heading, and under it sits a highlighted placeholder line the client types over. A Google Form would do something similar, but a Doc is friendlier for long briefs — the client can paste images, drop in links, and the result reads like a real document, not a survey export.

What you’ll need

  • Permission to create Google Docs in your Drive — DocumentApp.create makes a new file each time.
  • The list of intake questions you want on every form. Edit the FIELDS array below to match Northwind’s actual brief.
  • Nothing else — there is no template Doc to maintain; the script builds the whole document.

The script

// The questions that appear on every intake form, in order.
const FIELDS = [
  'Project name:',
  'Primary contact:',
  'Goal (one sentence):',
  'Target audience:',
  'Inspiration links:',
  'Budget range:',
  'Deadline:',
  "Anything we shouldn't do:",
];

// Background colour for the placeholder answer lines.
const ANSWER_HIGHLIGHT = '#fefce8';

// Default text shown in each answer line.
const ANSWER_PLACEHOLDER = '[your answer here]';

/**
 * Creates a structured project intake Doc for one client.
 * Each field becomes a heading with a highlighted answer line.
 *
 * @param {string} clientName  Name of the client, used in the title.
 * @return {string} The URL of the new Doc.
 */
function createIntakeForm(clientName) {
  // Guard against an empty name producing a confusing title.
  if (!clientName) {
    throw new Error('createIntakeForm needs a client name.');
  }

  // 1. Create the Doc and grab its body.
  const doc = DocumentApp.create(`Project intake — ${clientName}`);
  const body = doc.getBody();

  // 2. Add the title at the top.
  body.appendParagraph('Northwind — Project intake')
    .setHeading(DocumentApp.ParagraphHeading.TITLE);

  // 3. For each field, add a heading and a highlighted answer line.
  for (const field of FIELDS) {
    body.appendParagraph(field)
      .setHeading(DocumentApp.ParagraphHeading.HEADING3);
    body.appendParagraph(ANSWER_PLACEHOLDER)
      .setBackgroundColor(ANSWER_HIGHLIGHT);
  }

  // 4. Save, close, and hand back the link to share.
  doc.saveAndClose();
  return doc.getUrl();
}

How it works

  1. createIntakeForm takes a client name and first checks it is not empty — an empty name would produce a confusing “Project intake — ” title.
  2. It calls DocumentApp.create to make a brand-new Doc named after the client, then gets its body to write into.
  3. It adds a title paragraph styled with the TITLE heading so the document opens with a clear header.
  4. It loops over the FIELDS array. For each question it appends a HEADING3 paragraph for the label, then a second paragraph holding the placeholder text on a pale yellow background.
  5. The highlight makes the answer lines obvious — the client can see exactly where to type and what to replace.
  6. It calls saveAndClose to commit the document and returns getUrl so the caller has a link to send straight to the client.

Example run

Calling createIntakeForm('Acme Coffee') creates a Doc titled Project intake — Acme Coffee that looks like this:

Northwind — Project intake

Project name:

[your answer here]

Primary contact:

[your answer here]

Goal (one sentence):

[your answer here]

(…and so on for every field)

Each [your answer here] line sits on a pale yellow background, so the client sees at a glance which lines to fill in.

Run it

This is an on-demand job — run it whenever a new client comes in:

  1. Paste the script into the Apps Script editor.
  2. Add a small wrapper that names the client and logs the link:
function runIntake() {
  const url = createIntakeForm('Acme Coffee');
  Logger.log('Intake form ready: ' + url);
}
  1. Select runIntake, click Run, and approve the authorisation prompt the first time.
  2. Open the logged URL, share the Doc with the client, and ask them to type over the highlighted lines.

Watch out for

  • The placeholder lines are ordinary paragraphs, not protected fields. A client could delete a heading or reorder sections — review the returned brief rather than trusting its structure blindly.
  • New Docs land in the root of your Drive. Move the file into a client folder after creating it, or extend the script to create it inside a specific folder with DriveApp.
  • The highlight is cosmetic. If a client types over the placeholder but the background stays yellow, that is expected — the colour is on the paragraph, not the placeholder text.
  • For short, strictly structured intake, a Google Form gives you cleaner data and a spreadsheet of responses. Use this Doc approach when the brief is long and benefits from free-form writing, images, and links.
  • Each run creates a separate Doc. Calling it twice for the same client leaves two intake files — name carefully or check Drive before regenerating.

Related