I'm building a website hosted on Netlify that submits a form to a Google Apps Script web app. The form data is sent as JSON with the Content-Type: application/json header using the fetch API.
The issue I'm encountering is that within my Google Apps Script's doPost(e) function, the e.postData property is consistently undefined. This is preventing me from accessing the data sent from my Netlify site.
My Google Apps Script web app is deployed with the following settings:
- Execute as: Me (my Google account email)
- Who has access: Anyone with the link
- The web app URL is:
https://script.google.com/macros/s/AKfycbx8tg0J8GmI7gGvYu2iIiqB6JQK2PxbpBpGTLioS_Jv7i09LVZAvK1jbymkN3A048Vd/exec
Here are the relevant code snippets:
JavaScript (Netlify - Form Submission):
JavaScript
document.getElementById('requestForm').addEventListener('submit', async function(e) {
e.preventDefault();
const form = e.target;
const data = Object.fromEntries(new FormData(form).entries());
data.ip = userIP;
try {
const response = await fetch(
"https://script.google.com/macros/s/AKfycbx8tg0J8GmI7gGvYu2iIiqB6JQK2PxbpBpGTLioS_Jv7i09LVZAvK1jbymkN3A048Vd/exec",
{ method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(data) }
);
// ... (rest of your fetch handling - if relevant, you can include a brief summary) ...
} catch (err) {
console.error("Submit error:", err);
// ...
}
});
Google Apps Script (doOptions(e)):
JavaScript
function doOptions(e) {
Logger.log("doOptions called");
Logger.log(JSON.stringify(e));
const output = ContentService.createTextOutput('');
output.setMimeType(ContentService.MimeType.TEXT);
output.setHeader('Access-Control-Allow-Origin', 'https://sanibelsong.com');
output.setHeader('Access-Control-Allow-Methods', 'GET,POST,OPTIONS');
output.setHeader('Access-Control-Allow-Headers', 'Content-Type');
return output;
}
Google Apps Script (doPost(e) - with logging):
JavaScript
function doPost(e) {
Logger.log("doPost called");
Logger.log("e.postData: " + JSON.stringify(e.postData));
try {
const data = JSON.parse(e.postData.contents || '{}');
// ... (rest of your doPost logic) ...
} catch (err) {
Logger.log("Error in doPost: " + err);
// ... (your error handling) ...
}
}
Troubleshooting Steps Already Taken:
- Verified the Google Apps Script web app URL in the fetch request. Checked the deployment settings in Google Apps Script.
- Implemented and confirmed that the
doOptions(e)function is being called (initially saw a 400 on OPTIONS, but now it seems to be 200). - Tried simplifying the
doOptions(e)function. - Confirmed that a simple
doGet(e)function works. - Logged the e object in
doPost(e)(unfortunately,e.postDatais logged as undefined, and the error occurs before we can see the entire e object). - Tried inlining CORS headers directly in doPost(e).
- Created and deployed from a brand new Google Apps Script project.
- Reviewed Netlify DNS records, which appear standard.
Error Message:
The error I consistently receive in the Google Apps Script Execution Log is:
TypeError: Cannot read properties of undefined (reading 'postData')
Browser Network Tab:
The OPTIONS request to the Apps Script URL now seems to be returning a 200 OK status with the expected CORS headers. The POST request to the same URL also returns a 200 OK status in the browser, but the Google Apps Script logs indicate that e.postData is undefined.
My Question:
- Why is
e.postDataconsistently undefined in mydoPost(e)function despite sending a POST request with application/json content from my Netlify website? - Is there a configuration issue I'm overlooking on either the Netlify or Google Apps Script side?
- Could there be a subtle header issue or a limitation in how Google Apps Script handles POST requests from external domains in this specific scenario?
-
Duplicate of How do i allow a CORS requests in my google script?Wicket– Wicket2025年08月06日 22:28:37 +00:00Commented Aug 6 at 22:28
-
Related XMLHttpRequest blocked by CORS policy when posting data to a Web AppWicket– Wicket2025年08月09日 15:46:18 +00:00Commented Aug 9 at 15:46
1 Answer 1
From your question, I understood that your setting of Web Apps is as follows.
- Execute as: Me
- Who has access to the app: Anyone
Although I'm not sure whether this is the direct solution to your current issue, how about the following modification? Please modify your JavaScript as follows.
From:
const response = await fetch(
"https://script.google.com/macros/s/AKfycbx8tg0J8GmI7gGvYu2iIiqB6JQK2PxbpBpGTLioS_Jv7i09LVZAvK1jbymkN3A048Vd/exec",
{ method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(data) }
);
To:
const response = await fetch(
"https://script.google.com/macros/s/AKfycbx8tg0J8GmI7gGvYu2iIiqB6JQK2PxbpBpGTLioS_Jv7i09LVZAvK1jbymkN3A048Vd/exec",
{ method: "POST", body: JSON.stringify(data) }
);
or
const response = await fetch(
"https://script.google.com/macros/s/AKfycbx8tg0J8GmI7gGvYu2iIiqB6JQK2PxbpBpGTLioS_Jv7i09LVZAvK1jbymkN3A048Vd/exec",
{ method: "POST", headers: { "Content-Type": "text/plain" }, body: JSON.stringify(data) }
);
Also, at doPost in your showing script, no value is returned. In that case, how about the following modification?
function doPost(e) {
Logger.log("doPost called");
Logger.log("e.postData: " + JSON.stringify(e.postData));
try {
const data = JSON.parse(e.postData.contents || '{}');
// ... (rest of your doPost logic) ...
} catch (err) {
Logger.log("Error in doPost: " + err);
// ... (your error handling) ...
}
return ContentService.createTextOutput("ok"); // Added
}
When I tested the above modified script using data of a sample value, I confirmed that no error occurs and const data = JSON.parse(e.postData.contents || '{}'); at Google Apps Script worked.
Note:
In your showing script, it seems that Web Apps is used. When you modify the Google Apps Script of Web Apps, please modify the deployment as a new version. By this, the modified script is reflected in Web Apps. Please be careful about this.
You can see the details of this in my report "Redeploying Web Apps without Changing URL of Web Apps (Author: me)".
References:
Comments
Explore related questions
See similar questions with these tags.