Post Google Forms Responses into Kintone

Contents

Overview

This article introduces how to post Google Forms responses into Kintone Apps using Google Apps Script.

Benefits of the Integration

Google Forms allows end users to easily create and send questionnaires and event invitations. There are many advantages of capturing the form responses into Kintone's databases over spreadsheets.

Google Forms (External link)

  1. Access controls
    Kintone allows end users to set granular access controls to the data in its Apps. For example, records that have a "Keep Private" answer for one of their Google Forms questions can be made private. The permissions can be set so that only the HR department can view the submitted data. For more information on access controls, refer to the following article on the Kintone Help Site:
    Configuring Permissions for Records (External link)

  2. Business Process Management
    Workflows can be set for each record in the Kintone App. This makes the actions after the form submission much clearer. For example, after receiving a Google Forms submission into Kintone, the record can be assigned to a Design team member to work on creating creatives related to the submission data. For more information about workflows, refer to the following article on the Kintone Help Site:
    Setting Up Process Management (External link)

  3. Communication
    Each record inside the Kintone App has a feature for posting comments for other team members to read. For example, after receiving a Google Forms submission, an Events team member can write a comment in the record. They can reach out to a Sales team member who may have some connection with the submitter of the form. For more information about posting comments, refer to the following article on the Kintone Help Site:
    Posting Comments on Records (External link)

Required Environments

In addition to a Kintone environment, the following will also need to be prepared:

  1. A user with Kintone Users & System Administrators permission.
    Users & System Administrators (External link)
  2. A Google account.

Prepare Google Forms

Step 1

Log in to the Google account and select Google Forms from the Google app icon, or directly login from the following link, and click the [+] Blank Form.
https://docs.google.com/forms/ (External link)

Step 2

Enter a title and description for the form.

Step 3

Click the Settings tab, and open the Responses menu. Select Responder Input for the Collect email addresses option.

Step 4

Click the Questions tab and select the Short answer question type. First, collect the applicants' full names. Mark the question as required.

Step 5

Add the following questions as shown in the reference images below:

Type Question Options
Date Date of Birth -
Checkbox Desired Position Human Resources, Sales, Reception, Purchasing
Dropdown Employment Type Full-time, Contract, Part-time
Time Desired Start Time -
Radio Button Previous Work Experience Yes, No
File Upload Resume -

After entering the above questions into the form, a Kintone App should be created to match the data that will be collected.

Prepare a Kintone App

Create an App

Log in to Kintone, and create a new App with the following fields and settings.

Field Type Field Name Field Code Notes
Text (Single line) Full Name name Required field
Text (Single line) Email Address email Required field
Date Date of Birth dob
Checkbox Desired Position department Options: Human Resources, Sales, Reception, Purchasing
Dropdown Employment Type employment Options: Full-time, Contract, Part-time
Time Desired Start Time start_time
Radio Button Previous Work Experience experience Options: Yes, No
Attachment Resume resume

The form should look like the following:

Generate an API Token

Next, follow the steps in the following article to generate an API token.

Generating API Tokens (External link)

Apply the Add records permissions to the API Token. Save the settings, and apply the changes to the App. Take note of the API token, as it is needed for the integration in the later steps.

Prepare a Google Apps Script Program

Step 1

Reopen the Google Form, click the three vertical dots in the upper right-hand corner, and select Apps Script.

Enter a project name and a file name.

Step 2

Add OAuth scopes to the manifest file.
Go to Project Settings by clicking the gear icon on the left sidebar. Check the option "Show appsscript.json manifest file in editor".

Return to the editor and add the OAuth scopes to appsscript.json as follows:

1
"oauthScopes": ["https://www.googleapis.com/auth/forms","https://www.googleapis.com/auth/forms.currentonly", "https://www.googleapis.com/auth/script.external_request","https://www.googleapis.com/auth/drive"]

Step 3

Enter the JavaScript code below into the post-to-kintone.gs code file.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/*
 * Sample program for integrating Google Forms with Kintone
 * Copyright (c) 2025 Cybozu
 *
 * Licensed under the MIT License
 * https://opensource.org/license/mit/
 */
// Function to retrieve form responses
const getFormResponse = () => {
  // Get the active form
  const form = FormApp.getActiveForm();
  // Get form responses
  const formResponses = form.getResponses();
  // Get the latest form response
  const latestResponse = formResponses[formResponses.length - 1];
  const records = {};
  // Get the respondent's email address
  records.email = {value: latestResponse.getRespondentEmail()};
  // Get the question response items from the form
  const itemResponses = latestResponse.getItemResponses();
  // Loop through to get each question and its response
  itemResponses.forEach(itemResponse => {
    switch (itemResponse.getItem().getTitle()) {
      case 'Full Name':
        records.name = {value: itemResponse.getResponse()}; // Get the name response
        break;
      case 'Date of Birth':
        records.dob = {value: itemResponse.getResponse()}; // Get the date of birth response
        break;
      case 'Desired Position':
        records.department = {value: JSON.parse(JSON.stringify([].concat(...itemResponse.getResponse())))};
        // Get multiple responses for desired position
        break;
      case 'Employment Type':
        records.employment = {value: itemResponse.getResponse()}; // Get the employment type response
        break;
      case 'Desired Start Time':
        records.start_time = {value: itemResponse.getResponse()}; // Get the desired start time response
        break;
      case 'Previous Work Experience':
        records.experience = {value: itemResponse.getResponse()}; // Get the work experience response
        break;
      case 'Resume':
        // Check if the question type is file upload
        if (itemResponse.getItem().getType() === FormApp.ItemType.FILE_UPLOAD) {
          const fileIds = itemResponse.getResponse(); // Get array of file IDs
          // Get file details from Google Drive
          const file = DriveApp.getFileById(fileIds[0]);
          // Get file content as Blob
          const blob = file.getBlob();
          const fileKey = uploadFile(blob);
          if (fileKey !== null) {
            fileKey.contentType = blob.getContentType();
            fileKey.name = blob.getName();
            fileKey.size = blob.getBytes().length;
            records.resume = {value: [fileKey]};
          }
        }
        break;
    }
  });
  return records;
};
// Function to send form responses to Kintone
const sendToKintone = () => {
  Logger.log('Form submitted');
  const subdomain = '{SUBDOMAIN}.kintone.com/k/v1/records.json'; // Resource URL
  // Get form responses
  const formResponse = getFormResponse();
  const records = {app: {KINTONE_APP_ID}, records: [formResponse]};
  // Create POST request
  const options = {
    method: 'post',
    contentType: 'application/json',
    // Convert JavaScript object to JSON string
    payload: JSON.stringify(records),
    headers: {'X-Cybozu-API-Token': '{KINTONE_API_TOKEN}'},
  };
  // Execute POST request
  const response = UrlFetchApp.fetch(subdomain, options);
  Logger.log('Response is "%s"', response.getContentText());
};
// Function to upload attachment files to Kintone
const uploadFile = (blob) => {
  const formData = {
    file: blob
  };
  const url = '{SUBDOMAIN}.kintone.com/k/v1/file.json'; // Resource URL
  const options = {
    method: 'post',
    payload: formData,
    headers: {'X-Requested-With': 'XMLHttpRequest', 'X-Cybozu-API-Token': '{KINTONE_API_TOKEN}'},
  };
  const response = UrlFetchApp.fetch(url, options);
  return JSON.parse(response.getContentText()); // Return FileKey
};
caution
Attention

The strings name, email, dob, department, employment, start_time, experience, and resume that are listed in the code are the field codes of the fields in the Kintone App. Make sure these field codes match exactly with those you configured in your Kintone App.

Additionally, the code relies on the google form question titles matching the code. Make sure the questions are typed exactly as above, or the code is updated to match the questions.

Make sure to also change the {SUBDOMAIN}, {KINTONE_APP_ID}, and {KINTONE_API_TOKEN} to values that correspond to the Kintone App.

Save the code when done.

Step 4

Click the clock icon in the left sidebar to open the Triggers settings and click the + Add Trigger button.

Select the sendToKintone function, set the event type to On form submit, and click Save.

Step 5

On the google forms edit page, click the Publish button, and proceed to publish the form.

Test the Integration

Access the form via the Published button, and open the published form's link.

After filling out the form, confirm the responses have been properly uploaded to the Kintone App.

tips
Note

If the form response data is not posted into the Kintone App, check the Executions tab in the Apps Script page. It shows a response-by-response breakdown of each function call. Adding logging to the JavaScript code via console.log(foo) will also help debug potential typos and variable mismatches.

Code Explanation

The following API function first retrieves the active form (the form that received the submission): FormApp.getActiveForm()

10
11
// Get the active form
const form = FormApp.getActiveForm();

The following API function retrieves the form submission data: form.getResponses();

12
13
14
15
// Get form responses
const formResponses = form.getResponses();
// Get the latest form response
const latestResponse = formResponses[formResponses.length - 1];

Create JSON-formatted data to send to Kintone. The respondent's email address can be retrieved with the following API function: latestResponse.getRespondentEmail();

16
17
18
const records = {};
// Get the respondent's email address
records.email = {value: latestResponse.getRespondentEmail()};

Retrieve the details of the question response items from the form: latestResponse.getItemResponses();

19
20
// Get the question response items from the form
const itemResponses = latestResponse.getItemResponses();

Loop through to get each question and its response:

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// Loop through to get each question and its response
itemResponses.forEach(itemResponse => {
  switch (itemResponse.getItem().getTitle()) {
    case 'Full Name':
      records.name = {value: itemResponse.getResponse()}; // Get the name response
      break;
    case 'Date of Birth':
      records.dob = {value: itemResponse.getResponse()}; // Get the date of birth response
      break;
    case 'Desired Position':
      records.department = {value: JSON.parse(JSON.stringify([].concat(...itemResponse.getResponse())))};
      // Get multiple responses for desired position
      break;
    case 'Employment Type':
      records.employment = {value: itemResponse.getResponse()}; // Get the employment type response
      break;
    case 'Desired Start Time':
      records.start_time = {value: itemResponse.getResponse()}; // Get the desired start time response
      break;
    case 'Previous Work Experience':
      records.experience = {value: itemResponse.getResponse()}; // Get the work experience response
      break;
    // ***
    // ***
  }
});

For details on the JSON format of the request data to send to Kintone, refer to the following article:
Add record

Retrieve the file data uploaded to Google Drive and upload it to Kintone to set the File Key:

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// Check if the question type is file upload
if (itemResponse.getItem().getType() === FormApp.ItemType.FILE_UPLOAD) {
  const fileIds = itemResponse.getResponse(); // Get array of file IDs
  // Get file details from Google Drive
  const file = DriveApp.getFileById(fileIds[0]);
  // Get file content as Blob
  const blob = file.getBlob();
  const fileKey = uploadFile(blob);
  if (fileKey !== null) {
    fileKey.contentType = blob.getContentType();
    fileKey.name = blob.getName();
    fileKey.size = blob.getBytes().length;
    records.resume = {value: [fileKey]};
  }
}

Upload the file data retrieved from Google Drive to Kintone, then return the obtained File Key:

83
84
85
86
87
88
89
90
91
92
93
94
95
96
// Function to upload attachment files to Kintone
const uploadFile = (blob) => {
  const formData = {
    file: blob
  };
  const url = '{SUBDOMAIN}.kintone.com/k/v1/file.json'; // Resource URL
  const options = {
    method: 'post',
    payload: formData,
    headers: {'X-Requested-With': 'XMLHttpRequest', 'X-Cybozu-API-Token': '{KINTONE_API_TOKEN}'},
  };
  const response = UrlFetchApp.fetch(url, options);
  return JSON.parse(response.getContentText()); // Return FileKey
};

Set the information for the Kintone App created above:

67
68
69
70
71
72
73
74
75
76
77
const subdomain = '{SUBDOMAIN}.kintone.com/k/v1/records.json'; // Resource URL
// ***
const records = {app: {KINTONE_APP_ID}, records: [formResponse]};
// Create POST request
const options = {
  method: 'post',
  contentType: 'application/json',
  // Convert JavaScript object to JSON string
  payload: JSON.stringify(records),
  headers: {'X-Cybozu-API-Token': '{KINTONE_API_TOKEN}'},
};

Send the data to Kintone using the following API function: UrlFetchApp.fetch(url, options);

80
const response = UrlFetchApp.fetch(subdomain, options);

If the response returns in the following format, it's successful: {"ids":["record ID"],"revisions":["revision number"]}

81
Logger.log('Response is "%s"', response.getContentText());

Reference