Complete English Edition

Google Apps Script
Form Integration Guide

Send a contact form, a reCAPTCHA token, and an optional Base64 image from your website to a Google Apps Script Web App through HTTP POST, then validate the request, upload the image, write the submission to Google Sheets, send an email notification, and log errors.

3 POST content formats
5 MB Default image limit
19 Complete chapters
Asia/Taipei Default time zone

1End-to-End Workflow

Use case: a website sends a contact form, a reCAPTCHA token, and an optional Base64 image to a Google Apps Script Web App through HTTP POST.

Receive Data

Supports URL-encoded, multipart, and JSON requests.

Validate Safely

Validates reCAPTCHA, fields, and images.

Store Results

Images go to Drive and text goes to Sheets.

Notify and Log

Sends email and writes errors to LOG.

  1. Accept application/x-www-form-urlencoded, multipart/form-data, or application/json.
  2. Verify Google reCAPTCHA.
  3. Validate the name, phone number, email address, message, and image.
  4. Save the Base64 image to a specified Google Drive folder.
  5. Write the form submission to Google Sheets.
  6. Send an HTML email and image attachment to the administrator.
  7. Write image, email, and main-process errors to a LOG sheet.
  8. Return a consistent JSON response to the frontend.

2Recommended Apps Script File Structure

              Code.gs DriveAuthorization.gs appsscript.json
            
  • Code.gs: Request handling, validation, storage, notification, and error logging.
  • DriveAuthorization.gs: Manual Drive OAuth authorization and folder-access testing.
  • appsscript.json: Optional manifest for explicitly declaring OAuth scopes.

3Complete Optimized Code: Code.gs

Paste the following code into Code.gs. Identifiers and Google API names remain unchanged so the code can be used directly. Comments and user-facing messages are in English.

Before production: Replace every setting containing REPLACE WITH, and store the reCAPTCHA secret in Script Properties instead of hard-coding it.
Expand or collapse the full Code.gs file
                
              

4Drive Authorization and Access Test

Do not add a trailing underscore to a function that must be run manually. Functions without the trailing underscore are easier to select from the Apps Script editor toolbar.

Expand the full DriveAuthorization.gs file
                
              

5Required Configuration

At minimum, update the following settings:

              SPREADSHEET_ID: "YOUR ACTUAL GOOGLE SPREADSHEET ID", FOLDER_ID: "YOUR ACTUAL GOOGLE DRIVE FOLDER ID", SHEET_NAME: "Sheet1", ADMIN_EMAIL: "YOUR ACTUAL ADMINISTRATOR EMAIL"
            

Spreadsheet ID

Example URL: https://docs.google.com/spreadsheets/d/1AbCdEf123456/edit
The ID is: 1AbCdEf123456

Folder ID

Example URL: https://drive.google.com/drive/folders/1XyZ987654
The ID is: 1XyZ987654

6Configure the reCAPTCHA Secret

Do not hard-code the secret key. If a secret has appeared in a public message, repository, screenshot, or shared document, revoke it and generate a new one.

In Apps Script, open:

              Project Settings → Script Properties → Add script property
            
Property Value
RECAPTCHA_SECRET Your actual reCAPTCHA secret key

7Google Sheets Column Order

Column Content
A Submission time
B Name
C Phone
D Email
E Message
F Image link

The LOG sheet is created automatically when it does not exist.

8Trigger Google Drive Authorization

  1. Paste authorizeDriveAccess into DriveAuthorization.gs.
  2. Set the actual TEST_FOLDER_ID.
  3. Save the project.
  4. Select authorizeDriveAccess from the function menu in the Apps Script editor.
  5. Click Run.
  6. Complete the Google OAuth authorization flow.
  7. Confirm that the test text file appears in the target Drive folder.
Do not run doPost manually. It requires an event object named e from the deployed Web App.

9If authorizeDriveAccess Is Missing from the Function Menu

  • The function name must not end with an underscore.
  • The function must be declared at the top level.
  • The project must be saved first.
  • No .gs file may contain a syntax error.
  • Reload the Apps Script editor.
              // Correct: available for manual execution function authorizeDriveAccess() {}  // Not recommended as a manual entry point function authorizeDriveAccess_() {}  // Internal helper functions may use a trailing underscore function parseDataUrl_() {}
            

10Google Drive Folder Sharing Permissions

OAuth authorization and folder sharing are separate requirements. The account that deploys the Web App must:

  • Own the folder or be explicitly added to it.
  • Have permission to create or edit files.
When the Web App is configured to “Execute as me,” “me” means the account that deployed the Web App.

11Web App Deployment

              Deployment type: Web app Execute as: Me Who has access: Select according to your website requirements
            

When the Web App executes as the deployer:

  • Drive uses the deployer's permissions.
  • Spreadsheet uses the deployer's permissions.
  • MailApp uses the deployer's email quota.
  • Website visitors do not need access to the Drive folder.

Redeploy After Updating the Code

              Deploy → Manage deployments → Edit → Select a new version → Deploy
            

Use the /exec URL on the production website.

12Optional appsscript.json Manifest

Apps Script usually infers the required permissions automatically. To declare OAuth scopes explicitly, use:

              {"timeZone":"Asia/Taipei","exceptionLogging":"STACKDRIVER","runtimeVersion":"V8","oauthScopes":["https://www.googleapis.com/auth/drive","https://www.googleapis.com/auth/spreadsheets","https://www.googleapis.com/auth/script.send_mail","https://www.googleapis.com/auth/script.external_request"]}
            

Changing scopes usually requires authorization again.

13Frontend Submission Examples

FormData

              
            

JSON

              
            
The frontend should check both result.ok and result.statusCode. Do not rely only on the HTTP status code.

14Response Format

Success

              {"ok":true,"statusCode":200,"requestId":"unique identifier","mailSent":true,"imageSaved":true,"fileUrl":"Google Drive file URL"}
            

Failure

              {"ok":false,"statusCode":500,"requestId":"unique identifier","error":"error description"}
            

Recommended for production: RETURN_DEBUG_INFO: false

15Image Data Format

Complete Data URL

              data:image/png;base64,iVBORw0KGgoAAA...
            

Raw Base64

              iVBORw0KGgoAAA...
            

When sending raw Base64, also provide:

              image_mime=image/png
            

Allowed formats: PNG, JPEG, JPG, WebP, and GIF. The default size limit is 5 MB.

16Security Checklist

  • Store the reCAPTCHA secret only in Script Properties.
  • Disable debug responses in production.
  • Restrict image MIME types and file size.
  • Do not trust summary_html received from the frontend.
  • Use escapeHtml_() to prevent email HTML injection.
  • Use safeSheetText_() to prevent spreadsheet formula injection.
  • Do not write full tokens or Base64 images to logs.
  • Keep MAKE_FILE_PUBLIC: false by default in production.
  • Revoke and replace any secret that has been exposed.

17Common Errors and Troubleshooting

Access denied: DriveApp

Possible causes include incomplete OAuth authorization, the wrong signed-in account, Drive being blocked by a Workspace administrator, revoked permissions, or a missing Drive scope in the manifest.

  1. Run authorizeDriveAccess.
  2. Complete authorization with the deployment account.
  3. Verify the folder ID.
  4. Verify folder sharing permissions.
Folder not found

Pass only the folder ID, not the complete URL.

                DriveApp.getFolderById("FOLDER_ID_ONLY");
              
The editor test succeeds, but doPost fails
  • Confirm that the Web App was updated to a new version.
  • Confirm that the website uses the latest /exec URL.
  • Confirm that the Web App executes as the correct account.
  • Confirm that the deployment account can access the Sheet and Drive folder.
  • Review the Apps Script Executions page and the LOG sheet.
Other people cannot open the image link

This is a Drive sharing issue, not an OAuth issue. You may set MAKE_FILE_PUBLIC: true, but Workspace policies can still block public sharing.

reCAPTCHA action mismatch
                // Frontend grecaptcha.execute(siteKey, { action: "submit" });  // Backend RECAPTCHA_EXPECTED_ACTION: "submit"
              

The frontend and backend values must match exactly.

18Completion Checklist

  • The Spreadsheet ID has been replaced.
  • The Folder ID has been replaced.
  • The sheet name is correct.
  • The administrator email is correct.
  • RECAPTCHA_SECRET exists in Script Properties.
  • authorizeDriveAccess has been run manually.
  • The Drive test file was created.
  • The deployment account can edit the Drive folder.
  • The Sheet column order is correct.
  • A new Web App version has been deployed.
  • The production website uses the /exec URL.
  • RETURN_DEBUG_INFO is false in production.
  • A real frontend submission test has been completed.
  • Sheets, Drive, email, LOG, and Executions have been verified.

19Recommended Setup Order

  1. Create the target Google Drive folder.
  2. Create the Google Spreadsheet.
  3. Add the worksheet header row.
  4. Share the folder with the GAS deployment account.
  5. Paste the complete code.
  6. Complete the CONFIG settings.
  7. Add the reCAPTCHA secret to Script Properties.
  8. Run authorizeDriveAccess.
  9. Run authorizeRequiredServices.
  10. Deploy the project as a Web App.
  11. Add the /exec URL to the frontend.
  12. Submit a test form.
  13. Verify Sheets, Drive, email, LOG, and Executions.
Completion standard: The frontend receives ok: true, data is written to Sheets, the image appears in Drive, the administrator receives the email, and there are no unhandled errors in LOG or Executions.