https://www.endpointdev.com/blog/tags/google-forms/2021-11-16T00:00:00+00:00End Point DevForwarding Google Forms responses to an external APIhttps://www.endpointdev.com/blog/2021/11/forwarding-google-forms-responses-to-api/2021-11-16T00:00:00+00:00Afif Sohaili
<p><img src="/blog/2021/11/forwarding-google-forms-responses-to-api/banner.jpg" alt="Sunrise over the Wasatch mountains"></p>
<!-- Photo by Mira Jensen -->
<p>Google Forms is a great form service that many people use for surveys, research, questionnaires, etc. It has an intuitive and flexible interface for building forms and is fairly easy to use for everyone. Once you get a response, you can view the results in the admin section of the form or in a Google Sheets document in which Google will automatically insert all your responses.</p>
<p>However, you may need to do something else with the responses. For example, what if you want to have the response printed in your Slack channel or Discord server? Or what if you want to use the raw data to make more complex visualizations than Google Sheets is capable of?</p>
<h3 id="google-apps-script-to-the-rescue">Google Apps Script to the rescue!</h3>
<p>Google Apps Script is a development platform for building add-ons for Google products, such as Google Sheets, Google Docs, and Google Forms. You write your JavaScript in the code editor that Google provides for you, so there is nothing to install on your local machine to start developing. This code then gets executed on Google’s servers. These Google Apps Script projects can then be published as a Google Workspace add-on that others can use or shared within your organization.</p>
<p>Even though Google Apps Script is basically just JavaScript, there are a few key differences from a Node.js project. For example, in a Node.js environment you could use the <code>https</code> module to send an HTTP request to another external service (or you could grab a package like <code>axios</code> or <code>node-fetch</code> that can do the same thing). In Google Apps Script, however, you cannot use the <code>https</code> module because it is not a Node.js project per se and does not provide you with the ability to install external NPM packages. Instead, there is a limited set of standard libraries that comes built-in within a Google Apps Script project.</p>
<h4 id="1-start-a-new-google-apps-script-project">1. Start a new Google Apps Script project</h4>
<ol>
<li>Head to <a href="https://forms.google.com">Google Forms</a> and create a new form.</li>
<li>Click the triple-dots icon at the top-right corner of the form and choose “Script Editor”.</li>
<li>You should now see the Google Apps Script editor. Great! Let’s change the project name to something more descriptive (e.g. “Forward to API”).</li>
</ol>
<h4 id="2-add-triggers-to-the-script-for-initialization">2. Add triggers to the script for initialization</h4>
<p>Google Apps Script allows you to install triggers to the current form. The ones we are interested in right now are <code>onOpen</code>, which runs when a user that has edit access opens the form, and <code>onInstall</code>, which runs when a user installs the add-on in the Google Forms form. There are other events that you might be interested in listed <a href="https://developers.google.com/apps-script/guides/triggers">here</a>.</p>
<p>We will also need to provide a way for users to set the outgoing URL for each response. The easiest would be to hardcode it in the code, but we can make our add-on a little bit more configurable; let’s also create a sidebar that contains the configuration interface for the users to change the settings for our add-on, in this case the destination URL for the responses.</p>
<p>Now, in the Google Apps Script code editor, paste the following code:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-javascript" data-lang="javascript"><span style="color:#888">/**
</span><span style="color:#888"> * Adds a custom menu to the active form to show the add-on sidebar.
</span><span style="color:#888"> */</span>
<span style="color:#080;font-weight:bold">function</span> onOpen(e) {
FormApp.getUi()
.createAddonMenu()
.addItem(<span style="color:#d20;background-color:#fff0f0">'Configure'</span>, <span style="color:#d20;background-color:#fff0f0">'showSidebar'</span>)
.addToUi();
}
<span style="color:#888">/**
</span><span style="color:#888"> * Runs when the add-on is installed.
</span><span style="color:#888"> */</span>
<span style="color:#080;font-weight:bold">function</span> onInstall(e) {
onOpen(e);
}
<span style="color:#888">/**
</span><span style="color:#888"> * Opens a sidebar in the form containing the add-on's user interface for
</span><span style="color:#888"> * configuring the notifications this add-on will produce.
</span><span style="color:#888"> */</span>
<span style="color:#080;font-weight:bold">function</span> showSidebar() {
<span style="color:#080;font-weight:bold">var</span> sidebarPage = HtmlService.createHtmlOutputFromFile(<span style="color:#d20;background-color:#fff0f0">'sidebar'</span>)
.setTitle(<span style="color:#d20;background-color:#fff0f0">'Your add-on configuration'</span>);
FormApp.getUi().showSidebar(sidebarPage);
}
<span style="color:#888">// Save settings
</span><span style="color:#888"></span>
<span style="color:#888">// Load settings
</span></code></pre></div><p>First, we would like to have a menu item on the form to access the add-on. This is done through the <code>createAddonMenu().addItem</code> function within the <code>onOpen</code> trigger. We also have the <code>onInstall</code> trigger that does the same thing as what <code>onOpen</code> is doing. With these, both installing the add-on for the first time and opening the form creates an add-on menu item called “Configure”.</p>
<p><code>createAddonMenu().addItem</code> accepts two arguments, a label (<code>Configure</code>) and a function name to be executed when the item is selected (<code>showSidebar</code>). In the code above, it will run the <code>showSidebar</code> function. <code>showSidebar</code> initializes the add-on’s view by loading and running the HTML file we specified in <code>createHtmlOutputFromFile</code>. Since we are passing <code>sidebar</code> to the function, it will automatically assume the filename <code>sidebar.html</code> and load the file from our project.</p>
<h4 id="3-adding-the-configuration-sidebar">3. Adding the configuration sidebar</h4>
<p>In the previous step, we specified our menu item to show the sidebar. Now, let’s go ahead and create a new file called <code>sidebar.html</code>.</p>
<ol>
<li>On the Files panel, click the <code>+</code> icon and choose <code>HTML</code> in the dropdown menu.</li>
<li>Name the file <code>sidebar.html</code> when prompted. This is important as we have specified the name <code>sidebar</code> to the <code>createHtmlOutputFromFile</code> function within <code>showSidebar</code>.</li>
<li>Open the HTML file and paste the following HTML content:</li>
</ol>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-html" data-lang="html"><span style="color:#c00;font-weight:bold"><!DOCTYPE html></span>
<<span style="color:#b06;font-weight:bold">html</span>>
<<span style="color:#b06;font-weight:bold">head</span>>
<<span style="color:#b06;font-weight:bold">base</span> <span style="color:#369">target</span>=<span style="color:#d20;background-color:#fff0f0">"_top"</span>>
<<span style="color:#b06;font-weight:bold">style</span>>
<span style="color:#b06;font-weight:bold">body</span> {
<span style="color:#080;font-weight:bold">font-family</span>: <span style="color:#080;font-weight:bold">sans-serif</span>;
<span style="color:#080;font-weight:bold">font-size</span>: <span style="color:#00d;font-weight:bold">14</span><span style="color:#888;font-weight:bold">px</span>;
}
<span style="color:#b06;font-weight:bold">input</span> {
<span style="color:#080;font-weight:bold">border</span>: <span style="color:#00d;font-weight:bold">1</span><span style="color:#888;font-weight:bold">px</span> <span style="color:#080;font-weight:bold">solid</span> <span style="color:#00d;font-weight:bold">#3f3f3f</span>;
<span style="color:#080;font-weight:bold">padding</span>: <span style="color:#00d;font-weight:bold">0.25</span><span style="color:#888;font-weight:bold">rem</span>;
<span style="color:#080;font-weight:bold">width</span>: <span style="color:#00d;font-weight:bold">100</span><span style="color:#888;font-weight:bold">%</span>;
}
#<span style="color:#b06;font-weight:bold">error</span> {
<span style="color:#080;font-weight:bold">margin-top</span>: <span style="color:#00d;font-weight:bold">0.5</span><span style="color:#888;font-weight:bold">rem</span>;
}
.<span style="color:#b06;font-weight:bold">input-field</span> {
<span style="color:#080;font-weight:bold">margin-bottom</span>: <span style="color:#00d;font-weight:bold">1</span><span style="color:#888;font-weight:bold">rem</span>;
}
</<span style="color:#b06;font-weight:bold">style</span>>
</<span style="color:#b06;font-weight:bold">head</span>>
<<span style="color:#b06;font-weight:bold">body</span>>
<<span style="color:#b06;font-weight:bold">form</span>>
<<span style="color:#b06;font-weight:bold">div</span> <span style="color:#369">class</span>=<span style="color:#d20;background-color:#fff0f0">"input-field"</span>>
<<span style="color:#b06;font-weight:bold">label</span> <span style="color:#369">for</span>=<span style="color:#d20;background-color:#fff0f0">"url"</span>>URL to send responses to:</<span style="color:#b06;font-weight:bold">label</span>>
<<span style="color:#b06;font-weight:bold">input</span> <span style="color:#369">id</span>=<span style="color:#d20;background-color:#fff0f0">"url"</span> <span style="color:#369">type</span>=<span style="color:#d20;background-color:#fff0f0">"text"</span> <span style="color:#369">name</span>=<span style="color:#d20;background-color:#fff0f0">"url"</span> <span style="color:#369">placeholder</span>=<span style="color:#d20;background-color:#fff0f0">"e.g. https://some-api.com/accept/responses"</span>/>
</<span style="color:#b06;font-weight:bold">div</span>>
<<span style="color:#b06;font-weight:bold">div</span> <span style="color:#369">class</span>=<span style="color:#d20;background-color:#fff0f0">"block"</span> <span style="color:#369">id</span>=<span style="color:#d20;background-color:#fff0f0">"button-bar"</span>>
<<span style="color:#b06;font-weight:bold">button</span> <span style="color:#369">class</span>=<span style="color:#d20;background-color:#fff0f0">"action"</span> <span style="color:#369">id</span>=<span style="color:#d20;background-color:#fff0f0">"save-settings"</span>>Save</<span style="color:#b06;font-weight:bold">button</span>>
<<span style="color:#b06;font-weight:bold">p</span> <span style="color:#369">id</span>=<span style="color:#d20;background-color:#fff0f0">"response"</span>></<span style="color:#b06;font-weight:bold">p</span>>
</<span style="color:#b06;font-weight:bold">div</span>>
</<span style="color:#b06;font-weight:bold">form</span>>
<<span style="color:#b06;font-weight:bold">script</span> <span style="color:#369">src</span>=<span style="color:#d20;background-color:#fff0f0">"//ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"</span>>
</<span style="color:#b06;font-weight:bold">script</span>>
<<span style="color:#b06;font-weight:bold">script</span>>
<span style="color:#888">// Our JavaScript code
</span><span style="color:#888"></span> </<span style="color:#b06;font-weight:bold">script</span>>
</<span style="color:#b06;font-weight:bold">body</span>>
</<span style="color:#b06;font-weight:bold">html</span>>
</code></pre></div><h6 id="test-your-sidebar">Test your sidebar</h6>
<ol>
<li>Go back to your Google Forms form and refresh. You should now get an add-on menu on your form, with your add-on listed in the dropdown.</li>
<li>Choose your add-on and click “Configure”. This is the add-on menu item that we declared in step 1.</li>
<li>You should now be prompted to authorize the script. Follow the instructions to allow the script permission to run on your Google Forms forms.</li>
<li>Once you’re done, go to the add-on menu, choose your add-on, and choose “Configure” again. You should now see a sidebar on the right side of the form with a text field to fill in the destination URL and a submit button to save the settings.</li>
</ol>
<p><img src="/blog/2021/11/forwarding-google-forms-responses-to-api/forms-authorization.png" alt="Authorization"></p>
<p><img src="/blog/2021/11/forwarding-google-forms-responses-to-api/sidebar-1.png" alt="Your sidebar"></p>
<h4 id="4-saving-your-configuration">4. Saving your configuration</h4>
<p>Now we need to be able to save the URL we want to send the responses to and create a form trigger out of that. Let’s go ahead and add that:</p>
<p>Add the following script in the <code><script></code> block under the <code>// Our JavaScript code</code> comment.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-javascript" data-lang="javascript"><span style="color:#888">// sidebar.html
</span><span style="color:#888"></span>$(<span style="color:#080;font-weight:bold">function</span>() {
<span style="color:#888">// Load settings from the server
</span><span style="color:#888"></span> loadSettingsAndPopulateForm();
<span style="color:#888">// Listen to 'submit' event
</span><span style="color:#888"></span> $(<span style="color:#d20;background-color:#fff0f0">'form'</span>).submit(saveSettingsToServer);
});
<span style="color:#080;font-weight:bold">function</span> loadSettingsAndPopulateForm() {
google.script.run
.withSuccessHandler(
<span style="color:#080;font-weight:bold">function</span>(settings) {
$(<span style="color:#d20;background-color:#fff0f0">'#url'</span>).val(settings.url)
})
.withFailureHandler(
<span style="color:#080;font-weight:bold">function</span>(msg) {
$(<span style="color:#d20;background-color:#fff0f0">'#response'</span>).text(<span style="color:#d20;background-color:#fff0f0">'Failed to fetch settings. ERROR: '</span> + msg);
})
.fetchSettings();
}
<span style="color:#080;font-weight:bold">function</span> saveSettingsToServer(event) {
event.preventDefault();
<span style="color:#080;font-weight:bold">var</span> button = $(<span style="color:#080;font-weight:bold">this</span>).find(<span style="color:#d20;background-color:#fff0f0">'button'</span>);
button.attr(<span style="color:#d20;background-color:#fff0f0">'disabled'</span>, <span style="color:#d20;background-color:#fff0f0">'disabled'</span>);
<span style="color:#080;font-weight:bold">var</span> settings = {
<span style="color:#d20;background-color:#fff0f0">'url'</span>: $(<span style="color:#d20;background-color:#fff0f0">'#url'</span>).val(),
};
<span style="color:#888">// Save the settings on the server
</span><span style="color:#888"></span> google.script.run
.withSuccessHandler(
<span style="color:#080;font-weight:bold">function</span>(msg, button) {
button.removeAttr(<span style="color:#d20;background-color:#fff0f0">'disabled'</span>);
$(<span style="color:#d20;background-color:#fff0f0">'#response'</span>).text(<span style="color:#d20;background-color:#fff0f0">'Saved settings successfully'</span>);
})
.withFailureHandler(
<span style="color:#080;font-weight:bold">function</span>(msg, button) {
button.removeAttr(<span style="color:#d20;background-color:#fff0f0">'disabled'</span>);
$(<span style="color:#d20;background-color:#fff0f0">'#response'</span>).text(<span style="color:#d20;background-color:#fff0f0">'Failed to save settings. ERROR: '</span> + msg);
})
.withUserObject(button)
.saveSettings(settings);
}
</code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-javascript" data-lang="javascript"><span style="color:#888">// Code.gs
</span><span style="color:#888"></span>
<span style="color:#888">/**
</span><span style="color:#888"> * Used by the client-side via `google.script.run` to save setings from the form.
</span><span style="color:#888"> */</span>
<span style="color:#080;font-weight:bold">function</span> saveSettings(settings) {
PropertiesService.getDocumentProperties().setProperties(settings);
<span style="color:#888">// adjustFormSubmitTrigger();
</span><span style="color:#888"></span>}
<span style="color:#888">/**
</span><span style="color:#888"> * Used by the client-side via `google.script.run` to load saved setings.
</span><span style="color:#888"> */</span>
<span style="color:#080;font-weight:bold">function</span> fetchSettings() {
<span style="color:#080;font-weight:bold">return</span> PropertiesService.getDocumentProperties().getProperties();
}
</code></pre></div><p>Now, let’s go through the code:</p>
<p>The <code>$(function() {})</code> block is run at document load. Two things happen here:</p>
<ul>
<li>The <code>loadSettingsAndPopulateForm</code> function runs the <code>fetchSettings</code> function from the backend. Then it populates the text input field <code>#url</code> with the saved settings.</li>
<li>It installs an event listener on the configuration form submit to save the settings to the server. This listener, the <code>saveSettingsToServer</code> function, gathers all the values from the input fields, and runs the <code>saveSettings</code> function on the backend, with the input field values as the arguments.</li>
</ul>
<h5 id="googlescriptrun">google.script.run</h5>
<p><code>google.script.run</code> is the glue between frontend (the <code>*.html</code> files) and the backend (the <code>*.gs</code>) files. Once you declare a function (e.g. <code>doStuff</code>) on backend, you can use the function through <code>google.script.run.doStuff</code> from the frontend. <code>withSuccessHandler</code> and <code>withFailureHandler</code> are where you supply the callbacks for successful calls and failed calls to the backend respectively.</p>
<p>To see more, read the <a href="https://developers.google.com/apps-script/guides/html/reference/run">documentation</a>.</p>
<h4 id="5-installing-the-form-submit-event-handler">5. Installing the form submit event handler</h4>
<p>Now that we’re able to pinpoint the address we want send the form data to, we can start instructing Google Forms to send the data our way when someone submits the form. In order to do that, we:</p>
<ol>
<li>Code the form submit trigger to submit the data on the form response.</li>
<li>If there’s no existing form submit trigger and the URL is set, install the form submit trigger.</li>
<li>If there is an existing form submit trigger and the URL is unset, remove the trigger.</li>
</ol>
<p>Let’s write the form submit trigger first. Paste this code at the end of <code>Code.gs</code>:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-javascript" data-lang="javascript"><span style="color:#080;font-weight:bold">function</span> sendResponse(e) {
<span style="color:#080;font-weight:bold">var</span> data = {
<span style="color:#d20;background-color:#fff0f0">"form"</span>: {
<span style="color:#d20;background-color:#fff0f0">"id"</span>: e.source.getId(),
<span style="color:#d20;background-color:#fff0f0">"title"</span>: e.source.getTitle() ? e.source.getTitle() : <span style="color:#d20;background-color:#fff0f0">"Untitled Form"</span>,
<span style="color:#d20;background-color:#fff0f0">"is_private"</span>: e.source.requiresLogin(),
<span style="color:#d20;background-color:#fff0f0">"is_published"</span>: e.source.isAcceptingResponses(),
},
<span style="color:#d20;background-color:#fff0f0">"response"</span>: {
<span style="color:#d20;background-color:#fff0f0">"id"</span>: e.response.getId(),
<span style="color:#d20;background-color:#fff0f0">"email"</span>: e.response.getRespondentEmail(),
<span style="color:#d20;background-color:#fff0f0">"timestamp"</span>: e.response.getTimestamp(),
<span style="color:#d20;background-color:#fff0f0">"data"</span>: e.response.getItemResponses().map(<span style="color:#080;font-weight:bold">function</span>(y) {
<span style="color:#080;font-weight:bold">return</span> {
h: y.getItem().getTitle(),
k: y.getResponse()
}
}, <span style="color:#080;font-weight:bold">this</span>).reduce(<span style="color:#080;font-weight:bold">function</span>(r, y) {
r[y.h] = y.k;
<span style="color:#080;font-weight:bold">return</span> r
}, {}),
}
};
<span style="color:#080;font-weight:bold">var</span> options = {
method: <span style="color:#d20;background-color:#fff0f0">"post"</span>,
payload: JSON.stringify(data),
contentType: <span style="color:#d20;background-color:#fff0f0">"application/json; charset=utf-8"</span>,
};
<span style="color:#080;font-weight:bold">var</span> settings = PropertiesService.getDocumentProperties();
UrlFetchApp.fetch(settings.getProperty(<span style="color:#d20;background-color:#fff0f0">'url'</span>), options);
};
</code></pre></div><p>Let’s break it down. First, we compile the data that we want to send to our application. Form triggers accept a variable in their parameter, which we named <code>e</code> here. <code>e</code> is an <a href="https://developers.google.com/apps-script/guides/triggers/events?hl=en">Event Object</a>, and it provides us access to the form’s information (via <code>e.source</code>) as well as the responses to the form (via <code>e.response</code>). We gather all this in an object (called <code>data</code> in this case) and submit it to our app via the <code>UrlFetchApp</code>.</p>
<p><a href="https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app">UrlFetchApp</a> is a standard library in Google Apps Script. It allows us to make HTTP requests to other applications. Here, we are doing a <code>POST</code> HTTP request to the URL that we set (obtained via <code>PropertiesService.getDocumentProperties.getProperty('url')</code>).</p>
<h5 id="adjusting-the-form-trigger">Adjusting the form trigger</h5>
<p>Right now, <code>sendResponse</code> is not hooked to any function. Let’s hook it to the form trigger with this code:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-javascript" data-lang="javascript"><span style="color:#080;font-weight:bold">function</span> adjustFormSubmitTrigger() {
<span style="color:#080;font-weight:bold">var</span> form = FormApp.getActiveForm();
<span style="color:#080;font-weight:bold">var</span> triggers = ScriptApp.getUserTriggers(form);
<span style="color:#080;font-weight:bold">var</span> settings = PropertiesService.getDocumentProperties();
<span style="color:#080;font-weight:bold">var</span> url = settings.getProperty(<span style="color:#d20;background-color:#fff0f0">'url'</span>)
<span style="color:#080;font-weight:bold">var</span> triggerNeeded = url && url.length > <span style="color:#00d;font-weight:bold">0</span>;
<span style="color:#888">// Create a new trigger if required; delete existing trigger
</span><span style="color:#888"></span> <span style="color:#888">// if it is not needed.
</span><span style="color:#888"></span> <span style="color:#080;font-weight:bold">var</span> existingTrigger = <span style="color:#080;font-weight:bold">null</span>;
<span style="color:#080;font-weight:bold">for</span> (<span style="color:#080;font-weight:bold">var</span> i = <span style="color:#00d;font-weight:bold">0</span>; i < triggers.length; i++) {
<span style="color:#080;font-weight:bold">if</span> (triggers[i].getEventType() == ScriptApp.EventType.ON_FORM_SUBMIT) {
existingTrigger = triggers[i];
<span style="color:#080;font-weight:bold">break</span>;
}
}
<span style="color:#080;font-weight:bold">if</span> (triggerNeeded && !existingTrigger) {
<span style="color:#080;font-weight:bold">var</span> trigger = ScriptApp.newTrigger(<span style="color:#d20;background-color:#fff0f0">'sendResponse'</span>)
.forForm(form)
.onFormSubmit()
.create();
} <span style="color:#080;font-weight:bold">else</span> <span style="color:#080;font-weight:bold">if</span> (!triggerNeeded && existingTrigger) {
ScriptApp.deleteTrigger(existingTrigger);
}
}
</code></pre></div><p>Don’t forget to also uncomment <code>// adjustFormSubmitTrigger</code> in the <code>saveSettings</code> function.</p>
<p>This function is pretty straightforward. It checks if there is a URL saved in the settings and installs the form submit trigger if needed. If there is no URL saved or if it’s an empty string, then any existing form submit trigger will be deleted. Changing the URL will not do anything to the existing form submit trigger, since <code>sendResponse</code> will always pull the latest URL from the settings.</p>
<h4 id="6-test-the-triggers">6. Test the triggers</h4>
<p>Now we can test the submission. Let’s configure our add-on with a valid URL to our app, add a couple of questions to our form, then hit <code>Preview</code> in the top navigation bar to test our form submit trigger.</p>
<p><img src="/blog/2021/11/forwarding-google-forms-responses-to-api/forms-question.png" alt="Form"></p>
<p>Once we’ve filled the form, hit <code>Submit</code>. You should now see your form response gets sent to your destination URL as a POST request.</p>
<p><img src="/blog/2021/11/forwarding-google-forms-responses-to-api/forms-sample-response.png" alt="Form submit"></p>
<p>Here’s what I get from a simple Express app I developed to receive the response:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-plaintext" data-lang="plaintext">Example app listening at http://localhost:4000
</code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-json" data-lang="json">{
<span style="color:#b06;font-weight:bold">"form"</span>: {
<span style="color:#b06;font-weight:bold">"id"</span>: <span style="color:#d20;background-color:#fff0f0">"1zm_anJLsYnnmI-MlRqLcEhK8Eemd90rg_oJmsThiONw"</span>,
<span style="color:#b06;font-weight:bold">"title"</span>: <span style="color:#d20;background-color:#fff0f0">"HR Benefits Survey"</span>,
<span style="color:#b06;font-weight:bold">"is_private"</span>: <span style="color:#080;font-weight:bold">true</span>,
<span style="color:#b06;font-weight:bold">"is_published"</span>: <span style="color:#080;font-weight:bold">true</span>
},
<span style="color:#b06;font-weight:bold">"response"</span>: {
<span style="color:#b06;font-weight:bold">"id"</span>: <span style="color:#d20;background-color:#fff0f0">"2_ABaOnufmy5dDzYsUl3-G5vlkQaOPoW-Jf5Wskk9SZHhXvpgnTzx6LGVq9YGDqivvo6TXpko"</span>,
<span style="color:#b06;font-weight:bold">"email"</span>: <span style="color:#d20;background-color:#fff0f0">""</span>,
<span style="color:#b06;font-weight:bold">"timestamp"</span>: <span style="color:#d20;background-color:#fff0f0">"2021-11-07T08:56:08.299Z"</span>,
<span style="color:#b06;font-weight:bold">"data"</span>: {
<span style="color:#b06;font-weight:bold">"What's the most important thing for you?"</span>: <span style="color:#d20;background-color:#fff0f0">"4-day workweek"</span>,
<span style="color:#b06;font-weight:bold">"Select games you'd like to have at the office"</span>: [
<span style="color:#d20;background-color:#fff0f0">"Foosball"</span>,
<span style="color:#d20;background-color:#fff0f0">"Dart"</span>
]
}
}
}
</code></pre></div><h3 id="conclusion">Conclusion</h3>
<p>That’s it! We can now send Google Forms responses to our app for better data processing and visualization.</p>