We've gotten so used to everything having an API that it can be a little bit disorienting when you encounter a situation where you cannot accomplish a task via an API. This can be especially difficult in the JAMstack world where any dynamic functionality is accomplished via an API of some sort - the A in JAM stands for APIs after all. In this post, I want to talk about a solution that can work in many cases where either an API doesn't exist or it doesn't necessarily do exactly what you want to achieve.
I have been using Zapier for some time. Like similar services such as IFTTT, it allows you to mash up tasks in a "when X event happens do Y" type of fashion. For example, I have used it to do things like automatically sign someone up for a mailing list when they register for an event I'm running or run a new Netlify build at a particular time each day. However, Zapier also has a feature called Webhooks that allow you to kind of "create your own API" by connecting the webhook to any service Zapier integrates with. (Note: IFTTT also offers webhooks that seem to work similarly.)
In this tutorial, I'll show you how to set up webhooks by Zapier to send information to a third-party service and how to integrate them into your JAMstack site using Netlify Functions. This combination allows you to quickly and easily create dynamic functionality on your JAMstack site and create services that do things existing APIs may not even support.
Note webhooks by Zapier are currently a premium feature.
The sample code from this post is available at https://github.com/remotesynth/webhooks.
Sending Data via a Webhook
The first scenario we'll look at is creating a webhook with an endpoint that receives data from your site and passes that data to an existing service Zapier supports.
Configuring a Webhook in Zapier
Let's start by creating a new webhook as an endpoint within Zapier. To start, make a new Zap and search for Webhooks by Zapier. Then for the type of trigger event choose "Catch Hook", which will give us a Zapier endpoint URL to post to.
When you continue to the next step, Zapier will give you your endpoint URL. This is where we will send our GET or POST requests to.
If you had complex data the child key could help you select only the data under a specific key but, for our purposes, it won't be necessary. The best thing to do here is to plug the URL into something like Postman and send a sample request. You'll see why in a moment. In my case, this will be a simple API that takes only a name and email.
The webhook should return a success status. It doesn't really matter what data you send, the webhook is designed to take whatever data and pass it along. Back in Zapier, click continue and you should see a request with sample data - this is why we sent the sample request. You can send additional requests and they will be listed here. Choosing one will allow you to map the data sent to the remainder of the zap. Click "Test & Continue" to move on to the next step.
In this example, we'll be doing something fairly simple, which is to pass the data into a Google Sheet. So, obviously you'll need the sheet set up. It's best to include headers as it makes mapping the data much easier. You can see my columns map to the data I sent to the webhook.
Next, for the "Do this..." step in Zapier search for Google Sheets. Choose "Create Spreadsheet Row" for the Action Event.
You'll need to choose your account - you may need to authenticate and grant Zapier permissions here as well.
Once the Google account is selected, you can choose the spreadsheet you want to use (I chose the simple sheet I created earlier), then worksheet within that spreadsheet and finally map the columns (based on the column headers) to the sample data from our previous POST to the Zapier webhook endpoint.
Ok. We're done in Zapier - just click "Test & Continue" to finish and then enable your Zap. Next we need to set up the Netlify function that will be used by our JAMstack site to call the Zapier webhook endpoint.
Creating the Netlify Function
Netlify Functions are serverless functions that run on AWS that can help turn your site from a static site to a JAMstack site by connecting with APIs or performing dynamic tasks. While this can obviously be accomplished by using a straight serverless cloud function on any provider, the benefit of Netlify Functions is that it simplifies the testing and deployment within the context of a JAMstack application.
To start, create a folder to place our Netlify functions (I named mine lambda
but you can name it anything). Next, create a netlify.toml
configuration file at the root of the site and add the following configuration to tell Netlify where to find our functions.
[build]
functions = "./lambda"
Now let's create our function. We'll be using Axios to handle our HTTP requests, so you'll need to install that first using npm install axios --savedev
. Then create a .js
file in our lambda
folder. It doesn't matter what it is called but I named mine zapierSend.js
. Let's look at the source for that file and I'll explain it.
const axios = require('axios');
exports.handler = async (event, context, callback) => {
try {
if(!event.body) {
return {
statusCode: 500,
body: 'Name and email are required.'
};
}
const body = JSON.parse(event.body);
const email = body.email;
const fullName = body.fullName;
if(!email) {
return {
statusCode: 500,
body: 'email parameter required'
};
}
if(!fullName) {
return {
statusCode: 500,
body: 'name parameter required'
};
}
return axios({
method: 'post',
url: 'https://hooks.zapier.com/hooks/catch/2422393/otw0s6l/',
data:{
'email':email,
'fullName':fullName
}
}).then(res => {
console.log(res);
return {
statusCode:200,
body: JSON.stringify(res.data)
}
})
.catch(err => {
return { statusCode: 200, body: JSON.stringify(err.response.data.errors[0]) };
});
} catch (err) {[]
return { statusCode: 500, body: err.toString() };
}
};
This is a fairly standard Netlify function whose primary function is to wrap the HTTP request performed by Axios. The first part looks for required values within the event
object that is passed in, which in our case are fullName
and email
. We'll be passing these when we call the function from JavaScript within our application just as we did earlier with Postman. If the request is successful, we pass back any data sent with a status code of 200 or if it fails we return the error with a status code of 500.
Testing the Function
Now let's test the function using Netlify Dev. Netlify Dev is functionality within the Netlify CLI that makes it easy to do local testing of your JAMStack site that is deployed to Netlify, including local testing of functions.
I've noticed that testing of functions locally generally requires that the function exist on Netlify first, so if you haven't deployed the function yet, do so. After that, any changes can be tested locally without needing to redeploy. Once that's done, start your site locally using netlify dev
and then open a tool like Postman and create a new POST request. Assuming the site is running on port 8888 (which is the default for Netlify Dev), the URL for the function should be localhost:8888/.netlify/functions/zapierSend
. You'll need to pass the JSON payload as well as shown below.
If everything is set up correctly, you should receive a success status back. Now it's time to call the function from within our application.
Calling the Function
Let's create a simple form to submit name and email.
<h1>Sending a Webhook</h1>
<form id="sendWebhookForm" onsubmit="return sendWebhook(this);">
<label for="fullName">Name:</label> <input type="text" name="fullName">
<label for="email">Email:</label> <input type="email" name="email">
<input name="sendInfo" type="submit" value="Submit">
</form>
We'll be sending the request from the browser using Axios, so we'll also need to load the Axios library as well as a script that will contain the sendWebhook()
function that is called by our form.
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="main.js"></script>
The sendWebhook()
function called when the form is submitted is a very simplistic HTTP request to our Netlify Function.
function sendWebhook(form) {
axios.post('/.netlify/functions/zapierSend', {
email: form.email.value,
fullName: form.fullName.value
})
.then(function (response) {
if (response.data.status === 'success') {
form.sendInfo.disabled = true;
form.email.value = '';
form.sendInfo.value = 'Saved!';
}
else {
alert('We apologize, there was a problem registering you.');
}
})
.catch(function (error) {
alert('We apologize, there was a problem registering you.');
});
return false;
}
I should note that for the purposes of example, this code doesn't include much in the way of validation and error checking. It sends a POST request with the form details to our Netlify Function which then passes that to the Zapier Webhook and, if everything is successful, posting the information to our Google spreadsheet.
Next Steps
The awesome thing is that this same process could allow you to easily connect your JAMstack application to any of the services that 1,500+ apps that Zapier has integrations with. This makes a lot of things possible that may have been either difficult or even impossible using existing APIs. You can explore the full code at https://github.com/remotesynth/webhooks.
In the next part, we'll flip things around. What if, rather than receiving data from your application, you want to use a webhook to send data to your application?