# Create posts from Google Forms responses

**URL:** https://meta.discourse.org/t/create-posts-from-google-forms-responses/21008
**Category:** Administrators
**Tags:** how-to
**Created:** [October 10, 2014, 11:01am UTC](https://meta.discourse.org/t/create-posts-from-google-forms-responses/21008 "2014-10-10T11:01:44Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![lightyear](https://avatars.discourse-cdn.com/v4/letter/l/848f3c/32.png) [@lightyear](https://meta.discourse.org/u/lightyear)
#### Post date: [October 10, 2014, 11:01am UTC](https://meta.discourse.org/t/create-posts-from-google-forms-responses/21008/1 "2014-10-10T11:01:44Z")

</div>

Heyah,

I have written a short script **automatically posting new Google-Form-Entries to Discourse**. You can use it to allow any kind of 3-party Data input into discourse for example:

- Anonymous Feedback
- Support-Request
- Membership-Applications (this is what we do with it)

### The script

The script is small and simple:

```javascript
// ----- MINIMUM CONFIGURATION !!!!
// generate this at /admin/api
API_KEY = "d29dXXXXXXXXXXXXXXXXXXXXX70"
// use full qualified domain name in url to discourse index
TARGET_INSTALLATION = "http://DISCOURSE.EXAMPLE.ORG/"

// ----- Optional Configuartion

// which category to post this to? Default: 'uncategorized'
CATEGORY = 'uncategorized'
// which user should be the one posting? Default: 'system'
POSTER = "system"

// you probably wanna activate this, when using templates
INCLUDE_RAW_DATA = true

// the title to post at,
// should contain any 'form'-replacer or Discourse might complain it already has that title
TITLE_TEMPLATE = "New Form Entry: {{Name}}"

// Wanna have it look pretty?
TEMPLATE = "# {{Name}}\n\n - Water Type: {{Water}}" + 
             

function _compile(source, values){
    var processed = source;
    for (key in values) {
      processed = processed.replace("{{" + key + "}}", values[key]);
    }
    return processed;
  }

function _compile_data_from_form(formResponse){
  var data = {},
      itemResponses = formResponse.getItemResponses();
  for (var j = 0; j < itemResponses.length; j++) {
    var itemResponse = itemResponses[j];
    data[itemResponse.getItem().getTitle()] = itemResponse.getResponse();
  }
  return data;
 }

function postToDiscourse(evt) {
  
  var vals = evt.namedValues || _compile_data_from_form(evt.response),
      title = _compile(TITLE_TEMPLATE, vals),
      text = _compile(TEMPLATE, vals);
 
  if (INCLUDE_RAW_DATA) {
    var entries = [];
    for (key in vals){
      entries.push(" - **" + key + "** : " + vals[key]);
    }
    text += "\n Raw Values: \n\n" + entries.join('\n');
  }
  
  UrlFetchApp.fetch(TARGET_INSTALLATION + "/posts", {'method': 'post', 'payload':{
                    'category': CATEGORY,
                    'auto_track': false,
                    'title': title,
                    'raw': text,
                    'api_key': API_KEY,
                    'api_username': POSTER
                    }});
}

function API_TEST(){
  //var form = {namedValues:{'Name': 'Benji', 'Email': 'Testi'}};
  var form = FormApp.openById("1RnCD4I2VgWpzTiJTq-0qq6u-v-LEpEKQgOBmhafTsQo"),
      formResponses = form.getResponses(),
      newestResponse = formResponses[formResponses.length -1];
  postToDiscourse({response: newestResponse});
}

```

### Installation

1. Generate an ADMIN-Key of your installation at /admin/api

2. Add Script to a new googles form or existing one via `Tools-> Script Editor`  
 ![](https://global.discourse-cdn.com/meta/original/3X/3/a/3ac2c05306bea1bf1bffcd1ab6c07128901d5fc2.png)

3. Copy the entire script into the new Editor that opens

4. Replace the API-Key in the script with the one from your installation,  
Change the Installation-Target-Name

5. Save and check your configuration by running the “API\_TEST” function:  
 ![](https://global.discourse-cdn.com/meta/original/3X/d/9/d919b8d3054432c8e48250cd3ee16ff1fa1e6453.png) ![](https://global.discourse-cdn.com/meta/original/3X/3/f/3f4544f93df306f8f36c916e19f7bc025e6318e8.png)

6. A new post should show up in your Discourse.  
– you might want to do redo this one until the configuration (posting user, posting in proper category) are all figure out

7. Connect function to trigger by going to `Resources->All Triggers` and an on-form-submit-trigger connected to the `postToDiscourse` function:  
 ![](https://global.discourse-cdn.com/meta/original/3X/1/6/16dd3f7b4ecb5fe7743768682e8c6cb583572326.png) ![](https://global.discourse-cdn.com/meta/original/3X/1/1/11ecd15ce45a2bbd55ca8096eac84f92e65b0907.png)  
(you might be asked to give permission when saving the first time: yes, please do so)

**Voilá, you’ll receive new posts (including all update and email features) of forms submitted in your discourse instance from now on.**

You might want to also take a look at my [“automatically email form-data” script and add that one](https://gist.github.com/ligthyear/5488787), too. As always, feel free to posts questions, feedback and praise right down here as replies 🙂 .

---

<div class="post-metadata">

### Author: ![lightyear](https://avatars.discourse-cdn.com/v4/letter/l/848f3c/32.png) [@lightyear](https://meta.discourse.org/u/lightyear)
#### Post date: [October 14, 2014, 6:24pm UTC](https://meta.discourse.org/t/create-posts-from-google-forms-responses/21008/2 "2014-10-14T18:24:14Z")

</div>

Looks like there was a tiny bug in the form, where it didn’t succeed when using form-only-forms. Updated the original Post with the fix.

---

<div class="post-metadata">

### Author: ![SGTGunner](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/sgtgunner/32/121330_2.png) [@SGTGunner](https://meta.discourse.org/u/SGTGunner)
#### Post date: [November 13, 2016, 7:51pm UTC](https://meta.discourse.org/t/create-posts-from-google-forms-responses/21008/3 "2016-11-13T19:51:30Z")

</div>

This still works really well. Thought the Google forms UI has changed a little, easy to work out.  
But there is a bug in the code if folks are not aware of:

> [@lightyear](#):
>
> TEMPLATE = “# {{Name}}\n\n - Water Type: {{Water}}” +

Need to remove the + on the end. I suspect that there was more content but wasn’t finished.

Great job!

~Cheers

---

<div class="post-metadata">

### Author: ![thaidb](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/thaidb/32/68488_2.png) [@thaidb](https://meta.discourse.org/u/thaidb)
#### Post date: [February 22, 2020, 4:08pm UTC](https://meta.discourse.org/t/create-posts-from-google-forms-responses/21008/4 "2020-02-22T16:08:53Z")

</div>

Can you build a plugin for easier setup google form 🙂

---

<div class="post-metadata">

### Author: ![srmrox](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/srmrox/32/224645_2.png) [@srmrox](https://meta.discourse.org/u/srmrox)
#### Post date: [June 18, 2021, 1:04am UTC](https://meta.discourse.org/t/create-posts-from-google-forms-responses/21008/5 "2021-06-18T01:04:11Z")

</div>

Since the API changed, the code for Google Forms (Google App Script) changed too. Here is a sample with a single question in the form.

```plaintext
FORM_ID = "<get this from the form URL>"
ITEM_ID = <get this from the Developer tools, look for the id of the whole question element> // int value

URL = "<site URL with the trailing />"
CATEGORY = <from sites.json> // int value
API_KEY = "<admin API key>"
POSTER = "<assigned user name to the key>"

MAX_TITLE_SIZE = 50 // this is just to keep title size in control

function onFormSubmit() {
  var form = FormApp.openById(FORM_ID),
      item = form.getItemById(ITEM_ID), // repeat this for all items in the form or use alternative means of getting all items
      formResponses = form.getResponses(),
      newestResponse = formResponses[formResponses.length - 1],
      response = newestResponse.getResponseForItem(item).getResponse(); // this reads only the single item noted above

  console.log(response)

  if (response.length < 20) {
    response = "New topic posted: " + response // just to make sure response captured is > 20 characters
  }

  var title = response.substring(0,Math.min(MAX_TITLE_SIZE,response.length)); // just to make sure the title is not too big

	const url = URL + "posts";
	
  const fetched = UrlFetchApp.fetch(url, {
		"method": "POST",
		"headers": {
			"Api-Key": API_KEY,
			"Api-Username": POSTER,
			"Content-Type": "multipart/form-data",
			"Accept": "application/json",
			"Content-Type": "application/json"
		},
		"muteHttpExceptions": true,
		"followRedirects": true,
		"validateHttpsCertificates": true,
		"contentType": "application/json",
		"payload": JSON.stringify({"title":title,"raw":response,"category":CATEGORY})
	});

	Logger.log("Response code is %s", fetched.getResponseCode());
	Logger.log(fetched.getContentText());
}

```

I hope this helps anyone looking for something similar for the original topic but with the new API.
