- 
      
- 
        Save skatkov/b524a6e60a5313acc4d299471a2a3902 to your computer and use it in GitHub Desktop. 
| MAILCHIMP_API_KEY="...-us19" | |
| MAILCHIMP_LIST_ID="..." | 
| import { parse } from 'querystring' | |
| const axios = require('axios'); | |
| const mailChimpAPI = process.env.MAILCHIMP_API_KEY; | |
| const mailChimpListID = process.env.MAILCHIMP_LIST_ID; | |
| exports.handler = (event, context, callback) => { | |
| let body = {} | |
| console.log(event) | |
| try { | |
| body = JSON.parse(event.body) | |
| } catch (e) { | |
| body = parse(event.body) | |
| } | |
| if (!body.email) { | |
| console.log('missing email') | |
| return callback(null, { | |
| statusCode: 400, | |
| body: JSON.stringify({ | |
| error: 'missing email' | |
| }) | |
| }) | |
| } | |
| if (!mailChimpAPI) { | |
| console.log('missing mailChimpAPI key') | |
| return callback(null, { | |
| statusCode: 400, | |
| body: JSON.stringify({ | |
| error: 'missing mailChimpAPI key' | |
| }) | |
| }) | |
| } | |
| if (!mailChimpListID) { | |
| console.log('missing mailChimpListID key') | |
| return callback(null, { | |
| statusCode: 400, | |
| body: JSON.stringify({ | |
| error: 'missing mailChimpListID key' | |
| }) | |
| }) | |
| } | |
| const data = { | |
| email_address: body.email, | |
| status: "pending", | |
| merge_fields: {} | |
| }; | |
| const subscriber = JSON.stringify(data); | |
| console.log("Sending data to mailchimp", subscriber); | |
| // Subscribe an email | |
| axios( | |
| { | |
| method: 'post', | |
| url: `https://us19.api.mailchimp.com/3.0/lists/${mailChimpListID}/members/`, //change region (us19) based on last values of ListId. | |
| data: subscriber, | |
| auth: { | |
| username: 'apikey', // any value will work | |
| password: mailChimpAPI | |
| } | |
| } | |
| ).then(function(response){ | |
| console.log(`status:${response.status}` ) | |
| console.log(`data:${response.data}` ) | |
| console.log(`headers:${response.headers}` ) | |
| if (response.headers['content-type'] === 'application/x-www-form-urlencoded') { | |
| // Do redirect for non JS enabled browsers | |
| return callback(null, { | |
| statusCode: 302, | |
| headers: { | |
| Location: '/thanks.html', | |
| 'Cache-Control': 'no-cache', | |
| }, | |
| body: JSON.stringify({}) | |
| }); | |
| } | |
| // Return data to AJAX request | |
| return callback(null, { | |
| statusCode: 200, | |
| body: JSON.stringify({ emailAdded: true }) | |
| }) | |
| }).catch(function(error) { | |
| if (error.response) { | |
| // The request was made and the server responded with a status code | |
| // that falls out of the range of 2xx | |
| console.log(error.response.data); | |
| console.log(error.response.status); | |
| console.log(error.response.headers); | |
| } else if (error.request) { | |
| // The request was made but no response was received | |
| console.log(error.request); | |
| } else { | |
| // Something happened in setting up the request that triggered an Error | |
| console.log('Error', error.message); | |
| } | |
| console.log(error.config); | |
| }); | |
| }; | 
| { | |
| "scripts": { | |
| "start": "netlify-lambda serve source/lambda", | |
| "build": "netlify-lambda build source/lambda" | |
| }, | |
| "dependencies": { | |
| "axios": "^0.19.0", | |
| "dotenv": "^8.1.0", | |
| "netlify-lambda": "^1.6.3" | |
| } | |
| } | 
| <div id="message"></div> | |
| <form id="newsletter" class="subscribe" action="/.netlify/functions/form-handler" method="post"> | |
| <input type="email" id="inputEmail" name='email' placeholder="Enter email to subscribe for FREE" class="email" required autofocus> | |
| <button class="button" type="submit">Subscribe</button> | |
| </form> | |
| <script> | |
| var form = document.getElementById('newsletter'); | |
| form.addEventListener("submit", function(e) { | |
| e.preventDefault(); | |
| email = document.getElementById('inputEmail').value; | |
| submitEmail(email) | |
| }); | |
| function submitEmail(email) { | |
| fetch('/.netlify/functions/form-handler', { | |
| method: 'post', | |
| body: JSON.stringify({ | |
| email: email | |
| }) | |
| }).then(function(response) { | |
| return response.json(); | |
| }).then(function(data) { | |
| console.log('data from function', data); | |
| messageDiv = document.getElementById('message'); | |
| messageDiv.innerText = 'Confirmation email has been sent!' | |
| }); | |
| }; | |
| </script> | 
I'm trying to deploy this on Netlify and running into an error: "SyntaxError: Cannot use import statement outside a module" with the form-handler.js. From what I understand this means that my build is not transpiled using netlify-lambda.
What does your netlify.toml look like for this gist?
@dejardine changing it to const { parse } = require('querystring'); should work without having to transpile the code
This is great! Thanks! I wonder how you would go about handling errors?
Currently, when submitting [email protected] or an already subscribed email address I get this in the browser console:
POST http://localhost:8888/.netlify/functions/form-handler 500 (Internal Server Error)
VM4085:1 Uncaught (in promise) SyntaxError: Unexpected token T in JSON at position 0
And, a timeout when viewing the logs when netlify dev is running: Task timed out after 10.00 seconds
Thank you for the tutorial and this code, it's been really helpful.
I don't know if something has changed since you wrote it, or if it has to do with my setup (using Astro and netlify), but the test for disabled javascript: if (response.headers['content-type'] === 'application/x-www-form-urlencoded') { ... } isn't working for me. I tried a lot of combinations, but with javascript disabled in the browser, response.headers always had a content-type of application/json, same as when javascript was enabled.
In order to distinguish form data submitted by ajax, I had the javascript add a field to the form data:
body: JSON.stringify({
          email: email,
          "js-submit": true, // form-handler.js can use this to determine whether to return a 302 redirect or a 200
        })
This function was open source from https://www.fbacatalog.com project.
To find more details on this code and our porject -- read up dev.to community post https://dev.to/skatkov/jamstack-progressive-mailchimp-sign-up-form-with-netlify-13m3
Thanks for your interest!