Answers.Body: <p>[<strong>Note</strong>: With apologies to Jeff Goldblum, I was so preoccupied with whether I <em>could</em> do this, I didn't stop to think if I <em>should</em>.  See the bottom for some caveats.]</p>
  <p>You can do this by adding a <em>Google Script</em> and <em>trigger</em> to your Google Form, and installing <a href="https://civicrm.org/extensions/form-processor" rel="nofollow noreferrer">Form Processor</a> on the CiviCRM side.</p>
  <p>Configuring Form Processor is out of scope of this question - there are <a href="https://docs.civicrm.org/formprocessor/en/latest/" rel="nofollow noreferrer">documentation</a> and <a href="https://civicrm.org/blog/jaapjansma/using-civicrm-form-processor-extension-to-handle-form-submissions-from-an-external" rel="nofollow noreferrer">blog posts</a> available to explain that.  However, no documentation exists for the Google side.</p>
  <h3>Instructions</h3>
  <ul>
  <li>From the Google Forms editing screen, click the <strong>More</strong> menu (three vertical dots) and select <strong>Script Editor</strong>.
  <ul>
  <li>This won't appear if you're too zoomed in.</li>
  </ul>
  </li>
  <li>Paste the following code into the editor and press <strong>Save</strong> (<a href="https://gist.github.com/MegaphoneJon/b1b344edeba594bbdd0acb0c31f47c6b" rel="nofollow noreferrer">latest version</a> on Github):</li>
  </ul>
  <pre><code>/**
   * @OnlyCurrentDoc
   */
  
  function onFormSubmit(event) {
  
    // Set the values on these four lines for your Form Processor and site.
    var url = '&lt;API3 REST Endpoint here&gt;';
    var api_key = '&lt;api key here&gt;';
    var site_key = '&lt;site key here&gt;';
    var form_processor_machine_name = '&lt;machine name of Form Processor here&gt;';
  
    // Don't modify anything below this line.
    var submission = {};
    var responses = event.response.getItemResponses();
    for (var i = 0; i &lt; responses.length; i++) {
      // Convert all non-alphanumeric values in the title to underscores, lowercase as well.
      title = responses[i].getItem().getTitle().replace(/[\W]+/g,&quot;_&quot;).toLowerCase();
      submission[title] = responses[i].getResponse();
    }
    
  
    var payload = { 
      &quot;entity&quot;: &quot;FormProcessor&quot;,
      &quot;action&quot;: form_processor_machine_name,
      &quot;json&quot;: JSON.stringify(submission),
      &quot;api_key&quot; : api_key,
      &quot;key&quot;: site_key,
    }
    var options = {
      &quot;method&quot; : &quot;post&quot;,
      &quot;payload&quot; : payload,
      &quot;muteHttpExceptions&quot; : true,
    };
  
    Logger.log(JSON.stringify(submission));
    // Fire the webhook.
    var response = UrlFetchApp.fetch(url,options);
  }
  </code></pre>
  <ul>
  <li><p>Modify the indicated lines at the top of the script to add these values:</p>
  <ul>
  <li>The URL of your REST endpoint (varies by CMS and by CiviCRM version; check the <a href="https://docs.civicrm.org/dev/en/latest/api/v3/rest/#end-point-url" rel="nofollow noreferrer">REST Endpoint</a> documentation);</li>
  <li>The API key of a user with the necessary permission specified by your Form Processor configuration;</li>
  <li>The site key (can be found in <code>civicrm.settings.php</code>);</li>
  <li>The machine name of your Form Processor instance (can be found in the configuration).</li>
  </ul>
  </li>
  <li><p>In the Google Script editor left navigation, click the <strong>Triggers</strong> tab, click <strong>Add a Trigger</strong> and configure it as follows:</p>
  <ul>
  <li><em>Choose which function to run</em>: <strong>onFormSubmit</strong></li>
  <li><em>Which runs at deployment</em>: <strong>Head</strong></li>
  <li><em>Select event source</em>: <strong>From form</strong></li>
  <li><em>Select event type</em>: <strong>On form submit</strong>.</li>
  <li><strong>NOTE</strong>: If you create the trigger before adding the code, Google won't ask you to authorize the necessary scopes.  Create the trigger last.</li>
  </ul>
  </li>
  </ul>
  <p>Now your forms will send the data to CiviCRM when they're submitted!  To find the names of the inputs to configure Form Processor, do a test form submission, then in Google Script editor, click the <strong>Executions</strong> tab.  The script will log the payload to Form Processor, and you can easily see the names of the fields as CiviCRM will see them.</p>
  <p><strong>Caveats</strong>
  This makes for an extremely brittle solution.</p>
  <ul>
  <li>Google Forms doesn't have &quot;machine names&quot; for fields - so changing a label requires a change in Form Processor or that field isn't processed.</li>
  <li>Multiple choice values must match EXACTLY in Google and Civi.  Punctuation and case included.</li>
  <li>Changing your multiple-choice options in Google will cause a form to crash if that option doesn't also change in Civi.</li>
  <li>Multiple choice values changed in Civi won't crash the form, but obviously need to be replicated in Google.</li>
  </ul>
  <p>In short - this is an inferior solution to, say, Civi Form Builder. It only makes sense if you have an existing Google Form that is embedded in your workflows, which changes rarely if ever.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-05-04T18:07:27.880Z
Answers.Text: Very nice, @Jon. Thanks for sharing this useful documentation.
Answers.UserDisplayName: Joe Murray
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-01-28T21:51:43.507Z
Answers.Text: Jon, how could I modify your code above so that instead of submitting the option text in a multiple-choice question (call this the script submits a "value" derived from the choice, e.g., if the options are "London", "Wight", and "West Sussex" and the user chooses "Wight" then the value "2" will be sent to the form processor. I can see this isn't a whole lot different from the manipulation you do on GitHub for option text "Yes" and "No" but I'm not knowledgeable of this script language and so can't work out how to make this modification. Your script is super useful. Thank you.
Answers.UserDisplayName: gillenpj
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-01-29T18:17:59.320Z
Answers.Text: @gillenpj You couldn't do that without hardcoding quite a bit into the script - but it's pretty straightforward on the Form Processor side.  Make sure you're passing it to an "Option Group" input, and then select the "Use label as value" checkbox.  It will convert it automatically for you.
Answers.UserDisplayName: Jon G - Megaphone Tech
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-01-29T19:44:18.367Z
Answers.Text: Jon, this is awesome! Thank you so much. It works a charm.
Answers.UserDisplayName: gillenpj
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-05-03T20:37:00.610Z
Answers.LastActivityDate: 2023-09-18T15:13:41.433Z
Answers.LastEditDate: 2023-09-18T15:13:41.433Z
Answers.UserDisplayName: Jon G - Megaphone Tech
Body: <p>I have a complicated Google Form I've already written.  While it could be reimplemented in Caldera Forms, this would be time-consuming, and Caldera Forms is no longer being developed.  Is there a way to integrate Google Forms with CiviCRM?</p>
  
Tags: <forms><form-processor>
Title: How can I integrate Google Forms with CiviCRM?
ThreadText: # How can I integrate Google Forms with CiviCRM?
  
  (Asked by: username_0 on 2021-05-03)
  
  I have a complicated Google Form I've already written. While it could be reimplemented in Caldera Forms, this would be time-consuming, and Caldera Forms is no longer being developed. Is there a way to integrate Google Forms with CiviCRM?
  
  **Tags:** forms, form-processor
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_0 on 2021-05-03. Score: 10
  
  [**Note**: With apologies to Jeff Goldblum, I was so preoccupied with whether I *could* do this, I didn't stop to think if I *should*. See the bottom for some caveats.]
  
  You can do this by adding a *Google Script* and *trigger* to your Google Form, and installing [Form Processor](https://civicrm.org/extensions/form-processor) on the CiviCRM side.
  
  Configuring Form Processor is out of scope of this question - there are [documentation](https://docs.civicrm.org/formprocessor/en/latest/) and [blog posts](https://civicrm.org/blog/jaapjansma/using-civicrm-form-processor-extension-to-handle-form-submissions-from-an-external) available to explain that. However, no documentation exists for the Google side.
  
  ### Instructions
  
  * From the Google Forms editing screen, click the **More** menu (three vertical dots) and select **Script Editor**.
    + This won't appear if you're too zoomed in.
  * Paste the following code into the editor and press **Save** ([latest version](https://gist.github.com/MegaphoneJon/b1b344edeba594bbdd0acb0c31f47c6b) on Github):
  
  ```
  /**
   * @OnlyCurrentDoc
   */
  
  function onFormSubmit(event) {
  
    // Set the values on these four lines for your Form Processor and site.
    var url = '<API3 REST Endpoint here>';
    var api_key = '<api key here>';
    var site_key = '<site key here>';
    var form_processor_machine_name = '<machine name of Form Processor here>';
  
    // Don't modify anything below this line.
    var submission = {};
    var responses = event.response.getItemResponses();
    for (var i = 0; i < responses.length; i++) {
      // Convert all non-alphanumeric values in the title to underscores, lowercase as well.
      title = responses[i].getItem().getTitle().replace(/[\W]+/g,"_").toLowerCase();
      submission[title] = responses[i].getResponse();
    }
    
  
    var payload = { 
      "entity": "FormProcessor",
      "action": form_processor_machine_name,
      "json": JSON.stringify(submission),
      "api_key" : api_key,
      "key": site_key,
    }
    var options = {
      "method" : "post",
      "payload" : payload,
      "muteHttpExceptions" : true,
    };
  
    Logger.log(JSON.stringify(submission));
    // Fire the webhook.
    var response = UrlFetchApp.fetch(url,options);
  }
  
  ```
  
  * Modify the indicated lines at the top of the script to add these values:
  
    + The URL of your REST endpoint (varies by CMS and by CiviCRM version; check the [REST Endpoint](https://docs.civicrm.org/dev/en/latest/api/v3/rest/#end-point-url) documentation);
    + The API key of a user with the necessary permission specified by your Form Processor configuration;
    + The site key (can be found in `civicrm.settings.php`);
    + The machine name of your Form Processor instance (can be found in the configuration).
  * In the Google Script editor left navigation, click the **Triggers** tab, click **Add a Trigger** and configure it as follows:
  
    + *Choose which function to run*: **onFormSubmit**
    + *Which runs at deployment*: **Head**
    + *Select event source*: **From form**
    + *Select event type*: **On form submit**.
    + **NOTE**: If you create the trigger before adding the code, Google won't ask you to authorize the necessary scopes. Create the trigger last.
  
  Now your forms will send the data to CiviCRM when they're submitted! To find the names of the inputs to configure Form Processor, do a test form submission, then in Google Script editor, click the **Executions** tab. The script will log the payload to Form Processor, and you can easily see the names of the fields as CiviCRM will see them.
  
  **Caveats**
  This makes for an extremely brittle solution.
  
  * Google Forms doesn't have "machine names" for fields - so changing a label requires a change in Form Processor or that field isn't processed.
  * Multiple choice values must match EXACTLY in Google and Civi. Punctuation and case included.
  * Changing your multiple-choice options in Google will cause a form to crash if that option doesn't also change in Civi.
  * Multiple choice values changed in Civi won't crash the form, but obviously need to be replicated in Google.
  
  In short - this is an inferior solution to, say, Civi Form Builder. It only makes sense if you have an existing Google Form that is embedded in your workflows, which changes rarely if ever.
  
  > **Comments:**
  > **username_1**: Very nice, @Jon. Thanks for sharing this useful documentation.  
  > **username_2**: Jon, how could I modify your code above so that instead of submitting the option text in a multiple-choice question (call this the script submits a "value" derived from the choice, e.g., if the options are "London", "Wight", and "West Sussex" and the user chooses "Wight" then the value "2" will be sent to the form processor. I can see this isn't a whole lot different from the manipulation you do on GitHub for option text "Yes" and "No" but I'm not knowledgeable of this script language and so can't work out how to make this modification. Your script is super useful. Thank you.  
  > **username_0**: @username_2 You couldn't do that without hardcoding quite a bit into the script - but it's pretty straightforward on the Form Processor side.  Make sure you're passing it to an "Option Group" input, and then select the "Use label as value" checkbox.  It will convert it automatically for you.  
  > **username_2**: Jon, this is awesome! Thank you so much. It works a charm.  
  
  ---
  
  