Form responses often die in a spreadsheet.

If your team needs a clean, formatted record of a submission, manually copying answers from a grid into a document is a waste of time.

Google Apps Script bridges this gap by automatically converting form data into a readable PDF and emailing it the moment a user hits submit.

It requires a bit of upfront code, but the payoff is a completely hands-off reporting pipeline.

What do you need before writing the script?

Before you open the code editor, you need to ensure your form and environment are set up correctly.

Trying to write the script while still changing your form questions will break your data mapping and cause unnecessary errors.

Prerequisite item Role in the workflow How to verify
A finalized Google Form Acts as the data source and the trigger event for the script. Review your form, ensure all required fields are marked, and submit one test response.
Consistent question types Dictates how the script extracts the data (e.g., text vs arrays). Check that multiple-choice or checkbox questions are fully defined and not likely to change.
Google Workspace or Gmail account Provides the Apps Script environment and the email sending quota. Log into your Google account and ensure you have access to Gmail and Google Drive.
Target email address The destination where the generated PDF will be sent. Confirm the exact email address or group alias that needs to receive the summaries.
Basic understanding of HTML Used to format the layout of the PDF document. You should know how to use basic tags like paragraphs, bold text, and line breaks.

If you are migrating an existing paper process, you might first turn a PDF intake form into a Google Form to get your digital baseline ready.

Once your form structure is locked in, you can safely build the automation around it.

How do you bind the Apps Script editor to your Google Form?

Apps Script can run as a standalone file in your Google Drive, but for this workflow, you want a container-bound script.

A container-bound script is attached directly to your Google Form.

This gives the script native context about the form, meaning you do not have to hardcode the form ID to fetch responses.

  1. Open your finalized Google Form in edit mode.
  2. Click the three-dot menu icon (More) in the top right corner of the screen, next to your profile picture.
  3. Select Script editor from the dropdown menu.
  4. Wait for the new browser tab to open the Google Apps Script dashboard.
  5. Click on Untitled project in the top left corner.
  6. Rename the project to something descriptive, like Form to PDF Emailer, and click Rename.
  7. Clear out the default function myFunction() {} block in the Code.gs file so you have a blank canvas.

You now have a script environment permanently attached to this specific form.

If you make a copy of the Google Form later, the bound script will copy over with it.

How do you write the script to generate and email the PDF?

The script needs to listen for a form submission, extract the answers, inject them into an HTML layout, convert that HTML into a PDF file, and attach it to an email.

We use HTML as an intermediary step because Apps Script does not have a native drag-and-drop PDF builder.

Instead, we tell the HtmlService to render a lightweight, hidden webpage and then export that page as a PDF blob.

Copy and paste the following code into your Code.gs file.

/**
 * Triggered when a user submits the Google Form.
 * Generates a PDF summary and emails it.
 * 
 * @param {Object} e - The event object containing the form response.
 */
function onFormSubmitHandler(e) {
  // 1. Define the destination email address
  var targetEmail = "[email protected]"; 
  var emailSubject = "New Form Submission PDF Summary";
  
  // 2. Fetch the form response from the event object
  var formResponse = e.response;
  var itemResponses = formResponse.getItemResponses();
  
  // 3. Start building the HTML template for the PDF
  var htmlBody = "<div style='font-family: Arial, sans-serif; padding: 20px;'>";
  htmlBody += "<h2 style='color: #333;'>Form Submission Summary</h2>";
  htmlBody += "<hr>";
  
  // 4. Loop through each question and answer
  for (var i = 0; i < itemResponses.length; i++) {
    var itemResponse = itemResponses[i];
    var questionTitle = itemResponse.getItem().getTitle();
    var answer = itemResponse.getResponse();
    
    // Handle array responses (like Checkbox questions)
    if (Array.isArray(answer)) {
      answer = answer.join(", ");
    }
    
    // Handle empty answers
    if (!answer) {
      answer = "<em>No response provided</em>";
    }
    
    // Append the question and answer to the HTML string
    htmlBody += "<p><strong>" + questionTitle + ":</strong><br>";
    htmlBody += answer + "</p>";
  }
  
  htmlBody += "<hr>";
  htmlBody += "<p style='font-size: 12px; color: #666;'>Generated automatically via Google Apps Script.</p>";
  htmlBody += "</div>";
  
  // 5. Convert the HTML string into a PDF Blob
  var htmlOutput = HtmlService.createHtmlOutput(htmlBody);
  var pdfBlob = htmlOutput.getAs('application/pdf');
  
  // Name the PDF file
  pdfBlob.setName("Submission_Summary.pdf");
  
  // 6. Send the email with the PDF attached
  MailApp.sendEmail({
    to: targetEmail,
    subject: emailSubject,
    htmlBody: "A new form submission was received. Please see the attached PDF summary.",
    attachments: [pdfBlob]
  });
}

Make sure to replace [email protected] with the actual email address you want to notify.

This script relies heavily on the event object, represented by the parameter e.

When Google Forms triggers the script, it passes this e object behind the scenes.

The e object contains the exact data the user just submitted, which is much more efficient than asking the script to search your form for the newest response.

Notice that we use inline CSS styles (style='font-family: Arial...') within the HTML string.

The Apps Script PDF generator runs on an older rendering engine that ignores external stylesheets and complex modern CSS like Flexbox or Grid.

Keep your formatting simple, relying on standard text tags, line breaks, and basic tables for the best results.

How do you automate the script to run on every form submission?

Writing the code is only half the job.

If you click the Run button in the editor right now, the script will fail.

It will fail because the editor does not provide the e event object - that object only exists when a user actually clicks submit on the live form.

To connect the live form to your code, you need to configure an installable trigger.

An installable trigger tells Google's servers to watch your form and execute your specific function whenever a submission occurs.

  1. In the Apps Script editor, look at the left-hand sidebar menu.
  2. Click the Triggers icon, which looks like an alarm clock.
  3. Click the blue + Add Trigger button in the bottom right corner of the screen.
  4. In the Choose which function to run dropdown, select onFormSubmitHandler.
  5. Leave Choose which deployment should run set to Head.
  6. In the Select event source dropdown, choose From form.
  7. In the Select event type dropdown, choose On form submit.
  8. Click Save.

When you click save, Google will prompt you to authorize the script.

This happens because the script needs your permission to read form data and send emails from your account.

Choose your Google account from the popup window.

You may see a warning screen stating "Google hasn't verified this app."

Since you wrote the code yourself and know exactly what it does, click Advanced at the bottom of the warning, then click Go to Untitled project (unsafe).

Click Allow on the final screen to grant the necessary permissions.

Your trigger is now active, and the next time someone submits your form, a PDF will land in your inbox.

Why is your PDF generator script failing?

Even with careful setup, scripts can break when real users interact with them.

Because this workflow relies on specific triggers and data objects, debugging requires knowing exactly where to look in the Apps Script execution logs.

Error message Root cause Quick fix
TypeError: Cannot read property 'response' of undefined You clicked the Run button manually in the editor. The script expects the e object from a live submission. Stop clicking Run. Submit a test response through the actual Google Form to test the code.
Exception: You do not have permission to send email The script was not authorized to use the MailApp service, or scopes changed after the trigger was set. Delete the existing trigger, create a new one, and go through the authorization flow again.
The PDF file is completely blank The htmlBody string is empty or contains malformed HTML tags that broke the PDF renderer. Check your string concatenation (+=) and ensure all HTML tags are properly closed.
Service invoked too many times for one day You have hit the daily limit for sending emails through Google Workspace or Gmail. Wait 24 hours for the quota to reset, or switch to a paid Workspace tier if you are on a free account.
TypeError: Cannot call method "getTitle" of undefined The script tried to read a question that was deleted from the form, or the array index is out of bounds. Ensure you are looping through itemResponses.length correctly and not hardcoding index numbers.

Expert tip: If you need to debug the data inside the event object without sending an email, use console.log(e.response.getItemResponses().length) and check the Executions tab in the left sidebar after submitting a test form.

Understanding these failure modes saves hours of frustration.

Always test your script with a form response that leaves optional questions blank to ensure your code handles empty data gracefully.

What are the execution limits and security risks to watch out for?

Apps Script is powerful, but it runs on shared Google infrastructure.

To prevent abuse, Google enforces strict quotas and limits on what your scripts can do.

If you are building an automated PDF pipeline for a high-traffic form, you must design around these constraints.

  • Daily email quotas: Free Gmail accounts are limited to sending 100 emails per day via Apps Script. Paid Google Workspace accounts can send up to 1,500 emails per day. If you expect more submissions than your tier allows, the script will silently fail after hitting the cap.
  • Execution time limits: A single script execution is allowed to run for a maximum of 6 minutes. Generating a simple PDF and sending an email usually takes less than 3 seconds, so this is rarely an issue unless you are processing massive image attachments.
  • Trigger execution limits: A single user can have a maximum of 20 triggers per script. You only need one trigger for this workflow, but keep it in mind if you expand the project later.
  • Run-as permissions: Installable triggers run under the authority of the user who created them. This means every email sent by the script will come from your email address, not a generic "no-reply" address.
  • OAuth scope exposure: When you authorize the script, you grant it broad access to your forms and email capabilities. Always review the scopes requested. If you copy a script from the internet that asks for Google Drive deletion permissions when it only needs to send an email, stop and review the code.

If you find yourself frequently hitting the email quota, you may need to redesign the workflow.

Instead of emailing every PDF, you could alter the script to save the PDFs directly to a shared Google Drive folder and send a single daily digest email instead.

FAQ

Can I customize the HTML template used for the PDF summary layout?

Yes, you can separate your HTML from your JavaScript to make formatting easier. You create a new HTML file in the Apps Script editor (e.g., Template.html), design your layout using standard HTML tags, and use HtmlService.createTemplateFromFile('Template') in your script. You can then pass the form answers into the template variables before evaluating it into a PDF.

How do I send the generated PDF to the person who submitted the form instead of myself?

If your form is set to collect email addresses, you can extract the submitter's email using e.response.getRespondentEmail(). Alternatively, if you have a specific question asking for their email, loop through the responses to find that answer and assign it to your targetEmail variable. Then, update the MailApp.sendEmail() function to use that dynamically captured address.

What happens to the script if my Google Form contains file upload questions?

The standard getItemResponses() method does not return the actual uploaded file; it returns the unique Google Drive file ID as a text string. If you want to include the file or a link to it in the PDF, you must use DriveApp.getFileById(fileId) to fetch the file details. You can then insert the file's URL into your HTML string as a clickable hyperlink.

Is there a way to store the generated PDFs in a specific Google Drive folder?

Yes, you can save the PDF blob to Drive before or after emailing it. You will need the ID of your target folder, which you can find in its URL. Add a line of code like DriveApp.getFolderById("YOUR_FOLDER_ID").createFile(pdfBlob); to permanently store the document alongside the email delivery.

Building automated workflows in Apps Script forces you to think about data structure early, which often reveals flaws in how the initial form was built. If you find yourself constantly tweaking form fields to make the PDF look right, you might benefit from tools that work in reverse. For example, Doc2Form lets you draft your ideal layout in a document first, and it will handle the heavy lifting to generate the matching Google Form. Getting the data structure right on day one makes everything downstream - especially custom scripting - much more reliable.