Rex Automaton
All posts
Document & Data ExtractionAugust 2, 20269 min read

How to Send Jotform to Google Sheets with Attachments

We built a resilient Jotform to Google Sheets sync that preserves file uploads as working links or Drive files, with structured field mapping and privacy-safe handling.

By Jacky Lei

Jotform to Google Sheets automation works by capturing each submission via the native integration, Zapier or Make, or a Jotform Webhook, then writing a structured row to a target sheet while preserving file uploads as working links or mirrored files in Drive. We shipped this for teams that need a reliable spreadsheet sink with attachments that actually open.

Jotform to Sheets automation is: a repeatable mapping from form fields to spreadsheet columns, with attachment URLs preserved and optional Drive copies created for long-term access.

The problem it solves

You likely started with a Jotform to Google Sheets click-integration. It worked until columns moved, file links stopped opening due to privacy settings, or a teammate edited the sheet and broke the sync. Attachments arrived as dead links, large sheets hit limits, and multi-file fields became messy to analyze.

Manual processAutomated pipeline
Export CSV from Jotform Tables weekly and paste into Sheets.Submissions stream into Sheets on submit with stable field mapping.
Download each uploaded file, rename it, re-upload to Drive.Store a working Jotform file URL or auto-save a copy to Drive and write the Drive link.
Rebuild a report every time the form changes.Central mapping translates field keys to clean column names.
Fix broken links when Jotform privacy blocks access.Either disable the privacy gate or fetch via the API with an API key.

A note on scale: Google Sheets supports up to 10 million cells per spreadsheet, which is a hard cap you should plan around if the form is high volume (source: Google Docs Editors Help).

How the automation works

We use the simplest path that fits your constraints. Three entry points exist and can coexist:

  • Native Jotform to Google Sheets integration: fastest for basic needs. Attachments appear as URLs. Renaming or reordering columns can break the sync.
  • Zapier or Make.com: official Jotform triggers add rows to a specific sheet with field mapping. Great when you want no-code routing and light transforms.
  • Webhook receiver: Jotform Webhooks post the full submission to your endpoint. We map fields, write to Sheets, and optionally save attachments to Drive for durable links.

The production pattern we ship most often uses Webhooks for control and traceability, while leaving the native integration enabled as a temporary safety net during cutover.

Jotform submissions flow into a webhook receiver that maps fields and writes a row to Google Sheets, while attachments are saved as links or mirrored to Drive for durable access

  • Jotform submission: the form posts to a Webhook URL you control. You can also keep the native Google Sheets integration for a fallback during cutover.
  • Webhook receiver (accent): normalizes fields, handles attachment URLs, applies your column schema, and logs errors.
  • Google Sheets: gets an append-only row with stable headers that match your reporting. We avoid editing the integrated sheet structure.
  • Attachment handling: either store the Jotform link as-is or fetch and mirror files to Drive, then write Drive URLs into the row.

Step-by-step: how to build it

Step 1: Prepare a stable Google Sheet schema

Decide column headers up front and keep them stable. Avoid renaming or reordering columns on any sheet that is bound to a live integration.

Timestamp,SubmissionID,Name,Email,Company,Plan,Notes,AttachmentURLs,DriveLinks

Key gotcha: Jotform confirms that editing an integrated Google Sheet can break the sync. Treat schema changes as a versioned migration, not an ad hoc edit.

Step 2: Choose your entry point and map field keys

Jotform exposes field keys in submission payloads. Build a mapping from Jotform keys to your Sheet headers.

// Example field map used by our receiver
const FIELD_MAP = {
  name: 'Name',
  email: 'Email',
  company: 'Company',
  plan: 'Plan',
  notes: 'Notes',
  attachments: 'AttachmentURLs'
};

If you start on Zapier or Make, their Jotform modules expose fields for drag-and-drop mapping to Google Sheets columns. For a webhook, you apply FIELD_MAP in code.

Step 3: Stand up a Google Apps Script Web App receiver

Apps Script is a simple, zero-infra way to accept Jotform Webhooks and write to Sheets.

// Code.gs
const SHEET_NAME = 'Submissions';
const API_KEY = PropertiesService.getScriptProperties().getProperty('JOTFORM_API_KEY');
 
function doPost(e) {
  const body = JSON.parse(e.postData.contents);
  const sheet = SpreadsheetApp.getActive().getSheetByName(SHEET_NAME);
 
  const row = buildRow(body);
  sheet.appendRow(row.values);
 
  // try mirroring attachments to Drive for durable links
  const driveLinks = mirrorAttachments(body, API_KEY);
  if (driveLinks.length) {
    const lastRow = sheet.getLastRow();
    const driveCol = row.headers.indexOf('DriveLinks') + 1;
    if (driveCol > 0) sheet.getRange(lastRow, driveCol).setValue(driveLinks.join('\n'));
  }
 
  return ContentService.createTextOutput('OK');
}
 
function buildRow(payload) {
  const headers = ['Timestamp','SubmissionID','Name','Email','Company','Plan','Notes','AttachmentURLs','DriveLinks'];
  const values = [
    new Date(),
    payload?.submission_id || payload?.id || '',
    payload?.name || '',
    payload?.email || '',
    payload?.company || '',
    payload?.plan || '',
    payload?.notes || '',
    Array.isArray(payload?.attachments) ? payload.attachments.join('\n') : (payload?.attachments || '') ,
    ''
  ];
  return { headers, values };
}
 
function mirrorAttachments(payload, apiKey) {
  const urls = Array.isArray(payload?.attachments) ? payload.attachments : (payload?.attachments ? [payload.attachments] : []);
  const dest = DriveApp.getFolderById(PropertiesService.getScriptProperties().getProperty('DEST_FOLDER_ID'));
  const links = [];
  urls.forEach(u => {
    try {
      // Some accounts require login to view uploaded files; Jotform documents using an API key
      // Include the API key header. If privacy blocks access, this may still return 403 until you change the Jotform setting.
      const resp = UrlFetchApp.fetch(u, { headers: { 'APIKEY': apiKey }, muteHttpExceptions: true });
      if (resp.getResponseCode() === 200) {
        const blob = resp.getBlob();
        const file = dest.createFile(blob.setName(blob.getName() || `jotform-${Date.now()}`));
        links.push(file.getUrl());
      } else {
        // fallback: keep the original link
        links.push(u);
      }
    } catch (err) {
      links.push(u);
    }
  });
  return links;
}

Deploy as a Web App, copy the URL, and set two Script Properties: JOTFORM_API_KEY and DEST_FOLDER_ID.

Step 4: Point the Jotform Webhook to your endpoint

In Jotform, add a Webhook integration and paste the Web App URL. Submit a test to see the payload arrive. Jotform's Webhooks send full submission data, which you can log for troubleshooting.

Settings: Integrations: Webhooks: https://script.google.com/macros/s/.../exec

If you prefer Zapier or Make, use their official Jotform triggers and Google Sheets modules to map the same columns. They handle the POST for you.

By default, file uploads in Sheets appear as URLs. They may fail to open if Jotform privacy is set to Require login to view uploaded files. Fix this one of two ways: disable that setting, or fetch files via the API in your receiver and mirror them to Drive.

Jotform: Account Settings: Privacy: Require login to view uploaded files: Off (for link access)

If you keep privacy On, keep the API-key download path in your receiver and store Drive links next to the original URL.

Step 6: Guard your sheet and plan for growth

Protect header rows and do not reorder columns on integrated sheets. When volume grows, archive to a data warehouse periodically and rotate to a new tab when approaching Google's limits.

-- Example archival pattern (BigQuery target)
CREATE TABLE IF NOT EXISTS dataset.jotform_submissions_2026 AS
SELECT * FROM dataset.jotform_submissions_live;
TRUNCATE TABLE dataset.jotform_submissions_live;

Google Sheets' 10 million cell limit is a practical ceiling for always-on form sinks. Rotate before you hit it to avoid surprise failures.

Where it gets complicated

  • Privacy-locked file URLs: When Require login to view uploaded files is enabled, simple clicks on links in Sheets fail. Either disable that setting or fetch via the API with an API key and mirror to Drive.
  • Column edits break native sync: Jotform's Google Sheets integration can stop syncing if you rename or reorder columns. Treat schema as code and version changes.
  • Sheet size ceilings: Large Sheets hit Google's cell and column limits. Plan archival and rotation so you do not stall intake during a surge.
  • Multi-file fields: Some forms let a user upload multiple files. Normalize to a newline-joined list and store Drive links side-by-side for analytics and access.
  • Regional API domains: Jotform uses api.jotform.com, with eu-api and hipaa-api variants. Pick the right base when you add any API calls.

What this actually changes

In production we stopped CSV exports, eliminated dead attachment links, and made reporting consistent by controlling the schema. Operators moved from weekly paste-jobs to live dashboards that stayed accurate even as forms evolved. The attachment mirroring removed the need to click into Jotform to fetch files. Plan capacity around Google's documented 10 million cell limit per spreadsheet so growth does not surprise you (source: Google Docs Editors Help).

Frequently asked questions

Does Jotform have an official API?

Yes. Jotform's API base is https://api.jotform.com, with regional variants for EU and HIPAA. Authentication uses an API key passed either as a query parameter apiKey or as an APIKEY HTTP header. You can pair the API with Webhooks to build a custom Sheets sink.

Will attachments appear in Google Sheets?

They appear as URLs. Those URLs may require login depending on your Jotform privacy setting. Either disable Require login to view uploaded files or have your receiver fetch files via the API and mirror them to Drive, then write the Drive URLs into the sheet.

Can I use Zapier or Make instead of a webhook?

Yes. Both have official Jotform triggers and Google Sheets modules that add rows with mapped fields. They are quick to set up and work well for light transforms. For attachment mirroring or strict schema control, a webhook receiver gives you more flexibility.

What breaks the Jotform to Sheets integration?

Editing the integrated sheet's structure is the most common cause: renaming or reordering columns can break the native sync. Also watch for hitting Sheets' size limits. Keep schema stable and rotate or archive as volume grows.

Can this update rows when someone edits a submission?

It can, but you need a reliable row key. With a webhook approach you capture the submission ID and look up the row to update. With Zapier or Make you can route submission edits and map to updates if you store the submission ID in the sheet.


If you want a Jotform to Google Sheets pipeline that keeps attachments opening and your columns stable, we have shipped this exact build. See our related post on using Sheets as a production sink for orders in Shopify: /blog/automate-shopify-local-orders-google-sheets. Or explore our broader workflow automation services. Ready to scope yours: /book.

Want us to build this for you?

15-minute discovery call. No pitch. We tell you what to automate first.

Book a Discovery Call

Related reading