Connect Google Forms to Productboard

You can integrate Google Forms with Productboard by using Productboard’s Notes API. Once you configure the API connection with a Google form, whenever a form is submitted, it will be pushed into your Insights board as a Note.

By using Google Forms for collecting user insights, you can

  • Bring structure to your customer feedback.
  • Let the note owner initially assess the priority.
  • Always capture important information like pain points, use cases, and benefits.

If additional customization is needed, anyone with knowledge of JavaScript should be able to make adjustments to the provided script. 

In this article:

Copying the form and script

  1. Make a copy of this form. You may use an existing form but keep in mind you may need to edit the script based on your form structure. 
    Note: Before continuing onwards, if you make a copy of the form, it is recommended to make your changes to the form’s questions and options. Also, if you would like to associate your customers with your Productboard notes, the first question (i.e. Requestor email) is required. Otherwise, the Productboard notes will appear as anonymous.
  2. Go into the settings in the form and make sure you toggle on Collect email addresses.
  3. Click on Responses and then click on the Spreadsheets logo.
  4. Select Create a new spreadsheet and click on Create. Renaming your new spreadsheet is optional.
  5. Once you create a new spreadsheet, you will get the message Spreadsheet linked. Click Open and go to the new spreadsheet. This spreadsheet will now have columns that are linked to the questions in your form.
  6. In the spreadsheet, click on Extensions and then Apps Script.
  7. Go to Project Settings:
    Screenshot 2024-05-21 at 1.14.31 PM.png
  8. Create a token in your Productboard workspace and add a Script Property (at the bottom of the Project Settings page) with your new API token. 

    PB_API_TOKEN paste-your-api-token-here

    It should look like this once inputted: 
  9. Click on the Editor section, go to the file and delete all the lines before pasting the code below.
  10. Copy and paste the code below into the editor for the file:
// Get the Productboard token from Script Properties
const scriptProperties = PropertiesService.getScriptProperties();
const productboardToken = scriptProperties.getProperty('PB_API_TOKEN');

// Adds a trigger that runs a function when a Google Form is submitted. Triggers are managed in the left hand menu.
function addTrigger() {
if (!productboardToken) {
throw new Error ("Please add your Productboard API token in the Project settings in the left hand menu. More info here:")
try {
const triggers = ScriptApp.getProjectTriggers();
triggers.forEach(trigger => ScriptApp.deleteTrigger(trigger));
// Create a new trigger that will run the 'submitGoogleFormData' function when the form is submitted
Logger.log("Trigger successfully added. A Productboard note will be created upon a Google form submission.");
} catch (error) {
throw new Error("Error when adding trigger: " + error.toString());

// Function called when a form is submitted
function createNoteInProductboard(e) {
// Check if the function is called manually and throw an error if true
if (!e) {
throw new Error("This function cannot be run manually. Please run the 'addTrigger' function from the Run menu and submit a form to test.");
try {
// Get the active sheet and the last row and column with data
const activeSheet = SpreadsheetApp.getActiveSheet();
const lastRow = activeSheet.getLastRow();
const numOfColumns = activeSheet.getLastColumn();
const timestamp = getCellValue(activeSheet, lastRow, 1);
const submitterEmail = getCellValue(activeSheet, lastRow, 2);
let requestorEmail = getCellValue(activeSheet, lastRow, 3);
requestorEmail = validateEmail(requestorEmail) ? requestorEmail : null;
// Get questions from the first row/headers and answers from the last row
const questions = getRowValues(activeSheet, 1, numOfColumns);
const answers = getRowValues(activeSheet, lastRow, numOfColumns);
// Create note content for the Productboard note by combining questions and answers
const content = createNoteContent(questions, answers);
// Prepare the payload for the Productboard API
const payload = {
title: "Feedback from Google Forms",
content: content,
user: {
email: requestorEmail
// Make the API request to create a note in Productboard
const url = "";
const response = sendPostRequest(url, payload, productboardToken);
if (response) {
const parsedResponse = JSON.parse(response)
Logger.log(`Productboard note created: ${parsedResponse.links.html}`);
try {
const noteId =;
const addFollowerUrl = `${noteId}/user-followers`
const addFollowerPayload = [
"email": submitterEmail
sendPostRequest(addFollowerUrl, addFollowerPayload, productboardToken);
console.log(`${submitterEmail} was added as a follower to the note.`)
catch (error) {
console.log(`Attempted to add the submitter as a follower to the note but no matching email was found. `)
} catch (error) {
throw new Error(`Could not create a Productboard note. Full error response: ${error}. Check for more information.`);

// Helper function to get a cell value
function getCellValue(sheet, row, column) {
return sheet.getRange(row, column).getValue();

// Helper function to get values of a row
function getRowValues(sheet, row, numOfColumns) {
return sheet.getRange(row, 1, 1, numOfColumns).getValues()[0];

// Helper function to validate email format
function validateEmail(email) {
const emailRegex = /[^@\s]+@[^@\s]+/;
return emailRegex.test(email);

// Helper function to create content for Productboard note
function createNoteContent(questions, answers) {
let content = "";
const length = questions.length;
for (let i = 1; i < length; i++) {
content += `<strong>${questions[i]}:</strong> ${answers[i]}<br><br>`;
return content;

// Helper function to send a POST request to the Productboard API
function sendPostRequest(url, payload, token) {
const options = {
method: "POST",
contentType: "application/json",
headers: {
Authorization: `Bearer ${token}`,
payload: JSON.stringify(payload),
muteHttpExceptions: false,
return UrlFetchApp.fetch(url, options);

Running the addTrigger function

  1. Once you have added the API token in the Script Properties and pasted the script above into your file, click on Save and then Run. It should default to running the addTrigger function and add a trigger for you. 
  2. You may need to Review permissions.
  3. After clicking on Review permissions and then Allow in the next window, you should see these notes in the Execution log at the bottom of the page.
  4. If you see the Execution log messages above, it means that you have successfully configured the connection.
  5. You may now test the connection by submitting a form.

Troubleshooting and debugging

If nothing appears in your Productboard Insights board after your first test, start by looking in the Executions menu of Apps Script. This will show the last functions that were run and the possible errors.

If you have any feedback on this guide, feel free to email

school Productboard Academy Quick Tip

Take a look at our quick tip academy course about connecting Google Forms to Productboard.

By using Google Forms to collect user insights, you can

  • Bring structure to your customer feedback.
  • Let the note owner initially assess the priority.
  • Always capture important information like pain points, use cases, and benefits.

Continue learning

Note: Productboard's Academy content is available to trial users and paid customers only.
Was this article helpful?
5 out of 6 found this helpful



Article is closed for comments.

Articles in this section

See more
Our Support hours:
Monday to Friday from 9:00 am - 2:00 am CET. Monday to Friday from 0:00 am - 5:00 pm PST.
Productboard Academy
Become a Productboard expert with self-paced courses, quick tip videos, webinars and more.
Product Makers Community
Connect with product leaders, share and find product jobs, and learn how to approach similar challenges. Come join our Product Makers community.