Skip to content

Instantly share code, notes, and snippets.

@skatkov
Last active April 8, 2023 10:08
Show Gist options
  • Save skatkov/b524a6e60a5313acc4d299471a2a3902 to your computer and use it in GitHub Desktop.
Save skatkov/b524a6e60a5313acc4d299471a2a3902 to your computer and use it in GitHub Desktop.
Progressive mailchimp subscription on Netlify
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>
@skatkov
Copy link
Author

skatkov commented Sep 22, 2019

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!

@dejardine
Copy link

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?

@sgnl
Copy link

sgnl commented Dec 22, 2021

@dejardine changing it to const { parse } = require('querystring'); should work without having to transpile the code

@alistairtweedie
Copy link

This is great! Thanks! I wonder how you would go about handling errors?

Currently, when submitting test@test.com 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

@paulrudy
Copy link

paulrudy commented Sep 21, 2022

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
        })

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment