The problem

You have a Google Form collecting responses. Client intake forms, project requests, event registrations, service inquiries, job applications. The responses land in a spreadsheet, and then you have to manually turn each one into a formatted document.

That usually means: open the response sheet, find the new entry, open a Doc template, copy and paste each field into the right spot, format it, export as PDF or share the Doc. Do that 5 times a day and you've lost an hour to copying and pasting.

Google Forms is great at collecting structured data. It's terrible at doing anything with that data after collection. There's no built-in way to say "when someone submits this form, create a formatted document from their answers."

Apps Script fills that gap. This guide shows you exactly how to connect a Google Form to a Google Doc template so that every submission automatically generates a formatted document. No add-ons. No third-party tools. Just a script that runs inside your Sheet.

Skip the setup? Get the pre-built template. Form-to-Doc Template $49

What we're building

An automation that triggers every time someone submits your Google Form. It takes the response data, plugs it into a Google Doc template (replacing placeholder tags with the actual answers), converts the result to PDF, saves it to a Drive folder, and optionally emails it to someone.

This works for any form-to-document workflow: intake summaries, client briefs, service agreements, confirmation letters, onboarding packets, event registrations, quote requests.

Before you start

You need:

  1. A Google Form that's connected to a response spreadsheet (this happens automatically when you create a form)
  2. A Google Doc template with placeholder tags matching your form field names
  3. A Google Drive folder for the output documents

Connecting your form to a Sheet

If your form doesn't already have a linked spreadsheet, open the form in edit mode, click the "Responses" tab, then click the green Sheets icon. This creates a response Sheet where every submission becomes a new row. The column headers match your form question titles.

Setting up the Doc template

Create a Google Doc that looks exactly like you want the finished document to look. Use placeholder tags in double curly braces wherever you want form data to appear:

  • {{Full Name}}
  • {{Email Address}}
  • {{Company}}
  • {{Service Requested}}
  • {{Project Details}}
  • {{Budget Range}}

The tag names must match your form question titles (which become the column headers in the response Sheet). Open your Doc URL and copy the document ID from between /d/ and /edit.

Setting up the output folder

Create a Drive folder for the generated documents. Copy the folder ID from the URL (the string after /folders/).

Step-by-step setup

Step 1: Open the response Sheet

Go to your Google Form, click Responses, click the Sheets icon. This opens the response spreadsheet. Verify that the column headers match your form questions.

Step 2: Open the Apps Script editor

In the response Sheet, click Extensions, then Apps Script. Delete any existing code.

Step 3: Paste the form-to-document script

javascript
function onFormSubmit(e) {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  var row = sheet.getLastRow();

  // === CONFIGURATION ===
  var templateId = 'YOUR\_GOOGLE\_DOC\_TEMPLATE\_ID';
  var folderId   = 'YOUR\_DRIVE\_FOLDER\_ID';
  var sendEmail  = true;
  var emailField = 'Email Address'; // column header name for email
  var docTitle   = 'Intake Summary'; // prefix for the generated doc name
  // === END CONFIGURATION ===

  var headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0];
  var data    = sheet.getRange(row, 1, 1, sheet.getLastColumn()).getValues()[0];

  // Build the document name
  var nameField = data[0]; // uses first column value
  var docName   = docTitle + ' - ' + nameField;

  // Copy the template and replace placeholders
  var folder = DriveApp.getFolderById(folderId);
  var copy   = DriveApp.getFileById(templateId).makeCopy(docName, folder);
  var doc    = DocumentApp.openById(copy.getId());
  var body   = doc.getBody();

  for (var i = 0; i < headers.length; i++) {
var placeholder = '\\\\\{\\\\\{' + headers[i] + '\\\\\}\\\\\}';
var value = data[i];

// Format dates nicely
if (value instanceof Date) {
  value = Utilities.formatDate(value, Session.getScriptTimeZone(), 'yyyy-MM-dd');
}

body.replaceText(placeholder, value || '');
  }
  doc.saveAndClose();

  // Convert to PDF
  var pdfBlob = DriveApp.getFileById(copy.getId()).getAs('application/pdf');
  var pdfFile = folder.createFile(pdfBlob).setName(docName + '.pdf');

  // Keep the Doc or trash it (set to true to keep both Doc and PDF)
  var keepDoc = false;
  if (!keepDoc) {
DriveApp.getFileById(copy.getId()).setTrashed(true);
  }

  // Email the PDF
  if (sendEmail) {
var emailIndex = headers.indexOf(emailField);
if (emailIndex !== -1) {
  var email = data[emailIndex];
  if (email && email.toString().includes('@')) {
    MailApp.sendEmail({
      to: email,
      subject: docName,
      body: 'Thank you for your submission. Please find the attached document.',
      attachments: [pdfFile.getAs(MimeType.PDF)]
    });
  }
}
  }

  // Mark the row as processed
  var statusCol = headers.length + 1;
  sheet.getRange(row, statusCol).setValue('Doc created ' + new Date().toLocaleDateString());
}

Step 4: Configure the script

Update the configuration block near the top:

  1. Replace YOUR\_GOOGLE\_DOC\_TEMPLATE\_ID with your Doc template's ID
  2. Replace YOUR\_DRIVE\_FOLDER\_ID with your output folder's ID
  3. Set emailField to the exact column header name that contains the respondent's email
  4. Set docTitle to whatever prefix you want on the generated filenames
  5. Set sendEmail to false if you don't want to email the document

Step 5: Set up the form submit trigger

This is the step that makes it automatic. In the Apps Script editor:

  1. Click the clock icon in the left sidebar (Triggers)
  2. Click "Add Trigger" in the bottom right
  3. Set the function to onFormSubmit
  4. Set the event source to "From spreadsheet"
  5. Set the event type to "On form submit"
  6. Click Save

Google will ask for authorization. Click through the permissions.

Step 6: Test it

Submit a test response through your Google Form. Wait 10 to 30 seconds (triggers aren't instant). Check your Drive folder. The generated document should be there. If you enabled email, check the inbox for the test email address you used.

How to extend this

Generate a Doc instead of a PDF. Remove the PDF conversion lines and the setTrashed line. Set keepDoc to true. The output will be an editable Google Doc instead of a locked PDF. Useful when you want to review or modify the document before sending it.

Send the document to someone other than the respondent. Change the email logic to send to a fixed address: MailApp.sendEmail({to: 'yourteam@company.com', ...}). Or add a second email send so both the respondent and your team get a copy.

Route documents to different folders based on form answers. Add conditional logic that checks a specific column value and picks a folder ID based on the answer. For example, if the "Department" field is "Sales," save to the Sales folder. If it's "Support," save to the Support folder.

Add a confirmation page URL. After creating the PDF, write the Drive file URL back to the Sheet so you have a direct link to every generated document: sheet.getRange(row, statusCol + 1).setValue(pdfFile.getUrl());

Common issues

"This script requires authorization." You need to run the script manually once before the trigger will work. Open Apps Script, select onFormSubmit from the dropdown, click Run, and approve the permissions.

Trigger doesn't fire. Make sure the trigger is set to "From spreadsheet" and "On form submit." If you set it to "From form" instead, it won't have access to the Sheet data. Also check that the form is actually linked to this specific Sheet.

Timestamps show as numbers. Google Forms stores timestamps as Date objects. The script handles this with the date formatting block. If you're seeing raw numbers, make sure the Utilities.formatDate line is running for date columns.

Document looks blank. This almost always means your placeholder tags don't match the column headers. Open your Doc template and your response Sheet side by side. Verify that every {{tag}} in the Doc matches a column header in the Sheet exactly.